galaxy-commits
Threads by month
- ----- 2026 -----
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- 15302 discussions
commit/galaxy-central: nsoranzo: Fix API workflow show for workflows created with history Extract Workflow.
by commits-noreply@bitbucket.org 19 Nov '13
by commits-noreply@bitbucket.org 19 Nov '13
19 Nov '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/e5d2170d26ab/
Changeset: e5d2170d26ab
User: nsoranzo
Date: 2013-11-19 19:36:17
Summary: Fix API workflow show for workflows created with history Extract Workflow.
To reproduce:
1) for an existing history, select "Extract Workflow" from the history menu
2) find the id of the new workflow, e.g. by opening /api/workflows/
3) open /api/workflows/$workflow_id
Result is an Internal Server Error.
In Galaxy log:
galaxy.web.framework ERROR 2013-11-19 12:44:17,367 Uncaught exception in exposed API method:
Traceback (most recent call last):
File "/srv/galaxy/lib/galaxy/web/framework/__init__.py", line 197, in decorator
rval = func( self, trans, *args, **kwargs)
File "/srv/galaxy/lib/galaxy/webapps/galaxy/api/workflows.py", line 77, in show
inputs[step.id] = {'label':step.tool_inputs['name'], 'value':""}
TypeError: 'NoneType' object has no attribute '__getitem__'
Reported-by: Simone Leo <simone.leo(a)crs4.it>
Affected #: 2 files
diff -r f2186f4796ad4c6aa2c9191f9804d8f5d59eb15d -r e5d2170d26ab226d326b80003e8838b2d255d6c4 lib/galaxy/webapps/galaxy/api/workflows.py
--- a/lib/galaxy/webapps/galaxy/api/workflows.py
+++ b/lib/galaxy/webapps/galaxy/api/workflows.py
@@ -73,7 +73,10 @@
inputs = {}
for step in latest_workflow.steps:
if step.type == 'data_input':
- inputs[step.id] = {'label':step.tool_inputs['name'], 'value':""}
+ if step.tool_inputs and "name" in step.tool_inputs:
+ inputs[step.id] = {'label':step.tool_inputs['name'], 'value':""}
+ else:
+ inputs[step.id] = {'label':"Input Dataset", 'value':""}
else:
pass
# Eventually, allow regular tool parameters to be inserted and modified at runtime.
diff -r f2186f4796ad4c6aa2c9191f9804d8f5d59eb15d -r e5d2170d26ab226d326b80003e8838b2d255d6c4 lib/galaxy/webapps/galaxy/controllers/workflow.py
--- a/lib/galaxy/webapps/galaxy/controllers/workflow.py
+++ b/lib/galaxy/webapps/galaxy/controllers/workflow.py
@@ -1223,6 +1223,7 @@
for hid in dataset_ids:
step = model.WorkflowStep()
step.type = 'data_input'
+ step.tool_inputs = dict( name="Input Dataset" )
hid_to_output_pair[ hid ] = ( step, 'output' )
steps.append( step )
# Tool steps
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: carlfeberhard: Remove print from f166a09
by commits-noreply@bitbucket.org 19 Nov '13
by commits-noreply@bitbucket.org 19 Nov '13
19 Nov '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/f2186f4796ad/
Changeset: f2186f4796ad
User: carlfeberhard
Date: 2013-11-19 16:29:38
Summary: Remove print from f166a09
Affected #: 1 file
diff -r f166a093ebe3237d1374c3ebda520f085a85ba1d -r f2186f4796ad4c6aa2c9191f9804d8f5d59eb15d lib/galaxy/visualization/registry.py
--- a/lib/galaxy/visualization/registry.py
+++ b/lib/galaxy/visualization/registry.py
@@ -510,9 +510,6 @@
# result type should tell the registry how to convert the result before the test
test_result_type = test_elem.get( 'result_type', 'string' )
- print
- print test_attr, test_result_type
- print
# test functions should be sent an object to test, and the parsed result expected from the test
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
2 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/22fd4e79f08c/
Changeset: 22fd4e79f08c
User: carlfeberhard
Date: 2013-11-19 16:24:35
Summary: Visualizations API: fix create/update validation
Affected #: 1 file
diff -r b812508869b95cc994d049f724d9475aafd417d9 -r 22fd4e79f08c0185be71fbe37fa43d4aad631e78 lib/galaxy/webapps/galaxy/api/visualizations.py
--- a/lib/galaxy/webapps/galaxy/api/visualizations.py
+++ b/lib/galaxy/webapps/galaxy/api/visualizations.py
@@ -10,7 +10,7 @@
from sqlalchemy import or_
from galaxy import web, util
-from galaxy.web.base.controller import BaseAPIController, UsesVisualizationMixin
+from galaxy.web.base.controller import BaseAPIController, UsesVisualizationMixin, SharableMixin
from galaxy.model.item_attrs import UsesAnnotations
from galaxy.exceptions import ( ItemAccessibilityException, ItemDeletionException, ItemOwnershipException,
MessageException )
@@ -20,7 +20,7 @@
import logging
log = logging.getLogger( __name__ )
-class VisualizationsController( BaseAPIController, UsesVisualizationMixin, UsesAnnotations ):
+class VisualizationsController( BaseAPIController, UsesVisualizationMixin, SharableMixin, UsesAnnotations ):
"""
RESTful controller for interactions with visualizations.
"""
@@ -122,9 +122,10 @@
else:
payload = self._validate_and_parse_payload( payload )
+ vis_type = payload.pop( 'type', False )
payload[ 'save' ] = True
- # create needs defaults like wizard needs food - generate defaults - this will err if given a weird key?
- visualization = self.create_visualization( trans, **payload )
+ # generate defaults - this will err if given a weird key?
+ visualization = self.create_visualization( trans, vis_type, **payload )
rval = { 'id' : trans.security.encode_id( visualization.id ) }
@@ -217,11 +218,20 @@
#TODO: deleted
#TODO: importable
+ # must have a type (I've taken this to be the visualization name)
+ if 'type' not in payload:
+ raise ValueError( "key/value 'type' is required" )
+
validated_payload = {}
for key, val in payload.items():
- if key == 'config':
+ #TODO: validate types in VALID_TYPES/registry names at the mixin/model level?
+ if key == 'type':
+ if not ( isinstance( val, str ) or isinstance( val, unicode ) ):
+ raise ValueError( '%s must be a string or unicode: %s' %( key, str( type( val ) ) ) )
+ val = util.sanitize_html.sanitize_html( val, 'utf-8' )
+ elif key == 'config':
if not isinstance( val, dict ):
- raise ValueError( '%s must be a dictionary (JSON): %s' %( key, str( type( val ) ) ) )
+ raise ValueError( '%s must be a dictionary: %s' %( key, str( type( val ) ) ) )
elif key == 'annotation':
if not ( isinstance( val, str ) or isinstance( val, unicode ) ):
@@ -235,21 +245,16 @@
raise ValueError( '%s must be a string or unicode: %s' %( key, str( type( val ) ) ) )
val = util.sanitize_html.sanitize_html( val, 'utf-8' )
elif key == 'slug':
- if not isinstance( val, str ):
+ if not ( isinstance( val, str ) or isinstance( val, unicode ) ):
raise ValueError( '%s must be a string: %s' %( key, str( type( val ) ) ) )
val = util.sanitize_html.sanitize_html( val, 'utf-8' )
- elif key == 'type':
- if not isinstance( val, str ):
- raise ValueError( '%s must be a string: %s' %( key, str( type( val ) ) ) )
- val = util.sanitize_html.sanitize_html( val, 'utf-8' )
- #TODO: validate types in VALID_TYPES/registry names at the mixin/model level?
elif key == 'dbkey':
if not ( isinstance( val, str ) or isinstance( val, unicode ) ):
raise ValueError( '%s must be a string or unicode: %s' %( key, str( type( val ) ) ) )
val = util.sanitize_html.sanitize_html( val, 'utf-8' )
- elif key not in valid_but_uneditable_keys:
- raise AttributeError( 'unknown key: %s' %( str( key ) ) )
+ #elif key not in valid_but_uneditable_keys:
+ # raise AttributeError( 'unknown key: %s' %( str( key ) ) )
validated_payload[ key ] = val
return validated_payload
https://bitbucket.org/galaxy/galaxy-central/commits/f166a093ebe3/
Changeset: f166a093ebe3
User: carlfeberhard
Date: 2013-11-19 16:26:48
Summary: Visualizations Registry: propery default to str eqv test for test_type, properly call getattr_lambda
Affected #: 1 file
diff -r 22fd4e79f08c0185be71fbe37fa43d4aad631e78 -r f166a093ebe3237d1374c3ebda520f085a85ba1d lib/galaxy/visualization/registry.py
--- a/lib/galaxy/visualization/registry.py
+++ b/lib/galaxy/visualization/registry.py
@@ -477,7 +477,7 @@
return lambda o: getattr( o, next_attr_name )
# recursive case
- return lambda o: getattr( self._build_getattr_lambda( attr_name_list[:-1] ), next_attr_name )
+ return lambda o: getattr( self._build_getattr_lambda( attr_name_list[:-1] )( o ), next_attr_name )
def parse_tests( self, xml_tree_list ):
"""
@@ -493,7 +493,7 @@
return tests
for test_elem in xml_tree_list:
- test_type = test_elem.get( 'type' )
+ test_type = test_elem.get( 'type', 'eq' )
test_result = test_elem.text
if not test_type or not test_result:
log.warn( 'Skipping test. Needs both type attribute and text node to be parsed: '
@@ -509,9 +509,13 @@
getter = self._build_getattr_lambda( test_attr )
# result type should tell the registry how to convert the result before the test
- test_result_type = test_elem.get( 'result_type' ) or 'string'
+ test_result_type = test_elem.get( 'result_type', 'string' )
+ print
+ print test_attr, test_result_type
+ print
# test functions should be sent an object to test, and the parsed result expected from the test
+
# is test_attr attribute an instance of result
if test_type == 'isinstance':
#TODO: wish we could take this further but it would mean passing in the datatypes_registry
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: carlfeberhard: Scatterplot (plugin version): small fixes, move dataset out of config, namespace hbrs templates
by commits-noreply@bitbucket.org 19 Nov '13
by commits-noreply@bitbucket.org 19 Nov '13
19 Nov '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/b812508869b9/
Changeset: b812508869b9
User: carlfeberhard
Date: 2013-11-19 16:19:22
Summary: Scatterplot (plugin version): small fixes, move dataset out of config, namespace hbrs templates
Affected #: 6 files
diff -r aa8204e99326288ea07e1af26c7d3ffd11f0aff1 -r b812508869b95cc994d049f724d9475aafd417d9 config/plugins/visualizations/scatterplot/Gruntfile.js
--- a/config/plugins/visualizations/scatterplot/Gruntfile.js
+++ b/config/plugins/visualizations/scatterplot/Gruntfile.js
@@ -9,7 +9,7 @@
// compile all hb templates into a single file in the build dir
compile: {
options: {
- namespace: 'Templates',
+ namespace: 'scatterplot',
processName : function( filepath ){
return filepath.match( /\w*\.handlebars/ )[0].replace( '.handlebars', '' );
}
diff -r aa8204e99326288ea07e1af26c7d3ffd11f0aff1 -r b812508869b95cc994d049f724d9475aafd417d9 config/plugins/visualizations/scatterplot/src/scatterplot-config-editor.js
--- a/config/plugins/visualizations/scatterplot/src/scatterplot-config-editor.js
+++ b/config/plugins/visualizations/scatterplot/src/scatterplot-config-editor.js
@@ -37,14 +37,19 @@
/** initialize requires a configuration Object containing a dataset Object */
initialize : function( attributes ){
//console.log( this + '.initialize, attributes:', attributes );
- if( !attributes || !attributes.config || !attributes.config.dataset ){
+ if( !attributes || !attributes.config || !attributes.dataset ){
throw new Error( "ScatterplotView requires a configuration and dataset" );
}
- this.dataset = attributes.config.dataset;
+ //console.log( 'config:', attributes.config );
+
+ this.dataset = attributes.dataset;
//console.log( 'dataset:', this.dataset );
+//TODO: ScatterplotView -> ScatterplotDisplay, this.plotView -> this.display
this.plotView = new ScatterplotView({
+ dataset : attributes.dataset,
config : attributes.config
+//TODO: if data
});
},
@@ -197,8 +202,8 @@
// parse the column values for both indeces (for the data fetch) and names (for the chart)
var $dataControls = this.$el.find( '#data-control' );
var settings = {
- xColumn : $dataControls.find( '[name="xColumn"]' ).val(),
- yColumn : $dataControls.find( '[name="yColumn"]' ).val()
+ xColumn : Number( $dataControls.find( '[name="xColumn"]' ).val() ),
+ yColumn : Number( $dataControls.find( '[name="yColumn"]' ).val() )
};
if( $dataControls.find( '#include-id-checkbox' ).prop( 'checked' ) ){
settings.idColumn = $dataControls.find( '[name="idColumn"]' ).val();
@@ -229,9 +234,9 @@
});
ScatterplotConfigEditor.templates = {
- mainLayout : Templates.editor,
- dataControl : Templates.datacontrol,
- chartControl : Templates.chartcontrol
+ mainLayout : scatterplot.editor,
+ dataControl : scatterplot.datacontrol,
+ chartControl : scatterplot.chartcontrol
};
//==============================================================================
diff -r aa8204e99326288ea07e1af26c7d3ffd11f0aff1 -r b812508869b95cc994d049f724d9475aafd417d9 config/plugins/visualizations/scatterplot/src/scatterplot-display.js
--- a/config/plugins/visualizations/scatterplot/src/scatterplot-display.js
+++ b/config/plugins/visualizations/scatterplot/src/scatterplot-display.js
@@ -10,14 +10,10 @@
//TODO: should be a view on visualization(revision) model
defaults : {
- dataset : {
- },
metadata : {
dataLines : undefined
},
- ajaxFn : null,
-
pagination : {
currPage : 0,
perPage : 3000
@@ -48,6 +44,7 @@
initialize : function( attributes ){
this.config = _.extend( _.clone( this.defaults ), attributes.config || {});
+ this.dataset = attributes.dataset;
//console.debug( this + '.config:', this.config );
},
@@ -65,7 +62,7 @@
//console.debug( 'currPage', this.config.pagination.currPage );
var view = this;
//TODO: very tied to datasets - should be generalized eventually
- xhr = jQuery.getJSON( '/api/datasets/' + this.config.dataset.id, {
+ xhr = jQuery.getJSON( '/api/datasets/' + this.dataset.id, {
data_type : 'raw_data',
provider : 'dataset-column',
limit : this.config.pagination.perPage,
@@ -151,7 +148,7 @@
},
renderLineInfo : function( data ){
- var totalLines = this.config.dataset.metadata_data_lines || 'an unknown number of',
+ var totalLines = this.dataset.metadata_data_lines || 'an unknown number of',
lineStart = ( this.config.pagination.currPage * this.config.pagination.perPage ),
lineEnd = lineStart + data.length;
return $( '<p/>' ).addClass( 'scatterplot-data-info' )
@@ -168,9 +165,9 @@
}
//TODO: cache numPages/numLines in config
var view = this,
- dataLines = this.config.dataset.metadata_data_lines,
+ dataLines = this.dataset.metadata_data_lines,
numPages = ( dataLines )?( Math.ceil( dataLines / this.config.pagination.perPage ) ):( undefined );
- //console.debug( 'data:', this.config.dataset.metadata_data_lines, 'numPages:', numPages );
+ //console.debug( 'data:', this.dataset.metadata_data_lines, 'numPages:', numPages );
// prev next buttons
var $prev = makePage$Li( 'Prev' ).click( function(){
@@ -207,9 +204,9 @@
}
//TODO: cache numPages/numLines in config
var view = this,
- dataLines = this.config.dataset.metadata_data_lines,
+ dataLines = this.dataset.metadata_data_lines,
numPages = ( dataLines )?( Math.ceil( dataLines / this.config.pagination.perPage ) ):( undefined );
- //console.debug( 'data:', this.config.dataset.metadata_data_lines, 'numPages:', numPages );
+ //console.debug( 'data:', this.dataset.metadata_data_lines, 'numPages:', numPages );
// page numbers (as separate control)
//var $paginationContainer = $( '<div/>' ).addClass( 'pagination-container' ),
diff -r aa8204e99326288ea07e1af26c7d3ffd11f0aff1 -r b812508869b95cc994d049f724d9475aafd417d9 config/plugins/visualizations/scatterplot/src/visualization-templates.html
--- a/config/plugins/visualizations/scatterplot/src/visualization-templates.html
+++ /dev/null
@@ -1,197 +0,0 @@
-<script type="text/template" class="template-visualization" id="template-visualization-scatterplotControlForm">
-{{! main layout }}
-
-<h1>WHAAAAA?</h1>
-<div class="scatterplot-container chart-container tabbable tabs-left">
- {{! tab buttons/headers using Bootstrap }}
- <ul class="nav nav-tabs">
- {{! start with the data controls as the displayed tab }}
- <li class="active">
- <a title="Use this tab to change which data are used"
- href="#data-control" data-toggle="tab">Data Controls</a>
- </li>
- <li>
- <a title="Use this tab to change how the chart is drawn"
- href="#chart-control" data-toggle="tab" >Chart Controls</a>
- </li>
- <li>
- <a title="This tab will display overall statistics for your data"
- href="#stats-display" data-toggle="tab">Statistics</a>
- </li>
- <li>
- <a title="This tab will display the chart"
- href="#chart-display" data-toggle="tab">Chart</a>
-
- <div id="loading-indicator" style="display: none;">
- <img class="loading-img" src="{{loadingIndicatorImagePath}}" />
- <span class="loading-message">{{message}}</span>
- </div>
- </li>
- </ul>
-
- {{! data form, chart config form, stats, and chart all get their own tab }}
- <div class="tab-content">
- {{! ---------------------------- tab for data settings form }}
- <div id="data-control" class="tab-pane active">
- {{! rendered separately }}
- </div>
-
- {{! ---------------------------- tab for chart graphics control form }}
- <div id="chart-control" class="tab-pane">
- {{! rendered separately }}
- </div>
-
- {{! ---------------------------- tab for data statistics }}
- <div id="stats-display" class="tab-pane">
- <p class="help-text">By column:</p>
- <table id="chart-stats-table">
- <thead><th></th><th>X</th><th>Y</th></thead>
- {{#each stats}}
- <tr><td>{{name}}</td><td>{{xval}}</td><td>{{yval}}</td></tr>
- </tr>
- {{/each}}
- </table>
- </div>
-
- {{! ---------------------------- tab for actual chart }}
- <div id="chart-display" class="tab-pane">
- <svg width="{{width}}" height="{{height}}"></svg>
- </div>
-
- </div>{{! end .tab-content }}
-</div>{{! end .chart-control }}
-</script>
-
-<script type="text/template" class="template-visualization" id="template-visualization-dataControl">
-
- <p class="help-text">
- Use the following controls to change the data used by the chart.
- Use the 'Draw' button to render (or re-render) the chart with the current settings.
- </p>
-
- {{! column selector containers }}
- <div class="column-select">
- <label for="X-select">Data column for X: </label>
- <select name="X" id="X-select">
- {{#each numericColumns}}
- <option value="{{index}}">{{name}}</option>
- {{/each}}
- </select>
- </div>
- <div class="column-select">
- <label for="Y-select">Data column for Y: </label>
- <select name="Y" id="Y-select">
- {{#each numericColumns}}
- <option value="{{index}}">{{name}}</option>
- {{/each}}
- </select>
- </div>
-
- {{! optional id column }}
- <div id="include-id">
- <label for="include-id-checkbox">Include a third column as data point IDs?</label>
- <input type="checkbox" name="include-id" id="include-id-checkbox" />
- <p class="help-text-small">
- These will be displayed (along with the x and y values) when you hover over
- a data point.
- </p>
- </div>
- <div class="column-select" style="display: none">
- <label for="ID-select">Data column for IDs: </label>
- <select name="ID" id="ID-select">
- {{#each allColumns}}
- <option value="{{index}}">{{name}}</option>
- {{/each}}
- </select>
- </div>
-
- {{! if we're using generic column selection names ('column 1') - allow the user to use the first line }}
- <div id="first-line-header" style="display: none;">
- <p>Possible headers: {{ possibleHeaders }}
- </p>
- <label for="first-line-header-checkbox">Use the above as column headers?</label>
- <input type="checkbox" name="include-id" id="first-line-header-checkbox"
- {{#if usePossibleHeaders }}checked="true"{{/if}}/>
- <p class="help-text-small">
- It looks like Galaxy couldn't get proper column headers for this data.
- Would you like to use the column headers above as column names to select columns?
- </p>
- </div>
-
- <input id="render-button" type="button" value="Draw" />
- <div class="clear"></div>
-</script>
-
-<script type="text/template" class="template-visualization" id="template-visualization-chartControl">
- <p class="help-text">
- Use the following controls to how the chart is displayed.
- The slide controls can be moved by the mouse or, if the 'handle' is in focus, your keyboard's arrow keys.
- Move the focus between controls by using the tab or shift+tab keys on your keyboard.
- Use the 'Draw' button to render (or re-render) the chart with the current settings.
- </p>
-
- <div id="datapointSize" class="form-input numeric-slider-input">
- <label for="datapointSize">Size of data point: </label>
- <div class="slider-output">{{datapointSize}}</div>
- <div class="slider"></div>
- <p class="form-help help-text-small">
- Size of the graphic representation of each data point
- </p>
- </div>
-
- <div id="animDuration" class="form-input checkbox-input">
- <label for="animate-chart">Animate chart transitions?: </label>
- <input type="checkbox" id="animate-chart"
- class="checkbox control"{{#if animDuration}} checked="true"{{/if}} />
- <p class="form-help help-text-small">
- Uncheck this to disable the animations used on the chart
- </p>
- </div>
-
- <div id="width" class="form-input numeric-slider-input">
- <label for="width">Chart width: </label>
- <div class="slider-output">{{width}}</div>
- <div class="slider"></div>
- <p class="form-help help-text-small">
- (not including chart margins and axes)
- </p>
- </div>
-
- <div id="height" class="form-input numeric-slider-input">
- <label for="height">Chart height: </label>
- <div class="slider-output">{{height}}</div>
- <div class="slider"></div>
- <p class="form-help help-text-small">
- (not including chart margins and axes)
- </p>
- </div>
-
- <div id="X-axis-label"class="text-input form-input">
- <label for="X-axis-label">Re-label the X axis: </label>
- <input type="text" name="X-axis-label" id="X-axis-label" value="{{xLabel}}" />
- <p class="form-help help-text-small"></p>
- </div>
-
- <div id="Y-axis-label" class="text-input form-input">
- <label for="Y-axis-label">Re-label the Y axis: </label>
- <input type="text" name="Y-axis-label" id="Y-axis-label" value="{{yLabel}}" />
- <p class="form-help help-text-small"></p>
- </div>
-
- <input id="render-button" type="button" value="Draw" />
-</script>
-
-<script type="text/template" class="template-visualization" id="template-visualization-statsDisplay">
- <p class="help-text">By column:</p>
- <table id="chart-stats-table">
- <thead><th></th><th>X</th><th>Y</th></thead>
- {{#each stats}}
- <tr><td>{{name}}</td><td>{{xval}}</td><td>{{yval}}</td></tr>
- </tr>
- {{/each}}
- </table>
-</script>
-
-<script type="text/template" class="template-visualization" id="template-visualization-chartDisplay">
- <svg width="{{width}}" height="{{height}}"></svg>
-</script>
diff -r aa8204e99326288ea07e1af26c7d3ffd11f0aff1 -r b812508869b95cc994d049f724d9475aafd417d9 config/plugins/visualizations/scatterplot/static/scatterplot-edit.js
--- a/config/plugins/visualizations/scatterplot/static/scatterplot-edit.js
+++ b/config/plugins/visualizations/scatterplot/static/scatterplot-edit.js
@@ -1,1 +1,1 @@
-function scatterplot(a,b,c){function d(){var a={v:{},h:{}};return a.v.lines=p.selectAll("line.v-grid-line").data(m.x.ticks(q.x.fn.ticks()[0])),a.v.lines.enter().append("svg:line").classed("grid-line v-grid-line",!0),a.v.lines.attr("x1",m.x).attr("x2",m.x).attr("y1",0).attr("y2",b.height),a.v.lines.exit().remove(),a.h.lines=p.selectAll("line.h-grid-line").data(m.y.ticks(q.y.fn.ticks()[0])),a.h.lines.enter().append("svg:line").classed("grid-line h-grid-line",!0),a.h.lines.attr("x1",0).attr("x2",b.width).attr("y1",m.y).attr("y2",m.y),a.h.lines.exit().remove(),a}function e(){return t.attr("cx",function(a,b){return m.x(j(a,b))}).attr("cy",function(a,b){return m.y(k(a,b))}).style("display","block").filter(function(){var a=d3.select(this).attr("cx"),c=d3.select(this).attr("cy");return 0>a||a>b.width?!0:0>c||c>b.height?!0:!1}).style("display","none")}function f(){q.redraw(),e(),s=d(),$(".chart-info-box").remove(),$(o.node()).trigger("zoom.scatterplot",[])}function g(a,c,d){return c+=8,$(['<div class="chart-info-box" style="position: absolute">',b.idColumn?"<div>"+d[b.idColumn]+"</div>":"","<div>",j(d),"</div>","<div>",k(d),"</div>","</div>"].join("")).css({top:a,left:c,"z-index":2})}var h=function(a,b){return"translate("+a+","+b+")"},i=function(a,b,c){return"rotate("+a+","+b+","+c+")"},j=function(a){return a[b.xColumn]},k=function(a){return a[b.yColumn]},l={x:{extent:d3.extent(c,j)},y:{extent:d3.extent(c,k)}},m={x:d3.scale.linear().domain(l.x.extent).range([0,b.width]),y:d3.scale.linear().domain(l.y.extent).range([b.height,0])},n=d3.behavior.zoom().x(m.x).y(m.y).scaleExtent([1,10]),o=d3.select(a).attr("class","scatterplot").attr("width","100%").attr("height",b.height+(b.margin.top+b.margin.bottom)),p=o.append("g").attr("class","content").attr("transform",h(b.margin.left,b.margin.top)).call(n);p.append("rect").attr("class","zoom-rect").attr("width",b.width).attr("height",b.height).style("fill","transparent");var q={x:{},y:{}};q.x.fn=d3.svg.axis().orient("bottom").scale(m.x).ticks(b.x.ticks).tickFormat(d3.format("s")),q.y.fn=d3.svg.axis().orient("left").scale(m.y).ticks(b.y.ticks).tickFormat(d3.format("s")),q.x.g=p.append("g").attr("class","x axis").attr("transform",h(0,b.height)).call(q.x.fn),q.y.g=p.append("g").attr("class","y axis").call(q.y.fn);var r=4;q.x.label=o.append("text").attr("class","axis-label").text(b.x.label).attr("text-anchor","middle").attr("dominant-baseline","text-after-edge").attr("x",b.width/2+b.margin.left).attr("y",b.height+b.margin.bottom+b.margin.top-r),q.y.label=o.append("text").attr("class","axis-label").text(b.y.label).attr("text-anchor","middle").attr("dominant-baseline","text-before-edge").attr("x",r).attr("y",b.height/2).attr("transform",i(-90,r,b.height/2)),q.redraw=function(){o.select(".x.axis").call(q.x.fn),o.select(".y.axis").call(q.y.fn)};var s=d(),t=p.selectAll(".glyph").data(c).enter().append("svg:circle").classed("glyph",!0).attr("cx",function(a,b){return m.x(j(a,b))}).attr("cy",b.height).attr("r",0);t.transition().duration(b.animDuration).attr("cy",function(a,b){return m.y(k(a,b))}).attr("r",b.datapointSize),n.on("zoom",f),t.on("mouseover",function(a,c){var d=d3.select(this);d.style("fill","red").style("fill-opacity",1),p.append("line").attr("stroke","red").attr("stroke-width",1).attr("x1",d.attr("cx")-b.datapointSize).attr("y1",d.attr("cy")).attr("x2",0).attr("y2",d.attr("cy")).classed("hoverline",!0),d.attr("cy")<b.height&&p.append("line").attr("stroke","red").attr("stroke-width",1).attr("x1",d.attr("cx")).attr("y1",+d.attr("cy")+b.datapointSize).attr("x2",d.attr("cx")).attr("y2",b.height).classed("hoverline",!0);var e=this.getBoundingClientRect();$("body").append(g(e.top,e.right,a)),$(o.node()).trigger("mouseover-datapoint.scatterplot",[this,a,c])}),t.on("mouseout",function(){d3.select(this).style("fill","black").style("fill-opacity",.2),p.selectAll(".hoverline").remove(),$(".chart-info-box").remove()})}this.Templates=this.Templates||{},this.Templates.chartcontrol=Handlebars.template(function(a,b,c,d,e){this.compilerInfo=[4,">= 1.0.0"],c=this.merge(c,a.helpers),e=e||{};var f,g="",h="function",i=this.escapeExpression;return g+='<p class="help-text">\n Use the following controls to how the chart is displayed.\n The slide controls can be moved by the mouse or, if the \'handle\' is in focus, your keyboard\'s arrow keys.\n Move the focus between controls by using the tab or shift+tab keys on your keyboard.\n Use the \'Draw\' button to render (or re-render) the chart with the current settings.\n</p>\n\n<div data-config-key="datapointSize" class="form-input numeric-slider-input">\n <label for="datapointSize">Size of data point: </label>\n <div class="slider-output">',(f=c.datapointSize)?f=f.call(b,{hash:{},data:e}):(f=b.datapointSize,f=typeof f===h?f.apply(b):f),g+=i(f)+'</div>\n <div class="slider"></div>\n <p class="form-help help-text-small">\n Size of the graphic representation of each data point\n </p>\n</div>\n\n<div data-config-key="width" class="form-input numeric-slider-input">\n <label for="width">Chart width: </label>\n <div class="slider-output">',(f=c.width)?f=f.call(b,{hash:{},data:e}):(f=b.width,f=typeof f===h?f.apply(b):f),g+=i(f)+'</div>\n <div class="slider"></div>\n <p class="form-help help-text-small">\n (not including chart margins and axes)\n </p>\n</div>\n\n<div data-config-key="height" class="form-input numeric-slider-input">\n <label for="height">Chart height: </label>\n <div class="slider-output">',(f=c.height)?f=f.call(b,{hash:{},data:e}):(f=b.height,f=typeof f===h?f.apply(b):f),g+=i(f)+'</div>\n <div class="slider"></div>\n <p class="form-help help-text-small">\n (not including chart margins and axes)\n </p>\n</div>\n\n<div data-config-key="X-axis-label"class="text-input form-input">\n <label for="X-axis-label">Re-label the X axis: </label>\n <input type="text" name="X-axis-label" id="X-axis-label" value="'+i((f=b.x,f=null==f||f===!1?f:f.label,typeof f===h?f.apply(b):f))+'" />\n <p class="form-help help-text-small"></p>\n</div>\n\n<div data-config-key="Y-axis-label" class="text-input form-input">\n <label for="Y-axis-label">Re-label the Y axis: </label>\n <input type="text" name="Y-axis-label" id="Y-axis-label" value="'+i((f=b.y,f=null==f||f===!1?f:f.label,typeof f===h?f.apply(b):f))+'" />\n <p class="form-help help-text-small"></p>\n</div>\n\n<button class="render-button btn btn-primary active">Draw</button>\n'}),this.Templates.datacontrol=Handlebars.template(function(a,b,c,d,e){function f(a,b){var d,e="";return e+='\n <option value="',(d=c.index)?d=d.call(a,{hash:{},data:b}):(d=a.index,d=typeof d===j?d.apply(a):d),e+=k(d)+'">',(d=c.name)?d=d.call(a,{hash:{},data:b}):(d=a.name,d=typeof d===j?d.apply(a):d),e+=k(d)+"</option>\n "}function g(){return'checked="true"'}this.compilerInfo=[4,">= 1.0.0"],c=this.merge(c,a.helpers),e=e||{};var h,i="",j="function",k=this.escapeExpression,l=this;return i+='<p class="help-text">\n Use the following controls to change the data used by the chart.\n Use the \'Draw\' button to render (or re-render) the chart with the current settings.\n</p>\n\n\n<div class="column-select">\n <label>Data column for X: </label>\n <select name="xColumn">\n ',h=c.each.call(b,b.numericColumns,{hash:{},inverse:l.noop,fn:l.program(1,f,e),data:e}),(h||0===h)&&(i+=h),i+='\n </select>\n</div>\n<div class="column-select">\n <label>Data column for Y: </label>\n <select name="yColumn">\n ',h=c.each.call(b,b.numericColumns,{hash:{},inverse:l.noop,fn:l.program(1,f,e),data:e}),(h||0===h)&&(i+=h),i+='\n </select>\n</div>\n\n\n<div id="include-id">\n <label for="include-id-checkbox">Include a third column as data point IDs?</label>\n <input type="checkbox" name="include-id" id="include-id-checkbox" />\n <p class="help-text-small">\n These will be displayed (along with the x and y values) when you hover over\n a data point.\n </p>\n</div>\n<div class="column-select" style="display: none">\n <label for="ID-select">Data column for IDs: </label>\n <select name="idColumn">\n ',h=c.each.call(b,b.allColumns,{hash:{},inverse:l.noop,fn:l.program(1,f,e),data:e}),(h||0===h)&&(i+=h),i+='\n </select>\n</div>\n\n\n<div id="first-line-header" style="display: none;">\n <p>Possible headers: ',(h=c.possibleHeaders)?h=h.call(b,{hash:{},data:e}):(h=b.possibleHeaders,h=typeof h===j?h.apply(b):h),i+=k(h)+'\n </p>\n <label for="first-line-header-checkbox">Use the above as column headers?</label>\n <input type="checkbox" name="include-id" id="first-line-header-checkbox"\n ',h=c["if"].call(b,b.usePossibleHeaders,{hash:{},inverse:l.noop,fn:l.program(3,g,e),data:e}),(h||0===h)&&(i+=h),i+='/>\n <p class="help-text-small">\n It looks like Galaxy couldn\'t get proper column headers for this data.\n Would you like to use the column headers above as column names to select columns?\n </p>\n</div>\n\n<button class="render-button btn btn-primary active">Draw</button>\n'}),this.Templates.editor=Handlebars.template(function(a,b,c,d,e){this.compilerInfo=[4,">= 1.0.0"],c=this.merge(c,a.helpers),e=e||{};var f="";return f+='<div class="scatterplot-editor tabbable tabs-left">\n \n <ul class="nav nav-tabs">\n \n <li class="active">\n <a title="Use this tab to change which data are used"\n href="#data-control" data-toggle="tab">Data Controls</a>\n </li>\n <li>\n <a title="Use this tab to change how the chart is drawn"\n href="#chart-control" data-toggle="tab" >Chart Controls</a>\n </li>\n \n <li class="disabled">\n <a title="This tab will display the chart"\n href="#chart-display" data-toggle="tab">Chart</a>\n </li>\n </ul>\n\n \n <div class="tab-content">\n \n <div id="data-control" class="scatterplot-config-control tab-pane active">\n \n </div>\n \n \n <div id="chart-control" class="scatterplot-config-control tab-pane">\n \n </div>\n\n \n <div id="chart-display" class="scatterplot-display tab-pane"></div>\n\n </div>\n</div>\n'});var ScatterplotConfigEditor=BaseView.extend(LoggableMixin).extend({className:"scatterplot-control-form",initialize:function(a){if(!a||!a.config||!a.config.dataset)throw new Error("ScatterplotView requires a configuration and dataset");this.dataset=a.config.dataset,this.plotView=new ScatterplotView({config:a.config})},render:function(){return this.$el.append(ScatterplotConfigEditor.templates.mainLayout({})),this.$el.find("#data-control").append(this._render_dataControl()),this._render_chartControls(this.$el.find("#chart-control")),this._render_chartDisplay(),this.$el.find("[title]").tooltip(),this},_render_dataControl:function(){var a=this.dataset,b=_.map(a.metadata_column_types,function(b,c){var d={index:c,type:b,name:"column "+(c+1)};return a.metadata_column_names&&a.metadata_column_names[c]&&(d.name=a.metadata_column_names[c]),d}),c=_.filter(b,function(a){return"int"===a.type||"float"===a.type});2>c&&(c=b);var d=this.$el.find(".tab-pane#data-control");return d.html(ScatterplotConfigEditor.templates.dataControl({allColumns:b,numericColumns:c})),d.find('[name="xColumn"]').val(this.plotView.config.xColumn||c[0].index),d.find('[name="yColumn"]').val(this.plotView.config.yColumn||c[1].index),void 0!==this.plotView.config.idColumn&&(d.find("#include-id-checkbox").prop("checked",!0).trigger("change"),d.find('select[name="idColumn"]').val(this.plotView.config.idColumn)),d},_render_chartControls:function(a){function b(){var a=$(this);a.siblings(".slider-output").text(a.slider("value"))}a.html(ScatterplotConfigEditor.templates.chartControl(this.plotView.config));var c=this,d={datapointSize:{min:2,max:10,step:1},width:{min:200,max:800,step:20},height:{min:200,max:800,step:20}};return a.find(".numeric-slider-input").each(function(){var a=$(this),e=a.attr("data-config-key"),f=_.extend(d[e],{value:c.plotView.config[e],change:b,slide:b});a.find(".slider").slider(f)}),this.dataset.metadata_column_names,a},_render_chartDisplay:function(){var a=this.$el.find(".tab-pane#chart-display");return this.plotView.setElement(a),this.plotView.render(),a},events:{"change #include-id-checkbox":"toggleThirdColumnSelector","click #data-control .render-button":"renderChart","click #chart-control .render-button":"renderChart"},toggleThirdColumnSelector:function(){this.$el.find('select[name="idColumn"]').parent().toggle()},renderChart:function(){this.$el.find(".nav li.disabled").removeClass("disabled"),this.updateConfigWithDataSettings(),this.updateConfigWithChartSettings(),this.$el.find("ul.nav").find('a[href="#chart-display"]').tab("show"),this.plotView.fetchData()},updateConfigWithDataSettings:function(){var a=this.$el.find("#data-control"),b={xColumn:a.find('[name="xColumn"]').val(),yColumn:a.find('[name="yColumn"]').val()};return a.find("#include-id-checkbox").prop("checked")&&(b.idColumn=a.find('[name="idColumn"]').val()),_.extend(this.plotView.config,b)},updateConfigWithChartSettings:function(){var a=this.plotView,b=this.$el.find("#chart-control");return["datapointSize","width","height"].forEach(function(c){a.config[c]=b.find('.numeric-slider-input[data-config-key="'+c+'"]').find(".slider").slider("value")}),a.config.x.label=b.find('input[name="X-axis-label"]').val(),a.config.y.label=b.find('input[name="Y-axis-label"]').val(),a.config},toString:function(){return"ScatterplotConfigEditor("+(this.dataset?this.dataset.id:"")+")"}});ScatterplotConfigEditor.templates={mainLayout:Templates.editor,dataControl:Templates.datacontrol,chartControl:Templates.chartcontrol};var ScatterplotView=Backbone.View.extend({defaults:{dataset:{},metadata:{dataLines:void 0},ajaxFn:null,pagination:{currPage:0,perPage:3e3},width:400,height:400,margin:{top:16,right:16,bottom:40,left:54},x:{ticks:10,label:"X"},y:{ticks:10,label:"Y"},datapointSize:4,animDuration:500},initialize:function(a){this.config=_.extend(_.clone(this.defaults),a.config||{})},updateConfig:function(a){this.config=this.config||{},_.extend(this.config,a)},fetchData:function(){this.showLoadingIndicator("getting data");var a=this;return xhr=jQuery.getJSON("/api/datasets/"+this.config.dataset.id,{data_type:"raw_data",provider:"dataset-column",limit:this.config.pagination.perPage,offset:this.config.pagination.currPage*this.config.pagination.perPage}),xhr.done(function(b){a.renderData(b.data)}),xhr.fail(function(a,b,c){alert("Error loading data:\n"+a.responseText),console.error(a,b,c)}),xhr.always(function(){a.hideLoadingIndicator()}),xhr},render:function(a){return this.$el.addClass("scatterplot-display").html(['<div class="controls clear"></div>','<div class="loading-indicator">','<span class="fa fa-spinner fa-spin"></span>','<span class="loading-indicator-message"></span>',"</div>","<svg/>",'<div class="stats-display"></div>'].join("")),this.$el.children().hide(),a&&this.renderData(a),this},showLoadingIndicator:function(a,b){a=a||"",b=b||"fast";var c=this.$el.find(".loading-indicator");a&&c.find(".loading-indicator-message").text(a),c.is(":visible")||(this.toggleStats(!1),c.css({left:this.config.width/2,top:this.config.height/2}).show())},hideLoadingIndicator:function(a){a=a||"fast",this.$el.find(".loading-indicator").hide()},renderData:function(a){this.$el.find(".controls").empty().append(this.renderControls(a)).show(),this.renderPlot(a),this.getStats(a)},renderControls:function(a){var b=this,c=$('<div class="left"></div>'),d=$('<div class="right"></div>');return c.append([this.renderPrevNext(a),this.renderPagination(a)]),d.append([this.renderLineInfo(a),$("<button>Stats</button>").addClass("stats-toggle-btn").click(function(){b.toggleStats()}),$("<button>Redraw</button>").addClass("rerender-btn").click(function(){b.renderPlot(a)})]),[c,d]},renderLineInfo:function(a){var b=this.config.dataset.metadata_data_lines||"an unknown number of",c=this.config.pagination.currPage*this.config.pagination.perPage,d=c+a.length;return $("<p/>").addClass("scatterplot-data-info").text(["Displaying lines",c+1,"to",d,"of",b,"lines"].join(" "))},renderPrevNext:function(a){function b(a){return $(['<li><a href="javascript:void(0);">',a,"</a></li>"].join(""))}if(!a||0===this.config.pagination.currPage&&a.length<this.config.pagination.perPage)return null;var c=this,d=this.config.dataset.metadata_data_lines,e=d?Math.ceil(d/this.config.pagination.perPage):void 0,f=b("Prev").click(function(){c.config.pagination.currPage>0&&(c.config.pagination.currPage-=1,c.fetchData())}),g=b("Next").click(function(){(!e||c.config.pagination.currPage<e-1)&&(c.config.pagination.currPage+=1,c.fetchData())}),h=$("<ul/>").addClass("pagination data-prev-next").append([f,g]);return 0===c.config.pagination.currPage&&f.addClass("disabled"),e&&c.config.pagination.currPage===e-1&&g.addClass("disabled"),h},renderPagination:function(a){function b(a){return $(['<li><a href="javascript:void(0);">',a,"</a></li>"].join(""))}function c(){d.config.pagination.currPage=$(this).data("page"),d.fetchData()}if(!a||0===this.config.pagination.currPage&&a.length<this.config.pagination.perPage)return null;for(var d=this,e=this.config.dataset.metadata_data_lines,f=e?Math.ceil(e/this.config.pagination.perPage):void 0,g=$("<ul/>").addClass("pagination data-pages"),h=0;f>h;h+=1){var i=b(h+1).attr("data-page",h).click(c);h===this.config.pagination.currPage&&i.addClass("active"),g.append(i)}return g},renderPlot:function(a){this.toggleStats(!1);var b=this.$el.find("svg");b.off().empty().show(),scatterplot(b.get(0),this.config,a)},getStats:function(a){var b=this;meanWorker=new Worker("/plugins/visualizations/scatterplot/static/worker-stats.js"),meanWorker.postMessage({data:a,keys:[this.config.xColumn,this.config.yColumn]}),meanWorker.onerror=function(){meanWorker.terminate()},meanWorker.onmessage=function(a){b.renderStats(a.data)}},renderStats:function(a){var b=this.$el.find(".stats-display"),c=this.config.x.label,d=this.config.y.label,e=$("<table/>").addClass("table").append(["<thead><th></th><th>",c,"</th><th>",d,"</th></thead>"].join("")).append(_.map(a,function(a,b){return $(["<tr><td>",b,"</td><td>",a[0],"</td><td>",a[1],"</td></tr>"].join(""))}));b.empty().append(e)},toggleStats:function(a){var b=this.$el.find(".stats-display");a=void 0===a?b.is(":hidden"):a,a?(this.$el.find("svg").hide(),b.show(),this.$el.find(".controls .stats-toggle-btn").text("Plot")):(b.hide(),this.$el.find("svg").show(),this.$el.find(".controls .stats-toggle-btn").text("Stats"))},toString:function(){return"ScatterplotView()"}});
\ No newline at end of file
+function scatterplot(a,b,c){function d(){var a={v:{},h:{}};return a.v.lines=p.selectAll("line.v-grid-line").data(m.x.ticks(q.x.fn.ticks()[0])),a.v.lines.enter().append("svg:line").classed("grid-line v-grid-line",!0),a.v.lines.attr("x1",m.x).attr("x2",m.x).attr("y1",0).attr("y2",b.height),a.v.lines.exit().remove(),a.h.lines=p.selectAll("line.h-grid-line").data(m.y.ticks(q.y.fn.ticks()[0])),a.h.lines.enter().append("svg:line").classed("grid-line h-grid-line",!0),a.h.lines.attr("x1",0).attr("x2",b.width).attr("y1",m.y).attr("y2",m.y),a.h.lines.exit().remove(),a}function e(){return t.attr("cx",function(a,b){return m.x(j(a,b))}).attr("cy",function(a,b){return m.y(k(a,b))}).style("display","block").filter(function(){var a=d3.select(this).attr("cx"),c=d3.select(this).attr("cy");return 0>a||a>b.width?!0:0>c||c>b.height?!0:!1}).style("display","none")}function f(){q.redraw(),e(),s=d(),$(".chart-info-box").remove(),$(o.node()).trigger("zoom.scatterplot",[])}function g(a,c,d){return c+=8,$(['<div class="chart-info-box" style="position: absolute">',b.idColumn?"<div>"+d[b.idColumn]+"</div>":"","<div>",j(d),"</div>","<div>",k(d),"</div>","</div>"].join("")).css({top:a,left:c,"z-index":2})}var h=function(a,b){return"translate("+a+","+b+")"},i=function(a,b,c){return"rotate("+a+","+b+","+c+")"},j=function(a){return a[b.xColumn]},k=function(a){return a[b.yColumn]},l={x:{extent:d3.extent(c,j)},y:{extent:d3.extent(c,k)}},m={x:d3.scale.linear().domain(l.x.extent).range([0,b.width]),y:d3.scale.linear().domain(l.y.extent).range([b.height,0])},n=d3.behavior.zoom().x(m.x).y(m.y).scaleExtent([1,10]),o=d3.select(a).attr("class","scatterplot").attr("width","100%").attr("height",b.height+(b.margin.top+b.margin.bottom)),p=o.append("g").attr("class","content").attr("transform",h(b.margin.left,b.margin.top)).call(n);p.append("rect").attr("class","zoom-rect").attr("width",b.width).attr("height",b.height).style("fill","transparent");var q={x:{},y:{}};q.x.fn=d3.svg.axis().orient("bottom").scale(m.x).ticks(b.x.ticks).tickFormat(d3.format("s")),q.y.fn=d3.svg.axis().orient("left").scale(m.y).ticks(b.y.ticks).tickFormat(d3.format("s")),q.x.g=p.append("g").attr("class","x axis").attr("transform",h(0,b.height)).call(q.x.fn),q.y.g=p.append("g").attr("class","y axis").call(q.y.fn);var r=4;q.x.label=o.append("text").attr("class","axis-label").text(b.x.label).attr("text-anchor","middle").attr("dominant-baseline","text-after-edge").attr("x",b.width/2+b.margin.left).attr("y",b.height+b.margin.bottom+b.margin.top-r),q.y.label=o.append("text").attr("class","axis-label").text(b.y.label).attr("text-anchor","middle").attr("dominant-baseline","text-before-edge").attr("x",r).attr("y",b.height/2).attr("transform",i(-90,r,b.height/2)),q.redraw=function(){o.select(".x.axis").call(q.x.fn),o.select(".y.axis").call(q.y.fn)};var s=d(),t=p.selectAll(".glyph").data(c).enter().append("svg:circle").classed("glyph",!0).attr("cx",function(a,b){return m.x(j(a,b))}).attr("cy",b.height).attr("r",0);t.transition().duration(b.animDuration).attr("cy",function(a,b){return m.y(k(a,b))}).attr("r",b.datapointSize),n.on("zoom",f),t.on("mouseover",function(a,c){var d=d3.select(this);d.style("fill","red").style("fill-opacity",1),p.append("line").attr("stroke","red").attr("stroke-width",1).attr("x1",d.attr("cx")-b.datapointSize).attr("y1",d.attr("cy")).attr("x2",0).attr("y2",d.attr("cy")).classed("hoverline",!0),d.attr("cy")<b.height&&p.append("line").attr("stroke","red").attr("stroke-width",1).attr("x1",d.attr("cx")).attr("y1",+d.attr("cy")+b.datapointSize).attr("x2",d.attr("cx")).attr("y2",b.height).classed("hoverline",!0);var e=this.getBoundingClientRect();$("body").append(g(e.top,e.right,a)),$(o.node()).trigger("mouseover-datapoint.scatterplot",[this,a,c])}),t.on("mouseout",function(){d3.select(this).style("fill","black").style("fill-opacity",.2),p.selectAll(".hoverline").remove(),$(".chart-info-box").remove()})}this.Templates=this.Templates||{},this.Templates.chartcontrol=Handlebars.template(function(a,b,c,d,e){this.compilerInfo=[4,">= 1.0.0"],c=this.merge(c,a.helpers),e=e||{};var f,g="",h="function",i=this.escapeExpression;return g+='<p class="help-text">\n Use the following controls to how the chart is displayed.\n The slide controls can be moved by the mouse or, if the \'handle\' is in focus, your keyboard\'s arrow keys.\n Move the focus between controls by using the tab or shift+tab keys on your keyboard.\n Use the \'Draw\' button to render (or re-render) the chart with the current settings.\n</p>\n\n<div data-config-key="datapointSize" class="form-input numeric-slider-input">\n <label for="datapointSize">Size of data point: </label>\n <div class="slider-output">',(f=c.datapointSize)?f=f.call(b,{hash:{},data:e}):(f=b.datapointSize,f=typeof f===h?f.apply(b):f),g+=i(f)+'</div>\n <div class="slider"></div>\n <p class="form-help help-text-small">\n Size of the graphic representation of each data point\n </p>\n</div>\n\n<div data-config-key="width" class="form-input numeric-slider-input">\n <label for="width">Chart width: </label>\n <div class="slider-output">',(f=c.width)?f=f.call(b,{hash:{},data:e}):(f=b.width,f=typeof f===h?f.apply(b):f),g+=i(f)+'</div>\n <div class="slider"></div>\n <p class="form-help help-text-small">\n (not including chart margins and axes)\n </p>\n</div>\n\n<div data-config-key="height" class="form-input numeric-slider-input">\n <label for="height">Chart height: </label>\n <div class="slider-output">',(f=c.height)?f=f.call(b,{hash:{},data:e}):(f=b.height,f=typeof f===h?f.apply(b):f),g+=i(f)+'</div>\n <div class="slider"></div>\n <p class="form-help help-text-small">\n (not including chart margins and axes)\n </p>\n</div>\n\n<div data-config-key="X-axis-label"class="text-input form-input">\n <label for="X-axis-label">Re-label the X axis: </label>\n <input type="text" name="X-axis-label" id="X-axis-label" value="'+i((f=b.x,f=null==f||f===!1?f:f.label,typeof f===h?f.apply(b):f))+'" />\n <p class="form-help help-text-small"></p>\n</div>\n\n<div data-config-key="Y-axis-label" class="text-input form-input">\n <label for="Y-axis-label">Re-label the Y axis: </label>\n <input type="text" name="Y-axis-label" id="Y-axis-label" value="'+i((f=b.y,f=null==f||f===!1?f:f.label,typeof f===h?f.apply(b):f))+'" />\n <p class="form-help help-text-small"></p>\n</div>\n\n<button class="render-button btn btn-primary active">Draw</button>\n'}),this.Templates.datacontrol=Handlebars.template(function(a,b,c,d,e){function f(a,b){var d,e="";return e+='\n <option value="',(d=c.index)?d=d.call(a,{hash:{},data:b}):(d=a.index,d=typeof d===j?d.apply(a):d),e+=k(d)+'">',(d=c.name)?d=d.call(a,{hash:{},data:b}):(d=a.name,d=typeof d===j?d.apply(a):d),e+=k(d)+"</option>\n "}function g(){return'checked="true"'}this.compilerInfo=[4,">= 1.0.0"],c=this.merge(c,a.helpers),e=e||{};var h,i="",j="function",k=this.escapeExpression,l=this;return i+='<p class="help-text">\n Use the following controls to change the data used by the chart.\n Use the \'Draw\' button to render (or re-render) the chart with the current settings.\n</p>\n\n\n<div class="column-select">\n <label>Data column for X: </label>\n <select name="xColumn">\n ',h=c.each.call(b,b.numericColumns,{hash:{},inverse:l.noop,fn:l.program(1,f,e),data:e}),(h||0===h)&&(i+=h),i+='\n </select>\n</div>\n<div class="column-select">\n <label>Data column for Y: </label>\n <select name="yColumn">\n ',h=c.each.call(b,b.numericColumns,{hash:{},inverse:l.noop,fn:l.program(1,f,e),data:e}),(h||0===h)&&(i+=h),i+='\n </select>\n</div>\n\n\n<div id="include-id">\n <label for="include-id-checkbox">Include a third column as data point IDs?</label>\n <input type="checkbox" name="include-id" id="include-id-checkbox" />\n <p class="help-text-small">\n These will be displayed (along with the x and y values) when you hover over\n a data point.\n </p>\n</div>\n<div class="column-select" style="display: none">\n <label for="ID-select">Data column for IDs: </label>\n <select name="idColumn">\n ',h=c.each.call(b,b.allColumns,{hash:{},inverse:l.noop,fn:l.program(1,f,e),data:e}),(h||0===h)&&(i+=h),i+='\n </select>\n</div>\n\n\n<div id="first-line-header" style="display: none;">\n <p>Possible headers: ',(h=c.possibleHeaders)?h=h.call(b,{hash:{},data:e}):(h=b.possibleHeaders,h=typeof h===j?h.apply(b):h),i+=k(h)+'\n </p>\n <label for="first-line-header-checkbox">Use the above as column headers?</label>\n <input type="checkbox" name="include-id" id="first-line-header-checkbox"\n ',h=c["if"].call(b,b.usePossibleHeaders,{hash:{},inverse:l.noop,fn:l.program(3,g,e),data:e}),(h||0===h)&&(i+=h),i+='/>\n <p class="help-text-small">\n It looks like Galaxy couldn\'t get proper column headers for this data.\n Would you like to use the column headers above as column names to select columns?\n </p>\n</div>\n\n<button class="render-button btn btn-primary active">Draw</button>\n'}),this.Templates.editor=Handlebars.template(function(a,b,c,d,e){this.compilerInfo=[4,">= 1.0.0"],c=this.merge(c,a.helpers),e=e||{};var f="";return f+='<div class="scatterplot-editor tabbable tabs-left">\n \n <ul class="nav nav-tabs">\n \n <li class="active">\n <a title="Use this tab to change which data are used"\n href="#data-control" data-toggle="tab">Data Controls</a>\n </li>\n <li>\n <a title="Use this tab to change how the chart is drawn"\n href="#chart-control" data-toggle="tab" >Chart Controls</a>\n </li>\n \n <li class="disabled">\n <a title="This tab will display the chart"\n href="#chart-display" data-toggle="tab">Chart</a>\n </li>\n </ul>\n\n \n <div class="tab-content">\n \n <div id="data-control" class="scatterplot-config-control tab-pane active">\n \n </div>\n \n \n <div id="chart-control" class="scatterplot-config-control tab-pane">\n \n </div>\n\n \n <div id="chart-display" class="scatterplot-display tab-pane"></div>\n\n </div>\n</div>\n'});var ScatterplotConfigEditor=BaseView.extend(LoggableMixin).extend({className:"scatterplot-control-form",initialize:function(a){if(!a||!a.config||!a.dataset)throw new Error("ScatterplotView requires a configuration and dataset");this.dataset=a.dataset,this.plotView=new ScatterplotView({dataset:a.dataset,config:a.config})},render:function(){return this.$el.append(ScatterplotConfigEditor.templates.mainLayout({})),this.$el.find("#data-control").append(this._render_dataControl()),this._render_chartControls(this.$el.find("#chart-control")),this._render_chartDisplay(),this.$el.find("[title]").tooltip(),this},_render_dataControl:function(){var a=this.dataset,b=_.map(a.metadata_column_types,function(b,c){var d={index:c,type:b,name:"column "+(c+1)};return a.metadata_column_names&&a.metadata_column_names[c]&&(d.name=a.metadata_column_names[c]),d}),c=_.filter(b,function(a){return"int"===a.type||"float"===a.type});2>c&&(c=b);var d=this.$el.find(".tab-pane#data-control");return d.html(ScatterplotConfigEditor.templates.dataControl({allColumns:b,numericColumns:c})),d.find('[name="xColumn"]').val(this.plotView.config.xColumn||c[0].index),d.find('[name="yColumn"]').val(this.plotView.config.yColumn||c[1].index),void 0!==this.plotView.config.idColumn&&(d.find("#include-id-checkbox").prop("checked",!0).trigger("change"),d.find('select[name="idColumn"]').val(this.plotView.config.idColumn)),d},_render_chartControls:function(a){function b(){var a=$(this);a.siblings(".slider-output").text(a.slider("value"))}a.html(ScatterplotConfigEditor.templates.chartControl(this.plotView.config));var c=this,d={datapointSize:{min:2,max:10,step:1},width:{min:200,max:800,step:20},height:{min:200,max:800,step:20}};return a.find(".numeric-slider-input").each(function(){var a=$(this),e=a.attr("data-config-key"),f=_.extend(d[e],{value:c.plotView.config[e],change:b,slide:b});a.find(".slider").slider(f)}),this.dataset.metadata_column_names,a},_render_chartDisplay:function(){var a=this.$el.find(".tab-pane#chart-display");return this.plotView.setElement(a),this.plotView.render(),a},events:{"change #include-id-checkbox":"toggleThirdColumnSelector","click #data-control .render-button":"renderChart","click #chart-control .render-button":"renderChart"},toggleThirdColumnSelector:function(){this.$el.find('select[name="idColumn"]').parent().toggle()},renderChart:function(){this.$el.find(".nav li.disabled").removeClass("disabled"),this.updateConfigWithDataSettings(),this.updateConfigWithChartSettings(),this.$el.find("ul.nav").find('a[href="#chart-display"]').tab("show"),this.plotView.fetchData()},updateConfigWithDataSettings:function(){var a=this.$el.find("#data-control"),b={xColumn:Number(a.find('[name="xColumn"]').val()),yColumn:Number(a.find('[name="yColumn"]').val())};return a.find("#include-id-checkbox").prop("checked")&&(b.idColumn=a.find('[name="idColumn"]').val()),_.extend(this.plotView.config,b)},updateConfigWithChartSettings:function(){var a=this.plotView,b=this.$el.find("#chart-control");return["datapointSize","width","height"].forEach(function(c){a.config[c]=b.find('.numeric-slider-input[data-config-key="'+c+'"]').find(".slider").slider("value")}),a.config.x.label=b.find('input[name="X-axis-label"]').val(),a.config.y.label=b.find('input[name="Y-axis-label"]').val(),a.config},toString:function(){return"ScatterplotConfigEditor("+(this.dataset?this.dataset.id:"")+")"}});ScatterplotConfigEditor.templates={mainLayout:Templates.editor,dataControl:Templates.datacontrol,chartControl:Templates.chartcontrol};var ScatterplotView=Backbone.View.extend({defaults:{metadata:{dataLines:void 0},pagination:{currPage:0,perPage:3e3},width:400,height:400,margin:{top:16,right:16,bottom:40,left:54},x:{ticks:10,label:"X"},y:{ticks:10,label:"Y"},datapointSize:4,animDuration:500},initialize:function(a){this.config=_.extend(_.clone(this.defaults),a.config||{}),this.dataset=a.dataset},updateConfig:function(a){this.config=this.config||{},_.extend(this.config,a)},fetchData:function(){this.showLoadingIndicator("getting data");var a=this;return xhr=jQuery.getJSON("/api/datasets/"+this.dataset.id,{data_type:"raw_data",provider:"dataset-column",limit:this.config.pagination.perPage,offset:this.config.pagination.currPage*this.config.pagination.perPage}),xhr.done(function(b){a.renderData(b.data)}),xhr.fail(function(a,b,c){alert("Error loading data:\n"+a.responseText),console.error(a,b,c)}),xhr.always(function(){a.hideLoadingIndicator()}),xhr},render:function(a){return this.$el.addClass("scatterplot-display").html(['<div class="controls clear"></div>','<div class="loading-indicator">','<span class="fa fa-spinner fa-spin"></span>','<span class="loading-indicator-message"></span>',"</div>","<svg/>",'<div class="stats-display"></div>'].join("")),this.$el.children().hide(),a&&this.renderData(a),this},showLoadingIndicator:function(a,b){a=a||"",b=b||"fast";var c=this.$el.find(".loading-indicator");a&&c.find(".loading-indicator-message").text(a),c.is(":visible")||(this.toggleStats(!1),c.css({left:this.config.width/2,top:this.config.height/2}).show())},hideLoadingIndicator:function(a){a=a||"fast",this.$el.find(".loading-indicator").hide()},renderData:function(a){this.$el.find(".controls").empty().append(this.renderControls(a)).show(),this.renderPlot(a),this.getStats(a)},renderControls:function(a){var b=this,c=$('<div class="left"></div>'),d=$('<div class="right"></div>');return c.append([this.renderPrevNext(a),this.renderPagination(a)]),d.append([this.renderLineInfo(a),$("<button>Stats</button>").addClass("stats-toggle-btn").click(function(){b.toggleStats()}),$("<button>Redraw</button>").addClass("rerender-btn").click(function(){b.renderPlot(a)})]),[c,d]},renderLineInfo:function(a){var b=this.dataset.metadata_data_lines||"an unknown number of",c=this.config.pagination.currPage*this.config.pagination.perPage,d=c+a.length;return $("<p/>").addClass("scatterplot-data-info").text(["Displaying lines",c+1,"to",d,"of",b,"lines"].join(" "))},renderPrevNext:function(a){function b(a){return $(['<li><a href="javascript:void(0);">',a,"</a></li>"].join(""))}if(!a||0===this.config.pagination.currPage&&a.length<this.config.pagination.perPage)return null;var c=this,d=this.dataset.metadata_data_lines,e=d?Math.ceil(d/this.config.pagination.perPage):void 0,f=b("Prev").click(function(){c.config.pagination.currPage>0&&(c.config.pagination.currPage-=1,c.fetchData())}),g=b("Next").click(function(){(!e||c.config.pagination.currPage<e-1)&&(c.config.pagination.currPage+=1,c.fetchData())}),h=$("<ul/>").addClass("pagination data-prev-next").append([f,g]);return 0===c.config.pagination.currPage&&f.addClass("disabled"),e&&c.config.pagination.currPage===e-1&&g.addClass("disabled"),h},renderPagination:function(a){function b(a){return $(['<li><a href="javascript:void(0);">',a,"</a></li>"].join(""))}function c(){d.config.pagination.currPage=$(this).data("page"),d.fetchData()}if(!a||0===this.config.pagination.currPage&&a.length<this.config.pagination.perPage)return null;for(var d=this,e=this.dataset.metadata_data_lines,f=e?Math.ceil(e/this.config.pagination.perPage):void 0,g=$("<ul/>").addClass("pagination data-pages"),h=0;f>h;h+=1){var i=b(h+1).attr("data-page",h).click(c);h===this.config.pagination.currPage&&i.addClass("active"),g.append(i)}return g},renderPlot:function(a){this.toggleStats(!1);var b=this.$el.find("svg");b.off().empty().show(),scatterplot(b.get(0),this.config,a)},getStats:function(a){var b=this;meanWorker=new Worker("/plugins/visualizations/scatterplot/static/worker-stats.js"),meanWorker.postMessage({data:a,keys:[this.config.xColumn,this.config.yColumn]}),meanWorker.onerror=function(){meanWorker.terminate()},meanWorker.onmessage=function(a){b.renderStats(a.data)}},renderStats:function(a){var b=this.$el.find(".stats-display"),c=this.config.x.label,d=this.config.y.label,e=$("<table/>").addClass("table").append(["<thead><th></th><th>",c,"</th><th>",d,"</th></thead>"].join("")).append(_.map(a,function(a,b){return $(["<tr><td>",b,"</td><td>",a[0],"</td><td>",a[1],"</td></tr>"].join(""))}));b.empty().append(e)},toggleStats:function(a){var b=this.$el.find(".stats-display");a=void 0===a?b.is(":hidden"):a,a?(this.$el.find("svg").hide(),b.show(),this.$el.find(".controls .stats-toggle-btn").text("Plot")):(b.hide(),this.$el.find("svg").show(),this.$el.find(".controls .stats-toggle-btn").text("Stats"))},toString:function(){return"ScatterplotView()"}});
\ No newline at end of file
diff -r aa8204e99326288ea07e1af26c7d3ffd11f0aff1 -r b812508869b95cc994d049f724d9475aafd417d9 config/plugins/visualizations/scatterplot/templates/scatterplot.mako
--- a/config/plugins/visualizations/scatterplot/templates/scatterplot.mako
+++ b/config/plugins/visualizations/scatterplot/templates/scatterplot.mako
@@ -43,22 +43,18 @@
data = None
##data = list( hda.datatype.dataset_column_dataprovider( hda, limit=10000 ) )
%>
- var hda = ${h.to_json_string( trans.security.encode_dict_ids( hda.to_dict() ) )},
- data = ${h.to_json_string( data )},
- querySettings = ${h.to_json_string( query_args )},
- config = _.extend( querySettings, {
- containerSelector : '#chart',
- dataset : hda,
- });
- //console.debug( querySettings );
+ var hda = ${h.to_json_string( trans.security.encode_dict_ids( hda.to_dict() ) )};
var editor = new ScatterplotConfigEditor({
el : $( '.scatterplot-editor' ).attr( 'id', 'scatterplot-editor-hda-' + hda.id ),
- config : config
+ config : ${h.to_json_string( query_args )},
+ dataset : ${h.to_json_string( trans.security.encode_dict_ids( hda.to_dict() ) )}
}).render();
+ window.editor = editor;
// uncomment to auto render for development
//$( '.render-button:visible' ).click();
});
+
</script>
%endif
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: Dave Bouvier: Log more information about tool dependency and repository installation status when installing and testing.
by commits-noreply@bitbucket.org 19 Nov '13
by commits-noreply@bitbucket.org 19 Nov '13
19 Nov '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/aa8204e99326/
Changeset: aa8204e99326
User: Dave Bouvier
Date: 2013-11-19 15:51:30
Summary: Log more information about tool dependency and repository installation status when installing and testing.
Affected #: 2 files
diff -r 73b57b7e1b73dbbf8b786d5dc749b67d635f8338 -r aa8204e99326288ea07e1af26c7d3ffd11f0aff1 test/install_and_test_tool_shed_repositories/base/twilltestcase.py
--- a/test/install_and_test_tool_shed_repositories/base/twilltestcase.py
+++ b/test/install_and_test_tool_shed_repositories/base/twilltestcase.py
@@ -107,6 +107,7 @@
self.submit_form( 1, 'select_tool_panel_section_button', **kwd )
self.check_for_strings( post_submit_strings_displayed, strings_not_displayed )
repository_ids = self.initiate_installation_process( new_tool_panel_section=new_tool_panel_section )
+ log.debug( 'Waiting for the installation of repository IDs: %s' % str( repository_ids ) )
self.wait_for_repository_installation( repository_ids )
def visit_url( self, url, allowed_codes=[ 200 ] ):
@@ -124,10 +125,14 @@
if repository_ids:
for repository_id in repository_ids:
galaxy_repository = test_db_util.get_repository( self.security.decode_id( repository_id ) )
+ log.debug( 'Repository %s with ID %s has initial state %s.' % ( str( galaxy_repository.name ), str( repository_id ), str( galaxy_repository.status ) ) )
timeout_counter = 0
while galaxy_repository.status not in final_states:
test_db_util.refresh( galaxy_repository )
+ log.debug( 'Repository %s with ID %s is in state %s, continuing to wait.' % ( str( galaxy_repository.name ), str( repository_id ), str( galaxy_repository.status ) ) )
timeout_counter = timeout_counter + 1
+ if timeout_counter % 10 == 0:
+ log.debug( 'Waited %d seconds for repository %s.' % ( timeout_counter, str( galaxy_repository.name ) ) )
# This timeout currently defaults to 180 seconds, or 3 minutes.
if timeout_counter > common.repository_installation_timeout:
raise AssertionError( 'Repository installation timed out, %d seconds elapsed, repository state is %s.' % \
diff -r 73b57b7e1b73dbbf8b786d5dc749b67d635f8338 -r aa8204e99326288ea07e1af26c7d3ffd11f0aff1 test/install_and_test_tool_shed_repositories/functional_tests.py
--- a/test/install_and_test_tool_shed_repositories/functional_tests.py
+++ b/test/install_and_test_tool_shed_repositories/functional_tests.py
@@ -363,7 +363,10 @@
return '000000000000'
def get_missing_tool_dependencies( repository ):
+ log.debug( 'Checking %s repository %s for missing tool dependencies.' % ( repository.status, repository.name ) )
missing_tool_dependencies = repository.missing_tool_dependencies
+ for tool_dependency in repository.tool_dependencies:
+ log.debug( 'Tool dependency %s version %s has status %s.' % ( tool_dependency.name, tool_dependency.version, tool_dependency.status ) )
for repository_dependency in repository.repository_dependencies:
if not repository_dependency.includes_tool_dependencies:
continue
@@ -687,7 +690,10 @@
tool_dependency_install_path = tool_dependency.installation_directory( app )
uninstalled, error_message = tool_dependency_util.remove_tool_dependency( app, tool_dependency )
if error_message:
+ log.debug( 'There was an error attempting to remove directory: %s' % str( tool_dependency_install_path ) )
log.debug( error_message )
+ else:
+ log.debug( 'Successfully removed tool dependency installation directory: %s' % str( tool_dependency_install_path ) )
sa_session = app.model.context.current
if not uninstalled or tool_dependency.status != app.model.ToolDependency.installation_status.UNINSTALLED:
tool_dependency.status = app.model.ToolDependency.installation_status.UNINSTALLED
@@ -1107,7 +1113,8 @@
# }
if 'missing_test_components' not in repository_status:
repository_status[ 'missing_test_components' ] = []
- if repository.missing_tool_dependencies or repository.missing_repository_dependencies:
+ missing_tool_dependencies = get_missing_tool_dependencies( repository )
+ if missing_tool_dependencies or repository.missing_repository_dependencies:
# If a tool dependency fails to install correctly, this should be considered an installation error,
# and functional tests should be skipped, since the tool dependency needs to be correctly installed
# for the test to be considered reliable.
@@ -1143,9 +1150,7 @@
# The deactivate flag is set to True if the environment variable GALAXY_INSTALL_TEST_KEEP_TOOL_DEPENDENCIES
# is set to 'true'.
if deactivate:
- # Recursively retrieve every missing tool dependency for this repository and its required repositories.
log.debug( 'Due to the above missing tool dependencies, we are now uninstalling the following tool dependencies, but not changing their repositories.' )
- missing_tool_dependencies = get_missing_tool_dependencies( repository )
for missing_tool_dependency in missing_tool_dependencies:
uninstall_tool_dependency( app, missing_tool_dependency )
# We are deactivating this repository and all of its repository dependencies.
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: greg: Fix for populating the missing tool dependencies container in certain special cases in Tool Shed repositories.
by commits-noreply@bitbucket.org 19 Nov '13
by commits-noreply@bitbucket.org 19 Nov '13
19 Nov '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/73b57b7e1b73/
Changeset: 73b57b7e1b73
User: greg
Date: 2013-11-19 14:55:23
Summary: Fix for populating the missing tool dependencies container in certain special cases in Tool Shed repositories.
Affected #: 1 file
diff -r 0632a6fe11a2027bdd15e5ddbc4c9c192bb6eaeb -r 73b57b7e1b73dbbf8b786d5dc749b67d635f8338 lib/tool_shed/util/metadata_util.py
--- a/lib/tool_shed/util/metadata_util.py
+++ b/lib/tool_shed/util/metadata_util.py
@@ -1507,8 +1507,14 @@
common_install_util.get_installed_and_missing_repository_dependencies( trans, repository )
# Handle the current repository's tool dependencies.
repository_tool_dependencies = metadata.get( 'tool_dependencies', None )
+ # Make sure to display missing tool dependencies as well.
+ repository_invalid_tool_dependencies = metadata.get( 'invalid_tool_dependencies', None )
+ if repository_invalid_tool_dependencies is not None:
+ if repository_tool_dependencies is None:
+ repository_tool_dependencies = {}
+ repository_tool_dependencies.update( repository_invalid_tool_dependencies )
repository_installed_tool_dependencies, repository_missing_tool_dependencies = \
- tool_dependency_util.get_installed_and_missing_tool_dependencies( trans, repository, repository_tool_dependencies )
+ tool_dependency_util.get_installed_and_missing_tool_dependencies_for_installed_repository( trans, repository, repository_tool_dependencies )
if reinstalling:
installed_tool_dependencies, missing_tool_dependencies = \
tool_dependency_util.populate_tool_dependencies_dicts( trans=trans,
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: greg: Fix for populating and unpopulating complex repository dependency tags sets in tool dependency definitions contained in tool shed repositories.
by commits-noreply@bitbucket.org 19 Nov '13
by commits-noreply@bitbucket.org 19 Nov '13
19 Nov '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/0632a6fe11a2/
Changeset: 0632a6fe11a2
User: greg
Date: 2013-11-19 14:52:20
Summary: Fix for populating and unpopulating complex repository dependency tags sets in tool dependency definitions contained in tool shed repositories.
Affected #: 1 file
diff -r facb9f9d2ee4d614d21e4fc1a4a6d99f2668349a -r 0632a6fe11a2027bdd15e5ddbc4c9c192bb6eaeb lib/tool_shed/util/commit_util.py
--- a/lib/tool_shed/util/commit_util.py
+++ b/lib/tool_shed/util/commit_util.py
@@ -368,6 +368,8 @@
unpopulate=unpopulate )
if message:
error_message += message
+ if package_altered:
+ root[ root_index ] = root_elem
elif package_elem.tag == 'install':
# <install version="1.0">
for actions_index, actions_elem in enumerate( package_elem ):
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: jmchilton: Re-fix tool API for uploads coming through nginx.
by commits-noreply@bitbucket.org 19 Nov '13
by commits-noreply@bitbucket.org 19 Nov '13
19 Nov '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/facb9f9d2ee4/
Changeset: facb9f9d2ee4
User: jmchilton
Date: 2013-11-19 04:26:29
Summary: Re-fix tool API for uploads coming through nginx.
Give tools.get_incoming_value a chance to mangle all keys and see if they appear in some other format. Thanks to @natefoo for detecting the problem, determining the source of the error, and describing the exact path through the code - i.e. doing all the work.
Affected #: 1 file
diff -r b0535b4864b4bf542e31af7acc027fcbb5a00a54 -r facb9f9d2ee4d614d21e4fc1a4a6d99f2668349a lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -2083,19 +2083,11 @@
if any_group_errors:
errors[input.name] = group_errors
else:
- if key not in incoming \
- and "__force_update__" + key not in incoming:
- # No new value provided, and we are only updating, so keep
- # the old value (which should already be in the state) and
- # preserve the old error message.
- pass
- else:
- incoming_value = get_incoming_value( incoming, key, None )
- value, error = check_param( trans, input, incoming_value, context, source=source )
- # If a callback was provided, allow it to process the value
- if error:
- errors[ input.name ] = error
- state[ input.name ] = value
+ incoming_value = get_incoming_value( incoming, key, None )
+ value, error = check_param( trans, input, incoming_value, context, source=source )
+ if error:
+ errors[ input.name ] = error
+ state[ input.name ] = value
return errors
def update_state( self, trans, inputs, state, incoming, source='html', prefix="", context=None,
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
18 Nov '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/b0535b4864b4/
Changeset: b0535b4864b4
User: guerler
Date: 2013-11-18 22:02:41
Summary: Toolshed: Fix grids
Affected #: 2 files
diff -r 32acc00ca229951afbd659281f57d93a47bcab06 -r b0535b4864b4bf542e31af7acc027fcbb5a00a54 templates/webapps/tool_shed/category/grid.mako
--- a/templates/webapps/tool_shed/category/grid.mako
+++ b/templates/webapps/tool_shed/category/grid.mako
@@ -6,6 +6,7 @@
## Render grid header.
## TODO: This is very similar to this directory's valid_grid.mako, so see if we can re-use this code in a better way.
<%def name="render_grid_header( grid, repo_grid, render_title=True)">
+ ${init()}
<div class="grid-header">
%if render_title:
${grid_title()}
diff -r 32acc00ca229951afbd659281f57d93a47bcab06 -r b0535b4864b4bf542e31af7acc027fcbb5a00a54 templates/webapps/tool_shed/category/valid_grid.mako
--- a/templates/webapps/tool_shed/category/valid_grid.mako
+++ b/templates/webapps/tool_shed/category/valid_grid.mako
@@ -5,6 +5,7 @@
## Render grid header.
<%def name="render_grid_header( grid, repo_grid, render_title=True)">
+ ${init()}
<div class="grid-header">
%if render_title:
${grid_title()}
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
2 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/fe8bb4e8e3a1/
Changeset: fe8bb4e8e3a1
User: jgoecks
Date: 2013-11-18 20:18:10
Summary: Trackster painters: rename y_center variable to y_start to reflect real position.
Affected #: 1 file
diff -r c0eb0f44b7fe80fdcb6590c4364312bbdcb286b0 -r fe8bb4e8e3a122930548c03c899fcdcaff52f484 static/scripts/viz/trackster/painters.js
--- a/static/scripts/viz/trackster/painters.js
+++ b/static/scripts/viz/trackster/painters.js
@@ -466,7 +466,7 @@
f_end = Math.ceil( Math.min(width, Math.max(0, (feature_end - tile_low - 0.5) * w_scale)) ),
draw_start = f_start,
draw_end = f_end,
- y_center = (mode === "Dense" ? 0 : (0 + slot)) * y_scale + this.get_top_padding(width),
+ y_start = (mode === "Dense" ? 0 : (0 + slot)) * y_scale + this.get_top_padding(width),
thickness, y_start, thick_start = null, thick_end = null,
// TODO: is there any reason why block, label color cannot be set at the Painter level?
// For now, assume '.' === '+'
@@ -484,7 +484,7 @@
if (mode === "no_detail") {
// No details for feature, so only one way to display.
ctx.fillStyle = block_color;
- ctx.fillRect(f_start, y_center + 5, f_end - f_start, NO_DETAIL_FEATURE_HEIGHT);
+ ctx.fillRect(f_start, y_start + 5, f_end - f_start, NO_DETAIL_FEATURE_HEIGHT);
}
else { // Mode is either Squish or Pack:
// Feature details.
@@ -517,7 +517,7 @@
if (!feature_blocks) {
// If there are no blocks, treat the feature as one big exon.
ctx.fillStyle = block_color;
- ctx.fillRect(f_start, y_center + 1, f_end - f_start, thick_height);
+ ctx.fillRect(f_start, y_start + 1, f_end - f_start, thick_height);
// If strand is specified, draw arrows over feature
if ( feature_strand && full_height ) {
if (feature_strand === "+") {
@@ -525,7 +525,7 @@
} else if (feature_strand === "-") {
ctx.fillStyle = ctx.canvas.manager.get_pattern( 'left_strand_inv' );
}
- ctx.fillRect(f_start, y_center + 1, f_end - f_start, thick_height);
+ ctx.fillRect(f_start, y_start + 1, f_end - f_start, thick_height);
}
} else {
//
@@ -536,19 +536,19 @@
// a block, is visible.
//
- // Compute y axis center position and height
- var cur_y_center, cur_height;
+ // Compute y axis start position and height
+ var cur_y_start, cur_height;
if (mode === "Squish" || mode === "Dense") {
- cur_y_center = y_center + Math.floor(SQUISH_FEATURE_HEIGHT/2) + 1;
+ cur_y_start = y_start + Math.floor(SQUISH_FEATURE_HEIGHT/2) + 1;
cur_height = 1;
}
else { // mode === "Pack"
if (feature_strand) {
- cur_y_center = y_center;
+ cur_y_start = y_start;
cur_height = thick_height;
}
else {
- cur_y_center += (SQUISH_FEATURE_HEIGHT/2) + 1;
+ cur_y_start += (SQUISH_FEATURE_HEIGHT/2) + 1;
cur_height = 1;
}
}
@@ -570,7 +570,7 @@
ctx.fillStyle = CONNECTOR_COLOR;
}
}
- ctx.fillRect(f_start, cur_y_center, f_end - f_start, cur_height);
+ ctx.fillRect(f_start, cur_y_start, f_end - f_start, cur_height);
}
// Draw blocks.
@@ -587,14 +587,14 @@
// Draw thin block.
ctx.fillStyle = block_color;
- ctx.fillRect(block_start, y_center + (thick_height-thin_height)/2 + 1, block_end - block_start, thin_height);
+ ctx.fillRect(block_start, y_start + (thick_height-thin_height)/2 + 1, block_end - block_start, thin_height);
// If block intersects with thick region, draw block as thick.
// - No thick is sometimes encoded as thick_start == thick_end, so don't draw in that case
if (thick_start !== undefined && feature_te > feature_ts && !(block_start > thick_end || block_end < thick_start) ) {
var block_thick_start = Math.max(block_start, thick_start),
block_thick_end = Math.min(block_end, thick_end);
- ctx.fillRect(block_thick_start, y_center + 1, block_thick_end - block_thick_start, thick_height);
+ ctx.fillRect(block_thick_start, y_start + 1, block_thick_end - block_thick_start, thick_height);
if ( feature_blocks.length === 1 && mode === "Pack") {
// Exactly one block means we have no introns, but do have a distinct "thick" region,
// draw arrows over it if in pack mode.
@@ -608,12 +608,12 @@
block_thick_start += 2;
block_thick_end -= 2;
}
- ctx.fillRect(block_thick_start, y_center + 1, block_thick_end - block_thick_start, thick_height);
+ ctx.fillRect(block_thick_start, y_start + 1, block_thick_end - block_thick_start, thick_height);
}
}
// Draw individual connectors if required
if ( this.draw_individual_connectors && last_block_start ) {
- this.draw_connector( ctx, last_block_start, last_block_end, block_start, block_end, y_center );
+ this.draw_connector( ctx, last_block_start, last_block_end, block_start, block_end, y_start );
}
last_block_start = block_start;
last_block_end = block_end;
@@ -632,8 +632,8 @@
new_height = Math.ceil(thick_height * hscale_factor),
ws_height = Math.round( (thick_height-new_height)/2 );
if (hscale_factor !== 1) {
- ctx.fillRect(f_start, cur_y_center + 1, f_end - f_start, ws_height);
- ctx.fillRect(f_start, cur_y_center + thick_height - ws_height + 1, f_end - f_start, ws_height);
+ ctx.fillRect(f_start, cur_y_start + 1, f_end - f_start, ws_height);
+ ctx.fillRect(f_start, cur_y_start + thick_height - ws_height + 1, f_end - f_start, ws_height);
}
}
}
@@ -647,11 +647,11 @@
// FIXME: assumption here that the entire view starts at 0
if (tile_low === 0 && f_start - ctx.measureText(feature_name).width < 0) {
ctx.textAlign = "left";
- ctx.fillText(feature_name, f_end + LABEL_SPACING, y_center + 8);
+ ctx.fillText(feature_name, f_end + LABEL_SPACING, y_start + 8);
draw_end += ctx.measureText(feature_name).width + LABEL_SPACING;
} else {
ctx.textAlign = "right";
- ctx.fillText(feature_name, f_start - LABEL_SPACING, y_center + 8);
+ ctx.fillText(feature_name, f_start - LABEL_SPACING, y_start + 8);
draw_start -= ctx.measureText(feature_name).width + LABEL_SPACING;
}
//ctx.fillStyle = block_color;
@@ -741,7 +741,7 @@
/**
* Draw a single read.
*/
- draw_read: function(ctx, mode, w_scale, y_center, tile_low, tile_high, feature_start, cigar, strand, read_seq) {
+ draw_read: function(ctx, mode, w_scale, y_start, tile_low, tile_high, feature_start, cigar, strand, read_seq) {
ctx.textAlign = "center";
var tile_region = [tile_low, tile_high],
base_offset = 0,
@@ -793,7 +793,7 @@
// Draw read base as rectangle.
ctx.fillStyle = block_color;
ctx.fillRect(s_start,
- y_center + (pack_mode ? 1 : 4 ),
+ y_start + (pack_mode ? 1 : 4 ),
s_end - s_start,
(pack_mode ? PACK_FEATURE_HEIGHT : SQUISH_FEATURE_HEIGHT));
@@ -824,12 +824,12 @@
var c_start = Math.floor( Math.max(0, (seq_start + c - tile_low) * w_scale) );
ctx.fillStyle = this.base_color_fn(seq[c]);
if (pack_mode && w_scale > char_width_px) {
- ctx.fillText(seq[c], c_start, y_center + 9);
+ ctx.fillText(seq[c], c_start, y_start + 9);
}
// Require a minimum w_scale so that variants are only drawn when somewhat zoomed in.
else if (w_scale > 0.05) {
ctx.fillRect(c_start - gap,
- y_center + (pack_mode ? 1 : 4),
+ y_start + (pack_mode ? 1 : 4),
Math.max( 1, Math.round(w_scale) ),
(pack_mode ? PACK_FEATURE_HEIGHT : SQUISH_FEATURE_HEIGHT));
}
@@ -843,12 +843,12 @@
break;
case "N": // Skipped bases.
ctx.fillStyle = CONNECTOR_COLOR;
- ctx.fillRect(s_start, y_center + 5, s_end - s_start, 1);
- //ctx.dashedLine(s_start + this.left_offset, y_center + 5, this.left_offset + s_end, y_center + 5);
+ ctx.fillRect(s_start, y_start + 5, s_end - s_start, 1);
+ //ctx.dashedLine(s_start + this.left_offset, y_start + 5, this.left_offset + s_end, y_start + 5);
base_offset += cig_len;
break;
case "D": // Deletion.
- paint_utils.draw_deletion(s_start, y_center, 1);
+ paint_utils.draw_deletion(s_start, y_start, 1);
base_offset += cig_len;
break;
case "P": // TODO: No good way to draw insertions/padding right now, so ignore
@@ -874,8 +874,8 @@
if ( (mode === "Pack" || this.mode === "Auto") && read_seq !== undefined && w_scale > char_width_px) {
// Draw sequence container.
ctx.fillStyle = "yellow";
- ctx.fillRect(x_center - gap, y_center - 9, s_end - s_start, 9);
- draw_last[draw_last.length] = {type: "triangle", data: [insert_x_coord, y_center + 4, 5]};
+ ctx.fillRect(x_center - gap, y_start - 9, s_end - s_start, 9);
+ draw_last[draw_last.length] = {type: "triangle", data: [insert_x_coord, y_start + 4, 5]};
ctx.fillStyle = CONNECTOR_COLOR;
// Based on overlap b/t sequence and tile, get sequence to be drawn.
switch( compute_overlap( [seq_start, seq_start + cig_len], tile_region ) ) {
@@ -895,21 +895,21 @@
// Draw sequence.
for (var c = 0, str_len = seq.length; c < str_len; c++) {
var c_start = Math.floor( Math.max(0, (seq_start + c - tile_low) * w_scale) );
- ctx.fillText(seq[c], c_start - (s_end - s_start)/2, y_center);
+ ctx.fillText(seq[c], c_start - (s_end - s_start)/2, y_start);
}
}
else {
// Draw block.
ctx.fillStyle = "yellow";
// TODO: This is a pretty hack-ish way to fill rectangle based on mode.
- ctx.fillRect(x_center, y_center + (this.mode !== "Dense" ? 2 : 5),
+ ctx.fillRect(x_center, y_start + (this.mode !== "Dense" ? 2 : 5),
s_end - s_start, (mode !== "Dense" ? SQUISH_FEATURE_HEIGHT : DENSE_FEATURE_HEIGHT));
}
}
else {
if ( (mode === "Pack" || this.mode === "Auto") && read_seq !== undefined && w_scale > char_width_px) {
// Show insertions with a single number at the insertion point.
- draw_last.push( { type: "text", data: [seq.length, insert_x_coord, y_center + 9] } );
+ draw_last.push( { type: "text", data: [seq.length, insert_x_coord, y_start + 9] } );
}
else {
// TODO: probably can merge this case with code above.
@@ -955,7 +955,7 @@
// -0.5 to put element between bases.
f_start = Math.floor( Math.max(-0.5 * w_scale, (feature_start - tile_low - 0.5) * w_scale) ),
f_end = Math.ceil( Math.min(width, Math.max(0, (feature_end - tile_low - 0.5) * w_scale)) ),
- y_center = (mode === "Dense" ? 0 : (0 + slot)) * y_scale,
+ y_start = (mode === "Dense" ? 0 : (0 + slot)) * y_scale,
label_color = this.prefs.label_color;
@@ -966,7 +966,7 @@
// Draw left/forward read.
if (feature[4][1] >= tile_low && feature[4][0] <= tile_high && feature[4][2]) {
- this.draw_read(ctx, mode, w_scale, y_center, tile_low, tile_high, feature[4][0], feature[4][2], feature[4][3], feature[4][4]);
+ this.draw_read(ctx, mode, w_scale, y_start, tile_low, tile_high, feature[4][0], feature[4][2], feature[4][3], feature[4][4]);
}
else {
connector = false;
@@ -974,7 +974,7 @@
// Draw right/reverse read.
if (feature[5][1] >= tile_low && feature[5][0] <= tile_high && feature[5][2]) {
- this.draw_read(ctx, mode, w_scale, y_center, tile_low, tile_high, feature[5][0], feature[5][2], feature[5][3], feature[5][4]);
+ this.draw_read(ctx, mode, w_scale, y_start, tile_low, tile_high, feature[5][0], feature[5][2], feature[5][3], feature[5][4]);
}
else {
connector = false;
@@ -989,21 +989,21 @@
b2_start = Math.floor( Math.max(-0.5 * w_scale, (feature[5][0] - tile_low - 0.5) * w_scale) );
if (connector && b2_start > b1_end) {
ctx.fillStyle = CONNECTOR_COLOR;
- dashedLine(ctx, b1_end, y_center + 5, b2_start, y_center + 5);
+ dashedLine(ctx, b1_end, y_start + 5, b2_start, y_start + 5);
}
} else {
// Read is single.
- this.draw_read(ctx, mode, w_scale, y_center, tile_low, tile_high, feature_start, feature[4], feature[5], feature[6]);
+ this.draw_read(ctx, mode, w_scale, y_start, tile_low, tile_high, feature_start, feature[4], feature[5], feature[6]);
}
if (mode === "Pack" && feature_start >= tile_low && feature_name !== ".") {
// Draw label.
ctx.fillStyle = this.prefs.label_color;
if (tile_low === 0 && f_start - ctx.measureText(feature_name).width < 0) {
ctx.textAlign = "left";
- ctx.fillText(feature_name, f_end + LABEL_SPACING, y_center + 8);
+ ctx.fillText(feature_name, f_end + LABEL_SPACING, y_start + 8);
} else {
ctx.textAlign = "right";
- ctx.fillText(feature_name, f_start - LABEL_SPACING, y_center + 8);
+ ctx.fillText(feature_name, f_start - LABEL_SPACING, y_start + 8);
}
}
@@ -1024,7 +1024,7 @@
/**
* Draw a single read from reference-based read sequence and cigar.
*/
- draw_read: function(ctx, mode, w_scale, y_center, tile_low, tile_high, feature_start, cigar, strand, read_seq) {
+ draw_read: function(ctx, mode, w_scale, y_start, tile_low, tile_high, feature_start, cigar, strand, read_seq) {
ctx.textAlign = "center";
var tile_region = [tile_low, tile_high],
base_offset = 0,
@@ -1063,7 +1063,7 @@
// Draw read base as rectangle.
ctx.fillStyle = block_color;
ctx.fillRect(s_start,
- y_center + (pack_mode ? 1 : 4 ),
+ y_start + (pack_mode ? 1 : 4 ),
s_end - s_start,
(pack_mode ? PACK_FEATURE_HEIGHT : SQUISH_FEATURE_HEIGHT));
}
@@ -1130,12 +1130,12 @@
var c_start = Math.floor( Math.max(0, (start_pos + c - tile_low) * w_scale) );
ctx.fillStyle = this.base_color_fn(cur_seq[c]);
if (pack_mode && w_scale > char_width_px) {
- ctx.fillText(cur_seq[c], c_start, y_center + 9);
+ ctx.fillText(cur_seq[c], c_start, y_start + 9);
}
// Require a minimum w_scale so that variants are only drawn when somewhat zoomed in.
else if (w_scale > 0.05) {
ctx.fillRect(c_start - gap,
- y_center + (pack_mode ? 1 : 4),
+ y_start + (pack_mode ? 1 : 4),
Math.max( 1, Math.round(w_scale) ),
(pack_mode ? PACK_FEATURE_HEIGHT : SQUISH_FEATURE_HEIGHT));
}
@@ -1150,14 +1150,14 @@
break;
case "N": // Skipped bases.
ctx.fillStyle = CONNECTOR_COLOR;
- ctx.fillRect(s_start, y_center + 5, s_end - s_start, 1);
- //ctx.dashedLine(s_start + this.left_offset, y_center + 5, this.left_offset + s_end, y_center + 5);
+ ctx.fillRect(s_start, y_start + 5, s_end - s_start, 1);
+ //ctx.dashedLine(s_start + this.left_offset, y_start + 5, this.left_offset + s_end, y_start + 5);
// No change in seq_offset because sequence not used when skipping.
base_offset += cig_len;
break;
case "D": // Deletion.
ctx.fillStyle = "black";
- ctx.fillRect(s_start, y_center + 4, s_end - s_start, 3);
+ ctx.fillRect(s_start, y_start + 4, s_end - s_start, 3);
base_offset += cig_len;
break;
case "I": // Insertion.
@@ -1180,8 +1180,8 @@
if ( (mode === "Pack" || this.mode === "Auto") && read_seq !== undefined && w_scale > char_width_px) {
// Draw sequence container.
ctx.fillStyle = "yellow";
- ctx.fillRect(x_center - gap, y_center - 9, s_end - s_start, 9);
- draw_last[draw_last.length] = {type: "triangle", data: [insert_x_coord, y_center + 4, 5]};
+ ctx.fillRect(x_center - gap, y_start - 9, s_end - s_start, 9);
+ draw_last[draw_last.length] = {type: "triangle", data: [insert_x_coord, y_start + 4, 5]};
ctx.fillStyle = CONNECTOR_COLOR;
// Based on overlap b/t sequence and tile, get sequence to be drawn.
switch( compute_overlap( [seq_start, seq_start + cig_len], tile_region ) ) {
@@ -1201,21 +1201,21 @@
// Draw sequence.
for (var c = 0, str_len = seq.length; c < str_len; c++) {
var c_start = Math.floor( Math.max(0, (seq_start + c - tile_low) * w_scale) );
- ctx.fillText(seq[c], c_start - (s_end - s_start)/2, y_center);
+ ctx.fillText(seq[c], c_start - (s_end - s_start)/2, y_start);
}
}
else {
// Draw block.
ctx.fillStyle = "yellow";
// TODO: This is a pretty hack-ish way to fill rectangle based on mode.
- ctx.fillRect(x_center, y_center + (this.mode !== "Dense" ? 2 : 5),
+ ctx.fillRect(x_center, y_start + (this.mode !== "Dense" ? 2 : 5),
s_end - s_start, (mode !== "Dense" ? SQUISH_FEATURE_HEIGHT : DENSE_FEATURE_HEIGHT));
}
}
else {
if ( (mode === "Pack" || this.mode === "Auto") && read_seq !== undefined && w_scale > char_width_px) {
// Show insertions with a single number at the insertion point.
- draw_last.push( { type: "text", data: [seq.length, insert_x_coord, y_center + 9] } );
+ draw_last.push( { type: "text", data: [seq.length, insert_x_coord, y_start + 9] } );
}
else {
// TODO: probably can merge this case with code above.
@@ -1275,7 +1275,7 @@
return Math.min( 128, Math.ceil( ( this.longest_feature_length / 2 ) * w_scale ) );
},
- draw_connector: function( ctx, block1_start, block1_end, block2_start, block2_end, y_center ) {
+ draw_connector: function( ctx, block1_start, block1_end, block2_start, block2_end, y_start ) {
// Arc drawing -- from closest endpoints
var x_center = ( block1_end + block2_start ) / 2,
radius = block2_start - x_center;
@@ -1283,7 +1283,7 @@
var angle1 = Math.PI, angle2 = 0;
if ( radius > 0 ) {
ctx.beginPath();
- ctx.arc( x_center, y_center, block2_start - x_center, Math.PI, 0 );
+ ctx.arc( x_center, y_start, block2_start - x_center, Math.PI, 0 );
ctx.stroke();
}
}
https://bitbucket.org/galaxy/galaxy-central/commits/32acc00ca229/
Changeset: 32acc00ca229
User: jgoecks
Date: 2013-11-18 21:57:15
Summary: Trackster: more improvements for drawing deletions in read and variant track.
Affected #: 1 file
diff -r fe8bb4e8e3a122930548c03c899fcdcaff52f484 -r 32acc00ca229951afbd659281f57d93a47bcab06 static/scripts/viz/trackster/painters.js
--- a/static/scripts/viz/trackster/painters.js
+++ b/static/scripts/viz/trackster/painters.js
@@ -750,7 +750,7 @@
char_width_px = ctx.canvas.manager.char_width_px,
block_color = (strand === "+" ? this.prefs.block_color : this.prefs.reverse_strand_color),
pack_mode = (mode === 'Pack'),
- paint_utils = new ReadPainterUtils(ctx, (pack_mode ? PACK_FEATURE_HEIGHT : SQUISH_FEATURE_HEIGHT), w_scale);
+ paint_utils = new ReadPainterUtils(ctx, (pack_mode ? PACK_FEATURE_HEIGHT : SQUISH_FEATURE_HEIGHT), w_scale, mode);
// Keep list of items that need to be drawn on top of initial drawing layer.
var draw_last = [];
@@ -770,6 +770,10 @@
// -0.5 to offset sequence between bases.
s_start = Math.floor( Math.max(-0.5 * w_scale, (seq_start - tile_low - 0.5) * w_scale) ),
s_end = Math.floor( Math.max(0, (seq_start + cig_len - tile_low - 0.5) * w_scale) );
+
+ if (!is_overlap([seq_start, seq_start + cig_len], tile_region)) {
+ continue;
+ }
// Make sure that read is drawn even if it too small to be rendered officially; in this case,
// read is drawn at 1px.
@@ -789,55 +793,54 @@
case "M": // Loose match with reference; can be match or mismatch.
case "=": // Strict match with reference.
case "X": // Strict mismatch with reference.
- if (is_overlap([seq_start, seq_start + cig_len], tile_region)) {
- // Draw read base as rectangle.
- ctx.fillStyle = block_color;
- ctx.fillRect(s_start,
- y_start + (pack_mode ? 1 : 4 ),
- s_end - s_start,
- (pack_mode ? PACK_FEATURE_HEIGHT : SQUISH_FEATURE_HEIGHT));
+ // Draw read base as rectangle.
+ ctx.fillStyle = block_color;
+ ctx.fillRect(s_start,
+ y_start + (pack_mode ? 1 : 4 ),
+ s_end - s_start,
+ (pack_mode ? PACK_FEATURE_HEIGHT : SQUISH_FEATURE_HEIGHT));
- // Draw sequence and/or variants.
- var seq = read_seq.slice(seq_offset, seq_offset + cig_len),
- ref_char,
- read_char;
- for (var c = 0, str_len = seq.length; c < str_len; c++) {
- // Draw base if it's on tile:
- if (seq_start + c >= tile_low && seq_start + c <= tile_high) {
- // Get reference and read character.
- ref_char = (this.ref_seq ? this.ref_seq[seq_start - tile_low + c] : null);
- read_char = seq[c];
+ // Draw sequence and/or variants.
+ var seq = read_seq.slice(seq_offset, seq_offset + cig_len),
+ ref_char,
+ read_char;
+ for (var c = 0, str_len = seq.length; c < str_len; c++) {
+ // Draw base if it's on tile:
+ if (seq_start + c >= tile_low && seq_start + c <= tile_high) {
+ // Get reference and read character.
+ ref_char = (this.ref_seq ? this.ref_seq[seq_start - tile_low + c] : null);
+ read_char = seq[c];
- // Draw base depending on (a) available reference data and (b) config options.
- if (
- // If there's reference data and (a) showing all (i.e. not showing
- // differences) or (b) if there is a variant.
- (ref_char &&
- (!this.prefs.show_differences ||
- (read_char.toLowerCase !== 'n' && (ref_char.toLowerCase() !== read_char.toLowerCase())))
- ) ||
- // If there's no reference data and showing all.
- (!ref_char && !this.prefs.show_differences)
- ) {
+ // Draw base depending on (a) available reference data and (b) config options.
+ if (
+ // If there's reference data and (a) showing all (i.e. not showing
+ // differences) or (b) if there is a variant.
+ (ref_char &&
+ (!this.prefs.show_differences ||
+ (read_char.toLowerCase !== 'n' && (ref_char.toLowerCase() !== read_char.toLowerCase())))
+ ) ||
+ // If there's no reference data and showing all.
+ (!ref_char && !this.prefs.show_differences)
+ ) {
- // Draw base.
- var c_start = Math.floor( Math.max(0, (seq_start + c - tile_low) * w_scale) );
- ctx.fillStyle = this.base_color_fn(seq[c]);
- if (pack_mode && w_scale > char_width_px) {
- ctx.fillText(seq[c], c_start, y_start + 9);
- }
- // Require a minimum w_scale so that variants are only drawn when somewhat zoomed in.
- else if (w_scale > 0.05) {
- ctx.fillRect(c_start - gap,
- y_start + (pack_mode ? 1 : 4),
- Math.max( 1, Math.round(w_scale) ),
- (pack_mode ? PACK_FEATURE_HEIGHT : SQUISH_FEATURE_HEIGHT));
- }
+ // Draw base.
+ var c_start = Math.floor( Math.max(0, (seq_start + c - tile_low) * w_scale) );
+ ctx.fillStyle = this.base_color_fn(seq[c]);
+ if (pack_mode && w_scale > char_width_px) {
+ ctx.fillText(seq[c], c_start, y_start + 9);
}
+ // Require a minimum w_scale so that variants are only drawn when somewhat zoomed in.
+ else if (w_scale > 0.05) {
+ ctx.fillRect(c_start - gap,
+ y_start + (pack_mode ? 1 : 4),
+ Math.max( 1, Math.round(w_scale) ),
+ (pack_mode ? PACK_FEATURE_HEIGHT : SQUISH_FEATURE_HEIGHT));
+ }
+ }
- }
}
}
+
seq_offset += cig_len;
base_offset += cig_len;
break;
@@ -1033,6 +1036,7 @@
char_width_px = ctx.canvas.manager.char_width_px,
block_color = (strand === "+" ? this.prefs.block_color : this.prefs.reverse_strand_color),
pack_mode = (mode === 'Pack'),
+ paint_utils = new ReadPainterUtils(ctx, (pack_mode ? PACK_FEATURE_HEIGHT : SQUISH_FEATURE_HEIGHT), w_scale, mode),
drawing_blocks = [];
// Keep list of items that need to be drawn on top of initial drawing layer.
@@ -1074,11 +1078,15 @@
var cig = cigar[cig_id],
cig_op = "MIDNSHP=X"[ cig[0] ],
cig_len = cig[1];
-
+
var seq_start = feature_start + base_offset,
// -0.5 to offset sequence between bases.
s_start = Math.floor( Math.max(0, -0.5 * w_scale, (seq_start - tile_low - 0.5) * w_scale) ),
s_end = Math.floor( Math.max(0, (seq_start + cig_len - tile_low - 0.5) * w_scale) );
+
+ if (!is_overlap([seq_start, seq_start + cig_len], tile_region)) {
+ continue;
+ }
// Make sure that read is drawn even if it too small to be rendered officially; in this case,
// read is drawn at 1px.
@@ -1100,45 +1108,43 @@
break;
case "=": // Match with reference.
case "X": // Mismatch with reference.
- if (is_overlap([seq_start, seq_start + cig_len], tile_region)) {
- //
- // Draw sequence and/or variants.
- //
+ //
+ // Draw sequence and/or variants.
+ //
- // Get sequence to draw.
- var cur_seq = '';
- if (cig_op === 'X') {
- // Get sequence from read_seq.
- cur_seq = read_seq.slice(seq_offset, seq_offset + cig_len);
- }
- else if (this.ref_seq) { // && cig_op === '='
- // Use reference sequence.
- cur_seq = this.ref_seq.slice(
- // If read starts after tile start, slice at read start.
- Math.max(0, seq_start - tile_low),
- // If read ends before tile end, slice at read end.
- Math.min(seq_start - tile_low + cig_len, tile_high - tile_low)
- );
- }
+ // Get sequence to draw.
+ var cur_seq = '';
+ if (cig_op === 'X') {
+ // Get sequence from read_seq.
+ cur_seq = read_seq.slice(seq_offset, seq_offset + cig_len);
+ }
+ else if (this.ref_seq) { // && cig_op === '='
+ // Use reference sequence.
+ cur_seq = this.ref_seq.slice(
+ // If read starts after tile start, slice at read start.
+ Math.max(0, seq_start - tile_low),
+ // If read ends before tile end, slice at read end.
+ Math.min(seq_start - tile_low + cig_len, tile_high - tile_low)
+ );
+ }
- // Draw sequence. Because cur_seq starts and read/tile start, go to there to start writing.
- var start_pos = Math.max(seq_start, tile_low);
- for (var c = 0; c < cur_seq.length; c++) {
- // Draw base if showing all (i.e. not showing differences) or there is a mismatch.
- if (cur_seq && !this.prefs.show_differences || cig_op === 'X') {
- // Draw base.
- var c_start = Math.floor( Math.max(0, (start_pos + c - tile_low) * w_scale) );
- ctx.fillStyle = this.base_color_fn(cur_seq[c]);
- if (pack_mode && w_scale > char_width_px) {
- ctx.fillText(cur_seq[c], c_start, y_start + 9);
- }
- // Require a minimum w_scale so that variants are only drawn when somewhat zoomed in.
- else if (w_scale > 0.05) {
- ctx.fillRect(c_start - gap,
- y_start + (pack_mode ? 1 : 4),
- Math.max( 1, Math.round(w_scale) ),
- (pack_mode ? PACK_FEATURE_HEIGHT : SQUISH_FEATURE_HEIGHT));
- }
+ // Draw sequence. Because cur_seq starts and read/tile start, go to there to start writing.
+ var start_pos = Math.max(seq_start, tile_low);
+ for (var c = 0; c < cur_seq.length; c++) {
+ // Draw base if showing all (i.e. not showing differences) or there is a mismatch.
+ if (cur_seq && !this.prefs.show_differences || cig_op === 'X') {
+ // Draw base.
+ var c_start = Math.floor( Math.max(0, (start_pos + c - tile_low) * w_scale) );
+ ctx.fillStyle = this.base_color_fn(cur_seq[c]);
+ if (pack_mode && w_scale > char_width_px) {
+ ctx.fillText(cur_seq[c], c_start, y_start + 9);
+ }
+ // Require a minimum w_scale so that variants are only drawn when somewhat zoomed in.
+ else if (w_scale > 0.05) {
+ ctx.fillRect(c_start - gap,
+ y_start + (pack_mode ? 1 : 4),
+ Math.max( 1, Math.round(w_scale) ),
+ (pack_mode ? PACK_FEATURE_HEIGHT : SQUISH_FEATURE_HEIGHT));
}
}
}
@@ -1156,8 +1162,7 @@
base_offset += cig_len;
break;
case "D": // Deletion.
- ctx.fillStyle = "black";
- ctx.fillRect(s_start, y_start + 4, s_end - s_start, 3);
+ paint_utils.draw_deletion(s_start, y_start + (pack_mode ? 1 : 4), cig_len);
base_offset += cig_len;
break;
case "I": // Insertion.
@@ -1509,21 +1514,24 @@
/**
* Utilities for painting reads.
*/
-var ReadPainterUtils = function(ctx, row_height, char_width) {
+var ReadPainterUtils = function(ctx, row_height, px_per_base, mode) {
this.ctx = ctx;
this.row_height = row_height;
- this.char_width = char_width;
+ this.px_per_base = px_per_base;
+ this.draw_details = (mode === 'Pack' || mode === 'Auto') && (px_per_base >= ctx.canvas.manager.char_width_px);
+ this.delete_details_thickness = 0.2;
};
extend(ReadPainterUtils.prototype, {
/**
- * Draw deletion of base(s).
+ * Draw deletion of base(s).
+ * @param draw_detail if true, drawing in detail and deletion is drawn more subtly
*/
draw_deletion: function(x, y, len) {
this.ctx.fillStyle = "black";
- var thickness = Math.max( 0.25 * this.row_height, 1 );
+ var thickness = (this.draw_details ? this.delete_details_thickness : 1) * this.row_height;
y += 0.5 * ( this.row_height - thickness );
- this.ctx.fillRect( x, y + 4, len * this.char_width, thickness);
+ this.ctx.fillRect(x, y, len * this.px_per_base, thickness);
}
});
@@ -1631,7 +1639,7 @@
(this.mode === 'Squish' ? SQUISH_FEATURE_HEIGHT : PACK_FEATURE_HEIGHT)
),
draw_summary = true,
- paint_utils = new ReadPainterUtils(ctx, row_height, base_px),
+ paint_utils = new ReadPainterUtils(ctx, row_height, w_scale, this.mode),
j;
// If there's a single sample, update drawing variables.
@@ -1738,15 +1746,15 @@
if (variant.type === 'snp') {
var snp = variant.value;
ctx.fillStyle = this.base_color_fn(snp);
- if (this.mode === 'Squish' || w_scale < ctx.canvas.manager.char_width_px) {
- ctx.fillRect(draw_x_start, draw_y_start + 1, base_px, feature_height);
+ if (paint_utils.draw_details) {
+ ctx.fillText(snp, char_x_start, draw_y_start + row_height);
}
else {
- ctx.fillText(snp, char_x_start, draw_y_start + row_height);
+ ctx.fillRect(draw_x_start, draw_y_start + 1, base_px, feature_height);
}
}
else if (variant.type === 'deletion') {
- paint_utils.draw_deletion(draw_x_start + base_px * variant.start, draw_y_start, variant.len);
+ paint_utils.draw_deletion(draw_x_start + base_px * variant.start, draw_y_start + 1, variant.len);
}
else {
// TODO: handle insertions.
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0