details:
http://www.bx.psu.edu/hg/galaxy/rev/7d3667e8e415
changeset: 3216:7d3667e8e415
user: Kanwei Li <kanwei(a)gmail.com>
date: Thu Jan 07 15:45:15 2010 -0500
description:
trackster: support BAM visualization with samtools, automatically enable tracks for any
datatype with "get_track_type" defined
diffstat:
datatypes_conf.xml.sample | 4 +-
eggs.ini | 2 +
lib/galaxy/datatypes/binary.py | 4 +-
lib/galaxy/datatypes/coverage.py | 2 -
lib/galaxy/datatypes/interval.py | 7 +-
lib/galaxy/datatypes/registry.py | 8 ++-
lib/galaxy/web/controllers/tracks.py | 38 ++++++--------
static/scripts/packed/galaxy.panels.js | 2 +-
static/scripts/packed/trackster.js | 2 +-
static/scripts/trackster.js | 88 +++++++++++++++++++++++++++++----
templates/tracks/browser.mako | 2 +-
templates/tracks/new_browser.mako | 4 +-
12 files changed, 117 insertions(+), 46 deletions(-)
diffs (439 lines):
diff -r 427d93bf3d39 -r 7d3667e8e415 datatypes_conf.xml.sample
--- a/datatypes_conf.xml.sample Thu Jan 07 14:52:51 2010 -0500
+++ b/datatypes_conf.xml.sample Thu Jan 07 15:45:15 2010 -0500
@@ -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"/>
diff -r 427d93bf3d39 -r 7d3667e8e415 eggs.ini
--- a/eggs.ini Thu Jan 07 14:52:51 2010 -0500
+++ b/eggs.ini Thu Jan 07 15:45:15 2010 -0500
@@ -19,6 +19,7 @@
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 @@
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.t...
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
diff -r 427d93bf3d39 -r 7d3667e8e415 lib/galaxy/datatypes/binary.py
--- a/lib/galaxy/datatypes/binary.py Thu Jan 07 14:52:51 2010 -0500
+++ b/lib/galaxy/datatypes/binary.py Thu Jan 07 15:45:15 2010 -0500
@@ -132,7 +132,9 @@
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"
diff -r 427d93bf3d39 -r 7d3667e8e415 lib/galaxy/datatypes/coverage.py
--- a/lib/galaxy/datatypes/coverage.py Thu Jan 07 14:52:51 2010 -0500
+++ b/lib/galaxy/datatypes/coverage.py Thu Jan 07 15:45:15 2010 -0500
@@ -63,6 +63,4 @@
resolution = max( resolution, 1 )
return resolution
- def get_track_type( self ):
- return "LineTrack"
diff -r 427d93bf3d39 -r 7d3667e8e415 lib/galaxy/datatypes/interval.py
--- a/lib/galaxy/datatypes/interval.py Thu Jan 07 14:52:51 2010 -0500
+++ b/lib/galaxy/datatypes/interval.py Thu Jan 07 15:45:15 2010 -0500
@@ -325,8 +325,6 @@
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 @@
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 @@
resolution = max( resolution, 1 )
return resolution
def get_track_type( self ):
- return "LineTrack"
+ return "LineTrack", "array_tree"
class CustomTrack ( Tabular ):
"""UCSC CustomTrack"""
diff -r 427d93bf3d39 -r 7d3667e8e415 lib/galaxy/datatypes/registry.py
--- a/lib/galaxy/datatypes/registry.py Thu Jan 07 14:52:51 2010 -0500
+++ b/lib/galaxy/datatypes/registry.py Thu Jan 07 15:45:15 2010 -0500
@@ -18,6 +18,7 @@
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 @@
# 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 @@
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:
diff -r 427d93bf3d39 -r 7d3667e8e415 lib/galaxy/web/controllers/tracks.py
--- a/lib/galaxy/web/controllers/tracks.py Thu Jan 07 14:52:51 2010 -0500
+++ b/lib/galaxy/web/controllers/tracks.py Thu Jan 07 15:45:15 2010 -0500
@@ -23,35 +23,26 @@
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 @@
# 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 @@
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 @@
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 @@
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 @@
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
diff -r 427d93bf3d39 -r 7d3667e8e415 static/scripts/packed/galaxy.panels.js
--- a/static/scripts/packed/galaxy.panels.js Thu Jan 07 14:52:51 2010 -0500
+++ b/static/scripts/packed/galaxy.panels.js Thu Jan 07 15:45:15 2010 -0500
@@ -1,1 +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=$(".dia
log-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()}};
\ No newline at end of file
+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=$(".dia
log-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+"' sc
rolling='"+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()}};
\ No newline at end of file
diff -r 427d93bf3d39 -r 7d3667e8e415 static/scripts/packed/trackster.js
--- a/static/scripts/packed/trackster.js Thu Jan 07 14:52:51 2010 -0500
+++ b/static/scripts/packed/trackster.js Thu Jan 07 15:45:15 2010 -0500
@@ -1,1 +1,1 @@
-var DEBUG=false;var DENSITY=1000,FEATURE_LEVELS=100,DATA_ERROR="There was an error
in indexing this dataset.",DATA_NONE="No data for this
chrom/contig.",DATA_PENDING="Currently indexing... please
wait",DATA_LOADING="Loading
data...",CACHED_TILES_FEATURE=10,CACHED_TILES_LINE=30,CACHED_DATA=20,CONTEXT=$("<canvas></canvas>").get(0).getContext("2d"),RIGHT_STRAND,LEFT_STRAND;var
right_img=new
Image();right_img.src="../images/visualization/strand_right.png";right_img.onload=function(){RIGHT_STRAND=CONTEXT.createPattern(right_img,"repeat")};var
left_img=new
Image();left_img.src="../images/visualization/strand_left.png";left_img.onload=function(){LEFT_STRAND=CONTEXT.createPattern(left_img,"repeat")};var
right_img_inv=new
Image();right_img_inv.src="../images/visualization/strand_right_inv.png";right_img_inv.onload=function(){RIGHT_STRAND_INV=CONTEXT.createPattern(right_img_inv,"repeat")};var
left_img_inv=new
Image();left_img_inv.src="../images/visualization/strand_left_inv.png";left_
img_inv.onload=function(){LEFT_STRAND_INV=CONTEXT.createPattern(left_img_inv,"repeat")};function
commatize(b){b+="";var
a=/(\d+)(\d{3})/;while(a.test(b)){b=b.replace(a,"$1,$2")}return b}var
Cache=function(a){this.num_elements=a;this.obj_cache={};this.key_ary=[]};$.extend(Cache.prototype,{get:function(b){var
a=this.key_ary.indexOf(b);if(a!=-1){this.key_ary.splice(a,1);this.key_ary.push(b)}return
this.obj_cache[b]},set:function(b,c){if(!this.obj_cache[b]){if(this.key_ary.length>=this.num_elements){var
a=this.key_ary.shift();delete
this.obj_cache[a]}this.key_ary.push(b)}this.obj_cache[b]=c;return c}});var
View=function(b,a){this.chrom=b;this.tracks=[];this.max_low=0;this.max_high=a;this.center=(this.max_high-this.max_low)/2;this.span=this.max_high-this.max_low;this.zoom_factor=2;this.zoom_level=0};$.extend(View.prototype,{add_track:function(a){a.view=this;this.tracks.push(a);if(a.init){a.init()}},redraw:function(){var
d=this.span/Math.pow(this.zoom_factor,this.zoom_level),b=thi
s.center-(d/2),e=b+d;if(b<0){b=0;e=b+d}else{if(e>this.max_high){e=this.max_high;b=e-d}}this.low=Math.floor(b);this.high=Math.ceil(e);this.center=Math.round(this.low+(this.high-this.low)/2);this.resolution=Math.pow(10,Math.ceil(Math.log((this.high-this.low)/DENSITY)/Math.LN10));this.zoom_res=Math.max(1,Math.ceil(Math.log(this.resolution,FEATURE_LEVELS)/Math.log(FEATURE_LEVELS)));$("#overview-box").css({left:(this.low/this.span)*$("#overview-viewport").width(),width:Math.max(12,((this.high-this.low)/this.span)*$("#overview-viewport").width())}).show();$("#low").val(commatize(this.low));$("#high").val(commatize(this.high));for(var
c=0,a=this.tracks.length;c<a;c++){this.tracks[c].draw()}},zoom_in:function(a){if(this.max_high===0||this.high-this.low<30){return}if(a){this.center=a/$(document).width()*(this.high-this.low)+this.low}this.zoom_level+=1;this.redraw()},zoom_out:function(){if(this.max_high===0){return}if(this.zoom_level<=0){this.zoom_level=0;return}this.zoom_level-=1;thi
s.redraw()}});var
Track=function(a,b){this.name=a;this.parent_element=b;this.make_container()};$.extend(Track.prototype,{make_container:function(){this.header_div=$("<div
class='track-header'>").text(this.name);this.content_div=$("<div
class='track-content'>");this.container_div=$("<div
class='track'></div>").append(this.header_div).append(this.content_div);this.parent_element.append(this.container_div)}});var
TiledTrack=function(){};$.extend(TiledTrack.prototype,Track.prototype,{draw:function(){var
j=this.view.low,e=this.view.high,f=e-j,d=this.view.resolution;if(DEBUG){$("#debug").text(d+"
"+this.view.zoom_res)}var l=$("<div style='position:
relative;'></div>");this.content_div.children(":first").remove();this.content_div.append(l);var
m=this.content_div.width()/f;var i=20;var h;var
a=Math.floor(j/d/DENSITY);while((a*DENSITY*d)<e){var
k=this.content_div.width()+"_"+this.view.zoom_level+"_"+a;var
c=this.tile_cache.get(k);if(c){var g=a*DENSITY*d;var b=(g-j)*m;if(this.left_off
set){b-=this.left_offset}c.css({left:b});l.append(c);i=Math.max(i,c.height())}else{h=this.draw_tile(d,a,l,m);if(h){this.tile_cache.set(k,h);i=Math.max(i,h.height())}}this.content_div.css("height",i);a+=1}}});var
LabelTrack=function(a){Track.call(this,null,a);this.container_div.addClass("label-track")};$.extend(LabelTrack.prototype,Track.prototype,{draw:function(){var
c=this.view,d=c.high-c.low,g=Math.floor(Math.pow(10,Math.floor(Math.log(d)/Math.log(10)))),a=Math.floor(c.low/g)*g,e=this.content_div.width(),b=$("<div
style='position: relative; height:
1.3em;'></div>");while(a<c.high){var
f=(a-c.low)/d*e;b.append($("<div
class='label'>"+commatize(a)+"</div>").css({position:"absolute",left:f-1}));a+=g}this.content_div.children(":first").remove();this.content_div.append(b)}});var
LineTrack=function(c,b,a){this.tile_cache=new
Cache(CACHED_TILES_LINE);Track.call(this,c,$("#viewport"));TiledTrack.call(this);this.track_type="line";this.height_px=(a?a:100);this.container_div.addClass
("line-track");this.dataset_id=b;this.data_queue={};this.cache=new
Cache(CACHED_DATA)};$.extend(LineTrack.prototype,TiledTrack.prototype,{init:function(){var
a=this;a.content_div.text(DATA_LOADING);$.getJSON(data_url,{stats:true,track_type:a.track_type,chrom:a.view.chrom,low:null,high:null,dataset_id:a.dataset_id},function(c){if(!c||c=="error"){a.container_div.addClass("error");a.content_div.text(DATA_ERROR)}else{if(c=="no
data"){a.container_div.addClass("nodata");a.content_div.text(DATA_NONE)}else{if(c=="pending"){a.container_div.addClass("pending");a.content_div.text(DATA_PENDING);setTimeout(function(){a.init()},5000)}else{a.content_div.text("");a.content_div.css("height",a.height_px+"px");a.min_value=c.min;a.max_value=c.max;a.vertical_range=a.max_value-a.min_value;var
d=$("<div
class='yaxislabel'>"+a.min_value+"</div>");var
b=$("<div
class='yaxislabel'>"+a.max_value+"</div>");b.css({position:"relative",top:"35px"});b.prependTo(a.container_div);d.css({position:"relative",t
op:a.height_px+32+"px"});d.prependTo(a.container_div);a.draw()}}}})},get_data:function(d,b){var
c=this,a=b*DENSITY*d,f=(b+1)*DENSITY*d,e=d+"_"+b;if(!c.data_queue[e]){c.data_queue[e]=true;$.getJSON(data_url,{track_type:this.track_type,chrom:this.view.chrom,low:a,high:f,dataset_id:this.dataset_id,resolution:this.view.resolution},function(g){c.cache.set(e,g);delete
c.data_queue[e];c.draw()})}},draw_tile:function(d,a,m,o){if(!this.vertical_range){return}var
h=a*DENSITY*d,b=DENSITY*d,c=$("<canvas
class='tile'></canvas>"),l=d+"_"+a;if(!this.cache.get(l)){this.get_data(d,a);return}var
g=this.cache.get(l);c.css({position:"absolute",top:0,left:(h-this.view.low)*o});c.get(0).width=Math.ceil(b*o);c.get(0).height=this.height_px;var
n=c.get(0).getContext("2d");var e=false;n.beginPath();for(var
f=0;f<g.length-1;f++){var k=g[f][0]-h;var
j=g[f][1];if(isNaN(j)){e=false}else{k=k*o;j=(j-this.min_value)/this.vertical_range*this.height_px;if(e){n.lineTo(k,j)}else{n.moveTo(k,j);e=true}}}n.stroke(
);m.append(c);return c}});var FeatureTrack=function(c,b,a){this.tile_cache=new
Cache(CACHED_TILES_FEATURE);Track.call(this,c,$("#viewport"));TiledTrack.call(this);this.track_type="feature";this.height_px=(a?a:100);this.container_div.addClass("feature-track");this.dataset_id=b;this.zo_slots={};this.show_labels_scale=0.001;this.showing_labels=false;this.vertical_gap=10;this.base_color="#2C3143";this.default_font="9px
Monaco, Lucida Console,
monospace";this.left_offset=200;this.inc_slots={};this.data_queue={};this.data_cache=new
Cache(20)};$.extend(FeatureTrack.prototype,TiledTrack.prototype,{init:function(){var
a=this;a.content_div.text(DATA_LOADING);$.getJSON(data_url,{track_type:a.track_type,low:a.view.max_low,high:a.view.max_high,dataset_id:a.dataset_id,chrom:a.view.chrom},function(b){if(b=="error"){a.container_div.addClass("error");a.content_div.text(DATA_ERROR)}else{if(b.length===0||b=="no
data"){a.container_div.addClass("nodata");a.content_div.text(DATA_NONE)}else{if(b==
"pending"){a.container_div.addClass("pending");a.content_div.text(DATA_PENDING);setTimeout(function(){a.init()},5000)}else{a.content_div.text("");a.content_div.css("height",a.height_px+"px");a.values=b;a.calc_slots();a.slots=a.zo_slots;a.draw()}}}})},get_data:function(a,d){var
b=this,c=a+"_"+d;if(!b.data_queue[c]){b.data_queue[c]=true;$.getJSON(data_url,{track_type:b.track_type,chrom:b.view.chrom,low:a,high:d,dataset_id:b.dataset_id,include_blocks:true},function(e){b.data_cache.set(c,e);delete
b.data_queue[c];b.draw()})}},calc_slots:function(){var
c=[],b=this.content_div.width()/(this.view.high-this.view.low),a=this.view.max_high,e=this.view.max_low;for(var
f=0,g=this.values.length;f<g;f++){var
h,k,l=this.values[f];h=Math.floor((l.start-e)*b);k=Math.ceil((l.end-e)*b);var
d=0;while(true){if(c[d]===undefined||c[d]<h){c[d]=k;this.zo_slots[l.uid]=d;break}d++}}this.height_px=c.length*this.vertical_gap+15;this.content_div.css("height",this.height_px+"px")},incremental_slots:functi
on(a,b){if(!this.inc_slots[a]){this.inc_slots[a]={};this.inc_slots[a].w_scale=DENSITY/Math.pow(FEATURE_LEVELS,a+1)}var
k=this.inc_slots[a];var
d=[],l=[],c=0,m=$("<canvas></canvas>").get(0).getContext("2d"),f=this.view.max_low;for(var
g=0,h=b.length;g<h;g++){var
n=b[g];if(k[n.uid]){c=Math.max(c,k[n.uid]);d[k[n.uid]]=Math.ceil((n.end-f)*k.w_scale)}else{l.push(n)}}for(var
g=0,h=l.length;g<h;g++){var
n=l[g];f_start=Math.floor((n.start-f)*k.w_scale);f_start-=m.measureText(n.name).width;f_end=Math.ceil((n.end-f)*k.w_scale);var
e=0;while(true){if(d[e]===undefined||d[e]<f_start){d[e]=f_end;k[n.uid]=e;c=Math.max(c,e);break}e++}}return
c},draw_tile:function(A,F,n,r){if(!this.values){return}var
G=F*DENSITY*A,c=(F+1)*DENSITY*A,v=DENSITY*A;var
K,u,h;if(r>this.show_labels_scale){if(!this.showing_labels){this.showing_labels=true}for(var
B in this.data_cache.obj_cache){var
p=B.split("_"),e=p[0],d=p[1];if(e<=G&&d>=c){K=this.data_cache.get(B);break}}if(!K){this.data_queue[[G,c]]=true;this.get
_data(G,c);return}h=this.incremental_slots(this.view.zoom_res,K)*this.vertical_gap+15;u=this.inc_slots[this.view.zoom_res]}else{if(this.showing_labels){this.showing_labels=false}h=this.height_px;u=this.zo_slots;K=this.values}var
y=Math.ceil(v*r),x=$("<canvas
class='tile'></canvas>");x.css({position:"absolute",top:0,left:(G-this.view.low)*r-this.left_offset});x.get(0).width=y+this.left_offset;x.get(0).height=h;var
z=x.get(0).getContext("2d");z.fillStyle=this.base_color;z.font=this.default_font;z.textAlign="right";var
C=0;for(var D=0,E=K.length;D<E;D++){var
m=K[D];if(m.start<=c&&m.end>=G){var
g=Math.floor(Math.max(0,(m.start-G)*r)),l=Math.ceil(Math.min(y,(m.end-G)*r)),f=u[m.uid]*this.vertical_gap;var
a,L,b=null,s=null;if(m.thick_start&&m.thick_end){b=Math.floor(Math.max(0,(m.thick_start-G)*r));s=Math.ceil(Math.min(y,(m.thick_end-G)*r))}if(!this.showing_labels){z.fillRect(g+this.left_offset,f+5,l-g,1)}else{if(z.fillText&&m.start>G){z.fillText(m.name,g-1+this.left_offset,f+8)}va
r
I=m.blocks;if(I){if(m.strand){if(m.strand=="+"){z.fillStyle=RIGHT_STRAND}else{if(m.strand=="-"){z.fillStyle=LEFT_STRAND}}z.fillRect(g+this.left_offset,f,l-g,10);z.fillStyle=this.base_color}for(var
B=0,J=I.length;B<J;B++){var
q=I[B],o=Math.floor(Math.max(0,(q[0]-G)*r)),H=Math.ceil(Math.min(y,(q[1]-G)*r));if(o>H){continue}a=5;L=3;z.fillRect(o+this.left_offset,f+L,H-o,a);if(b&&(o<s||H>b)){a=9;L=1;var
w=Math.max(o,b),t=Math.min(H,s);z.fillRect(w+this.left_offset,f+L,t-w,a)}}}else{a=9;L=1;z.fillRect(g+this.left_offset,f+L,l-g,a);if(m.strand){if(m.strand=="+"){z.fillStyle=RIGHT_STRAND_INV}else{if(m.strand=="-"){z.fillStyle=LEFT_STRAND_INV}}z.fillRect(g+this.left_offset,f,l-g,10);z.fillStyle=this.base_color}}}C++}}n.append(x);return
x}});
\ No newline at end of file
+var DEBUG=false;var DENSITY=1000,FEATURE_LEVELS=100,DATA_ERROR="There was an error
in indexing this dataset.",DATA_NONE="No data for this
chrom/contig.",DATA_PENDING="Currently indexing... please
wait",DATA_LOADING="Loading
data...",CACHED_TILES_FEATURE=10,CACHED_TILES_LINE=30,CACHED_DATA=20,CONTEXT=$("<canvas></canvas>").get(0).getContext("2d"),RIGHT_STRAND,LEFT_STRAND;var
right_img=new
Image();right_img.src="../images/visualization/strand_right.png";right_img.onload=function(){RIGHT_STRAND=CONTEXT.createPattern(right_img,"repeat")};var
left_img=new
Image();left_img.src="../images/visualization/strand_left.png";left_img.onload=function(){LEFT_STRAND=CONTEXT.createPattern(left_img,"repeat")};var
right_img_inv=new
Image();right_img_inv.src="../images/visualization/strand_right_inv.png";right_img_inv.onload=function(){RIGHT_STRAND_INV=CONTEXT.createPattern(right_img_inv,"repeat")};var
left_img_inv=new
Image();left_img_inv.src="../images/visualization/strand_left_inv.png";left_
img_inv.onload=function(){LEFT_STRAND_INV=CONTEXT.createPattern(left_img_inv,"repeat")};function
commatize(b){b+="";var
a=/(\d+)(\d{3})/;while(a.test(b)){b=b.replace(a,"$1,$2")}return b}var
Cache=function(a){this.num_elements=a;this.obj_cache={};this.key_ary=[]};$.extend(Cache.prototype,{get:function(b){var
a=this.key_ary.indexOf(b);if(a!=-1){this.key_ary.splice(a,1);this.key_ary.push(b)}return
this.obj_cache[b]},set:function(b,c){if(!this.obj_cache[b]){if(this.key_ary.length>=this.num_elements){var
a=this.key_ary.shift();delete
this.obj_cache[a]}this.key_ary.push(b)}this.obj_cache[b]=c;return c}});var
View=function(b,a){this.chrom=b;this.tracks=[];this.max_low=0;this.max_high=a;this.center=(this.max_high-this.max_low)/2;this.span=this.max_high-this.max_low;this.zoom_factor=3;this.zoom_level=0};$.extend(View.prototype,{add_track:function(a){a.view=this;this.tracks.push(a);if(a.init){a.init()}},redraw:function(){var
d=this.span/Math.pow(this.zoom_factor,this.zoom_level),b=thi
s.center-(d/2),e=b+d;if(b<0){b=0;e=b+d}else{if(e>this.max_high){e=this.max_high;b=e-d}}this.low=Math.floor(b);this.high=Math.ceil(e);this.center=Math.round(this.low+(this.high-this.low)/2);this.resolution=Math.pow(10,Math.ceil(Math.log((this.high-this.low)/DENSITY)/Math.LN10));this.zoom_res=Math.max(1,Math.ceil(Math.log(this.resolution,FEATURE_LEVELS)/Math.log(FEATURE_LEVELS)));$("#overview-box").css({left:(this.low/this.span)*$("#overview-viewport").width(),width:Math.max(12,((this.high-this.low)/this.span)*$("#overview-viewport").width())}).show();$("#low").val(commatize(this.low));$("#high").val(commatize(this.high));for(var
c=0,a=this.tracks.length;c<a;c++){this.tracks[c].draw()}},zoom_in:function(a){if(this.max_high===0||this.high-this.low<30){return}if(a){this.center=a/$(document).width()*(this.high-this.low)+this.low}this.zoom_level+=1;this.redraw()},zoom_out:function(){if(this.max_high===0){return}if(this.zoom_level<=0){this.zoom_level=0;return}this.zoom_level-=1;thi
s.redraw()}});var
Track=function(a,b){this.name=a;this.parent_element=b;this.make_container()};$.extend(Track.prototype,{make_container:function(){this.header_div=$("<div
class='track-header'>").text(this.name);this.content_div=$("<div
class='track-content'>");this.container_div=$("<div
class='track'></div>").append(this.header_div).append(this.content_div);this.parent_element.append(this.container_div)}});var
TiledTrack=function(){};$.extend(TiledTrack.prototype,Track.prototype,{draw:function(){var
j=this.view.low,e=this.view.high,f=e-j,d=this.view.resolution;if(DEBUG){$("#debug").text(d+"
"+this.view.zoom_res)}var l=$("<div style='position:
relative;'></div>");this.content_div.children(":first").remove();this.content_div.append(l);var
m=this.content_div.width()/f;var i=20;var h;var
a=Math.floor(j/d/DENSITY);while((a*DENSITY*d)<e){var
k=this.content_div.width()+"_"+this.view.zoom_level+"_"+a;var
c=this.tile_cache.get(k);if(c){var g=a*DENSITY*d;var b=(g-j)*m;if(this.left_off
set){b-=this.left_offset}c.css({left:b});l.append(c);i=Math.max(i,c.height())}else{h=this.draw_tile(d,a,l,m);if(h){this.tile_cache.set(k,h);i=Math.max(i,h.height())}}this.content_div.css("height",i);a+=1}}});var
LabelTrack=function(a){Track.call(this,null,a);this.container_div.addClass("label-track")};$.extend(LabelTrack.prototype,Track.prototype,{draw:function(){var
c=this.view,d=c.high-c.low,g=Math.floor(Math.pow(10,Math.floor(Math.log(d)/Math.log(10)))),a=Math.floor(c.low/g)*g,e=this.content_div.width(),b=$("<div
style='position: relative; height:
1.3em;'></div>");while(a<c.high){var
f=(a-c.low)/d*e;b.append($("<div
class='label'>"+commatize(a)+"</div>").css({position:"absolute",left:f-1}));a+=g}this.content_div.children(":first").remove();this.content_div.append(b)}});var
LineTrack=function(c,b,d,a){this.tile_cache=new
Cache(CACHED_TILES_LINE);Track.call(this,c,$("#viewport"));TiledTrack.call(this);this.indexer=d;this.height_px=(a?a:100);this.container_div.addClass("line
-track");this.dataset_id=b;this.data_queue={};this.cache=new
Cache(CACHED_DATA)};$.extend(LineTrack.prototype,TiledTrack.prototype,{init:function(){var
a=this;a.content_div.text(DATA_LOADING);$.getJSON(data_url,{stats:true,indexer:a.indexer,chrom:a.view.chrom,low:null,high:null,dataset_id:a.dataset_id},function(c){if(!c||c=="error"){a.container_div.addClass("error");a.content_div.text(DATA_ERROR)}else{if(c=="no
data"){a.container_div.addClass("nodata");a.content_div.text(DATA_NONE)}else{if(c=="pending"){a.container_div.addClass("pending");a.content_div.text(DATA_PENDING);setTimeout(function(){a.init()},5000)}else{a.content_div.text("");a.content_div.css("height",a.height_px+"px");a.min_value=c.min;a.max_value=c.max;a.vertical_range=a.max_value-a.min_value;var
d=$("<div
class='yaxislabel'>"+a.min_value+"</div>");var
b=$("<div
class='yaxislabel'>"+a.max_value+"</div>");b.css({position:"relative",top:"35px"});b.prependTo(a.container_div);d.css({position:"relative",top:a.height_
px+32+"px"});d.prependTo(a.container_div);a.draw()}}}})},get_data:function(d,b){var
c=this,a=b*DENSITY*d,f=(b+1)*DENSITY*d,e=d+"_"+b;if(!c.data_queue[e]){c.data_queue[e]=true;$.getJSON(data_url,{indexer:this.indexer,chrom:this.view.chrom,low:a,high:f,dataset_id:this.dataset_id,resolution:this.view.resolution},function(g){c.cache.set(e,g);delete
c.data_queue[e];c.draw()})}},draw_tile:function(d,a,m,o){if(!this.vertical_range){return}var
h=a*DENSITY*d,b=DENSITY*d,c=$("<canvas
class='tile'></canvas>"),l=d+"_"+a;if(!this.cache.get(l)){this.get_data(d,a);return}var
g=this.cache.get(l);c.css({position:"absolute",top:0,left:(h-this.view.low)*o});c.get(0).width=Math.ceil(b*o);c.get(0).height=this.height_px;var
n=c.get(0).getContext("2d");var e=false;n.beginPath();for(var
f=0;f<g.length-1;f++){var k=g[f][0]-h;var
j=g[f][1];if(isNaN(j)){e=false}else{k=k*o;j=(j-this.min_value)/this.vertical_range*this.height_px;if(e){n.lineTo(k,j)}else{n.moveTo(k,j);e=true}}}n.stroke();m.append(c);retu
rn c}});var FeatureTrack=function(c,b,d,a){this.tile_cache=new
Cache(CACHED_TILES_FEATURE);Track.call(this,c,$("#viewport"));TiledTrack.call(this);this.indexer=d;this.height_px=(a?a:100);this.container_div.addClass("feature-track");this.dataset_id=b;this.zo_slots={};this.show_labels_scale=0.001;this.showing_labels=false;this.vertical_gap=10;this.base_color="#2C3143";this.default_font="9px
Monaco, Lucida Console,
monospace";this.left_offset=200;this.inc_slots={};this.data_queue={};this.data_cache=new
Cache(20)};$.extend(FeatureTrack.prototype,TiledTrack.prototype,{init:function(){var
a=this;a.content_div.text(DATA_LOADING);$.getJSON(data_url,{indexer:a.indexer,low:a.view.max_low,high:a.view.max_high,dataset_id:a.dataset_id,chrom:a.view.chrom},function(b){if(b=="error"){a.container_div.addClass("error");a.content_div.text(DATA_ERROR)}else{if(b.length===0||b=="no
data"){a.container_div.addClass("nodata");a.content_div.text(DATA_NONE)}else{if(b=="pending"){a.container_div.addCla
ss("pending");a.content_div.text(DATA_PENDING);setTimeout(function(){a.init()},5000)}else{a.content_div.text("");a.content_div.css("height",a.height_px+"px");a.values=b;a.calc_slots();a.slots=a.zo_slots;a.draw()}}}})},get_data:function(a,d){var
b=this,c=a+"_"+d;if(!b.data_queue[c]){b.data_queue[c]=true;$.getJSON(data_url,{indexer:b.indexer,chrom:b.view.chrom,low:a,high:d,dataset_id:b.dataset_id,include_blocks:true},function(e){b.data_cache.set(c,e);delete
b.data_queue[c];b.draw()})}},calc_slots:function(){var
c=[],b=this.content_div.width()/(this.view.high-this.view.low),a=this.view.max_high,e=this.view.max_low;for(var
f=0,g=this.values.length;f<g;f++){var
h,k,l=this.values[f];h=Math.floor((l.start-e)*b);k=Math.ceil((l.end-e)*b);var
d=0;while(true){if(c[d]===undefined||c[d]<h){c[d]=k;this.zo_slots[l.uid]=d;break}d++}}this.height_px=c.length*this.vertical_gap+15;this.content_div.css("height",this.height_px+"px")},incremental_slots:function(a,b){if(!this.inc_slots[a]){this.inc
_slots[a]={};this.inc_slots[a].w_scale=DENSITY/Math.pow(FEATURE_LEVELS,a+1)}var
k=this.inc_slots[a];var
d=[],l=[],c=0,m=$("<canvas></canvas>").get(0).getContext("2d"),f=this.view.max_low;for(var
g=0,h=b.length;g<h;g++){var
n=b[g];if(k[n.uid]){c=Math.max(c,k[n.uid]);d[k[n.uid]]=Math.ceil((n.end-f)*k.w_scale)}else{l.push(n)}}for(var
g=0,h=l.length;g<h;g++){var
n=l[g];f_start=Math.floor((n.start-f)*k.w_scale);f_start-=m.measureText(n.name).width;f_end=Math.ceil((n.end-f)*k.w_scale);var
e=0;while(true){if(d[e]===undefined||d[e]<f_start){d[e]=f_end;k[n.uid]=e;c=Math.max(c,e);break}e++}}return
c},draw_tile:function(A,F,n,r){if(!this.values){return}var
G=F*DENSITY*A,c=(F+1)*DENSITY*A,v=DENSITY*A;var
K,u,h;if(r>this.show_labels_scale){if(!this.showing_labels){this.showing_labels=true}for(var
B in this.data_cache.obj_cache){var
p=B.split("_"),e=p[0],d=p[1];if(e<=G&&d>=c){K=this.data_cache.get(B);break}}if(!K){this.data_queue[[G,c]]=true;this.get_data(G,c);return}h=this.incremental_sl
ots(this.view.zoom_res,K)*this.vertical_gap+15;u=this.inc_slots[this.view.zoom_res]}else{if(this.showing_labels){this.showing_labels=false}h=this.height_px;u=this.zo_slots;K=this.values}var
y=Math.ceil(v*r),x=$("<canvas
class='tile'></canvas>");x.css({position:"absolute",top:0,left:(G-this.view.low)*r-this.left_offset});x.get(0).width=y+this.left_offset;x.get(0).height=h;var
z=x.get(0).getContext("2d");z.fillStyle=this.base_color;z.font=this.default_font;z.textAlign="right";var
C=0;for(var D=0,E=K.length;D<E;D++){var
m=K[D];if(m.start<=c&&m.end>=G){var
g=Math.floor(Math.max(0,(m.start-G)*r)),l=Math.ceil(Math.min(y,(m.end-G)*r)),f=u[m.uid]*this.vertical_gap;var
a,L,b=null,s=null;if(m.thick_start&&m.thick_end){b=Math.floor(Math.max(0,(m.thick_start-G)*r));s=Math.ceil(Math.min(y,(m.thick_end-G)*r))}if(!this.showing_labels){z.fillRect(g+this.left_offset,f+5,l-g,1)}else{if(z.fillText&&m.start>G){z.fillText(m.name,g-1+this.left_offset,f+8)}var
I=m.blocks;if(I){if(m.strand){if(m.st
rand=="+"){z.fillStyle=RIGHT_STRAND}else{if(m.strand=="-"){z.fillStyle=LEFT_STRAND}}z.fillRect(g+this.left_offset,f,l-g,10);z.fillStyle=this.base_color}for(var
B=0,J=I.length;B<J;B++){var
q=I[B],o=Math.floor(Math.max(0,(q[0]-G)*r)),H=Math.ceil(Math.min(y,(q[1]-G)*r));if(o>H){continue}a=5;L=3;z.fillRect(o+this.left_offset,f+L,H-o,a);if(b&&(o<s||H>b)){a=9;L=1;var
w=Math.max(o,b),t=Math.min(H,s);z.fillRect(w+this.left_offset,f+L,t-w,a)}}}else{a=9;L=1;z.fillRect(g+this.left_offset,f+L,l-g,a);if(m.strand){if(m.strand=="+"){z.fillStyle=RIGHT_STRAND_INV}else{if(m.strand=="-"){z.fillStyle=LEFT_STRAND_INV}}z.fillRect(g+this.left_offset,f,l-g,10);z.fillStyle=this.base_color}}}C++}}n.append(x);return
x}});var ReadTrack=function(c,b,d,a){this.tile_cache=new
Cache(CACHED_TILES_FEATURE);Track.call(this,c,$("#viewport"));TiledTrack.call(this);FeatureTrack.call(this,c,b,d,a);this.default_font="9px
Monaco, Lucida Console,
monospace"};$.extend(ReadTrack.prototype,TiledTrack.prototype,FeatureT
rack.prototype,{draw_tile:function(w,A,n,o){if(!this.values){return}var
B=A*DENSITY*w,f=(A+1)*DENSITY*w,r=DENSITY*w;var
E,q,k;k=this.height_px;q=this.zo_slots;E=this.values;var
u=Math.ceil(r*o),s=$("<canvas class='tile'></canvas>");var
b=$("<canvas></canvas>").get(0).getContext("2d");s.css({position:"absolute",top:0,left:(B-this.view.low)*o-this.left_offset});s.get(0).width=u+this.left_offset;s.get(0).height=k;var
v=s.get(0).getContext("2d");v.fillStyle=this.base_color;v.font=this.default_font;v.textAlign="right";var
t=v.measureText("A").width;var x=0;for(var y=0,z=E.length;y<z;y++){var
m=E[y];if(m.start<=f&&m.end>=B){var
h=Math.floor(Math.max(0,(m.start-B)*o)),l=Math.ceil(Math.min(u,(m.end-B)*o)),g=q[m.uid]*this.vertical_gap;var
a,F,e=null,p=null;if(o>t){for(var C=0,d=m.name.length;C<d;C++){var
D=Math.floor(Math.max(0,(m.start+C-B)*o));v.fillText(m.name[C],D+this.left_offset,g+8)}}else{v.fillRect(h+this.left_offset,g+4,l-h,3)}}}n.append(s);return
s}});
\ No newline at end of file
diff -r 427d93bf3d39 -r 7d3667e8e415 static/scripts/trackster.js
--- a/static/scripts/trackster.js Thu Jan 07 14:52:51 2010 -0500
+++ b/static/scripts/trackster.js Thu Jan 07 15:45:15 2010 -0500
@@ -81,7 +81,7 @@
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 @@
}
});
-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 @@
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 @@
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 @@
}
});
-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 @@
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 @@
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 @@
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 @@
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;
+ }
+});
diff -r 427d93bf3d39 -r 7d3667e8e415 templates/tracks/browser.mako
--- a/templates/tracks/browser.mako Thu Jan 07 14:52:51 2010 -0500
+++ b/templates/tracks/browser.mako Thu Jan 07 15:45:15 2010 -0500
@@ -20,7 +20,7 @@
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 ) {
diff -r 427d93bf3d39 -r 7d3667e8e415 templates/tracks/new_browser.mako
--- a/templates/tracks/new_browser.mako Thu Jan 07 14:52:51 2010 -0500
+++ b/templates/tracks/new_browser.mako Thu Jan 07 15:45:15 2010 -0500
@@ -11,7 +11,7 @@
</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 @@
<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}" />