diff --git a/lib/galaxy/visualization/tracks/data/array_tree.py b/lib/galaxy/visualization/tracks/data/array_tree.py
index dcac488f693..a13123dc41d 100644
--- a/lib/galaxy/visualization/tracks/data/array_tree.py
+++ b/lib/galaxy/visualization/tracks/data/array_tree.py
@@ -7,8 +7,9 @@ pkg_resources.require( "numpy" )
pkg_resources.require( "bx-python" )
from bx.arrays.array_tree import FileArrayTreeDict
from math import floor, ceil, log, pow
+from base import TracksDataProvider
-class ArrayTreeDataProvider( object ):
+class ArrayTreeDataProvider( TracksDataProvider ):
def __init__( self, dataset, original_dataset ):
self.dataset = dataset
diff --git a/lib/galaxy/visualization/tracks/data/bam.py b/lib/galaxy/visualization/tracks/data/bam.py
index 90440d5988c..9278066a736 100644
--- a/lib/galaxy/visualization/tracks/data/bam.py
+++ b/lib/galaxy/visualization/tracks/data/bam.py
@@ -9,10 +9,11 @@ from pysam import csamtools
from math import floor, ceil, log
import logging
log = logging.getLogger(__name__)
+from base import TracksDataProvider
MAX_VALS = 5000 # only display first MAX_VALS datapoints
-class BamDataProvider( object ):
+class BamDataProvider( TracksDataProvider ):
"""
Provides access to intervals from a sorted indexed BAM file.
"""
diff --git a/lib/galaxy/visualization/tracks/data/base.py b/lib/galaxy/visualization/tracks/data/base.py
new file mode 100644
index 00000000000..957663f9cc3
--- /dev/null
+++ b/lib/galaxy/visualization/tracks/data/base.py
@@ -0,0 +1,11 @@
+class TracksDataProvider( object ):
+ """ Base class for tracks data providers. """
+
+ def __init__( self, converted_dataset, original_dataset ):
+ self.converted_dataset = converted_dataset
+ self.original_dataset = original_dataset
+
+ def get_data( self, chrom, start, end, **kwargs ):
+ """ Returns data in region defined by chrom, start, and end. """
+ # Override.
+ pass
\ No newline at end of file
diff --git a/lib/galaxy/visualization/tracks/data/interval_index.py b/lib/galaxy/visualization/tracks/data/interval_index.py
index d9deb24e023..106a3515546 100644
--- a/lib/galaxy/visualization/tracks/data/interval_index.py
+++ b/lib/galaxy/visualization/tracks/data/interval_index.py
@@ -8,15 +8,11 @@ Payload format: [ uid (offset), start, end, name, strand, thick_start, thick_end
import pkg_resources; pkg_resources.require( "bx-python" )
from bx.interval_index_file import Indexes
from galaxy.datatypes.interval import Bed, Gff
-from galaxy.datatypes.tabular import Vcf
+from base import TracksDataProvider
MAX_VALS = 5000 # only display first MAX_VALS features
-class IntervalIndexDataProvider( object ):
- def __init__( self, converted_dataset, original_dataset ):
- self.original_dataset = original_dataset
- self.converted_dataset = converted_dataset
-
+class IntervalIndexDataProvider( TracksDataProvider ):
def get_data( self, chrom, start, end, **kwargs ):
start, end = int(start), int(end)
source = open( self.original_dataset.file_name )
@@ -66,10 +62,7 @@ class IntervalIndexDataProvider( object ):
block_starts = [ int(n) for n in feature[11].split(',') if n != '' ]
blocks = zip(block_sizes, block_starts)
payload.append( [ (start + block[1], start + block[1] + block[0]) for block in blocks] )
- elif isinstance( self.original_dataset.datatype, Vcf ):
- # VCF dataset.
- payload.append( feature[2] ) # name
-
+
results.append(payload)
return { 'data': results, 'message': message }
diff --git a/lib/galaxy/visualization/tracks/data/vcf.py b/lib/galaxy/visualization/tracks/data/vcf.py
new file mode 100644
index 00000000000..aa70553f3a6
--- /dev/null
+++ b/lib/galaxy/visualization/tracks/data/vcf.py
@@ -0,0 +1,53 @@
+"""
+VCF data provider for the Galaxy track browser.
+
+Payload format:
+[ uid (offset), start, end, ID, reference base(s), alternate base(s), quality score]
+"""
+
+import pkg_resources; pkg_resources.require( "bx-python" )
+from bx.interval_index_file import Indexes
+from galaxy.datatypes.tabular import Vcf
+from base import TracksDataProvider
+
+MAX_VALS = 5000 # only display first MAX_VALS features
+
+class VCFDataProvider( TracksDataProvider ):
+ """ Provides data for VCF tracks. """
+
+ def get_data( self, chrom, start, end, **kwargs ):
+ """ Returns data in region defined by chrom, start, and end. """
+ start, end = int(start), int(end)
+ source = open( self.original_dataset.file_name )
+ index = Indexes( self.converted_dataset.file_name )
+ results = []
+ count = 0
+ message = None
+
+ # If chrom is not found in indexes, try removing the first three
+ # characters (e.g. 'chr') and see if that works. This enables the
+ # provider to handle chrome names defined as chrXXX and as XXX.
+ chrom = str(chrom)
+ if chrom not in index.indexes and chrom[3:] in index.indexes:
+ chrom = chrom[3:]
+
+ for start, end, offset in index.find(chrom, start, end):
+ if count >= MAX_VALS:
+ message = "Only the first %s features are being displayed." % MAX_VALS
+ break
+ count += 1
+ source.seek(offset)
+ feature = source.readline().split()
+
+ payload = [ offset, start, end, \
+ # ID:
+ feature[2], \
+ # reference base(s):
+ feature[3], \
+ # alternative base(s)
+ feature[4], \
+ # phred quality score
+ feature[5] ]
+ results.append(payload)
+
+ return { 'data_type' : 'vcf', 'data': results, 'message': message }
diff --git a/lib/galaxy/web/controllers/tracks.py b/lib/galaxy/web/controllers/tracks.py
index a1995c781d9..12d7ddb92b0 100644
--- a/lib/galaxy/web/controllers/tracks.py
+++ b/lib/galaxy/web/controllers/tracks.py
@@ -24,6 +24,7 @@ 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
from galaxy.visualization.tracks.data.summary_tree import SummaryTreeDataProvider
+from galaxy.visualization.tracks.data.vcf import VCFDataProvider
# Message strings returned to browser
messages = Bunch(
@@ -36,10 +37,11 @@ messages = Bunch(
)
# Mapping from dataset type to a class that can fetch data from a file of that
-# type. This also needs to be more flexible.
+# type. First key is converted dataset type; if result is another dict, second key
+# is original dataset type. TODO: This needs to be more flexible.
dataset_type_to_data_provider = {
"array_tree": ArrayTreeDataProvider,
- "interval_index": IntervalIndexDataProvider,
+ "interval_index": { "vcf": VCFDataProvider, "default" : IntervalIndexDataProvider },
"bai": BamDataProvider,
"summary_tree": SummaryTreeDataProvider
}
@@ -300,15 +302,28 @@ class TracksController( BaseController, UsesVisualization ):
frequencies, max_v, avg_v, delta = summary
return { 'dataset_type': data_sources['index'], 'data': frequencies, 'max': max_v, 'avg': avg_v, 'delta': delta }
- dataset_type = data_sources['data']
- data_provider = dataset_type_to_data_provider[ dataset_type ]( dataset.get_converted_dataset(trans, dataset_type), dataset )
+ # Get data provider.
+ tracks_dataset_type = data_sources['data']
+ value = dataset_type_to_data_provider[ tracks_dataset_type ]
+ if isinstance( value, dict ):
+ # Get converter by dataset extension; if there is no data provider,
+ # get the default
+ data_provider_class = value.get( dataset.ext, value.get( "default" ) )
+ else:
+ data_provider_class = value
+ data_provider = data_provider_class( dataset.get_converted_dataset(trans, tracks_dataset_type), dataset )
+ # Get and return data from data_provider.
data = data_provider.get_data( chrom, low, high, **kwargs )
message = None
if isinstance(data, dict) and 'message' in data:
message = data['message']
- data = data['data']
- return { 'dataset_type': dataset_type, 'extra_info': extra_info, 'data': data, 'message': message }
+ dataset_type = data.get( 'data_type', tracks_dataset_type )
+ track_data = data['data']
+ else:
+ track_data = data
+ return { 'dataset_type': dataset_type, 'extra_info': extra_info, 'data': track_data, 'message': message }
+
@web.json
def save( self, trans, **kwargs ):
diff --git a/static/scripts/packed/trackster.js b/static/scripts/packed/trackster.js
index 40979042563..f27c956d1ad 100644
--- a/static/scripts/packed/trackster.js
+++ b/static/scripts/packed/trackster.js
@@ -1 +1 @@
-var DENSITY=200,FEATURE_LEVELS=10,MAX_FEATURE_DEPTH=100,DATA_ERROR="There was an error in indexing this dataset. ",DATA_NOCONVERTER="A converter for this dataset is not installed. Please check your datatypes_conf.xml file.",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=5,CONTEXT=$("").get(0).getContext("2d"),PX_PER_CHAR=CONTEXT.measureText("A").width,RIGHT_STRAND,LEFT_STRAND;var right_img=new Image();right_img.src=image_path+"/visualization/strand_right.png";right_img.onload=function(){RIGHT_STRAND=CONTEXT.createPattern(right_img,"repeat")};var left_img=new Image();left_img.src=image_path+"/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=image_path+"/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=image_path+"/visualization/strand_left_inv.png";left_img_inv.onload=function(){LEFT_STRAND_INV=CONTEXT.createPattern(left_img_inv,"repeat")};function round_1000(a){return Math.round(a*1000)/1000}var Cache=function(a){this.num_elements=a;this.clear()};$.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},clear:function(){this.obj_cache={};this.key_ary=[]}});var View=function(a,c,e,d,b){this.container=a;this.vis_id=d;this.dbkey=b;this.title=e;this.chrom=c;this.tracks=[];this.label_tracks=[];this.max_low=0;this.max_high=0;this.num_tracks=0;this.track_id_counter=0;this.zoom_factor=3;this.min_separation=30;this.has_changes=false;this.init();this.reset()};$.extend(View.prototype,{init:function(){var c=this.container,a=this;this.top_labeltrack=$("
").addClass("top-labeltrack").appendTo(c);this.content_div=$("").addClass("content").css("position","relative").hide().appendTo(c);this.intro_div=$("").addClass("intro").text("Select a chrom from the dropdown below").hide().appendTo(c);this.viewport_container=$("").addClass("viewport-container").addClass("viewport-container").appendTo(this.content_div);this.nav_container=$("").addClass("nav-container").appendTo(c);this.nav_labeltrack=$("").addClass("nav-labeltrack").appendTo(this.nav_container);this.nav=$("").addClass("nav").appendTo(this.nav_container);this.overview=$("").addClass("overview").appendTo(this.nav);this.overview_viewport=$("").addClass("overview-viewport").appendTo(this.overview);this.overview_box_background=$("").addClass("overview-boxback").appendTo(this.overview_viewport);this.overview_box=$("").addClass("overview-box").appendTo(this.overview_viewport);this.default_overview_height=this.overview_box.height();this.nav_controls=$("").addClass("nav-controls").appendTo(this.nav);this.chrom_form=$("").attr("action",function(){void (0)}).appendTo(this.nav_controls);this.chrom_select=$("").attr({name:"chrom"}).css("width","15em").addClass("no-autocomplete").append("").appendTo(this.chrom_form);var b=function(d){if(d.type==="focusout"||(d.keyCode||d.which)===13||(d.keyCode||d.which)===27){if((d.keyCode||d.which)!==27){a.go_to($(this).val())}$(this).hide();a.location_span.show();a.chrom_select.show();return false}};this.nav_input=$("").addClass("nav-input").hide().bind("keypress focusout",b).appendTo(this.chrom_form);this.location_span=$("").addClass("location").appendTo(this.chrom_form);this.location_span.bind("click",function(){a.location_span.hide();a.chrom_select.hide();a.nav_input.css("display","inline-block");a.nav_input.select();a.nav_input.focus()});if(this.vis_id!==undefined){this.hidden_input=$("").attr("type","hidden").val(this.vis_id).appendTo(this.chrom_form)}this.zo_link=$("").click(function(){a.zoom_out();a.redraw()}).html('
').appendTo(this.chrom_form);this.zi_link=$("").click(function(){a.zoom_in();a.redraw()}).html('
').appendTo(this.chrom_form);$.ajax({url:chrom_url,data:(this.vis_id!==undefined?{vis_id:this.vis_id}:{dbkey:this.dbkey}),dataType:"json",success:function(d){if(d.reference){a.add_label_track(new ReferenceTrack(a))}a.chrom_data=d.chrom_info;var f='';for(i in a.chrom_data){var e=a.chrom_data[i]["chrom"];f+='"}a.chrom_select.html(f);a.intro_div.show();a.content_div.hide();a.chrom_select.bind("change",function(){a.change_chrom(a.chrom_select.val())})},error:function(){alert("Could not load chroms for this dbkey:",a.dbkey)}});this.content_div.bind("dblclick",function(d){a.zoom_in(d.pageX,this.viewport_container)});this.overview_box.bind("dragstart",function(d){this.current_x=d.offsetX}).bind("drag",function(d){var g=d.offsetX-this.current_x;this.current_x=d.offsetX;var f=Math.round(g/a.viewport_container.width()*(a.max_high-a.max_low));a.move_delta(-f)});this.viewport_container.bind("dragstart",function(d){this.original_low=a.low;this.current_height=d.clientY;this.current_x=d.offsetX;this.enable_pan=(d.clientX").css({height:a.content_div.height()+30,top:"0px",position:"absolute","background-color":"#cfc",border:"1px solid #6a6",opacity:0.5,"z-index":1000}).appendTo($(this))}).bind("drag",function(j){var f=Math.min(j.clientX,this.drag_origin_x)-a.container.offset().left,d=Math.max(j.clientX,this.drag_origin_x)-a.container.offset().left,h=(a.high-a.low),g=a.viewport_container.width();a.update_location(Math.round(f/g*h)+a.low,Math.round(d/g*h)+a.low);this.drag_div.css({left:f+"px",width:(d-f)+"px"})}).bind("dragend",function(k){var f=Math.min(k.clientX,this.drag_origin_x),d=Math.max(k.clientX,this.drag_origin_x),h=(a.high-a.low),g=a.viewport_container.width(),j=a.low;a.low=Math.round(f/g*h)+j;a.high=Math.round(d/g*h)+j;this.drag_div.remove();a.redraw()});this.add_label_track(new LabelTrack(this,this.top_labeltrack));this.add_label_track(new LabelTrack(this,this.nav_labeltrack))},update_location:function(a,b){this.location_span.text(commatize(a)+" - "+commatize(b));this.nav_input.val(this.chrom+":"+commatize(a)+"-"+commatize(b))},change_chrom:function(d,a,f){var c=this;var e=$.grep(c.chrom_data,function(h,j){return h.chrom===d})[0];if(e===undefined){return}if(d!==c.chrom){c.chrom=d;if(c.chrom===""){c.intro_div.show();c.content_div.hide()}else{c.intro_div.hide();c.content_div.show()}c.chrom_select.val(c.chrom);c.max_high=e.len;c.reset();c.redraw(true);for(var g in c.tracks){var b=c.tracks[g];if(b.init){b.init()}}}if(a!==undefined&&f!==undefined){c.low=Math.max(a,0);c.high=Math.min(f,c.max_high)}c.overview_viewport.find("canvas").remove();c.redraw()},go_to:function(f){var k=this,b=f.split(":"),h=b[0],j=b[1];if(j!==undefined){try{var g=j.split("-"),a=parseInt(g[0].replace(/,/g,"")),d=parseInt(g[1].replace(/,/g,""))}catch(c){return false}}k.change_chrom(h,a,d)},move_delta:function(c){var a=this;var b=a.high-a.low;if(a.low-ca.max_high){a.high=a.max_high;a.low=a.max_high-b}else{a.high-=c;a.low-=c}}a.redraw()},add_track:function(a){a.view=this;a.track_id=this.track_id_counter;this.tracks.push(a);if(a.init){a.init()}a.container_div.attr("id","track_"+a.track_id);this.track_id_counter+=1;this.num_tracks+=1},add_label_track:function(a){a.view=this;this.label_tracks.push(a)},remove_track:function(a){this.has_changes=true;a.container_div.fadeOut("slow",function(){$(this).remove()});delete this.tracks[this.tracks.indexOf(a)];this.num_tracks-=1},reset:function(){this.low=this.max_low;this.high=this.max_high;this.viewport_container.find(".yaxislabel").remove()},redraw:function(h){var d=this.high-this.low,b=this.low,f=this.high;if(bthis.max_high){f=this.max_high}if(this.high!==0&&d").addClass("track");if(!this.hidden){this.header_div=$("").appendTo(this.container_div);this.drag_div=$("").appendTo(this.header_div);this.name_div=$("").appendTo(this.header_div);this.name_div.text(this.name)}this.content_div=$("").appendTo(this.container_div);this.parent_element.append(this.container_div)},init_each:function(c,b){var a=this;a.enabled=false;a.data_queue={};a.tile_cache.clear();a.data_cache.clear();a.initial_canvas=undefined;a.content_div.css("height","auto");if(!a.content_div.text()){a.content_div.text(DATA_LOADING)}a.container_div.removeClass("nodata error pending");if(a.view.chrom){$.getJSON(data_url,c,function(d){if(!d||d==="error"||d.kind==="error"){a.container_div.addClass("error");a.content_div.text(DATA_ERROR);if(d.message){var f=a.view.tracks.indexOf(a);var e=$("
").attr("id",f+"_error");e.text("Click to view error");$("#"+f+"_error").live("click",function(){show_modal("Trackster Error","
"+d.message+"
",{Close:hide_modal})});a.content_div.append(e)}}else{if(d==="no converter"){a.container_div.addClass("error");a.content_div.text(DATA_NOCONVERTER)}else{if(d.data!==undefined&&(d.data===null||d.data.length===0)){a.container_div.addClass("nodata");a.content_div.text(DATA_NONE)}else{if(d==="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.enabled=true;b(d);a.draw()}}}}})}else{a.container_div.addClass("nodata");a.content_div.text(DATA_NONE)}}});var TiledTrack=function(){var d=this,c=d.view;if(d.hidden){return}if(d.display_modes!==undefined){if(d.mode_div===undefined){d.mode_div=$("").appendTo(d.header_div);var h=d.display_modes[0];d.mode=h;d.mode_div.text(h);var a=function(j){d.mode_div.text(j);d.mode=j;d.tile_cache.clear();d.draw()};var f={};for(var e in d.display_modes){var g=d.display_modes[e];f[g]=function(j){return function(){a(j)}}(g)}make_popupmenu(d.mode_div,f)}else{d.mode_div.hide()}}var b={};b["Set track as overview"]=function(){c.overview_viewport.find("canvas").remove();d.is_overview=true;d.set_overview();for(var j in c.tracks){if(c.tracks[j]!==d){c.tracks[j].is_overview=false}}};b["Edit configuration"]=function(){var k=function(){hide_modal()};var j=function(){d.update_options(d.track_id);hide_modal()};show_modal("Configure Track",d.gen_options(d.track_id),{Cancel:k,OK:j})};b.Remove=function(){c.remove_track(d);if(c.num_tracks===0){$("#no-tracks").show()}};make_popupmenu(d.name_div,b)};$.extend(TiledTrack.prototype,Track.prototype,{draw:function(){var j=this.view.low,e=this.view.high,f=e-j,d=this.view.resolution;var l=$("
"),m=this.content_div.width()/f,h;this.content_div.children(":first").remove();this.content_div.append(l),this.max_height=0;var a=Math.floor(j/d/DENSITY);while((a*DENSITY*d)
c.view.high||f").addClass("overview-highlight").appendTo(a.overview_viewport)}a.overview_viewport.append(this.initial_canvas);a.overview_highlight.height(this.initial_canvas.height());a.overview_viewport.height(this.initial_canvas.height()+a.overview_box.height())}$(window).trigger("resize")}});var LabelTrack=function(a,b){this.track_type="LabelTrack";this.hidden=true;Track.call(this,null,a,b);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=$("");while(a"+commatize(a)+" ").css({position:"absolute",left:f-1}));a+=g}this.content_div.children(":first").remove();this.content_div.append(b)}});var ReferenceTrack=function(a){this.track_type="ReferenceTrack";this.hidden=true;Track.call(this,null,a,a.top_labeltrack);TiledTrack.call(this);this.height_px=12;this.container_div.addClass("reference-track");this.dummy_canvas=$("").get(0).getContext("2d");this.data_queue={};this.data_cache=new Cache(CACHED_DATA);this.tile_cache=new Cache(CACHED_TILES_LINE)};$.extend(ReferenceTrack.prototype,TiledTrack.prototype,{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;$.ajax({url:reference_url,dataType:"json",data:{chrom:this.view.chrom,low:a,high:f,dbkey:this.view.dbkey},success:function(g){c.data_cache.set(e,g);delete c.data_queue[e];c.draw()},error:function(h,g,j){console.log(h,g,j)}})}},draw_tile:function(f,b,k,o){var g=b*DENSITY*f,d=DENSITY*f,e=$(""),n=e.get(0).getContext("2d"),j=f+"_"+b;if(o>PX_PER_CHAR){if(this.data_cache.get(j)===undefined){this.get_data(f,b);return}var m=this.data_cache.get(j);if(m===null){this.content_div.css("height","0px");return}e.get(0).width=Math.ceil(d*o+this.left_offset);e.get(0).height=this.height_px;e.css({position:"absolute",top:0,left:(g-this.view.low)*o-this.left_offset});for(var h=0,l=m.length;h").addClass("yaxislabel").attr("id","linetrack_"+b+"_minval").text(round_1000(a.prefs.min_value));var d=$("").addClass("yaxislabel").attr("id","linetrack_"+b+"_maxval").text(round_1000(a.prefs.max_value));d.css({position:"relative",top:"32px",left:"10px"});d.prependTo(a.container_div);e.css({position:"relative",top:a.height_px+32+"px",left:"10px"});e.prependTo(a.container_div)})},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;$.ajax({url:data_url,dataType:"json",data:{chrom:this.view.chrom,low:a,high:f,dataset_id:this.dataset_id,resolution:this.view.resolution},success:function(g){data=g.data;c.data_cache.set(e,data);delete c.data_queue[e];c.draw()},error:function(h,g,j){console.log(h,g,j)}})}},draw_tile:function(p,r,c,e){if(this.vertical_range===undefined){return}var s=r*DENSITY*p,a=DENSITY*p,b=$(""),v=p+"_"+r;if(this.data_cache.get(v)===undefined){this.get_data(p,r);return}var j=this.data_cache.get(v);if(j===null){return}b.css({position:"absolute",top:0,left:(s-this.view.low)*e});b.get(0).width=Math.ceil(a*e);b.get(0).height=this.height_px;var o=b.get(0).getContext("2d"),k=false,l=this.prefs.min_value,g=this.prefs.max_value,n=this.vertical_range,t=this.total_frequency,d=this.height_px,m=this.mode;o.beginPath();if(data.length>1){var f=Math.ceil((data[1][0]-data[0][0])*e)}else{var f=10}var u,h;for(var q=0;q=g){h=g}}h=255-Math.floor((h-l)/n*255);o.fillStyle="rgb("+h+","+h+","+h+")";o.fillRect(u,0,f,this.height_px)}else{if(h===null){if(k&&m==="Filled"){o.lineTo(u,d)}k=false;continue}else{if(h<=l){h=l}else{if(h>=g){h=g}}h=Math.round(d-(h-l)/n*d);if(k){o.lineTo(u,h)}else{k=true;if(m==="Filled"){o.moveTo(u,d);o.lineTo(u,h)}else{o.moveTo(u,h)}}}}}if(m==="Filled"){if(k){o.lineTo(u,d)}o.fill()}else{o.stroke()}c.append(b);return b},gen_options:function(k){var a=$("").addClass("form-row");var e="track_"+k+"_minval",h=$("").attr("for",e).text("Min value:"),b=(this.prefs.min_value===undefined?"":this.prefs.min_value),j=$("").attr("id",e).val(b),g="track_"+k+"_maxval",d=$("").attr("for",g).text("Max value:"),f=(this.prefs.max_value===undefined?"":this.prefs.max_value),c=$("").attr("id",g).val(f);return a.append(h).append(j).append(d).append(c)},update_options:function(c){var a=$("#track_"+c+"_minval").val(),b=$("#track_"+c+"_maxval").val();if(a!==this.prefs.min_value||b!==this.prefs.max_value){this.prefs.min_value=parseFloat(a);this.prefs.max_value=parseFloat(b);this.vertical_range=this.prefs.max_value-this.prefs.min_value;$("#linetrack_"+c+"_minval").text(this.prefs.min_value);$("#linetrack_"+c+"_maxval").text(this.prefs.max_value);this.tile_cache.clear();this.draw()}}});var FeatureTrack=function(d,b,a,c){this.track_type="FeatureTrack";this.display_modes=["Auto","Dense","Squish","Pack"];Track.call(this,d,b,b.viewport_container);TiledTrack.call(this);this.height_px=0;this.container_div.addClass("feature-track");this.dataset_id=a;this.zo_slots={};this.show_labels_scale=0.001;this.showing_details=false;this.vertical_detail_px=10;this.vertical_nodetail_px=2;this.summary_draw_height=20;this.default_font="9px Monaco, Lucida Console, monospace";this.inc_slots={};this.data_queue={};this.s_e_by_tile={};this.tile_cache=new Cache(CACHED_TILES_FEATURE);this.data_cache=new Cache(20);this.left_offset=200;this.prefs={block_color:"black",label_color:"black",show_counts:true};if(c.block_color!==undefined){this.prefs.block_color=c.block_color}if(c.label_color!==undefined){this.prefs.label_color=c.label_color}if(c.show_counts!==undefined){this.prefs.show_counts=c.show_counts}};$.extend(FeatureTrack.prototype,TiledTrack.prototype,{init:function(){var a=this,b="initial";this.init_each({low:a.view.max_low,high:a.view.max_high,dataset_id:a.dataset_id,chrom:a.view.chrom,resolution:this.view.resolution,mode:a.mode},function(c){a.mode_div.show();a.data_cache.set(b,c);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,{chrom:b.view.chrom,low:a,high:d,dataset_id:b.dataset_id,resolution:this.view.resolution,mode:this.mode},function(e){b.data_cache.set(c,e);delete b.data_queue[c];b.draw()})}},incremental_slots:function(a,h,c,r){if(!this.inc_slots[a]){this.inc_slots[a]={};this.inc_slots[a].w_scale=a;this.inc_slots[a].mode=r;this.s_e_by_tile[a]={}}var n=this.inc_slots[a].w_scale,z=[],l=0,b=$("").get(0).getContext("2d"),o=this.view.max_low;var B=[];if(this.inc_slots[a].mode!==r){delete this.inc_slots[a];this.inc_slots[a]={mode:r,w_scale:n};delete this.s_e_by_tile[a];this.s_e_by_tile[a]={}}for(var w=0,x=h.length;wy[0]&&ePX_PER_CHAR){n.fillStyle=this.prefs.block_color;n.fillRect(k,h+1,e,9);n.fillStyle="#eee";for(var g=0,l=d.length;g=f&&b+g<=m){var a=Math.floor(Math.max(0,(b+g-f)*o));n.fillText(d[g],a+this.left_offset+j,h+9)}}}else{n.fillStyle=this.prefs.block_color;n.fillRect(k,h+4,e,3)}},draw_tile:function(aa,l,o,an){var H=l*DENSITY*aa,ag=(l+1)*DENSITY*aa,G=ag-H;var ah=(!this.initial_canvas?"initial":H+"_"+ag);var C=this.data_cache.get(ah);var d;if(C===undefined||(this.mode!=="Auto"&&C.dataset_type==="summary_tree")){this.data_queue[[H,ag]]=true;this.get_data(H,ag);return}var a=Math.ceil(G*an),O=$(""),ac=this.prefs.label_color,g=this.prefs.block_color,n=this.mode,r=25,Y=(n==="Squish")||(n==="Dense")&&(n!=="Pack")||(n==="Auto"&&(C.extra_info==="no_detail")),S=this.left_offset,am,v,ao;if(C.dataset_type==="summary_tree"){v=this.summary_draw_height}else{if(n==="Dense"){v=r;ao=10}else{ao=(Y?this.vertical_nodetail_px:this.vertical_detail_px);var s=(an<0.0001?1/view.zoom_res:an);v=this.incremental_slots(s,C.data,Y,n)*ao+r;am=this.inc_slots[s]}}O.css({position:"absolute",top:0,left:(H-this.view.low)*an-S});O.get(0).width=a+S;O.get(0).height=v;o.parent().css("height",Math.max(this.height_px,v)+"px");var D=O.get(0).getContext("2d");D.fillStyle=g;D.font=this.default_font;D.textAlign="right";if(C.dataset_type=="summary_tree"){var N,K=55,af=255-K,h=af*2/3,U=C.data,F=C.max,m=C.avg,b=Math.ceil(C.delta*an);for(var aj=0,B=U.length;ajh){D.fillStyle="black"}else{D.fillStyle="#ddd"}D.textAlign="center";D.fillText(V,W+S+(b/2),12)}}d="Summary";o.append(O);return O}if(C.message){O.css({border:"solid red","border-width":"2px 2px 2px 0px"});D.fillStyle="red";D.textAlign="left";D.fillText(C.message,100+S,ao)}var al=C.data;var ai=0;for(var aj=0,B=al.length;aj=H){var Z=Math.floor(Math.max(0,(ak-H)*an)),E=Math.ceil(Math.min(a,Math.max(0,(X-H)*an))),T=(n==="Dense"?1:(1+am[M]))*ao;if(C.dataset_type==="bai"){D.fillStyle=g;if(P[4] instanceof Array){var w=Math.floor(Math.max(0,(P[4][0]-H)*an)),L=Math.ceil(Math.min(a,Math.max(0,(P[4][1]-H)*an))),u=Math.floor(Math.max(0,(P[5][0]-H)*an)),q=Math.ceil(Math.min(a,Math.max(0,(P[5][1]-H)*an)));if(P[4][1]>=H&&P[4][0]<=ag){this.rect_or_text(D,an,H,ag,P[4][0],P[4][2],w+S,L-w,T)}if(P[5][1]>=H&&P[5][0]<=ag){this.rect_or_text(D,an,H,ag,P[5][0],P[5][2],u+S,q-u,T)}if(u>L){D.fillStyle="#999";D.fillRect(L+S,T+5,u-L,1)}}else{D.fillStyle=g;this.rect_or_text(D,an,H,ag,ak,I,Z+S,E-Z,T)}if(n!=="Dense"&&!Y&&ak>H){D.fillStyle=this.prefs.label_color;if(l===0&&Z-D.measureText(I).width<0){D.textAlign="left";D.fillText(M,E+2+S,T+8)}else{D.textAlign="right";D.fillText(M,Z-2+S,T+8)}D.fillStyle=g}}else{if(C.dataset_type==="interval_index"){if(Y){D.fillStyle=g;D.fillRect(Z+S,T+5,E-Z,1)}else{var A=P[4],R=P[5],ab=P[6],f=P[7];var z,ad,J=null,ap=null;if(R&&ab){J=Math.floor(Math.max(0,(R-H)*an));ap=Math.ceil(Math.min(a,Math.max(0,(ab-H)*an)))}if(n!=="Dense"&&I!==undefined&&ak>H){D.fillStyle=ac;if(l===0&&Z-D.measureText(I).width<0){D.textAlign="left";D.fillText(I,E+2+S,T+8)}else{D.textAlign="right";D.fillText(I,Z-2+S,T+8)}D.fillStyle=g}if(f){if(A){if(A=="+"){D.fillStyle=RIGHT_STRAND}else{if(A=="-"){D.fillStyle=LEFT_STRAND}}D.fillRect(Z+S,T,E-Z,10);D.fillStyle=g}for(var ah=0,e=f.length;ahQ){continue}z=5;ad=3;D.fillRect(c+S,T+ad,Q-c,z);if(J!==undefined&&!(c>ap||Q").addClass("form-row");var e="track_"+j+"_block_color",l=$("").attr("for",e).text("Block color:"),m=$("").attr("id",e).attr("name",e).val(this.prefs.block_color),k="track_"+j+"_label_color",g=$("").attr("for",k).text("Text color:"),h=$("").attr("id",k).attr("name",k).val(this.prefs.label_color),f="track_"+j+"_show_count",c=$("").attr("for",f).text("Show summary counts"),b=$('').attr("id",f).attr("name",f).attr("checked",this.prefs.show_counts),d=$("").append(b).append(c);return a.append(l).append(m).append(g).append(h).append(d)},update_options:function(e){var b=$("#track_"+e+"_block_color").val(),d=$("#track_"+e+"_label_color").val(),c=$("#track_"+e+"_mode option:selected").val(),a=$("#track_"+e+"_show_count").attr("checked");if(b!==this.prefs.block_color||d!==this.prefs.label_color||a!==this.prefs.show_counts){this.prefs.block_color=b;this.prefs.label_color=d;this.prefs.show_counts=a;this.tile_cache.clear();this.draw()}}});var ReadTrack=function(d,b,a,c){FeatureTrack.call(this,d,b,a,c);this.track_type="ReadTrack";this.vertical_detail_px=10;this.vertical_nodetail_px=5};$.extend(ReadTrack.prototype,TiledTrack.prototype,FeatureTrack.prototype,{});
\ No newline at end of file
+var DENSITY=200,FEATURE_LEVELS=10,MAX_FEATURE_DEPTH=100,DATA_ERROR="There was an error in indexing this dataset. ",DATA_NOCONVERTER="A converter for this dataset is not installed. Please check your datatypes_conf.xml file.",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=5,CONTEXT=$("").get(0).getContext("2d"),PX_PER_CHAR=CONTEXT.measureText("A").width,RIGHT_STRAND,LEFT_STRAND;var right_img=new Image();right_img.src=image_path+"/visualization/strand_right.png";right_img.onload=function(){RIGHT_STRAND=CONTEXT.createPattern(right_img,"repeat")};var left_img=new Image();left_img.src=image_path+"/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=image_path+"/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=image_path+"/visualization/strand_left_inv.png";left_img_inv.onload=function(){LEFT_STRAND_INV=CONTEXT.createPattern(left_img_inv,"repeat")};function round_1000(a){return Math.round(a*1000)/1000}var Cache=function(a){this.num_elements=a;this.clear()};$.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},clear:function(){this.obj_cache={};this.key_ary=[]}});var View=function(a,c,e,d,b){this.container=a;this.vis_id=d;this.dbkey=b;this.title=e;this.chrom=c;this.tracks=[];this.label_tracks=[];this.max_low=0;this.max_high=0;this.num_tracks=0;this.track_id_counter=0;this.zoom_factor=3;this.min_separation=30;this.has_changes=false;this.init();this.reset()};$.extend(View.prototype,{init:function(){var c=this.container,a=this;this.top_labeltrack=$("").addClass("top-labeltrack").appendTo(c);this.content_div=$("").addClass("content").css("position","relative").hide().appendTo(c);this.intro_div=$("").addClass("intro").text("Select a chrom from the dropdown below").hide().appendTo(c);this.viewport_container=$("").addClass("viewport-container").addClass("viewport-container").appendTo(this.content_div);this.nav_container=$("").addClass("nav-container").appendTo(c);this.nav_labeltrack=$("").addClass("nav-labeltrack").appendTo(this.nav_container);this.nav=$("").addClass("nav").appendTo(this.nav_container);this.overview=$("").addClass("overview").appendTo(this.nav);this.overview_viewport=$("").addClass("overview-viewport").appendTo(this.overview);this.overview_box_background=$("").addClass("overview-boxback").appendTo(this.overview_viewport);this.overview_box=$("").addClass("overview-box").appendTo(this.overview_viewport);this.default_overview_height=this.overview_box.height();this.nav_controls=$("").addClass("nav-controls").appendTo(this.nav);this.chrom_form=$("").attr("action",function(){void (0)}).appendTo(this.nav_controls);this.chrom_select=$("").attr({name:"chrom"}).css("width","15em").addClass("no-autocomplete").append("").appendTo(this.chrom_form);var b=function(d){if(d.type==="focusout"||(d.keyCode||d.which)===13||(d.keyCode||d.which)===27){if((d.keyCode||d.which)!==27){a.go_to($(this).val())}$(this).hide();a.location_span.show();a.chrom_select.show();return false}};this.nav_input=$("").addClass("nav-input").hide().bind("keypress focusout",b).appendTo(this.chrom_form);this.location_span=$("").addClass("location").appendTo(this.chrom_form);this.location_span.bind("click",function(){a.location_span.hide();a.chrom_select.hide();a.nav_input.css("display","inline-block");a.nav_input.select();a.nav_input.focus()});if(this.vis_id!==undefined){this.hidden_input=$("").attr("type","hidden").val(this.vis_id).appendTo(this.chrom_form)}this.zo_link=$("").click(function(){a.zoom_out();a.redraw()}).html('
').appendTo(this.chrom_form);this.zi_link=$("").click(function(){a.zoom_in();a.redraw()}).html('
').appendTo(this.chrom_form);$.ajax({url:chrom_url,data:(this.vis_id!==undefined?{vis_id:this.vis_id}:{dbkey:this.dbkey}),dataType:"json",success:function(d){if(d.reference){a.add_label_track(new ReferenceTrack(a))}a.chrom_data=d.chrom_info;var f='';for(i in a.chrom_data){var e=a.chrom_data[i]["chrom"];f+='"}a.chrom_select.html(f);a.intro_div.show();a.content_div.hide();a.chrom_select.bind("change",function(){a.change_chrom(a.chrom_select.val())})},error:function(){alert("Could not load chroms for this dbkey:",a.dbkey)}});this.content_div.bind("dblclick",function(d){a.zoom_in(d.pageX,this.viewport_container)});this.overview_box.bind("dragstart",function(d){this.current_x=d.offsetX}).bind("drag",function(d){var g=d.offsetX-this.current_x;this.current_x=d.offsetX;var f=Math.round(g/a.viewport_container.width()*(a.max_high-a.max_low));a.move_delta(-f)});this.viewport_container.bind("dragstart",function(d){this.original_low=a.low;this.current_height=d.clientY;this.current_x=d.offsetX;this.enable_pan=(d.clientX").css({height:a.content_div.height()+30,top:"0px",position:"absolute","background-color":"#cfc",border:"1px solid #6a6",opacity:0.5,"z-index":1000}).appendTo($(this))}).bind("drag",function(j){var f=Math.min(j.clientX,this.drag_origin_x)-a.container.offset().left,d=Math.max(j.clientX,this.drag_origin_x)-a.container.offset().left,h=(a.high-a.low),g=a.viewport_container.width();a.update_location(Math.round(f/g*h)+a.low,Math.round(d/g*h)+a.low);this.drag_div.css({left:f+"px",width:(d-f)+"px"})}).bind("dragend",function(k){var f=Math.min(k.clientX,this.drag_origin_x),d=Math.max(k.clientX,this.drag_origin_x),h=(a.high-a.low),g=a.viewport_container.width(),j=a.low;a.low=Math.round(f/g*h)+j;a.high=Math.round(d/g*h)+j;this.drag_div.remove();a.redraw()});this.add_label_track(new LabelTrack(this,this.top_labeltrack));this.add_label_track(new LabelTrack(this,this.nav_labeltrack))},update_location:function(a,b){this.location_span.text(commatize(a)+" - "+commatize(b));this.nav_input.val(this.chrom+":"+commatize(a)+"-"+commatize(b))},change_chrom:function(d,a,f){var c=this;var e=$.grep(c.chrom_data,function(h,j){return h.chrom===d})[0];if(e===undefined){return}if(d!==c.chrom){c.chrom=d;if(c.chrom===""){c.intro_div.show();c.content_div.hide()}else{c.intro_div.hide();c.content_div.show()}c.chrom_select.val(c.chrom);c.max_high=e.len;c.reset();c.redraw(true);for(var g in c.tracks){var b=c.tracks[g];if(b.init){b.init()}}}if(a!==undefined&&f!==undefined){c.low=Math.max(a,0);c.high=Math.min(f,c.max_high)}c.overview_viewport.find("canvas").remove();c.redraw()},go_to:function(f){var k=this,b=f.split(":"),h=b[0],j=b[1];if(j!==undefined){try{var g=j.split("-"),a=parseInt(g[0].replace(/,/g,"")),d=parseInt(g[1].replace(/,/g,""))}catch(c){return false}}k.change_chrom(h,a,d)},move_delta:function(c){var a=this;var b=a.high-a.low;if(a.low-ca.max_high){a.high=a.max_high;a.low=a.max_high-b}else{a.high-=c;a.low-=c}}a.redraw()},add_track:function(a){a.view=this;a.track_id=this.track_id_counter;this.tracks.push(a);if(a.init){a.init()}a.container_div.attr("id","track_"+a.track_id);this.track_id_counter+=1;this.num_tracks+=1},add_label_track:function(a){a.view=this;this.label_tracks.push(a)},remove_track:function(a){this.has_changes=true;a.container_div.fadeOut("slow",function(){$(this).remove()});delete this.tracks[this.tracks.indexOf(a)];this.num_tracks-=1},reset:function(){this.low=this.max_low;this.high=this.max_high;this.viewport_container.find(".yaxislabel").remove()},redraw:function(h){var d=this.high-this.low,b=this.low,f=this.high;if(bthis.max_high){f=this.max_high}if(this.high!==0&&d").addClass("track");if(!this.hidden){this.header_div=$("").appendTo(this.container_div);this.drag_div=$("").appendTo(this.header_div);this.name_div=$("").appendTo(this.header_div);this.name_div.text(this.name)}this.content_div=$("").appendTo(this.container_div);this.parent_element.append(this.container_div)},init_each:function(c,b){var a=this;a.enabled=false;a.data_queue={};a.tile_cache.clear();a.data_cache.clear();a.initial_canvas=undefined;a.content_div.css("height","auto");if(!a.content_div.text()){a.content_div.text(DATA_LOADING)}a.container_div.removeClass("nodata error pending");if(a.view.chrom){$.getJSON(data_url,c,function(d){if(!d||d==="error"||d.kind==="error"){a.container_div.addClass("error");a.content_div.text(DATA_ERROR);if(d.message){var f=a.view.tracks.indexOf(a);var e=$("
").attr("id",f+"_error");e.text("Click to view error");$("#"+f+"_error").live("click",function(){show_modal("Trackster Error","
"+d.message+"
",{Close:hide_modal})});a.content_div.append(e)}}else{if(d==="no converter"){a.container_div.addClass("error");a.content_div.text(DATA_NOCONVERTER)}else{if(d.data!==undefined&&(d.data===null||d.data.length===0)){a.container_div.addClass("nodata");a.content_div.text(DATA_NONE)}else{if(d==="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.enabled=true;b(d);a.draw()}}}}})}else{a.container_div.addClass("nodata");a.content_div.text(DATA_NONE)}}});var TiledTrack=function(){var d=this,c=d.view;if(d.hidden){return}if(d.display_modes!==undefined){if(d.mode_div===undefined){d.mode_div=$("").appendTo(d.header_div);var h=d.display_modes[0];d.mode=h;d.mode_div.text(h);var a=function(j){d.mode_div.text(j);d.mode=j;d.tile_cache.clear();d.draw()};var f={};for(var e in d.display_modes){var g=d.display_modes[e];f[g]=function(j){return function(){a(j)}}(g)}make_popupmenu(d.mode_div,f)}else{d.mode_div.hide()}}var b={};b["Set track as overview"]=function(){c.overview_viewport.find("canvas").remove();d.is_overview=true;d.set_overview();for(var j in c.tracks){if(c.tracks[j]!==d){c.tracks[j].is_overview=false}}};b["Edit configuration"]=function(){var k=function(){hide_modal()};var j=function(){d.update_options(d.track_id);hide_modal()};show_modal("Configure Track",d.gen_options(d.track_id),{Cancel:k,OK:j})};b.Remove=function(){c.remove_track(d);if(c.num_tracks===0){$("#no-tracks").show()}};make_popupmenu(d.name_div,b)};$.extend(TiledTrack.prototype,Track.prototype,{draw:function(){var j=this.view.low,e=this.view.high,f=e-j,d=this.view.resolution;var l=$("
"),m=this.content_div.width()/f,h;this.content_div.children(":first").remove();this.content_div.append(l),this.max_height=0;var a=Math.floor(j/d/DENSITY);while((a*DENSITY*d)
c.view.high||f").addClass("overview-highlight").appendTo(a.overview_viewport)}a.overview_viewport.append(this.initial_canvas);a.overview_highlight.height(this.initial_canvas.height());a.overview_viewport.height(this.initial_canvas.height()+a.overview_box.height())}$(window).trigger("resize")}});var LabelTrack=function(a,b){this.track_type="LabelTrack";this.hidden=true;Track.call(this,null,a,b);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=$("");while(a"+commatize(a)+" ").css({position:"absolute",left:f-1}));a+=g}this.content_div.children(":first").remove();this.content_div.append(b)}});var ReferenceTrack=function(a){this.track_type="ReferenceTrack";this.hidden=true;Track.call(this,null,a,a.top_labeltrack);TiledTrack.call(this);this.height_px=12;this.container_div.addClass("reference-track");this.dummy_canvas=$("").get(0).getContext("2d");this.data_queue={};this.data_cache=new Cache(CACHED_DATA);this.tile_cache=new Cache(CACHED_TILES_LINE)};$.extend(ReferenceTrack.prototype,TiledTrack.prototype,{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;$.ajax({url:reference_url,dataType:"json",data:{chrom:this.view.chrom,low:a,high:f,dbkey:this.view.dbkey},success:function(g){c.data_cache.set(e,g);delete c.data_queue[e];c.draw()},error:function(h,g,j){console.log(h,g,j)}})}},draw_tile:function(f,b,k,o){var g=b*DENSITY*f,d=DENSITY*f,e=$(""),n=e.get(0).getContext("2d"),j=f+"_"+b;if(o>PX_PER_CHAR){if(this.data_cache.get(j)===undefined){this.get_data(f,b);return}var m=this.data_cache.get(j);if(m===null){this.content_div.css("height","0px");return}e.get(0).width=Math.ceil(d*o+this.left_offset);e.get(0).height=this.height_px;e.css({position:"absolute",top:0,left:(g-this.view.low)*o-this.left_offset});for(var h=0,l=m.length;h").addClass("yaxislabel").attr("id","linetrack_"+b+"_minval").text(round_1000(a.prefs.min_value));var d=$("").addClass("yaxislabel").attr("id","linetrack_"+b+"_maxval").text(round_1000(a.prefs.max_value));d.css({position:"relative",top:"32px",left:"10px"});d.prependTo(a.container_div);e.css({position:"relative",top:a.height_px+32+"px",left:"10px"});e.prependTo(a.container_div)})},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;$.ajax({url:data_url,dataType:"json",data:{chrom:this.view.chrom,low:a,high:f,dataset_id:this.dataset_id,resolution:this.view.resolution},success:function(g){data=g.data;c.data_cache.set(e,data);delete c.data_queue[e];c.draw()},error:function(h,g,j){console.log(h,g,j)}})}},draw_tile:function(p,r,c,e){if(this.vertical_range===undefined){return}var s=r*DENSITY*p,a=DENSITY*p,b=$(""),v=p+"_"+r;if(this.data_cache.get(v)===undefined){this.get_data(p,r);return}var j=this.data_cache.get(v);if(j===null){return}b.css({position:"absolute",top:0,left:(s-this.view.low)*e});b.get(0).width=Math.ceil(a*e);b.get(0).height=this.height_px;var o=b.get(0).getContext("2d"),k=false,l=this.prefs.min_value,g=this.prefs.max_value,n=this.vertical_range,t=this.total_frequency,d=this.height_px,m=this.mode;o.beginPath();if(data.length>1){var f=Math.ceil((data[1][0]-data[0][0])*e)}else{var f=10}var u,h;for(var q=0;q=g){h=g}}h=255-Math.floor((h-l)/n*255);o.fillStyle="rgb("+h+","+h+","+h+")";o.fillRect(u,0,f,this.height_px)}else{if(h===null){if(k&&m==="Filled"){o.lineTo(u,d)}k=false;continue}else{if(h<=l){h=l}else{if(h>=g){h=g}}h=Math.round(d-(h-l)/n*d);if(k){o.lineTo(u,h)}else{k=true;if(m==="Filled"){o.moveTo(u,d);o.lineTo(u,h)}else{o.moveTo(u,h)}}}}}if(m==="Filled"){if(k){o.lineTo(u,d)}o.fill()}else{o.stroke()}c.append(b);return b},gen_options:function(k){var a=$("").addClass("form-row");var e="track_"+k+"_minval",h=$("").attr("for",e).text("Min value:"),b=(this.prefs.min_value===undefined?"":this.prefs.min_value),j=$("").attr("id",e).val(b),g="track_"+k+"_maxval",d=$("").attr("for",g).text("Max value:"),f=(this.prefs.max_value===undefined?"":this.prefs.max_value),c=$("").attr("id",g).val(f);return a.append(h).append(j).append(d).append(c)},update_options:function(c){var a=$("#track_"+c+"_minval").val(),b=$("#track_"+c+"_maxval").val();if(a!==this.prefs.min_value||b!==this.prefs.max_value){this.prefs.min_value=parseFloat(a);this.prefs.max_value=parseFloat(b);this.vertical_range=this.prefs.max_value-this.prefs.min_value;$("#linetrack_"+c+"_minval").text(this.prefs.min_value);$("#linetrack_"+c+"_maxval").text(this.prefs.max_value);this.tile_cache.clear();this.draw()}}});var FeatureTrack=function(d,b,a,c){this.track_type="FeatureTrack";this.display_modes=["Auto","Dense","Squish","Pack"];Track.call(this,d,b,b.viewport_container);TiledTrack.call(this);this.height_px=0;this.container_div.addClass("feature-track");this.dataset_id=a;this.zo_slots={};this.show_labels_scale=0.001;this.showing_details=false;this.vertical_detail_px=10;this.vertical_nodetail_px=2;this.summary_draw_height=20;this.default_font="9px Monaco, Lucida Console, monospace";this.inc_slots={};this.data_queue={};this.s_e_by_tile={};this.tile_cache=new Cache(CACHED_TILES_FEATURE);this.data_cache=new Cache(20);this.left_offset=200;this.prefs={block_color:"black",label_color:"black",show_counts:true};if(c.block_color!==undefined){this.prefs.block_color=c.block_color}if(c.label_color!==undefined){this.prefs.label_color=c.label_color}if(c.show_counts!==undefined){this.prefs.show_counts=c.show_counts}};$.extend(FeatureTrack.prototype,TiledTrack.prototype,{init:function(){var a=this,b="initial";this.init_each({low:a.view.max_low,high:a.view.max_high,dataset_id:a.dataset_id,chrom:a.view.chrom,resolution:this.view.resolution,mode:a.mode},function(c){a.mode_div.show();a.data_cache.set(b,c);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,{chrom:b.view.chrom,low:a,high:d,dataset_id:b.dataset_id,resolution:this.view.resolution,mode:this.mode},function(e){b.data_cache.set(c,e);delete b.data_queue[c];b.draw()})}},incremental_slots:function(a,h,c,r){if(!this.inc_slots[a]){this.inc_slots[a]={};this.inc_slots[a].w_scale=a;this.inc_slots[a].mode=r;this.s_e_by_tile[a]={}}var n=this.inc_slots[a].w_scale,z=[],l=0,b=$("").get(0).getContext("2d"),o=this.view.max_low;var B=[];if(this.inc_slots[a].mode!==r){delete this.inc_slots[a];this.inc_slots[a]={mode:r,w_scale:n};delete this.s_e_by_tile[a];this.s_e_by_tile[a]={}}for(var w=0,x=h.length;wy[0]&&ePX_PER_CHAR){n.fillStyle=this.prefs.block_color;n.fillRect(k,h+1,e,9);n.fillStyle="#eee";for(var g=0,l=d.length;g=f&&b+g<=m){var a=Math.floor(Math.max(0,(b+g-f)*o));n.fillText(d[g],a+this.left_offset+j,h+9)}}}else{n.fillStyle=this.prefs.block_color;n.fillRect(k,h+4,e,3)}},draw_tile:function(ae,o,r,ar){var L=o*DENSITY*ae,ak=(o+1)*DENSITY*ae,K=ak-L;var al=(!this.initial_canvas?"initial":L+"_"+ak);var G=this.data_cache.get(al);var e;if(G===undefined||(this.mode!=="Auto"&&G.dataset_type==="summary_tree")){this.data_queue[[L,ak]]=true;this.get_data(L,ak);return}var a=Math.ceil(K*ar),S=$(""),ag=this.prefs.label_color,h=this.prefs.block_color,q=this.mode,v=25,ac=(q==="Squish")||(q==="Dense")&&(q!=="Pack")||(q==="Auto"&&(G.extra_info==="no_detail")),W=this.left_offset,aq,B,at;if(G.dataset_type==="summary_tree"){B=this.summary_draw_height}else{if(q==="Dense"){B=v;at=10}else{at=(ac?this.vertical_nodetail_px:this.vertical_detail_px);var w=(ar<0.0001?1/view.zoom_res:ar);B=this.incremental_slots(w,G.data,ac,q)*at+v;aq=this.inc_slots[w]}}S.css({position:"absolute",top:0,left:(L-this.view.low)*ar-W});S.get(0).width=a+W;S.get(0).height=B;r.parent().css("height",Math.max(this.height_px,B)+"px");var H=S.get(0).getContext("2d");H.fillStyle=h;H.font=this.default_font;H.textAlign="right";if(G.dataset_type=="summary_tree"){var R,O=55,aj=255-O,n=aj*2/3,Y=G.data,J=G.max,p=G.avg,b=Math.ceil(G.delta*ar);for(var an=0,F=Y.length;ann){H.fillStyle="black"}else{H.fillStyle="#ddd"}H.textAlign="center";H.fillText(Z,aa+W+(b/2),12)}}e="Summary";r.append(S);return S}if(G.message){S.css({border:"solid red","border-width":"2px 2px 2px 0px"});H.fillStyle="red";H.textAlign="left";H.fillText(G.message,100+W,at)}var ap=G.data;var am=0;for(var an=0,F=ap.length;an=L){var ad=Math.floor(Math.max(0,(ao-L)*ar)),I=Math.ceil(Math.min(a,Math.max(0,(ab-L)*ar))),X=(q==="Dense"?1:(1+aq[Q]))*at;if(G.dataset_type==="bai"){H.fillStyle=h;if(T[4] instanceof Array){var C=Math.floor(Math.max(0,(T[4][0]-L)*ar)),P=Math.ceil(Math.min(a,Math.max(0,(T[4][1]-L)*ar))),A=Math.floor(Math.max(0,(T[5][0]-L)*ar)),u=Math.ceil(Math.min(a,Math.max(0,(T[5][1]-L)*ar)));if(T[4][1]>=L&&T[4][0]<=ak){this.rect_or_text(H,ar,L,ak,T[4][0],T[4][2],C+W,P-C,X)}if(T[5][1]>=L&&T[5][0]<=ak){this.rect_or_text(H,ar,L,ak,T[5][0],T[5][2],A+W,u-A,X)}if(A>P){H.fillStyle="#999";H.fillRect(P+W,X+5,A-P,1)}}else{H.fillStyle=h;this.rect_or_text(H,ar,L,ak,ao,M,ad+W,I-ad,X)}if(q!=="Dense"&&!ac&&ao>L){H.fillStyle=this.prefs.label_color;if(o===0&&ad-H.measureText(M).width<0){H.textAlign="left";H.fillText(Q,I+2+W,X+8)}else{H.textAlign="right";H.fillText(Q,ad-2+W,X+8)}H.fillStyle=h}}else{if(G.dataset_type==="interval_index"){if(ac){H.fillStyle=h;H.fillRect(ad+W,X+5,I-ad,1)}else{var E=T[4],V=T[5],af=T[6],g=T[7];var D,ah,N=null,au=null;if(V&&af){N=Math.floor(Math.max(0,(V-L)*ar));au=Math.ceil(Math.min(a,Math.max(0,(af-L)*ar)))}if(q!=="Dense"&&M!==undefined&&ao>L){H.fillStyle=ag;if(o===0&&ad-H.measureText(M).width<0){H.textAlign="left";H.fillText(M,I+2+W,X+8)}else{H.textAlign="right";H.fillText(M,ad-2+W,X+8)}H.fillStyle=h}if(g){if(E){if(E=="+"){H.fillStyle=RIGHT_STRAND}else{if(E=="-"){H.fillStyle=LEFT_STRAND}}H.fillRect(ad+W,X,I-ad,10);H.fillStyle=h}for(var al=0,f=g.length;alU){continue}D=5;ah=3;H.fillRect(d+W,X+ah,U-d,D);if(N!==undefined&&!(d>au||UL){H.fillStyle=ag;if(o===0&&ad-H.measureText(M).width<0){H.textAlign="left";H.fillText(M,I+2+W,X+8)}else{H.textAlign="right";H.fillText(M,ad-2+W,X+8)}H.fillStyle=h}var l=s+" / "+m;if(ao>L&&H.measureText(l).width<(I-ad)){H.fillStyle="white";H.textAlign="center";H.fillText(l,W+ad+(I-ad)/2,X+8);H.fillStyle=h}}}}}am++}}r.append(S);return S},gen_options:function(j){var a=$("").addClass("form-row");var e="track_"+j+"_block_color",l=$("").attr("for",e).text("Block color:"),m=$("").attr("id",e).attr("name",e).val(this.prefs.block_color),k="track_"+j+"_label_color",g=$("").attr("for",k).text("Text color:"),h=$("").attr("id",k).attr("name",k).val(this.prefs.label_color),f="track_"+j+"_show_count",c=$("").attr("for",f).text("Show summary counts"),b=$('').attr("id",f).attr("name",f).attr("checked",this.prefs.show_counts),d=$("").append(b).append(c);return a.append(l).append(m).append(g).append(h).append(d)},update_options:function(e){var b=$("#track_"+e+"_block_color").val(),d=$("#track_"+e+"_label_color").val(),c=$("#track_"+e+"_mode option:selected").val(),a=$("#track_"+e+"_show_count").attr("checked");if(b!==this.prefs.block_color||d!==this.prefs.label_color||a!==this.prefs.show_counts){this.prefs.block_color=b;this.prefs.label_color=d;this.prefs.show_counts=a;this.tile_cache.clear();this.draw()}}});var ReadTrack=function(d,b,a,c){FeatureTrack.call(this,d,b,a,c);this.track_type="ReadTrack";this.vertical_detail_px=10;this.vertical_nodetail_px=5};$.extend(ReadTrack.prototype,TiledTrack.prototype,FeatureTrack.prototype,{});
\ No newline at end of file
diff --git a/static/scripts/trackster.js b/static/scripts/trackster.js
index cc31727bedb..be2239b5b4f 100644
--- a/static/scripts/trackster.js
+++ b/static/scripts/trackster.js
@@ -1348,8 +1348,45 @@ $.extend( FeatureTrack.prototype, TiledTrack.prototype, {
}
ctx.fillRect(f_start + left_offset, y_center, f_end - f_start, 10);
ctx.fillStyle = block_color;
+ }
+ }
+ }
+ } else if (result.dataset_type === 'vcf') {
+ if (no_detail) {
+ ctx.fillStyle = block_color;
+ ctx.fillRect(f_start + left_offset, y_center + 5, f_end - f_start, 1);
+ }
+ else { // Show blocks, labels, etc.
+ // Unpack.
+ var ref_base = feature[4], alt_base = feature[5], qual = feature[6];
+
+ // Draw block for entry.
+ thickness = 9;
+ y_start = 1;
+ ctx.fillRect(f_start + left_offset, y_center, f_end - f_start, thickness);
+
+ // Add label for entry.
+ if (mode !== "Dense" && feature_name !== undefined && feature_start > tile_low) {
+ // Draw label
+ ctx.fillStyle = label_color;
+ if (tile_index === 0 && f_start - ctx.measureText(feature_name).width < 0) {
+ ctx.textAlign = "left";
+ ctx.fillText(feature_name, f_end + 2 + left_offset, y_center + 8);
+ } else {
+ ctx.textAlign = "right";
+ ctx.fillText(feature_name, f_start - 2 + left_offset, y_center + 8);
}
+ ctx.fillStyle = block_color;
}
+
+ // Show additional data on block.
+ var vcf_label = ref_base + " / " + alt_base;
+ if (feature_start > tile_low && ctx.measureText(vcf_label).width < (f_end - f_start)) {
+ ctx.fillStyle = "white";
+ ctx.textAlign = "center";
+ ctx.fillText(vcf_label, left_offset + f_start + (f_end-f_start)/2, y_center + 8);
+ ctx.fillStyle = block_color;
+ }
}
}
j++;