Merge branch 'dev' into bbi-js3

This commit is contained in:
jgoecks
2016-08-31 12:47:42 -04:00
137 changed files with 5666 additions and 4622 deletions
+1
View File
@@ -69,6 +69,7 @@ lib/galaxy/jobs/actions/
lib/galaxy/jobs/datasets.py
lib/galaxy/jobs/deferred/
lib/galaxy/jobs/error_level.py
lib/galaxy/jobs/__init__.py
lib/galaxy/jobs/manager.py
lib/galaxy/jobs/metrics/collectl/__init__.py
lib/galaxy/jobs/metrics/collectl/stats.py
+4 -4
View File
@@ -157,10 +157,10 @@ release-create: release-ensure-upstream ## Create a release branch
git commit -m "Merge branch 'release_$(RELEASE_CURR)' into dev"
git checkout master
git merge release_$(RELEASE_CURR)
#git push $(RELEASE_UPSTREAM) release_$(RELEASE_CURR):release_$(RELEASE_CURR)
#git push $(RELEASE_UPSTREAM) dev:dev
#git push $(RELEASE_UPSTREAM) master:master
#git push $(RELEASE_UPSTREAM) --tags
git push $(RELEASE_UPSTREAM) release_$(RELEASE_CURR):release_$(RELEASE_CURR)
git push $(RELEASE_UPSTREAM) dev:dev
git push $(RELEASE_UPSTREAM) master:master
git push $(RELEASE_UPSTREAM) --tags
release-create-point: ## Create a point release
git pull --ff-only $(RELEASE_UPSTREAM) master
+11 -7
View File
@@ -251,16 +251,20 @@ var TabularDatasetChunkedView = Backbone.View.extend({
}, this);
row.append(this._renderCell(cells.slice(num_columns - 1).join('\t'), num_columns - 1));
}
else if (num_columns > 5 && cells.length === num_columns - 1 ) {
// SAM file or like format with optional metadata missing.
else if (cells.length === 1){
// Comment line, just return the one cell.
row.append(this._renderCell(line, 0, num_columns));
}
else {
// cells.length is greater than one, but less than num_columns. Render cells and pad tds.
// Possibly a SAM file or like format with optional metadata missing.
// Could also be a tabular file with a line with missing columns.
_.each(cells, function(cell_contents, index) {
row.append(this._renderCell(cell_contents, index));
}, this);
row.append($('<td>'));
}
else {
// Comment line, just return the one cell.
row.append(this._renderCell(line, 0, num_columns));
_.each(_.range(num_columns - cells.length), function(){
row.append($('<td>'));
});
}
this.row_count++;
+4 -13
View File
@@ -1,6 +1,4 @@
/*
This class maps the form dom to an api compatible javascript dictionary.
*/
/* This class maps the form dom to an api compatible javascript dictionary. */
define([ 'utils/utils' ], function( Utils ) {
var Manager = Backbone.Model.extend({
initialize: function( app ) {
@@ -21,14 +19,6 @@ define([ 'utils/utils' ], function( Utils ) {
return sum;
},
/** Set parameter values from model */
set: function( model ) {
for ( var attr in model.attributes ) {
var index = this.match( attr );
index && this.app.field_list[ index ].value( model.get( attr ) );
}
},
/** Convert dom into a dictionary of flat id/value pairs used e.g. on job submission. */
create: function() {
var self = this;
@@ -211,8 +201,9 @@ define([ 'utils/utils' ], function( Utils ) {
context[ input.name ] = input;
}
});
for ( var i in inputs ) {
var node = inputs[ i ];
for ( var key in inputs ) {
var node = inputs[ key ];
node.name = node.name || key;
var name = prefix ? prefix + '|' + node.name : node.name;
switch ( node.type ) {
case 'repeat':
@@ -86,11 +86,6 @@ function( Utils, Portlet, Ui, FormSection, FormData ) {
}
},
/** Modify onchange event handler */
setOnChange: function( callback ) {
this.options.onchange = callback;
},
/** Render tool form */
render: function() {
var self = this;
@@ -10,29 +10,18 @@ define(['utils/utils'], function( Utils ) {
['a5a5a5','262626','494429','17365d','366092','953734','76923c','5f497a','31859b','e36c09'],
['7f7f7e','0c0c0c','1d1b10','0f243e','244061','632423','4f6128','3f3151','205867','974806']]
},
initialize : function( options ) {
this.options = Utils.merge( options, {} );
this.setElement( this._template() );
// link components
this.$panel = this.$( '.ui-color-picker-panel' );
this.$view = this.$( '.ui-color-picker-view' );
this.$value = this.$( '.ui-color-picker-value' );
this.$header = this.$( '.ui-color-picker-header' );
// build panel
this._build();
// hide panel on start up
this.visible = false;
// set initial value
this.value( this.options.value );
// link boxes
this.$boxes = this.$( '.ui-color-picker-box' );
// add event handler
var self = this;
this.$boxes.on( 'click', function() {
self.value( $( this ).css( 'background-color' ) );
@@ -48,25 +37,18 @@ define(['utils/utils'], function( Utils ) {
} );
},
// value
/** Get/set value */
value : function ( new_val ) {
if ( new_val !== undefined && new_val !== null ) {
// update color value
this.$value.css( 'background-color', new_val );
// check selected color in panel
this.$( '.ui-color-picker-box' ).empty();
this.$( this._getValue() ).html( this._templateCheck() );
// trigger custom event
this.options.onchange && this.options.onchange( new_val );
}
// return current value
return this._getValue();
},
// get value from dom
/** Get value from dom */
_getValue: function() {
var rgb = this.$value.css( 'background-color' );
rgb = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
@@ -80,7 +62,7 @@ define(['utils/utils'], function( Utils ) {
}
},
// build panel
/** Build color panel */
_build: function() {
var $content = this._content({
label : 'Theme Colors',
@@ -110,27 +92,20 @@ define(['utils/utils'], function( Utils ) {
});
},
// create content
/** Create content */
_content: function( options ) {
// get parameters
var label = options.label;
var colors = options.colors;
var padding = options.padding;
var top = options.top;
var bottom = options.bottom;
// create lines
var $content = $( this._templateContent() );
// set label
var $label = $content.find( '.label' );
if ( options.label ) {
$label.html( options.label );
} else {
$label.hide();
}
// build line
var $line = $content.find( '.line' );
this.$panel.append( $content );
for ( var i in colors ) {
@@ -153,12 +128,12 @@ define(['utils/utils'], function( Utils ) {
return $content;
},
// check icon
/** Check icon */
_templateCheck: function() {
return '<div class="ui-color-picker-check fa fa-check"/>';
},
// content template
/** Content template */
_templateContent: function() {
return '<div class="ui-color-picker-content">' +
'<div class="label"/>' +
@@ -166,12 +141,12 @@ define(['utils/utils'], function( Utils ) {
'</div>';
},
// box template
/** Box template */
_templateBox: function( color ) {
return '<div id="' + color + '" class="ui-color-picker-box" style="background-color: #' + color + ';"/>';
},
// template
/** Main template */
_template: function() {
return '<div class="ui-color-picker">' +
'<div class="ui-color-picker-header">' +
+11 -1
View File
@@ -109,7 +109,7 @@ var View = Backbone.View.extend({
},
/** Delete all tabs */
delRemovable: function() {
delAll: function() {
for ( var id in this.list ) {
this.del( id );
}
@@ -135,6 +135,16 @@ var View = Backbone.View.extend({
this.visible = false;
},
/** Show tab */
showTab: function( id ) {
this.$( '#tab-' + id ).show();
},
/** hide tab */
hideTab: function( id ) {
this.$( '#tab-' + id ).hide();
},
/** Hide operation by id */
hideOperation: function( id ) {
this.$nav.find( '#' + id ).hide();
+7 -1
View File
@@ -25,6 +25,11 @@ function deepeach( dict, callback ) {
}
}
/** Clone */
function clone( obj ) {
return JSON.parse( JSON.stringify( obj ) || null );
}
/**
* Check if a string is a json string
* @param{String} text - Content to be validated
@@ -275,7 +280,8 @@ return {
textify: textify,
isEmpty: isEmpty,
deepeach: deepeach,
isJSON: isJSON
isJSON: isJSON,
clone: clone
};
});
+7 -15
View File
@@ -175,7 +175,7 @@ paste.app_factory = galaxy.web.buildapp:app_factory
# the Tool Shed to install dependencies and can also be used by administrators
# to manually install or link to dependencies. For details, see:
# https://wiki.galaxyproject.org/Admin/Config/ToolDependencies
# Set to the string none to explicitly disable tool dependency handling.
# Set the string to None to explicitly disable tool dependency handling.
# If this option is set to none or an invalid path, installing tools with dependencies
# from the Tool Shed will fail.
#tool_dependency_dir = database/dependencies
@@ -320,7 +320,6 @@ paste.app_factory = galaxy.web.buildapp:app_factory
# Time to sleep between checks if check_job_script_integrity is enabled (in seconds).
#check_job_script_integrity_sleep = .25
# Set the default shell used by non-containerized jobs Galaxy-wide. This
# defaults to bash for all jobs and can be overidden at the destination
# level for heterogenous clusters. conda job resolution requires bash or zsh
@@ -632,7 +631,7 @@ nglims_config_file = tool-data/nglims.yaml
# implementation, alongside a new Golang single-binary-no-dependencies
# version. Valid values are (node, golang)
#dynamic_proxy=node
#
# The NodeJS dynamic proxy can use an SQLite database or a JSON file for IPC,
# set that here.
#dynamic_proxy_session_map=database/session_map.sqlite
@@ -702,7 +701,6 @@ nglims_config_file = tool-data/nglims.yaml
# log_events and log_actions functionality will eventually be merged.
#log_actions = True
# Fluentd configuration. Various events can be logged to the fluentd instance
# configured below by enabling fluent_log.
#fluent_log = False
@@ -956,23 +954,17 @@ use_interactive = True
#expose_user_email = False
# -- Beta features
# Enable new run workflow form
#run_workflow_toolform_upgrade = False
# Enable Galaxy to communicate directly with a sequencer
#enable_sequencer_communication = False
# Separate tool command from rest of job script so tool dependencies
# don't interfer with metadata generation.
# Despite the name, this feature is enabled by default
# in 16.01 and the option will go away in the future.
#enable_beta_tool_command_isolation = True
# Enable the new interface for installing tools from Tool Shed
# via the API. Admin menu will list both if enabled.
#enable_beta_ts_api_install = False
# Set the following to a number of threads greater than 1 to spawn
# a Python task queue for dealing with large tool submissions (either
# through the tool form or as part of an individual workflow step across
@@ -1184,14 +1176,14 @@ use_interactive = True
# if running many handlers.
#cache_user_job_count = False
# ToolBox filtering
# -- ToolBox filtering
# Modules from lib/galaxy/tools/toolbox/filters/ can be specified in
# the following lines. tool_* filters will be applied for all users
# and can not be changed by them. user_tool_* filters will be shown
# under user preferences and can be toogled on and off by
# under user preferences and can be toggled on and off at
# runtime. Example shown below are not real defaults (no custom
# filters applied by defualt) but can be enabled with by renaming the
# filters are applied by default), but can be enabled by renaming the
# example.py.sample in the filters directory to example.py.
#tool_filters =
@@ -1206,7 +1198,7 @@ use_interactive = True
# modifying the following option.
#toolbox_filter_base_modules = galaxy.tools.toolbox.filters,galaxy.tools.filters
# Galaxy Application Internal Message Queue
# -- Galaxy Application Internal Message Queue
# Galaxy uses AMQP internally TODO more documentation on what for.
# For examples, see http://ask.github.io/kombu/userguide/connections.html
@@ -1,38 +1,69 @@
.charts-tooltip {
position: absolute;
text-align: center;
padding: 3px 5px 3px 5px;
font: 12px sans-serif;
background: white;
border: 1px solid gray;
border-radius: 4px;
pointer-events: none;
.charts-viewer .ui-message {
position: absolute;
width: calc(100% - 20px);
z-index: 100;
}
.charts-description {
margin-bottom: 20px;
}
.charts-description-image-td {
vertical-align: top;
}
.charts-types .nav-tabs {
margin-bottom: 10px;
}
.charts-description-image {
width: 50px;
height: 43px;
margin-right: 10px;
}
.charts-description-title {
font-weight: bold;
}
.charts-description-text {
word-wrap: break-word;
}
.charts-tooltip {
position: absolute;
text-align: center;
padding: 3px 5px 3px 5px;
font: 12px sans-serif;
background: white;
border: 1px solid gray;
border-radius: 4px;
pointer-events: none;
}
.charts-tooltip-first {
font-weight: bold;
text-align: left;
padding-right: 5px;
font-weight: bold;
text-align: left;
padding-right: 5px;
}
.charts-grid .item {
padding: 5px;
margin: 5px;
float: left;
cursor: pointer;
border-radius:5px
padding: 5px;
margin: 5px;
float: left;
cursor: pointer;
border-radius:5px
}
.charts-grid .current {
border-color:#66afe9;
background-color:#EEEEFF;
outline:0;
-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);
box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);
border-color:#66afe9;
background-color:#EEEEFF;
outline:0;
-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);
box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);
}
.charts-grid .image {
padding: 10px;
padding: 10px;
width: 100px;
height: 86px;
}
@@ -49,6 +80,7 @@
font-size: 0.9em;
font-weight: bold;
padding-bottom: 10px;
clear: both;
}
.charts-viewport {
@@ -62,27 +94,27 @@
}
.charts-viewport .text {
position: relative;
margin-left: 5px;
top: -1px;
font-size: 1.0em;
display: inline;
position: relative;
margin-left: 5px;
top: -1px;
font-size: 1.0em;
display: inline;
}
.charts-viewport .icon {
font-size: 1.2em;
display: inline-block;
font-size: 1.2em;
display: inline-block;
}
.charts-viewport .charts-viewport-container {
float: left;
display: block;
height: 100%;
float: left;
display: block;
height: 100%;
}
.charts-viewport .charts-viewport-canvas {
display: block;
width:100%;
min-height: 100px;
height: inherit;
display: block;
width: 100%;
min-height: 100px;
height: inherit;
}
@@ -1,35 +1,22 @@
/**
* Main application class.
*/
define( [ 'mvc/ui/ui-modal', 'mvc/ui/ui-portlet', 'mvc/ui/ui-misc', 'utils/utils',
'plugin/library/jobs', 'plugin/library/datasets', 'plugin/library/storage', 'utils/deferred',
'plugin/views/viewer', 'plugin/views/editor',
'plugin/models/config', 'plugin/models/chart', 'plugin/charts/types' ],
function( Modal, Portlet, Ui, Utils, Jobs, Datasets, Storage, Deferred,
ViewerView, EditorView, Config, Chart, Types ) {
define( [ 'mvc/ui/ui-modal', 'mvc/ui/ui-portlet', 'mvc/ui/ui-misc', 'utils/utils', 'plugin/components/storage', 'plugin/components/model', 'utils/deferred', 'plugin/views/viewer', 'plugin/views/editor', 'plugin/charts/types' ],
function( Modal, Portlet, Ui, Utils, Storage, Chart, Deferred, Viewer, Editor, Types ) {
return Backbone.View.extend({
initialize: function(options){
this.options = options;
this.modal = parent.Galaxy && parent.Galaxy.modal || new Modal.View();
// models
this.config = new Config();
this.types = new Types();
this.types = Types;
this.chart = new Chart();
// libraries
this.jobs = new Jobs(this);
this.datasets = new Datasets( this );
this.storage = new Storage( this );
this.deferred = new Deferred();
// views
this.viewer_view = new ViewerView( this );
this.editor_view = new EditorView( this );
// append views
this.$el.append( this.viewer_view.$el );
this.$el.append( this.editor_view.$el );
this.viewer = new Viewer( this );
this.editor = new Editor( this );
this.$el.append( this.viewer.$el );
this.$el.append( this.editor.$el );
// pick start screen
if ( !this.storage.load() ) {
@@ -43,31 +30,25 @@ define( [ 'mvc/ui/ui-modal', 'mvc/ui/ui-portlet', 'mvc/ui/ui-misc', 'utils/utils
/** Loads a view and makes sure that all others are hidden */
go: function( view_id ) {
$( '.tooltip' ).hide();
switch ( view_id ) {
case 'editor' :
this.editor_view.show();
this.viewer_view.hide();
break;
case 'viewer' :
this.editor_view.hide();
this.viewer_view.show();
break;
}
},
/** Returns root path */
chartPath: function( chart_type ) {
var path = chart_type.split( /_(.+)/ );
if ( path.length >= 2 ) {
return path[ 0 ] + '/' + path[ 1 ];
}
console.debug( 'FAILED app:chartPath() - Invalid format: ' + chart_type );
this.viewer.hide();
this.editor.hide();
this[ view_id ].show();
},
/** Message */
showModal: function( title, body ) {
var self = this;
this.modal.show( { title: title, body: body, buttons: { 'Close': function() { self.modal.hide() } } } );
},
/** Split chart type into path components */
split: function( chart_type ) {
var path = chart_type.split( /_(.+)/ );
if ( path.length >= 2 ) {
return path[ 0 ] + '/' + path[ 1 ];
} else {
return chart_type;
}
}
});
});
@@ -1,259 +0,0 @@
define([], function() {
return {
title : '',
category : '',
library : '',
tag : '',
keywords : '',
settings : {
separator_x : {
title : 'X axis',
type : 'separator'
},
x_axis_label : {
title : 'Axis label',
info : 'Provide a label for the axis.',
type : 'text',
init : 'X-axis',
placeholder : 'Axis label'
},
x_axis_type : {
title : 'Axis value type',
info : 'Select the value type of the axis.',
type : 'select',
init : 'auto',
data : [
{
label : '-- Do not show values --',
value : 'hide',
operations : {
hide : ['x_axis_precision']
}
},
{
label : 'Auto',
value : 'auto',
operations : {
hide : ['x_axis_precision']
}
},
{
label : 'Float',
value : 'f',
operations : {
show : ['x_axis_precision']
}
},
{
label : 'Exponent',
value : 'e',
operations : {
show : ['x_axis_precision']
}
},
{
label : 'Integer',
value : 'd',
operations : {
hide : ['x_axis_precision']
}
},
{
label : 'Percentage',
value : 'p',
operations : {
show : ['x_axis_precision']
}
},
{
label : 'SI-prefix',
value : 's',
operations : {
hide : ['x_axis_precision']
}
}
]
},
x_axis_precision : {
title : 'Axis tick format',
info : 'Select the tick format for the axis.',
type : 'select',
init : '1',
data : [
{
label : '0.00001',
value : '5'
},
{
label : '0.0001',
value : '4'
},
{
label : '0.001',
value : '3'
},
{
label : '0.01',
value : '2'
},
{
label : '0.1',
value : '1'
},
{
label : '1',
value : '0'
}
]
},
separator_y : {
title : 'Y axis',
type : 'separator'
},
y_axis_label : {
title : 'Axis label',
info : 'Provide a label for the axis.',
type : 'text',
init : 'Y-axis',
placeholder : 'Axis label'
},
y_axis_type : {
title : 'Axis value type',
info : 'Select the value type of the axis.',
type : 'select',
init : 'auto',
data : [
{
label : '-- Do not show values --',
value : 'hide',
operations : {
hide : ['y_axis_precision']
}
},
{
label : 'Auto',
value : 'auto',
operations : {
hide : ['y_axis_precision']
}
},
{
label : 'Float',
value : 'f',
operations : {
show : ['y_axis_precision']
}
},
{
label : 'Exponent',
value : 'e',
operations : {
show : ['y_axis_precision']
}
},
{
label : 'Integer',
value : 'd',
operations : {
hide : ['y_axis_precision']
}
},
{
label : 'Percentage',
value : 'p',
operations : {
show : ['y_axis_precision']
}
},
{
label : 'SI-prefix',
value : 's',
operations : {
hide : ['y_axis_precision']
}
}
]
},
y_axis_precision : {
title : 'Axis tick format',
info : 'Select the tick format for the axis.',
type : 'select',
init : '1',
data : [
{
label : '0.00001',
value : '5'
},
{
label : '0.0001',
value : '4'
},
{
label : '0.001',
value : '3'
},
{
label : '0.01',
value : '2'
},
{
label : '0.1',
value : '1'
},
{
label : '1',
value : '0'
}
]
},
separator_legend : {
title : 'Others',
type : 'separator'
},
show_legend : {
title : 'Show legend',
info : 'Would you like to add a legend?',
type : 'select',
display : 'radiobutton',
init : 'true',
data : [
{
label : 'Yes',
value : 'true'
},
{
label : 'No',
value : 'false'
}
]
},
use_panels : {
title : 'Use multi-panels',
info : 'Would you like to separate your data into individual panels?',
type : 'select',
display : 'radiobutton',
init : 'false',
data : [
{
label : 'Yes',
value : 'true'
},
{
label : 'No',
value : 'false'
}
]
}
},
series : [{
name : 'key',
label : 'Provide a label',
type : 'text',
placeholder : 'Data label'
}]
};
});
@@ -1,20 +1,20 @@
define(['plugin/charts/jqplot/common/config'], function(plot_config) {
return $.extend(true, {}, plot_config, {
title : 'Regular',
category : 'Bar diagrams',
columns : {
x : {
title : 'Values for x-axis',
is_label : true,
is_auto : true,
is_unique : true
},
y : {
title : 'Values for y-axis',
is_numeric : true
define( [ 'plugin/charts/jqplot/common/config' ], function( plot_config ) {
return $.extend( true, {}, plot_config, {
title : 'Regular',
category : 'Bar diagrams',
groups : {
x : {
label : 'Values for x-axis',
type : 'data_column',
is_label : true,
is_auto : true,
is_unique : true
},
y : {
label : 'Values for y-axis',
type : 'data_column',
is_numeric : true
}
}
}
});
});
});
@@ -1,26 +1,22 @@
// dependencies
define(['plugin/charts/jqplot/common/wrapper'], function(Plot) {
// widget
return Backbone.Model.extend({
initialize: function(app, options) {
options.makeConfig = function(groups, plot_config){
$.extend(true, plot_config, {
seriesDefaults: {
renderer : $.jqplot.BarRenderer
},
axes: {
xaxis: {
min : -1
define( [ 'plugin/charts/jqplot/common/wrapper' ], function( Plot ) {
return Backbone.Model.extend({
initialize: function( app, options ) {
options.makeConfig = function( groups, plot_config ){
$.extend( true, plot_config, {
seriesDefaults: {
renderer : $.jqplot.BarRenderer
},
yaxis: {
pad : 1.2
axes: {
xaxis: {
min : -1
},
yaxis: {
pad : 1.2
}
}
}
});
};
new Plot(app, options);
}
});
});
};
new Plot( app, options );
}
});
});
@@ -1,23 +1,16 @@
define(['plugin/charts/jqplot/common/config'], function(plot_config) {
return $.extend(true, {}, plot_config, {
title : 'Box plot',
category : 'Data processing (requires \'charts\' tool from Toolshed)',
library : 'jqPlot',
tag : 'div',
execute : 'boxplot',
keywords : 'small medium large',
columns : {
y : {
title : 'Observations',
is_numeric : true
define( [ 'plugin/charts/jqplot/common/config' ], function( plot_config ) {
return $.extend( true, {}, plot_config, {
title : 'Box plot',
category : 'Data processing (requires \'charts\' tool from Toolshed)',
library : 'jqPlot',
tag : 'div',
keywords : 'jqplot default',
groups : {
y : {
label : 'Observations',
type : 'data_column',
is_numeric : true
}
}
},
settings : {
show_legend : {
init : 'false'
}
}
});
});
});
@@ -1,127 +1,98 @@
// dependencies
define(['plugin/charts/jqplot/common/wrapper', 'plugin/charts/tools'], function(Plot, Tools) {
// widget
return Backbone.View.extend(
{
// initialize
initialize: function(app, options) {
// get request dictionary
var request_dictionary = options.request_dictionary;
var chart = options.chart;
// modify request
var index = 0;
for (var i in request_dictionary.groups) {
var group = request_dictionary.groups[i];
group.columns = null;
group.columns = {
x: {
index: index++
}
}
}
// create plot
var plot = new Plot(app, {
process : options.process,
chart : options.chart,
request_dictionary : options.request_dictionary,
canvas_list : options.canvas_list,
makeConfig : function(groups, plot_config){
var boundary = Tools.getDomains(groups, 'x');
$.extend(true, plot_config, {
seriesDefaults: {
renderer: $.jqplot.OHLCRenderer,
rendererOptions : {
candleStick : true,
fillUpBody : true,
fillDownBody : true
define( [ 'plugin/charts/jqplot/common/wrapper', 'plugin/components/jobs', 'plugin/charts/utilities/tabular-utilities' ], function( Plot, Jobs, Utilities ) {
return Backbone.View.extend({
initialize: function( app, options ) {
Jobs.request( app, Utilities.buildJobDictionary( 'boxplot', app.chart ), function( dataset ) {
var request_dictionary = Utilities.buildRequestDictionary( app.chart, dataset.id );
var chart = options.chart;
var index = 0;
_.each( request_dictionary.groups, function( group ) {
group.columns = { x: { index : index++ } };
});
var plot = new Plot( app, {
process : options.process,
chart : options.chart,
request_dictionary : request_dictionary,
canvas_list : options.canvas_list,
makeConfig : function( groups, plot_config ){
var boundary = Utilities.getDomains( groups, 'x' );
$.extend( true, plot_config, {
seriesDefaults: {
renderer: $.jqplot.OHLCRenderer,
rendererOptions : {
candleStick : true,
fillUpBody : true,
fillDownBody : true
}
},
axes : {
xaxis: {
min: -1,
max: groups.length + 0.01
},
yaxis: {
min: boundary.x.min,
max: boundary.x.max
}
}
});
},
makeCategories: function( groups ) {
var x_labels = [];
for ( var group_index in groups ) {
x_labels.push( groups[ group_index ].key );
}
Utilities.mapCategories ( groups, x_labels );
return {
array: {
x : x_labels
}
}
},
axes : {
xaxis: {
min: -1,
max: groups.length + 0.01
},
yaxis: {
min: boundary.x.min,
max: boundary.x.max
makeSeriesLabels : function ( groups, plot_config ) {
return [ { label : 'Boxplot values' } ];
},
makeSeries: function ( groups ) {
/*/ example data
var catOHLC = [
[0, 138.7, 139.68, 135.18, 135.4],
[1, 143.46, 144.66, 139.79, 140.02],
[2, 140.67, 143.56, 132.88, 142.44],
[3, 136.01, 139.5, 134.53, 139.48]
];
return [catOHLC];*/
// plot data
var plot_data = [];
// check group length
if ( groups.length == 0 || groups[0].values.length < 5 ) {
chart.state( 'failed', 'Boxplot data could not be found.' );
return [ plot_data ];
}
// loop through data groups
var indeces = [ 2, 4, 0, 1 ];
for ( var group_index in groups ) {
var group = groups[ group_index ];
var point = [];
point.push( parseInt( group_index ) );
for ( var key in indeces ) {
point.push( group.values[ indeces[ key ] ].x );
}
plot_data.push( point );
}
// HACK: the boxplot renderer has an issue with single elements
var point = [];
point[ 0 ] = plot_data.length;
for ( var key in indeces ) {
point.push( 0 );
}
plot_data.push ( point );
return [ plot_data ];
}
});
},
makeCategories: function(groups) {
// define custom category labels
var x_labels = [];
for (var group_index in groups) {
x_labels.push(groups[group_index].key);
}
// use default mapping
Tools.mapCategories (groups, x_labels);
// return labels array for x axis
return {
array: {
x : x_labels
}
}
},
makeSeriesLabels : function (groups, plot_config) {
return [{
label: 'Boxplot values'
}];
},
makeSeries: function (groups) {
/*/ example data
var catOHLC = [
[0, 138.7, 139.68, 135.18, 135.4],
[1, 143.46, 144.66, 139.79, 140.02],
[2, 140.67, 143.56, 132.88, 142.44],
[3, 136.01, 139.5, 134.53, 139.48]
];
return [catOHLC];*/
// plot data
var plot_data = [];
// check group length
if (groups.length == 0 || groups[0].values.length < 5) {
chart.state('failed', 'Boxplot data could not be found.');
return [plot_data];
}
// loop through data groups
var indeces = [2, 4, 0, 1];
for (var group_index in groups) {
// get group
var group = groups[group_index];
// format chart data
var point = [];
point.push(parseInt(group_index));
for (var key in indeces) {
point.push(group.values[indeces[key]].x);
}
// add to data
plot_data.push (point);
}
// HACK: the boxplot renderer has an issue with single elements
var point = [];
point[0] = plot_data.length;
for (var key in indeces) {
point.push(0);
}
plot_data.push (point);
// return
return [plot_data];
}
});
}
});
}, function() { options.process.reject() } );
}
});
});
@@ -1,52 +1,22 @@
define(['plugin/charts/forms/default'], function(config_default) {
return $.extend(true, {}, config_default, {
title : '',
category : '',
library : 'jqPlot',
tag : 'div',
zoomable : true,
keywords : 'medium',
settings : {
separator_grid : {
title : 'Grids',
type : 'separator'
},
x_axis_grid : {
title : 'Axis grid',
info : 'Would you like to show grid lines for the X axis?',
type : 'select',
display : 'radiobutton',
init : 'false',
data : [
{
label : 'On',
value : 'true'
},
{
label : 'Off',
value : 'false'
}
]
},
y_axis_grid : {
title : 'Axis grid',
info : 'Would you like to show grid lines for the Y axis?',
type : 'select',
display : 'radiobutton',
init : 'true',
data : [
{
label : 'On',
value : 'true'
},
{
label : 'Off',
value : 'false'
}
]
define( [ 'plugin/charts/utilities/tabular-form' ], function( default_config ) {
return $.extend(true, {}, default_config, {
title : '',
category : '',
library : 'jqPlot',
tag : 'div',
zoomable : true,
keywords : 'jqplot',
settings : {
x_axis_grid : {
label : 'Axis grid',
help : 'Would you like to show grid lines for the X axis?',
type : 'boolean'
},
y_axis_grid : {
label : 'Axis grid',
help : 'Would you like to show grid lines for the Y axis?',
type : 'boolean'
}
}
}
});
});
});
@@ -1,115 +1,110 @@
// dependencies
define([], function() {
define( [], function() {
return function( chart ) {
// highcharts configuration
return function(chart) {
// get chart settings
var settings = chart.settings;
var plot_config = {
enablePlugins: true,
seriesColors: d3.scale.category20().range(),
seriesDefaults: {
renderer : $.jqplot.LineRenderer,
//lineWidth : 1, // width of the line in pixels.
shadow : false, // show shadow or not.
showLine : true, // whether to render the line segments or not.
rendererOptions: {
shadowDepth : 0,
barWidth : 3,
barPadding : 3
// get chart settings
var settings = chart.settings;
var plot_config = {
enablePlugins: true,
seriesColors: d3.scale.category20().range(),
seriesDefaults: {
renderer : $.jqplot.LineRenderer,
//lineWidth : 1, // width of the line in pixels.
shadow : false, // show shadow or not.
showLine : true, // whether to render the line segments or not.
rendererOptions: {
shadowDepth : 0,
barWidth : 3,
barPadding : 3
},
markerRenderer : $.jqplot.MarkerRenderer,
markerOptions: {
show : false, // wether to show data point markers.
style : 'filledCircle', // circle, diamond, square, filledCircle.
// filledDiamond or filledSquare.
lineWidth : 0, // width of the stroke drawing the marker.
size : 10, // size (diameter, edge length, etc.) of the marker.
shadow : false, // wether to draw shadow on marker or not.
shadowAngle : 45, // angle of the shadow. Clockwise from x axis.
shadowOffset : 1, // offset from the line of the shadow,
shadowDepth : 3, // number of strokes to make when drawing shadow. Each stroke
// offset by shadowOffset from the last.
shadowAlpha : 0.07 // opacity of the shadow
}
},
markerRenderer : $.jqplot.MarkerRenderer,
markerOptions: {
show : false, // wether to show data point markers.
style : 'filledCircle', // circle, diamond, square, filledCircle.
// filledDiamond or filledSquare.
lineWidth : 0, // width of the stroke drawing the marker.
size : 10, // size (diameter, edge length, etc.) of the marker.
shadow : false, // wether to draw shadow on marker or not.
shadowAngle : 45, // angle of the shadow. Clockwise from x axis.
shadowOffset : 1, // offset from the line of the shadow,
shadowDepth : 3, // number of strokes to make when drawing shadow. Each stroke
// offset by shadowOffset from the last.
shadowAlpha : 0.07 // opacity of the shadow
}
},
axesDefaults: {
labelRenderer : $.jqplot.CanvasAxisLabelRenderer,
labelOptions: {
fontSize : '12pt',
textColor : '#000000'
},
tickRenderer : $.jqplot.CanvasAxisTickRenderer ,
tickOptions: {
fontSize : '12pt',
textColor : '#000000'
}
},
axes: {
xaxis: {
label : chart.settings.get('x_axis_label'),
tickRenderer : $.jqplot.CanvasAxisTickRenderer,
axesDefaults: {
labelRenderer : $.jqplot.CanvasAxisLabelRenderer,
labelOptions: {
fontSize : '12pt',
textColor : '#000000'
},
tickRenderer : $.jqplot.CanvasAxisTickRenderer ,
tickOptions: {
angle : chart.settings.get('use_panels') === 'true' ? 0 : -30,
showGridline : chart.settings.get('x_axis_grid') === 'true'
},
pad : 0
fontSize : '12pt',
textColor : '#000000'
}
},
yaxis: {
label : chart.settings.get('y_axis_label'),
tickOptions : {
showGridline : chart.settings.get('y_axis_grid') === 'true'
axes: {
xaxis: {
label : chart.settings.get( 'x_axis_label' ),
tickRenderer : $.jqplot.CanvasAxisTickRenderer,
tickOptions: {
angle : chart.settings.get( 'use_panels' ) === 'true' ? 0 : -30,
showGridline : chart.settings.get( 'x_axis_grid' ) === 'true'
},
pad : 0
},
pad : 0
}
},
grid: {
background : '#FFFFFF',
borderWidth : 0,
shadow : false
},
cursor: {
show : true,
zoom : true,
showTooltip : false,
style : 'pointer'
},
highlighter: {
show : true,
showMarker : false,
tooltipAxes : 'xy'
},
series: []
};
// show the legend and put it outside the grid
if (chart.settings.get('show_legend') == 'true') {
plot_config.legend = {
renderer : $.jqplot.EnhancedLegendRenderer,
show : true,
placement : 'outsideGrid',
location : 'n',
rendererOptions: {
textColor : '#000000',
fontSize : '12pt',
border : 'none',
shadowAlpha : 1,
background : 'rgba(255, 255, 255, 0.9)',
fontFamily : 'Arial',
numberRows : 1
}
yaxis: {
label : chart.settings.get( 'y_axis_label' ),
tickOptions : {
showGridline : chart.settings.get( 'y_axis_grid' ) === 'true'
},
pad : 0
}
},
grid: {
background : '#FFFFFF',
borderWidth : 0,
shadow : false
},
cursor: {
show : true,
zoom : true,
showTooltip : false,
style : 'pointer'
},
highlighter: {
show : true,
showMarker : false,
tooltipAxes : 'xy'
},
series: []
};
}
// callback
return plot_config;
};
// show the legend and put it outside the grid
if ( chart.settings.get( 'show_legend' ) == 'true' ) {
plot_config.legend = {
renderer : $.jqplot.EnhancedLegendRenderer,
show : true,
placement : 'outsideGrid',
location : 'n',
rendererOptions: {
textColor : '#000000',
fontSize : '12pt',
border : 'none',
shadowAlpha : 1,
background : 'rgba(255, 255, 255, 0.9)',
fontFamily : 'Arial',
numberRows : 1
}
};
}
return plot_config;
};
});
@@ -1,138 +1,105 @@
// dependencies
define(['plugin/charts/jqplot/common/plot-config', 'plugin/charts/tools'], function(configmaker, Tools) {
/** This is the common wrapper for jqplot based visualizations. */
define( [ 'plugin/charts/jqplot/common/plot-config', 'plugin/charts/utilities/tabular-utilities' ], function( configmaker, Utilities ) {
return Backbone.View.extend({
initialize: function( app, options ) {
this.options = options;
var self = this;
options.render = function( canvas_id, groups ) {
return self.render( canvas_id, groups )
};
Utilities.panelHelper( options );
},
/**
* This is the common wrapper for jqplot based visualizations.
*/
return Backbone.View.extend({
// initialize
initialize: function(app, options) {
// get parameters
this.options = options;
// define render function
var self = this;
options.render = function(canvas_id, groups) {
return self.render(canvas_id, groups)
};
// call panel helper
Tools.panelHelper(app, options);
},
// draw all data into a single canvas
render: function(canvas_id, groups) {
// get parameters
var chart = this.options.chart;
var makeCategories = this.options.makeCategories;
var makeSeries = this.options.makeSeries;
var makeSeriesLabels = this.options.makeSeriesLabels;
var makeConfig = this.options.makeConfig;
// create configuration
var plot_config = configmaker(chart);
var plot_data = [];
// draw plot
try {
// make custom categories call
this._makeAxes(groups, plot_config, chart.settings);
// make custom series call
if (makeSeriesLabels) {
plot_config.series = makeSeriesLabels(groups, plot_config);
} else {
plot_config.series = this._makeSeriesLabels(groups);
}
// make custom series call
if (makeSeries) {
plot_data = makeSeries(groups, plot_config);
} else {
plot_data = Tools.makeSeries(groups);
}
// make custom config call
if (makeConfig) {
makeConfig(groups, plot_config);
}
// check chart state
if (chart.get('state') == 'failed') {
/** Draw all data into a single canvas */
render: function( canvas_id, groups ) {
var chart = this.options.chart;
var makeCategories = this.options.makeCategories;
var makeSeries = this.options.makeSeries;
var makeSeriesLabels = this.options.makeSeriesLabels;
var makeConfig = this.options.makeConfig;
var plot_config = configmaker( chart );
var plot_data = [];
try {
this._makeAxes( groups, plot_config, chart.settings );
if ( makeSeriesLabels ) {
plot_config.series = makeSeriesLabels( groups, plot_config );
} else {
plot_config.series = this._makeSeriesLabels( groups );
}
if ( makeSeries ) {
plot_data = makeSeries( groups, plot_config );
} else {
plot_data = Utilities.makeSeries( groups );
}
if ( makeConfig ) {
makeConfig( groups, plot_config );
}
if ( chart.get( 'state' ) == 'failed' ) {
return false;
}
// draw graph with default options, overwriting with passed options
function drawGraph ( opts ) {
var canvas = $( '#' + canvas_id );
if ( canvas.length == 0 ) {
return;
}
canvas.empty();
var plot_cnf = _.extend( _.clone( plot_config ), opts || {} );
return plot = $.jqplot( canvas_id, plot_data, plot_cnf );
}
// draw plot
var plot = drawGraph();
$( window ).on( 'resize', function () { drawGraph() } );
return true;
} catch ( err ) {
this._handleError( chart, err );
return false;
}
// draw graph with default options, overwriting with passed options
function drawGraph (opts) {
var canvas = $('#' + canvas_id);
if(canvas.length == 0) {
return;
}
canvas.empty();
var plot_cnf = _.extend(_.clone(plot_config), opts || {});
return plot = $.jqplot(canvas_id, plot_data, plot_cnf);
}
// draw plot
var plot = drawGraph();
// catch window resize event
$(window).on('resize', function () {
drawGraph();
});
return true;
} catch (err) {
this._handleError(chart, err);
return false;
}
},
// make series labels
_makeSeriesLabels: function(groups, plot_config) {
var series = [];
for (var group_index in groups) {
series.push({
label: groups[group_index].key
});
}
return series;
},
// create axes formatting
_makeAxes: function(groups, plot_config, settings) {
// result
var makeCategories = this.options.makeCategories;
var categories;
if (makeCategories) {
categories = makeCategories(groups, plot_config);
} else {
categories = Tools.makeCategories(groups);
}
// make axes
function makeAxis (id) {
Tools.makeTickFormat({
categories : categories.array[id],
type : settings.get(id + '_axis_type'),
precision : settings.get(id + '_axis_precision'),
formatter : function(formatter) {
if (formatter) {
plot_config.axes[id + 'axis'].tickOptions.formatter = function(format, value) {
return formatter(value);
};
}
}
});
};
makeAxis('x');
makeAxis('y');
},
// handle error
_handleError: function(chart, err) {
chart.state('failed', err);
}
});
},
/** Make series labels */
_makeSeriesLabels: function( groups, plot_config ) {
var series = [];
for ( var group_index in groups ) {
series.push( { label: groups[ group_index ].key } );
}
return series;
},
/** Create axes formatting */
_makeAxes: function( groups, plot_config, settings ) {
var makeCategories = this.options.makeCategories;
var categories;
if ( makeCategories ) {
categories = makeCategories( groups, plot_config );
} else {
categories = Utilities.makeCategories( groups );
}
// make axes
function makeAxis (id) {
Utilities.makeTickFormat({
categories : categories.array[ id ],
type : settings.get( id + '_axis_type|type' ),
precision : settings.get( id + '_axis_type|precision' ),
formatter : function( formatter ) {
if ( formatter ) {
plot_config.axes[ id + 'axis' ].tickOptions.formatter = function( format, value ) {
return formatter( value );
};
}
}
});
};
makeAxis( 'x' );
makeAxis( 'y' );
},
/** Handle error */
_handleError: function( chart, err ) {
chart.state( 'failed', err );
}
});
});
@@ -1,24 +1,14 @@
define(['plugin/charts/jqplot/common/config'], function(default_config) {
return $.extend(true, {}, default_config, {
title : 'Discrete Histogram',
category : 'Data processing (requires \'charts\' tool from Toolshed)',
execute : 'histogramdiscrete',
keywords : 'small medium large',
columns : {
x : {
title : 'Observations',
is_label : true
define( [ 'plugin/charts/jqplot/common/config' ], function( default_config ) {
return $.extend( true, {}, default_config, {
title : 'Discrete Histogram',
category : 'Data processing (requires \'charts\' tool from Toolshed)',
keywords : 'jqplot default',
groups : {
x : {
label : 'Observations',
type : 'data_column',
is_label : true
}
}
},
settings : {
x_axis_label : {
init : 'Breaks'
},
y_axis_label : {
init : 'Density'
}
}
});
});
});
@@ -1,57 +1,25 @@
// dependencies
define(['plugin/charts/jqplot/common/wrapper'], function(Plot) {
// widget
return Backbone.Model.extend({
initialize: function(app, options) {
// link request
var request_dictionary = options.request_dictionary;
// configure request
var index = 1;
var tmp_dict = {
id : request_dictionary.id,
groups : []
};
// configure groups
for (var group_index in request_dictionary.groups) {
var group = request_dictionary.groups[group_index];
tmp_dict.groups.push({
key : group.key,
columns : {
x: {
index : 0,
is_label : true
},
y: {
index : index++
}
}
define( [ 'plugin/charts/utilities/tabular-utilities', 'plugin/components/jobs', 'plugin/charts/jqplot/common/wrapper' ], function( Utilities, Jobs, Plot ) {
return Backbone.Model.extend({
initialize: function( app, options ) {
Jobs.request( app, Utilities.buildJobDictionary( 'histogramdiscrete', app.chart ), function( dataset ) {
var request_dictionary = Utilities.buildRequestDictionary( app.chart, dataset.id );
var index = 1;
var tmp_dict = { id : request_dictionary.id, groups : [] };
_.each( request_dictionary.groups, function( group ) {
tmp_dict.groups.push({
key : group.key,
columns : { x: { index : 0, is_label : true }, y: { index : index++ } }
});
});
options.request_dictionary = tmp_dict;
options.makeConfig = function( groups, plot_config ){
$.extend( true, plot_config, {
seriesDefaults: { renderer: $.jqplot.BarRenderer },
axes: { xaxis: { min : -1 }, yaxis: { pad : 1.2 } }
});
};
new Plot( app, options );
});
}
// add new request dictionary
options.request_dictionary = tmp_dict;
// add config maker
options.makeConfig = function(groups, plot_config){
$.extend(true, plot_config, {
seriesDefaults: {
renderer : $.jqplot.BarRenderer
},
axes: {
xaxis: {
min : -1
},
yaxis: {
pad : 1.2
}
}
});
};
new Plot(app, options);
}
});
});
});
@@ -1,20 +1,20 @@
define(['plugin/charts/jqplot/common/config'], function(plot_config) {
return $.extend(true, {}, plot_config, {
title : 'Line chart',
category : 'Others',
columns : {
x : {
title : 'Values for x-axis',
is_label : true,
is_auto : true,
is_unique : true
},
y : {
title : 'Values for y-axis',
is_numeric : true
define( [ 'plugin/charts/jqplot/common/config' ], function( plot_config ) {
return $.extend( true, {}, plot_config, {
title : 'Line chart',
category : 'Others',
groups : {
x : {
label : 'Values for x-axis',
type : 'data_column',
is_label : true,
is_auto : true,
is_unique : true
},
y : {
label : 'Values for y-axis',
type : 'data_column',
is_numeric : true
}
}
}
});
});
});
@@ -1,11 +1,7 @@
// dependencies
define(['plugin/charts/jqplot/common/wrapper'], function(Plot) {
// widget
return Backbone.Model.extend({
initialize: function(app, options) {
new Plot(app, options);
}
});
define( [ 'plugin/charts/jqplot/common/wrapper' ], function( Plot ) {
return Backbone.Model.extend({
initialize: function( app, options ) {
new Plot( app, options );
}
});
});
@@ -1,23 +1,18 @@
define(['plugin/charts/jqplot/common/config'], function(plot_config) {
return $.extend(true, {}, plot_config, {
title : 'Scatter plot',
category : 'Others',
columns : {
x : {
title : 'Values for x-axis',
is_numeric : true
},
y : {
title : 'Values for y-axis',
is_numeric : true
define( [ 'plugin/charts/jqplot/common/config' ], function( plot_config ) {
return $.extend( true, {}, plot_config, {
title : 'Scatter plot',
category : 'Others',
groups : {
x : {
label : 'Values for x-axis',
type : 'data_column',
is_numeric : true
},
y : {
label : 'Values for y-axis',
type : 'data_column',
is_numeric : true
}
}
},
settings : {
x_axis_grid : {
init : 'true'
}
}
});
});
});
@@ -1,22 +1,18 @@
// dependencies
define(['plugin/charts/jqplot/common/wrapper'], function(Plot) {
// widget
return Backbone.Model.extend({
initialize: function(app, options) {
options.makeConfig = function(groups, plot_config){
$.extend(true, plot_config, {
seriesDefaults: {
renderer: $.jqplot.LineRenderer,
showLine: false,
markerOptions : {
show : true
define( [ 'plugin/charts/jqplot/common/wrapper' ], function( Plot ) {
return Backbone.Model.extend({
initialize: function( app, options ) {
options.makeConfig = function( groups, plot_config ) {
$.extend( true, plot_config, {
seriesDefaults: {
renderer: $.jqplot.LineRenderer,
showLine: false,
markerOptions : {
show : true
}
}
}
});
};
new Plot(app, options);
}
});
});
};
new Plot( app, options );
}
});
});
@@ -1,20 +1,20 @@
define(['plugin/charts/nvd3/common/config'], function(nvd3_config) {
return $.extend(true, {}, nvd3_config, {
title : 'Regular',
category : 'Bar diagrams',
columns : {
x : {
title : 'Values for x-axis',
is_label : true,
is_auto : true,
is_unique : true
},
y : {
title : 'Values for y-axis',
is_numeric : true
define( [ 'plugin/charts/nvd3/common/config' ], function( nvd3_config ) {
return $.extend(true, {}, nvd3_config, {
title : 'Regular',
category : 'Bar diagrams',
groups : {
x : {
label : 'Values for x-axis',
type : 'data_column',
is_label : true,
is_auto : true,
is_unique : true
},
y : {
label : 'Values for y-axis',
type : 'data_column',
is_numeric : true
}
}
}
});
});
});
@@ -1,12 +1,8 @@
// dependencies
define(['plugin/charts/nvd3/common/wrapper'], function(NVD3) {
// widget
return Backbone.Model.extend({
initialize: function(app, options) {
options.type = 'multiBarChart';
new NVD3(app, options);
}
});
define( [ 'plugin/charts/nvd3/common/wrapper' ], function( NVD3 ) {
return Backbone.Model.extend({
initialize: function( app, options ) {
options.type = 'multiBarChart';
new NVD3( app, options );
}
});
});
@@ -1,25 +1,20 @@
define(['plugin/charts/nvd3/common/config'], function(nvd3_config) {
return $.extend(true, {}, nvd3_config, {
title : 'Horizontal',
category : 'Bar diagrams',
settings : {
x_axis_type : {
init : 'hide'
define( [ 'plugin/charts/nvd3/common/config' ], function( nvd3_config ) {
return $.extend( true, {}, nvd3_config, {
title : 'Horizontal',
category : 'Bar diagrams',
groups : {
x : {
label : 'Values for x-axis',
type : 'data_column',
is_label : true,
is_auto : true,
is_unique : true
},
y : {
label : 'Values for y-axis',
type : 'data_column',
is_numeric : true
}
}
},
columns : {
x : {
title : 'Values for x-axis',
is_label : true,
is_auto : true,
is_unique : true
},
y : {
title : 'Values for y-axis',
is_numeric : true
}
}
});
});
});
@@ -1,12 +1,8 @@
// dependencies
define(['plugin/charts/nvd3/common/wrapper'], function(NVD3) {
// widget
return Backbone.Model.extend({
initialize: function(app, options) {
options.type = 'multiBarHorizontalChart';
new NVD3(app, options);
}
});
define( [ 'plugin/charts/nvd3/common/wrapper' ], function( NVD3 ) {
return Backbone.Model.extend({
initialize: function( app, options ) {
options.type = 'multiBarHorizontalChart';
new NVD3( app, options );
}
});
});
@@ -1,25 +1,20 @@
define(['plugin/charts/nvd3/common/config'], function(nvd3_config) {
return $.extend(true, {}, nvd3_config, {
title : 'Stacked horizontal',
category : 'Bar diagrams',
settings : {
x_axis_type : {
init : 'hide'
define( [ 'plugin/charts/nvd3/common/config' ], function( nvd3_config ) {
return $.extend( true, {}, nvd3_config, {
title : 'Stacked horizontal',
category : 'Bar diagrams',
groups : {
x : {
label : 'Values for x-axis',
type : 'data_column',
is_label : true,
is_auto : true,
is_unique : true
},
y : {
label : 'Values for y-axis',
type : 'data_column',
is_numeric : true
}
}
},
columns : {
x : {
title : 'Values for x-axis',
is_label : true,
is_auto : true,
is_unique : true
},
y : {
title : 'Values for y-axis',
is_numeric : true
}
}
});
});
});
@@ -1,15 +1,11 @@
// dependencies
define(['plugin/charts/nvd3/common/wrapper'], function(NVD3) {
// widget
return Backbone.Model.extend({
initialize: function(app, options) {
options.type = 'multiBarHorizontalChart';
options.makeConfig = function(nvd3_model) {
nvd3_model.stacked(true);
};
new NVD3(app, options);
}
});
define( [ 'plugin/charts/nvd3/common/wrapper' ], function( NVD3 ) {
return Backbone.Model.extend({
initialize: function( app, options ) {
options.type = 'multiBarHorizontalChart';
options.makeConfig = function( nvd3_model ) {
nvd3_model.stacked( true );
};
new NVD3( app, options );
}
});
});
@@ -1,20 +1,20 @@
define(['plugin/charts/nvd3/common/config'], function(nvd3_config) {
return $.extend(true, {}, nvd3_config, {
title : 'Stacked',
category : 'Bar diagrams',
columns : {
x : {
title : 'Values for x-axis',
is_label : true,
is_auto : true,
is_unique : true
},
y : {
title : 'Values for y-axis',
is_numeric : true
define( [ 'plugin/charts/nvd3/common/config' ], function( nvd3_config ) {
return $.extend( true, {}, nvd3_config, {
title : 'Stacked',
category : 'Bar diagrams',
groups : {
x : {
label : 'Values for x-axis',
type : 'data_column',
is_label : true,
is_auto : true,
is_unique : true
},
y : {
label : 'Values for y-axis',
type : 'data_column',
is_numeric : true
}
}
}
});
});
});
@@ -1,15 +1,11 @@
// dependencies
define(['plugin/charts/nvd3/common/wrapper'], function(NVD3) {
// widget
return Backbone.Model.extend({
initialize: function(app, options) {
options.type = 'multiBarChart';
options.makeConfig = function(nvd3_model) {
nvd3_model.stacked(true);
};
new NVD3(app, options);
}
});
define( [ 'plugin/charts/nvd3/common/wrapper' ], function( NVD3 ) {
return Backbone.Model.extend({
initialize: function( app, options ) {
options.type = 'multiBarChart';
options.makeConfig = function( nvd3_model ) {
nvd3_model.stacked( true );
};
new NVD3( app, options );
}
});
});
@@ -1,27 +1,22 @@
define( [ 'plugin/charts/forms/default', 'plugin/plugins/nvd3/nv.d3' ], function( config_default ) {
return $.extend( true, {}, config_default, {
define( [ 'plugin/charts/utilities/tabular-form', 'plugin/plugins/nvd3/nv.d3' ], function( default_config ) {
return $.extend( true, {}, default_config, {
title : '',
category : '',
library : 'NVD3',
tag : 'svg',
keywords : 'small',
columns : {
keywords : 'nvd3 default',
groups : {
color: {
label : 'Pick a series color',
type : 'color'
},
tooltip : {
title : 'Data point labels',
is_text : true,
is_numeric : true,
is_auto : true
label : 'Data point labels',
type : 'data_column',
is_label : true,
is_auto : true,
is_unique : true
}
},
series : [{
name : 'key',
label : 'Provide a label',
type : 'text',
placeholder : 'Data label'
},{
name : 'color',
label : 'Pick a series color',
type : 'color'
}]
}
});
});
@@ -1,7 +1,5 @@
/**
* This is the common wrapper for nvd3 based visualizations.
*/
define( [ 'plugin/charts/tools' ], function( Tools ) {
/** This is the common wrapper for nvd3 based visualizations. */
define( [ 'plugin/charts/utilities/tabular-utilities' ], function( Utilities ) {
return Backbone.View.extend({
initialize: function( app, options ) {
var self = this;
@@ -9,7 +7,7 @@ define( [ 'plugin/charts/tools' ], function( Tools ) {
options.render = function( canvas_id, groups ) {
return self.render( canvas_id, groups )
};
Tools.panelHelper( app, options );
Utilities.panelHelper( options );
},
render: function( canvas_id, groups ) {
@@ -37,7 +35,7 @@ define( [ 'plugin/charts/tools' ], function( Tools ) {
canvas.datum( groups ).call( d3chart );
if ( chart.definition.zoomable && chart.definition.zoomable != 'native' ) {
d3chart.clipEdge && d3chart.clipEdge( true );
Tools.addZoom({
Utilities.addZoom({
xAxis : d3chart.xAxis,
yAxis : d3chart.yAxis,
yDomain: d3chart.yDomain,
@@ -57,12 +55,12 @@ define( [ 'plugin/charts/tools' ], function( Tools ) {
/** Format axes ticks */
_makeAxes: function( d3chart, groups, settings ) {
var categories = Tools.makeCategories( groups );
var categories = Utilities.makeCategories( groups );
function makeTickFormat( id ) {
Tools.makeTickFormat({
Utilities.makeTickFormat({
categories : categories.array[ id ],
type : settings.get( id + '_axis_type' ),
precision : settings.get( id + '_axis_precision' ),
type : settings.get( id + '_axis_type|type' ),
precision : settings.get( id + '_axis_type|precision' ),
formatter : function( formatter ) {
formatter && d3chart[ id + 'Axis' ].tickFormat( function( value ) {
return formatter( value );
@@ -1,31 +1,27 @@
define(['plugin/charts/forms/default'], function(config_default) {
return $.extend(true, {}, config_default, {
library : 'NVD3',
tag : 'svg',
title : 'Histogram',
category : 'Data processing (requires \'charts\' tool from Toolshed)',
execute : 'histogram',
keywords : 'small medium large',
columns : {
y : {
title : 'Observations',
is_numeric : true
define( [ 'plugin/charts/utilities/tabular-form' ], function( default_config ) {
return $.extend( true, {}, default_config, {
library : 'NVD3',
tag : 'svg',
title : 'Histogram',
category : 'Data processing (requires \'charts\' tool from Toolshed)',
keywords : 'nvd3 default',
datatype : 'tabular',
groups : {
key : {
label : 'Provide a label',
type : 'text',
placeholder : 'Data label',
value : 'Data label'
},
color : {
label : 'Pick a series color',
type : 'color'
},
y : {
label : 'Observations',
type : 'data_column',
is_numeric : true
}
}
},
settings : {
x_axis_label : {
init : 'Values'
},
y_axis_label : {
init : 'Density'
},
y_axis_type : {
init : 'f'
},
y_axis_precision : {
init : '.2'
}
}
});
});
});
@@ -1,34 +1,18 @@
// dependencies
define(['plugin/charts/nvd3/common/wrapper'], function(NVD3) {
// widget
return Backbone.Model.extend({
initialize: function(app, options) {
// link request
var request_dictionary = options.request_dictionary;
// configure request
var index = 1;
for (var i in request_dictionary.groups) {
var group = request_dictionary.groups[i];
group.columns = {
x: {
index : 0,
is_numeric : true
},
y: {
index : index++
}
}
define( [ 'plugin/charts/utilities/tabular-utilities', 'plugin/components/jobs', 'plugin/charts/nvd3/common/wrapper' ], function( Utilities, Jobs, NVD3 ) {
return Backbone.Model.extend({
initialize: function( app, options ) {
Jobs.request( app, Utilities.buildJobDictionary( 'histogram', app.chart ), function( dataset ) {
options.request_dictionary = Utilities.buildRequestDictionary( app.chart, dataset.id );
var index = 1;
_.each( options.request_dictionary.groups, function( group ) {
group.columns = { x : { index : 0, is_numeric : true }, y : { index : index++ } }
});
options.type = 'multiBarChart';
options.makeConfig = function( nvd3_model ) {
nvd3_model.options( { showControls: true } );
};
new NVD3( app, options );
}, function() { options.process.reject() } );
}
// setup chart wrapper
options.type = 'multiBarChart';
options.makeConfig = function(nvd3_model) {
nvd3_model.options({showControls: true});
};
new NVD3(app, options);
}
});
});
});
@@ -1,31 +1,17 @@
define(['plugin/charts/forms/default'], function(config_default) {
return $.extend(true, {}, config_default, {
library : 'NVD3',
tag : 'svg',
title : 'Discrete Histogram',
category : 'Data processing (requires \'charts\' tool from Toolshed)',
execute : 'histogramdiscrete',
keywords : 'small medium large',
columns : {
x : {
title : 'Observations',
is_label : true
define( [ 'plugin/charts/utilities/tabular-form' ], function( default_config ) {
return $.extend(true, {}, default_config, {
library : 'NVD3',
tag : 'svg',
title : 'Discrete Histogram',
category : 'Data processing (requires \'charts\' tool from Toolshed)',
keywords : 'nvd3',
datatype : 'tabular',
groups : {
x : {
label : 'Observations',
type : 'data_column',
is_label : true
}
}
},
settings : {
x_axis_label : {
init : 'Breaks'
},
y_axis_label : {
init : 'Density'
},
y_axis_type : {
init : 'f'
},
y_axis_precision : {
init : '2'
}
}
});
});
});
@@ -1,44 +1,23 @@
// dependencies
define(['plugin/charts/nvd3/common/wrapper'], function(NVD3) {
// widget
return Backbone.Model.extend({
initialize: function(app, options) {
// link request
var request_dictionary = options.request_dictionary;
// configure request
var index = 1;
var tmp_dict = {
id : request_dictionary.id,
groups : []
};
// configure groups
for (var group_index in request_dictionary.groups) {
var group = request_dictionary.groups[group_index];
tmp_dict.groups.push({
key : group.key,
columns : {
x: {
index : 0,
is_label : true
},
y: {
index : index++
}
}
});
define( [ 'plugin/charts/utilities/tabular-utilities', 'plugin/components/jobs', 'plugin/charts/nvd3/common/wrapper' ], function( Utilities, Jobs, NVD3 ) {
return Backbone.Model.extend({
initialize: function( app, options ) {
Jobs.request( app, Utilities.buildJobDictionary( 'histogramdiscrete', app.chart ), function( dataset ) {
var request_dictionary = Utilities.buildRequestDictionary( app.chart, dataset.id );
var index = 1;
var tmp_dict = { id : request_dictionary.id, groups : [] };
_.each( request_dictionary.groups, function( group ) {
tmp_dict.groups.push({
key : group.key,
columns : { x: { index : 0, is_label : true }, y: { index : index++ } }
});
});
options.request_dictionary = tmp_dict;
options.type = 'multiBarChart';
options.makeConfig = function( nvd3_model ) {
nvd3_model.options( { showControls: true } );
};
new NVD3( app, options );
}, function() { options.process.reject() } );
}
// setup chart wrapper
options.type = 'multiBarChart';
options.request_dictionary = tmp_dict;
options.makeConfig = function(nvd3_model) {
nvd3_model.options({showControls: true});
};
new NVD3(app, options);
}
});
});
});
@@ -1,21 +1,21 @@
define(['plugin/charts/nvd3/common/config'], function(nvd3_config) {
return $.extend(true, {}, nvd3_config, {
title : 'Line chart',
category : 'Others',
zoomable : true,
columns : {
x : {
title : 'Values for x-axis',
is_label : true,
is_auto : true,
is_unique : true
},
y : {
title : 'Values for y-axis',
is_numeric : true
define( [ 'plugin/charts/nvd3/common/config' ], function( nvd3_config ) {
return $.extend( true, {}, nvd3_config, {
title : 'Line chart',
category : 'Others',
zoomable : true,
groups : {
x : {
label : 'Values for x-axis',
type : 'data_column',
is_label : true,
is_auto : true,
is_unique : true
},
y : {
label : 'Values for y-axis',
type : 'data_column',
is_numeric : true
}
}
}
});
});
});
@@ -1,12 +1,8 @@
// dependencies
define(['plugin/charts/nvd3/common/wrapper'], function(NVD3) {
// widget
return Backbone.Model.extend({
initialize: function(app, options) {
options.type = 'lineChart';
new NVD3(app, options);
}
});
define( [ 'plugin/charts/nvd3/common/wrapper' ], function( NVD3 ) {
return Backbone.Model.extend({
initialize: function( app, options ) {
options.type = 'lineChart';
new NVD3( app, options );
}
});
});
@@ -1,21 +1,21 @@
define(['plugin/charts/nvd3/common/config'], function(nvd3_config) {
return $.extend(true, {}, nvd3_config, {
title : 'Line with focus',
category : 'Others',
zoomable : 'native',
columns : {
x : {
title : 'Values for x-axis',
is_label : true,
is_auto : true,
is_unique : true
},
y : {
title : 'Values for y-axis',
is_numeric : true
define( [ 'plugin/charts/nvd3/common/config' ], function( nvd3_config ) {
return $.extend( true, {}, nvd3_config, {
title : 'Line with focus',
category : 'Others',
zoomable : 'native',
groups : {
x : {
label : 'Values for x-axis',
type : 'data_column',
is_label : true,
is_auto : true,
is_unique : true
},
y : {
label : 'Values for y-axis',
type : 'data_column',
is_numeric : true
}
}
}
});
});
});
@@ -1,12 +1,8 @@
// dependencies
define(['plugin/charts/nvd3/common/wrapper'], function(NVD3) {
// widget
return Backbone.Model.extend({
initialize: function(app, options) {
options.type = 'lineWithFocusChart';
new NVD3(app, options);
}
});
define( [ 'plugin/charts/nvd3/common/wrapper' ], function( NVD3 ) {
return Backbone.Model.extend({
initialize: function( app, options ) {
options.type = 'lineWithFocusChart';
new NVD3( app, options );
}
});
});
@@ -1,128 +1,75 @@
define(['plugin/plugins/nvd3/nv.d3'], function() {
return $.extend(true, {}, {
title : 'Pie chart',
category : 'Area charts',
library : 'NVD3',
tag : 'svg',
keywords : 'small',
columns : {
label : {
title : 'Labels',
is_label : true,
is_auto : true
define( [ 'plugin/charts/utilities/tabular-form' ], function( default_config ) {
return $.extend( true, {}, default_config, {
title : 'Pie chart',
category : 'Area charts',
library : 'NVD3',
tag : 'svg',
keywords : 'nvd3 default',
datatype : 'tabular',
groups : {
label : {
label : 'Labels',
type : 'data_column',
is_label : true,
is_auto : true
},
y : {
label : 'Values',
type : 'data_column',
is_numeric : true
}
},
y : {
title : 'Values',
is_numeric : true
settings : {
donut_ratio : {
label : 'Donut ratio',
help : 'Determine how large the donut hole will be.',
type : 'float',
value : 0.5,
max : 1,
min : 0.0
},
show_legend : {
label : 'Show legend',
help : 'Would you like to add a legend?',
type : 'select',
display : 'radiobutton',
value : 'false',
data : [ { label : 'Yes', value : 'true' }, { label : 'No', value : 'false' } ]
},
label_type : {
type : 'conditional',
test_param : {
name : 'type',
label : 'Donut label',
type : 'select',
value : 'percent',
help : 'What would you like to show for each slice?',
data : [ { value : 'hide', label : '-- Nothing --' },
{ value : 'key', label : 'Label column' },
{ value : 'percent', label : 'Percentage' } ]
},
cases : [ { value : 'hide' },
{ value : 'key', inputs: [ { name : 'label_outside',
label : 'Show outside',
help : 'Would you like to show labels outside the donut?',
type : 'select',
display : 'radiobutton',
value : 'true',
data : [ { label : 'Yes', value : 'true' },
{ label : 'No', value : 'false' } ] } ] },
{ value : 'percent', inputs: [ { name : 'label_outside',
label : 'Show outside',
help : 'Would you like to show labels outside the donut?',
type : 'select',
display : 'radiobutton',
value : 'true',
data : [ { label : 'Yes', value : 'true' },
{ label : 'No', value : 'false' } ] } ] } ]
},
use_panels : {
value : 'true',
hidden : true
}
}
},
settings : {
main_separator : {
type : 'separator',
title : 'Pie chart settings'
},
donut_ratio : {
title : 'Donut ratio',
info : 'Determine how large the donut hole will be.',
type : 'select',
init : '0.5',
data : [
{
label : '50%',
value : '0.5'
},
{
label : '25%',
value : '0.25'
},
{
label : '10%',
value : '0.10'
},
{
label : '0%',
value : '0'
}
]
},
show_legend : {
title : 'Show legend',
info : 'Would you like to add a legend?',
type : 'select',
display : 'radiobutton',
init : 'false',
data : [
{
label : 'Yes',
value : 'true'
},
{
label : 'No',
value : 'false'
}
]
},
label_separator : {
type : 'separator',
title : 'Label settings'
},
label_type : {
title : 'Donut label',
info : 'What would you like to show for each slice?',
type : 'select',
init : 'percent',
data : [
{
label : '-- Nothing --',
value : 'hide',
hide : 'label_outside'
},
{
label : 'Label column',
value : 'key',
show : 'label_outside'
},
{
label : 'Value column',
value : 'value',
show : 'label_outside'
},
{
label : 'Percentage',
value : 'percent',
show : 'label_outside'
}
],
},
label_outside : {
title : 'Show outside',
info : 'Would you like to show labels outside the donut?',
type : 'select',
display : 'radiobutton',
init : 'false',
data : [
{
label : 'Yes',
value : 'true'
},
{
label : 'No',
value : 'false'
}
]
},
use_panels : {
init : 'true',
hide : true
}
}
});
});
});
@@ -1,122 +1,67 @@
// dependencies
define(['utils/utils'], function(Utils) {
// widget
return Backbone.View.extend(
{
// initialize
initialize: function(app, options) {
// get parameters
var request_dictionary = options.request_dictionary;
var chart = options.chart;
var canvas_list = options.canvas_list;
var process = options.process;
// setup handler
var self = this;
request_dictionary.success = function() {
// loop through data groups
for (var group_index in request_dictionary.groups) {
// get group
var group = request_dictionary.groups[group_index];
// draw group
self._drawGroup(chart, group, canvas_list[group_index]);
}
// set chart state
chart.state('ok', 'Pie chart has been drawn.');
// unregister process
process.resolve();
}
// request data
app.datasets.request(request_dictionary);
},
// draw group
_drawGroup: function(chart, group, canvas_id) {
try {
// get canvas
var canvas = d3.select('#' + canvas_id);
// add title
var title = canvas.append('text');
// configure title attributes
this._fixTitle(chart, canvas, title, group.key);
// format chart data
var pie_data = [];
for (var key in group.values) {
var value = group.values[key];
pie_data.push ({
y : value.y,
x : value.label
});
}
// add graph to screen
/** Pie chart wrapper */
define( [ 'utils/utils', 'plugin/charts/utilities/tabular-utilities', 'plugin/charts/utilities/tabular-datasets' ], function( Utils, Utilities, Datasets ) {
return Backbone.View.extend({
initialize: function( app, options ) {
var self = this;
nv.addGraph(function() {
// legend
var legend_visible = true;
if (chart.settings.get('show_legend') == 'false') {
legend_visible = false;
var chart = app.chart;
var request_dictionary = Utilities.buildRequestDictionary( app.chart );
var canvas_list = options.canvas_list;
var process = options.process;
request_dictionary.success = function( result ) {
for ( var group_index in result.groups ) {
var group = result.groups[ group_index ];
self._drawGroup( chart, group, canvas_list[ group_index ] );
}
// legend
var label_outside = true;
if (chart.settings.get('label_outside') == 'false') {
label_outside = false;
}
// label type
var label_type = chart.settings.get('label_type');
// ratio
var donut_ratio = parseFloat(chart.settings.get('donut_ratio'))
// create chart model
var chart_3d = nv.models.pieChart()
.donut(true)
.labelThreshold(.05)
.showLegend(legend_visible)
.labelType(label_type)
.donutRatio(donut_ratio)
.donutLabelsOutside(label_outside);
// add data to canvas
canvas.datum(pie_data)
.call(chart_3d);
// add resize trigger
nv.utils.windowResize(function() {
// update chart
chart_3d.update();
// fix title
self._fixTitle(chart, canvas, title, group.key);
});
});
} catch (err) {
console.log(err);
}
},
// fix title
_fixTitle: function(chart, canvas, title_element, title_text) {
// update title
var width = parseInt(canvas.style('width'));
var height = parseInt(canvas.style('height'));
// add title
title_element.attr('x', width / 2)
.attr('y', height - 10)
.attr('text-anchor', 'middle')
.text(title_text);
}
});
chart.state('ok', 'Pie chart has been drawn.');
process.resolve();
}
Datasets.request( request_dictionary );
},
/** Draw group */
_drawGroup: function( chart, group, canvas_id ) {
try {
var self = this;
var canvas = d3.select( '#' + canvas_id );
var title = canvas.append( 'text' );
this._fixTitle( chart, canvas, title, group.key );
var pie_data = [];
_.each( group.values, function( value ) {
pie_data.push( { y : value.y, x : value.label } );
});
// add graph to screen
nv.addGraph(function() {
var legend_visible = chart.settings.get( 'show_legend' ) == 'true';
var label_outside = chart.settings.get( 'label_outside' ) == 'true';
var label_type = chart.settings.get( 'label_type' );
var donut_ratio = parseFloat( chart.settings.get( 'donut_ratio' ) );
var chart_3d = nv.models.pieChart()
.donut( true )
.labelThreshold( .05 )
.showLegend( legend_visible )
.labelType( label_type )
.donutRatio( donut_ratio )
.donutLabelsOutside( label_outside );
canvas.datum( pie_data ).call( chart_3d );
nv.utils.windowResize( function() {
chart_3d.update();
self._fixTitle( chart, canvas, title, group.key );
});
});
} catch ( err ) {
console.log( err );
}
},
/** Fix title */
_fixTitle: function( chart, canvas, title_element, title_text ) {
var width = parseInt( canvas.style( 'width' ) );
var height = parseInt( canvas.style( 'height' ) );
title_element.attr( 'x', width / 2 )
.attr( 'y', height - 10 )
.attr( 'text-anchor', 'middle' )
.text( title_text );
}
});
});
@@ -1,19 +1,19 @@
define(['plugin/charts/nvd3/common/config'], function(nvd3_config) {
return $.extend(true, {}, nvd3_config, {
title : 'Scatter plot',
category : 'Others',
zoomable : true,
columns : {
x : {
title : 'Values for x-axis',
is_numeric : true
},
y : {
title : 'Values for y-axis',
is_numeric : true
define( [ 'plugin/charts/nvd3/common/config' ], function( nvd3_config ) {
return $.extend( true, {}, nvd3_config, {
title : 'Scatter plot',
category : 'Others',
zoomable : true,
groups : {
x : {
label : 'Values for x-axis',
type : 'data_column',
is_numeric : true
},
y : {
label : 'Values for y-axis',
type : 'data_column',
is_numeric : true
}
}
}
});
});
});
@@ -1,17 +1,13 @@
// dependencies
define(['plugin/charts/nvd3/common/wrapper'], function(NVD3) {
// widget
return Backbone.Model.extend({
initialize: function(app, options) {
options.type = 'scatterChart';
options.makeConfig = function(nvd3_model) {
nvd3_model.showDistX(true)
.showDistY(true)
.color(d3.scale.category10().range());
};
new NVD3(app, options);
}
});
define( [ 'plugin/charts/nvd3/common/wrapper' ], function( NVD3 ) {
return Backbone.Model.extend({
initialize: function( app, options ) {
options.type = 'scatterChart';
options.makeConfig = function( nvd3_model ) {
nvd3_model.showDistX( true )
.showDistY( true )
.color( d3.scale.category10().range() );
};
new NVD3( app, options );
}
});
});
@@ -1,22 +1,22 @@
define(['plugin/charts/nvd3/common/config'], function(nvd3_config) {
return $.extend(true, {}, nvd3_config, {
title : 'Regular',
zoomable : true,
category : 'Area charts',
keywords : 'default small',
columns : {
x : {
title : 'Values for x-axis',
is_label : true,
is_auto : true,
is_unique : true
},
y : {
title : 'Values for y-axis',
is_numeric : true
define( [ 'plugin/charts/nvd3/common/config' ], function( nvd3_config ) {
return $.extend( true, {}, nvd3_config, {
title : 'Regular',
zoomable : true,
category : 'Area charts',
keywords : 'nvd3 default',
groups : {
x : {
label : 'Values for x-axis',
type : 'data_column',
is_label : true,
is_auto : true,
is_unique : true
},
y : {
label : 'Values for y-axis',
type : 'data_column',
is_numeric : true
}
}
}
});
});
});
@@ -1,12 +1,8 @@
// dependencies
define(['plugin/charts/nvd3/common/wrapper'], function(NVD3) {
// widget
return Backbone.Model.extend({
initialize: function(app, options) {
options.type = 'stackedAreaChart';
new NVD3(app, options);
}
});
define( [ 'plugin/charts/nvd3/common/wrapper' ], function( NVD3 ) {
return Backbone.Model.extend({
initialize: function( app, options ) {
options.type = 'stackedAreaChart';
new NVD3( app, options );
}
});
});
@@ -1,22 +1,22 @@
define(['plugin/charts/nvd3/common/config'], function(nvd3_config) {
return $.extend(true, {}, nvd3_config, {
title : 'Expanded',
zoomable : true,
category : 'Area charts',
keywords : 'default small',
columns : {
x : {
title : 'Values for x-axis',
is_label : true,
is_auto : true,
is_unique : true
},
y : {
title : 'Values for y-axis',
is_numeric : true
define( [ 'plugin/charts/nvd3/common/config' ], function( nvd3_config ) {
return $.extend( true, {}, nvd3_config, {
title : 'Expanded',
zoomable : true,
category : 'Area charts',
keywords : 'nvd3 default',
groups : {
x : {
label : 'Values for x-axis',
type : 'data_column',
is_label : true,
is_auto : true,
is_unique : true
},
y : {
label : 'Values for y-axis',
type : 'data_column',
is_numeric : true
}
}
}
});
});
});
@@ -1,15 +1,11 @@
// dependencies
define(['plugin/charts/nvd3/common/wrapper'], function(NVD3) {
// widget
return Backbone.Model.extend({
initialize: function(app, options) {
options.type = 'stackedAreaChart';
options.makeConfig = function(nvd3_model) {
nvd3_model.style('expand');
};
new NVD3(app, options);
}
});
define( [ 'plugin/charts/nvd3/common/wrapper' ], function( NVD3 ) {
return Backbone.Model.extend({
initialize: function( app, options ) {
options.type = 'stackedAreaChart';
options.makeConfig = function( nvd3_model ) {
nvd3_model.style( 'expand' );
};
new NVD3( app, options );
}
});
});
@@ -1,23 +1,23 @@
define(['plugin/charts/nvd3/common/config'], function(nvd3_config) {
return $.extend(true, {}, nvd3_config, {
title : 'Stream',
category : 'Area charts',
zoomable : true,
keywords : 'default small',
showmaxmin : true,
columns : {
x : {
title : 'Values for x-axis',
is_label : true,
is_auto : true,
is_unique : true
},
y : {
title : 'Values for y-axis',
is_numeric : true
define( [ 'plugin/charts/nvd3/common/config' ], function( nvd3_config ) {
return $.extend(true, {}, nvd3_config, {
title : 'Stream',
category : 'Area charts',
zoomable : true,
keywords : 'nvd3 default',
showmaxmin : true,
groups : {
x : {
label : 'Values for x-axis',
type : 'data_column',
is_label : true,
is_auto : true,
is_unique : true
},
y : {
label : 'Values for y-axis',
type : 'data_column',
is_numeric : true
}
}
}
});
});
});
@@ -1,15 +1,11 @@
// dependencies
define(['plugin/charts/nvd3/common/wrapper'], function(NVD3) {
// widget
return Backbone.Model.extend({
initialize: function(app, options) {
options.type = 'stackedAreaChart';
options.makeConfig = function(nvd3_model) {
nvd3_model.style('stream')
};
new NVD3(app, options);
}
});
define( [ 'plugin/charts/nvd3/common/wrapper' ], function( NVD3 ) {
return Backbone.Model.extend({
initialize: function( app, options ) {
options.type = 'stackedAreaChart';
options.makeConfig = function( nvd3_model ) {
nvd3_model.style( 'stream' )
};
new NVD3( app, options );
}
});
});
@@ -0,0 +1,18 @@
define([], function() {
return {
title : 'Example',
category : 'Developer Examples',
library : 'Custom',
tag : 'svg',
keywords : 'others',
description : 'This is a developer example which demonstrates how to implement and configure a basic d3-based plugin for charts.',
groups : {
x : { type : 'data_column', is_numeric : true, label : 'Bubble x-position' },
y : { type : 'data_column', is_numeric : true, label : 'Bubble y-position' },
z : { type : 'data_column', is_numeric : true, label : 'Bubble size' }
},
settings : {
use_panels : { label : 'Use multiple panels', help : 'Do you want to draw all data series into a individual panels?', type : 'boolean' }
}
}
});
Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

@@ -0,0 +1,37 @@
define( [ 'plugin/charts/utilities/tabular-utilities', 'plugin/charts/utilities/tabular-datasets' ], function( Utilities, Datasets ) {
return Backbone.View.extend({
initialize: function( app, options ) {
var chart = app.chart;
var request_dictionary = Utilities.buildRequestDictionary( chart );
var error = null;
request_dictionary.success = function( result ) {
var colors = d3.scale.category20();
_.each( result.groups, function( group, group_index ) {
try {
var svg = d3.select( '#' + ( options.canvas_list[ group_index ] || options.canvas_list[ 0 ] ) );
var height = parseInt( svg.style( 'height' ) );
var width = parseInt( svg.style( 'width' ) );
var maxValue = d3.max( group.values, function( d ) { return Math.max( d.x, d.y ) } );
svg.selectAll( 'bubbles' )
.data( group.values )
.enter().append( 'circle' )
.attr( 'r', function( d ) { return ( Math.abs( d.z ) * 20 ) / maxValue } )
.attr( 'cy', function( d, i ) { return height * d.y / maxValue } )
.attr( 'cx', function( d ) { return width * d.x / maxValue } )
.style( 'stroke', colors( group_index ) )
.style( 'fill', 'white' );
} catch ( err ) {
error = err;
}
});
if ( error ) {
chart.state( 'failed', error );
} else {
chart.state( 'ok', 'Workshop chart has been drawn.' );
}
options.process.resolve();
}
Datasets.request( request_dictionary );
}
});
});
@@ -1,111 +1,65 @@
define(['plugin/charts/forms/default'], function(config_default) {
return $.extend(true, {}, config_default, {
title : 'Heatmap',
category : 'Others',
library : 'Custom',
tag : 'svg',
keywords : 'small',
zoomable : true,
columns : {
x : {
title : 'Column labels',
is_label : true,
is_numeric : true,
is_unique : true
define( [ 'plugin/charts/utilities/tabular-form' ], function( default_config ) {
return $.extend( true, {}, default_config, {
title : 'Heatmap',
category : 'Others',
library : 'Custom',
tag : 'svg',
keywords : 'others default',
zoomable : true,
groups : {
x : {
label : 'Column labels',
type : 'data_column',
is_label : true,
is_unique : true,
is_numeric : true
},
y : {
label : 'Row labels',
type : 'data_column',
is_label : true,
is_unique : true,
is_numeric : true
},
z : {
label : 'Observation',
type : 'data_column',
is_numeric : true
}
},
y : {
title : 'Row labels',
is_label : true,
is_numeric : true,
is_unique : true
},
z : {
title : 'Observation',
is_numeric : true
settings : {
use_panels : {
value : 'true',
hidden : true
},
color_set : {
label : 'Color scheme',
help : 'Select a color scheme for your heatmap',
type : 'select',
value : 'jet',
data : [ { label : 'Cold-to-Hot', value : 'hot' },
{ label : 'Cool', value : 'cool' },
{ label : 'Copper', value : 'copper' },
{ label : 'Gray scale', value : 'gray' },
{ label : 'Jet', value : 'jet' },
{ label : 'No-Green', value : 'no_green' },
{ label : 'Ocean', value : 'ocean' },
{ label : 'Polar', value : 'polar' },
{ label : 'Red-to-Green', value : 'redgreen' },
{ label : 'Red-to-green (saturated)', value : 'red2green' },
{ label : 'Relief', value : 'relief' },
{ label : 'Seismograph', value : 'seis' },
{ label : 'Sealand', value : 'sealand' },
{ label : 'Split', value : 'split' },
{ label : 'Wysiwyg', value : 'wysiwyg' } ]
},
url_template: {
label : 'Url template',
help : 'Enter a url to link the labels with external sources. Use __LABEL__ as placeholder.',
type : 'text',
value : '',
placeholder : 'http://someurl.com?id=__LABEL__'
}
}
},
settings : {
use_panels : {
init : 'true',
hide : true
},
color_set : {
title : 'Color scheme',
info : 'Select a color scheme for your heatmap',
type : 'select',
init : 'jet',
data : [
{
label : 'Cold-to-Hot',
value : 'hot'
},
{
label : 'Cool',
value : 'cool'
},
{
label : 'Copper',
value : 'copper'
},
{
label : 'Gray scale',
value : 'gray'
},
{
label : 'Jet',
value : 'jet'
},
{
label : 'No-Green',
value : 'no_green'
},
{
label : 'Ocean',
value : 'ocean'
},
{
label : 'Polar',
value : 'polar'
},
{
label : 'Red-to-Green',
value : 'redgreen'
},
{
label : 'Red-to-green (saturated)',
value : 'red2green'
},
{
label : 'Relief',
value : 'relief'
},
{
label : 'Seismograph',
value : 'seis'
},
{
label : 'Sealand',
value : 'sealand'
},
{
label : 'Split',
value : 'split'
},
{
label : 'Wysiwyg',
value : 'wysiwyg'
}
]
},
url_template: {
title : 'Url template',
info : 'Enter a url to link the labels with external sources. Use __LABEL__ as placeholder.',
type : 'text',
init : '',
placeholder : 'http://someurl.com?id=__LABEL__'
}
}
});
});
});
@@ -1,42 +1,35 @@
// dependencies
define([], function() {
return {
colorSets: {
seis: ['#AA0000', '#D00000', '#F70000', '#FF1D00', '#FF4400', '#FF6A00', '#FF9000', '#FFB700', '#FFDD00', '#FFFF00', '#FFFF00', '#FFFF00', '#BDFF0C', '#73FF1A', '#3FFA36', '#16F45A', '#00D08B', '#0087CD', '#0048FA', '#0024E3'].reverse(),
sealand: ['#8C66FF', '#6A66FF', '#6684FF', '#66A7FF', '#66CAFF', '#66ECFF', '#66FFF0', '#66FFCE', '#66FFAB', '#66FF88', '#66FF66', '#88FF66', '#ABFF66', '#CEFF66', '#FFEEA6', '#FFD3A6', '#FFB8A6', '#FFAAB0', '#FFB5CB', '#FFC0E1'].reverse(),
redgreen: ['#005824', '#1A693B', '#347B53', '#4F8D6B', '#699F83', '#83B09B', '#9EC2B3', '#B8D4CB', '#D2E6E3', '#EDF8FB', '#FFFFFF', '#F1EEF6', '#E6D3E1','#DBB9CD', '#D19EB9', '#C684A4', '#BB6990', '#B14F7C', '#A63467', '#9B1A53', '#91003F'],
ocean: ['#000000', '#000209', '#000413', '#00061E', '#000728', '#000932', '#002650', '#00426E', '#005E8C', '#007AAA', '#0096C8', '#22A9C2', '#45BCBB', '#67CFB5', '#8AE2AE', '#ACF6A8', '#BCF8B9', '#CBF9CA', '#DBFBDC', '#EBFDED'].reverse(),
cool: ['#00FFFF', '#0DF2FF', '#19E6FF', '#26D9FF', '#33CCFF', '#3FBFFF', '#4CB3FF', '#59A6FF', '#6699FF', '#738CFF', '#7F7FFF', '#8C73FF', '#9966FF', '#A659FF', '#B24DFF', '#BF3FFF', '#CC33FF', '#D926FF', '#E619FF', '#F20DFF'],
copper: ['#000000', '#100906', '#1F130D', '#301E13', '#40281A', '#50321F', '#603C26', '#70462D', '#805033', '#905A3A', '#A06440', '#B06E46', '#C0784D', '#D08253', '#E08C5A', '#F09660', '#FFA066', '#FFAA6D', '#FFB473', '#FFBE7A'].reverse(),
gray: ['#000000', '#0D0D0D', '#191919', '#262626', '#333333', '#3F3F3F', '#4C4C4C', '#595959', '#666666', '#737373', '#7F7F7F', '#8C8C8C', '#999999', '#A6A6A6', '#B2B2B2', '#BFBFBF', '#CCCCCC', '#D9D9D9', '#E6E6E6', '#F2F2F2'].reverse(),
hot: ['#000000', '#220000', '#440000', '#660000', '#880000', '#AA0000', '#CC0000', '#EE0000', '#FF1100', '#FF3300', '#FF5500', '#FF7700', '#FF9900', '#FFBB00', '#FFDD00', '#FFFF00', '#FFFF33', '#FFFF66', '#FFFF99', '#FFFFCC'].reverse(),
jet: ['#00007F', '#0000B2', '#0000E5', '#0019FF', '#004DFF', '#007FFF', '#00B2FF', '#00E5FF', '#FFFFF2', '#FFFFD9', '#FFFFBF', '#FFFFA5', '#FFFF8C', '#FFE500', '#FFB300', '#FF7F00', '#FF4C00', '#FF1900', '#E50000', '#B20000'],
no_green: ['#1F60FF', '#1F60FF', '#1F9FFF', '#1FBFFF', '#00CFFF', '#2AFFFF', '#2AFFFF', '#55FFFF', '#7FFFFF', '#AAFFFF', '#FFFF54', '#FFFF54', '#FFF000', '#FFBF00', '#FFA800', '#FF8A00', '#FF8A00', '#FF7000', '#FF4D00', '#FF0000'],
// color palettes
var colorSets = {
seis: ['#AA0000', '#D00000', '#F70000', '#FF1D00', '#FF4400', '#FF6A00', '#FF9000', '#FFB700', '#FFDD00', '#FFFF00', '#FFFF00', '#FFFF00', '#BDFF0C', '#73FF1A', '#3FFA36', '#16F45A', '#00D08B', '#0087CD', '#0048FA', '#0024E3'].reverse(),
sealand: ['#8C66FF', '#6A66FF', '#6684FF', '#66A7FF', '#66CAFF', '#66ECFF', '#66FFF0', '#66FFCE', '#66FFAB', '#66FF88', '#66FF66', '#88FF66', '#ABFF66', '#CEFF66', '#FFEEA6', '#FFD3A6', '#FFB8A6', '#FFAAB0', '#FFB5CB', '#FFC0E1'].reverse(),
redgreen: ['#005824', '#1A693B', '#347B53', '#4F8D6B', '#699F83', '#83B09B', '#9EC2B3', '#B8D4CB', '#D2E6E3', '#EDF8FB', '#FFFFFF', '#F1EEF6', '#E6D3E1','#DBB9CD', '#D19EB9', '#C684A4', '#BB6990', '#B14F7C', '#A63467', '#9B1A53', '#91003F'],
ocean: ['#000000', '#000209', '#000413', '#00061E', '#000728', '#000932', '#002650', '#00426E', '#005E8C', '#007AAA', '#0096C8', '#22A9C2', '#45BCBB', '#67CFB5', '#8AE2AE', '#ACF6A8', '#BCF8B9', '#CBF9CA', '#DBFBDC', '#EBFDED'].reverse(),
cool: ['#00FFFF', '#0DF2FF', '#19E6FF', '#26D9FF', '#33CCFF', '#3FBFFF', '#4CB3FF', '#59A6FF', '#6699FF', '#738CFF', '#7F7FFF', '#8C73FF', '#9966FF', '#A659FF', '#B24DFF', '#BF3FFF', '#CC33FF', '#D926FF', '#E619FF', '#F20DFF'],
copper: ['#000000', '#100906', '#1F130D', '#301E13', '#40281A', '#50321F', '#603C26', '#70462D', '#805033', '#905A3A', '#A06440', '#B06E46', '#C0784D', '#D08253', '#E08C5A', '#F09660', '#FFA066', '#FFAA6D', '#FFB473', '#FFBE7A'].reverse(),
gray: ['#000000', '#0D0D0D', '#191919', '#262626', '#333333', '#3F3F3F', '#4C4C4C', '#595959', '#666666', '#737373', '#7F7F7F', '#8C8C8C', '#999999', '#A6A6A6', '#B2B2B2', '#BFBFBF', '#CCCCCC', '#D9D9D9', '#E6E6E6', '#F2F2F2'].reverse(),
hot: ['#000000', '#220000', '#440000', '#660000', '#880000', '#AA0000', '#CC0000', '#EE0000', '#FF1100', '#FF3300', '#FF5500', '#FF7700', '#FF9900', '#FFBB00', '#FFDD00', '#FFFF00', '#FFFF33', '#FFFF66', '#FFFF99', '#FFFFCC'].reverse(),
jet: ['#00007F', '#0000B2', '#0000E5', '#0019FF', '#004DFF', '#007FFF', '#00B2FF', '#00E5FF', '#FFFFF2', '#FFFFD9', '#FFFFBF', '#FFFFA5', '#FFFF8C', '#FFE500', '#FFB300', '#FF7F00', '#FF4C00', '#FF1900', '#E50000', '#B20000'],
no_green: ['#1F60FF', '#1F60FF', '#1F9FFF', '#1FBFFF', '#00CFFF', '#2AFFFF', '#2AFFFF', '#55FFFF', '#7FFFFF', '#AAFFFF', '#FFFF54', '#FFFF54', '#FFF000', '#FFBF00', '#FFA800', '#FF8A00', '#FF8A00', '#FF7000', '#FF4D00', '#FF0000'],
polar: ['#0000FF', '#1919FF', '#3333FF', '#4C4CFF', '#6666FF', '#7F7FFF', '#9999FF', '#B2B2FF', '#CCCCFF', '#E6E6FF', '#FFFFFF', '#FFE5E5', '#FFCCCC', '#FFB2B2', '#FF9999', '#FF7F7F', '#FF6666', '#FF4C4C', '#FF3333', '#FF1A1A'],
polar: ['#0000FF', '#1919FF', '#3333FF', '#4C4CFF', '#6666FF', '#7F7FFF', '#9999FF', '#B2B2FF', '#CCCCFF', '#E6E6FF', '#FFFFFF', '#FFE5E5', '#FFCCCC', '#FFB2B2', '#FF9999', '#FF7F7F', '#FF6666', '#FF4C4C', '#FF3333', '#FF1A1A'],
red2green: ['#FF0000', '#FF1919', '#FF3333', '#FF4C4C', '#FF6666', '#FF7F7F', '#FF9999', '#FFB2B2', '#FFCCCC', '#FFE6E6', '#FFFFFF', '#E5FFE5', '#CCFFCC', '#B2FFB2', '#99FF99', '#7FFF7F', '#66FF66', '#4CFF4C', '#33FF33', '#1AFF1A'].reverse(),
relief: ['#000000', '#000413', '#000728', '#002650', '#005E8C', '#0096C8', '#45BCBB', '#8AE2AE', '#BCF8B9', '#DBFBDC', '#467832', '#887438', '#B19D48', '#DBC758', '#FAE769', '#FAEB7E', '#FCED93', '#FCF1A7', '#FCF6C1', '#FDFAE0'].reverse(),
split: ['#7F7FFF', '#6666E6', '#4D4DCC', '#3333B3', '#1A1A99', '#00007F', '#000066', '#00004D', '#000033', '#00001A', '#000000', '#1A0000', '#330000', '#4D0000', '#660000', '#7F0000', '#991A1A', '#B33333', '#CC4D4D', '#E66666'],
wysiwyg: ['#3F003F', '#3F003F', '#3F00BF', '#003FFF', '#00A0FF', '#3FBFFF', '#3FBFFF', '#40E0FF', '#3FFFBF', '#3FFF3F', '#7FFF3F', '#BFFF3F', '#BFFF3F', '#FFE040', '#FFE040', '#FF6040', '#FF1F40', '#FF60C0', '#FFA0FF', '#FFA0FF'].reverse()
}
// return
return {
colorSets: colorSets
}
red2green: ['#FF0000', '#FF1919', '#FF3333', '#FF4C4C', '#FF6666', '#FF7F7F', '#FF9999', '#FFB2B2', '#FFCCCC', '#FFE6E6', '#FFFFFF', '#E5FFE5', '#CCFFCC', '#B2FFB2', '#99FF99', '#7FFF7F', '#66FF66', '#4CFF4C', '#33FF33', '#1AFF1A'].reverse(),
relief: ['#000000', '#000413', '#000728', '#002650', '#005E8C', '#0096C8', '#45BCBB', '#8AE2AE', '#BCF8B9', '#DBFBDC', '#467832', '#887438', '#B19D48', '#DBC758', '#FAE769', '#FAEB7E', '#FCED93', '#FCF1A7', '#FCF6C1', '#FDFAE0'].reverse(),
split: ['#7F7FFF', '#6666E6', '#4D4DCC', '#3333B3', '#1A1A99', '#00007F', '#000066', '#00004D', '#000033', '#00001A', '#000000', '#1A0000', '#330000', '#4D0000', '#660000', '#7F0000', '#991A1A', '#B33333', '#CC4D4D', '#E66666'],
wysiwyg: ['#3F003F', '#3F003F', '#3F00BF', '#003FFF', '#00A0FF', '#3FBFFF', '#3FBFFF', '#40E0FF', '#3FFFBF', '#3FFF3F', '#7FFF3F', '#BFFF3F', '#BFFF3F', '#FFE040', '#FFE040', '#FF6040', '#FF1F40', '#FF60C0', '#FFA0FF', '#FFA0FF'].reverse()
}
}
});
@@ -1,448 +1,391 @@
// dependencies
define(['plugin/charts/tools', 'utils/utils', 'plugin/charts/others/heatmap/heatmap-parameters'], function(Tools, Utils, HeatmapParameters) {
// widget
return Backbone.View.extend({
// options
optionsDefault: {
margin: {
top : 40,
right : 70,
bottom : 70,
left : 70
},
style: {
'font-weight' : 'normal',
'font-family' : 'Verdana',
'font-size' : 12
},
legend: {
width : 15,
size : 0.9,
style : {
'font-weight' : 'normal',
'font-family' : 'Verdana',
'font-size' : 11
define( [ 'plugin/charts/utilities/tabular-utilities', 'utils/utils', 'plugin/charts/others/heatmap/heatmap-parameters' ], function( Utilities, Utils, HeatmapParameters ) {
return Backbone.View.extend({
optionsDefault: {
margin: {
top : 40,
right : 70,
bottom : 70,
left : 70
},
limit : 7
style: {
'font-weight' : 'normal',
'font-family' : 'Verdana',
'font-size' : 12
},
legend: {
width : 15,
size : 0.9,
style : {
'font-weight' : 'normal',
'font-family' : 'Verdana',
'font-size' : 11
},
limit : 7
},
background_color : '#FFFFFF',
debug_color : '#FFFFFF'
},
background_color : '#FFFFFF',
debug_color : '#FFFFFF'
},
// initialize
initialize: function(app, options) {
// collect parameters
this.app = app;
this.chart = options.chart;
this.canvas_id = options.canvas_id;
this.group = options.groups[0];
this.data = options.groups[0].values;
this.options = Utils.merge (this.optionsDefault, options);
// get color set
this.color_set = HeatmapParameters.colorSets[this.chart.settings.get('color_set')];
// categories
this.categories = Tools.makeUniqueCategories([this.group]);
// domains/scales
this.xScale = d3.scale.linear().domain([0, this.categories.array.x.length]);
this.yScale = d3.scale.linear().domain([0, this.categories.array.y.length]);
// color scale
this.zMin = d3.min(this.data, function(d) { return d.z; });
this.zMax = d3.max(this.data, function(d) { return d.z; });
this.zScale = d3.scale.quantize().domain([this.zMin, this.zMax]).range(this.color_set);
// create axis
this.xAxis = d3.svg.axis().scale(this.xScale).orient('bottom');
this.yAxis = d3.svg.axis().scale(this.yScale).orient('left');
// make categories
this._makeTickFormat('x');
this._makeTickFormat('y');
// add tooltip
this.tooltip = d3.select('.charts-viewport-container').append('div')
.attr('class', 'charts-tooltip')
.style(this.options.style)
.style('opacity', 0);
// refresh on window resize
var self = this;
$(window).on('resize', function () {
self.redraw();
});
// draw
this.redraw();
// add zoom
Tools.addZoom({
xAxis : this.xAxis,
yAxis : this.yAxis,
redraw : function() { self.redraw(); },
svg : d3.select('#' + this.canvas_id)
});
},
// redraw
redraw: function() {
// get parameters
var chart = this.chart;
var data = this.data;
var self = this;
this.data = data;
// get/reset container
var container = $('#' + this.canvas_id);
container.empty();
// get domain
var xDomain = this.xScale.domain();
var yDomain = this.yScale.domain();
// set ticks
var xTickStart = Math.ceil(xDomain[0]);
var xTickEnd = Math.floor(xDomain[1]);
var yTickStart = Math.ceil(yDomain[0]);
var yTickEnd = Math.floor(yDomain[1]);
this.xAxis.tickValues(d3.range(xTickStart, xTickEnd, 1));
this.yAxis.tickValues(d3.range(yTickStart, yTickEnd, 1));
// get margins
var margin = this.options.margin;
// configure dimensions
this.height = parseInt(container.height()) - margin.top - margin.bottom;
this.width = parseInt(container.width()) - margin.left - margin.right;
// set range
this.xScale.range([0, this.width]);
this.yScale.range([this.height, 0]);
// get box properties
this.rowCount = yDomain[1] - yDomain[0];
this.colCount = xDomain[1] - xDomain[0];
this.boxWidth = Math.max(1, Math.floor(this.width / this.colCount));
this.boxHeight = Math.max(1, Math.floor(this.height / this.rowCount));
// create group
var svg = this.svg = d3.select('#' + this.canvas_id)
.append('g')
.attr('class', 'heatmap')
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
// build elements
this._buildBoxes();
this._buildX();
this._buildY();
// show legend only if requested
if (this.chart.settings.get('show_legend') == 'true') {
this._buildLegend();
}
},
// y axis
_buildBoxes: function() {
// link this
var self = this;
// collect parameters
var height = this.height;
var width = this.width;
var margin = this.options.margin;
var svg = this.svg;
var boxWidth = this.boxWidth;
var boxHeight = this.boxHeight;
// box location
function _locator(d) {
return 'translate(' + self.xScale(d.x) + ',' + self.yScale(d.y+1) + ')';
};
// box color
function _color (d) {
return self.zScale(d.z);
};
// set background color
var gBackground = svg.append('rect')
.attr('width', width)
.attr('height', height)
.attr('fill', this.options.background_color);
// clip path
var clip = svg.append('clipPath')
.attr('id', 'clip')
.append('rect')
.attr('x', 0)
.attr('y', 0)
.attr('width', width)
.attr('height', height);
// create chart area
var chartBody = svg.append('g')
.attr('clip-path', 'url(#clip)');
initialize: function( app, options ) {
var self = this;
this.app = app;
this.chart = options.chart;
this.canvas_id = options.canvas_id;
this.group = options.groups[ 0 ];
this.data = options.groups[ 0 ].values;
this.options = Utils.merge ( this.optionsDefault, options );
// add boxes to chart area
var boxes = chartBody.selectAll('box-group').data(this.data, function(d, i) {
return d.x + '\0' + d.y;
});
var gEnter = boxes.enter().append('g')
.attr('class', 'box-group');
gEnter.append('rect')
.attr('class','heat-box');
boxes.selectAll('rect')
.attr('rx', 1)
.attr('ry', 1)
.attr('fill', _color)
.attr('width', boxWidth)
.attr('height', boxHeight)
.attr('transform', _locator);
// add tooltip events
boxes.selectAll('rect')
.on('dblclick', function(d) {
var url = self.chart.settings.get('url_template').trim();
if (url) {
d3.event.stopPropagation();
var xLabel = self.categories.array.x[d.x];
var yLabel = self.categories.array.y[d.y];
window.open(url.replace('__LABEL__', xLabel));
window.open(url.replace('__LABEL__', yLabel));
// get color set
this.color_set = HeatmapParameters.colorSets[ this.chart.settings.get( 'color_set' ) ];
// categories
this.categories = Utilities.makeUniqueCategories( [ this.group ] );
// domains/scales
this.xScale = d3.scale.linear().domain( [ 0, this.categories.array.x.length ] );
this.yScale = d3.scale.linear().domain( [ 0, this.categories.array.y.length ] );
// color scale
this.zMin = d3.min( this.data, function( d ) { return d.z; } );
this.zMax = d3.max( this.data, function( d ) { return d.z; } );
this.zScale = d3.scale.quantize().domain( [ this.zMin, this.zMax ] ).range( this.color_set );
// create axis
this.xAxis = d3.svg.axis().scale( this.xScale ).orient( 'bottom' );
this.yAxis = d3.svg.axis().scale( this.yScale ).orient( 'left' );
// make categories
this._makeTickFormat( 'x' );
this._makeTickFormat( 'y' );
// add tooltip
this.tooltip = d3.select( '.charts-viewport-container' ).append( 'div' )
.attr( 'class', 'charts-tooltip' )
.style( this.options.style )
.style( 'opacity', 0 );
// refresh on window resize
$( window ).on( 'resize', function () { self.redraw() } );
this.redraw();
Utilities.addZoom({
xAxis : this.xAxis,
yAxis : this.yAxis,
redraw : function() { self.redraw() },
svg : d3.select( '#' + this.canvas_id )
});
},
/** Redraw */
redraw: function() {
// get parameters
var chart = this.chart;
var data = this.data;
var self = this;
this.data = data;
// get/reset container
var container = $( '#' + this.canvas_id );
container.empty();
// get domain
var xDomain = this.xScale.domain();
var yDomain = this.yScale.domain();
// set ticks
var xTickStart = Math.ceil( xDomain[ 0 ] );
var xTickEnd = Math.floor( xDomain[ 1 ] );
var yTickStart = Math.ceil( yDomain[ 0 ] );
var yTickEnd = Math.floor( yDomain[ 1 ] );
this.xAxis.tickValues( d3.range( xTickStart, xTickEnd, 1 ) );
this.yAxis.tickValues( d3.range( yTickStart, yTickEnd, 1 ) );
// get margins
var margin = this.options.margin;
// configure dimensions
this.height = parseInt( container.height() ) - margin.top - margin.bottom;
this.width = parseInt( container.width() ) - margin.left - margin.right;
// set range
this.xScale.range( [ 0, this.width ] );
this.yScale.range( [ this.height, 0 ] );
// get box properties
this.rowCount = yDomain[ 1 ] - yDomain[ 0 ];
this.colCount = xDomain[ 1 ] - xDomain[ 0 ];
this.boxWidth = Math.max( 1, Math.floor( this.width / this.colCount ) );
this.boxHeight = Math.max( 1, Math.floor( this.height / this.rowCount ) );
// create group
var svg = this.svg = d3.select( '#' + this.canvas_id )
.append( 'g' )
.attr( 'class', 'heatmap' )
.attr( 'transform', 'translate(' + margin.left + ',' + margin.top + ')' );
// build elements
this._buildBoxes();
this._buildX();
this._buildY();
// show legend only if requested
if ( this.chart.settings.get('show_legend') == 'true' ) {
this._buildLegend();
}
})
.on('mouseover', function(d) {
self.tooltip.style('opacity', 0.9);
self.tooltip .html(self._templateTooltip(d))
.style('left', (d3.event.pageX) + 'px')
.style('top', (d3.event.pageY - 20) + 'px');
})
.on('mouseout', function(d) {
self.tooltip.style('opacity', 0);
});
},
/** Build boxes */
_buildBoxes: function() {
var self = this;
var height = this.height;
var width = this.width;
var margin = this.options.margin;
var svg = this.svg;
var boxWidth = this.boxWidth;
var boxHeight = this.boxHeight;
function _locator( d ) { return 'translate(' + self.xScale( d.x ) + ',' + self.yScale( d.y + 1 ) + ')' };
function _color ( d ) { return self.zScale( d.z ) };
// initially hide tooltips
this.tooltip.style('opacity', 0);
// exit
boxes.exit().remove();
},
// x axis
_buildX : function() {
// link this
var self = this;
// collect parameters
var height = this.height;
var width = this.width;
var margin = this.options.margin;
var svg = this.svg;
var font_size = this.options.style['font-size'];
var boxWidth = this.boxWidth;
// draw x axis
this.gxAxis = svg.append('g')
.attr('class', 'x axis')
.style('stroke-width', 1)
.attr('transform', 'translate(0,' + height + ')')
.call(this.xAxis);
// fix text
var xFontSize = Math.min(boxWidth, font_size);
this.gxAxis.selectAll('text')
.style(this.options.style)
.style({'font-size': xFontSize + 'px'})
.attr('transform', function(d) {
var y = -this.getBBox().height - 15;
var x = -xFontSize + boxWidth/2;
return 'rotate(-90)translate(' + y + ',' + x + ')';
});
// set background color
var gxAxisLabelBackground = svg.append('rect')
.attr('width', width)
.attr('height', font_size + 3)
.attr('y', height + margin.bottom - font_size - 3)
.attr('fill', this.options.debug_color)
.attr('opacity', 0.7);
// axis label
this.gxAxisLabel = svg.append('text')
.attr('class', 'x label')
.style(this.options.style)
.text(this.chart.settings.get('x_axis_label'))
.attr('transform', function(d) {
var y = height + margin.bottom - font_size/3;
var x = (width - this.getBBox().width)/2;
return 'translate(' + x + ',' + y + ')';
});
// chart title
this.gxTickLabel = svg.append('text')
.attr('class', 'title')
.style(this.options.style)
.style({'font-size' : 1.5*font_size})
.text(this.group.key)
.attr('transform', function(d) {
var y = -margin.top/2;
var x = (width - this.getBBox().width)/2;
return 'translate(' + x + ',' + y + ')';
});
},
// y axis
_buildY : function() {
// link this
var self = this;
// collect parameters
var height = this.height;
var width = this.width;
var margin = this.options.margin;
var svg = this.svg;
var font_size = this.options.style['font-size'];
var boxHeight = this.boxHeight;
// draw y axis
this.gyAxis = svg.append('g')
.attr('class', 'y axis')
.style('stroke-width', 1)
.call(this.yAxis);
// set background color
var gBackground = svg.append( 'rect' )
.attr( 'width', width )
.attr( 'height', height )
.attr( 'fill', this.options.background_color );
// fix text
var yFontSize = Math.min(boxHeight, font_size);
this.gyAxis.selectAll('text')
.style(this.options.style)
.style({'font-size': yFontSize + 'px'})
.attr('y', -boxHeight/2);
// set background color
var gyAxisLabelBackground = svg.append('rect')
.attr('width', font_size)
.attr('height', height)
.attr('x', -margin.left)
.attr('fill', this.options.debug_color)
.attr('opacity', 0.7);
// axis label
this.gyAxisLabel = svg.append('text')
.attr('class', 'y label')
.style(this.options.style)
.text(this.chart.settings.get('y_axis_label'))
.attr('transform', function(d) {
var x = -margin.left + font_size-2;
var y = -(height + this.getBBox().width)/2;
return 'rotate(-90)translate(' + y + ',' + x + ')';
});
},
// clip path
var clip = svg.append( 'clipPath' )
.attr( 'id', 'clip' )
.append( 'rect' )
.attr( 'x', 0 )
.attr( 'y', 0 )
.attr( 'width', width )
.attr( 'height', height );
// legend
_buildLegend : function() {
// link this
var self = this;
// collect parameters
var height = this.height;
var width = this.width;
var margin = this.options.margin;
var font_size = this.options.legend.style['font-size'];
var limit = this.options.legend.limit;
// create chart area
var chartBody = svg.append( 'g' ).attr( 'clip-path', 'url(#clip)' );
// identify legend dimensions
var legendSize = this.options.legend.size;
var legendWidth = this.options.legend.width;
var legendElements = this.zScale.range().length;
var legendElementHeight = Math.max(legendSize * height / legendElements, font_size);
var legendHeight = legendElements * legendElementHeight / 2;
// add boxes to chart area
var boxes = chartBody.selectAll( 'box-group' ).data( this.data, function( d, i ) {
return d.x + '\0' + d.y;
});
var gEnter = boxes.enter().append( 'g' )
.attr( 'class', 'box-group' );
gEnter.append( 'rect' )
.attr( 'class','heat-box' );
boxes.selectAll( 'rect' )
.attr( 'rx', 1 )
.attr( 'ry', 1 )
.attr( 'fill', _color )
.attr( 'width', boxWidth )
.attr( 'height', boxHeight )
.attr( 'transform', _locator );
// add tooltip events
boxes.selectAll( 'rect' )
.on( 'dblclick', function( d ) {
var url = self.chart.settings.get( 'url_template' ).trim();
if ( url ) {
d3.event.stopPropagation();
var xLabel = self.categories.array.x[ d.x ];
var yLabel = self.categories.array.y[ d.y ];
window.open( url.replace( '__LABEL__', xLabel ) );
window.open( url.replace( '__LABEL__', yLabel ) );
}
})
.on('mouseover', function( d ) {
self.tooltip.style( 'opacity', 0.9 );
self.tooltip .html( self._templateTooltip( d ) )
.style( 'left', ( d3.event.pageX ) + 'px' )
.style( 'top', ( d3.event.pageY - 20 ) + 'px' );
})
.on('mouseout', function( d ) {
self.tooltip.style( 'opacity', 0 );
});
// initially hide tooltips
this.tooltip.style( 'opacity', 0 );
// exit
boxes.exit().remove();
},
// check number of legend elements
var data = d3.range(this.zMin, this.zMax, 2 * (this.zMax-this.zMin) / legendElements).reverse();
if (data.length < 2) {
return;
}
// create legend elements
var legend = this.svg.selectAll('.legend')
.data(data)
.enter().append('g')
.attr('class', 'legend')
.attr('transform', function(d, i) {
var x = width + 10;
var y = ((height - legendHeight) / 2) + (i * legendElementHeight);
/** Build x axis */
_buildX : function() {
var self = this;
var height = this.height;
var width = this.width;
var margin = this.options.margin;
var svg = this.svg;
var font_size = this.options.style[ 'font-size' ];
var boxWidth = this.boxWidth;
// draw x axis
this.gxAxis = svg.append( 'g' )
.attr( 'class', 'x axis' )
.style( 'stroke-width', 1 )
.attr( 'transform', 'translate(0,' + height + ')' )
.call( this.xAxis );
// fix text
var xFontSize = Math.min( boxWidth, font_size );
this.gxAxis.selectAll( 'text' )
.style( this.options.style )
.style( { 'font-size': xFontSize + 'px' } )
.attr( 'transform', function( d ) {
var y = -this.getBBox().height - 15;
var x = -xFontSize + boxWidth / 2;
return 'rotate(-90)translate(' + y + ',' + x + ')';
});
// set background color
var gxAxisLabelBackground = svg.append( 'rect' )
.attr( 'width', width )
.attr( 'height', font_size + 3 )
.attr( 'y', height + margin.bottom - font_size - 3 )
.attr( 'fill', this.options.debug_color )
.attr( 'opacity', 0.7 );
// axis label
this.gxAxisLabel = svg.append( 'text' )
.attr( 'class', 'x label' )
.style( this.options.style )
.text( this.chart.settings.get( 'x_axis_label' ) )
.attr( 'transform', function( d ) {
var y = height + margin.bottom - font_size / 3;
var x = ( width - this.getBBox().width ) / 2;
return 'translate(' + x + ',' + y + ')';
});
legend.append('rect')
.attr('width', legendWidth)
.attr('height', legendElementHeight)
.style('fill', function(z) {
return self.zScale(z);
});
legend.append('text')
.attr('x', legendWidth + 4)
.attr('y', function() {
return (legendElementHeight+this.getBBox().height)/2;
})
.style(this.options.legend.style)
.text(function(d) {
var str = String(d);
if (str.length > limit) {
return str.substr(0, limit-2) + '..';
} else {
return str;
}
});
this.svg.append('text')
.style(this.options.legend.style)
.style({'font-size' : 9, 'font-weight': 'bold'})
.text('Legend')
.attr('transform', function(d, i) {
var x = width + (margin.right - this.getBBox().width) / 2;
var y = ((height - legendHeight) / 2) - 10;
return 'translate(' + x + ',' + y + ')';
});
},
// create axes formatting
_makeTickFormat: function(id) {
var settings = this.chart.settings;
var self = this;
Tools.makeTickFormat({
categories : self.categories.array[id],
type : settings.get(id + '_axis_type'),
precision : settings.get(id + '_axis_precision'),
formatter : function(formatter) {
if (formatter) {
self[id + 'Axis'].tickFormat(function(value) {
return formatter(value);
});
}
}
});
},
// handle error
_handleError: function(err) {
this.chart.state('failed', err);
},
// templates
_templateTooltip: function(d) {
// collect data values
var x = this.categories.array.x[d.x];
var y = this.categories.array.y[d.y];
var z = d.z;
// chart title
this.gxTickLabel = svg.append( 'text' )
.attr( 'class', 'title' )
.style( this.options.style )
.style({'font-size' : 1.1 * font_size } )
.text( this.group.key )
.attr( 'transform', function( d ) {
var y = -margin.top / 2;
var x = ( width - this.getBBox().width ) / 2;
return 'translate(' + x + ',' + y + ')';
});
},
// create tooltip
var tmpl = '<table>' +
/** Build y axis */
_buildY : function() {
var self = this;
var height = this.height;
var width = this.width;
var margin = this.options.margin;
var svg = this.svg;
var font_size = this.options.style[ 'font-size' ];
var boxHeight = this.boxHeight;
// draw y axis
this.gyAxis = svg.append( 'g' )
.attr( 'class', 'y axis' )
.style( 'stroke-width', 1 )
.call( this.yAxis );
// fix text
var yFontSize = Math.min( boxHeight, font_size );
this.gyAxis.selectAll( 'text' )
.style( this.options.style )
.style( { 'font-size': yFontSize + 'px' } )
.attr( 'y', -boxHeight / 2 );
// set background color
var gyAxisLabelBackground = svg.append( 'rect' )
.attr( 'width', font_size )
.attr( 'height', height )
.attr( 'x', -margin.left )
.attr( 'fill', this.options.debug_color )
.attr( 'opacity', 0.7 );
// axis label
this.gyAxisLabel = svg.append( 'text' )
.attr( 'class', 'y label' )
.style( this.options.style )
.text( this.chart.settings.get( 'y_axis_label' ) )
.attr( 'transform', function( d ) {
var x = -margin.left + font_size - 2;
var y = -( height + this.getBBox().width ) / 2;
return 'rotate(-90)translate(' + y + ',' + x + ')';
});
},
/** Build legend */
_buildLegend : function() {
var self = this;
var height = this.height;
var width = this.width;
var margin = this.options.margin;
var font_size = this.options.legend.style[ 'font-size' ];
var limit = this.options.legend.limit;
var legendSize = this.options.legend.size;
var legendWidth = this.options.legend.width;
var legendElements = this.zScale.range().length;
var legendElementHeight = Math.max( legendSize * height / legendElements, font_size );
var legendHeight = legendElements * legendElementHeight / 2;
var data = d3.range( this.zMin, this.zMax, 2 * ( this.zMax - this.zMin ) / legendElements ).reverse();
if ( data.length < 2 ) {
return;
}
var legend = this.svg.selectAll( '.legend' )
.data( data )
.enter().append( 'g' )
.attr( 'class', 'legend' )
.attr( 'transform', function( d, i ) {
var x = width + 10;
var y = ( ( height - legendHeight ) / 2 ) + ( i * legendElementHeight );
return 'translate(' + x + ',' + y + ')';
});
legend.append( 'rect' )
.attr( 'width', legendWidth )
.attr( 'height', legendElementHeight )
.style( 'fill', function( z ) { return self.zScale( z ) } );
legend.append('text')
.attr( 'x', legendWidth + 4 )
.attr( 'y', function() { return ( legendElementHeight + this.getBBox().height ) / 2 } )
.style( this.options.legend.style )
.text( function( d ) { return String( d ).length > limit ? String( d ).substr( 0, limit - 2 ) + '..' : String( d ) } );
this.svg.append( 'text' )
.style( this.options.legend.style )
.style( { 'font-size' : 9, 'font-weight': 'bold' } )
.text( 'Legend' )
.attr( 'transform', function( d, i ) {
var x = width + ( margin.right - this.getBBox().width ) / 2;
var y = ( ( height - legendHeight ) / 2 ) - 10;
return 'translate(' + x + ',' + y + ')';
});
},
/** Create axes formatting */
_makeTickFormat: function( id ) {
var settings = this.chart.settings;
var self = this;
Utilities.makeTickFormat({
categories : self.categories.array[ id ],
type : settings.get( id + '_axis_type|type' ),
precision : settings.get( id + '_axis_type|precision' ),
formatter : function( formatter ) {
if ( formatter ) {
self[ id + 'Axis' ].tickFormat( function( value ) {
return formatter( value );
});
}
}
});
},
/** Handle error */
_handleError: function( err ) {
this.chart.state( 'failed', err );
},
/** Main template */
_templateTooltip: function(d) {
var x = this.categories.array.x[ d.x ];
var y = this.categories.array.y[ d.y ];
var z = d.z;
return '<table>' +
'<tr>' +
'<td class="charts-tooltip-first">Row:</td>' +
'<td>' + y + '</td>' +
@@ -456,8 +399,6 @@ return Backbone.View.extend({
'<td>' + z + '</td>' +
'</tr>' +
'</table>';
return tmpl;
}
});
}
});
});
@@ -1,23 +1,15 @@
// dependencies
define(['plugin/charts/tools', 'plugin/charts/others/heatmap/heatmap-plugin'], function(Tools, HeatMap) {
// widget
return Backbone.View.extend({
// initialize
initialize: function(app, options) {
// define render function
options.render = function(canvas_id, groups) {
new HeatMap(app, {
chart : options.chart,
canvas_id : canvas_id,
groups : groups
});
return true;
};
// call panel helper
Tools.panelHelper(app, options);
}
});
define( [ 'plugin/charts/utilities/tabular-utilities', 'plugin/charts/others/heatmap/heatmap-plugin' ], function( Utilities, HeatMap ) {
return Backbone.View.extend({
initialize: function( app, options ) {
options.render = function( canvas_id, groups ) {
new HeatMap( app, {
chart : options.chart,
canvas_id : canvas_id,
groups : groups
});
return true;
};
Utilities.panelHelper( options );
}
});
});
@@ -1,10 +1,7 @@
define(['plugin/charts/others/heatmap/config'], function(config_default) {
return $.extend(true, {}, config_default, {
title : 'Clustered Heatmap',
category : 'Data processing (requires \'charts\' tool from Toolshed)',
execute : 'heatmap',
keywords : 'small medium large'
});
define( [ 'plugin/charts/others/heatmap/config' ], function( default_config ) {
return $.extend( true, {}, default_config, {
title : 'Clustered Heatmap',
category : 'Data processing (requires \'charts\' tool from Toolshed)',
keywords : 'others default'
});
});
@@ -1,55 +1,40 @@
// dependencies
define(['plugin/charts/tools', 'plugin/charts/others/heatmap/heatmap-plugin'], function(Tools, HeatMap) {
// widget
return Backbone.View.extend({
// initialize
initialize: function(app, options) {
// get request dictionary
var request_dictionary = options.request_dictionary;
// configure request
var index = 0;
var tmp_dict = {
id : request_dictionary.id,
groups : []
};
// configure groups
for (var group_index in request_dictionary.groups) {
var group = request_dictionary.groups[group_index];
tmp_dict.groups.push({
key : group.key,
columns : {
x: {
index : index++,
is_label : true
},
y: {
index : index++,
is_label : true
},
z: {
index : index++
}
define( [ 'plugin/charts/utilities/tabular-utilities', 'plugin/components/jobs', 'plugin/charts/others/heatmap/heatmap-plugin' ], function( Utilities, Jobs, HeatMap ) {
return Backbone.View.extend({
initialize: function(app, options) {
Jobs.request( app, Utilities.buildJobDictionary( 'heatmap', app.chart ), function( dataset ) {
var request_dictionary = Utilities.buildRequestDictionary( app.chart, dataset.id );
var index = 0;
var tmp_dict = { id : request_dictionary.id, groups : [] };
for ( var group_index in request_dictionary.groups ) {
var group = request_dictionary.groups[ group_index ];
tmp_dict.groups.push({
key : group.key,
columns : {
x: {
index : index++,
is_label : true
},
y: {
index : index++,
is_label : true
},
z: {
index : index++
}
}
});
}
});
options.request_dictionary = tmp_dict;
options.render = function( canvas_id, groups ) {
new HeatMap( app, {
chart : options.chart,
canvas_id : canvas_id,
groups : groups
});
return true;
};
Utilities.panelHelper( options );
}, function() { options.process.reject() } );
}
// define render function
options.request_dictionary = tmp_dict;
options.render = function(canvas_id, groups) {
new HeatMap(app, {
chart : options.chart,
canvas_id : canvas_id,
groups : groups
});
return true;
};
// call panel helper
Tools.panelHelper(app, options);
}
});
});
});
@@ -0,0 +1,13 @@
define( [], function() {
return [
{ label : 'Default', value: 'default',
help : 'The visualizations below were curated from different libraries. Its a representative set covering most use cases. Use this selection by default.' },
{ label : 'NVD3', value: 'nvd3',
help : 'NVD3 is a popular d3-based library hosted at <a href="http://www.nvd3.org" target="_blank">www.nvd3.org<a/>. Most visualization types support intuitive drag-and-drop zooming and scaling. NVD3 generates high quality vector graphics. As with all vector based plugins, you may experience a slow down in browser responsiveness if visualizing thousands of data points.' },
{ label : 'jqPlot', value: 'jqplot',
help : 'jqPlot is a canvas-based library hosted at <a href="http://www.jqplot.com" target="_blank">www.jqplot.com<a/>. It is a plotting and charting plugin for the jQuery Javascript framework. Since based on canvas it is capable of rendering many thousand data points without adverse effects.' },
{ label : 'Others', value: 'others',
help : 'These visualizations were developed by the Galaxy team.'
}
];
});
@@ -1,379 +0,0 @@
// dependencies
define(['utils/utils'], function(Utils) {
// render
function panelHelper (app, options) {
// link this
var self = this;
// require parameters
var process = options.process;
var chart = options.chart;
var request_dictionary = options.request_dictionary;
var render = options.render;
var canvas_list = options.canvas_list;
// get request size from chart
request_dictionary.query_limit = chart.definition.query_limit;
// define success function
request_dictionary.success = function() {
try {
// check if this chart has multiple panels
if (chart.settings.get('use_panels') === 'true') {
// draw groups in separate panels
var valid = true;
for (var group_index in request_dictionary.groups) {
var group = request_dictionary.groups[group_index];
if (!render(canvas_list[group_index], [group])) {
valid = false;
break;
}
}
if (valid) {
chart.state('ok', 'Multi-panel chart drawn.');
}
} else {
// draw all groups into a single panel
if (render(canvas_list[0], request_dictionary.groups)) {
chart.state('ok', 'Chart drawn.');
}
}
// unregister process
process.resolve();
} catch (err) {
// log
console.debug('FAILED: Tools::panelHelper() - ' + err);
// set chart state
chart.state('failed', err);
// unregister process
process.reject();
}
};
// add progress
request_dictionary.progress = function(percentage) {
if (chart.get('state') == 'wait') {
chart.state('wait', 'Loading data...' + percentage + '%');
}
};
// request data
app.datasets.request(request_dictionary);
};
// get domain boundaries value
function getDomains(groups, keys) {
// get value
function _apply(operator, key) {
var value = undefined;
for (var group_index in groups) {
var value_sub = d3[operator](groups[group_index].values, function(d) { return d[key]; });
if (value === undefined) {
value = value_sub;
} else {
value = Math[operator](value, value_sub);
}
}
return value;
};
var result = {};
for (var index in keys) {
var key = keys[index];
result[key] = {
min : _apply('min', key),
max : _apply('max', key),
};
}
return result;
};
// default series maker
function makeSeries(groups, keys) {
// plot data
var plot_data = [];
// loop through data groups
for (var group_index in groups) {
// get group
var group = groups[group_index];
// reset data
var data = [];
// format chart data
for (var value_index in group.values) {
// parse data
var point = [];
if (keys) {
for (var key_index in keys) {
var column_index = keys[key_index];
point.push(group.values[value_index][column_index]);
}
} else {
for (var column_index in group.values[value_index]) {
point.push(group.values[value_index][column_index]);
}
}
// add to data
data.push (point);
}
// append series
plot_data.push(data);
}
// return
return plot_data;
};
// default category maker
function makeCategories(groups, with_index) {
// hashkeys, arrays and counter for labeled columns
var array = {};
// identify label columns
var chart_definition = groups[0];
for (var key in chart_definition.columns) {
var column_def = chart_definition.columns[key];
if (column_def.is_label) {
array[key] = [];
}
}
// collect string labels in array
if (groups && groups[0]) {
var group = groups[0];
for (var j in group.values) {
var value_dict = group.values[j];
for (var key in array) {
array[key].push (String(value_dict[key]));
}
}
}
// index all values contained in label columns (for all groups)
mapCategories(array, groups);
// return dictionary
return {
array : array
}
};
// apply default mapping
// index all values contained in label columns (for all groups)
function mapCategories(array, groups) {
for (var i in groups) {
var group = groups[i];
for (var j in group.values) {
var value_dict = group.values[j];
for (var key in array) {
value_dict[key] = parseInt(j)
}
}
}
};
// category make for unique category labels
function makeUniqueCategories(groups, with_index) {
// hashkeys, arrays and counter for labeled columns
var categories = {};
var array = {};
var counter = {};
// identify label columns
var chart_definition = groups[0];
for (var key in chart_definition.columns) {
var column_def = chart_definition.columns[key];
if (column_def.is_label) {
categories[key] = {};
array[key] = [];
counter[key] = 0;
}
}
// index all values contained in label columns (for all groups)
for (var i in groups) {
var group = groups[i];
for (var j in group.values) {
var value_dict = group.values[j];
for (var key in categories) {
var value = String(value_dict[key]);
if (categories[key][value] === undefined) {
// add index
categories[key][value] = counter[key];
// array formatter
if (with_index) {
array[key].push([counter[key], value]);
} else {
array[key].push(value);
}
// increase counter
counter[key]++;
}
}
}
}
// convert group values into category indeces
for (var i in groups) {
var group = groups[i];
for (var j in group.values) {
var value_dict = group.values[j];
for (var key in categories) {
var value = String(value_dict[key]);
value_dict[key] = categories[key][value]
}
}
}
// return dictionary
return {
categories : categories,
array : array,
counter : counter
}
};
// make axis
function makeTickFormat (options) {
var type = options.type;
var precision = options.precision;
var categories = options.categories;
var formatter = options.formatter;
// hide axis
if (type == 'hide') {
formatter(function() { return '' });
return;
}
// format values/labels
if (type == 'auto') {
if (categories) {
formatter(function(value) {
return categories[value] || '';
});
}
} else {
var d3format = function(d) {
switch (type) {
case 's' :
var prefix = d3.formatPrefix(d);
return prefix.scale(d).toFixed() + prefix.symbol;
default :
return d3.format('.' + precision + type)(d);
}
};
if (categories) {
formatter(function(value) {
var label = categories[value];
if (label) {
if (isNaN(label)) {
return label;
} else {
try {
return d3format(label);
} catch (err) {
return label;
}
}
} else {
return '';
}
});
} else {
formatter(function(value) {
return d3format(value);
});
}
}
};
// add zoom handler
function addZoom(options) {
// scaleExtent
var scaleExtent = 100;
// parameters
var yAxis = options.yAxis;
var xAxis = options.xAxis;
var xDomain = options.xDomain || xAxis.scale().domain;
var yDomain = options.yDomain || yAxis.scale().domain;
var redraw = options.redraw;
var svg = options.svg;
// scales
var xScale = xAxis.scale();
var yScale = yAxis.scale();
// min/max boundaries
var x_boundary = xScale.domain().slice();
var y_boundary = yScale.domain().slice();
// create d3 zoom handler
var d3zoom = d3.behavior.zoom();
// ensure nice axis
xScale.nice();
yScale.nice();
// fix domain
function fixDomain(domain, boundary) {
domain[0] = Math.min(Math.max(domain[0], boundary[0]), boundary[1] - boundary[1]/scaleExtent);
domain[1] = Math.max(boundary[0] + boundary[1]/scaleExtent, Math.min(domain[1], boundary[1]));
return domain;
};
// zoom event handler
function zoomed() {
yDomain(fixDomain(yScale.domain(), y_boundary));
xDomain(fixDomain(xScale.domain(), x_boundary));
redraw();
};
// zoom event handler
function unzoomed() {
xDomain(x_boundary);
yDomain(y_boundary);
redraw();
d3zoom.scale(1);
d3zoom.translate([0,0]);
};
// initialize wrapper
d3zoom.x(xScale)
.y(yScale)
.scaleExtent([1, scaleExtent])
.on('zoom', zoomed);
// add handler
svg.call(d3zoom).on('dblclick.zoom', unzoomed);
// return
return d3zoom;
};
// return
return {
panelHelper : panelHelper,
makeCategories : makeCategories,
makeUniqueCategories : makeUniqueCategories,
makeSeries : makeSeries,
getDomains : getDomains,
mapCategories : mapCategories,
makeTickFormat : makeTickFormat,
addZoom : addZoom
}
});
@@ -1,4 +1,3 @@
// dependencies
define(['plugin/charts/nvd3/bar/config',
'plugin/charts/nvd3/bar_stacked/config',
'plugin/charts/nvd3/bar_horizontal/config',
@@ -8,6 +7,7 @@ define(['plugin/charts/nvd3/bar/config',
'plugin/charts/nvd3/stackedarea_full/config',
'plugin/charts/nvd3/stackedarea_stream/config',
'plugin/charts/nvd3/histogram/config',
'plugin/charts/nvd3/histogram_discrete/config',
'plugin/charts/nvd3/line/config',
'plugin/charts/nvd3/scatter/config',
'plugin/charts/nvd3/stackedarea/config',
@@ -17,33 +17,30 @@ define(['plugin/charts/nvd3/bar/config',
'plugin/charts/jqplot/boxplot/config',
'plugin/charts/jqplot/histogram_discrete/config',
'plugin/charts/others/heatmap/config',
'plugin/charts/others/heatmap_cluster/config'
], function(nvd3_bar,
nvd3_bar_stacked,
nvd3_bar_horizontal,
nvd3_bar_horizontal_stacked,
nvd3_line_focus,
nvd3_pie,
nvd3_stackedarea_full,
nvd3_stackedarea_stream,
nvd3_histogram,
nvd3_line,
nvd3_scatter,
nvd3_stackedarea,
jqplot_bar,
jqplot_line,
jqplot_scatter,
jqplot_boxplot,
jqplot_histogram_discrete,
others_heatmap,
others_heatmap_cluster
) {
// widget
return Backbone.Model.extend(
{
// types
defaults: {
'plugin/charts/others/heatmap_cluster/config',
'plugin/charts/others/example/config' ],
function(nvd3_bar,
nvd3_bar_stacked,
nvd3_bar_horizontal,
nvd3_bar_horizontal_stacked,
nvd3_line_focus,
nvd3_pie,
nvd3_stackedarea_full,
nvd3_stackedarea_stream,
nvd3_histogram,
nvd3_histogram_discrete,
nvd3_line,
nvd3_scatter,
nvd3_stackedarea,
jqplot_bar,
jqplot_line,
jqplot_scatter,
jqplot_boxplot,
jqplot_histogram_discrete,
others_heatmap,
others_heatmap_cluster,
others_example) {
return {
'nvd3_bar' : nvd3_bar,
'nvd3_bar_stacked' : nvd3_bar_stacked,
'nvd3_bar_horizontal' : nvd3_bar_horizontal,
@@ -56,14 +53,14 @@ return Backbone.Model.extend(
'nvd3_line' : nvd3_line,
'nvd3_scatter' : nvd3_scatter,
'nvd3_histogram' : nvd3_histogram,
'nvd3_histogram_discrete' : nvd3_histogram_discrete,
'jqplot_bar' : jqplot_bar,
'jqplot_histogram_discrete' : jqplot_histogram_discrete,
'jqplot_line' : jqplot_line,
'jqplot_scatter' : jqplot_scatter,
'jqplot_boxplot' : jqplot_boxplot,
'others_heatmap' : others_heatmap,
'others_heatmap_cluster' : others_heatmap_cluster
'others_heatmap_cluster' : others_heatmap_cluster,
'others_example' : others_example
}
});
});
@@ -0,0 +1,122 @@
/** This class handles, formats and caches datasets. */
define( [ 'utils/utils' ], function( Utils ) {
/** Fills request dictionary with data from cache/response */
var _cache = {};
var request = function( options ) {
// identify columns needed to fulfill request
var column_list = [];
_.each( options.groups, function( group ) {
_.each( group.columns, function( column ) {
var column = column.index;
var block_id = _block_id( options, column );
if ( column_list.indexOf( column ) === -1 && !_cache[ block_id ] && column != 'auto' && column != 'zero' && column !== undefined ) {
column_list.push( column );
}
});
});
if ( column_list.length == 0 ) {
_fillFromCache( options );
return;
}
// Fetch data columns into dataset object
Utils.get({
url : Galaxy.root + 'api/datasets/' + options.id,
data : {
data_type : 'raw_data',
provider : 'dataset-column',
indeces : column_list.toString()
},
success : function( response ) {
var results = new Array( column_list.length );
for ( var i = 0; i < results.length; i++ ) {
results[ i ] = [];
}
for ( var i in response.data ) {
var row = response.data[ i ];
for ( var j in row ) {
var v = row[ j ];
if ( v !== undefined && v != 2147483647 ) {
results[ j ].push( v );
}
}
}
console.debug( 'tabular-datasets::_fetch() - Fetching complete.' );
for ( var i in results ) {
var column = column_list[ i ];
var block_id = _block_id( options, column );
_cache[ block_id ] = results[ i ];
}
_fillFromCache( options );
}
});
};
/** Fill data from cache */
var _fillFromCache = function( options ) {
var result = Utils.clone( options );
console.debug( 'tabular-datasets::_fillFromCache() - Filling request from cache.' );
var limit = 0;
for ( var i in result.groups ) {
var group = result.groups[ i ];
for ( var key in group.columns ) {
var column = group.columns[ key ];
var block_id = _block_id( result, column.index );
var column_data = _cache[ block_id ];
if ( column_data ) {
limit = Math.max( limit, column_data.length );
}
}
}
if ( limit == 0 ) {
console.debug( 'tabular-datasets::_fillFromCache() - Reached data range limit.' );
}
for ( var i in result.groups ) {
var group = result.groups[ i ];
group.values = [];
for ( var j = 0; j < limit; j++ ) {
group.values[ j ] = { x : parseInt( j ) };
}
}
for ( var i in result.groups ) {
var group = result.groups[ i ];
for ( var key in group.columns ) {
var column = group.columns[ key ];
switch ( column.index ) {
case 'auto':
for ( var j = 0; j < limit; j++ ) {
var value = group.values[ j ];
value[ key ] = parseInt( j );
}
break;
case 'zero':
for ( var j = 0; j < limit; j++ ) {
var value = group.values[ j ];
value[ key ] = 0;
}
break;
default:
var block_id = _block_id( result, column.index );
var column_data = _cache[ block_id ];
for ( var j = 0; j < limit; j++ ) {
var value = group.values[ j ];
var v = column_data[ j ];
if ( isNaN( v ) && !column.is_label && !column.is_text ) {
v = 0;
}
value[ key ] = v;
}
}
}
}
options.success( result );
};
/** Get block id */
var _block_id = function ( options, column ) {
return options.id + '_' + '_' + column;
};
return { request: request };
});
@@ -0,0 +1,26 @@
define( [ 'plugin/charts/utilities/tabular-inputs' ], function( Inputs ) {
return {
title : '',
category : '',
library : '',
tag : '',
keywords : '',
datatype : 'tabular',
settings : {
x_axis_label : Inputs.axisLabel( 'x_axis_label' ),
x_axis_type : Inputs.axisType( 'x_axis_type' ),
y_axis_label : Inputs.axisLabel( 'y_axis_label' ),
y_axis_type : Inputs.axisType( 'y_axis_type' ),
show_legend : Inputs.boolean( 'show_legend', { label: 'Show legend', help: 'Would you like to add a legend?' } ),
use_panels : Inputs.boolean( 'use_panels', { label: 'Use multi-panels', help: 'Would you like to separate your data into individual panels?' } )
},
groups : {
key: {
label : 'Provide a label',
type : 'text',
placeholder : 'Data label',
value : 'Data label'
}
}
}
});
@@ -0,0 +1,65 @@
define( [], function() {
return {
axisLabel : function( name, options ) {
options = options || {};
prefix = name.substr( 0, 1 );
return {
name : name,
label : prefix.toUpperCase() + '-Axis label',
help : 'Provide a label for the axis.',
type : 'text',
value : options.value || prefix.toUpperCase() + '-axis',
placeholder : 'Axis label'
}
},
axisType : function( name, options ) {
options = options || {};
prefix = name.substr( 0, 1 );
var axisPrecision = function() {
return { name : 'precision',
label : 'Axis tick format',
help : 'Select the tick format for the axis.',
type : 'select',
value : options.precision || 1,
data : [ { label : '0.00001', value : '5' },
{ label : '0.0001', value : '4' },
{ label : '0.001', value : '3' },
{ label : '0.01', value : '2' },
{ label : '0.1', value : '1' },
{ label : '1', value : '0' } ] }
}
return {
name : prefix + '_axis_type',
type : 'conditional',
test_param : {
name : 'type',
label : prefix.toUpperCase() + '-Axis value type',
type : 'select',
value : options.value || 'auto',
help : 'Select the value type of the axis.',
data : [ { value : 'hide', label : '-- Do not show values --' },
{ value : 'auto', label : 'Auto' },
{ value : 'f', label : 'Float' },
{ value : 'd', label : 'Integer' },
{ value : 'e', label : 'Exponent' },
{ value : 'p', label : 'Percent' },
{ value : 's', label : 'SI-prefix' } ]
},
cases : [ { value : 'hide' },
{ value : 'auto' },
{ value : 'f', inputs: [ axisPrecision() ] },
{ value : 'd' },
{ value : 'e', inputs: [ axisPrecision() ] },
{ value : 'p', inputs: [ axisPrecision() ] },
{ value : 's' } ]
}
},
boolean : function( name, options ) {
options = options || {};
return { name : name,
label : options.label,
help : options.help,
type : 'boolean' }
}
}
});
@@ -0,0 +1,320 @@
define( [ 'utils/utils', 'plugin/charts/utilities/tabular-datasets' ], function( Utils, Datasets ) {
/** Create default data request dictionary */
function buildRequestDictionary( chart, dataset_id ) {
var result = { groups : [] };
result.id = dataset_id ? dataset_id : chart.get( 'dataset_id' );
var group_index = 0;
chart.groups.each( function( group ) {
var columns = {};
_.each( group.get( '__data_columns' ), function( data_columns, name ) {
columns[ name ] = Utils.merge( { index : group.get( name ) }, data_columns );
});
result.groups.push( Utils.merge({
key : ( ++group_index ) + ':' + group.get( 'key' ),
columns : columns
}, group.attributes ));
});
return result;
};
/** build job dictionary */
function buildJobDictionary( module, chart ) {
var settings_string = '';
var columns_string = '';
var group_index = 0;
for ( key in chart.settings.attributes ) {
settings_string += key + ':' + chart.settings.get( key ) + ', ';
};
settings_string = settings_string.substring( 0, settings_string.length - 2 )
chart.groups.each( function( group ) {
group_index++;
_.each( group.get( '__data_columns' ), function( data_columns, name ) {
columns_string += name + '_' + group_index + ':' + ( parseInt( group.get( name ) ) + 1 ) + ', ';
});
});
columns_string = columns_string.substring( 0, columns_string.length - 2 );
return {
'tool_id' : 'charts',
'inputs' : {
'input' : {
'id' : chart.get( 'dataset_id' ),
'src' : 'hda'
},
'module' : module,
'columns' : columns_string,
'settings' : settings_string
}
}
};
/** Assists in assigning the viewport panels */
function panelHelper( options ) {
var self = this;
var process = options.process;
var chart = options.chart;
var request_dictionary = options.request_dictionary || buildRequestDictionary( chart );
var render = options.render;
var canvas_list = options.canvas_list;
request_dictionary.success = function( result ) {
try {
if ( chart.settings.get( 'use_panels' ) === 'true' ) {
var valid = true;
for ( var group_index in result.groups ) {
var group = result.groups[ group_index ];
if (!render( canvas_list[ group_index ], [ group ] ) ) {
valid = false;
break;
}
}
if ( valid ) {
chart.state( 'ok', 'Multi-panel chart drawn.' );
}
} else {
if ( render( canvas_list[ 0 ], result.groups ) ) {
chart.state( 'ok', 'Chart drawn.' );
}
}
process.resolve();
} catch ( err ) {
console.debug( 'FAILED: tabular-utilities::panelHelper() - ' + err );
chart.state( 'failed', err );
process.reject();
}
};
Datasets.request( request_dictionary );
};
/** Get domain boundaries value */
function getDomains( groups, keys ) {
function _apply( operator, key ) {
var value = undefined;
for ( var group_index in groups ) {
var value_sub = d3[ operator ]( groups[ group_index ].values, function( d ) { return d[ key ] } );
value = value === undefined ? value_sub : Math[ operator ]( value, value_sub );
}
return value;
};
var result = {};
for( var index in keys ) {
var key = keys[ index ];
result[ key ] = {
min : _apply( 'min', key ),
max : _apply( 'max', key ),
};
}
return result;
};
/** Default series maker */
function makeSeries( groups, keys ) {
var plot_data = [];
for ( var group_index in groups ) {
var group = groups[ group_index ];
var data = [];
for ( var value_index in group.values ) {
var point = [];
if ( keys ) {
for ( var key_index in keys ) {
var column_index = keys[ key_index ];
point.push( group.values[ value_index ][ column_index ] );
}
} else {
for ( var column_index in group.values[ value_index ] ) {
point.push( group.values[ value_index ][ column_index ] );
}
}
data.push( point );
}
plot_data.push( data );
}
return plot_data;
};
/** Default category maker */
function makeCategories( groups, with_index ) {
var array = {};
// identify label columns
var chart_definition = groups[ 0 ];
for ( var key in chart_definition.columns ) {
var column_def = chart_definition.columns[ key ];
if ( column_def.is_label ) {
array[ key ] = [];
}
}
// collect string labels in array
if ( groups && groups[ 0 ] ) {
var group = groups[ 0 ];
for ( var j in group.values ) {
var value_dict = group.values[ j ];
for ( var key in array ) {
array[ key ].push ( String( value_dict[ key ] ) );
}
}
}
// index all values contained in label columns (for all groups)
mapCategories( array, groups );
return { array : array }
};
/** Apply default mapping index all values contained in label columns (for all groups) */
function mapCategories( array, groups ) {
for ( var i in groups ) {
var group = groups[ i ];
for ( var j in group.values ) {
var value_dict = group.values[ j ];
for ( var key in array ) {
value_dict[ key ] = parseInt( j )
}
}
}
};
/** Category make for unique category labels */
function makeUniqueCategories( groups, with_index ) {
var categories = {};
var array = {};
var counter = {};
var chart_definition = groups[ 0 ];
for( var key in chart_definition.columns ) {
var column_def = chart_definition.columns[ key ];
if ( column_def.is_label ) {
categories[ key ] = {};
array[ key ] = [];
counter[ key ] = 0;
}
}
// index all values contained in label columns (for all groups)
for ( var i in groups ) {
var group = groups[ i ];
for ( var j in group.values ) {
var value_dict = group.values[ j ];
for ( var key in categories ) {
var value = String( value_dict[ key ] );
if ( categories[ key ][ value ] === undefined ) {
categories[ key ][ value ] = counter[ key ];
array[ key ].push( with_index ? [counter[key], value] : value );
counter[ key ]++;
}
}
}
}
// convert group values into category indeces
for ( var i in groups ) {
var group = groups[ i ];
for ( var j in group.values ) {
var value_dict = group.values[ j ];
for ( var key in categories ) {
var value = String( value_dict[ key ] );
value_dict[ key ] = categories[ key ][ value ];
}
}
}
return {
categories : categories,
array : array,
counter : counter
}
};
/** Make axis */
function makeTickFormat ( options ) {
var type = options.type;
var precision = options.precision;
var categories = options.categories;
var formatter = options.formatter;
if ( type == 'hide' ) {
formatter( function() { return '' } );
} else if ( type == 'auto' ) {
if ( categories ) {
formatter( function( value ) { return categories[ value ] || '' } );
}
} else {
var d3format = function( d ) {
switch ( type ) {
case 's':
var prefix = d3.formatPrefix( d );
return prefix.scale( d ).toFixed() + prefix.symbol;
default :
return d3.format( '.' + precision + type )( d );
}
};
if ( categories ) {
formatter( function( value ) {
var label = categories[ value ];
if ( label ) {
if ( isNaN( label ) ) {
return label;
} else {
try {
return d3format( label );
} catch ( err ) {
return label;
}
}
} else {
return '';
}
});
} else {
formatter( function( value ) { return d3format( value ) } );
}
}
};
/** Add zoom handler */
function addZoom( options ) {
var scaleExtent = 100;
var yAxis = options.yAxis;
var xAxis = options.xAxis;
var xDomain = options.xDomain || xAxis.scale().domain;
var yDomain = options.yDomain || yAxis.scale().domain;
var redraw = options.redraw;
var svg = options.svg;
var xScale = xAxis.scale();
var yScale = yAxis.scale();
var x_boundary = xScale.domain().slice();
var y_boundary = yScale.domain().slice();
var d3zoom = d3.behavior.zoom();
xScale.nice();
yScale.nice();
function fixDomain( domain, boundary ) {
domain[ 0 ] = Math.min( Math.max( domain[ 0 ], boundary[ 0 ] ), boundary[ 1 ] - boundary[ 1 ]/scaleExtent );
domain[ 1 ] = Math.max( boundary[ 0 ] + boundary[ 1 ] / scaleExtent, Math.min( domain[ 1 ], boundary[ 1 ] ) );
return domain;
};
function zoomed() {
yDomain( fixDomain( yScale.domain(), y_boundary ) );
xDomain( fixDomain( xScale.domain(), x_boundary ) );
redraw();
};
function unzoomed() {
xDomain( x_boundary );
yDomain( y_boundary );
redraw();
d3zoom.scale( 1 );
d3zoom.translate( [ 0 , 0 ] );
};
d3zoom.x( xScale )
.y( yScale )
.scaleExtent( [ 1, scaleExtent ] )
.on( 'zoom', zoomed );
svg.call( d3zoom ).on( 'dblclick.zoom', unzoomed );
return d3zoom;
};
return {
buildRequestDictionary : buildRequestDictionary,
buildJobDictionary : buildJobDictionary,
panelHelper : panelHelper,
makeCategories : makeCategories,
makeUniqueCategories : makeUniqueCategories,
makeSeries : makeSeries,
getDomains : getDomains,
mapCategories : mapCategories,
makeTickFormat : makeTickFormat,
addZoom : addZoom
}
});
@@ -0,0 +1,102 @@
/** This class handles job submissions to the charts tool. */
define( [ 'utils/utils' ], function( Utils ) {
/** Time to wait before refreshing to check if job has completed */
var WAITTIME = 1000;
/** Submit job request to charts tool */
var request = function( app, parameters, success, error ) {
var chart = app.chart;
chart.state( 'wait', 'Requesting job results...' );
if ( chart.get( 'modified' ) ) {
cleanup( chart );
chart.set( 'modified', false );
}
var dataset_id_job = chart.get( 'dataset_id_job' );
if ( dataset_id_job != '' ) {
wait( chart, success, error );
} else {
var chart_id = chart.id;
var chart_type = chart.get( 'type' );
var chart_definition = chart.definition;
chart.state( 'wait', 'Sending job request...' );
Utils.request({
type : 'POST',
url : Galaxy.root + 'api/tools',
data : parameters,
success : function( response ) {
if ( !response.outputs || response.outputs.length == 0 ) {
chart.state( 'failed', 'Job submission failed. No response.' );
error && error();
} else {
refreshHdas();
var job = response.outputs[0];
chart.state( 'wait', 'Your job has been queued. You may close the browser window. The job will run in the background.' );
chart.set( 'dataset_id_job', job.id );
self.app.storage.save();
wait( chart, success, error );
}
},
error : function( response ) {
var message = '';
if ( response && response.message && response.message.data && response.message.data.input ) {
message = response.message.data.input + '.';
}
chart.state( 'failed', 'This visualization requires the \'' + parameters.tool_id + '\' tool. Please make sure it is installed. ' + message );
error && error();
}
});
}
};
/* Remove previous data when re-running jobs */
var cleanup = function( chart ) {
var self = this;
var previous = chart.get( 'dataset_id_job' );
if (previous != '') {
Utils.request({
type : 'PUT',
url : Galaxy.root + 'api/histories/none/contents/' + previous,
data : { deleted: true },
success : function() { refreshHdas() }
});
chart.set( 'dataset_id_job', '' );
}
};
/** Request job details */
var wait = function( chart, success, error ) {
var self = this;
Utils.request({
type : 'GET',
url : Galaxy.root + 'api/datasets/' + chart.get( 'dataset_id_job' ),
data : {},
success : function( dataset ) {
var ready = false;
switch ( dataset.state ) {
case 'ok':
chart.state( 'wait', 'Job completed successfully...' );
success && success( dataset );
ready = true;
break;
case 'error':
chart.state( 'failed', 'Job has failed. Please check the history for details.' );
error && error( dataset );
ready = true;
break;
case 'running':
chart.state( 'wait', 'Your job is running. You may close the browser window. The job will continue in the background.' );
}
!ready && setTimeout( function() { wait( chart, success, error ) }, WAITTIME );
}
});
};
/** Refresh history panel */
var refreshHdas = function() {
Galaxy && Galaxy.currHistoryPanel && Galaxy.currHistoryPanel.refreshContents();
};
return { request: request }
});
@@ -0,0 +1,39 @@
define( [ 'utils/utils' ], function( Utils ) {
return Backbone.Model.extend({
defaults : {
id : null,
title : '',
type : '',
date : null,
state : '',
state_info : '',
modified : false,
dataset_id : '',
dataset_id_job : ''
},
initialize: function( options ) {
this.groups = new Backbone.Collection();
this.settings = new Backbone.Model();
this.definition = {};
},
reset: function( options ) {
this.set({
'id' : Utils.uid(),
'type' : 'nvd3_bar',
'dataset_id' : options.config.dataset_id,
'title' : 'New Chart'
});
this.settings.clear();
this.groups.reset();
this.groups.add( { id : Utils.uid() } );
},
state: function( value, info ) {
this.set( { 'state': value, 'state_info': info } );
this.trigger( 'set:state' );
console.debug( 'Chart:state() - ' + info + ' (' + value + ')' );
}
});
});
@@ -1,10 +1,6 @@
/**
* This class saves and loads a chart through the api.
*/
define( [ 'utils/utils', 'plugin/models/chart', 'mvc/visualization/visualization-model' ],
function( Utils, Chart ) {
/** This class saves and loads a chart through the api. */
define( [ 'utils/utils', 'plugin/components/model', 'mvc/visualization/visualization-model' ], function( Utils, Chart ) {
return Backbone.Model.extend({
vis: null,
initialize: function( app ) {
this.app = app;
@@ -39,33 +35,34 @@
});
this.vis.set( 'title', chart.get( 'title' ) || '' );
this.vis.get( 'config' ).chart_dict = chart_dict;
this.vis.save().fail(function( xhr, status, message ) {
self.app.showModal( 'Saving failed.', 'An attempt to save this chart to the server failed. Please try again and contact the administrator.' );
})
.then( function( response ) {
if ( response && response.id ) {
self.id = response.id;
} else {
console.debug('Storage::save() - Unrecognized response. Saving may have failed.');
}
});
this.vis.save()
.fail(function( xhr, status, message ) {
self.app.showModal( 'Saving failed.', 'An attempt to save this chart to the server failed. Please try again and contact the administrator.' );
})
.then( function( response ) {
if ( response && response.id ) {
self.id = response.id;
} else {
console.debug( 'Storage::save() - Unrecognized response. Saving may have failed.' );
}
});
},
/** Load nested models/collections from packed dictionary */
load: function() {
var chart_dict = this.vis.get( 'config' ).chart_dict;
if ( !chart_dict.attributes ) {
console.debug('Storage::load() - Chart attributes not found. Invalid format.');
console.debug( 'Storage::load() - Chart attributes not found. Invalid format.' );
return false;
}
var chart_type = chart_dict.attributes[ 'type' ];
if ( !chart_type ) {
console.debug('Storage::load() - Chart type not provided. Invalid format.');
console.debug( 'Storage::load() - Chart type not provided. Invalid format.' );
return false;
}
var chart_definition = this.app.types.get( chart_type );
var chart_definition = this.app.types[ chart_type ];
if ( !chart_definition ) {
console.debug('Storage::load() - Chart type not supported. Please re-configure the chart. Resetting chart.');
console.debug( 'Storage::load() - Chart type not supported. Please re-configure the chart.' );
return false;
}
this.chart.definition = chart_definition;
@@ -75,7 +72,7 @@
this.chart.groups.reset();
this.chart.groups.add( chart_dict.groups );
this.chart.set( 'modified', false );
console.debug('Storage::load() - Loading chart type ' + chart_type + '.');
console.debug( 'Storage::load() - Loading chart type ' + chart_type + '.' );
return true;
}
});
@@ -1,378 +0,0 @@
/**
* This class handles, formats and caches datasets.
*/
define( [ 'utils/utils' ], function( Utils ) {
return Backbone.Collection.extend({
// list of datasets
list: {},
// cache for datablocks
cache: {},
// initialize
initialize: function(app, options){
this.app = app;
this.options = Utils.merge(options, this.optionsDefault);
},
// request handler
request: function(request_dictionary) {
if (request_dictionary.groups) {
this._get_blocks(request_dictionary);
} else {
this._get_dataset(request_dictionary.id, request_dictionary.success, request_dictionary.error)
}
},
// multiple request handler
_get_blocks: function(request_dictionary) {
// get callbacks
var success = request_dictionary.success;
var progress = request_dictionary.progress;
// query block size
var query_size = this.app.config.get('query_limit');
// set range
var query_start = request_dictionary.start || 0;
var query_end = query_start + request_dictionary.query_limit || query_start + this.app.config.get('query_limit');
// get query limit
var query_range = Math.abs(query_end - query_start);
if (query_range <= 0) {
console.debug('FAILED - Datasets::request() - Invalid query range.');
return;
}
// get number of required queries
var query_number = Math.ceil(query_range / query_size) || 1;
// get query dictionary template
var query_dictionary_template = $.extend(true, {}, request_dictionary);
// reset query counter
var query_counter = 0;
// fetch blocks
var self = this;
function fetch_blocks (query) {
self._get(query, function() {
// copy values from query into request_dictionary
var done = false;
for (var group_index in request_dictionary.groups) {
// get source/destination
destination_group = request_dictionary.groups[group_index];
source_group = query.groups[group_index];
// check if value fields already exist
if (!destination_group.values) {
destination_group.values = [];
}
// concat values
destination_group.values = destination_group.values.concat(source_group.values);
// validate
if (source_group.values.length == 0) {
done = true;
break;
}
}
// check if for remaining queries
if (++query_counter < query_number && !done) {
// report progress
if (progress) {
progress(parseInt((query_counter / query_number) * 100));
}
// next query
var start = query.start + query_size;
query = $.extend(true, query_dictionary_template, {start: start});
fetch_blocks(query);
} else {
success();
}
});
};
// prepare query
var query = $.extend(true, query_dictionary_template, {start: query_start});
// get dataset meta data
this._get_dataset(request_dictionary.id, function() {
fetch_blocks(query);
});
},
// get dataset
_get_dataset: function(id, success, error) {
// check if dataset is available from cache
var dataset = this.list[id];
if (dataset) {
success(dataset);
return;
}
// request dataset
var self = this;
Utils.request({
type : 'GET',
url : config.root + 'api/datasets/' + id,
success : function(dataset) {
switch (dataset.state) {
case 'error':
if (error) {
error(dataset);
}
break;
default:
self.list[id] = dataset;
success(dataset);
}
}
});
},
// get block id
_block_id: function (options, column) {
return options.id + '_' + options.start + '_' + options.start + this.app.config.get('query_limit') + '_' + column;
},
// fills request dictionary with data from cache/response
_get: function(request_dictionary, callback) {
// set start
request_dictionary.start = request_dictionary.start || 0;
// get column indices
var column_list = [];
var column_map = {};
var column_count = 0;
for (var i in request_dictionary.groups) {
var group = request_dictionary.groups[i];
for (var key in group.columns) {
// identify column
var column = group.columns[key].index;
// check if column is in cache
var block_id = this._block_id(request_dictionary, column);
if (this.cache[block_id] || column === 'auto' || column === 'zero') {
continue;
}
// add to dictionary
if (!column_map[column] && column !== undefined) {
column_map[column] = column_count;
column_list.push(column);
column_count++;
}
}
}
// check length of blocks not available in cache
if (column_list.length == 0) {
// fill dictionary from cache
this._fill_from_cache(request_dictionary);
// parse requested data
callback(request_dictionary);
// return
return;
}
// configure dataset request dictionary
var dataset_request = {
dataset_id : request_dictionary.id,
start : request_dictionary.start,
columns : column_list
}
// fetch data
var self = this;
this._fetch(dataset_request, function(results) {
// add results to cache
for (var i in results) {
var column = column_list[i];
var block_id = self._block_id(request_dictionary, column);
self.cache[block_id] = results[i];
}
// fill dictionary from cache
self._fill_from_cache(request_dictionary);
// trigger callback
callback(request_dictionary);
});
},
// convert
_fill_from_cache: function(request_dictionary) {
// identify start of request
var start = request_dictionary.start;
// log
console.debug('Datasets::_fill_from_cache() - Filling request from cache at ' + start + '.');
// identify end of request
var limit = 0;
for (var i in request_dictionary.groups) {
var group = request_dictionary.groups[i];
for (var key in group.columns) {
var column = group.columns[key];
var block_id = this._block_id(request_dictionary, column.index);
var column_data = this.cache[block_id];
if (column_data) {
limit = Math.max(limit, column_data.length);
}
}
}
// check length
if (limit == 0) {
console.debug('Datasets::_fill_from_cache() - Reached data range limit.');
}
// initialize group values
for (var i in request_dictionary.groups) {
// get group
var group = request_dictionary.groups[i];
// reset group
group.values = [];
// add values
for (var j = 0; j < limit; j++) {
// add default x values
group.values[j] = {
x : parseInt(j) + start
};
}
}
// collect all data into the defined groups
for (var i in request_dictionary.groups) {
// get group
var group = request_dictionary.groups[i];
// fill value
for (var key in group.columns) {
// get column
var column = group.columns[key];
// check if auto block is requested
switch (column.index) {
case 'auto':
for (var j = 0; j < limit; j++) {
// get value dictionary
var value = group.values[j];
// add auto value
value[key] = parseInt(j) + start;
}
break;
case 'zero':
for (var j = 0; j < limit; j++) {
// get value dictionary
var value = group.values[j];
// add zero value
value[key] = 0;
}
break;
default:
// get block
var block_id = this._block_id(request_dictionary, column.index);
var column_data = this.cache[block_id];
// go through column
for (var j = 0; j < limit; j++) {
// get value dictionary
var value = group.values[j];
// get/fix value
var v = column_data[j];
if (isNaN(v) && !column.is_label && !column.is_text) {
v = 0;
}
// add to dict
value[key] = v;
}
}
}
}
},
// fetch data columns into dataset object
_fetch: function(dataset_request, callback) {
// set offset
var offset = dataset_request.start ? dataset_request.start : 0;
// set limit
var limit = this.app.config.get('query_limit');
// check length
var n_columns = 0;
if (dataset_request.columns) {
n_columns = dataset_request.columns.length;
console.debug('Datasets::_fetch() - Fetching ' + n_columns + ' column(s) at ' + offset + '.');
}
if (n_columns == 0) {
console.debug('Datasets::_fetch() - No columns requested');
}
// get column indices
var column_string = '';
for (var i in dataset_request.columns) {
column_string += dataset_request.columns[i] + ',';
}
column_string = column_string.substring(0, column_string.length - 1);
// make request
var self = this;
Utils.request({
type : 'GET',
url : config.root + 'api/datasets/' + dataset_request.dataset_id,
data : {
data_type : 'raw_data',
provider : 'dataset-column',
limit : limit,
offset : offset,
indeces : column_string
},
success : function(response) {
// initialize result dictionary
var result = new Array(n_columns);
for (var i = 0; i < n_columns; i++) {
result[i] = [];
}
// loop through rows
for (var i in response.data) {
// get row
var row = response.data[i];
// collect all data into the defined groups
for (var j in row) {
// get group
var v = row[j];
if (v !== undefined && v != 2147483647) {
// add to result
result[j].push(v);
}
}
}
// log
console.debug('Datasets::_fetch() - Fetching complete.');
// callback
callback(result);
}
});
}
});
});
@@ -1,153 +0,0 @@
/**
* This class handles job submissions to the charts tool.
*/
define( [ 'utils/utils' ], function( Utils ) {
return Backbone.Model.extend({
initialize: function( app, options ) {
this.app = app;
this.options = Utils.merge( options, this.optionsDefault );
},
/* Request job results */
request: function( chart, settings_string, columns_string, success, error ) {
var self = this;
chart.state( 'wait', 'Requesting job results...' );
var dataset_id_job = chart.get( 'dataset_id_job' );
if (dataset_id_job != '') {
self._wait( chart, success, error );
} else {
self._submit( chart, settings_string, columns_string, success, error );
}
},
/* Remove previous data when re-running jobs */
cleanup: function( chart ) {
var self = this;
var previous = chart.get( 'dataset_id_job' );
if (previous != '') {
Utils.request({
type : 'PUT',
url : config.root + 'api/histories/none/contents/' + previous,
data : { deleted: true },
success : function() {
self._refreshHdas();
}
});
chart.set( 'dataset_id_job', '' );
}
},
// create job
_submit: function(chart, settings_string, columns_string, success, error) {
// link this
var self = this;
// backup chart details
var chart_id = chart.id;
var chart_type = chart.get('type');
// get chart settings
var chart_definition = chart.definition;
// configure tool
data = {
'tool_id' : 'charts',
'inputs' : {
'input' : {
'id' : chart.get('dataset_id'),
'src' : 'hda'
},
'module' : chart_definition.execute,
'columns' : columns_string,
'settings' : settings_string
}
}
// set chart state
chart.state('wait', 'Sending job request...');
// post job
Utils.request({
type : 'POST',
url : config.root + 'api/tools',
data : data,
success : function(response) {
if (!response.outputs || response.outputs.length == 0) {
chart.state('failed', 'Job submission failed. No response.');
// call error
error && error();
} else {
// update galaxy history
self._refreshHdas();
// get dataset
var job = response.outputs[0];
// check dataset
chart.state('wait', 'Your job has been queued. You may close the browser window. The job will run in the background.');
// backup resulting dataset id
chart.set('dataset_id_job', job.id);
// save
self.app.storage.save();
// wait for job completion
self._wait(chart, success, error);
}
},
error : function(response) {
var message = '';
if (response && response.message && response.message.data && response.message.data.input) {
message = response.message.data.input + '.';
}
// update state
chart.state('failed', 'This visualization requires the \'charts\' tool. Please make sure it is installed. ' + message);
// call error
error && error();
}
});
},
/** Request job details */
_wait: function( chart, success, error ) {
var self = this;
Utils.request({
type : 'GET',
url : config.root + 'api/datasets/' + chart.get( 'dataset_id_job' ),
data : {},
success : function( dataset ) {
var ready = false;
switch ( dataset.state ) {
case 'ok':
chart.state( 'wait', 'Job completed successfully...' );
success && success( dataset );
ready = true;
break;
case 'error':
chart.state( 'failed', 'Job has failed. Please check the history for details.' );
error && error( dataset );
ready = true;
break;
case 'running':
chart.state( 'wait', 'Your job is running. You may close the browser window. The job will continue in the background.' );
}
if ( !ready ) {
setTimeout( function() {
self._wait( chart, success, error );
}, self.app.config.get( 'query_timeout' ) );
}
}
});
},
/** Refresh history panel */
_refreshHdas: function() {
Galaxy && Galaxy.currHistoryPanel && Galaxy.currHistoryPanel.refreshContents();
}
});
});
@@ -1,58 +0,0 @@
define( [], function() {
var Groups = Backbone.Collection.extend({
model: Backbone.Model.extend({
defaults : {
key : 'Data label',
date : ''
},
reset: function(){
this.clear( { silent: true } ).set( this.defaults );
this.trigger( 'reset', this );
}
})
});
return Backbone.Model.extend({
defaults : {
id : null,
title : '',
type : '',
date : null,
state : '',
state_info : '',
modified : false,
dataset_id : '',
dataset_id_job : ''
},
initialize: function( options ) {
this.groups = new Groups();
this.settings = new Backbone.Model();
},
reset: function() {
this.clear( { silent: true } ).set( this.defaults );
this.groups.reset();
this.settings.clear();
this.trigger( 'reset', this );
},
copy: function( new_chart ) {
var current = this;
current.clear( { silent: true } ).set( this.defaults );
current.set( new_chart.attributes );
current.settings = new_chart.settings.clone();
current.groups.reset();
new_chart.groups.each( function( group ) {
current.groups.add( group.clone() );
});
current.trigger( 'change', current );
},
state: function( value, info ) {
this.set( { 'state': value, 'state_info': info } );
this.trigger( 'set:state' );
console.debug( 'Chart:state() - ' + info + ' (' + value + ')' );
}
});
});
@@ -1,8 +0,0 @@
define( [], function() {
return Backbone.Model.extend({
defaults : {
query_limit : 1000,
query_timeout : 100
}
});
});
@@ -0,0 +1,36 @@
/** This class renders the chart configuration form. */
define( [], function() {
return Backbone.View.extend({
initialize: function( app, options ) {
var self = this;
this.chart = app.chart;
this.app = app;
this.setElement( this._template() );
this.$title = this.$( '.charts-description-title' );
this.$image = this.$( '.charts-description-image' );
this.$text = this.$( '.charts-description-text' );
this.listenTo( this.chart, 'change', function() { self.render() } );
this.render();
},
render: function() {
this.$image.attr( 'src', app_root + 'charts/' + this.app.split( this.chart.get( 'type' ) ) + '/logo.png' );
this.$title.html( this.chart.definition.title + ' (' + this.chart.definition.library + ')' );
this.$text.html( this.chart.definition.description || this.chart.definition.category );
},
_template: function() {
return '<div class="charts-description">' +
'<table>' +
'<tr>' +
'<td class="charts-description-image-td">' +
'<img class="charts-description-image"/>' +
'</td>' +
'<td>' +
'<div class="charts-description-title ui-form-info"/>' +
'<div class="charts-description-text ui-form-info"/>' +
'</td>' +
'</tr>' +
'</table>' +
'</div>';
}
});
});
@@ -2,9 +2,8 @@
* The charts editor holds the tabs for selecting chart types, chart configuration
* and data group selections.
*/
define( [ 'mvc/ui/ui-tabs', 'mvc/ui/ui-misc', 'mvc/ui/ui-portlet', 'utils/utils',
'plugin/models/chart', 'plugin/views/settings', 'plugin/views/groups', 'plugin/views/types' ],
function( Tabs, Ui, Portlet, Utils, Chart, SettingsView, GroupsView, TypesView ) {
define( [ 'mvc/ui/ui-tabs', 'mvc/ui/ui-misc', 'mvc/ui/ui-portlet', 'utils/utils', 'plugin/views/settings', 'plugin/views/groups', 'plugin/views/types' ],
function( Tabs, Ui, Portlet, Utils, SettingsView, GroupsView, TypesView ) {
return Backbone.View.extend({
initialize: function( app, options ){
var self = this;
@@ -36,14 +35,11 @@ define( [ 'mvc/ui/ui-tabs', 'mvc/ui/ui-misc', 'mvc/ui/ui-portlet', 'utils/utils'
});
// grid with chart types
this.types = new TypesView(app, {
onchange : function(chart_type) {
var chart_definition = self.app.types.get( chart_type );
if ( !chart_definition ) {
console.debug('FAILED - Editor::onchange() - Chart type not supported.');
}
this.types = new TypesView( app, {
onchange : function( chart_type ) {
var chart_definition = self.app.types[ chart_type ];
!chart_definition && console.debug( 'FAILED - Editor::onchange() - Chart type not supported.' );
self.chart.definition = chart_definition;
self.chart.settings.clear();
self.chart.set( { type : chart_type, modified : true } );
console.debug( 'Editor::onchange() - Switched chart type.' );
},
@@ -69,8 +65,9 @@ define( [ 'mvc/ui/ui-tabs', 'mvc/ui/ui-misc', 'mvc/ui/ui-portlet', 'utils/utils'
tooltip : 'Start by selecting a chart type.',
$el : $( '<div/>' ).append( ( new Ui.Label( { title : 'Provide a chart title:' } ).$el ) )
.append( this.title.$el )
.append( $( '<div/>' ).addClass( 'ui-form-info' ).html( 'This title will appear in the list of \'Saved Visualizations\'. Charts are saved upon creation.' ) )
.append( this.types.$el.addClass( 'ui-margin-top' ) )
.append( $( '<div/>' ).addClass( 'ui-form-info ui-margin-bottom' ).html( 'This title will appear in the list of \'Saved Visualizations\'. Charts are saved upon creation.' ) )
.append( ( new Ui.Label( { title : 'Select a chart type:' } ).$el.addClass( 'ui-margin-top' ) ) )
.append( this.types.$el )
});
this.tabs.add({
id : 'settings',
@@ -83,22 +80,22 @@ define( [ 'mvc/ui/ui-tabs', 'mvc/ui/ui-misc', 'mvc/ui/ui-portlet', 'utils/utils'
id : 'groups',
title : 'Select data',
icon : 'fa-database',
tooltip : 'Specify your data columns.',
tooltip : 'Specify your data options.',
$el : ( new GroupsView( this.app ) ).$el
});
// set elements
this.portlet.append( this.message.$el );
this.portlet.append( this.tabs.$el.addClass( 'ui-margin-top-large' ) );
this.portlet.hideOperation( 'back' );
this.setElement( this.portlet.$el );
this.tabs.hideOperation( 'back' );
// chart events
this.chart.on( 'change:title', function( chart ) { self._refreshTitle() } );
this.chart.on( 'change:type', function( chart ) { self.types.value( chart.get( 'type' ) ) } );
this.chart.on( 'reset', function( chart ) { self._resetChart() } );
this.app.chart.on( 'redraw', function( chart ) { self.portlet.showOperation( 'back' ) } );
this._resetChart();
this.chart.on( 'redraw', function( chart ) { self.portlet.showOperation( 'back' ) } );
this.chart.reset( this.app.options );
},
/** Show editor */
@@ -118,19 +115,6 @@ define( [ 'mvc/ui/ui-tabs', 'mvc/ui/ui-misc', 'mvc/ui/ui-portlet', 'utils/utils'
this.title.value( title );
},
/** Reset entire chart */
_resetChart: function() {
this.chart.set({
'id' : Utils.uid(),
'type' : 'nvd3_bar',
'dataset_id' : this.app.options.config.dataset_id,
'title' : 'New Chart'
});
this.chart.groups.reset();
this.chart.groups.add( { id : Utils.uid() } );
this.portlet.hideOperation( 'back' );
},
/** Save chart data */
_saveChart: function() {
var self = this;
@@ -140,7 +124,7 @@ define( [ 'mvc/ui/ui-tabs', 'mvc/ui/ui-misc', 'mvc/ui/ui-portlet', 'utils/utils'
date : Utils.time()
});
if ( this.chart.groups.length == 0 ) {
this.message.update( { message: 'Please specify data columns before drawing the chart.' } );
this.message.update( { message: 'Please specify data options before drawing the chart.' } );
this.tabs.show( 'groups' );
return;
}
@@ -148,13 +132,13 @@ define( [ 'mvc/ui/ui-tabs', 'mvc/ui/ui-misc', 'mvc/ui/ui-portlet', 'utils/utils'
var chart_def = this.chart.definition;
this.chart.groups.each( function( group ) {
if ( valid ) {
for ( var key in chart_def.columns ) {
if ( group.attributes[ key ] === null ) {
_.each( group.get( '__data_columns' ), function( data_columns, name ) {
if ( group.attributes[ name ] === null ) {
self.message.update( { status: 'danger', message: 'This chart type requires column types not found in your tabular file.' } );
self.tabs.show( 'groups' );
valid = false;
}
}
});
}
});
if ( valid ) {
@@ -1,62 +1,59 @@
/**
* This class renders the chart configuration form.
*/
define( [ 'mvc/ui/ui-table', 'mvc/ui/ui-misc', 'mvc/form/form-view', 'mvc/form/form-repeat', 'utils/utils' ], function( Table, Ui, Form, Repeat, Utils ) {
/** This class renders the chart configuration form. */
define( [ 'utils/utils', 'mvc/ui/ui-misc', 'mvc/form/form-view', 'mvc/form/form-repeat', 'mvc/form/form-data', 'plugin/views/description' ],
function( Utils, Ui, Form, Repeat, FormData, Description ) {
var GroupView = Backbone.View.extend({
initialize: function( app, options ) {
var self = this;
this.app = app;
this.chart = app.chart;
this.group = options.group;
this.app = app;
this.chart = app.chart;
this.group = options.group;
this.setElement( $( '<div/>' ) );
this.chart.on( 'change:dataset_id change:type', function() { self.render() } );
this.group.on( 'change', function() { self.form && self.form.data.set( self.group ) } );
this.listenTo( this.chart, 'change:dataset_id change:type', function() { self.render() } );
this.render();
},
render: function() {
var self = this;
var inputs = this.chart.definition.series && this.chart.definition.series.slice() || [];
_.each( this.chart.definition.columns, function( column, name ) {
inputs.push( { name: name, label: column.title, type: 'select' } );
});
this.form = new Form( {
inputs : inputs,
cls : 'ui-portlet-plain'
} );
this.$el.empty().append( this.form.$el );
var inputs = this.chart.definition.groups ? Utils.clone( this.chart.definition.groups ) : [];
var dataset_id = this.chart.get( 'dataset_id' );
var chart_type = this.chart.get( 'type' );
var chart_definition = this.chart.definition;
if ( dataset_id && chart_type ) {
this.chart.state( 'wait', 'Loading metadata...' );
this.app.deferred.execute( function( process ) {
self.app.datasets.request({
id : dataset_id,
Utils.get({
url : Galaxy.root + 'api/datasets/' + dataset_id,
cache : true,
success : function( dataset ) {
for ( var id in chart_definition.columns ) {
var index = self.form.data.match( id );
if ( index ) {
var data_columns = {};
FormData.visitInputs( inputs, function( input, prefixed ) {
if ( input.type == 'data_column' ) {
data_columns[ prefixed ] = Utils.clone( input );
var columns = [];
var select = self.form.field_list[ index ];
var input_def = chart_definition.columns[ id ];
input_def.is_auto && columns.push( { 'label': 'Column: Row Number', 'value': 'auto' } );
input_def.is_zero && columns.push( { 'label' : 'Column: None', 'value' : 'zero' } );
input.is_auto && columns.push( { 'label': 'Column: Row Number', 'value': 'auto' } );
input.is_zero && columns.push( { 'label' : 'Column: None', 'value' : 'zero' } );
var meta = dataset.metadata_column_types;
for ( var key in meta ) {
var valid = ( [ 'int', 'float' ].indexOf( meta[ key ] ) != -1 && input_def.is_numeric ) || input_def.is_text || input_def.is_label;
var valid = ( [ 'int', 'float' ].indexOf( meta[ key ] ) != -1 && input.is_numeric ) || input.is_text || input.is_label;
valid && columns.push( { 'label' : 'Column: ' + ( parseInt( key ) + 1 ), 'value' : key } );
}
select.update( columns );
self.group.set( id, select.value( self.group.get( id ) ) );
input.data = columns;
}
}
self.chart.state( 'ok', 'Metadata initialized...' );
self.form.data.set( self.group );
self.form.setOnChange( function() {
self.group.set( self.form.data.create() );
self.chart.set( 'modified', true );
var model_value = self.group.get( prefixed );
model_value !== undefined && !input.hidden && ( input.value = model_value );
});
inputs[ '__data_columns' ] = { name: '__data_columns', type: 'hidden', hidden: true, value: data_columns };
self.chart.state( 'ok', 'Metadata initialized...' );
self.form = new Form( {
inputs : inputs,
cls : 'ui-portlet-plain',
onchange: function() {
self.group.set( self.form.data.create() );
self.chart.set( 'modified', true );
}
} );
self.group.set( self.form.data.create() );
self.$el.empty().append( self.form.$el );
process.resolve();
}
});
@@ -67,24 +64,42 @@ define( [ 'mvc/ui/ui-table', 'mvc/ui/ui-misc', 'mvc/form/form-view', 'mvc/form/f
return Backbone.View.extend({
initialize: function( app ) {
var repeat = new Repeat.View({
var self = this;
this.app = app;
this.chart = app.chart;
this.repeat = new Repeat.View({
title : 'Data series',
title_new : 'Data series',
min : 1,
onnew : function() { app.chart.groups.add( { id : Utils.uid() } ) }
onnew : function() { self.chart.groups.add( { id : Utils.uid() } ) }
});
this.setElement( repeat.$el );
app.chart.groups.on( 'add remove reset', function() { app.chart.set( 'modified', true ) } )
.on( 'remove', function( group ) { repeat.del( group.id ) } )
.on( 'reset', function() { repeat.delAll() } )
.on( 'add', function( group ) {
repeat.add({
id : group.id,
cls : 'ui-portlet-panel',
$el : ( new GroupView( app, { group: group } ) ).$el,
ondel : function() { app.chart.groups.remove( group ) }
});
});
this.description = new Description( this.app );
this.message = new Ui.Message( { message : 'There are no options for this chart type.', persistent : true, status : 'info' } );
this.setElement( $( '<div/>' ).append( this.description.$el )
.append( this.repeat.$el.addClass( 'ui-margin-bottom' ) )
.append( this.message.$el.addClass( 'ui-margin-bottom' ) ) );
this.listenTo( this.chart, 'change', function() { self.render() } );
this.listenTo( this.chart.groups, 'add remove reset', function() { self.chart.set( 'modified', true ) } );
this.listenTo( this.chart.groups, 'remove', function( group ) { self.repeat.del( group.id ) } );
this.listenTo( this.chart.groups, 'reset', function() { self.repeat.delAll() } );
this.listenTo( this.chart.groups, 'add', function( group ) {
self.repeat.add({
id : group.id,
cls : 'ui-portlet-panel',
$el : ( new GroupView( self.app, { group: group } ) ).$el,
ondel : function() { self.chart.groups.remove( group ) }
});
});
},
render: function() {
if ( _.size( this.chart.definition.groups ) > 0 ) {
this.repeat.$el.show();
this.message.$el.hide();
} else {
this.repeat.$el.hide();
this.message.$el.show();
}
}
});
});
@@ -1,76 +1,35 @@
/**
* This class renders the chart configuration form.
*/
define( [ 'mvc/ui/ui-table', 'mvc/ui/ui-misc', 'mvc/form/form-parameters', 'utils/utils' ], function( Table, Ui, Parameters, Utils ) {
/** This class renders the chart configuration form. */
define( [ 'utils/utils', 'mvc/ui/ui-misc', 'mvc/form/form-view', 'mvc/form/form-data', 'plugin/views/description' ], function( Utils, Ui, Form, FormData, Description ) {
return Backbone.View.extend({
initialize: function( app, options ) {
var self = this;
this.app = app;
this.chart = this.app.chart;
this.list = [];
this.parameters = new Parameters();
this.table_title = new Ui.Label({});
this.table = new Table.View( { content: 'This chart type does not provide any options.' } );
this.setElement( $( '<div/>' ).addClass( 'ui-form' )
.append( this.table_title.$el )
.append( this.table.$el ) );
this.chart.on( 'change', function() { self.render() } );
this.chart = app.chart;
this.description = new Description( this.app );
this.message = new Ui.Message( { message: 'There are no options for this chart type.', persistent: true, status: 'info' } );
this.setElement( $( '<div/>' ).append( this.description.$el ).append( this.message.$el ).append( this.$form = $( '<div/>' ) ) );
this.listenTo( this.chart, 'change', function() { self.render() } );
},
render: function() {
var chart_definition = this.chart.definition;
if ( chart_definition ) {
this.table_title.title( chart_definition.category + ' - ' + chart_definition.title + ':' );
this.table.delAll();
this.list = [];
var settings = chart_definition.settings;
for ( var id in settings ) {
this._add( settings[ id ].id || id, settings[ id ], this.chart.settings );
}
for ( var id in this.list ) {
this.list[ id ].trigger('change');
}
}
},
/** Add table row */
_add: function( name, settings_def, model ) {
var self = this;
if ( settings_def.type !== 'separator' ) {
switch( settings_def.type ) {
case 'select':
settings_def.onchange = function( new_value ) {
model.set( name, new_value );
var dict = _.findWhere( settings_def.data, { value: new_value } );
if ( dict && dict.operations ) {
var operations = dict.operations;
for ( var i in operations.show ) {
self.table.get( operations.show[ i ] ).fadeIn( 'fast' );
}
for ( var i in operations.hide ) {
self.table.get( operations.hide[ i ] ).hide();
}
}
};
break;
default:
settings_def.onchange = function( new_value ) { model.set( name, new_value ) };
}
settings_def.id = name;
settings_def.value = model.get( name ) || settings_def.init;
model.set( name, settings_def.value );
var field = this.parameters.create( settings_def );
var $input = $( '<div/>' ).append( field.$el );
settings_def.info && $input.append( $( '<div/>' ).addClass( 'ui-form-info' ).append( settings_def.info ) );
this.table.add( $( '<span/>' ).addClass( 'ui-form-title' ).append( settings_def.title ), '20%' );
this.table.add( $input );
this.list[ name ] = field;
var inputs = Utils.clone( this.chart.definition.settings );
if ( _.size( inputs ) > 0 ) {
FormData.visitInputs( inputs, function( input, name ) {
var model_value = self.chart.settings.get( name );
model_value !== undefined && !input.hidden && ( input.value = model_value );
});
this.form = new Form({
inputs : inputs,
cls : 'ui-portlet-plain',
onchange : function() { self.chart.settings.set( self.form.data.create() ); }
});
this.chart.settings.set( this.form.data.create() );
this.$form.empty().append( this.form.$el );
this.message.$el.hide();
} else {
this.table.add( $( '<div/>' ).addClass( 'ui-form-separator' ).append( settings_def.title + ':' ) );
this.table.add( $( '<div/>' ) );
this.$form.empty();
this.message.$el.show();
}
this.table.append( name );
settings_def.hide && this.table.get( name ).hide();
}
});
});
@@ -1,44 +1,63 @@
/**
* This class renders the chart type selection grid.
*/
define( [ 'utils/utils', 'mvc/ui/ui-misc' ], function( Utils, Ui ) {
/** This class renders the chart type selection grid. */
define( [ 'utils/utils', 'mvc/ui/ui-misc', 'mvc/ui/ui-tabs', 'plugin/charts/overview' ], function( Utils, Ui, Tabs, Overview ) {
return Backbone.View.extend({
optionsDefault: {
onchange : null,
ondblclick : null
},
events : {
'click' : '_onclick',
'dblclick' : '_ondblclick'
'click .item' : '_onclick',
'dblclick .item' : '_ondblclick'
},
initialize : function( app, options ) {
var self = this;
this.app = app;
this.options = Utils.merge( options, this.optionsDefault );
this.library = new Ui.RadioButton.View({
data : [ { label: 'Few (<500)', value: 'small' },
{ label: 'Some (<10k)', value: 'medium' },
{ label: 'Many (>10k)', value: 'large' }],
onchange: function( value ) { self._filter( value ) }
this.tabs = new Tabs.View( {} );
this.setElement( this.tabs.$el.addClass( 'charts-types' ) );
this.render();
},
render: function() {
var self = this;
this.index = {};
_.each( this.app.types, function( type, type_id ) {
_.each( type.keywords.split( ' ' ), function( keyword ) {
self.index[ keyword ] = self.index[ keyword ] || {};
self.index[ keyword ][ type.category ] = self.index[ keyword ][ type.category ] || {};
self.index[ keyword ][ type.category ][ type_id ] = type;
});
});
this.tabs.delAll();
_.each( Overview, function( d, i ) {
var keyword = d.value;
var categories = self.index[ keyword ];
var $help = $( '<p/>' ).addClass( 'ui-form-info' ).html( d.help ) ;
var $el = $( '<div/>' ).addClass( 'charts-grid' ).append( $help );
_.each( categories, function( category, category_header ) {
var $category = self._templateHeader( { title: category_header } );
$el.append( $category );
_.each( category, function( type, type_id ) {
$el.append( self._templateType({
id : type_id,
title : ( type.zoomable ? '<span class="fa fa-search-plus"/>' : '' ) + type.title + ' (' + type.library + ')',
url : app_root + 'charts/' + self.app.split( type_id ) + '/logo.png'
}));
});
});
self.tabs.add({
id : Utils.uid(),
title : d.label,
$el : $el
});
});
this.setElement( $( '<div/>' ).addClass( 'charts-grid' )
.append( ( new Ui.Label( { title : 'How many data points would you like to analyze?' } ) ).$el )
.append( this.library.$el.addClass( 'ui-margin-bottom' ) ) );
this._render();
this.library.value( 'small' );
this.library.trigger( 'change' );
},
/** Set/Get selected chart type */
value: function( new_value ) {
var before = this.$el.find( '.current' ).attr( 'id' );
var before = this.$( '.current' ).attr( 'chart_id' );
if ( new_value !== undefined ) {
this.$el.find( '.current' ).removeClass( 'current' );
this.$el.find( '#' + new_value ).addClass( 'current' );
this.$( '.current' ).removeClass( 'current' );
this.$( '[chart_id="' + new_value + '"]' ).addClass( 'current' );
}
var after = this.$el.find( '.current' ).attr( 'id' );
var after = this.$( '.current' ).attr( 'chart_id' );
if( after !== undefined ) {
if ( after != before && this.options.onchange ) {
this.options.onchange( new_value );
@@ -47,91 +66,26 @@ define( [ 'utils/utils', 'mvc/ui/ui-misc' ], function( Utils, Ui ) {
}
},
/** Filter chart types */
_filter: function( value ) {
this.$el.find( '.header' ).hide();
var types = this.app.types.attributes;
for ( var id in types ) {
var type = types[ id ];
var $el = this.$el.find( '#' + id );
var $header = this.$el.find( '#types-header-' + this.categories_index[ type.category ] );
var keywords = type.keywords || '';
if ( keywords.indexOf( value ) >= 0 ) {
$el.show();
$header.show();
} else {
$el.hide();
}
}
},
/** Render chart type view */
_render: function() {
var category_index = 0;
this.categories = {};
this.categories_index = {};
var types = this.app.types.attributes;
for ( var id in types ) {
var type = types[ id ];
var category = type.category;
if ( !this.categories[ category ] ) {
this.categories[ category ] = {};
this.categories_index[ category ] = category_index++;
}
this.categories[ category ][ id ] = type;
}
// add categories and charts to screen
for (var category in this.categories) {
var $el = $( '<div style="clear: both;"/>' ).append( this._template_header({
id : 'types-header-' + this.categories_index[ category ],
title : category
}));
for ( var id in this.categories[ category ] ) {
var type = this.categories[ category ][ id ];
var title = type.title + ' (' + type.library + ')';
if ( type.zoomable ) {
title = '<span class="fa fa-search-plus"/>' + title;
}
$el.append( this._template_item({
id : id,
title : title,
url : config.app_root + 'charts/' + this.app.chartPath( id ) + '/logo.png'
}));
}
this.$el.append( $el );
}
},
/** Add click handler */
_onclick: function( e ) {
var old_value = this.value();
var new_value = $( e.target ).closest( '.item' ).attr( 'id' );
if ( new_value != '' ) {
if ( new_value && old_value != new_value ) {
this.value( new_value );
}
}
this.value( $( e.target ).closest( '.item' ).attr( 'chart_id' ) );
},
/** Add double click handler */
_ondblclick: function( e ) {
var value = this.value();
if ( value && this.options.ondblclick ) {
this.options.ondblclick( value );
}
this.options.ondblclick && this.options.ondblclick( this.value() );
},
// header template
_template_header: function( options ) {
return '<div id="' + options.id + '" class="header">' +
/** Header template */
_templateHeader: function( options ) {
return '<div class="header ui-margin-top">' +
'&bull; ' + options.title +
'<div>';
},
// item template
_template_item: function( options ) {
return '<div id="' + options.id + '" class="item">' +
/* Chart type template with image */
_templateType: function( options ) {
return '<div class="item" chart_id="' + options.id + '">' +
'<img class="image" src="' + options.url + '">' +
'<div class="title">' + options.title + '</div>' +
'<div>';
@@ -1,15 +1,12 @@
/**
* This class renders the chart viewer which encapsulates the chart viewport.
*/
define( [ 'utils/utils', 'mvc/ui/ui-misc', 'mvc/ui/ui-portlet',
'plugin/views/viewport', 'plugin/library/screenshot' ],
function( Utils, Ui, Portlet, ViewportView, Screenshot ) {
/** This class renders the chart viewer which encapsulates the chart viewport. */
define( [ 'utils/utils', 'mvc/ui/ui-misc', 'mvc/ui/ui-portlet', 'plugin/views/viewport', 'plugin/components/screenshot' ],
function( Utils, Ui, Portlet, Viewport, Screenshot ) {
return Backbone.View.extend({
initialize: function(app, options){
var self = this;
this.app = app;
this.chart = this.app.chart;
this.viewport_view = new ViewportView( app );
this.viewport = new Viewport( app );
this.message = new Ui.Message();
// button menu
@@ -27,7 +24,7 @@ define( [ 'utils/utils', 'mvc/ui/ui-misc', 'mvc/ui/ui-portlet',
onclick : function() {
self._wait( self.chart, function() {
Screenshot.createPNG({
$el : self.viewport_view.$el,
$el : self.viewport.$el,
title : self.chart.get( 'title' ),
error : function( err ) {
self.message.update( { message: err, status: 'danger' } );
@@ -45,7 +42,7 @@ define( [ 'utils/utils', 'mvc/ui/ui-misc', 'mvc/ui/ui-portlet',
onclick : function() {
self._wait( self.chart, function() {
Screenshot.createSVG({
$el : self.viewport_view.$el,
$el : self.viewport.$el,
title : self.chart.get( 'title' ),
error : function( err ) {
self.message.update( { message: err, status: 'danger' } );
@@ -70,7 +67,7 @@ define( [ 'utils/utils', 'mvc/ui/ui-misc', 'mvc/ui/ui-portlet',
self.app.modal.hide();
self._wait( self.chart, function() {
Screenshot.createPDF({
$el : self.viewport_view.$el,
$el : self.viewport.$el,
title : self.chart.get( 'title' ),
error : function( err ) {
self.message.update( { message: err, status: 'danger' } );
@@ -87,6 +84,7 @@ define( [ 'utils/utils', 'mvc/ui/ui-misc', 'mvc/ui/ui-portlet',
this.portlet = new Portlet.View({
icon : 'fa-bar-chart-o',
title: 'Viewport',
cls : 'ui-portlet charts-viewer',
operations: {
edit_button: new Ui.ButtonIcon({
icon : 'fa-edit',
@@ -103,8 +101,8 @@ define( [ 'utils/utils', 'mvc/ui/ui-misc', 'mvc/ui/ui-portlet',
});
// append elements
this.portlet.append( this.message.$el.addClass( 'ui-margin-top' ) );
this.portlet.append( this.viewport_view.$el );
this.portlet.append( this.message.$el );
this.portlet.append( this.viewport.$el.addClass( 'ui-margin-top' ) );
this.setElement( this.portlet.$el );
// events
@@ -129,7 +127,7 @@ define( [ 'utils/utils', 'mvc/ui/ui-misc', 'mvc/ui/ui-portlet',
},
/** Check if chart is ready for export */
_wait: function(chart, callback) {
_wait: function( chart, callback ) {
if ( this.app.deferred.ready() ) {
callback();
} else {
@@ -5,9 +5,6 @@
*/
define( [ 'mvc/ui/ui-portlet', 'mvc/ui/ui-misc', 'utils/utils' ], function( Portlet, Ui, Utils ) {
return Backbone.View.extend({
// list of container/canvas elements
container_list: [],
canvas_list: [],
initialize: function( app, options ) {
var self = this;
this.app = app;
@@ -22,7 +19,7 @@ define( [ 'mvc/ui/ui-portlet', 'mvc/ui/ui-misc', 'utils/utils' ], function( Port
this.$text = this.$( '.text' );
// use full screen for viewer
this._fullscreen( this.$el, 50 );
this._fullscreen( this.$el, 55 );
// prevent window scrolling
var initial_overflow = $( 'body' ).css( 'overflow' );
@@ -110,85 +107,12 @@ define( [ 'mvc/ui/ui-portlet', 'mvc/ui/ui-misc', 'utils/utils' ], function( Port
/** Draws a new chart by loading and executing the corresponding chart wrapper */
_draw: function( process, chart ) {
var self = this;
var chart_type = chart.get( 'type' );
this.chart_definition = chart.definition;
var n_panels = 1;
if ( chart.settings.get( 'use_panels' ) === 'true' ) {
n_panels = chart.groups.length;
}
this._createContainer( this.chart_definition.tag, n_panels );
var n_panels = chart.settings.get( 'use_panels' ) === 'true' ? chart.groups.length : 1;
this._createContainer( chart.definition.tag, n_panels );
chart.state( 'wait', 'Please wait...' );
if ( !this.chart_definition.execute || ( this.chart_definition.execute && chart.get( 'modified' ) ) ) {
this.app.jobs.cleanup( chart );
chart.set( 'modified', false );
}
require( [ 'plugin/charts/' + this.app.chartPath( chart_type ) + '/wrapper' ], function( ChartView ) {
if ( self.chart_definition.execute ) {
self.app.jobs.request( chart, self._defaultSettingsString( chart ), self._defaultRequestString( chart ),
function() {
var view = new ChartView( self.app, {
process : process,
chart : chart,
request_dictionary : self._defaultRequestDictionary( chart ),
canvas_list : self.canvas_list
});
},
function() {
process.reject();
}
);
} else {
var view = new ChartView( self.app, {
process : process,
chart : chart,
request_dictionary : self._defaultRequestDictionary( chart ),
canvas_list : self.canvas_list
});
}
require( [ 'plugin/charts/' + this.app.split( chart.get( 'type' ) ) + '/wrapper' ], function( ChartView ) {
new ChartView( self.app, { process : process, chart : chart, canvas_list : self.canvas_list } );
});
},
/** Creates default chart request */
_defaultRequestString: function( chart ) {
var request_string = '';
var group_index = 0;
var self = this;
chart.groups.each( function( group ) {
group_index++;
for ( var key in self.chart_definition.columns ) {
request_string += key + '_' + group_index + ':' + ( parseInt( group.get( key ) ) + 1 ) + ', ';
}
});
return request_string.substring( 0, request_string.length - 2 );
},
/** Creates default settings string for charts which require a job execution */
_defaultSettingsString: function( chart ) {
var settings_string = '';
for ( key in chart.settings.attributes ) {
settings_string += key + ':' + chart.settings.get( key ) + ', ';
};
return settings_string.substring( 0, settings_string.length - 2 );
},
/** Create default data request dictionary */
_defaultRequestDictionary: function( chart ) {
var request_dictionary = { groups : [] };
request_dictionary.id = this.chart_definition.execute ? chart.get( 'dataset_id_job' ) : chart.get( 'dataset_id' );
var group_index = 0;
var self = this;
chart.groups.each( function( group ) {
var columns = {};
for ( var column_key in self.chart_definition.columns ) {
var column_settings = self.chart_definition.columns[ column_key ];
columns[ column_key ] = Utils.merge( { index : group.get( column_key ) }, column_settings );
}
request_dictionary.groups.push( Utils.merge({
key : ( ++group_index ) + ':' + group.get( 'key' ),
columns : columns
}, group.attributes ));
});
return request_dictionary;
}
});
});
@@ -12,6 +12,7 @@
## install shared libraries
${h.js( 'libs/jquery/jquery',
'libs/jquery/jquery-ui',
'libs/jquery/select2',
'libs/bootstrap',
'libs/underscore',
@@ -20,7 +21,7 @@
'libs/require')}
## shared css
${h.css( 'base' )}
${h.css( 'base', 'jquery-ui/smoothness/jquery-ui' )}
## crossfilter
${h.javascript_link( app_root + "plugins/crossfilter/crossfilter.js" )}
@@ -46,21 +47,13 @@
<body>
<script type="text/javascript">
// get configuration
var config = {
root : '${root}',
app_root : '${app_root}'
};
// link galaxy
var app_root = '${app_root}';
var Galaxy = Galaxy || parent.Galaxy || {
root : '${root}',
emit : {
debug: function() {}
}
};
// console protection
window.console = window.console || {
log : function(){},
debug : function(){},
@@ -69,10 +62,8 @@
error : function(){},
assert : function(){}
};
// configure require
require.config({
baseUrl: config.root + "static/scripts/",
baseUrl: Galaxy.root + "static/scripts/",
paths: {
"plugin" : "${app_root}",
"d3" : "libs/d3"
@@ -87,22 +78,15 @@
window.onbeforeunload = function() {
return 'You are leaving Charts.';
};
// application
var app = null;
$(function() {
// request application script
require(['plugin/app'], function(App) {
// load options
require( [ 'plugin/app' ], function( App ) {
var options = {
id : ${h.dumps( visualization_id )} || undefined,
config : ${h.dumps( config )}
}
// create application
app = new App(options);
// add to body
$('body').append(app.$el);
app = new App( options );
$( 'body' ).append( app.$el );
});
});
Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

+137
View File
@@ -0,0 +1,137 @@
Galaxy Communication Server
===========================
A problem faced by administrators, especially those of smaller galaxy sites, is how to connect users with documentation on workflows and analysis procedures, and then helping them through running these steps. For sites where the admins and the tool developers are the same groups, finding time for developing the required training resources and providing the level of hands-on guidance required can be an impossible challenge in time management.
In order to solve this, a simple chat server has been added to Galaxy to provide realtime communication between users. The hope is that this will decrease the burden on administrators:
- *Troubleshooting*: When users have trouble with a tool, they can ask in chat if
anyone can help, rather than coming to administrators and tool developers
first.
- *Sharing*: Your galaxy users can easily talk to coworkers, maybe learn about
new analyses they've each developed
- *Dedicated Discussion*: The chat implementation provides the ability to
designate some fixed chat rooms which will always be visible to users, these
can be used to help guide user discussion to topics like NGS.
.. image:: communication_server.png
Pre-requisites
--------------
This service will need to be deployed on a host that has:
- Access to the Galaxy database
- A port exposed
- A non-default ``id_secret`` set in your ``galaxy.ini``
We say "access to galaxy database", this service could run on an NFS mounted
copy of Galaxy, if the host it is deployed on can access the database of the
main galaxy instance. This is required, because the chat service validates
connecting users to prevent impersonation.
Deploying the Server
--------------------
The chat server is a very new feature in Galaxy and has been disabled by
default at a number of levels, as not all users may wish to use this feature.
Configuration is managed in ``galaxy.ini``:
.. code-block:: ini
# Galaxy real time communication server settings
enable_communication_server = True
communication_server_host = http://localhost
communication_server_port = 7070
# persistent_communication_rooms is a comma-separated list of rooms that should be always available.
persistent_communication_rooms = NGS,RNA-Seq,Genome Annotation
As you can see in this configuration, it is pointing at a service running on
the same host as Galaxy, talking to port 7070.
Once you have configured this portion, you will want to install the required
dependencies, and launch the chat server. This is run as a separate flask based
service.
Installing the Dependencies
---------------------------
Most admins will find it convenient to activate the Galaxy virtualenv, and run
the following command:
.. code-block:: console
(.venv)$ pip install flask flask-login flask-socketio eventlet
You can then launch the server:
.. code-block:: console
(.venv)$ python ./scripts/communication/communication_server.py --port 7070 --host localhost
Next we'll configure user-level access.
Enabling the Chat Interace
--------------------------
Users who wish to enable the chat can do so in their user preferences.
.. image:: chat-0.png
There is a new element at the top of the list, which controls chat preferences
.. image:: chat-1.png
And a short dialog to enable it
.. image:: chat-2.png
After which, a new icon becomes visible next to "Analyse Data" on your Galaxy
header.
.. image:: chat-3.png
Opening the chat interface, lastly we notice that chat defaults to an offline
state. Clicking the red chat bubble icon will turn it green and allow the user
to engage with others.
.. image:: chat-4.png
Finally users can connect with one another within Galaxy.
.. image:: communication_server_rooms.png
Security Considerations
-----------------------
This service does:
- Ensure authenticated access by decoding their Galaxy ``galaxysession``
cookie.
- Prevent user spoofing
This service does not:
- enforce rate-limiting of messages
- run any sort of text/obscenity filtering rules
- prevent user spoofing if the user is an administrator and impersonating
another user
Keeping the Chat Server Running
-------------------------------
Here is an example supervisord configuration for keeping the chat server running:
.. code-block:: console
[program:galaxy_chat_server]
directory = GALAXY_ROOT
command = python ./scripts/communication/communication_server.py --port 7070 --host localhost
autostart = true
autorestart = unexpected
user = GALAXY_USER
startsecs = 2
redirect_stderr = true
Configuration with virtualenvs will be slightly different.
Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

+333
View File
@@ -0,0 +1,333 @@
=================================
Conda for Tool Dependencies
=================================
Galaxy tools (also called wrappers) traditionally use Tool Shed package
recipes to install their dependencies. At the tool's installation time
the recipe is downloaded and executed in order to provide the underlying
software executables. Introduction of these Galaxy-specific recipes was
a necessary step at the time, however nowadays there are other more
mature and stable options to install software in a similar manner. The
Galaxy community has taken steps to improve the tool dependency system
in order to enable new features and expand its reach. This document aims
to describe these and answer the FAQ.
Galaxy has adopted a new standard for tool dependencies: Conda packages!
Not only do Conda packages make tool dependencies more reliable and
stable, they are also easier to test and faster to develop than the
traditional Tool Shed package recipes.
Conda is a package manager like apt-get, yum, pip, brew or guix. We
don't want to argue about the relative merits of various package
managers here, in fact Galaxy supports multiple package managers and we
welcome community contributions (such as implementing a Guix package
manager or enhancing the existing brew support to bring it on par with
Conda).
As a community, we have decided that Conda is the one that best fulfills
our needs. The following are some of the crucial Conda features that led
to this decision:
- Installation of packages does not require root privileges
(Installation at any location the Galaxy user has write access to)
- Multiple versions of software can be installed in parallel
- HPC-ready
- Faster and more robust package installations through p re-compiled
packages (no build environment complications)
- Independent of programming language ( R, Perl, Python, Julia, Java,
pre-compiled binaries, and more )
- Easy to write recipes (1 YAML description file + 1 Bash install
script)
- An active, large and growing community (with more and more software
authors managing their own recipes)
- Extensive documentation: `Conda documentation`_ and `Conda quick-start`_
Below we answer some common questions (collected by Lance Parsons):
1. How do I enable Conda dependency resolution for existing Galaxy installations?
*********************************************************************************
Most Galaxy administrators have not set up a dependency resolvers
configuration file ( ``dependency_resolvers_conf.xml`` ) which means they
are using Galaxy's default ( ``dependency_resolvers_conf.xml.sample`` ).
Galaxy has enabled Conda dependency resolution by default since release
16.04 (if Conda was installed already), so many existing installations
can use Conda dependencies. Having Conda enabled in ``dependency_resolvers_conf.xml`` means that Galaxy will
look for dependencies using the Conda system when it attempts to run
tools. If ``conda_auto_install`` is True , and a dependency is not found,
Galaxy will attempt to install it using the configured Conda channels. A
graphical user interface that allows administrators install Conda
packages directly from Galaxy when tools are installed from the Tool
Shed is available since the 16.07 version of Galaxy.
The most important configuration settings related to Conda are listed in Table 1.
+--------------------------+--------------------------+---------------------------+
| Setting | Default setting | Meaning |
+--------------------------+--------------------------+---------------------------+
| ``conda_prefix`` | <tool\_dependency\_dir>/ | the location |
| | \_conda | on the |
| | | filesystem where Conda |
| | | packages and |
| | | environments are |
| | | installed |
| | | |
| | | IMPORTANT : Due to a |
| | | current limitation in |
| | | Conda, the total length |
| | | of the |
| | | |
| | | ``conda_prefix`` and the |
| | | ``job_working_directory`` |
| | | path should be less |
| | | than 50 characters! |
+--------------------------+--------------------------+---------------------------+
| ``conda_auto_install`` | False | Set to True to instruct |
| | | Galaxy to look for and |
| | | install Conda packages |
| | | for missing tool |
| | | dependencies before |
| | | running a job |
+--------------------------+--------------------------+---------------------------+
| ``conda_auto_init`` | False | Set to True to instruct |
| | | Galaxy to install Conda |
| | | automatically if it |
| | | cannot find a local copy |
+--------------------------+--------------------------+---------------------------+
*Table 1: Important configuration options for Conda in Galaxy*
2. How do Conda dependencies work? Where do things get installed?
*********************************************************************************
In contrast to the old dependency system, which was used exclusively by
Galaxy, Conda is a pre-existing, independent project. With Conda it
is possible for an admin to install packages without touching Galaxy at
all – managing your dependencies independently from Galaxy. Galaxy can
handle these dependencies for you, but admins are not required to use
Galaxy for dependency management.
There are a few new config options in the galaxy.ini file (see Table
1 or ``galaxy.ini.sample`` for more information), but by default Galaxy
will install Conda (the package manager) and the required packages in
the ``<tool_dependency_dir>/_conda/`` directory. In this directory,
Galaxy will create an ``envs`` folder with all of the environments managed
by Galaxy. Every environment contains a ``lib``, ``bin``, ``share``, and ``include``
subdirectory, depending on the tool, and is sufficient to get a Galaxy
tool up and running. Galaxy simply sources this folder via Conda and
makes everything available before the tool is executed on your cluster.
To summarize, there are four ways to manage Conda dependencies for use
with Galaxy. For all of these options, Conda dependency management must
be configured in the ``dependency_resolvers_conf.xml`` and the ``galaxy.ini`` file.
#. Manual Install - Conda dependencies may be installed by
administrators from the command line. Conda (and thus the Conda
environments) should be installed in the location specified by the
``conda_prefix`` path (defined in ``galaxy.ini`` and by default
``<tool_dependency_dir>/_conda/`` directory). Galaxy will search
these environments for required packages when tools are run. Conda
environment names have to follow a specific naming pattern. As an
example, to install samtools in version 0.1.19, the administrator can
run the command:
.. code-block:: bash
$ conda create --name __package__samtools@__version__0.1.19 samtools==0.1.19 --channel bioconda
Tools that require samtools version 0.1.19 will then be able to find
and use the installed Conda package.
#. Galaxy Admin Interface (>= 16.07) - Galaxy will install Conda tool
dependencies when tools are installed from the Tool Shed if the
option “When available, install externally managed dependencies (e.g.
Conda)? Beta” is checked. Admins may also view and manage Conda
dependencies via the Admin interface.
#. Automatically at tool run time - When a tool is run and a dependency
is not found, Galaxy will attempt to install the dependency using
Conda if ``conda_auto_install`` is activated in the configuration.
#. Via the API , upon tool installation (>= 16.07) - The Galaxy
community maintains an `ansible role`_ that uses
BioBlend_ and the Galaxy API to install tools.
3. What is required to make use of this? Any specific packages, Galaxy revision, OS version, etc.?
*********************************************************************************
The minimum required version of Galaxy to use Conda is 16.01, however
version 16.07 or greater is recommended. The 16.07 release of Galaxy has
a nice graphical user interface to manage packages, but this is not
required to have Conda dependencies managed and used by Galaxy.
Conda packages should work on all compatible operating systems with
glibc version (2.5) or newer (this includes Centos 5). We will most
likely switch soon to glibc version 2.12 as minimum requirement (this
includes CentOS 6). So all packages will run on all \*nix operating
systems newer than 2007.
4. How do I know what system is being used by a given tool?
*********************************************************************************
The Galaxy log will tell you which dependency resolution system is used
to satisfy each tool dependency and you can specify priorities using the
``config/dependency_resolution_conf.xml`` file. If you put Conda on
top, Galaxy will at first try to use Conda to resolve a tool dependency;
if this does not work, the following dependency resolvers is used, as
specified. See `resolver docs`_ for detailed documentation. Starting from galaxy release 16.07, you can
see which dependency will be used (“resolved”) in the admin panel.
5. How do I go about specifying Conda dependencies for a tool? All the docs still seem to recommend (or exclusively discuss) the ``tool_dependencies.xml`` method.
*********************************************************************************
The simple answer is: you don't need to do much to make Conda work for a tool.
The ``<requirement>`` tag in the tool XML file is enough. The name and the
version should correspond to a Conda package in the ``default``, ``r``,
``bioconda`` or ``iuc`` Conda channel (you can extend this list if you
like in your ``galaxy.ini`` ). If this is the case you are ready to go. Read
more about `Conda channels`_ and browse their packages on https://anaconda.org/ url followed by the channel name (e.g.
`https://anaconda.org/bioconda <https://anaconda.org/bioconda>`__
).
We will gradually adjust the documentation about ``tool_dependencies.xml`` and
deprecate it everywhere.
6. During tool installation what if there is no Conda package available for given requirement? What if the requirement is resolved in a different software than the original wrapper author meant to use?
*********************************************************************************
If there is no Conda package available during tool installation the tool
will install successfully, and can be used if its dependencies are
satisfied by another dependency system such as Tool Shed package
recipes, Docker containers or modules.
If there is a package of correct name and version it will be used. There
is no equivalent of the “owner” concept used in Galaxy packages
installed from the Tool Shed.
7. Where can I find a list of existing Conda packages that I can point to, so I don't have to reinvent the wheel for common dependencies?
*********************************************************************************
With Conda installed run:
.. code-block:: bash
$ conda search <package_name> -c bioconda -c iuc
This will search in all channels that are activated by default in
Galaxy. If you find your package your are ready to go. If not please
`create a Conda package`_ and submit_ it to BioConda_ or get in `contact with the IUC`_.
8. How can I create a new Conda package for a dependency?
*********************************************************************************
Adding a package to the BioConda or IUC Conda channels will make it
available for Galaxy tools to use as a dependency. To learn how, get in
touch with the awesome BioConda community. They have great documentation
and assist with all development. You will also see a few of us at this
project to get you started :)
Don't be scared! Conda recipes are really simple to write. Conda also
offers you, so called \`skeleton\` generators, generating recipes from
pypi, cran, cpan for you (mostly) automatically.
9. Is there a way to convert traditional Tool Shed package recipes that are not yet in a Conda channel?
*********************************************************************************
First, you do not need to do anything to your wrapper as long as the
package name in the requirement tag matches the name of correct
Conda package. (You may want to mention in the README or a comment the
Conda channel that contains the package).
If you want to migrate some recipes from XML to Conda, IUC is happy to
give you a hand. We are trying to get all new versions under Conda and
leave the old versions as they are – simply because of time.
10. What is the recommendation for existing installations? Will I continue to maintain both systems or migrate to the new Conda system eventually?
*********************************************************************************
Old tools will use the traditional installation system, this system will
stay and will be supported to install old tools. This we promised to our
community to guarantee sustainability and reproducibility. New tools
from the IUC, may be Conda only.
11. If I have Conda enabled, what do I need to do to install tools using it? For example, how can I install the latest Trinity? And how will I know dependencies are installed?
*********************************************************************************
This depends on your ``galaxy.ini`` setting. Galaxy will install Conda for
you if you have enabled ``conda_auto_init``. If ``conda_auto_install`` is
enabled, Galaxy will install Trinity via Conda when a Trinity job is
launched and Trinity is not yet installed . With the latest 16.07
release you can see which dependencies are being used in the “Manage
installed tools” section of the admin panel and you can select whether
or not to install Conda packages or Tool Shed package recipes when you
install new tools, even if ``conda_auto_install`` is disabled.
More improvements to the UI will be coming in future releases. To see if Galaxy
has created a Trinity environment for you have a look at folder under
``<tool_dependency_dir>/_conda/envs/``(or ``<conda_prefix>/envs`` if you have changed `conda_prefix` in your galaxy.ini file).
12. Can I mix traditional Galaxy packages and Conda packages?
*********************************************************************************
Yes, the way this works is that Galaxy goes through the list of
requirements for a tool, and then determines for each requirement if it
can be satisfied by any of the active resolver systems.
The order in which resolvers are tried is listed in the
``dependency_resolvers_conf.xml`` file, and the default order is
- Tool Shed packages
- Packages manually installed by administrators
- Conda packages
The first system that satisfies a requirement will be used.
13. What can I do if Conda doesn't work for me?
*********************************************************************************
There is currently a limitation in the way Conda packages are being
built. This limitation will be addressed shortly by the Conda community,
however this requires all packages to be rebuilt.
To work around this limitation, please make sure that the total length
of the ``conda_prefix`` and ``job_working_directory`` path is less than 50
characters long.
If this is your problem, you should see a warning similar to the
following in your galaxy log files:
.. code-block:: bash
ERROR: placeholder '/home/ray/r_3_3_1-x64-3.5/envs/_build_placehold_placehold_placehold_placehold_pl' too short
In rare cases Conda may not have been properly installed by Galaxy.
A symptom for this is if there is no activate script in
``<conda_prefix>/bin`` folder. In that case you can delete the ``conda_prefix`` folder
and restart Galaxy, which will again attempt to install Conda.
If this does not solve your problem or you have any trouble following
the instructions, please ask on the Galaxy mailing list or the Galaxy
IRC channel.
.. _Conda documentation: http://conda.pydata.org/docs/building/build.html
.. _Conda quick-start: http://conda.pydata.org/docs/get-started.html
.. _ansible role: https://github.com/galaxyproject/ansible-galaxy-tools
.. _BioBlend: https://github.com/galaxyproject/bioblend
.. _resolver docs: https://docs.galaxyproject.org/en/master/admin/dependency_resolvers.html
.. _Conda channels: http://conda.pydata.org/docs/custom-channels.html
.. _create a Conda package: http://conda.pydata.org/docs/building/recipe.html#conda-recipe-files-overview
.. _submit: https://bioconda.github.io/#step-4-join-the-team
.. _BioConda: https://bioconda.github.io
.. _contact with the IUC: https://gitter.im/galaxy-iuc/iuc
+6 -2
View File
@@ -8,12 +8,16 @@ documentation. These resources should be used together.
.. toctree::
:maxdepth: 3
interactive_environments.rst
dependency_resolvers.rst
conda_faq.rst
interactive_environments.rst
framework_dependencies.rst
useful_scripts.rst
grt.rst
chat.rst
+788
View File
@@ -0,0 +1,788 @@
.. to_doc
-------------------------------
16.07
-------------------------------
.. announce_start
Highlighted Enhancements
-------------------------------
* Implement an Azure backend for the Galaxy objectstore
(thanks to `@zfrenchee <https://github.com/zfrenchee>`__.)
`Pull Request 2621`_
* HTCondor Docker Integration
(thanks to `@bgruening <https://github.com/bgruening>`__.)
`Pull Request 2278`_
* Implement a Kubernetes job runner
(thanks to `@pcm32 <https://github.com/pcm32>`__.)
`Pull Request 2314`_, `Pull Request 2498`_, `Pull Request 2559`_,
`Pull Request 2578`_, `Pull Request 2616`_, `Pull Request 2528`_
* Implement collection operations - tool-like entities allowing users
to zip, unzip, flatten, and filter failed datasets out of collections.
(You may need to sync your ``tool_conf.xml`` against sample.)
`Pull Request 2434`_
* Allow history panel to display list of lists dataset collections.
`Pull Request 2613`_
* Add a Tool Shed API endpoint method to check the current user.
`Pull Request 2243`_
* Add a Galaxy API endpoint to update a user object.
`Pull Request 2595`_
* Improvements to toolbox search.
`Pull Request 2273`_
* New pages and general improvements to the Reports application
(thanks to `@BalthazarPavot <https://github.com/BalthazarPavot>`__.)
`Pull Request 2664`_
* Nicer bug report emails
(thanks to `@erasche <https://github.com/erasche>`__.)
`Pull Request 2143`_
* Tools with auto_format='true' now connectable in workflow editor
(thanks to `@yhoogstrate <https://github.com/yhoogstrate>`__.)
`Pull Request 2144`_
* Drop "Galaxy pip" in favor of manylinux1 wheels (which are supported in pip
>= 8.1).
`Pull Request 2383`_
* Allow tool form to listen to history
(thanks to `@nturaga <https://github.com/nturaga>`__.)
`Pull Request 2476`_
* Add `EDAM <http://edamontology.org/page>`__ operations to tools and expose in API
(thanks to `@mvdbeek <https://github.com/mvdbeek>`__, `@nsoranzo <https://github.com/nsoranzo>`__ and `@odoppelt <https://github.com/odoppelt>`__.)
`Pull Request 2379`_
* Add support to PDBQT molecule datatype
(thanks to `@leobiscassi <https://github.com/leobiscassi>`__.)
`Pull Request 2452`_
* Add the trackhub composite datatype
(thanks to `@remimarenco <https://github.com/remimarenco>`__.)
`Pull Request 2348`_, `Pull Request 2646`_, `Pull Request 2701`_
* Add the Mothur datatypes
(thanks to `@shiltemann <https://github.com/shiltemann>`__.)
`Pull Request 2038`_, `Pull Request 2429`_
* Add the dynamic tool destination tool to Galaxy for defining finer grained
tool destination rules.
(thanks to `@ericenns <https://github.com/ericenns>`__.)
`Pull Request 2579`_
* Galaxy can now install Conda dependencies in addition to tool shed
dependencies during repository installations
(thanks to `@mvdbeek <https://github.com/mvdbeek>`__
and `@bwlang <https://github.com/bwlang>`__.)
`Pull Request 2554`_
* Implement the Galaxy Communication Server (a simple in-Galaxy chat server)
(thanks to `@anuprulez <https://github.com/anuprulez>`__
and `@bgruening <https://github.com/bgruening>`__.)
`Pull Request 2515`_
Enhancements
-------------------------------
* Install Conda at startup; enable conda_auto_init in sample conf
`Pull Request 2759`_
* Add ``filter_failed_datasets_from_collection.py`` script to ``scripts/``
(thanks to `@chambm <https://github.com/chambm>`__.)
`Pull Request 2358`_
* Enhanced workflow run form using newer client forms architecture.
`Pull Request 2077`_
* Tweaks to various library functions for galaxy-lib.
`Pull Request 2110`_, `Pull Request 2494`_, `Pull Request 2354`_,
`Pull Request 2414`_, `Pull Request 2436`_
* Automate and clarify more of the release process.
`Pull Request 2117`_, `Pull Request 2366`_, `Pull Request 2372`_,
`Pull Request 2388`_
* Update template to include the release of the Docker container
(thanks to `@bgruening <https://github.com/bgruening>`__.)
`Pull Request 2378`_
* Add ``server_starttime`` to configuration API.
`Pull Request 2124`_
* Show line breaks in commit log in the Tool Shed
(thanks to `@nturaga <https://github.com/nturaga>`__.)
`Pull Request 2142`_
* Replacing the ``_getIndex`` method by UnderscoreJS method ``_.findIndex()``
(thanks to `@anuprulez <https://github.com/anuprulez>`__.)
`Pull Request 2157`_
* Small enhancements to user activation process.
`Pull Request 2158`_
* Implement ``single_user = <email>`` config option.
`Pull Request 2165`_
* More documentation and flexibility for FTP imports.
`Pull Request 2168`_
* Make stats prefix configurable and add a conditional wheel requirement.
`Pull Request 2171`_
* Fix running tool tests if remote user middleware is enabled.
`Pull Request 2173`_
* Improve handling of a missing R environment during Tool Shed dependency
installations.
`Pull Request 2215`_
* Quote some parameters in the trim tool command
(thanks to `@nsoranzo <https://github.com/nsoranzo>`__.)
`Pull Request 2248`_
* Remove overly chatty tool dependency resolution logging statement.
`Pull Request 2254`_
* Update the list of contributors.
`Pull Request 2256`_, `Pull Request 2257`_, `Pull Request 2258`_
* Add grunt watcher on .less files
(thanks to `@remimarenco <https://github.com/remimarenco>`__.)
`Pull Request 2274`_
* Remove dependency on custom Whoosh (requirements update).
`Pull Request 2276`_
* Various enhancements for library functions related to tools.
`Pull Request 2279`_
* Shift ``asbool`` handling in datatypes API so that an appropriate error message is now returned.
`Pull Request 2286`_
* More small fixes from downstream projects.
`Pull Request 2292`_
* For published workflow display, provide a better error when the workflow or user cannot be found
`Pull Request 2302`_
* Bump sqlite3 version
(thanks to `@matthdsm <https://github.com/matthdsm>`__.)
`Pull Request 2307`_
* Show collection counts in collection and history collection views.
`Pull Request 2326`_
* Various client library updates.
`Pull Request 2328`_
* Revise form data visitor.
`Pull Request 2330`_
* Update using xhr date header.
`Pull Request 2335`_
* Implement an API for managing history/sharable model user sharing.
`Pull Request 2340`_
* Revise portlet view, integrate collapsible option.
`Pull Request 2360`_
* Fix issue with lowercasing in datatypes/registry.py
(thanks to `@remimarenco <https://github.com/remimarenco>`__.)
`Pull Request 2361`_
* Improve composite output tool test.
`Pull Request 2363`_
* Upgrade shared ui libraries, add test cases
`Pull Request 2368`_
* Throughout backend use open() instead of file() for Python 3
(thanks to `@nsoranzo <https://github.com/nsoranzo>`__.)
`Pull Request 2370`_
* Remove backported importlib and ordereddict.
`Pull Request 2380`_
* Note on updating tool testing
(thanks to `@erasche <https://github.com/erasche>`__.)
`Pull Request 2381`_
* Docker swarm support for Galaxy Interactive Environments (GIEs)
`Pull Request 2386`_, `Pull Request 2392`_
* Add support for EDAM data annotations to datatypes
(thanks to `@nsoranzo <https://github.com/nsoranzo>`__, `@bgruening <https://github.com/bgruening>`__, `@hmenager <https://github.com/hmenager>`__ and `@mvdbeek <https://github.com/mvdbeek>`__.)
`Pull Request 2387`_
* Add a new workflow building mode variation which does access the history
`Pull Request 2390`_
* Add conda search function to ``conda_util`` library function
(thanks to `@bgruening <https://github.com/bgruening>`__.)
`Pull Request 2395`_
* Add history navigation options for dataset frames to scratch book
`Pull Request 2396`_
* Add EDAM topics to tools and expose in API
(thanks to `@nsoranzo <https://github.com/nsoranzo>`__.)
`Pull Request 2397`_
* Update SLURM runner so when scontrol fails, Galaxy attempts to get job
state with sacct
(thanks to `@nsoranzo <https://github.com/nsoranzo>`__.)
`Pull Request 2403`_
* Enhancements to tool test output verification.
`Pull Request 2409`_
* Show history dataset id (hid) in dataset 'view details' page.
`Pull Request 2411`_
* Updates and fixes for the run workflow UI elements.
`Pull Request 2416`_
* Raise ``Exception`` if ``watch_tools`` has an unrecognized value
(thanks to `@nsoranzo <https://github.com/nsoranzo>`__.)
`Pull Request 2418`_
* Use ``log.warning()`` instead of deprecated ``log.warn()`` (for Python 3)
(thanks to `@nsoranzo <https://github.com/nsoranzo>`__.)
`Pull Request 2420`_
* Minor updates to documentation.
`Pull Request 2427`_
* Correct various EDAM data/format annotations in datatypes
(thanks to `@hmenager <https://github.com/hmenager>`__.)
`Pull Request 2428`_
* Fix ``$defaults`` according to `#2430
<https://github.com/galaxyproject/galaxy/issues/2430>`__
(thanks to `@ThomasWollmann <https://github.com/ThomasWollmann>`__.)
`Pull Request 2438`_
* Properly list subworkflows in run workflow form.
`Pull Request 2440`_
* Make some files compatible with Python3
(thanks to `@nsoranzo <https://github.com/nsoranzo>`__.)
`Pull Request 2453`_
* Add parameter expansion caller and test cases as preparation for workflow
API extension.
`Pull Request 2464`_
* Set a default for ``tool_dependencies_dir``.
`Pull Request 2480`_
* Add a password expiration config option (resolves `#2485
<https://github.com/galaxyproject/galaxy/issues/2485>`__)
(thanks to `@benfulton <https://github.com/benfulton>`__.)
`Pull Request 2486`_
* Display TIFF format in upload
(thanks to `@bgruening <https://github.com/bgruening>`__.)
`Pull Request 2516`_
* Use ``self.decode_id`` instead of ``trans.security.decode_id``
(thanks to `@nsoranzo <https://github.com/nsoranzo>`__.)
`Pull Request 2529`_
* Charts revision.
`Pull Request 2531`_
* Add ``Makefile`` target for fetching updated bower dependencies.
`Pull Request 2534`_
* Make conda autoinstall of packages safer:
(thanks to `@pvanheus <https://github.com/pvanheus>`__.)
`Pull Request 2538`_
* Updates to Interactive Environment docs
(thanks to `@pvanheus <https://github.com/pvanheus>`__.)
`Pull Request 2543`_
* Allow displaying bigWig files in IGV
(thanks to `@dpryan79 <https://github.com/dpryan79>`__.)
`Pull Request 2545`_
* Allow users to purge datasets by default.
`Pull Request 2553`_
* Add Jupyter IE to the allowed visualizations for BAM datasets
(thanks to `@erasche <https://github.com/erasche>`__.)
`Pull Request 2572`_
* Python3: port 215 files
(thanks to `@nsoranzo <https://github.com/nsoranzo>`__, `@tshtatland <https://github.com/tshtatland>`__, `@xiaoqian1984 <https://github.com/xiaoqian1984>`__, `@alanryanwang <https://github.com/alanryanwang>`__ and `@ericenns <https://github.com/ericenns>`__.)
`Pull Request 2574`_
* Add python-ldap module to conditional requirements
(thanks to `@abretaud <https://github.com/abretaud>`__.)
`Pull Request 2576`_
* Update gsummary.xml
(thanks to `@lecorguille <https://github.com/lecorguille>`__.)
`Pull Request 2590`_
* Add Warning when Conda is installed
(thanks to `@remimarenco <https://github.com/remimarenco>`__.)
`Pull Request 2596`_
* Added the neostore (neo4j db) for noe4jdb dataset
(thanks to `@zipho <https://github.com/zipho>`__.)
`Pull Request 2605`_
* Fix smart_str for Python 3. Add doctests
(thanks to `@nsoranzo <https://github.com/nsoranzo>`__.)
`Pull Request 2608`_
* Added Neo4j IE
(thanks to `@thobalose <https://github.com/thobalose>`__.)
`Pull Request 2610`_
* Committing format changes to the user impersonation dropdown.
(thanks to `@sszakony <https://github.com/sszakony>`__.)
`Pull Request 2612`_
* Use pagination and filtering for select2 fields
`Pull Request 2615`_
* Update workflow share dropdown width
(thanks to `@sszakony <https://github.com/sszakony>`__.)
`Pull Request 2617`_
* Graph visualization: add parsers, change datatypes
`Pull Request 2620`_
* Fix certain combos of dynamic deeply nested collections in workflows.
`Pull Request 2634`_
* add tar to datatypes_conf.xml
(thanks to `@mariabernard <https://github.com/mariabernard>`__.)
`Pull Request 2636`_
* Optimize get_file_peek()
(thanks to `@nsoranzo <https://github.com/nsoranzo>`__.)
`Pull Request 2637`_
* Move workflow run and history options to top, add loading indicator
`Pull Request 2643`_
* Enhance workflow run button to indicate workflow loading progress, keep
header fixed
`Pull Request 2647`_
* Allow uploading strict BED datatypes.
`Pull Request 2648`_
* Reduce server sided refresh requests to changes in data associated input
fields
`Pull Request 2652`_
* Add import order linting using tox and flake8-import-order.
`Pull Request 2661`_
* Add hg38 to main for ucsc_build_sites.txt.sample
`Pull Request 2670`_
* Extend the list of files tested with flake8-import-order to all files
already passing
(thanks to `@nsoranzo <https://github.com/nsoranzo>`__.)
`Pull Request 2682`_
* List resolver Tool Shed packages
(thanks to `@mvdbeek <https://github.com/mvdbeek>`__.)
`Pull Request 2750`_
.. small_enhancement
* Remove buildbot remnants
`Pull Request 2125`_
* Try pushing again when we get unexpected exception (test fix)
`Pull Request 2130`_
* Refactor checking tool files toward reuse with workflows in Planemo.
`Pull Request 2183`_
* Rename/refactor Utils.validate() to Utils.isEmpty()
`Pull Request 2239`_
* Cleanup of the install and test framework.
`Pull Request 2249`_
* cleanup TS and Reports configs
`Pull Request 2267`_
* Move specific methods from shed_util_common.py to specific_util.py
`Pull Request 2269`_
* Revise selection, options and drilldown wrappers, add tests
`Pull Request 2305`_
* Visualizations: remove graphview
`Pull Request 2329`_
* Update qunit and sinon
`Pull Request 2338`_
* Build job success messages within tool form view
`Pull Request 2355`_
* Cleanup of E203 primarily, and some other misc formatting
`Pull Request 2364`_
* Isolate the data libraries css to affect only the libraries app
`Pull Request 2444`_
* Re-add get_updated_changeset_revisions_from_tool_shed() method
(thanks to `@nsoranzo <https://github.com/nsoranzo>`__.)
`Pull Request 2472`_
* Workaround for circular import. Refactor.
`Pull Request 2477`_
* run_tests.sh: Clarify when/where the report file is created.
(thanks to `@NickSto <https://github.com/NickSto>`__.)
`Pull Request 2564`_
* Reroute consistent workflow endpoint to internal API
`Pull Request 2622`_
* Add tool test for what happens when output filter throws exception.
`Pull Request 2631`_
* Ignore .tox and eggs directories for flake8
`Pull Request 2650`_
* Reorder base templates meta tags
`Pull Request 2651`_
* Import pyparsing in testing so twill's older version doesn't get loaded.
`Pull Request 2656`_
* Change default refresh mode for form views
`Pull Request 2667`_
* Fix unit tests
(thanks to `@nsoranzo <https://github.com/nsoranzo>`__.)
`Pull Request 2691`_
* Create a uWSGI postfork function registry and start the tool conf watcher
thread post-fork
`Pull Request 2774`_
Fixes
-------------------------------
.. major_bug
* Do not encode dict items that start with ``metadata\_`` in return value of
api/tools/create.
`Pull Request 2459`_
* Generate metadata in separate conda environment
(thanks to `@mvdbeek <https://github.com/mvdbeek>`__.)
`Pull Request 2253`_
* Fix to use "$NCPUS" if defined to set GALAXY_SLOTS
(thanks to `@mvdbeek <https://github.com/mvdbeek>`__.)
`Pull Request 2145`_
.. bug
* fix blocking issue check
`Pull Request 2113`_
* Correctly check set_environment declarations when updating repository.
`Pull Request 2116`_
* Hide hidden data parameters in workflow editor
`Pull Request 2120`_
* Place $headers before integrity_check
(thanks to `@mvdbeek <https://github.com/mvdbeek>`__.)
`Pull Request 2146`_
* Fix bug when determining locale
(thanks to `@xiaojay <https://github.com/xiaojay>`__.)
`Pull Request 2213`_
* Add pyparsing dependency of svgwrite. Unpin mercurial.
(thanks to `@nsoranzo <https://github.com/nsoranzo>`__.)
`Pull Request 2223`_
* Sanitize poorly escaped input value in run workflow form
(thanks to `@erasche <https://github.com/erasche>`__.)
`Pull Request 2231`_
* Multi-data collection reductions in repeat blocks are broken.
`Pull Request 2233`_
* Encode collection reduce in serializable fashion
`Pull Request 2241`_
* Cast everything to a string
(thanks to `@erasche <https://github.com/erasche>`__.)
`Pull Request 2252`_
* Use standard model.orm.now for toolshed's password reset token datetime math
`Pull Request 2261`_
* fixed ui bugs in tours
(thanks to `@ThomasWollmann <https://github.com/ThomasWollmann>`__.)
`Pull Request 2262`_
* Preliminary fix for displaying raw text/html
`Pull Request 2263`_
* Correctly use defaults specified in galaxy.ini.sample for statsd.
`Pull Request 2268`_
* Fix encoding issues in test/unit/test_objectstore.py.
`Pull Request 2280`_
* Workflow sharing slug edit fix.
`Pull Request 2293`_
* Always remove the working directory after creating the capsule archive.
`Pull Request 2294`_
* update check for Conda env.
(thanks to `@matthdsm <https://github.com/matthdsm>`__.)
`Pull Request 2295`_
* Make grunt watch (for scripts) work again, settings were being overwritten by the new watch-style command
`Pull Request 2296`_
* Monkeypatch Whoosh to use mkdtemp rather than a fixed temporary directory
`Pull Request 2310`_
* Build: remove redundant webpack step in makefile
`Pull Request 2327`_
* Unicodify has different semantics to str, causing bug reporter bug
(thanks to `@erasche <https://github.com/erasche>`__.)
`Pull Request 2336`_
* Wrap statsd timing middleware more closely around the core application
`Pull Request 2342`_
* UI & API: fix display of inaccessible datasets
`Pull Request 2351`_
* Update README to remove 2.6
(thanks to `@remimarenco <https://github.com/remimarenco>`__.)
`Pull Request 2367`_
* Revise asserts triggering false exceptions for dynamic parameters
`Pull Request 2374`_
* Fix the installed conda version to 3.19.3.
(thanks to `@bgruening <https://github.com/bgruening>`__.)
`Pull Request 2394`_
* Check variable's presence before calling str methods
(thanks to `@erasche <https://github.com/erasche>`__.)
`Pull Request 2408`_
* UI, history: correctly handle index API defaults
`Pull Request 2413`_
* Fix to 4a61a4c: add hids for dataset inputs
`Pull Request 2415`_
* wrap bare str raises with generic Exception()
`Pull Request 2421`_
* Fix raven.js import order in galaxy.panels.mako
`Pull Request 2445`_
* Fix usage of super() in the mothur datatypes.
(thanks to `@bgruening <https://github.com/bgruening>`__.)
`Pull Request 2457`_
* Make pykube an optional dependency since we don't have wheels for it.
`Pull Request 2468`_
* fix markup for button links on sharing template
`Pull Request 2481`_
* fix image generation for workflows with missing tools
`Pull Request 2488`_
* mothur datatypes: don't generate error for pairwise distance matrices
(thanks to `@shiltemann <https://github.com/shiltemann>`__.)
`Pull Request 2489`_
* Toolbox filter fixes
`Pull Request 2499`_
* Fix Post Job Action problem
`Pull Request 2505`_
* Copy PJAs when importing a workflow.
`Pull Request 2508`_
* Fix two errors in sff_extract.py detected by flake8
`Pull Request 2509`_
* Fix HTML errors on 2 templates
(thanks to `@nsoranzo <https://github.com/nsoranzo>`__.)
`Pull Request 2524`_
* Fix tabular display chunking
`Pull Request 2527`_
* Fix dataset matcher when no tool available.
(thanks to `@zipho <https://github.com/zipho>`__.)
`Pull Request 2540`_
* Initialize objectstore for fix_set_dataset_sizes script
`Pull Request 2544`_
* Fix old bug in non-allowed_images.yml GIEs
(thanks to `@erasche <https://github.com/erasche>`__.)
`Pull Request 2548`_
* More defensive GIE Proxying
(thanks to `@erasche <https://github.com/erasche>`__.)
`Pull Request 2552`_
* Fixes for showing min/max labels in Trackster.
`Pull Request 2555`_
* Fix tag_autocomplete issue in workflow editor.
`Pull Request 2569`_
* Fix element_identifier unavailable with data_collection input param
(thanks to `@abretaud <https://github.com/abretaud>`__.)
`Pull Request 2570`_
* Ignore W503 (line break before binary operator) as PEP 8 has reversed its
position on this.
`Pull Request 2594`_
* Fix hex vs float parsing in request body
`Pull Request 2597`_
* Fixes for workflow extraction of mapping collection jobs.
`Pull Request 2625`_
* Workflow SVG generation fix
`Pull Request 2628`_
* Properly initialize datasets when workflow is loaded for execution
`Pull Request 2632`_
* typo in summary statistics tool
(thanks to `@nturaga <https://github.com/nturaga>`__.)
`Pull Request 2639`_
* Set allow_duplicate_entries="False" for built-in Tool Data Tables.
`Pull Request 2644`_
* Ensure Galaxy's python binary is used for metadata generation.
`Pull Request 2660`_
* Fix an error with getting the size of an object from Azure
`Pull Request 2678`_
* Limit creation of multitudes of default, empty histories.
`Pull Request 2684`_
* Fix the sanitization of ``None`` values in utils
`Pull Request 2693`_
* Fix metadata collection on workdir outputs for Pulsar.
`Pull Request 2721`_
* Allow link buttons to trigger regular click events
`Pull Request 2743`_
* Fix unused href parameter when adding scratchbook frames
`Pull Request 2744`_
* Update common_startup.sh to require python2.7 in .venv
(thanks to `@BenjaminHCCarr <https://github.com/BenjaminHCCarr>`__.)
`Pull Request 2756`_
* Separate styles of new and old libraries fixing various ui bugs
`Pull Request 2780`_
* Make conda install and resolver status more robust
(thanks to `@mvdbeek <https://github.com/mvdbeek>`__.)
`Pull Request 2789`_
* Smart string handling on the wsgi response -- this fixes uWSGI blanking out when handling endpoints that return Unicode
`Pull Request 2630`_
* Do not instantiate the raven (sentry) client or tool conf watchdog threads
until uWSGI postfork
`Pull Request 2792`_
* API, history contents: allow ``source`` in payload
`Pull Request 2809`_
.. github_links
.. _Pull Request 2038: https://github.com/galaxyproject/galaxy/pull/2038
.. _Pull Request 2077: https://github.com/galaxyproject/galaxy/pull/2077
.. _Pull Request 2079: https://github.com/galaxyproject/galaxy/pull/2079
.. _Pull Request 2110: https://github.com/galaxyproject/galaxy/pull/2110
.. _Pull Request 2113: https://github.com/galaxyproject/galaxy/pull/2113
.. _Pull Request 2116: https://github.com/galaxyproject/galaxy/pull/2116
.. _Pull Request 2117: https://github.com/galaxyproject/galaxy/pull/2117
.. _Pull Request 2119: https://github.com/galaxyproject/galaxy/pull/2119
.. _Pull Request 2120: https://github.com/galaxyproject/galaxy/pull/2120
.. _Pull Request 2121: https://github.com/galaxyproject/galaxy/pull/2121
.. _Pull Request 2124: https://github.com/galaxyproject/galaxy/pull/2124
.. _Pull Request 2125: https://github.com/galaxyproject/galaxy/pull/2125
.. _Pull Request 2130: https://github.com/galaxyproject/galaxy/pull/2130
.. _Pull Request 2142: https://github.com/galaxyproject/galaxy/pull/2142
.. _Pull Request 2143: https://github.com/galaxyproject/galaxy/pull/2143
.. _Pull Request 2144: https://github.com/galaxyproject/galaxy/pull/2144
.. _Pull Request 2145: https://github.com/galaxyproject/galaxy/pull/2145
.. _Pull Request 2146: https://github.com/galaxyproject/galaxy/pull/2146
.. _Pull Request 2157: https://github.com/galaxyproject/galaxy/pull/2157
.. _Pull Request 2158: https://github.com/galaxyproject/galaxy/pull/2158
.. _Pull Request 2165: https://github.com/galaxyproject/galaxy/pull/2165
.. _Pull Request 2168: https://github.com/galaxyproject/galaxy/pull/2168
.. _Pull Request 2171: https://github.com/galaxyproject/galaxy/pull/2171
.. _Pull Request 2173: https://github.com/galaxyproject/galaxy/pull/2173
.. _Pull Request 2183: https://github.com/galaxyproject/galaxy/pull/2183
.. _Pull Request 2213: https://github.com/galaxyproject/galaxy/pull/2213
.. _Pull Request 2215: https://github.com/galaxyproject/galaxy/pull/2215
.. _Pull Request 2223: https://github.com/galaxyproject/galaxy/pull/2223
.. _Pull Request 2231: https://github.com/galaxyproject/galaxy/pull/2231
.. _Pull Request 2233: https://github.com/galaxyproject/galaxy/pull/2233
.. _Pull Request 2239: https://github.com/galaxyproject/galaxy/pull/2239
.. _Pull Request 2241: https://github.com/galaxyproject/galaxy/pull/2241
.. _Pull Request 2243: https://github.com/galaxyproject/galaxy/pull/2243
.. _Pull Request 2248: https://github.com/galaxyproject/galaxy/pull/2248
.. _Pull Request 2249: https://github.com/galaxyproject/galaxy/pull/2249
.. _Pull Request 2252: https://github.com/galaxyproject/galaxy/pull/2252
.. _Pull Request 2253: https://github.com/galaxyproject/galaxy/pull/2253
.. _Pull Request 2254: https://github.com/galaxyproject/galaxy/pull/2254
.. _Pull Request 2256: https://github.com/galaxyproject/galaxy/pull/2256
.. _Pull Request 2257: https://github.com/galaxyproject/galaxy/pull/2257
.. _Pull Request 2258: https://github.com/galaxyproject/galaxy/pull/2258
.. _Pull Request 2261: https://github.com/galaxyproject/galaxy/pull/2261
.. _Pull Request 2262: https://github.com/galaxyproject/galaxy/pull/2262
.. _Pull Request 2263: https://github.com/galaxyproject/galaxy/pull/2263
.. _Pull Request 2267: https://github.com/galaxyproject/galaxy/pull/2267
.. _Pull Request 2268: https://github.com/galaxyproject/galaxy/pull/2268
.. _Pull Request 2269: https://github.com/galaxyproject/galaxy/pull/2269
.. _Pull Request 2271: https://github.com/galaxyproject/galaxy/pull/2271
.. _Pull Request 2273: https://github.com/galaxyproject/galaxy/pull/2273
.. _Pull Request 2274: https://github.com/galaxyproject/galaxy/pull/2274
.. _Pull Request 2276: https://github.com/galaxyproject/galaxy/pull/2276
.. _Pull Request 2278: https://github.com/galaxyproject/galaxy/pull/2278
.. _Pull Request 2279: https://github.com/galaxyproject/galaxy/pull/2279
.. _Pull Request 2280: https://github.com/galaxyproject/galaxy/pull/2280
.. _Pull Request 2286: https://github.com/galaxyproject/galaxy/pull/2286
.. _Pull Request 2289: https://github.com/galaxyproject/galaxy/pull/2289
.. _Pull Request 2292: https://github.com/galaxyproject/galaxy/pull/2292
.. _Pull Request 2293: https://github.com/galaxyproject/galaxy/pull/2293
.. _Pull Request 2294: https://github.com/galaxyproject/galaxy/pull/2294
.. _Pull Request 2295: https://github.com/galaxyproject/galaxy/pull/2295
.. _Pull Request 2296: https://github.com/galaxyproject/galaxy/pull/2296
.. _Pull Request 2302: https://github.com/galaxyproject/galaxy/pull/2302
.. _Pull Request 2305: https://github.com/galaxyproject/galaxy/pull/2305
.. _Pull Request 2307: https://github.com/galaxyproject/galaxy/pull/2307
.. _Pull Request 2308: https://github.com/galaxyproject/galaxy/pull/2308
.. _Pull Request 2310: https://github.com/galaxyproject/galaxy/pull/2310
.. _Pull Request 2314: https://github.com/galaxyproject/galaxy/pull/2314
.. _Pull Request 2326: https://github.com/galaxyproject/galaxy/pull/2326
.. _Pull Request 2327: https://github.com/galaxyproject/galaxy/pull/2327
.. _Pull Request 2328: https://github.com/galaxyproject/galaxy/pull/2328
.. _Pull Request 2329: https://github.com/galaxyproject/galaxy/pull/2329
.. _Pull Request 2330: https://github.com/galaxyproject/galaxy/pull/2330
.. _Pull Request 2335: https://github.com/galaxyproject/galaxy/pull/2335
.. _Pull Request 2336: https://github.com/galaxyproject/galaxy/pull/2336
.. _Pull Request 2338: https://github.com/galaxyproject/galaxy/pull/2338
.. _Pull Request 2340: https://github.com/galaxyproject/galaxy/pull/2340
.. _Pull Request 2342: https://github.com/galaxyproject/galaxy/pull/2342
.. _Pull Request 2348: https://github.com/galaxyproject/galaxy/pull/2348
.. _Pull Request 2351: https://github.com/galaxyproject/galaxy/pull/2351
.. _Pull Request 2354: https://github.com/galaxyproject/galaxy/pull/2354
.. _Pull Request 2355: https://github.com/galaxyproject/galaxy/pull/2355
.. _Pull Request 2358: https://github.com/galaxyproject/galaxy/pull/2358
.. _Pull Request 2360: https://github.com/galaxyproject/galaxy/pull/2360
.. _Pull Request 2361: https://github.com/galaxyproject/galaxy/pull/2361
.. _Pull Request 2363: https://github.com/galaxyproject/galaxy/pull/2363
.. _Pull Request 2364: https://github.com/galaxyproject/galaxy/pull/2364
.. _Pull Request 2366: https://github.com/galaxyproject/galaxy/pull/2366
.. _Pull Request 2367: https://github.com/galaxyproject/galaxy/pull/2367
.. _Pull Request 2368: https://github.com/galaxyproject/galaxy/pull/2368
.. _Pull Request 2370: https://github.com/galaxyproject/galaxy/pull/2370
.. _Pull Request 2372: https://github.com/galaxyproject/galaxy/pull/2372
.. _Pull Request 2374: https://github.com/galaxyproject/galaxy/pull/2374
.. _Pull Request 2378: https://github.com/galaxyproject/galaxy/pull/2378
.. _Pull Request 2379: https://github.com/galaxyproject/galaxy/pull/2379
.. _Pull Request 2380: https://github.com/galaxyproject/galaxy/pull/2380
.. _Pull Request 2381: https://github.com/galaxyproject/galaxy/pull/2381
.. _Pull Request 2383: https://github.com/galaxyproject/galaxy/pull/2383
.. _Pull Request 2386: https://github.com/galaxyproject/galaxy/pull/2386
.. _Pull Request 2387: https://github.com/galaxyproject/galaxy/pull/2387
.. _Pull Request 2388: https://github.com/galaxyproject/galaxy/pull/2388
.. _Pull Request 2390: https://github.com/galaxyproject/galaxy/pull/2390
.. _Pull Request 2391: https://github.com/galaxyproject/galaxy/pull/2391
.. _Pull Request 2392: https://github.com/galaxyproject/galaxy/pull/2392
.. _Pull Request 2394: https://github.com/galaxyproject/galaxy/pull/2394
.. _Pull Request 2395: https://github.com/galaxyproject/galaxy/pull/2395
.. _Pull Request 2396: https://github.com/galaxyproject/galaxy/pull/2396
.. _Pull Request 2397: https://github.com/galaxyproject/galaxy/pull/2397
.. _Pull Request 2403: https://github.com/galaxyproject/galaxy/pull/2403
.. _Pull Request 2408: https://github.com/galaxyproject/galaxy/pull/2408
.. _Pull Request 2409: https://github.com/galaxyproject/galaxy/pull/2409
.. _Pull Request 2410: https://github.com/galaxyproject/galaxy/pull/2410
.. _Pull Request 2411: https://github.com/galaxyproject/galaxy/pull/2411
.. _Pull Request 2412: https://github.com/galaxyproject/galaxy/pull/2412
.. _Pull Request 2413: https://github.com/galaxyproject/galaxy/pull/2413
.. _Pull Request 2414: https://github.com/galaxyproject/galaxy/pull/2414
.. _Pull Request 2415: https://github.com/galaxyproject/galaxy/pull/2415
.. _Pull Request 2416: https://github.com/galaxyproject/galaxy/pull/2416
.. _Pull Request 2418: https://github.com/galaxyproject/galaxy/pull/2418
.. _Pull Request 2420: https://github.com/galaxyproject/galaxy/pull/2420
.. _Pull Request 2421: https://github.com/galaxyproject/galaxy/pull/2421
.. _Pull Request 2427: https://github.com/galaxyproject/galaxy/pull/2427
.. _Pull Request 2428: https://github.com/galaxyproject/galaxy/pull/2428
.. _Pull Request 2429: https://github.com/galaxyproject/galaxy/pull/2429
.. _Pull Request 2434: https://github.com/galaxyproject/galaxy/pull/2434
.. _Pull Request 2436: https://github.com/galaxyproject/galaxy/pull/2436
.. _Pull Request 2438: https://github.com/galaxyproject/galaxy/pull/2438
.. _Pull Request 2440: https://github.com/galaxyproject/galaxy/pull/2440
.. _Pull Request 2444: https://github.com/galaxyproject/galaxy/pull/2444
.. _Pull Request 2445: https://github.com/galaxyproject/galaxy/pull/2445
.. _Pull Request 2452: https://github.com/galaxyproject/galaxy/pull/2452
.. _Pull Request 2453: https://github.com/galaxyproject/galaxy/pull/2453
.. _Pull Request 2455: https://github.com/galaxyproject/galaxy/pull/2455
.. _Pull Request 2457: https://github.com/galaxyproject/galaxy/pull/2457
.. _Pull Request 2459: https://github.com/galaxyproject/galaxy/pull/2459
.. _Pull Request 2464: https://github.com/galaxyproject/galaxy/pull/2464
.. _Pull Request 2468: https://github.com/galaxyproject/galaxy/pull/2468
.. _Pull Request 2469: https://github.com/galaxyproject/galaxy/pull/2469
.. _Pull Request 2472: https://github.com/galaxyproject/galaxy/pull/2472
.. _Pull Request 2476: https://github.com/galaxyproject/galaxy/pull/2476
.. _Pull Request 2477: https://github.com/galaxyproject/galaxy/pull/2477
.. _Pull Request 2480: https://github.com/galaxyproject/galaxy/pull/2480
.. _Pull Request 2481: https://github.com/galaxyproject/galaxy/pull/2481
.. _Pull Request 2486: https://github.com/galaxyproject/galaxy/pull/2486
.. _Pull Request 2488: https://github.com/galaxyproject/galaxy/pull/2488
.. _Pull Request 2489: https://github.com/galaxyproject/galaxy/pull/2489
.. _Pull Request 2494: https://github.com/galaxyproject/galaxy/pull/2494
.. _Pull Request 2498: https://github.com/galaxyproject/galaxy/pull/2498
.. _Pull Request 2499: https://github.com/galaxyproject/galaxy/pull/2499
.. _Pull Request 2505: https://github.com/galaxyproject/galaxy/pull/2505
.. _Pull Request 2508: https://github.com/galaxyproject/galaxy/pull/2508
.. _Pull Request 2509: https://github.com/galaxyproject/galaxy/pull/2509
.. _Pull Request 2515: https://github.com/galaxyproject/galaxy/pull/2515
.. _Pull Request 2516: https://github.com/galaxyproject/galaxy/pull/2516
.. _Pull Request 2524: https://github.com/galaxyproject/galaxy/pull/2524
.. _Pull Request 2527: https://github.com/galaxyproject/galaxy/pull/2527
.. _Pull Request 2528: https://github.com/galaxyproject/galaxy/pull/2528
.. _Pull Request 2529: https://github.com/galaxyproject/galaxy/pull/2529
.. _Pull Request 2531: https://github.com/galaxyproject/galaxy/pull/2531
.. _Pull Request 2534: https://github.com/galaxyproject/galaxy/pull/2534
.. _Pull Request 2538: https://github.com/galaxyproject/galaxy/pull/2538
.. _Pull Request 2540: https://github.com/galaxyproject/galaxy/pull/2540
.. _Pull Request 2543: https://github.com/galaxyproject/galaxy/pull/2543
.. _Pull Request 2544: https://github.com/galaxyproject/galaxy/pull/2544
.. _Pull Request 2545: https://github.com/galaxyproject/galaxy/pull/2545
.. _Pull Request 2548: https://github.com/galaxyproject/galaxy/pull/2548
.. _Pull Request 2552: https://github.com/galaxyproject/galaxy/pull/2552
.. _Pull Request 2553: https://github.com/galaxyproject/galaxy/pull/2553
.. _Pull Request 2554: https://github.com/galaxyproject/galaxy/pull/2554
.. _Pull Request 2555: https://github.com/galaxyproject/galaxy/pull/2555
.. _Pull Request 2559: https://github.com/galaxyproject/galaxy/pull/2559
.. _Pull Request 2564: https://github.com/galaxyproject/galaxy/pull/2564
.. _Pull Request 2569: https://github.com/galaxyproject/galaxy/pull/2569
.. _Pull Request 2570: https://github.com/galaxyproject/galaxy/pull/2570
.. _Pull Request 2572: https://github.com/galaxyproject/galaxy/pull/2572
.. _Pull Request 2574: https://github.com/galaxyproject/galaxy/pull/2574
.. _Pull Request 2576: https://github.com/galaxyproject/galaxy/pull/2576
.. _Pull Request 2578: https://github.com/galaxyproject/galaxy/pull/2578
.. _Pull Request 2579: https://github.com/galaxyproject/galaxy/pull/2579
.. _Pull Request 2590: https://github.com/galaxyproject/galaxy/pull/2590
.. _Pull Request 2594: https://github.com/galaxyproject/galaxy/pull/2594
.. _Pull Request 2595: https://github.com/galaxyproject/galaxy/pull/2595
.. _Pull Request 2596: https://github.com/galaxyproject/galaxy/pull/2596
.. _Pull Request 2597: https://github.com/galaxyproject/galaxy/pull/2597
.. _Pull Request 2599: https://github.com/galaxyproject/galaxy/pull/2599
.. _Pull Request 2605: https://github.com/galaxyproject/galaxy/pull/2605
.. _Pull Request 2608: https://github.com/galaxyproject/galaxy/pull/2608
.. _Pull Request 2610: https://github.com/galaxyproject/galaxy/pull/2610
.. _Pull Request 2612: https://github.com/galaxyproject/galaxy/pull/2612
.. _Pull Request 2613: https://github.com/galaxyproject/galaxy/pull/2613
.. _Pull Request 2615: https://github.com/galaxyproject/galaxy/pull/2615
.. _Pull Request 2616: https://github.com/galaxyproject/galaxy/pull/2616
.. _Pull Request 2617: https://github.com/galaxyproject/galaxy/pull/2617
.. _Pull Request 2620: https://github.com/galaxyproject/galaxy/pull/2620
.. _Pull Request 2621: https://github.com/galaxyproject/galaxy/pull/2621
.. _Pull Request 2622: https://github.com/galaxyproject/galaxy/pull/2622
.. _Pull Request 2625: https://github.com/galaxyproject/galaxy/pull/2625
.. _Pull Request 2628: https://github.com/galaxyproject/galaxy/pull/2628
.. _Pull Request 2630: https://github.com/galaxyproject/galaxy/pull/2630
.. _Pull Request 2631: https://github.com/galaxyproject/galaxy/pull/2631
.. _Pull Request 2632: https://github.com/galaxyproject/galaxy/pull/2632
.. _Pull Request 2634: https://github.com/galaxyproject/galaxy/pull/2634
.. _Pull Request 2636: https://github.com/galaxyproject/galaxy/pull/2636
.. _Pull Request 2637: https://github.com/galaxyproject/galaxy/pull/2637
.. _Pull Request 2639: https://github.com/galaxyproject/galaxy/pull/2639
.. _Pull Request 2643: https://github.com/galaxyproject/galaxy/pull/2643
.. _Pull Request 2644: https://github.com/galaxyproject/galaxy/pull/2644
.. _Pull Request 2646: https://github.com/galaxyproject/galaxy/pull/2646
.. _Pull Request 2647: https://github.com/galaxyproject/galaxy/pull/2647
.. _Pull Request 2648: https://github.com/galaxyproject/galaxy/pull/2648
.. _Pull Request 2650: https://github.com/galaxyproject/galaxy/pull/2650
.. _Pull Request 2651: https://github.com/galaxyproject/galaxy/pull/2651
.. _Pull Request 2652: https://github.com/galaxyproject/galaxy/pull/2652
.. _Pull Request 2656: https://github.com/galaxyproject/galaxy/pull/2656
.. _Pull Request 2660: https://github.com/galaxyproject/galaxy/pull/2660
.. _Pull Request 2661: https://github.com/galaxyproject/galaxy/pull/2661
.. _Pull Request 2664: https://github.com/galaxyproject/galaxy/pull/2664
.. _Pull Request 2667: https://github.com/galaxyproject/galaxy/pull/2667
.. _Pull Request 2670: https://github.com/galaxyproject/galaxy/pull/2670
.. _Pull Request 2678: https://github.com/galaxyproject/galaxy/pull/2678
.. _Pull Request 2680: https://github.com/galaxyproject/galaxy/pull/2680
.. _Pull Request 2681: https://github.com/galaxyproject/galaxy/pull/2681
.. _Pull Request 2682: https://github.com/galaxyproject/galaxy/pull/2682
.. _Pull Request 2684: https://github.com/galaxyproject/galaxy/pull/2684
.. _Pull Request 2685: https://github.com/galaxyproject/galaxy/pull/2685
.. _Pull Request 2691: https://github.com/galaxyproject/galaxy/pull/2691
.. _Pull Request 2693: https://github.com/galaxyproject/galaxy/pull/2693
.. _Pull Request 2701: https://github.com/galaxyproject/galaxy/pull/2701
.. _Pull Request 2721: https://github.com/galaxyproject/galaxy/pull/2721
.. _Pull Request 2723: https://github.com/galaxyproject/galaxy/pull/2723
.. _Pull Request 2737: https://github.com/galaxyproject/galaxy/pull/2737
.. _Pull Request 2743: https://github.com/galaxyproject/galaxy/pull/2743
.. _Pull Request 2744: https://github.com/galaxyproject/galaxy/pull/2744
.. _Pull Request 2749: https://github.com/galaxyproject/galaxy/pull/2749
.. _Pull Request 2750: https://github.com/galaxyproject/galaxy/pull/2750
.. _Pull Request 2756: https://github.com/galaxyproject/galaxy/pull/2756
.. _Pull Request 2759: https://github.com/galaxyproject/galaxy/pull/2759
.. _Pull Request 2773: https://github.com/galaxyproject/galaxy/pull/2773
.. _Pull Request 2774: https://github.com/galaxyproject/galaxy/pull/2774
.. _Pull Request 2780: https://github.com/galaxyproject/galaxy/pull/2780
.. _Pull Request 2789: https://github.com/galaxyproject/galaxy/pull/2789
.. _Pull Request 2792: https://github.com/galaxyproject/galaxy/pull/2792
.. _Pull Request 2809: https://github.com/galaxyproject/galaxy/pull/2809
.. _Pull Request 2810: https://github.com/galaxyproject/galaxy/pull/2810
+52 -3
View File
@@ -3,8 +3,57 @@
July 2016 Galaxy Release (v 16.07)
===========================================================
.. include:: _header.rst
Schedule
Highlights
===========================================================
* Planned Freeze Date: 2016-07-04
* Planned Release Date: 2016-07-25
**Shift of Galaxy tool dependencies to Conda**
Galaxy admins obtained the ability to install Galaxy tool's
dependencies using the Conda package manager. This is a Beta feature
and we encourage interested deployers to opt-in by modifying configuration.
Documentation that explains this switch and answers FAQ is `available <https://docs.galaxyproject.org/en/master/admin/conda_faq.html>`__.
**Dynamic tool destinations**
Our friends from Canada National Microbiology Laboratory enhanced
Galaxy with feature that allows dynamic mapping of tools to destinations
based on finer grained admin-specified rules. Please see the
`wiki <https://wiki.galaxyproject.org/Admin/Config/Jobs#Dynamic_Destination_Mapping>`__.
Implemented in `PR #2579 <https://github.com/galaxyproject/galaxy/pull/2579>`__
**Galaxy chat**
Admins can now plug in the included communication server to enable
users of their instance to use real-time chat within the Galaxy interface.
Please see the `documentation <https://docs.galaxyproject.org/en/master/admin/chat.html>`__
to learn how to activate and use this feature.
Implemented in `PR #2515 <https://github.com/galaxyproject/galaxy/pull/2515>`__
`Github <https://github.com/galaxyproject/galaxy>`__
===========================================================
New Galaxy repository
.. code-block:: shell
$ git clone -b release_16.07 https://github.com/galaxyproject/galaxy.git
Update of existing Galaxy repository
.. code-block:: shell
$ git checkout release_16.07 && git pull --ff-only origin release_16.07
See `our wiki <https://wiki.galaxyproject.org/Develop/SourceCode>`__ for additional details regarding the source code locations.
Deprecation Notices
===========================================================
The following URLs will be removed and should be considered deprecated:
* ``<galaxy>\history\as_xml``
* ``<galaxy>\history\list_as_xml``
Release Notes
===========================================================
.. include:: 16.07.rst
:start-after: announce_start
.. include:: _thanks.rst
+10
View File
@@ -0,0 +1,10 @@
===========================================================
October 2016 Galaxy Release (v 16.10)
===========================================================
Schedule
===========================================================
* Planned Freeze Date: 2016-10-03
* Planned Release Date: 2016-10-24
-1
View File
@@ -222,7 +222,6 @@ class Configuration( object ):
# Tasked job runner.
self.use_tasked_jobs = string_as_bool( kwargs.get( 'use_tasked_jobs', False ) )
self.local_task_queue_workers = int(kwargs.get("local_task_queue_workers", 2))
self.commands_in_new_shell = string_as_bool( kwargs.get( 'enable_beta_tool_command_isolation', "True" ) )
self.tool_submission_burst_threads = int( kwargs.get( 'tool_submission_burst_threads', '1' ) )
self.tool_submission_burst_at = int( kwargs.get( 'tool_submission_burst_at', '10' ) )
# Enable new interface for API installations from TS.
+12 -12
View File
@@ -16,6 +16,8 @@ from abc import ABCMeta, abstractmethod
from json import loads
from xml.etree import ElementTree
import six
import galaxy
from galaxy import model, util
from galaxy.datatypes import metadata, sniff
@@ -28,11 +30,9 @@ from galaxy.util.bunch import Bunch
from galaxy.util.expressions import ExpressionContext
from galaxy.util.xml_macros import load
from .datasets import (DatasetPath, NullDatasetPathRewriter,
OutputsToWorkingDirectoryPathRewriter, TaskPathRewriter)
from .output_checker import check_output
from .datasets import TaskPathRewriter
from .datasets import OutputsToWorkingDirectoryPathRewriter
from .datasets import NullDatasetPathRewriter
from .datasets import DatasetPath
log = logging.getLogger( __name__ )
@@ -207,7 +207,7 @@ class JobConfiguration( object ):
if not self.handlers:
raise ValueError("Job configuration file defines no valid handler elements.")
# Determine the default handler(s)
self.default_handler_id = self.__get_default(handlers, self.handlers.keys())
self.default_handler_id = self.__get_default(handlers, list(self.handlers.keys()))
# Parse destinations
destinations = root.find('destinations')
@@ -238,7 +238,7 @@ class JobConfiguration( object ):
self.destinations[tag].append(job_destination)
# Determine the default destination
self.default_destination_id = self.__get_default(destinations, self.destinations.keys())
self.default_destination_id = self.__get_default(destinations, list(self.destinations.keys()))
# Parse resources...
resources = root.find('resources')
@@ -777,7 +777,7 @@ class JobWrapper( object ):
if use_persisted_destination:
self.job_runner_mapper.cached_job_destination = JobDestination( from_job=job )
self.__commands_in_new_shell = self.app.config.commands_in_new_shell
self.__commands_in_new_shell = True
self.__user_system_pwent = None
self.__galaxy_system_pwent = None
@@ -1469,8 +1469,8 @@ class JobWrapper( object ):
per_plugin_properties = self.app.job_metrics.collect_properties( job.destination_id, self.job_id, self.working_directory )
if per_plugin_properties:
log.info( "Collecting metrics for %s %s" % ( type(has_metrics).__name__, getattr( has_metrics, 'id', None ) ) )
for plugin, properties in per_plugin_properties.iteritems():
for metric_name, metric_value in properties.iteritems():
for plugin, properties in per_plugin_properties.items():
for metric_name, metric_value in properties.items():
if metric_value is not None:
has_metrics.add_metric( plugin, metric_name, metric_value )
@@ -1554,7 +1554,7 @@ class JobWrapper( object ):
def get_mutable_output_fnames( self ):
if self.output_paths is None:
self.compute_outputs()
return filter( lambda dsp: dsp.mutable, self.output_paths )
return [dsp for dsp in self.output_paths if dsp.mutable]
def get_output_hdas_and_fnames( self ):
if self.output_hdas_and_paths is None:
@@ -1985,11 +1985,11 @@ class TaskWrapper(JobWrapper):
return os.path.join( self.working_directory, os.path.basename( output_path ) )
@six.add_metaclass(ABCMeta)
class ComputeEnvironment( object ):
""" Definition of the job as it will be run on the (potentially) remote
compute server.
"""
__metaclass__ = ABCMeta
@abstractmethod
def output_paths( self ):
@@ -2097,7 +2097,7 @@ class ParallelismInfo(object):
def __init__(self, tag):
self.method = tag.get('method')
if isinstance(tag, dict):
items = tag.iteritems()
items = tag.items()
else:
items = tag.attrib.items()
self.attributes = dict( [ item for item in items if item[ 0 ] != 'method' ])

Some files were not shown because too many files have changed in this diff Show More