trackster: support BAM visualization with samtools, automatically enable tracks for any datatype with "get_track_type" defined

This commit is contained in:
Kanwei Li
2010-01-07 15:45:15 -05:00
parent c7b78b9f5d
commit 4ca761e9cc
12 changed files with 117 additions and 46 deletions
+3 -1
View File
@@ -3,7 +3,9 @@
<registration converters_path="lib/galaxy/datatypes/converters">
<datatype extension="ab1" type="galaxy.datatypes.binary:Ab1" mimetype="application/octet-stream" display_in_upload="true"/>
<datatype extension="axt" type="galaxy.datatypes.sequence:Axt" display_in_upload="true"/>
<datatype extension="bam" type="galaxy.datatypes.binary:Bam" mimetype="application/octet-stream" display_in_upload="true"/>
<datatype extension="bam" type="galaxy.datatypes.binary:Bam" mimetype="application/octet-stream" display_in_upload="true">
<converter file="bam_to_bai.xml" target_datatype="bai"/>
</datatype>
<datatype extension="bed" type="galaxy.datatypes.interval:Bed" display_in_upload="true">
<converter file="bed_to_gff_converter.xml" target_datatype="gff"/>
<converter file="interval_to_coverage.xml" target_datatype="coverage"/>
+2
View File
@@ -19,6 +19,7 @@ MySQL_python = 1.2.2
pbs_python = 2.9.4
psycopg2 = 2.0.6
pycrypto = 2.0.1
pysam = 0.1.1
pysqlite = 2.5.6
python_lzo = 1.08
threadframe = 0.2
@@ -74,6 +75,7 @@ MySQL_python = http://superb-west.dl.sourceforge.net/sourceforge/mysql-python/My
pbs_python = http://ftp.sara.nl/pub/outgoing/pbs_python-2.9.4.tar.gz
psycopg2 = http://initd.org/pub/software/psycopg/PSYCOPG-2-0/psycopg2-2.0.6.tar.gz ftp://ftp-archives.postgresql.org/pub/source/v8.2.6/postgresql-8.2.6.tar.bz2
pycrypto = http://www.amk.ca/files/python/crypto/pycrypto-2.0.1.tar.gz
pysam = http://bitbucket.org/kanwei/kanwei-pysam/get/e3c601a062fd.gz
pysqlite = http://pypi.python.org/packages/source/p/pysqlite/pysqlite-2.5.6.tar.gz
python_lzo = http://www.oberhumer.com/opensource/lzo/download/LZO-v1/python-lzo-1.08.tar.gz http://www.oberhumer.com/opensource/lzo/download/LZO-v1/lzo-1.08.tar.gz
threadframe = http://www.majid.info/python/threadframe/threadframe-0.2.tar.gz
+3 -1
View File
@@ -132,7 +132,9 @@ class Bam( Binary ):
return dataset.peek
except:
return "Binary bam alignments file (%s)" % ( data.nice_size( dataset.get_size() ) )
def get_track_type( self ):
return "ReadTrack", "bai"
class Binseq( Binary ):
"""Class describing a zip archive of binary sequence files"""
file_ext = "binseq.zip"
-2
View File
@@ -63,6 +63,4 @@ class LastzCoverage( Tabular ):
resolution = max( resolution, 1 )
return resolution
def get_track_type( self ):
return "LineTrack"
+4 -3
View File
@@ -325,8 +325,6 @@ class Interval( Tabular ):
def get_track_resolution( self, dataset, start, end):
return None
def get_track_type( self ):
return "FeatureTrack"
class Bed( Interval ):
"""Tab delimited data in BED format"""
@@ -484,6 +482,9 @@ class Bed( Interval ):
else: return False
return True
except: return False
def get_track_type( self ):
return "FeatureTrack", "interval_index"
class _RemoteCallMixin:
def _get_remote_call_url( self, redirect_url, site_name, dataset, type, app, base_url ):
@@ -904,7 +905,7 @@ class Wiggle( Tabular, _RemoteCallMixin ):
resolution = max( resolution, 1 )
return resolution
def get_track_type( self ):
return "LineTrack"
return "LineTrack", "array_tree"
class CustomTrack ( Tabular ):
"""UCSC CustomTrack"""
+7 -1
View File
@@ -18,6 +18,7 @@ class Registry( object ):
self.datatype_converters = odict()
self.datatype_indexers = odict()
self.converters = []
self.available_tracks = []
self.set_external_metadata_tool = None
self.indexers = []
self.sniff_order = []
@@ -54,6 +55,8 @@ class Registry( object ):
# Use default mime type as per datatype spec
mimetype = self.datatypes_by_extension[extension].get_mime()
self.mimetypes_by_extension[extension] = mimetype
if hasattr( getattr( module, datatype_class ), "get_track_type" ):
self.available_tracks.append( extension )
if display_in_upload:
self.upload_file_formats.append( extension )
for converter in elem.findall( 'converter' ):
@@ -206,7 +209,10 @@ class Registry( object ):
if not included:
self.sniff_order.append(datatype)
append_to_sniff_order()
def get_available_tracks(self):
return self.available_tracks
def get_mimetype_by_extension(self, ext ):
"""Returns a mimetype based on an extension"""
try:
+16 -22
View File
@@ -23,35 +23,26 @@ from galaxy.util.bunch import Bunch
from galaxy.visualization.tracks.data.array_tree import ArrayTreeDataProvider
from galaxy.visualization.tracks.data.interval_index import IntervalIndexDataProvider
from galaxy.visualization.tracks.data.bam import BamDataProvider
# Message strings returned to browser
messages = Bunch(
PENDING = "pending",
NO_DATA = "no data",
NO_CHROMOSOME = "no chromosome",
NO_CONVERTER = "no converter",
DATA = "data",
ERROR = "error"
)
# Dataset type required for each track type. This needs to be more flexible,
# there might be multiple types of indexes that suffice for a given track type.
track_type_to_dataset_type = {
"line": "array_tree",
"feature": "interval_index"
}
# Mapping from dataset type to a class that can fetch data from a file of that
# type. This also needs to be more flexible.
dataset_type_to_data_provider = {
"array_tree": ArrayTreeDataProvider,
"interval_index": IntervalIndexDataProvider
"interval_index": IntervalIndexDataProvider,
"bai": BamDataProvider
}
# FIXME: hardcoding this for now, but it should be derived from the available
# converters
browsable_types = ( "wig", "bed" )
class TracksController( BaseController ):
"""
Controller for track browser interface. Handles building a new browser from
@@ -107,11 +98,12 @@ class TracksController( BaseController ):
# Find all datasets in the current history that are of that dbkey
# and can be displayed
datasets = {}
available_tracks = trans.app.datatypes_registry.get_available_tracks()
for dataset in session.query( model.HistoryDatasetAssociation ).filter_by( deleted=False, history_id=trans.history.id ):
if dataset.metadata.dbkey == dbkey and dataset.extension in browsable_types:
if dataset.metadata.dbkey == dbkey and dataset.extension in available_tracks:
datasets[dataset.id] = (dataset.extension, dataset.name)
# Render the template
return trans.fill_template( "tracks/new_browser.mako", converters=browsable_types, dbkey=dbkey, dbkey_set=dbkey_set, datasets=datasets )
return trans.fill_template( "tracks/new_browser.mako", available_tracks=available_tracks, dbkey=dbkey, dbkey_set=dbkey_set, datasets=datasets )
@web.expose
def browser(self, trans, id, chrom=""):
@@ -127,8 +119,10 @@ class TracksController( BaseController ):
for t in vis.latest_revision.config['tracks']:
dataset_id = t['dataset_id']
dataset = hda_query.get( dataset_id )
track_type, indexer = dataset.datatype.get_track_type()
tracks.append( {
"type": dataset.datatype.get_track_type(),
"type": track_type,
"indexer": indexer,
"name": dataset.name,
"dataset_id": dataset.id
} )
@@ -184,14 +178,14 @@ class TracksController( BaseController ):
return manifest
@web.json
def data( self, trans, dataset_id, track_type, chrom, low, high, **kwargs ):
def data( self, trans, dataset_id, indexer, chrom, low, high, **kwargs ):
"""
Called by the browser to request a block of data
"""
# Load the requested dataset
dataset = trans.sa_session.query( trans.app.model.HistoryDatasetAssociation ).get( dataset_id )
# No dataset for that id
if not dataset:
if not dataset or not chrom:
return messages.NO_DATA
# Dataset is in error state, can't display
if dataset.state == trans.app.model.Job.states.ERROR:
@@ -200,12 +194,11 @@ class TracksController( BaseController ):
if dataset.state != trans.app.model.Job.states.OK:
return messages.PENDING
# Determine what to return based on the type of track being drawn.
converted_dataset_type = track_type_to_dataset_type[track_type]
converted_dataset_type = indexer
converted_dataset = self.__dataset_as_type( trans, dataset, converted_dataset_type )
# If at this point we still don't have an `array_tree_dataset`, there
# is no way we can display this data as an array tree
if not converted_dataset:
return messages.ERROR
# No converter
return messages.NO_CONVERTER
# Need to check states again for the converted version
if converted_dataset.state == model.Dataset.states.ERROR:
return messages.ERROR
@@ -228,6 +221,7 @@ class TracksController( BaseController ):
converted dataset (possibly new) is returned, if it cannot be converted,
None is returned.
"""
log.debug("Inside dataset as type")
# Already of correct type
if dataset.extension == type:
return dataset
+1 -1
View File
@@ -1 +1 @@
function ensure_dd_helper(){if($("#DD-helper").length==0){$("<div id='DD-helper'/>").css({background:"white",opacity:0,zIndex:9000,position:"absolute",top:0,left:0,width:"100%",height:"100%"}).appendTo("body").hide()}}function make_left_panel(h,c,e){var g=false;var f=null;var d=function(i){var j=i;if(i<0){i=0}$(h).css("width",i);$(e).css("left",j);$(c).css("left",i+7);if(document.recalc){document.recalc()}};var a=function(){if(g){$(e).removeClass("hover");$(e).animate({left:f},"fast");$(h).css("left",-f).show().animate({left:0},"fast",function(){d(f);$(e).removeClass("hidden")});g=false}else{f=$(e).position().left;$(c).css("left",$(e).innerWidth());if(document.recalc){document.recalc()}$(e).removeClass("hover");$(h).animate({left:-f},"fast");$(e).animate({left:-1},"fast",function(){$(this).addClass("hidden")});g=true}};$(e).hover(function(){$(this).addClass("hover")},function(){$(this).removeClass("hover")}).bind("dragstart",function(i){$("#DD-helper").show()}).bind("dragend",function(i){$("#DD-helper").hide()}).bind("drag",function(i){x=i.offsetX;x=Math.min(400,Math.max(100,x));if(g){$(h).css("left",0);$(e).removeClass("hidden");g=false}d(x)}).bind("dragclickonly",function(i){a()}).find("div").show();var b=function(i){if((g&&i=="show")||(!g&&i=="hide")){a()}};return{force_panel:b}}function make_right_panel(a,e,h){var j=false;var g=false;var c=null;var d=function(k){$(a).css("width",k);$(e).css("right",k+9);$(h).css("right",k).css("left","");if(document.recalc){document.recalc()}};var i=function(){if(j){$(h).removeClass("hover");$(h).animate({right:c},"fast");$(a).css("right",-c).show().animate({right:0},"fast",function(){d(c);$(h).removeClass("hidden")});j=false}else{c=$(document).width()-$(h).position().left-$(h).outerWidth();$(e).css("right",$(h).innerWidth()+1);if(document.recalc){document.recalc()}$(h).removeClass("hover");$(a).animate({right:-c},"fast");$(h).animate({right:-1},"fast",function(){$(this).addClass("hidden")});j=true}g=false};var b=function(k){var l=$(e).width()-(j?c:0);if(l<k){if(!j){i();g=true}}else{if(g){i();g=false}}};$(h).hover(function(){$(this).addClass("hover")},function(){$(this).removeClass("hover")}).bind("dragstart",function(k){$("#DD-helper").show()}).bind("dragend",function(k){$("#DD-helper").hide()}).bind("drag",function(k){x=k.offsetX;w=$(window).width();x=Math.min(w-100,x);x=Math.max(w-400,x);if(j){$(a).css("right",0);$(h).removeClass("hidden");j=false}d(w-x-$(this).outerWidth())}).bind("dragclickonly",function(k){i()}).find("div").show();var f=function(k){if((j&&k=="show")||(!j&&k=="hide")){i()}};return{handle_minwidth_hint:b,force_panel:f}}function hide_modal(){$(".dialog-box-container").fadeOut(function(){$("#overlay").hide();$(".dialog-box").find(".body").children().remove()})}function show_modal(f,c,e,d){if(f){$(".dialog-box").find(".title").html(f);$(".dialog-box").find(".unified-panel-header").show()}else{$(".dialog-box").find(".unified-panel-header").hide()}var a=$(".dialog-box").find(".buttons").html("");if(e){$.each(e,function(b,g){a.append($("<button/>").text(b).click(g));a.append(" ")});a.show()}else{a.hide()}var a=$(".dialog-box").find(".extra_buttons").html("");if(d){$.each(d,function(b,g){a.append($("<button/>").text(b).click(g));a.append(" ")});a.show()}else{a.hide()}if(c=="progress"){c=$("<img src='../images/yui/rel_interstitial_loading.gif')' />")}$(".dialog-box").find(".body").html(c);if(!$(".dialog-box-container").is(":visible")){$("#overlay").show();$(".dialog-box-container").fadeIn()}}function show_in_overlay(c){var d=c.width||"600";var b=c.height||"400";var a=c.scroll||"auto";$("#overlay-background").bind("click.overlay",function(){hide_modal();$("#overlay-background").unbind("click.overlay")});show_modal(null,$("<div style='margin: -5px;'><iframe style='margin: 0; padding: 0;' src='"+c.url+"' width='"+d+"' height='"+b+"' scrolling='"+a+"' frameborder='0'></iframe></div>"))}$(function(){$(".tab").each(function(){var a=$(this).children(".submenu");if(a.length>0){if($.browser.msie){a.prepend("<iframe style=\"position: absolute; top: 0; left: 0; width: 100%; height: 100%; z-index: -1; filter:Alpha(Opacity='0');\"></iframe>")}$(this).hover(function(){a.show()},function(){a.hide()});a.click(function(){a.hide()})}})});function user_changed(a,b){if(a){$(".loggedin-only").show();$(".loggedout-only").hide();$("#user-email").text(a);if(b){$(".admin-only").show()}}else{$(".loggedin-only").hide();$(".loggedout-only").show();$(".admin-only").hide()}};
function ensure_dd_helper(){if($("#DD-helper").length==0){$("<div id='DD-helper'/>").css({background:"white",opacity:0,zIndex:9000,position:"absolute",top:0,left:0,width:"100%",height:"100%"}).appendTo("body").hide()}}function make_left_panel(h,c,e){var g=false;var f=null;var d=function(i){var j=i;if(i<0){i=0}$(h).css("width",i);$(e).css("left",j);$(c).css("left",i+7);if(document.recalc){document.recalc()}};var a=function(){if(g){$(e).removeClass("hover");$(e).animate({left:f},"fast");$(h).css("left",-f).show().animate({left:0},"fast",function(){d(f);$(e).removeClass("hidden")});g=false}else{f=$(e).position().left;$(c).css("left",$(e).innerWidth());if(document.recalc){document.recalc()}$(e).removeClass("hover");$(h).animate({left:-f},"fast");$(e).animate({left:-1},"fast",function(){$(this).addClass("hidden")});g=true}};$(e).hover(function(){$(this).addClass("hover")},function(){$(this).removeClass("hover")}).bind("dragstart",function(i){$("#DD-helper").show()}).bind("dragend",function(i){$("#DD-helper").hide()}).bind("drag",function(i){x=i.offsetX;x=Math.min(400,Math.max(100,x));if(g){$(h).css("left",0);$(e).removeClass("hidden");g=false}d(x)}).bind("dragclickonly",function(i){a()}).find("div").show();var b=function(i){if((g&&i=="show")||(!g&&i=="hide")){a()}};return{force_panel:b}}function make_right_panel(a,e,h){var j=false;var g=false;var c=null;var d=function(k){$(a).css("width",k);$(e).css("right",k+9);$(h).css("right",k).css("left","");if(document.recalc){document.recalc()}};var i=function(){if(j){$(h).removeClass("hover");$(h).animate({right:c},"fast");$(a).css("right",-c).show().animate({right:0},"fast",function(){d(c);$(h).removeClass("hidden")});j=false}else{c=$(document).width()-$(h).position().left-$(h).outerWidth();$(e).css("right",$(h).innerWidth()+1);if(document.recalc){document.recalc()}$(h).removeClass("hover");$(a).animate({right:-c},"fast");$(h).animate({right:-1},"fast",function(){$(this).addClass("hidden")});j=true}g=false};var b=function(k){var l=$(e).width()-(j?c:0);if(l<k){if(!j){i();g=true}}else{if(g){i();g=false}}};$(h).hover(function(){$(this).addClass("hover")},function(){$(this).removeClass("hover")}).bind("dragstart",function(k){$("#DD-helper").show()}).bind("dragend",function(k){$("#DD-helper").hide()}).bind("drag",function(k){x=k.offsetX;w=$(window).width();x=Math.min(w-100,x);x=Math.max(w-400,x);if(j){$(a).css("right",0);$(h).removeClass("hidden");j=false}d(w-x-$(this).outerWidth())}).bind("dragclickonly",function(k){i()}).find("div").show();var f=function(k){if((j&&k=="show")||(!j&&k=="hide")){i()}};return{handle_minwidth_hint:b,force_panel:f}}function hide_modal(){$(".dialog-box-container").fadeOut(function(){$("#overlay").hide();$(".dialog-box").find(".body").children().remove()})}function show_modal(f,c,e,d){if(f){$(".dialog-box").find(".title").html(f);$(".dialog-box").find(".unified-panel-header").show()}else{$(".dialog-box").find(".unified-panel-header").hide()}var a=$(".dialog-box").find(".buttons").html("");if(e){$.each(e,function(b,g){a.append($("<button/>").text(b).click(g));a.append(" ")});a.show()}else{a.hide()}var a=$(".dialog-box").find(".extra_buttons").html("");if(d){$.each(d,function(b,g){a.append($("<button/>").text(b).click(g));a.append(" ")});a.show()}else{a.hide()}if(c=="progress"){c=$("<img src='../images/yui/rel_interstitial_loading.gif')' />")}$(".dialog-box").find(".body").html(c);if(!$(".dialog-box-container").is(":visible")){$("#overlay").show();$(".dialog-box-container").fadeIn()}}function show_in_overlay(c){var d=c.width||"600";var b=c.height||"400";var a=c.scroll||"auto";$("#overlay-background").bind("click.overlay",function(){hide_modal();$("#overlay-background").unbind("click.overlay")});show_modal(null,$("<div style='margin: -5px;'><img id='close_button' style='position:absolute;right:3px;top:3px;' src='../images/icon_error_sml.gif'><iframe style='margin: 0; padding: 0;' src='"+c.url+"' width='"+d+"' height='"+b+"' scrolling='"+a+"' frameborder='0'></iframe></div>"));$("#close_button").bind("click",function(){hide_modal()})}$(function(){$(".tab").each(function(){var a=$(this).children(".submenu");if(a.length>0){if($.browser.msie){a.prepend("<iframe style=\"position: absolute; top: 0; left: 0; width: 100%; height: 100%; z-index: -1; filter:Alpha(Opacity='0');\"></iframe>")}$(this).hover(function(){a.show()},function(){a.hide()});a.click(function(){a.hide()})}})});function user_changed(a,b){if(a){$(".loggedin-only").show();$(".loggedout-only").hide();$("#user-email").text(a);if(b){$(".admin-only").show()}}else{$(".loggedin-only").hide();$(".loggedout-only").show();$(".admin-only").hide()}};
File diff suppressed because one or more lines are too long
+77 -11
View File
@@ -81,7 +81,7 @@ var View = function( chrom, max_high ) {
this.max_high = max_high;
this.center = (this.max_high - this.max_low) / 2;
this.span = this.max_high - this.max_low;
this.zoom_factor = 2;
this.zoom_factor = 3;
this.zoom_level = 0;
};
$.extend( View.prototype, {
@@ -241,12 +241,12 @@ $.extend( LabelTrack.prototype, Track.prototype, {
}
});
var LineTrack = function ( name, dataset_id, height ) {
var LineTrack = function ( name, dataset_id, indexer, height ) {
this.tile_cache = new Cache(CACHED_TILES_LINE);
Track.call( this, name, $("#viewport") );
TiledTrack.call( this );
this.track_type = "line";
this.indexer = indexer;
this.height_px = (height ? height : 100);
this.container_div.addClass( "line-track" );
this.dataset_id = dataset_id;
@@ -258,7 +258,7 @@ $.extend( LineTrack.prototype, TiledTrack.prototype, {
init: function() {
var track = this;
track.content_div.text(DATA_LOADING);
$.getJSON( data_url, { stats: true, track_type: track.track_type,
$.getJSON( data_url, { stats: true, indexer: track.indexer,
chrom: track.view.chrom, low: null, high: null,
dataset_id: track.dataset_id }, function ( data ) {
if (!data || data == "error") {
@@ -300,7 +300,7 @@ $.extend( LineTrack.prototype, TiledTrack.prototype, {
if (!track.data_queue[key]) {
track.data_queue[key] = true;
$.getJSON( data_url, { track_type: this.track_type, chrom: this.view.chrom,
$.getJSON( data_url, { indexer: this.indexer, chrom: this.view.chrom,
low: low, high: high, dataset_id: this.dataset_id,
resolution: this.view.resolution }, function ( data ) {
track.cache.set(key, data);
@@ -360,12 +360,12 @@ $.extend( LineTrack.prototype, TiledTrack.prototype, {
}
});
var FeatureTrack = function ( name, dataset_id, height ) {
var FeatureTrack = function ( name, dataset_id, indexer, height ) {
this.tile_cache = new Cache(CACHED_TILES_FEATURE);
Track.call( this, name, $("#viewport") );
TiledTrack.call( this );
this.track_type = "feature";
this.indexer = indexer;
this.height_px = (height ? height : 100);
this.container_div.addClass( "feature-track" );
this.dataset_id = dataset_id;
@@ -384,7 +384,7 @@ $.extend( FeatureTrack.prototype, TiledTrack.prototype, {
init: function() {
var track = this;
track.content_div.text(DATA_LOADING);
$.getJSON( data_url, { track_type: track.track_type, low: track.view.max_low,
$.getJSON( data_url, { indexer: track.indexer, low: track.view.max_low,
high: track.view.max_high, dataset_id: track.dataset_id,
chrom: track.view.chrom }, function ( data ) {
if (data == "error") {
@@ -414,7 +414,7 @@ $.extend( FeatureTrack.prototype, TiledTrack.prototype, {
if (!track.data_queue[key]) {
track.data_queue[key] = true;
$.getJSON( data_url, { track_type: track.track_type, chrom: track.view.chrom,
$.getJSON( data_url, { indexer: track.indexer, chrom: track.view.chrom,
low: low, high: high, dataset_id: track.dataset_id,
include_blocks: true }, function ( data ) {
track.data_cache.set(key, data);
@@ -454,8 +454,6 @@ $.extend( FeatureTrack.prototype, TiledTrack.prototype, {
if (!this.inc_slots[level]) {
this.inc_slots[level] = {};
this.inc_slots[level].w_scale = DENSITY / Math.pow(FEATURE_LEVELS, level+1);
// this.inc_slots[level].w_scale = 1000 / (this.view.high - this.view.low);
}
var slots = this.inc_slots[level];
// console.log(level, slots.w_scale, slots);
@@ -629,3 +627,71 @@ $.extend( FeatureTrack.prototype, TiledTrack.prototype, {
return new_canvas;
}
});
var ReadTrack = function ( name, dataset_id, indexer, height ) {
this.tile_cache = new Cache(CACHED_TILES_FEATURE);
Track.call( this, name, $("#viewport") );
TiledTrack.call( this );
FeatureTrack.call( this, name, dataset_id, indexer, height );
this.default_font = "9px Monaco, Lucida Console, monospace";
};
$.extend( ReadTrack.prototype, TiledTrack.prototype, FeatureTrack.prototype, {
draw_tile: function( resolution, tile_index, parent_element, w_scale ) {
if (!this.values) {
return;
}
var tile_low = tile_index * DENSITY * resolution,
tile_high = ( tile_index + 1 ) * DENSITY * resolution,
tile_span = DENSITY * resolution;
// console.log("drawing " + tile_index);
// Once we zoom in enough, show name labels
var data, slots, required_height;
required_height = this.height_px;
slots = this.zo_slots;
data = this.values;
// console.log(tile_low, tile_high, tile_length, w_scale);
var width = Math.ceil( tile_span * w_scale ),
new_canvas = $("<canvas class='tile'></canvas>");
var dummy_canvas = $("<canvas></canvas>").get(0).getContext("2d");
new_canvas.css({
position: "absolute",
top: 0,
left: ( tile_low - this.view.low ) * w_scale - this.left_offset
});
new_canvas.get(0).width = width + this.left_offset;
new_canvas.get(0).height = required_height;
// console.log(( tile_low - this.view.low ) * w_scale, tile_index, w_scale);
var ctx = new_canvas.get(0).getContext("2d");
ctx.fillStyle = this.base_color;
ctx.font = this.default_font;
ctx.textAlign = "right";
var px_per_char = ctx.measureText("A").width;
var j = 0;
for (var i = 0, len = data.length; i < len; i++) {
var feature = data[i];
if (feature.start <= tile_high && feature.end >= tile_low) {
var f_start = Math.floor( Math.max(0, (feature.start - tile_low) * w_scale) ),
f_end = Math.ceil( Math.min(width, (feature.end - tile_low) * w_scale) ),
y_center = slots[feature.uid] * this.vertical_gap;
var thickness, y_start, thick_start = null, thick_end = null;
if (w_scale > px_per_char) {
for (var c = 0, str_len = feature.name.length; c < str_len; c++) {
var c_start = Math.floor( Math.max(0, (feature.start + c - tile_low) * w_scale) );
ctx.fillText(feature.name[c], c_start + this.left_offset, y_center + 8);
}
} else {
ctx.fillRect(f_start + this.left_offset, y_center + 4, f_end - f_start, 3);
}
}
}
parent_element.append( new_canvas );
return new_canvas;
}
});
+1 -1
View File
@@ -20,7 +20,7 @@ ${h.js( "jquery", "jquery.event.drag", "jquery.mousewheel", "trackster" )}
view.add_track( new LabelTrack( $("#nav-labeltrack" ) ) );
%for track in tracks:
view.add_track( new ${track["type"]}( "${track['name']}", ${track['dataset_id']} ) );
view.add_track( new ${track["type"]}( "${track['name']}", ${track['dataset_id']}, "${track['indexer']}" ) );
%endfor
$(document).bind( "redraw", function( e ) {
+2 -2
View File
@@ -11,7 +11,7 @@ $( function() {
</script>
</%def>
% if not converters:
% if not available_tracks:
<div class="errormessagelarge">
There are no available converters needed for visualization. Please verify that your tool_conf.xml file contains
converters for datatypes (see tool_conf.xml.sample) for examples.
@@ -46,7 +46,7 @@ $( function() {
<div style="clear: both;"></div>
</div>
<div class="form-row">
<label for="dataset_ids">Datasets to include: </label>
<label for="dataset_ids">Datasets to visualize: (${", ".join(available_tracks)} files are supported)</label>
%for dataset_id, (dataset_ext, dataset_name) in datasets.iteritems():
<div>
<input type="checkbox" id="${dataset_id}" name="dataset_ids" value="${dataset_id}" />