mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-10-16 07:19:13 +08:00
Trackster: enable a tool to be run on complete dataset or a visible region.
This commit is contained in:
@@ -645,16 +645,17 @@ class TracksController( BaseController, UsesVisualization, UsesHistoryDatasetAss
|
||||
return self.tracks_grid( trans, **kwargs )
|
||||
|
||||
@web.expose
|
||||
def run_tool( self, trans, dataset_id, chrom, low, high, tool_id, **kwargs ):
|
||||
def run_tool( self, trans, dataset_id, tool_id, chrom=None, low=None, high=None, **kwargs ):
|
||||
"""
|
||||
Run a tool on a subset of input data to produce a new output dataset that
|
||||
corresponds to a dataset that a user is currently viewing.
|
||||
"""
|
||||
|
||||
# Parameter checks.
|
||||
if not chrom or not low or not high:
|
||||
return messages.NO_DATA
|
||||
low, high = int( low ), int( high )
|
||||
# Run tool on region if region is specificied.
|
||||
run_on_region = False
|
||||
if chrom and low and high:
|
||||
run_on_region = True
|
||||
low, high = int( low ), int( high )
|
||||
|
||||
# Dataset check.
|
||||
original_dataset = self.get_dataset( trans, dataset_id, check_ownership=False, check_accessible=True )
|
||||
@@ -678,27 +679,23 @@ class TracksController( BaseController, UsesVisualization, UsesHistoryDatasetAss
|
||||
tool_params = tool.params_from_strings( tool_params, self.app )
|
||||
|
||||
#
|
||||
# Convert input datasets so that region of dataset can be quickly
|
||||
# extracted.
|
||||
# TODO: Is it useful/necessary to create data subsets for all input
|
||||
# datasets or only the original dataset (aka the dataset that the user
|
||||
# is viewing)? Currently we create data subsets for all input datasets
|
||||
# because this provides the best performance as the tool runs on small
|
||||
# datasets.
|
||||
# If running tool on region, convert input datasets (create indices) so
|
||||
# that can regions of data can be quickly extracted.
|
||||
#
|
||||
messages_list = []
|
||||
for jida in original_job.input_datasets:
|
||||
input_dataset = jida.dataset
|
||||
# TODO: put together more robust way to determine if a dataset can be indexed.
|
||||
if hasattr( input_dataset, 'get_track_type' ):
|
||||
# Can index dataset.
|
||||
track_type, data_sources = input_dataset.datatype.get_track_type()
|
||||
# Convert to datasource that provides 'data' because we need to
|
||||
# extract the original data.
|
||||
data_source = data_sources[ 'data' ]
|
||||
msg = self._convert_dataset( trans, input_dataset, data_source )
|
||||
if msg is not None:
|
||||
messages_list.append( msg )
|
||||
if run_on_region:
|
||||
for jida in original_job.input_datasets:
|
||||
input_dataset = jida.dataset
|
||||
# TODO: put together more robust way to determine if a dataset can be indexed.
|
||||
if hasattr( input_dataset, 'get_track_type' ):
|
||||
# Can index dataset.
|
||||
track_type, data_sources = input_dataset.datatype.get_track_type()
|
||||
# Convert to datasource that provides 'data' because we need to
|
||||
# extract the original data.
|
||||
data_source = data_sources[ 'data' ]
|
||||
msg = self._convert_dataset( trans, input_dataset, data_source )
|
||||
if msg is not None:
|
||||
messages_list.append( msg )
|
||||
|
||||
# Return any messages generated during conversions.
|
||||
return_message = _get_highest_priority_msg( messages_list )
|
||||
@@ -706,41 +703,40 @@ class TracksController( BaseController, UsesVisualization, UsesHistoryDatasetAss
|
||||
return return_message
|
||||
|
||||
#
|
||||
# Set input datasets for tool. Input datasets are subsets of full
|
||||
# datasets and are based on chrom, low, high.
|
||||
# Set target history (the history that tool will use for inputs/outputs).
|
||||
# If user owns dataset, put new data in original dataset's history; if
|
||||
# user does not own dataset (and hence is accessing dataset via sharing),
|
||||
# put new data in user's current history.
|
||||
#
|
||||
|
||||
# If user is rerunning own tool, put new data in original dataset's
|
||||
# history. If another user is running tool, put new data in current
|
||||
# history.
|
||||
if original_dataset.history.user == trans.user:
|
||||
working_history = original_dataset.history
|
||||
target_history = original_dataset.history
|
||||
else:
|
||||
working_history = trans.get_history( create=True )
|
||||
hda_permissions = trans.app.security_agent.history_get_default_permissions( working_history )
|
||||
messages_list = []
|
||||
target_history = trans.get_history( create=True )
|
||||
hda_permissions = trans.app.security_agent.history_get_default_permissions( target_history )
|
||||
|
||||
#
|
||||
# Set input datasets for tool. If running on region, extract and use subset
|
||||
# when possible.
|
||||
#
|
||||
for jida in original_job.input_datasets:
|
||||
input_dataset = jida.dataset
|
||||
if hasattr( input_dataset.datatype, 'get_track_type' ):
|
||||
#
|
||||
# Dataset can be indexed and hence a subset can be extracted.
|
||||
#
|
||||
if run_on_region and hasattr( input_dataset.datatype, 'get_track_type' ):
|
||||
# Dataset is indexed and hence a subset can be extracted and used
|
||||
# as input.
|
||||
track_type, data_sources = input_dataset.datatype.get_track_type()
|
||||
data_source = data_sources[ 'data' ]
|
||||
converted_dataset = input_dataset.get_converted_dataset( trans, data_source )
|
||||
deps = input_dataset.get_converted_dataset_deps( trans, data_source )
|
||||
|
||||
#
|
||||
# Create new HDA for input dataset's subset.
|
||||
#
|
||||
new_dataset = trans.app.model.HistoryDatasetAssociation( extension=input_dataset.ext, \
|
||||
dbkey=input_dataset.dbkey, \
|
||||
create_dataset=True, \
|
||||
sa_session=trans.sa_session,
|
||||
name="Subset [%s:%i-%i] of data %i" % \
|
||||
( chrom, low, high, input_dataset.hid ),
|
||||
visible=False )
|
||||
working_history.add_dataset( new_dataset )
|
||||
dbkey=input_dataset.dbkey, \
|
||||
create_dataset=True, \
|
||||
sa_session=trans.sa_session,
|
||||
name="Subset [%s:%i-%i] of data %i" % \
|
||||
( chrom, low, high, input_dataset.hid ),
|
||||
visible=False )
|
||||
target_history.add_dataset( new_dataset )
|
||||
trans.sa_session.add( new_dataset )
|
||||
trans.app.security_agent.set_all_dataset_permissions( new_dataset.dataset, hda_permissions )
|
||||
|
||||
@@ -751,7 +747,7 @@ class TracksController( BaseController, UsesVisualization, UsesHistoryDatasetAss
|
||||
dependencies=deps )
|
||||
data_provider.write_data_to_file( chrom, low, high, new_dataset.file_name )
|
||||
|
||||
# TODO: size not working.
|
||||
# TODO: (a) size not working; (b) need to set peek.
|
||||
new_dataset.set_size()
|
||||
new_dataset.info = "Data subset for trackster"
|
||||
new_dataset.set_dataset_state( trans.app.model.Dataset.states.OK )
|
||||
@@ -761,18 +757,21 @@ class TracksController( BaseController, UsesVisualization, UsesHistoryDatasetAss
|
||||
tool_params[ jida.name ] = new_dataset
|
||||
|
||||
#
|
||||
# Start tool and handle outputs.
|
||||
# Execute tool and handle outputs.
|
||||
#
|
||||
try:
|
||||
subset_job, subset_job_outputs = tool.execute( trans, incoming=tool_params, history=working_history )
|
||||
subset_job, subset_job_outputs = tool.execute( trans, incoming=tool_params, history=target_history )
|
||||
except Exception, e:
|
||||
# Lots of things can go wrong when trying to execute tool.
|
||||
return to_json_string( { "error" : True, "message" : e.__class__.__name__ + ": " + str(e) } )
|
||||
for output in subset_job_outputs.values():
|
||||
output.visible = False
|
||||
trans.sa_session.flush()
|
||||
|
||||
if run_on_region:
|
||||
for output in subset_job_outputs.values():
|
||||
output.visible = False
|
||||
trans.sa_session.flush()
|
||||
|
||||
#
|
||||
# Return new track that corresponds to the original dataset.
|
||||
#
|
||||
output_name = None
|
||||
for joda in original_job.output_datasets:
|
||||
if joda.dataset == original_dataset:
|
||||
@@ -784,9 +783,9 @@ class TracksController( BaseController, UsesVisualization, UsesHistoryDatasetAss
|
||||
|
||||
return self.add_track_async( trans, output_dataset.id )
|
||||
|
||||
#
|
||||
# -----------------
|
||||
# Helper methods.
|
||||
#
|
||||
# -----------------
|
||||
|
||||
def _check_dataset_state( self, trans, dataset ):
|
||||
"""
|
||||
|
||||
File diff suppressed because one or more lines are too long
+62
-24
@@ -885,11 +885,15 @@ var Tool = function(track, tool_dict) {
|
||||
this.parent_div.find("input").click(function() { $(this).select() });
|
||||
|
||||
// Add 'Go' button.
|
||||
var run_tool_row = $("<div>").addClass("slider-row").appendTo(this.parent_div);
|
||||
var run_tool_button = $("<input type='submit'>").attr("value", "Run").appendTo(run_tool_row);
|
||||
var run_tool_row = $("<div>").addClass("param-row").appendTo(this.parent_div);
|
||||
var run_on_dataset_button = $("<input type='submit'>").attr("value", "Run on complete dataset").appendTo(run_tool_row);
|
||||
var run_on_region_button = $("<input type='submit'>").attr("value", "Run on visible region").css("margin-left", "3em").appendTo(run_tool_row);
|
||||
var tool = this;
|
||||
run_tool_button.click( function() {
|
||||
tool.run();
|
||||
run_on_region_button.click( function() {
|
||||
tool.run_on_region();
|
||||
});
|
||||
run_on_dataset_button.click( function() {
|
||||
tool.run_on_dataset();
|
||||
});
|
||||
};
|
||||
extend(Tool.prototype, {
|
||||
@@ -920,51 +924,87 @@ extend(Tool.prototype, {
|
||||
return param_values;
|
||||
},
|
||||
/**
|
||||
* Run tool. This creates a new child track, runs tool, and places tool's output in the new track.
|
||||
* Run tool on dataset. Output is placed in dataset's history and no changes to viz are made.
|
||||
*/
|
||||
run: function() {
|
||||
// Put together params for running tool.
|
||||
var url_params = {
|
||||
dataset_id: this.track.original_dataset_id,
|
||||
chrom: this.track.view.chrom,
|
||||
low: this.track.view.low,
|
||||
high: this.track.view.high,
|
||||
tool_id: this.name
|
||||
};
|
||||
$.extend(url_params, this.get_param_values_dict());
|
||||
run_on_dataset: function() {
|
||||
var tool = this;
|
||||
tool.run(
|
||||
// URL params.
|
||||
{
|
||||
dataset_id: this.track.original_dataset_id,
|
||||
tool_id: tool.name
|
||||
},
|
||||
// Success callback.
|
||||
function(track_data) {
|
||||
show_modal(tool.name + " is Running",
|
||||
tool.name + " is running on the complete dataset. Tool outputs are in dataset's history.",
|
||||
{ "Close" : hide_modal } );
|
||||
}
|
||||
);
|
||||
|
||||
},
|
||||
/**
|
||||
* Run dataset on visible region. This creates a new track and sets the track's contents
|
||||
* to the tool's output.
|
||||
*/
|
||||
run_on_region: function() {
|
||||
//
|
||||
// Create track for tool's output immediately to provide user feedback.
|
||||
//
|
||||
var
|
||||
url_params =
|
||||
{
|
||||
dataset_id: this.track.original_dataset_id,
|
||||
chrom: this.track.view.chrom,
|
||||
low: this.track.view.low,
|
||||
high: this.track.view.high,
|
||||
tool_id: this.name
|
||||
},
|
||||
current_track = this.track,
|
||||
// Set name of track to include tool name, parameters, and region used.
|
||||
track_name = url_params.tool_id +
|
||||
current_track.tool_region_and_parameters_str(url_params.chrom, url_params.low, url_params.high),
|
||||
new_track;
|
||||
|
||||
// Create and add track.
|
||||
// TODO: add support for other kinds of tool data tracks.
|
||||
if (current_track.track_type === 'FeatureTrack') {
|
||||
new_track = new ToolDataFeatureTrack(track_name, view, current_track.hda_ldda, undefined, {}, {}, current_track);
|
||||
}
|
||||
|
||||
this.track.add_track(new_track);
|
||||
new_track.content_div.text("Starting job.");
|
||||
|
||||
// Run tool.
|
||||
this.run(url_params,
|
||||
// Success callback.
|
||||
function(track_data) {
|
||||
new_track.dataset_id = track_data.dataset_id;
|
||||
new_track.content_div.text("Running job.");
|
||||
new_track.init();
|
||||
}
|
||||
);
|
||||
},
|
||||
/**
|
||||
* Run tool using a set of URL params and a success callback.
|
||||
*/
|
||||
run: function(url_params, success_callback) {
|
||||
// Add tool params to URL params.
|
||||
$.extend(url_params, this.get_param_values_dict());
|
||||
|
||||
// Run tool.
|
||||
var json_run_tool = function() {
|
||||
$.getJSON(run_tool_url, url_params, function(track_data) {
|
||||
if (track_data === "no converter") {
|
||||
$.getJSON(run_tool_url, url_params, function(response) {
|
||||
if (response === "no converter") {
|
||||
// No converter available for input datasets, so cannot run tool.
|
||||
new_track.container_div.addClass("error");
|
||||
new_track.content_div.text(DATA_NOCONVERTER);
|
||||
}
|
||||
else if (track_data.error) {
|
||||
else if (response.error) {
|
||||
// General error.
|
||||
new_track.container_div.addClass("error");
|
||||
new_track.content_div.text(DATA_CANNOT_RUN_TOOL + track_data.message);
|
||||
new_track.content_div.text(DATA_CANNOT_RUN_TOOL + response.message);
|
||||
}
|
||||
else if (track_data === "pending") {
|
||||
else if (response === "pending") {
|
||||
// Converting/indexing input datasets; show message and try again.
|
||||
new_track.container_div.addClass("pending");
|
||||
new_track.content_div.text("Converting input data so that it can be easily reused.");
|
||||
@@ -972,9 +1012,7 @@ extend(Tool.prototype, {
|
||||
}
|
||||
else {
|
||||
// Job submitted and running.
|
||||
new_track.dataset_id = track_data.dataset_id;
|
||||
new_track.content_div.text("Running job.");
|
||||
new_track.init();
|
||||
success_callback(response);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user