galaxy-commits
Threads by month
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
February 2011
- 1 participants
- 166 discussions
22 Feb '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/7e31d5c0a42d/
changeset: r5106:7e31d5c0a42d
user: dan
date: 2011-02-22 22:56:11
summary: Allow toolbox tests to upload a file found located in subdirectories. Fix a bug occurring on the determination of uploaded dataset name during the handling of the removal of .gzip or .zip extension from the uploaded filenames within the toolbox test framework.
affected #: 1 file (127 bytes)
--- a/test/functional/test_toolbox.py Tue Feb 22 15:31:57 2011 -0500
+++ b/test/functional/test_toolbox.py Tue Feb 22 16:56:11 2011 -0500
@@ -1,4 +1,5 @@
import sys, new
+import os.path
from galaxy.tools.parameters import grouping
from galaxy.tools.parameters import basic
from base.twilltestcase import TwillTestCase
@@ -58,8 +59,9 @@
if value:
for end in [ '.zip', '.gz' ]:
if value.endswith( end ):
- value = value.rstrip( end )
+ value = value[ :-len( end ) ]
break
+ value = os.path.basename( value ) #if uploading a file in a path other than root of test-data
all_inputs[ name ] = value
# See if we have a grouping.Repeat element
repeat_name = None
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
22 Feb '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/bcac5cc3ae9f/
changeset: r5105:bcac5cc3ae9f
user: rc
date: 2011-02-22 21:31:57
summary: Adding VCF annotate and intersect tools
affected #: 19 files (144 bytes)
Diff too large to display.
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: guru: Fixed functional tests for the following tools: histogram, estimate indel rates, compute q-values, kernel pca.
by Bitbucket 22 Feb '11
by Bitbucket 22 Feb '11
22 Feb '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/09682e35aa75/
changeset: r5104:09682e35aa75
user: guru
date: 2011-02-22 18:37:06
summary: Fixed functional tests for the following tools: histogram, estimate indel rates, compute q-values, kernel pca.
affected #: 10 files (509 bytes)
--- a/test-data/indelrates_3way.tabular Tue Feb 22 11:00:03 2011 -0500
+++ b/test-data/indelrates_3way.tabular Tue Feb 22 12:37:06 2011 -0500
@@ -1,15 +1,15 @@
#Block hg18_InsRate panTro2_InsRate canFam2_InsRate hg18_DelRate panTro2_DelRate canFam2_DelRate
-1 0.00e+00 0.00e+00 6.90e-03 0.00e+00 0.00e+00 6.90e-03
-2 0.00e+00 0.00e+00 1.20e-02 0.00e+00 0.00e+00 6.36e-03
+1 0.00e+00 6.90e-03 6.90e-03 0.00e+00 0.00e+00 1.38e-02
+2 0.00e+00 0.00e+00 1.27e-02 7.25e-04 0.00e+00 6.36e-03
3 0.00e+00 0.00e+00 6.21e-03 0.00e+00 0.00e+00 6.21e-03
4 0.00e+00 0.00e+00 2.07e-02 0.00e+00 0.00e+00 5.18e-03
-5 0.00e+00 0.00e+00 1.69e-02 0.00e+00 0.00e+00 8.47e-03
+5 0.00e+00 0.00e+00 2.54e-02 0.00e+00 0.00e+00 1.69e-02
6 0.00e+00 0.00e+00 9.61e-04 0.00e+00 0.00e+00 0.00e+00
7 0.00e+00 0.00e+00 1.97e-02 0.00e+00 0.00e+00 5.62e-03
8 0.00e+00 1.71e-03 1.17e-02 0.00e+00 1.71e-03 6.67e-03
-9 0.00e+00 0.00e+00 1.05e-02 0.00e+00 0.00e+00 1.57e-02
+9 0.00e+00 0.00e+00 1.05e-02 2.72e-03 0.00e+00 1.83e-02
10 0.00e+00 3.26e-03 1.51e-02 0.00e+00 0.00e+00 1.89e-02
-12 1.25e-03 0.00e+00 8.70e-03 0.00e+00 0.00e+00 1.12e-02
-13 0.00e+00 0.00e+00 6.76e-03 0.00e+00 0.00e+00 4.05e-02
-14 0.00e+00 0.00e+00 3.70e-03 0.00e+00 6.13e-04 5.55e-03
+12 1.25e-03 0.00e+00 8.70e-03 0.00e+00 0.00e+00 1.24e-02
+13 0.00e+00 0.00e+00 6.76e-03 0.00e+00 0.00e+00 4.73e-02
+14 0.00e+00 0.00e+00 4.93e-03 1.23e-03 1.23e-03 5.55e-03
15 0.00e+00 0.00e+00 2.29e-02 0.00e+00 0.00e+00 1.38e-02
--- a/test-data/kpca_out3.tabular Tue Feb 22 11:00:03 2011 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,304 +0,0 @@
-#Component 1
-#Eigenvalue 0.3836
-#Principal component vectors 1
-1 -0.1858
-2 -0.1814
-3 -0.1859
-4 -0.1806
-5 -0.1858
-6 -0.1735
-7 -0.1847
-8 -0.1833
-9 -0.1796
-10 -0.1813
-11 -0.1833
-12 -0.1805
-13 -0.182
-14 -0.1853
-15 -0.1845
-16 -0.1704
-17 -0.1833
-18 -0.1849
-19 -0.1757
-20 -0.1817
-21 -0.1772
-22 -0.181
-23 -0.1888
-24 -0.1717
-25 -0.1689
-26 -0.1762
-27 -0.1779
-28 -0.1836
-29 -0.1856
-30 -0.179
-31 -0.1777
-32 -0.1809
-33 -0.1793
-34 -0.1787
-35 -0.1813
-36 -0.187
-37 -0.1875
-38 -0.1813
-39 -0.1832
-40 -0.1833
-41 -0.1867
-42 -0.1641
-43 -0.1859
-44 -0.1743
-45 -0.1659
-46 -0.1805
-47 -0.18
-48 -0.1841
-49 -0.1833
-50 -0.185
-51 0.09424
-52 0.0852
-53 0.1077
-54 0.04757
-55 0.09435
-56 0.08257
-57 0.098
-58 -0.02337
-59 0.08823
-60 0.04166
-61 -0.002438
-62 0.06651
-63 0.03717
-64 0.09682
-65 0.009931
-66 0.07686
-67 0.08726
-68 0.04361
-69 0.08623
-70 0.03213
-71 0.1081
-72 0.04584
-73 0.1083
-74 0.09118
-75 0.0684
-76 0.07783
-77 0.1022
-78 0.1163
-79 0.08795
-80 -0.007513
-81 0.02424
-82 0.012
-83 0.03462
-84 0.1183
-85 0.08726
-86 0.08491
-87 0.09801
-88 0.07569
-89 0.05223
-90 0.04736
-91 0.07326
-92 0.09055
-93 0.04351
-94 -0.02219
-95 0.06216
-96 0.05659
-97 0.06096
-98 0.0684
-99 -0.04782
-100 0.05391
-101 0.1161
-102 0.1221
-103 0.1258
-104 0.1285
-105 0.1265
-106 0.1025
-107 0.09298
-108 0.116
-109 0.1247
-110 0.1087
-111 0.121
-112 0.1262
-113 0.1286
-114 0.1185
-115 0.1218
-116 0.1245
-117 0.128
-118 0.08626
-119 0.08214
-120 0.1082
-121 0.1253
-122 0.1168
-123 0.09795
-124 0.1146
-125 0.1259
-126 0.1232
-127 0.1106
-128 0.1141
-129 0.1287
-130 0.1256
-131 0.1219
-132 0.1007
-133 0.1281
-134 0.1165
-135 0.1219
-136 0.1191
-137 0.1221
-138 0.1274
-139 0.1099
-140 0.1275
-141 0.1254
-142 0.1218
-143 0.1221
-144 0.1227
-145 0.1211
-146 0.1244
-147 0.1179
-148 0.125
-149 0.1229
-150 0.1209
-#Rotated values 1
-1 -10.69
-2 -10.44
-3 -10.7
-4 -10.39
-5 -10.69
-6 -9.981
-7 -10.63
-8 -10.55
-9 -10.34
-10 -10.43
-11 -10.55
-12 -10.39
-13 -10.48
-14 -10.67
-15 -10.62
-16 -9.808
-17 -10.55
-18 -10.64
-19 -10.11
-20 -10.45
-21 -10.2
-22 -10.41
-23 -10.86
-24 -9.88
-25 -9.717
-26 -10.14
-27 -10.24
-28 -10.57
-29 -10.68
-30 -10.3
-31 -10.23
-32 -10.41
-33 -10.32
-34 -10.28
-35 -10.43
-36 -10.76
-37 -10.79
-38 -10.43
-39 -10.54
-40 -10.55
-41 -10.74
-42 -9.445
-43 -10.7
-44 -10.03
-45 -9.547
-46 -10.38
-47 -10.36
-48 -10.6
-49 -10.55
-50 -10.65
-51 5.423
-52 4.903
-53 6.197
-54 2.737
-55 5.43
-56 4.752
-57 5.639
-58 -1.345
-59 5.077
-60 2.397
-61 -0.1403
-62 3.827
-63 2.139
-64 5.572
-65 0.5715
-66 4.423
-67 5.021
-68 2.509
-69 4.962
-70 1.849
-71 6.218
-72 2.638
-73 6.23
-74 5.247
-75 3.936
-76 4.479
-77 5.884
-78 6.695
-79 5.061
-80 -0.4323
-81 1.395
-82 0.6907
-83 1.992
-84 6.805
-85 5.021
-86 4.886
-87 5.64
-88 4.355
-89 3.006
-90 2.725
-91 4.216
-92 5.211
-93 2.504
-94 -1.277
-95 3.577
-96 3.256
-97 3.508
-98 3.936
-99 -2.752
-100 3.102
-101 6.68
-102 7.026
-103 7.239
-104 7.395
-105 7.281
-106 5.899
-107 5.351
-108 6.677
-109 7.175
-110 6.254
-111 6.962
-112 7.265
-113 7.403
-114 6.821
-115 7.008
-116 7.163
-117 7.363
-118 4.964
-119 4.726
-120 6.229
-121 7.212
-122 6.719
-123 5.636
-124 6.595
-125 7.245
-126 7.087
-127 6.364
-128 6.566
-129 7.406
-130 7.23
-131 7.014
-132 5.796
-133 7.369
-134 6.703
-135 7.014
-136 6.852
-137 7.025
-138 7.331
-139 6.323
-140 7.335
-141 7.214
-142 7.008
-143 7.026
-144 7.059
-145 6.971
-146 7.158
-147 6.784
-148 7.191
-149 7.071
-150 6.959
--- a/test-data/q_values.tabular Tue Feb 22 11:00:03 2011 -0500
+++ b/test-data/q_values.tabular Tue Feb 22 12:37:06 2011 -0500
@@ -1,4 +1,4 @@
-pi0: 0.243863648325618
+pi0: 0.243863648325601
FDR level: 0.05
--- a/test/base/twilltestcase.py Tue Feb 22 11:00:03 2011 -0500
+++ b/test/base/twilltestcase.py Tue Feb 22 12:37:06 2011 -0500
@@ -76,7 +76,7 @@
# PDF files contain creation dates, modification dates, ids and descriptions that change with each
# new file, so we need to handle these differences. As long as the rest of the PDF file does
# not differ we're ok.
- valid_diff_strs = [ 'description', 'createdate', 'creationdate', 'moddate', 'id', 'producer', 'creator' ]
+ valid_diff_strs = [ 'description', 'createdate', 'creationdate', 'moddate', 'id', 'producer', 'creator', 'extgstate', 'ais' ]
valid_diff = False
for line in diff_slice:
# Make sure to lower case strings before checking.
--- a/tools/multivariate_stats/kpca.py Tue Feb 22 11:00:03 2011 -0500
+++ b/tools/multivariate_stats/kpca.py Tue Feb 22 12:37:06 2011 -0500
@@ -97,7 +97,7 @@
elif kernel=="anovadot":
pars = r.list(degree=float(options.degree),sigma=float(options.sigma))
else:
- pars = rlist()
+ pars = r.list()
try:
kpc = r.kpca(x=r.na_exclude(dat), kernel=kernel, kpar=pars, features=ncomps)
--- a/tools/multivariate_stats/kpca.xml Tue Feb 22 11:00:03 2011 -0500
+++ b/tools/multivariate_stats/kpca.xml Tue Feb 22 12:37:06 2011 -0500
@@ -110,17 +110,6 @@
<output name="out_file1" file="kpca_out1.tabular"/><output name="out_file2" file="kpca_out2.pdf"/></test>
- <test>
- <param name="input1" value="iris.tabular"/>
- <param name="var_cols" value="2,3,4"/>
- <param name="kernel" value="besseldot"/>
- <param name="features" value="1"/>
- <param name="sigma" value="1"/>
- <param name="order" value="1"/>
- <param name="degree" value="1"/>
- <output name="out_file1" file="kpca_out3.tabular"/>
- <output name="out_file2" file="kpca_out4.pdf"/>
- </test></tests><help>
--- a/tools/plotting/histogram.py Tue Feb 22 11:00:03 2011 -0500
+++ b/tools/plotting/histogram.py Tue Feb 22 12:37:06 2011 -0500
@@ -73,7 +73,7 @@
if skipped_lines < i:
try:
- a = array( matrix )
+ a = r.array( matrix )
r.pdf( out_fname, 8, 8 )
histogram = r.hist( a, probability=not frequency, main=title, xlab=xlab, breaks=breaks )
if density:
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
22 Feb '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/e323df1a604d/
changeset: r5103:e323df1a604d
user: jgoecks
date: 2011-02-22 17:00:03
summary: Trackster: (a) refactoring back down to a single draw_tile method for FeatureTracks but each track now has a draw_element() method for drawing individual elements; (b) when mode is Auto, enable squish mode when possible to bridge from summary tree to pack.
affected #: 2 files (14.7 KB)
--- a/static/scripts/packed/trackster.js Tue Feb 22 10:38:35 2011 -0500
+++ b/static/scripts/packed/trackster.js Tue Feb 22 11:00:03 2011 -0500
@@ -1,1 +1,1 @@
-CanvasRenderingContext2D.prototype.dashedLine=function(c,i,b,h,f){if(f==undefined){f=4}var e=b-c;var d=h-i;var g=Math.floor(Math.sqrt(e*e+d*d)/f);var k=e/g;var j=d/g;for(var a=0;a<g;a++,c+=k,i+=j){if(a%2!=0){continue}this.fillRect(c,i,f,1)}};CanvasRenderingContext2D.prototype.drawDownwardEquilateralTriangle=function(b,a,e){var d=b-e/2,c=b+e/2,f=a-Math.sqrt(e*3/2);this.beginPath();this.moveTo(d,f);this.lineTo(c,f);this.lineTo(b,a);this.lineTo(d,f);this.strokeStyle=this.fillStyle;this.fill();this.stroke();this.closePath()};function sortable(a,b){a.bind("drag",{handle:b,relative:true},function(h,j){var g=$(this).parent();var f=g.children();for(var c=0;c<f.length;c++){if(j.offsetY<$(f.get(c)).position().top){break}}if(c==f.length){if(this!=f.get(c-1)){g.append(this)}}else{if(this!=f.get(c)){$(this).insertBefore(f.get(c))}}})}var NO_OVERLAP=1001,CONTAINS=1002,OVERLAP_START=1003,OVERLAP_END=1004,CONTAINED_BY=1005;function compute_overlap(e,b){var g=e[0],f=e[1],d=b[0],c=b[1],a;if(g<d){if(f<d){a=NO_OVERLAP}else{if(f<=c){a=OVERLAP_START}else{a=CONTAINS}}}else{if(g>c){a=NO_OVERLAP}else{if(f<=c){a=CONTAINED_BY}else{a=OVERLAP_END}}}return a}function is_overlap(b,a){return(compute_overlap(b,a)!=NO_OVERLAP)}var DENSE_TRACK_HEIGHT=10,NO_DETAIL_TRACK_HEIGHT=3,SQUISH_TRACK_HEIGHT=5,PACK_TRACK_HEIGHT=10,NO_DETAIL_FEATURE_HEIGHT=DENSE_FEATURE_HEIGHT=1,SQUISH_FEATURE_HEIGHT=3,PACK_FEATURE_HEIGHT=9,LABEL_SPACING=2,PACK_SPACING=5,DEFAULT_FONT="9px Monaco, Lucida Console, monospace",DENSITY=200,FEATURE_LEVELS=10,MAX_FEATURE_DEPTH=100,DEFAULT_DATA_QUERY_WAIT=5000,MAX_CHROMS_SELECTABLE=100,CONNECTOR_COLOR="#ccc",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_CANNOT_RUN_TOOL="Tool cannot be rerun: ",DATA_LOADING="Loading data...",DATA_OK="Ready for display",FILTERABLE_CLASS="filterable",CACHED_TILES_FEATURE=10,CACHED_TILES_LINE=5,CACHED_DATA=5,DUMMY_CANVAS=document.createElement("canvas"),RIGHT_STRAND,LEFT_STRAND;if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(DUMMY_CANVAS)}var CONTEXT=DUMMY_CANVAS.getContext("2d");CONTEXT.font=DEFAULT_FONT;var CHAR_WIDTH_PX=CONTEXT.measureText("A").width,CHAR_HEIGHT_PX=9;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.move_key_to_end(b,a)}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},move_key_to_end:function(b,a){this.key_ary.splice(a,1);this.key_ary.push(b)},clear:function(){this.obj_cache={};this.key_ary=[]},size:function(){return this.key_ary.length}});var DataCache=function(a){Cache.call(this,a)};$.extend(DataCache.prototype,Cache.prototype,{get_data:function(g,b,e){var h=this.get(this.gen_key(g,b,e));if(h){return h}var j,f,a,d,e,h;for(var c=0;c<this.key_ary.length;c++){j=this.key_ary[c];f=this.split_key(j);a=f[0];d=f[1];if(g>=a&&b<=d){h=this.obj_cache[j];if(h.dataset_type!=="summary_tree"&&h.extra_info!=="no_detail"){this.move_key_to_end(j,c);return h}}}return undefined},set_data:function(b,c,d,a){return this.set(this.gen_key(b,c,d),a)},gen_key:function(a,c,d){var b=a+"_"+c+"_"+d;return b},split_key:function(a){return a.split("_")}});var View=function(a,d,c,b,e){this.container=a;this.chrom=null;this.vis_id=c;this.dbkey=b;this.title=d;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(e);this.reset()};$.extend(View.prototype,{init:function(d){var c=this.container,a=this;this.top_container=$("<div/>").addClass("top-container").appendTo(c);this.content_div=$("<div/>").addClass("content").css("position","relative").appendTo(c);this.bottom_container=$("<div/>").addClass("bottom-container").appendTo(c);this.top_labeltrack=$("<div/>").addClass("top-labeltrack").appendTo(this.top_container);this.viewport_container=$("<div/>").addClass("viewport-container").addClass("viewport-container").appendTo(this.content_div);this.intro_div=$("<div/>").addClass("intro").text("Select a chrom from the dropdown below").hide();this.nav_labeltrack=$("<div/>").addClass("nav-labeltrack").appendTo(this.bottom_container);this.nav_container=$("<div/>").addClass("nav-container").prependTo(this.top_container);this.nav=$("<div/>").addClass("nav").appendTo(this.nav_container);this.overview=$("<div/>").addClass("overview").appendTo(this.bottom_container);this.overview_viewport=$("<div/>").addClass("overview-viewport").appendTo(this.overview);this.overview_close=$("<a href='javascript:void(0);'>Close Overview</a>").addClass("overview-close").hide().appendTo(this.overview_viewport);this.overview_highlight=$("<div/>").addClass("overview-highlight").hide().appendTo(this.overview_viewport);this.overview_box_background=$("<div/>").addClass("overview-boxback").appendTo(this.overview_viewport);this.overview_box=$("<div/>").addClass("overview-box").appendTo(this.overview_viewport);this.default_overview_height=this.overview_box.height();this.nav_controls=$("<div/>").addClass("nav-controls").appendTo(this.nav);this.chrom_form=$("<form/>").attr("action",function(){}).appendTo(this.nav_controls);this.chrom_select=$("<select/>").attr({name:"chrom"}).css("width","15em").addClass("no-autocomplete").append("<option value=''>Loading</option>").appendTo(this.chrom_form);var b=function(f){if(f.type==="focusout"||(f.keyCode||f.which)===13||(f.keyCode||f.which)===27){if((f.keyCode||f.which)!==27){a.go_to($(this).val())}$(this).hide();a.location_span.show();a.chrom_select.show();return false}};this.nav_input=$("<input/>").addClass("nav-input").hide().bind("keypress focusout",b).appendTo(this.chrom_form);this.location_span=$("<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=$("<input/>").attr("type","hidden").val(this.vis_id).appendTo(this.chrom_form)}this.zo_link=$("<a id='zoom-out' />").click(function(){a.zoom_out();a.redraw()}).appendTo(this.chrom_form);this.zi_link=$("<a id='zoom-in' />").click(function(){a.zoom_in();a.redraw()}).appendTo(this.chrom_form);this.load_chroms({low:0},d);this.chrom_select.bind("change",function(){a.change_chrom(a.chrom_select.val())});this.intro_div.show();this.content_div.bind("click",function(f){$(this).find("input").trigger("blur")});this.content_div.bind("dblclick",function(f){a.zoom_in(f.pageX,this.viewport_container)});this.overview_box.bind("dragstart",function(f,g){this.current_x=g.offsetX}).bind("drag",function(f,h){var i=h.offsetX-this.current_x;this.current_x=h.offsetX;var g=Math.round(i/a.viewport_container.width()*(a.max_high-a.max_low));a.move_delta(-g)});this.overview_close.bind("click",function(){for(var f=0,e=a.tracks.length;f<e;f++){a.tracks[f].is_overview=false}$(this).siblings().filter("canvas").remove();$(this).parent().css("height",a.overview_box.height());a.overview_highlight.hide();$(this).hide()});this.viewport_container.bind("draginit",function(f,g){if(f.clientX>a.viewport_container.width()-16){return false}}).bind("dragstart",function(f,g){g.original_low=a.low;g.current_height=f.clientY;g.current_x=g.offsetX}).bind("drag",function(h,j){var f=$(this);var k=j.offsetX-j.current_x;var g=f.scrollTop()-(h.clientY-j.current_height);f.scrollTop(g);j.current_height=h.clientY;j.current_x=j.offsetX;var i=Math.round(k/a.viewport_container.width()*(a.high-a.low));a.move_delta(i)}).bind("mousewheel",function(h,j,g,f){if(g){var i=Math.round(-g/a.viewport_container.width()*(a.high-a.low));a.move_delta(i)}});this.top_labeltrack.bind("dragstart",function(f,g){return $("<div />").css({height:a.content_div.height()+a.top_labeltrack.height()+a.nav_labeltrack.height()+1,top:"0px",position:"absolute","background-color":"#ccf",opacity:0.5,"z-index":1000}).appendTo($(this))}).bind("drag",function(j,k){$(k.proxy).css({left:Math.min(j.pageX,k.startX),width:Math.abs(j.pageX-k.startX)});var g=Math.min(j.pageX,k.startX)-a.container.offset().left,f=Math.max(j.pageX,k.startX)-a.container.offset().left,i=(a.high-a.low),h=a.viewport_container.width();a.update_location(Math.round(g/h*i)+a.low,Math.round(f/h*i)+a.low)}).bind("dragend",function(k,l){var g=Math.min(k.pageX,l.startX),f=Math.max(k.pageX,l.startX),i=(a.high-a.low),h=a.viewport_container.width(),j=a.low;a.low=Math.round(g/h*i)+j;a.high=Math.round(f/h*i)+j;$(l.proxy).remove();a.redraw()});this.add_label_track(new LabelTrack(this,this.top_labeltrack));this.add_label_track(new LabelTrack(this,this.nav_labeltrack));$(window).bind("resize",function(){a.resize_window()});$(document).bind("redraw",function(){a.redraw()});this.reset();$(window).trigger("resize")},update_location:function(a,b){this.location_span.text(commatize(a)+" - "+commatize(b));this.nav_input.val(this.chrom+":"+commatize(a)+"-"+commatize(b))},load_chroms:function(b,c){b.num=MAX_CHROMS_SELECTABLE;$.extend(b,(this.vis_id!==undefined?{vis_id:this.vis_id}:{dbkey:this.dbkey}));var a=this;$.ajax({url:chrom_url,data:b,dataType:"json",success:function(e){if(e.reference){a.add_label_track(new ReferenceTrack(a))}a.chrom_data=e.chrom_info;var h='<option value="">Select Chrom/Contig</option>';for(var g=0,d=a.chrom_data.length;g<d;g++){var f=a.chrom_data[g].chrom;h+='<option value="'+f+'">'+f+"</option>"}if(e.prev_chroms){h+='<option value="previous">Previous '+MAX_CHROMS_SELECTABLE+"</option>"}if(e.next_chroms){h+='<option value="next">Next '+MAX_CHROMS_SELECTABLE+"</option>"}a.chrom_select.html(h);if(c){c()}a.chrom_start_index=e.start_index},error:function(){alert("Could not load chroms for this dbkey:",a.dbkey)}})},change_chrom:function(e,b,g){if(!e||e==="None"){return}var d=this;if(e=="previous"){d.load_chroms({low:this.chrom_start_index-MAX_CHROMS_SELECTABLE});return}if(e=="next"){d.load_chroms({low:this.chrom_start_index+MAX_CHROMS_SELECTABLE});return}var f=$.grep(d.chrom_data,function(j,k){return j.chrom===e})[0];if(f===undefined){d.load_chroms({chrom:e},function(){d.change_chrom(e,b,g)});return}else{if(e!==d.chrom){d.chrom=e;if(!d.chrom){d.intro_div.show()}else{d.intro_div.hide()}d.chrom_select.val(d.chrom);d.max_high=f.len-1;d.reset();d.redraw(true);for(var h=0,a=d.tracks.length;h<a;h++){var c=d.tracks[h];if(c.init){c.init()}}}if(b!==undefined&&g!==undefined){d.low=Math.max(b,0);d.high=Math.min(g,d.max_high)}d.reset_overview();d.redraw()}},go_to:function(f){var j=this,a,d,b=f.split(":"),h=b[0],i=b[1];if(i!==undefined){try{var g=i.split("-");a=parseInt(g[0].replace(/,/g,""),10);d=parseInt(g[1].replace(/,/g,""),10)}catch(c){return false}}j.change_chrom(h,a,d)},move_fraction:function(c){var a=this;var b=a.high-a.low;this.move_delta(c*b)},move_delta:function(c){var a=this;var b=a.high-a.low;if(a.low-c<a.max_low){a.low=a.max_low;a.high=a.max_low+b}else{if(a.high-c>a.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);sortable(a.container_div,".draghandle");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 g=this.high-this.low,f=this.low,b=this.high;if(f<this.max_low){f=this.max_low}if(b>this.max_high){b=this.max_high}if(this.high!==0&&g<this.min_separation){b=f+this.min_separation}this.low=Math.floor(f);this.high=Math.ceil(b);this.resolution=Math.pow(10,Math.ceil(Math.log((this.high-this.low)/200)/Math.LN10));this.zoom_res=Math.pow(FEATURE_LEVELS,Math.max(0,Math.ceil(Math.log(this.resolution,FEATURE_LEVELS)/Math.log(FEATURE_LEVELS))));var a=(this.low/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var e=((this.high-this.low)/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var j=13;this.overview_box.css({left:a,width:Math.max(j,e)}).show();if(e<j){this.overview_box.css("left",a-(j-e)/2)}if(this.overview_highlight){this.overview_highlight.css({left:a,width:e})}this.update_location(this.low,this.high);if(!h){for(var c=0,d=this.tracks.length;c<d;c++){if(this.tracks[c]&&this.tracks[c].enabled){this.tracks[c].draw()}}for(c=0,d=this.label_tracks.length;c<d;c++){this.label_tracks[c].draw()}}},zoom_in:function(b,c){if(this.max_high===0||this.high-this.low<this.min_separation){return}var d=this.high-this.low,e=d/2+this.low,a=(d/this.zoom_factor)/2;if(b){e=b/this.viewport_container.width()*(this.high-this.low)+this.low}this.low=Math.round(e-a);this.high=Math.round(e+a);this.redraw()},zoom_out:function(){if(this.max_high===0){return}var b=this.high-this.low,c=b/2+this.low,a=(b*this.zoom_factor)/2;this.low=Math.round(c-a);this.high=Math.round(c+a);this.redraw()},resize_window:function(){this.viewport_container.height(this.container.height()-this.top_container.height()-this.bottom_container.height());this.nav_container.width(this.container.width());this.redraw()},reset_overview:function(){this.overview_viewport.find("canvas").remove();this.overview_viewport.height(this.default_overview_height);this.overview_box.height(this.default_overview_height);this.overview_close.hide();this.overview_highlight.hide()}});var Tool=function(a,b){this.name=a;this.params=b};$.extend(Tool.prototype,{get_param_values_dict:function(){var b={};for(var a=0;a<this.params.length;a++){var c=this.params[a];b[c.name]=c.value}return b},get_param_values:function(){var b=[];for(var a=0;a<this.params.length;a++){b[a]=this.params[a].value}return b}});var NumberToolParameter=function(c,b,e,a,d){this.name=c;this.label=b;this.min=e;this.max=a;this.value=d};var get_tool_from_dict=function(f){if(obj_length(f)==0){return undefined}var b=f.name;var l=f.params;var c=Array();for(var e=0;e<l.length;e++){var g=l[e];var a=g.name,k=g.label,h=g.type,d=g.min,j=g.max,m=g.value;c[c.length]=new NumberToolParameter(a,k,d,j,m)}return new Tool(b,c)};var Filter=function(b,a,c){this.name=b;this.index=a;this.value=c};var NumberFilter=function(b,a){this.name=b;this.index=a;this.low=-Number.MAX_VALUE;this.high=Number.MAX_VALUE;this.slider_min=Number.MAX_VALUE;this.slider_max=-Number.MAX_VALUE;this.slider=null;this.slider_label=null};$.extend(NumberFilter.prototype,{applies_to:function(a){if(a.length>this.index){return true}return false},keep:function(a){if(!this.applies_to(a)){return true}return(a[this.index]>=this.low&&a[this.index]<=this.high)},update_attrs:function(b){var a=false;if(!this.applies_to(b)){return a}if(b[this.index]<this.slider_min){this.slider_min=b[this.index];a=true}if(b[this.index]>this.slider_max){this.slider_max=b[this.index];a=false}return a},update_ui_elt:function(){var b=this.slider.slider("option","min"),a=this.slider.slider("option","max");if(this.slider_min<b||this.slider_max>a){this.slider.slider("option","min",this.slider_min);this.slider.slider("option","max",this.slider_max);this.slider.slider("option","values",[this.slider_min,this.slider_max])}}});var get_filters_from_dict=function(a){var g=[];for(var d=0;d<a.length;d++){var f=a[d];var c=f.name,e=f.type,b=f.index;if(e=="int"||e=="float"){g[d]=new NumberFilter(c,b)}else{g[d]=new Filter(c,b,e)}}return g};var TrackConfig=function(a){this.track=a.track;this.params=a.params;this.values={};if(a.saved_values){this.restore_values(a.saved_values)}this.onchange=a.onchange};$.extend(TrackConfig.prototype,{restore_values:function(a){var b=this;$.each(this.params,function(c,d){if(a[d.key]!==undefined){b.values[d.key]=a[d.key]}else{b.values[d.key]=d.default_value}})},build_form:function(){var b=this;var a=$("<div />");$.each(this.params,function(f,d){if(!d.hidden){var c="param_"+f;var k=$("<div class='form-row' />").appendTo(a);k.append($("<label />").attr("for",c).text(d.label+":"));if(d.type=="bool"){k.append($('<input type="checkbox" />').attr("id",c).attr("name",c).attr("checked",b.values[d.key]))}else{if(d.type=="color"){var h=b.values[d.key];var g=$("<input />").attr("id",c).attr("name",c).val(h);var i=$("<div class='tipsy tipsy-north' style='position: absolute;' />").hide();var e=$("<div style='background-color: black; padding: 10px;'></div>").appendTo(i);var j=$("<div/>").appendTo(e).farbtastic({width:100,height:100,callback:g,color:h});$("<div />").append(g).append(i).appendTo(k).bind("click",function(l){i.css({left:$(this).position().left+($(g).width()/2)-60,top:$(this).position().top+$(this.height)}).show();$(document).bind("click.color-picker",function(){i.hide();$(document).unbind("click.color-picker")});l.stopPropagation()})}else{k.append($("<input />").attr("id",c).attr("name",c).val(b.values[d.key]))}}}});return a},update_from_form:function(a){var c=this;var b=false;$.each(this.params,function(d,f){if(!f.hidden){var g="param_"+d;var e=a.find("#"+g).val();if(f.type=="float"){e=parseFloat(e)}else{if(f.type=="int"){e=parseInt(e)}else{if(f.type=="bool"){e=a.find("#"+g).is(":checked")}}}if(e!==c.values[f.key]){c.values[f.key]=e;b=true}}});if(b){this.onchange()}}});var Track=function(b,a,e,c,d){this.name=b;this.view=a;this.parent_element=e;this.data_url=(c?c:default_data_url);this.data_query_wait=(d?d:DEFAULT_DATA_QUERY_WAIT);this.dataset_check_url=converted_datasets_state_url;this.container_div=$("<div />").addClass("track").css("position","relative");if(!this.hidden){this.header_div=$("<div class='track-header' />").appendTo(this.container_div);if(this.view.editor){this.drag_div=$("<div class='draghandle' />").appendTo(this.header_div)}this.name_div=$("<div class='menubutton popup' />").appendTo(this.header_div);this.name_div.text(this.name);this.name_div.attr("id",this.name.replace(/\s+/g,"-").replace(/[^a-zA-Z0-9\-]/g,"").toLowerCase())}this.content_div=$("<div class='track-content'>").appendTo(this.container_div);this.parent_element.append(this.container_div)};$.extend(Track.prototype,{init:function(){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");a.container_div.removeClass("nodata error pending");if(!a.dataset_id){return}if(a.view.chrom!=null){$.getJSON(converted_datasets_state_url,{hda_ldda:a.hda_ldda,dataset_id:a.dataset_id,chrom:a.view.chrom},function(b){if(!b||b==="error"||b.kind==="error"){a.container_div.addClass("error");a.content_div.text(DATA_ERROR);if(b.message){var d=a.view.tracks.indexOf(a);var c=$(" <a href='javascript:void(0);'></a>").text("View error").bind("click",function(){show_modal("Trackster Error","<pre>"+b.message+"</pre>",{Close:hide_modal})});a.content_div.append(c)}}else{if(b==="no converter"){a.container_div.addClass("error");a.content_div.text(DATA_NOCONVERTER)}else{if(b==="no data"||(b.data!==undefined&&(b.data===null||b.data.length===0))){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()},a.data_query_wait)}else{if(b.status==="data"){if(b.valid_chroms){a.valid_chroms=b.valid_chroms;a.name_div.data("menu_options")["List chrom/contigs with data"]=function(){show_modal("Chrom/contigs with data","<p>"+a.valid_chroms.join("<br/>")+"</p>",{Close:function(){hide_modal()}})}}a.content_div.text(DATA_OK);if(a.view.chrom){a.content_div.text("");a.content_div.css("height",a.height_px+"px");a.enabled=true;$.when(a.predraw_init()).done(function(){a.draw()})}}}}}}})}},predraw_init:function(){},update_name:function(a){this.old_name=this.name;this.name=a;this.name_div.text(this.name)},revert_name:function(){this.name=this.old_name;this.name_div.text(this.name)}});var TiledTrack=function(g,d,s){var o=this,j=o.view;this.filters=(g!==undefined?get_filters_from_dict(g):[]);this.tool=(d!==undefined?get_tool_from_dict(d):undefined);this.parent_track=s;this.child_tracks=[];if(o.hidden){return}if(this.parent_track){this.header_div.find(".draghandle").removeClass("draghandle").addClass("child-track-icon").addClass("icon-button");this.parent_element.addClass("child-track");this.tool=undefined}this.filtering_div=$("<div/>").addClass("track-filters").hide();this.header_div.after(this.filtering_div);this.filtering_div.bind("drag",function(i){i.stopPropagation()}).bind("dblclick",function(i){i.stopPropagation()});var t=$("<table class='filters'>").appendTo(this.filtering_div);$.each(this.filters,function(w,z){var v=$("<tr>").appendTo(t);var y=$("<th class='filter-info'>").appendTo(v);var u=$("<span class='name'>").appendTo(y);u.text(z.name+" ");var i=$("<span class='values'>").appendTo(y);var x=$("<td>").appendTo(v);z.control_element=$("<div id='"+z.name+"-filter-control' style='width: 200px; position: relative'>").appendTo(x);z.control_element.slider({range:true,min:Number.MAX_VALUE,max:-Number.MIN_VALUE,values:[0,0],slide:function(B,C){var A=C.values;i.text("["+A[0]+"-"+A[1]+"]");z.low=A[0];z.high=A[1];o.draw(true)},change:function(A,B){z.control_element.slider("option","slide").call(z.control_element,A,B)}});z.slider=z.control_element;z.slider_label=i});if(this.tool){this.dynamic_tool_div=$("<div/>").addClass("dynamic-tool").hide();this.header_div.after(this.dynamic_tool_div);this.dynamic_tool_div.bind("drag",function(i){i.stopPropagation()}).bind("click",function(i){i.stopPropagation()}).bind("dblclick",function(i){i.stopPropagation()});var l=$("<div class='tool-name'>").appendTo(this.dynamic_tool_div).text(this.tool.name);var e=this.tool.params;var o=this;$.each(this.tool.params,function(A,v){var y=$("<div>").addClass("param-row").appendTo(o.dynamic_tool_div);var x=$("<div>").addClass("slider-label").appendTo(y);var C=$("<span class='param-name'>").text(v.label+" ").appendTo(x);var w=$("<span/>").text(v.value);var z=$("<span class='param-value'>").appendTo(x).append("[").append(w).append("]");var B=$("<div/>").addClass("slider").appendTo(y);var i=$("<div id='"+v.name+"-param-control'>").appendTo(B);var u=(v.max<=1?0.01:(v.max<=1000?1:5));i.slider({min:v.min,max:v.max,step:u,value:v.value,slide:function(D,F){var E=F.value;v.value=E;if(0<E&&E<1){E=parseFloat(E).toFixed(2)}w.text(E)},change:function(D,E){v.value=E.value}});z.click(function(){var F=w,E=F.text(),D=(v.max<=1?4:v.max.length);F.text("");$("<input type='text'/>").attr("size",D).attr("maxlength",D).attr("value",E).appendTo(F).focus().select().click(function(G){G.stopPropagation()}).blur(function(){$(this).remove();F.text(E)}).keyup(function(I){if(I.keyCode===27){$(this).trigger("blur")}else{if(I.keyCode===13){var G=$(this),H=parseFloat(G.val());if(isNaN(H)||H>v.max||H<v.min){alert("Parameter value must be in the range ["+v.min+"-"+v.max+"]");return $(this)}F.text(H);i.slider("value",H);v.value=H}}})});$("<div style='clear: both;'/>").appendTo(y)});var b=$("<div>").addClass("param-row").appendTo(this.dynamic_tool_div);var n=$("<input type='submit'>").attr("value","Run").appendTo(b);var o=this;n.click(function(){o.run_tool()})}o.child_tracks_container=$("<div/>").addClass("child-tracks-container").hide();o.container_div.append(o.child_tracks_container);if(o.display_modes!==undefined){if(o.mode_div===undefined){o.mode_div=$("<div class='right-float menubutton popup' />").appendTo(o.header_div);var m=o.display_modes[0];o.mode=m;o.mode_div.text(m);var a=function(i){o.mode_div.text(i);o.mode=i;o.tile_cache.clear();o.draw()};var f={};for(var q=0,r=o.display_modes.length;q<r;q++){var k=o.display_modes[q];f[k]=function(i){return function(){a(i)}}(k)}make_popupmenu(o.mode_div,f)}else{o.mode_div.hide()}}var h={};h["Edit configuration"]=function(){var v=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},i=function(){o.track_config.update_from_form($(".dialog-box"));hide_modal();$(window).unbind("keypress.check_enter_esc")},u=function(w){if((w.keyCode||w.which)===27){v()}else{if((w.keyCode||w.which)===13){i()}}};$(window).bind("keypress.check_enter_esc",u);show_modal("Configure Track",o.track_config.build_form(),{Cancel:v,OK:i})};if(o.filters.length>0){h["Show filters"]=function(){var i;if(!o.filtering_div.is(":visible")){i="Hide filters";o.filters_visible=true}else{i="Show filters";o.filters_visible=false}o.filtering_div.toggle()}}if(o.tool){h["Toggle Tool"]=function(){var i;if(!o.dynamic_tool_div.is(":visible")){i="Hide dynamic tool";o.update_name(o.name+o.tool_region_and_parameters_str())}else{i="Show dynamic tool";o.revert_name()}o.dynamic_tool_div.toggle()}}var c=j;var p=function(){$("#no-tracks").show()};if(this.parent_track){c=this.parent_track;p=function(){}}h.Remove=function(){c.remove_track(o);if(c.num_tracks===0){p()}};o.popup_menu=make_popupmenu(o.name_div,h)};$.extend(TiledTrack.prototype,Track.prototype,{draw:function(b){var m=this.view.low,g=this.view.high,j=g-m,c=this.view.container.width(),f=this.view.resolution;var p=$("<div style='position: relative;'></div>"),r=c/j;this.content_div.append(p);this.max_height=0;var a=Math.floor(m/f/DENSITY);var l=0;while((a*DENSITY*f)<g){var n=c+"_"+r+"_"+a;var e=this.tile_cache.get(n);var k=a*DENSITY*this.view.resolution;var q=k+DENSITY*this.view.resolution;if(!b&&e){this.show_tile(e,p,k,r)}else{this.delayed_draw(b,n,k,q,a,f,p,r)}a+=1}var d=this;var o=setInterval(function(){if(l===0){var u=d.content_div.children();var t=false;for(var v=u.length-1,s=0;v>=s;v--){var x=$(u[v]);if(t){x.remove()}else{if(x.children().length!==0){t=true}}}for(var w=0;w<d.filters.length;w++){d.filters[w].update_ui_elt()}clearInterval(o)}},50);for(var h=0;h<this.child_tracks.length;h++){this.child_tracks[h].draw(b)}},delayed_draw:function(b,g,f,i,c,e,h,j){var d=this;var a=setTimeout(function(){if(f<=d.view.high&&i>=d.view.low){var k;if(!b){k=d.tile_cache.get(g)}if(!k){k=d.draw_tile(e,c,h,j);if(k){var l=$("<div class='track-tile'>").prepend(k);if(k.hasClass(FILTERABLE_CLASS)){l.addClass(FILTERABLE_CLASS)}k=l}}if(k){d.tile_cache.set(g,k);d.show_tile(k,h,f,j)}}},50)},show_tile:function(a,f,d,g){var b=this;var c=this.view.high-this.view.low,e=(d-this.view.low)*g;if(this.left_offset){e-=this.left_offset}a.css({position:"absolute",top:0,left:e,height:""});f.append(a);b.max_height=Math.max(b.max_height,a.height());b.content_div.css("height",b.max_height+"px");f.children().css("height",b.max_height+"px");if(b.hidden){return}if(a.hasClass(FILTERABLE_CLASS)){show_hide_popupmenu_options(b.popup_menu,"(Show|Hide) filters");if(b.filters_visible){b.filtering_div.show()}}else{show_hide_popupmenu_options(b.popup_menu,"(Show|Hide) filters",false);b.filtering_div.hide()}},set_overview:function(){var a=this.view;if(this.initial_canvas&&this.is_overview){a.overview_close.show();a.overview_viewport.append(this.initial_canvas);a.overview_highlight.show().height(this.initial_canvas.height());a.overview_viewport.height(this.initial_canvas.height()+a.overview_box.height())}$(window).trigger("resize")},run_tool:function(){var b={dataset_id:this.original_dataset_id,chrom:this.view.chrom,low:this.view.low,high:this.view.high,tool_id:this.tool.name};$.extend(b,this.tool.get_param_values_dict());var d=this,c=b.tool_id+d.tool_region_and_parameters_str(b.chrom,b.low,b.high),e;if(d.track_type=="FeatureTrack"){e=new ToolDataFeatureTrack(c,view,undefined,{},{},d)}this.add_track(e);e.content_div.text("Starting job.");view.has_changes=true;var a=function(){$.getJSON(run_tool_url,b,function(f){if(f=="no converter"){e.container_div.addClass("error");e.content_div.text(DATA_NOCONVERTER)}else{if(f.error){e.container_div.addClass("error");e.content_div.text(DATA_CANNOT_RUN_TOOL+f.message)}else{if(f=="pending"){e.container_div.addClass("pending");e.content_div.text("Converting input data so that it can be easily reused.");setTimeout(a,2000)}else{e.dataset_id=f.dataset_id;e.content_div.text("Running job.");e.init()}}}})};a()},tool_region_and_parameters_str:function(c,a,d){var b=this,e=(c!==undefined&&a!==undefined&&d!==undefined?c+":"+a+"-"+d:"all");return" - region=["+e+"], parameters=["+b.tool.get_param_values().join(", ")+"]"},add_track:function(a){a.track_id=this.track_id+"_"+this.child_tracks.length;a.container_div.attr("id","track_"+a.track_id);this.child_tracks_container.append(a.container_div);sortable(a.container_div,".child-track-icon");if(!$(this.child_tracks_container).is(":visible")){this.child_tracks_container.show()}this.child_tracks.push(a)},remove_track:function(a){a.container_div.fadeOut("slow",function(){$(this).remove()})}});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.view.container.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 ReferenceTrack=function(a){this.track_type="ReferenceTrack";this.hidden=true;Track.call(this,null,a,a.top_labeltrack);TiledTrack.call(this);this.left_offset=200;this.height_px=12;this.container_div.addClass("reference-track");this.content_div.css("background","none");this.content_div.css("min-height","0px");this.content_div.css("border","none");this.data_queue={};this.data_cache=new DataCache(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,i){console.log(h,g,i)}})}},draw_tile:function(f,b,k,o){var g=b*DENSITY*f,d=DENSITY*f,j=f+"_"+b;var e=document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(e)}e=$(e);var n=e.get(0).getContext("2d");if(o>CHAR_WIDTH_PX){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;for(var h=0,l=m.length;h<l;h++){var a=Math.round(h*o),i=Math.round(o/2);n.fillText(m[h],a+this.left_offset+i,10)}k.append(e);return e}this.content_div.css("height","0px")}});var LineTrack=function(e,c,f,a,d){var b=this;this.track_type="LineTrack";this.display_modes=["Histogram","Line","Filled","Intensity"];this.mode="Histogram";Track.call(this,e,c,c.viewport_container);TiledTrack.call(this);this.min_height_px=16;this.max_height_px=400;this.height_px=80;this.hda_ldda=f;this.dataset_id=a;this.original_dataset_id=a;this.data_cache=new DataCache(CACHED_DATA);this.tile_cache=new Cache(CACHED_TILES_LINE);this.track_config=new TrackConfig({track:this,params:[{key:"color",label:"Color",type:"color",default_value:"black"},{key:"min_value",label:"Min Value",type:"float",default_value:undefined},{key:"max_value",label:"Max Value",type:"float",default_value:undefined},{key:"mode",type:"string",default_value:this.mode,hidden:true},{key:"height",type:"int",default_value:this.height_px,hidden:true}],saved_values:d,onchange:function(){b.vertical_range=b.prefs.max_value-b.prefs.min_value;$("#linetrack_"+b.track_id+"_minval").text(b.prefs.min_value);$("#linetrack_"+b.track_id+"_maxval").text(b.prefs.max_value);b.tile_cache.clear();b.draw()}});this.prefs=this.track_config.values;this.height_px=this.track_config.values.height;this.vertical_range=this.track_config.values.max_value-this.track_config.values.min_value;(function(g){var j=false;var i=false;var h=$("<div class='track-resize'>");$(g.container_div).hover(function(){j=true;h.show()},function(){j=false;if(!i){h.hide()}});h.hide().bind("dragstart",function(k,l){i=true;l.original_height=$(g.content_div).height()}).bind("drag",function(l,m){var k=Math.min(Math.max(m.original_height+m.deltaY,g.min_height_px),g.max_height_px);$(g.content_div).css("height",k);g.height_px=k;g.draw(true)}).bind("dragend",function(k,l){g.tile_cache.clear();i=false;if(!j){h.hide()}g.track_config.values.height=g.height_px}).appendTo(g.container_div)})(this)};$.extend(LineTrack.prototype,TiledTrack.prototype,{predraw_init:function(){var a=this,b=a.view.tracks.indexOf(a);a.vertical_range=undefined;return $.getJSON(a.data_url,{stats:true,chrom:a.view.chrom,low:null,high:null,hda_ldda:a.hda_ldda,dataset_id:a.dataset_id},function(c){a.container_div.addClass("line-track");var e=c.data;if(isNaN(parseFloat(a.prefs.min_value))||isNaN(parseFloat(a.prefs.max_value))){a.prefs.min_value=e.min;a.prefs.max_value=e.max;$("#track_"+b+"_minval").val(a.prefs.min_value);$("#track_"+b+"_maxval").val(a.prefs.max_value)}a.vertical_range=a.prefs.max_value-a.prefs.min_value;a.total_frequency=e.total_frequency;a.container_div.find(".yaxislabel").remove();var f=$("<div />").addClass("yaxislabel").attr("id","linetrack_"+b+"_minval").text(round_1000(a.prefs.min_value));var d=$("<div />").addClass("yaxislabel").attr("id","linetrack_"+b+"_maxval").text(round_1000(a.prefs.max_value));d.css({position:"absolute",top:"24px",left:"10px"});d.prependTo(a.container_div);f.css({position:"absolute",bottom:"2px",left:"10px"});f.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:this.data_url,dataType:"json",data:{chrom:this.view.chrom,low:a,high:f,hda_ldda:this.hda_ldda,dataset_id:this.dataset_id,resolution:this.view.resolution},success:function(g){var h=g.data;c.data_cache.set(e,h);delete c.data_queue[e];c.draw()},error:function(h,g,i){console.log(h,g,i)}})}},draw_tile:function(o,r,c,e){if(this.vertical_range===undefined){return}var s=r*DENSITY*o,a=DENSITY*o,x=o+"_"+r;var b=document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(b)}b=$(b);if(this.data_cache.get(x)===undefined){this.get_data(o,r);return}var v=this.data_cache.get(x);if(!v){return}b.get(0).width=Math.ceil(a*e);b.get(0).height=this.height_px;var n=b.get(0).getContext("2d"),j=false,k=this.prefs.min_value,g=this.prefs.max_value,m=this.vertical_range,t=this.total_frequency,d=this.height_px,l=this.mode;var w=Math.round(d+k/m*d);n.beginPath();n.moveTo(0,w);n.lineTo(a*e,w);n.fillStyle="#aaa";n.stroke();n.beginPath();n.fillStyle=this.prefs.color;var u,h,f;if(v.length>1){f=Math.ceil((v[1][0]-v[0][0])*e)}else{f=10}for(var p=0,q=v.length;p<q;p++){u=Math.round((v[p][0]-s)*e);h=v[p][1];if(h===null){if(j&&l==="Filled"){n.lineTo(u,d)}j=false;continue}if(h<k){h=k}else{if(h>g){h=g}}if(l==="Histogram"){h=Math.round(h/m*d);n.fillRect(u,w,f,-h)}else{if(l==="Intensity"){h=255-Math.floor((h-k)/m*255);n.fillStyle="rgb("+h+","+h+","+h+")";n.fillRect(u,0,f,d)}else{h=Math.round(d-(h-k)/m*d);if(j){n.lineTo(u,h)}else{j=true;if(l==="Filled"){n.moveTo(u,d);n.lineTo(u,h)}else{n.moveTo(u,h)}}}}}if(l==="Filled"){if(j){n.lineTo(u,w);n.lineTo(0,w)}n.fill()}else{n.stroke()}return b}});var FeatureTrack=function(a,f,e,i,h,c,d,g){var b=this;this.track_type="FeatureTrack";this.display_modes=["Auto","Dense","Squish","Pack"];Track.call(this,a,f,f.viewport_container);TiledTrack.call(this,c,d,g);this.height_px=0;this.container_div.addClass("feature-track");this.hda_ldda=e;this.dataset_id=i;this.original_dataset_id=i;this.zo_slots={};this.show_labels_scale=0.001;this.showing_details=false;this.summary_draw_height=30;this.default_font=DEFAULT_FONT;this.inc_slots={};this.data_queue={};this.start_end_dct={};this.tile_cache=new Cache(CACHED_TILES_FEATURE);this.data_cache=new DataCache(20);this.left_offset=200;this.track_config=new TrackConfig({track:this,params:[{key:"block_color",label:"Block color",type:"color",default_value:"#444"},{key:"label_color",label:"Label color",type:"color",default_value:"black"},{key:"show_counts",label:"Show summary counts",type:"bool",default_value:true}],saved_values:h,onchange:function(){b.tile_cache.clear();b.draw()}});this.prefs=this.track_config.values};$.extend(FeatureTrack.prototype,TiledTrack.prototype,{get_data:function(a,d){var b=this,c=a+"_"+d;if(!b.data_queue[c]){b.data_queue[c]=true;$.getJSON(b.data_url,{chrom:b.view.chrom,low:a,high:d,hda_ldda:b.hda_ldda,dataset_id:b.dataset_id,resolution:this.view.resolution,mode:this.mode},function(e){b.data_cache.set_data(a,d,b.mode,e);delete b.data_queue[c];b.draw()})}},incremental_slots:function(a,j,d,q){var r=this.inc_slots[a];if(!r||(r.mode!==q)){r={};r.w_scale=a;r.mode=q;this.inc_slots[a]=r;this.start_end_dct[a]={}}var m=r.w_scale,x=[],y=[],k=0,o=this.view.max_low;for(var v=0,w=j.length;v<w;v++){var h=j[v],l=h[0];if(r[l]!==undefined){k=Math.max(k,r[l]);y.push(r[l])}else{x.push(v)}}var e=this.start_end_dct[a];var n=function(D,E){for(var C=0;C<=MAX_FEATURE_DEPTH;C++){var A=false,F=e[C];if(F!==undefined){for(var z=0,B=F.length;z<B;z++){var i=F[z];if(E>i[0]&&D<i[1]){A=true;break}}}if(!A){return C}}return -1};for(var v=0,w=x.length;v<w;v++){var h=j[x[v]],l=h[0],t=h[1],b=h[2],p=h[3],c=Math.floor((t-o)*m),g=Math.ceil((b-o)*m),u=CONTEXT.measureText(p).width,f;if(p!==undefined&&!d){u+=(LABEL_SPACING+PACK_SPACING);if(c-u>=0){c-=u;f="left"}else{g+=u;f="right"}}var s=n(c,g);if(s>=0){if(e[s]===undefined){e[s]=[]}e[s].push([c,g]);r[l]=s;k=Math.max(k,s)}else{}}return k},rect_or_text:function(v,n,z,d,u,l,h,g){v.textAlign="center";var b=[z,d],q=0,w=0,t=Math.round(n/2);var E=[];for(var o=0,y=l.length;o<y;o++){var m=l[o],e="MIDNSHP=X"[m[0]],p=m[1];if(e==="H"||e==="S"){q-=p}var j=u+q,D=Math.floor(Math.max(0,(j-z)*n)),k=Math.floor(Math.max(0,(j+p-z)*n));switch(e){case"H":break;case"S":case"M":case"=":var r=compute_overlap([j,j+p],b);if(r!=NO_OVERLAP){var s=h.slice(w,w+p);if((this.mode==="Pack"||this.mode==="Auto")&&h!==undefined&&n>CHAR_WIDTH_PX){v.fillStyle=this.prefs.block_color;v.fillRect(D+this.left_offset,g+1,k-D,9);v.fillStyle=CONNECTOR_COLOR;for(var B=0,a=s.length;B<a;B++){if(j+B>=z&&j+B<=d){var C=Math.floor(Math.max(0,(j+B-z)*n));v.fillText(s[B],C+this.left_offset+t,g+9)}}}else{v.fillStyle=this.prefs.block_color;v.fillRect(D+this.left_offset,g+(this.mode!="Dense"?4:5),k-D,(this.mode!="Dense"?SQUISH_FEATURE_HEIGHT:DENSE_FEATURE_HEIGHT))}}w+=p;q+=p;break;case"N":v.fillStyle=CONNECTOR_COLOR;v.fillRect(D+this.left_offset,g+5,k-D,1);q+=p;break;case"D":v.fillStyle="red";v.fillRect(D+this.left_offset,g+4,k-D,3);q+=p;break;case"P":break;case"I":var r=compute_overlap([j,j+p],b);if(r!=NO_OVERLAP){var s=h.slice(w,w+p);var f=this.left_offset+D-(k-D)/2;if((this.mode==="Pack"||this.mode==="Auto")&&h!==undefined&&n>CHAR_WIDTH_PX){v.fillStyle="yellow";v.fillRect(f,g-9,k-D,9);E[E.length]=[f+(k-D)/2,g+4,5];v.fillStyle=CONNECTOR_COLOR;switch(r){case (OVERLAP_START):s=s.slice(z-j);break;case (OVERLAP_END):s=s.slice(0,j-d);break;case (CONTAINED_BY):break;case (CONTAINS):s=s.slice(z-j,j-d);break}for(var B=0,a=s.length;B<a;B++){var C=Math.floor(Math.max(0,(j+B-z)*n));v.fillText(s[B],C+this.left_offset+t-(k-D)/2,g)}}else{v.fillStyle="yellow";v.fillRect(f,g+(this.mode!="Dense"?2:5),k-D,(this.mode!="Dense"?SQUISH_FEATURE_HEIGHT:DENSE_FEATURE_HEIGHT))}}w+=p;break;case"X":w+=p;break}}var A;for(var x=0;x<E.length;x++){A=E[x];v.fillStyle="yellow";v.drawDownwardEquilateralTriangle(A[0],A[1],A[2])}},draw_tile:function(ae,m,q,au){var K=m*DENSITY*ae,aj=(m+1)*DENSITY*ae,J=aj-K;var G=this.data_cache.get_data(K,aj,this.mode);if(G===undefined||G==="pending"||(this.mode!=="Auto"&&G.dataset_type==="summary_tree")){this.data_queue[[K,aj]]=true;this.get_data(K,aj);return}var a=Math.ceil(J*au),ag=this.prefs.label_color,g=this.prefs.block_color,p=this.mode,u=25,aa,V=this.left_offset,at,B,av;var o=document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(o)}o=$(o);if(G.dataset_type==="summary_tree"){B=this.summary_draw_height}else{if(p==="Dense"){B=u;av=DENSE_TRACK_HEIGHT}else{if(p==="Squish"){av=SQUISH_TRACK_HEIGHT;aa=true}else{if(p==="Pack"){av=PACK_TRACK_HEIGHT;aa=false}else{if(G.extra_info==="no_detail"){av=(G.track_type==="bai"?SQUISH_TRACK_HEIGHT:NO_DETAIL_TRACK_HEIGHT);aa=true}else{av=PACK_TRACK_HEIGHT;aa=false}}}B=this.incremental_slots(au,G.data,aa,p)*av+u;at=this.inc_slots[au]}}o.get(0).width=a+V;o.get(0).height=B;if(G.dataset_type=="summary_tree"){o.get(0).height+=LABEL_SPACING+CHAR_HEIGHT_PX}q.parent().css("height",Math.max(this.height_px,B)+"px");var H=o.get(0).getContext("2d");H.fillStyle=g;H.font=this.default_font;H.textAlign="right";this.container_div.find(".yaxislabel").remove();if(G.dataset_type=="summary_tree"){var v=B+LABEL_SPACING+CHAR_HEIGHT_PX;points=G.data,max=G.max,delta_x_px=Math.ceil(G.delta*au);var n=$("<div />").addClass("yaxislabel");n.text(max);n.css({position:"absolute",top:"22px",left:"10px"});n.prependTo(this.container_div);for(var an=0,F=points.length;an<F;an++){var Z=Math.floor((points[an][0]-K)*au);var Y=points[an][1];if(!Y){continue}var ak=Y/max*B;H.fillStyle="black";H.fillRect(Z+V,v-ak,delta_x_px,ak);var X=4;if(this.prefs.show_counts&&(H.measureText(Y).width+X)<delta_x_px){H.fillStyle="#666";H.textAlign="center";H.fillText(Y,Z+V+(delta_x_px/2),10)}}return o}if(G.message){o.css({"border-color":"red"});H.fillStyle="red";H.textAlign="left";H.fillText(G.message,100+V,av);if(!G.data){return o}}for(var aq=0;aq<this.filters.length;aq++){if(G.data.length&&this.filters[aq].applies_to(G.data[0])){o.addClass(FILTERABLE_CLASS);break}}var ar=G.data;var am=0;for(var an=0,F=ar.length;an<F;an++){var R=ar[an],O=R[0],ap=R[1],ac=R[2],L=R[3];if(this.mode!="Dense"&&at[O]===undefined){continue}var ab=false;var T;for(var aq=0;aq<this.filters.length;aq++){T=this.filters[aq];T.update_attrs(R);if(!T.keep(R)){ab=true;break}}if(ab){continue}if(ap<=aj&&ac>=K){if(G.dataset_type=="interval_index"){ac-=1}var ad=Math.floor(Math.max(0,(ap-K)*au)),I=Math.ceil(Math.min(a,Math.max(0,(ac-K)*au))),W=(p==="Dense"?1:(1+at[O]))*av;var E,ah,M=null,aw=null;if(G.dataset_type==="bai"){H.fillStyle=g;if(R[5] instanceof Array){var C=Math.floor(Math.max(0,(R[4][0]-K)*au)),N=Math.ceil(Math.min(a,Math.max(0,(R[4][1]-K)*au))),A=Math.floor(Math.max(0,(R[5][0]-K)*au)),t=Math.ceil(Math.min(a,Math.max(0,(R[5][1]-K)*au)));if(R[4][1]>=K&&R[4][0]<=aj&&R[4][2]){this.rect_or_text(H,au,K,aj,R[4][0],R[4][2],R[4][3],W)}if(R[5][1]>=K&&R[5][0]<=aj&&R[5][2]){this.rect_or_text(H,au,K,aj,R[5][0],R[5][2],R[5][3],W)}if(A>N){H.fillStyle=CONNECTOR_COLOR;H.dashedLine(N+V,W+5,V+A,W+5)}}else{H.fillStyle=g;this.rect_or_text(H,au,K,aj,ap,R[4],R[5],W)}if(p!=="Dense"&&!aa&&ap>K){H.fillStyle=this.prefs.label_color;if(m===0&&ad-H.measureText(L).width<0){H.textAlign="left";H.fillText(L,I+V+LABEL_SPACING,W+8)}else{H.textAlign="right";H.fillText(L,ad+V-LABEL_SPACING,W+8)}H.fillStyle=g}}else{if(G.dataset_type==="interval_index"){if(p=="Auto"){if(R.length<=4){p="Squish"}else{p="Pack"}}if(p=="Dense"){H.fillStyle=g;H.fillRect(ad+V,W+5,I-ad,DENSE_FEATURE_HEIGHT)}else{if(R.length<=4){H.fillStyle=g;H.fillRect(ad+V,W+5,I-ad,DENSE_FEATURE_HEIGHT)}else{var D=R[5],U=R[6],af=R[7],e=R[8];if(U&&af){M=Math.floor(Math.max(0,(U-K)*au));aw=Math.ceil(Math.min(a,Math.max(0,(af-K)*au)))}var ao,P;if(p=="Squish"){ao=1;P=SQUISH_FEATURE_HEIGHT}else{ao=5;P=PACK_FEATURE_HEIGHT}if(!e){if(R.strand){if(R.strand=="+"){H.fillStyle=RIGHT_STRAND_INV}else{if(R.strand=="-"){H.fillStyle=LEFT_STRAND_INV}}}else{H.fillStyle=CONNECTOR_COLOR}H.fillRect(ad+V,W+(P-ao)/2+1,I-ad,P)}else{var z,Q;if(p=="Squish"){H.fillStyle=CONNECTOR_COLOR;z=W+Math.floor(SQUISH_FEATURE_HEIGHT/2)+1;Q=1}else{if(D){var z=W;var Q=P;if(D=="+"){H.fillStyle=RIGHT_STRAND}else{if(D=="-"){H.fillStyle=LEFT_STRAND}}}else{H.fillStyle=CONNECTOR_COLOR;z+=(SQUISH_FEATURE_HEIGHT/2)+1;Q=1}}H.fillRect(ad+V,z,I-ad,Q);for(var al=0,d=e.length;al<d;al++){var s=e[al],c=Math.floor(Math.max(0,(s[0]-K)*au)),S=Math.ceil(Math.min(a,Math.max((s[1]-K)*au)));if(c>S){continue}H.fillStyle=g;H.fillRect(c+V,W+(P-ao)/2+1,S-c,ao);if(M!==undefined&&!(c>aw||S<M)){var ai=Math.max(c,M),w=Math.min(S,aw-1);H.fillRect(ai+V,W+1,w-ai,P)}}}if(p=="Pack"&&ap>K){H.fillStyle=ag;if(m===0&&ad-H.measureText(L).width<0){H.textAlign="left";H.fillText(L,I+V+LABEL_SPACING,W+8)}else{H.textAlign="right";H.fillText(L,ad+V-LABEL_SPACING,W+8)}H.fillStyle=g}}}}else{if(G.dataset_type==="vcf"){if(aa){H.fillStyle=g;H.fillRect(ad+V,W+5,I-ad,1)}else{var r=R[4],l=R[5],b=R[6];E=9;ah=1;H.fillRect(ad+V,W,I-ad,E);if(p!=="Dense"&&L!==undefined&&ap>K){H.fillStyle=ag;if(m===0&&ad-H.measureText(L).width<0){H.textAlign="left";H.fillText(L,I+2+V,W+8)}else{H.textAlign="right";H.fillText(L,ad-2+V,W+8)}H.fillStyle=g}var h=r+" / "+l;if(ap>K&&H.measureText(h).width<(I-ad)){H.fillStyle="white";H.textAlign="center";H.fillText(h,V+ad+(I-ad)/2,W+8);H.fillStyle=g}}}}}am++}}return o}});var ReadTrack=function(d,b,f,a,c,e){FeatureTrack.call(this,d,b,f,a,c,e);this.track_type="ReadTrack"};$.extend(ReadTrack.prototype,TiledTrack.prototype,FeatureTrack.prototype,{});var ToolDataFeatureTrack=function(e,c,g,a,d,f,b){FeatureTrack.call(this,e,c,g,a,d,f,{},b);this.track_type="ToolDataFeatureTrack";this.data_url=raw_data_url;this.data_query_wait=1000;this.dataset_check_url=dataset_state_url};$.extend(ToolDataFeatureTrack.prototype,TiledTrack.prototype,FeatureTrack.prototype,{predraw_init:function(){var b=this;var a=function(){if(b.data_cache.size()==0){setTimeout(a,300)}else{b.data_url=default_data_url;b.data_query_wait=DEFAULT_DATA_QUERY_WAIT;b.dataset_state_url=converted_datasets_state_url;$.getJSON(b.dataset_state_url,{dataset_id:b.dataset_id},function(c){})}};a()}});
\ No newline at end of file
+CanvasRenderingContext2D.prototype.dashedLine=function(c,j,b,h,f){if(f==undefined){f=4}var e=b-c;var d=h-j;var g=Math.floor(Math.sqrt(e*e+d*d)/f);var l=e/g;var k=d/g;for(var a=0;a<g;a++,c+=l,j+=k){if(a%2!=0){continue}this.fillRect(c,j,f,1)}};CanvasRenderingContext2D.prototype.drawDownwardEquilateralTriangle=function(b,a,e){var d=b-e/2,c=b+e/2,f=a-Math.sqrt(e*3/2);this.beginPath();this.moveTo(d,f);this.lineTo(c,f);this.lineTo(b,a);this.lineTo(d,f);this.strokeStyle=this.fillStyle;this.fill();this.stroke();this.closePath()};function sortable(a,b){a.bind("drag",{handle:b,relative:true},function(h,j){var g=$(this).parent();var f=g.children();for(var c=0;c<f.length;c++){if(j.offsetY<$(f.get(c)).position().top){break}}if(c==f.length){if(this!=f.get(c-1)){g.append(this)}}else{if(this!=f.get(c)){$(this).insertBefore(f.get(c))}}})}var NO_OVERLAP=1001,CONTAINS=1002,OVERLAP_START=1003,OVERLAP_END=1004,CONTAINED_BY=1005;function compute_overlap(e,b){var g=e[0],f=e[1],d=b[0],c=b[1],a;if(g<d){if(f<d){a=NO_OVERLAP}else{if(f<=c){a=OVERLAP_START}else{a=CONTAINS}}}else{if(g>c){a=NO_OVERLAP}else{if(f<=c){a=CONTAINED_BY}else{a=OVERLAP_END}}}return a}function is_overlap(b,a){return(compute_overlap(b,a)!=NO_OVERLAP)}var DENSE_TRACK_HEIGHT=10,NO_DETAIL_TRACK_HEIGHT=3,SQUISH_TRACK_HEIGHT=5,PACK_TRACK_HEIGHT=10,NO_DETAIL_FEATURE_HEIGHT=DENSE_FEATURE_HEIGHT=1,SQUISH_FEATURE_HEIGHT=3,PACK_FEATURE_HEIGHT=9,LABEL_SPACING=2,PACK_SPACING=5,MIN_SQUISH_VIEW_WIDTH=12000,DEFAULT_FONT="9px Monaco, Lucida Console, monospace",DENSITY=200,FEATURE_LEVELS=10,MAX_FEATURE_DEPTH=100,DEFAULT_DATA_QUERY_WAIT=5000,MAX_CHROMS_SELECTABLE=100,CONNECTOR_COLOR="#ccc",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_CANNOT_RUN_TOOL="Tool cannot be rerun: ",DATA_LOADING="Loading data...",DATA_OK="Ready for display",FILTERABLE_CLASS="filterable",CACHED_TILES_FEATURE=10,CACHED_TILES_LINE=5,CACHED_DATA=5,DUMMY_CANVAS=document.createElement("canvas"),RIGHT_STRAND,LEFT_STRAND;if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(DUMMY_CANVAS)}var CONTEXT=DUMMY_CANVAS.getContext("2d");CONTEXT.font=DEFAULT_FONT;var CHAR_WIDTH_PX=CONTEXT.measureText("A").width,CHAR_HEIGHT_PX=9;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.move_key_to_end(b,a)}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},move_key_to_end:function(b,a){this.key_ary.splice(a,1);this.key_ary.push(b)},clear:function(){this.obj_cache={};this.key_ary=[]},size:function(){return this.key_ary.length}});var DataCache=function(a){Cache.call(this,a)};$.extend(DataCache.prototype,Cache.prototype,{get_data:function(g,b,e){var h=this.get(this.gen_key(g,b,e));if(h){return h}var j,f,a,d,e,h;for(var c=0;c<this.key_ary.length;c++){j=this.key_ary[c];f=this.split_key(j);a=f[0];d=f[1];if(g>=a&&b<=d){h=this.obj_cache[j];if(h.dataset_type!=="summary_tree"&&h.extra_info!=="no_detail"){this.move_key_to_end(j,c);return h}}}return undefined},set_data:function(b,c,d,a){return this.set(this.gen_key(b,c,d),a)},gen_key:function(a,c,d){var b=a+"_"+c+"_"+d;return b},split_key:function(a){return a.split("_")}});var View=function(a,d,c,b,e){this.container=a;this.chrom=null;this.vis_id=c;this.dbkey=b;this.title=d;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(e);this.reset()};$.extend(View.prototype,{init:function(d){var c=this.container,a=this;this.top_container=$("<div/>").addClass("top-container").appendTo(c);this.content_div=$("<div/>").addClass("content").css("position","relative").appendTo(c);this.bottom_container=$("<div/>").addClass("bottom-container").appendTo(c);this.top_labeltrack=$("<div/>").addClass("top-labeltrack").appendTo(this.top_container);this.viewport_container=$("<div/>").addClass("viewport-container").addClass("viewport-container").appendTo(this.content_div);this.intro_div=$("<div/>").addClass("intro").text("Select a chrom from the dropdown below").hide();this.nav_labeltrack=$("<div/>").addClass("nav-labeltrack").appendTo(this.bottom_container);this.nav_container=$("<div/>").addClass("nav-container").prependTo(this.top_container);this.nav=$("<div/>").addClass("nav").appendTo(this.nav_container);this.overview=$("<div/>").addClass("overview").appendTo(this.bottom_container);this.overview_viewport=$("<div/>").addClass("overview-viewport").appendTo(this.overview);this.overview_close=$("<a href='javascript:void(0);'>Close Overview</a>").addClass("overview-close").hide().appendTo(this.overview_viewport);this.overview_highlight=$("<div/>").addClass("overview-highlight").hide().appendTo(this.overview_viewport);this.overview_box_background=$("<div/>").addClass("overview-boxback").appendTo(this.overview_viewport);this.overview_box=$("<div/>").addClass("overview-box").appendTo(this.overview_viewport);this.default_overview_height=this.overview_box.height();this.nav_controls=$("<div/>").addClass("nav-controls").appendTo(this.nav);this.chrom_form=$("<form/>").attr("action",function(){}).appendTo(this.nav_controls);this.chrom_select=$("<select/>").attr({name:"chrom"}).css("width","15em").addClass("no-autocomplete").append("<option value=''>Loading</option>").appendTo(this.chrom_form);var b=function(f){if(f.type==="focusout"||(f.keyCode||f.which)===13||(f.keyCode||f.which)===27){if((f.keyCode||f.which)!==27){a.go_to($(this).val())}$(this).hide();a.location_span.show();a.chrom_select.show();return false}};this.nav_input=$("<input/>").addClass("nav-input").hide().bind("keypress focusout",b).appendTo(this.chrom_form);this.location_span=$("<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=$("<input/>").attr("type","hidden").val(this.vis_id).appendTo(this.chrom_form)}this.zo_link=$("<a id='zoom-out' />").click(function(){a.zoom_out();a.redraw()}).appendTo(this.chrom_form);this.zi_link=$("<a id='zoom-in' />").click(function(){a.zoom_in();a.redraw()}).appendTo(this.chrom_form);this.load_chroms({low:0},d);this.chrom_select.bind("change",function(){a.change_chrom(a.chrom_select.val())});this.intro_div.show();this.content_div.bind("click",function(f){$(this).find("input").trigger("blur")});this.content_div.bind("dblclick",function(f){a.zoom_in(f.pageX,this.viewport_container)});this.overview_box.bind("dragstart",function(f,g){this.current_x=g.offsetX}).bind("drag",function(f,h){var j=h.offsetX-this.current_x;this.current_x=h.offsetX;var g=Math.round(j/a.viewport_container.width()*(a.max_high-a.max_low));a.move_delta(-g)});this.overview_close.bind("click",function(){for(var f=0,e=a.tracks.length;f<e;f++){a.tracks[f].is_overview=false}$(this).siblings().filter("canvas").remove();$(this).parent().css("height",a.overview_box.height());a.overview_highlight.hide();$(this).hide()});this.viewport_container.bind("draginit",function(f,g){if(f.clientX>a.viewport_container.width()-16){return false}}).bind("dragstart",function(f,g){g.original_low=a.low;g.current_height=f.clientY;g.current_x=g.offsetX}).bind("drag",function(h,k){var f=$(this);var l=k.offsetX-k.current_x;var g=f.scrollTop()-(h.clientY-k.current_height);f.scrollTop(g);k.current_height=h.clientY;k.current_x=k.offsetX;var j=Math.round(l/a.viewport_container.width()*(a.high-a.low));a.move_delta(j)}).bind("mousewheel",function(h,k,g,f){if(g){var j=Math.round(-g/a.viewport_container.width()*(a.high-a.low));a.move_delta(j)}});this.top_labeltrack.bind("dragstart",function(f,g){return $("<div />").css({height:a.content_div.height()+a.top_labeltrack.height()+a.nav_labeltrack.height()+1,top:"0px",position:"absolute","background-color":"#ccf",opacity:0.5,"z-index":1000}).appendTo($(this))}).bind("drag",function(k,l){$(l.proxy).css({left:Math.min(k.pageX,l.startX),width:Math.abs(k.pageX-l.startX)});var g=Math.min(k.pageX,l.startX)-a.container.offset().left,f=Math.max(k.pageX,l.startX)-a.container.offset().left,j=(a.high-a.low),h=a.viewport_container.width();a.update_location(Math.round(g/h*j)+a.low,Math.round(f/h*j)+a.low)}).bind("dragend",function(l,m){var g=Math.min(l.pageX,m.startX),f=Math.max(l.pageX,m.startX),j=(a.high-a.low),h=a.viewport_container.width(),k=a.low;a.low=Math.round(g/h*j)+k;a.high=Math.round(f/h*j)+k;$(m.proxy).remove();a.redraw()});this.add_label_track(new LabelTrack(this,this.top_labeltrack));this.add_label_track(new LabelTrack(this,this.nav_labeltrack));$(window).bind("resize",function(){a.resize_window()});$(document).bind("redraw",function(){a.redraw()});this.reset();$(window).trigger("resize")},update_location:function(a,b){this.location_span.text(commatize(a)+" - "+commatize(b));this.nav_input.val(this.chrom+":"+commatize(a)+"-"+commatize(b))},load_chroms:function(b,c){b.num=MAX_CHROMS_SELECTABLE;$.extend(b,(this.vis_id!==undefined?{vis_id:this.vis_id}:{dbkey:this.dbkey}));var a=this;$.ajax({url:chrom_url,data:b,dataType:"json",success:function(e){if(e.reference){a.add_label_track(new ReferenceTrack(a))}a.chrom_data=e.chrom_info;var h='<option value="">Select Chrom/Contig</option>';for(var g=0,d=a.chrom_data.length;g<d;g++){var f=a.chrom_data[g].chrom;h+='<option value="'+f+'">'+f+"</option>"}if(e.prev_chroms){h+='<option value="previous">Previous '+MAX_CHROMS_SELECTABLE+"</option>"}if(e.next_chroms){h+='<option value="next">Next '+MAX_CHROMS_SELECTABLE+"</option>"}a.chrom_select.html(h);if(c){c()}a.chrom_start_index=e.start_index},error:function(){alert("Could not load chroms for this dbkey:",a.dbkey)}})},change_chrom:function(e,b,g){if(!e||e==="None"){return}var d=this;if(e=="previous"){d.load_chroms({low:this.chrom_start_index-MAX_CHROMS_SELECTABLE});return}if(e=="next"){d.load_chroms({low:this.chrom_start_index+MAX_CHROMS_SELECTABLE});return}var f=$.grep(d.chrom_data,function(j,k){return j.chrom===e})[0];if(f===undefined){d.load_chroms({chrom:e},function(){d.change_chrom(e,b,g)});return}else{if(e!==d.chrom){d.chrom=e;if(!d.chrom){d.intro_div.show()}else{d.intro_div.hide()}d.chrom_select.val(d.chrom);d.max_high=f.len-1;d.reset();d.redraw(true);for(var h=0,a=d.tracks.length;h<a;h++){var c=d.tracks[h];if(c.init){c.init()}}}if(b!==undefined&&g!==undefined){d.low=Math.max(b,0);d.high=Math.min(g,d.max_high)}d.reset_overview();d.redraw()}},go_to:function(f){var k=this,a,d,b=f.split(":"),h=b[0],j=b[1];if(j!==undefined){try{var g=j.split("-");a=parseInt(g[0].replace(/,/g,""),10);d=parseInt(g[1].replace(/,/g,""),10)}catch(c){return false}}k.change_chrom(h,a,d)},move_fraction:function(c){var a=this;var b=a.high-a.low;this.move_delta(c*b)},move_delta:function(c){var a=this;var b=a.high-a.low;if(a.low-c<a.max_low){a.low=a.max_low;a.high=a.max_low+b}else{if(a.high-c>a.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);sortable(a.container_div,".draghandle");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 g=this.high-this.low,f=this.low,b=this.high;if(f<this.max_low){f=this.max_low}if(b>this.max_high){b=this.max_high}if(this.high!==0&&g<this.min_separation){b=f+this.min_separation}this.low=Math.floor(f);this.high=Math.ceil(b);this.resolution=Math.pow(10,Math.ceil(Math.log((this.high-this.low)/200)/Math.LN10));this.zoom_res=Math.pow(FEATURE_LEVELS,Math.max(0,Math.ceil(Math.log(this.resolution,FEATURE_LEVELS)/Math.log(FEATURE_LEVELS))));var a=(this.low/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var e=((this.high-this.low)/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var j=13;this.overview_box.css({left:a,width:Math.max(j,e)}).show();if(e<j){this.overview_box.css("left",a-(j-e)/2)}if(this.overview_highlight){this.overview_highlight.css({left:a,width:e})}this.update_location(this.low,this.high);if(!h){for(var c=0,d=this.tracks.length;c<d;c++){if(this.tracks[c]&&this.tracks[c].enabled){this.tracks[c].draw()}}for(c=0,d=this.label_tracks.length;c<d;c++){this.label_tracks[c].draw()}}},zoom_in:function(b,c){if(this.max_high===0||this.high-this.low<this.min_separation){return}var d=this.high-this.low,e=d/2+this.low,a=(d/this.zoom_factor)/2;if(b){e=b/this.viewport_container.width()*(this.high-this.low)+this.low}this.low=Math.round(e-a);this.high=Math.round(e+a);this.redraw()},zoom_out:function(){if(this.max_high===0){return}var b=this.high-this.low,c=b/2+this.low,a=(b*this.zoom_factor)/2;this.low=Math.round(c-a);this.high=Math.round(c+a);this.redraw()},resize_window:function(){this.viewport_container.height(this.container.height()-this.top_container.height()-this.bottom_container.height());this.nav_container.width(this.container.width());this.redraw()},reset_overview:function(){this.overview_viewport.find("canvas").remove();this.overview_viewport.height(this.default_overview_height);this.overview_box.height(this.default_overview_height);this.overview_close.hide();this.overview_highlight.hide()}});var Tool=function(a,b){this.name=a;this.params=b};$.extend(Tool.prototype,{get_param_values_dict:function(){var b={};for(var a=0;a<this.params.length;a++){var c=this.params[a];b[c.name]=c.value}return b},get_param_values:function(){var b=[];for(var a=0;a<this.params.length;a++){b[a]=this.params[a].value}return b}});var NumberToolParameter=function(c,b,e,a,d){this.name=c;this.label=b;this.min=e;this.max=a;this.value=d};var get_tool_from_dict=function(f){if(obj_length(f)==0){return undefined}var b=f.name;var l=f.params;var c=Array();for(var e=0;e<l.length;e++){var g=l[e];var a=g.name,k=g.label,h=g.type,d=g.min,j=g.max,m=g.value;c[c.length]=new NumberToolParameter(a,k,d,j,m)}return new Tool(b,c)};var Filter=function(b,a,c){this.name=b;this.index=a;this.value=c};var NumberFilter=function(b,a){this.name=b;this.index=a;this.low=-Number.MAX_VALUE;this.high=Number.MAX_VALUE;this.slider_min=Number.MAX_VALUE;this.slider_max=-Number.MAX_VALUE;this.slider=null;this.slider_label=null};$.extend(NumberFilter.prototype,{applies_to:function(a){if(a.length>this.index){return true}return false},keep:function(a){if(!this.applies_to(a)){return true}return(a[this.index]>=this.low&&a[this.index]<=this.high)},update_attrs:function(b){var a=false;if(!this.applies_to(b)){return a}if(b[this.index]<this.slider_min){this.slider_min=b[this.index];a=true}if(b[this.index]>this.slider_max){this.slider_max=b[this.index];a=false}return a},update_ui_elt:function(){var b=this.slider.slider("option","min"),a=this.slider.slider("option","max");if(this.slider_min<b||this.slider_max>a){this.slider.slider("option","min",this.slider_min);this.slider.slider("option","max",this.slider_max);this.slider.slider("option","values",[this.slider_min,this.slider_max])}}});var get_filters_from_dict=function(a){var g=[];for(var d=0;d<a.length;d++){var f=a[d];var c=f.name,e=f.type,b=f.index;if(e=="int"||e=="float"){g[d]=new NumberFilter(c,b)}else{g[d]=new Filter(c,b,e)}}return g};var TrackConfig=function(a){this.track=a.track;this.params=a.params;this.values={};if(a.saved_values){this.restore_values(a.saved_values)}this.onchange=a.onchange};$.extend(TrackConfig.prototype,{restore_values:function(a){var b=this;$.each(this.params,function(c,d){if(a[d.key]!==undefined){b.values[d.key]=a[d.key]}else{b.values[d.key]=d.default_value}})},build_form:function(){var b=this;var a=$("<div />");$.each(this.params,function(f,d){if(!d.hidden){var c="param_"+f;var l=$("<div class='form-row' />").appendTo(a);l.append($("<label />").attr("for",c).text(d.label+":"));if(d.type=="bool"){l.append($('<input type="checkbox" />').attr("id",c).attr("name",c).attr("checked",b.values[d.key]))}else{if(d.type=="color"){var h=b.values[d.key];var g=$("<input />").attr("id",c).attr("name",c).val(h);var j=$("<div class='tipsy tipsy-north' style='position: absolute;' />").hide();var e=$("<div style='background-color: black; padding: 10px;'></div>").appendTo(j);var k=$("<div/>").appendTo(e).farbtastic({width:100,height:100,callback:g,color:h});$("<div />").append(g).append(j).appendTo(l).bind("click",function(m){j.css({left:$(this).position().left+($(g).width()/2)-60,top:$(this).position().top+$(this.height)}).show();$(document).bind("click.color-picker",function(){j.hide();$(document).unbind("click.color-picker")});m.stopPropagation()})}else{l.append($("<input />").attr("id",c).attr("name",c).val(b.values[d.key]))}}}});return a},update_from_form:function(a){var c=this;var b=false;$.each(this.params,function(d,f){if(!f.hidden){var g="param_"+d;var e=a.find("#"+g).val();if(f.type=="float"){e=parseFloat(e)}else{if(f.type=="int"){e=parseInt(e)}else{if(f.type=="bool"){e=a.find("#"+g).is(":checked")}}}if(e!==c.values[f.key]){c.values[f.key]=e;b=true}}});if(b){this.onchange()}}});var Track=function(b,a,e,c,d){this.name=b;this.view=a;this.parent_element=e;this.data_url=(c?c:default_data_url);this.data_query_wait=(d?d:DEFAULT_DATA_QUERY_WAIT);this.dataset_check_url=converted_datasets_state_url;this.container_div=$("<div />").addClass("track").css("position","relative");if(!this.hidden){this.header_div=$("<div class='track-header' />").appendTo(this.container_div);if(this.view.editor){this.drag_div=$("<div class='draghandle' />").appendTo(this.header_div)}this.name_div=$("<div class='menubutton popup' />").appendTo(this.header_div);this.name_div.text(this.name);this.name_div.attr("id",this.name.replace(/\s+/g,"-").replace(/[^a-zA-Z0-9\-]/g,"").toLowerCase())}this.content_div=$("<div class='track-content'>").appendTo(this.container_div);this.parent_element.append(this.container_div)};$.extend(Track.prototype,{init:function(){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");a.container_div.removeClass("nodata error pending");if(!a.dataset_id){return}if(a.view.chrom!=null){$.getJSON(converted_datasets_state_url,{hda_ldda:a.hda_ldda,dataset_id:a.dataset_id,chrom:a.view.chrom},function(b){if(!b||b==="error"||b.kind==="error"){a.container_div.addClass("error");a.content_div.text(DATA_ERROR);if(b.message){var d=a.view.tracks.indexOf(a);var c=$(" <a href='javascript:void(0);'></a>").text("View error").bind("click",function(){show_modal("Trackster Error","<pre>"+b.message+"</pre>",{Close:hide_modal})});a.content_div.append(c)}}else{if(b==="no converter"){a.container_div.addClass("error");a.content_div.text(DATA_NOCONVERTER)}else{if(b==="no data"||(b.data!==undefined&&(b.data===null||b.data.length===0))){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()},a.data_query_wait)}else{if(b.status==="data"){if(b.valid_chroms){a.valid_chroms=b.valid_chroms;a.name_div.data("menu_options")["List chrom/contigs with data"]=function(){show_modal("Chrom/contigs with data","<p>"+a.valid_chroms.join("<br/>")+"</p>",{Close:function(){hide_modal()}})}}a.content_div.text(DATA_OK);if(a.view.chrom){a.content_div.text("");a.content_div.css("height",a.height_px+"px");a.enabled=true;$.when(a.predraw_init()).done(function(){a.draw()})}}}}}}})}},predraw_init:function(){},update_name:function(a){this.old_name=this.name;this.name=a;this.name_div.text(this.name)},revert_name:function(){this.name=this.old_name;this.name_div.text(this.name)}});var TiledTrack=function(g,d,s){var o=this,j=o.view;this.filters=(g!==undefined?get_filters_from_dict(g):[]);this.tool=(d!==undefined?get_tool_from_dict(d):undefined);this.parent_track=s;this.child_tracks=[];if(o.hidden){return}if(this.parent_track){this.header_div.find(".draghandle").removeClass("draghandle").addClass("child-track-icon").addClass("icon-button");this.parent_element.addClass("child-track");this.tool=undefined}this.filtering_div=$("<div/>").addClass("track-filters").hide();this.header_div.after(this.filtering_div);this.filtering_div.bind("drag",function(u){u.stopPropagation()}).bind("dblclick",function(u){u.stopPropagation()});var t=$("<table class='filters'>").appendTo(this.filtering_div);$.each(this.filters,function(x,A){var w=$("<tr>").appendTo(t);var z=$("<th class='filter-info'>").appendTo(w);var v=$("<span class='name'>").appendTo(z);v.text(A.name+" ");var u=$("<span class='values'>").appendTo(z);var y=$("<td>").appendTo(w);A.control_element=$("<div id='"+A.name+"-filter-control' style='width: 200px; position: relative'>").appendTo(y);A.control_element.slider({range:true,min:Number.MAX_VALUE,max:-Number.MIN_VALUE,values:[0,0],slide:function(C,D){var B=D.values;u.text("["+B[0]+"-"+B[1]+"]");A.low=B[0];A.high=B[1];o.draw(true)},change:function(B,C){A.control_element.slider("option","slide").call(A.control_element,B,C)}});A.slider=A.control_element;A.slider_label=u});if(this.tool){this.dynamic_tool_div=$("<div/>").addClass("dynamic-tool").hide();this.header_div.after(this.dynamic_tool_div);this.dynamic_tool_div.bind("drag",function(u){u.stopPropagation()}).bind("click",function(u){u.stopPropagation()}).bind("dblclick",function(u){u.stopPropagation()});var l=$("<div class='tool-name'>").appendTo(this.dynamic_tool_div).text(this.tool.name);var e=this.tool.params;var o=this;$.each(this.tool.params,function(B,w){var z=$("<div>").addClass("param-row").appendTo(o.dynamic_tool_div);var y=$("<div>").addClass("slider-label").appendTo(z);var D=$("<span class='param-name'>").text(w.label+" ").appendTo(y);var x=$("<span/>").text(w.value);var A=$("<span class='param-value'>").appendTo(y).append("[").append(x).append("]");var C=$("<div/>").addClass("slider").appendTo(z);var u=$("<div id='"+w.name+"-param-control'>").appendTo(C);var v=(w.max<=1?0.01:(w.max<=1000?1:5));u.slider({min:w.min,max:w.max,step:v,value:w.value,slide:function(E,G){var F=G.value;w.value=F;if(0<F&&F<1){F=parseFloat(F).toFixed(2)}x.text(F)},change:function(E,F){w.value=F.value}});A.click(function(){var G=x,F=G.text(),E=(w.max<=1?4:w.max.length);G.text("");$("<input type='text'/>").attr("size",E).attr("maxlength",E).attr("value",F).appendTo(G).focus().select().click(function(H){H.stopPropagation()}).blur(function(){$(this).remove();G.text(F)}).keyup(function(J){if(J.keyCode===27){$(this).trigger("blur")}else{if(J.keyCode===13){var H=$(this),I=parseFloat(H.val());if(isNaN(I)||I>w.max||I<w.min){alert("Parameter value must be in the range ["+w.min+"-"+w.max+"]");return $(this)}G.text(I);u.slider("value",I);w.value=I}}})});$("<div style='clear: both;'/>").appendTo(z)});var b=$("<div>").addClass("param-row").appendTo(this.dynamic_tool_div);var n=$("<input type='submit'>").attr("value","Run").appendTo(b);var o=this;n.click(function(){o.run_tool()})}o.child_tracks_container=$("<div/>").addClass("child-tracks-container").hide();o.container_div.append(o.child_tracks_container);if(o.display_modes!==undefined){if(o.mode_div===undefined){o.mode_div=$("<div class='right-float menubutton popup' />").appendTo(o.header_div);var m=(o.track_config&&o.track_config.values.mode?o.track_config.values.mode:o.display_modes[0]);o.mode=m;o.mode_div.text(m);var a=function(u){o.mode_div.text(u);o.mode=u;o.track_config.values.mode=u;o.tile_cache.clear();o.draw()};var f={};for(var q=0,r=o.display_modes.length;q<r;q++){var k=o.display_modes[q];f[k]=function(u){return function(){a(u)}}(k)}make_popupmenu(o.mode_div,f)}else{o.mode_div.hide()}}var h={};h["Edit configuration"]=function(){var w=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},u=function(){o.track_config.update_from_form($(".dialog-box"));hide_modal();$(window).unbind("keypress.check_enter_esc")},v=function(x){if((x.keyCode||x.which)===27){w()}else{if((x.keyCode||x.which)===13){u()}}};$(window).bind("keypress.check_enter_esc",v);show_modal("Configure Track",o.track_config.build_form(),{Cancel:w,OK:u})};if(o.filters.length>0){h["Show filters"]=function(){var u;if(!o.filtering_div.is(":visible")){u="Hide filters";o.filters_visible=true}else{u="Show filters";o.filters_visible=false}o.filtering_div.toggle()}}if(o.tool){h["Toggle Tool"]=function(){var u;if(!o.dynamic_tool_div.is(":visible")){u="Hide dynamic tool";o.update_name(o.name+o.tool_region_and_parameters_str())}else{u="Show dynamic tool";o.revert_name()}o.dynamic_tool_div.toggle()}}var c=j;var p=function(){$("#no-tracks").show()};if(this.parent_track){c=this.parent_track;p=function(){}}h.Remove=function(){c.remove_track(o);if(c.num_tracks===0){p()}};o.popup_menu=make_popupmenu(o.name_div,h)};$.extend(TiledTrack.prototype,Track.prototype,{draw:function(b){var m=this.view.low,g=this.view.high,j=g-m,c=this.view.container.width(),f=this.view.resolution;var p=$("<div style='position: relative;'></div>"),r=c/j;this.content_div.append(p);this.max_height=0;var a=Math.floor(m/f/DENSITY);var l=0;while((a*DENSITY*f)<g){var n=c+"_"+r+"_"+a;var e=this.tile_cache.get(n);var k=a*DENSITY*this.view.resolution;var q=k+DENSITY*this.view.resolution;if(!b&&e){this.show_tile(e,p,k,r)}else{this.delayed_draw(b,n,k,q,a,f,p,r)}a+=1}var d=this;var o=setInterval(function(){if(l===0){var u=d.content_div.children();var t=false;for(var v=u.length-1,s=0;v>=s;v--){var x=$(u[v]);if(t){x.remove()}else{if(x.children().length!==0){t=true}}}for(var w=0;w<d.filters.length;w++){d.filters[w].update_ui_elt()}clearInterval(o)}},50);for(var h=0;h<this.child_tracks.length;h++){this.child_tracks[h].draw(b)}},delayed_draw:function(b,g,f,j,c,e,h,k){var d=this;var a=setTimeout(function(){if(f<=d.view.high&&j>=d.view.low){var l;if(!b){l=d.tile_cache.get(g)}if(!l){l=d.draw_tile(e,c,h,k);if(l){var m=$("<div class='track-tile'>").prepend(l);if(l.hasClass(FILTERABLE_CLASS)){m.addClass(FILTERABLE_CLASS)}l=m}}if(l){d.tile_cache.set(g,l);d.show_tile(l,h,f,k)}}},50)},show_tile:function(a,f,d,g){var b=this;var c=this.view.high-this.view.low,e=(d-this.view.low)*g;if(this.left_offset){e-=this.left_offset}a.css({position:"absolute",top:0,left:e,height:""});f.append(a);b.max_height=Math.max(b.max_height,a.height());b.content_div.css("height",b.max_height+"px");f.children().css("height",b.max_height+"px");if(b.hidden){return}if(a.hasClass(FILTERABLE_CLASS)){show_hide_popupmenu_options(b.popup_menu,"(Show|Hide) filters");if(b.filters_visible){b.filtering_div.show()}}else{show_hide_popupmenu_options(b.popup_menu,"(Show|Hide) filters",false);b.filtering_div.hide()}},set_overview:function(){var a=this.view;if(this.initial_canvas&&this.is_overview){a.overview_close.show();a.overview_viewport.append(this.initial_canvas);a.overview_highlight.show().height(this.initial_canvas.height());a.overview_viewport.height(this.initial_canvas.height()+a.overview_box.height())}$(window).trigger("resize")},run_tool:function(){var b={dataset_id:this.original_dataset_id,chrom:this.view.chrom,low:this.view.low,high:this.view.high,tool_id:this.tool.name};$.extend(b,this.tool.get_param_values_dict());var d=this,c=b.tool_id+d.tool_region_and_parameters_str(b.chrom,b.low,b.high),e;if(d.track_type=="FeatureTrack"){e=new ToolDataFeatureTrack(c,view,undefined,{},{},d)}this.add_track(e);e.content_div.text("Starting job.");view.has_changes=true;var a=function(){$.getJSON(run_tool_url,b,function(f){if(f=="no converter"){e.container_div.addClass("error");e.content_div.text(DATA_NOCONVERTER)}else{if(f.error){e.container_div.addClass("error");e.content_div.text(DATA_CANNOT_RUN_TOOL+f.message)}else{if(f=="pending"){e.container_div.addClass("pending");e.content_div.text("Converting input data so that it can be easily reused.");setTimeout(a,2000)}else{e.dataset_id=f.dataset_id;e.content_div.text("Running job.");e.init()}}}})};a()},tool_region_and_parameters_str:function(c,a,d){var b=this,e=(c!==undefined&&a!==undefined&&d!==undefined?c+":"+a+"-"+d:"all");return" - region=["+e+"], parameters=["+b.tool.get_param_values().join(", ")+"]"},add_track:function(a){a.track_id=this.track_id+"_"+this.child_tracks.length;a.container_div.attr("id","track_"+a.track_id);this.child_tracks_container.append(a.container_div);sortable(a.container_div,".child-track-icon");if(!$(this.child_tracks_container).is(":visible")){this.child_tracks_container.show()}this.child_tracks.push(a)},remove_track:function(a){a.container_div.fadeOut("slow",function(){$(this).remove()})}});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.view.container.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 ReferenceTrack=function(a){this.track_type="ReferenceTrack";this.hidden=true;Track.call(this,null,a,a.top_labeltrack);TiledTrack.call(this);this.left_offset=200;this.height_px=12;this.container_div.addClass("reference-track");this.content_div.css("background","none");this.content_div.css("min-height","0px");this.content_div.css("border","none");this.data_queue={};this.data_cache=new DataCache(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,l,p){var g=b*DENSITY*f,d=DENSITY*f,k=f+"_"+b;var e=document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(e)}e=$(e);var o=e.get(0).getContext("2d");if(p>CHAR_WIDTH_PX){if(this.data_cache.get(k)===undefined){this.get_data(f,b);return}var n=this.data_cache.get(k);if(n===null){this.content_div.css("height","0px");return}e.get(0).width=Math.ceil(d*p+this.left_offset);e.get(0).height=this.height_px;for(var h=0,m=n.length;h<m;h++){var a=Math.round(h*p),j=Math.round(p/2);o.fillText(n[h],a+this.left_offset+j,10)}l.append(e);return e}this.content_div.css("height","0px")}});var LineTrack=function(e,c,f,a,d){var b=this;this.track_type="LineTrack";this.display_modes=["Histogram","Line","Filled","Intensity"];this.mode="Histogram";Track.call(this,e,c,c.viewport_container);TiledTrack.call(this);this.min_height_px=16;this.max_height_px=400;this.height_px=80;this.hda_ldda=f;this.dataset_id=a;this.original_dataset_id=a;this.data_cache=new DataCache(CACHED_DATA);this.tile_cache=new Cache(CACHED_TILES_LINE);this.track_config=new TrackConfig({track:this,params:[{key:"color",label:"Color",type:"color",default_value:"black"},{key:"min_value",label:"Min Value",type:"float",default_value:undefined},{key:"max_value",label:"Max Value",type:"float",default_value:undefined},{key:"mode",type:"string",default_value:this.mode,hidden:true},{key:"height",type:"int",default_value:this.height_px,hidden:true}],saved_values:d,onchange:function(){b.vertical_range=b.prefs.max_value-b.prefs.min_value;$("#linetrack_"+b.track_id+"_minval").text(b.prefs.min_value);$("#linetrack_"+b.track_id+"_maxval").text(b.prefs.max_value);b.tile_cache.clear();b.draw()}});this.prefs=this.track_config.values;this.height_px=this.track_config.values.height;this.vertical_range=this.track_config.values.max_value-this.track_config.values.min_value;(function(g){var k=false;var j=false;var h=$("<div class='track-resize'>");$(g.container_div).hover(function(){k=true;h.show()},function(){k=false;if(!j){h.hide()}});h.hide().bind("dragstart",function(l,m){j=true;m.original_height=$(g.content_div).height()}).bind("drag",function(m,n){var l=Math.min(Math.max(n.original_height+n.deltaY,g.min_height_px),g.max_height_px);$(g.content_div).css("height",l);g.height_px=l;g.draw(true)}).bind("dragend",function(l,m){g.tile_cache.clear();j=false;if(!k){h.hide()}g.track_config.values.height=g.height_px}).appendTo(g.container_div)})(this)};$.extend(LineTrack.prototype,TiledTrack.prototype,{predraw_init:function(){var a=this,b=a.view.tracks.indexOf(a);a.vertical_range=undefined;return $.getJSON(a.data_url,{stats:true,chrom:a.view.chrom,low:null,high:null,hda_ldda:a.hda_ldda,dataset_id:a.dataset_id},function(c){a.container_div.addClass("line-track");var e=c.data;if(isNaN(parseFloat(a.prefs.min_value))||isNaN(parseFloat(a.prefs.max_value))){a.prefs.min_value=e.min;a.prefs.max_value=e.max;$("#track_"+b+"_minval").val(a.prefs.min_value);$("#track_"+b+"_maxval").val(a.prefs.max_value)}a.vertical_range=a.prefs.max_value-a.prefs.min_value;a.total_frequency=e.total_frequency;a.container_div.find(".yaxislabel").remove();var f=$("<div />").addClass("yaxislabel").attr("id","linetrack_"+b+"_minval").text(round_1000(a.prefs.min_value));var d=$("<div />").addClass("yaxislabel").attr("id","linetrack_"+b+"_maxval").text(round_1000(a.prefs.max_value));d.css({position:"absolute",top:"24px",left:"10px"});d.prependTo(a.container_div);f.css({position:"absolute",bottom:"2px",left:"10px"});f.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:this.data_url,dataType:"json",data:{chrom:this.view.chrom,low:a,high:f,hda_ldda:this.hda_ldda,dataset_id:this.dataset_id,resolution:this.view.resolution},success:function(g){var h=g.data;c.data_cache.set(e,h);delete c.data_queue[e];c.draw()},error:function(h,g,j){console.log(h,g,j)}})}},draw_tile:function(o,r,c,e){if(this.vertical_range===undefined){return}var s=r*DENSITY*o,a=DENSITY*o,x=o+"_"+r;var b=document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(b)}b=$(b);if(this.data_cache.get(x)===undefined){this.get_data(o,r);return}var v=this.data_cache.get(x);if(!v){return}b.get(0).width=Math.ceil(a*e);b.get(0).height=this.height_px;var n=b.get(0).getContext("2d"),j=false,k=this.prefs.min_value,g=this.prefs.max_value,m=this.vertical_range,t=this.total_frequency,d=this.height_px,l=this.mode;var w=Math.round(d+k/m*d);n.beginPath();n.moveTo(0,w);n.lineTo(a*e,w);n.fillStyle="#aaa";n.stroke();n.beginPath();n.fillStyle=this.prefs.color;var u,h,f;if(v.length>1){f=Math.ceil((v[1][0]-v[0][0])*e)}else{f=10}for(var p=0,q=v.length;p<q;p++){u=Math.round((v[p][0]-s)*e);h=v[p][1];if(h===null){if(j&&l==="Filled"){n.lineTo(u,d)}j=false;continue}if(h<k){h=k}else{if(h>g){h=g}}if(l==="Histogram"){h=Math.round(h/m*d);n.fillRect(u,w,f,-h)}else{if(l==="Intensity"){h=255-Math.floor((h-k)/m*255);n.fillStyle="rgb("+h+","+h+","+h+")";n.fillRect(u,0,f,d)}else{h=Math.round(d-(h-k)/m*d);if(j){n.lineTo(u,h)}else{j=true;if(l==="Filled"){n.moveTo(u,d);n.lineTo(u,h)}else{n.moveTo(u,h)}}}}}if(l==="Filled"){if(j){n.lineTo(u,w);n.lineTo(0,w)}n.fill()}else{n.stroke()}return b}});var FeatureTrack=function(a,f,e,j,h,c,d,g){var b=this;this.track_type="FeatureTrack";this.display_modes=["Auto","Dense","Squish","Pack"];this.track_config=new TrackConfig({track:this,params:[{key:"block_color",label:"Block color",type:"color",default_value:"#444"},{key:"label_color",label:"Label color",type:"color",default_value:"black"},{key:"show_counts",label:"Show summary counts",type:"bool",default_value:true},{key:"mode",type:"string",default_value:this.mode,hidden:true},],saved_values:h,onchange:function(){b.tile_cache.clear();b.draw()}});this.prefs=this.track_config.values;Track.call(this,a,f,f.viewport_container);TiledTrack.call(this,c,d,g);this.height_px=0;this.container_div.addClass("feature-track");this.hda_ldda=e;this.dataset_id=j;this.original_dataset_id=j;this.zo_slots={};this.show_labels_scale=0.001;this.showing_details=false;this.summary_draw_height=30;this.default_font=DEFAULT_FONT;this.inc_slots={};this.data_queue={};this.start_end_dct={};this.tile_cache=new Cache(CACHED_TILES_FEATURE);this.data_cache=new DataCache(20);this.left_offset=200};$.extend(FeatureTrack.prototype,TiledTrack.prototype,{get_data:function(a,d){var b=this,c=a+"_"+d;if(!b.data_queue[c]){b.data_queue[c]=true;$.getJSON(b.data_url,{chrom:b.view.chrom,low:a,high:d,hda_ldda:b.hda_ldda,dataset_id:b.dataset_id,resolution:this.view.resolution,mode:this.mode},function(e){b.data_cache.set_data(a,d,b.mode,e);delete b.data_queue[c];b.draw()})}},incremental_slots:function(a,h,p){var q=this.inc_slots[a];if(!q||(q.mode!==p)){q={};q.w_scale=a;q.mode=p;this.inc_slots[a]=q;this.start_end_dct[a]={}}var l=q.w_scale,w=[],x=[],j=0,n=this.view.max_low;for(var u=0,v=h.length;u<v;u++){var g=h[u],k=g[0];if(q[k]!==undefined){j=Math.max(j,q[k]);x.push(q[k])}else{w.push(u)}}var d=this.start_end_dct[a];var m=function(D,E){for(var C=0;C<=MAX_FEATURE_DEPTH;C++){var A=false,F=d[C];if(F!==undefined){for(var z=0,B=F.length;z<B;z++){var y=F[z];if(E>y[0]&&D<y[1]){A=true;break}}}if(!A){return C}}return -1};for(var u=0,v=w.length;u<v;u++){var g=h[w[u]],k=g[0],s=g[1],b=g[2],o=g[3],c=Math.floor((s-n)*l),f=Math.ceil((b-n)*l),t=CONTEXT.measureText(o).width,e;if(o!==undefined&&p==="Pack"){t+=(LABEL_SPACING+PACK_SPACING);if(c-t>=0){c-=t;e="left"}else{f+=t;e="right"}}var r=m(c,f);if(r>=0){if(d[r]===undefined){d[r]=[]}d[r].push([c,f]);q[k]=r;j=Math.max(j,r)}else{}}return j},draw_summary_tree:function(b,o,n,l,r,j,f,e){var c=j+LABEL_SPACING+CHAR_HEIGHT_PX;delta_x_px=Math.ceil(n*r);var h=$("<div />").addClass("yaxislabel");h.text(l);h.css({position:"absolute",top:"22px",left:"10px"});h.prependTo(this.container_div);var q=b.get(0).getContext("2d");for(var d=0,g=o.length;d<g;d++){var m=Math.floor((o[d][0]-f)*r);var k=o[d][1];if(!k){continue}var p=k/l*j;q.fillStyle="black";q.fillRect(m+e,c-p,delta_x_px,p);var a=4;if(this.prefs.show_counts&&(q.measureText(k).width+a)<delta_x_px){q.fillStyle="#666";q.textAlign="center";q.fillText(k,m+e+(delta_x_px/2),10)}}},draw_element:function(p,f,g,x,j,r,I,M,N,a,A){var u=x[0],K=x[1],C=x[2],s=x[3],D=Math.floor(Math.max(0,(K-r)*M)),q=Math.ceil(Math.min(a,Math.max(0,(C-r)*M))),B=(g==="Dense"?1:(1+j))*N,o,G,t=null,O=null,d=this.prefs.block_color,F=this.prefs.label_color;if(g==="Dense"){p.fillStyle=d;p.fillRect(D+A,B+5,q-D,DENSE_FEATURE_HEIGHT)}else{if(g==="no_detail"){p.fillStyle=d;p.fillRect(D+A,B+5,q-D,DENSE_FEATURE_HEIGHT)}else{var n=x[5],z=x[6],E=x[7],e=x[8];if(z&&E){t=Math.floor(Math.max(0,(z-r)*M));O=Math.ceil(Math.min(a,Math.max(0,(E-r)*M)))}var L,v;if(g=="Squish"){L=1;v=SQUISH_FEATURE_HEIGHT}else{L=5;v=PACK_FEATURE_HEIGHT}if(!e){if(x.strand){if(x.strand=="+"){p.fillStyle=RIGHT_STRAND_INV}else{if(x.strand=="-"){p.fillStyle=LEFT_STRAND_INV}}}else{p.fillStyle=CONNECTOR_COLOR}p.fillRect(D+A,B+(v-L)/2+1,q-D,v)}else{var m,w;if(g=="Squish"){p.fillStyle=CONNECTOR_COLOR;m=B+Math.floor(SQUISH_FEATURE_HEIGHT/2)+1;w=1}else{if(n){var m=B;var w=v;if(n=="+"){p.fillStyle=RIGHT_STRAND}else{if(n=="-"){p.fillStyle=LEFT_STRAND}}}else{p.fillStyle=CONNECTOR_COLOR;m+=(SQUISH_FEATURE_HEIGHT/2)+1;w=1}}p.fillRect(D+A,m,q-D,w);for(var J=0,c=e.length;J<c;J++){var h=e[J],b=Math.floor(Math.max(0,(h[0]-r)*M)),y=Math.ceil(Math.min(a,Math.max((h[1]-r)*M)));if(b>y){continue}p.fillStyle=d;p.fillRect(b+A,B+(v-L)/2+1,y-b,L);if(t!==undefined&&!(b>O||y<t)){var H=Math.max(b,t),l=Math.min(y,O-1);p.fillRect(H+A,B+1,l-H,v)}}}if(g==="Pack"&&K>r){p.fillStyle=F;if(f===0&&D-p.measureText(s).width<0){p.textAlign="left";p.fillText(s,q+A+LABEL_SPACING,B+8)}else{p.textAlign="right";p.fillText(s,D+A-LABEL_SPACING,B+8)}p.fillStyle=d}}}},draw_tile:function(u,z,j,l){var B=z*DENSITY*u,a=(z+1)*DENSITY*u,p=a-B;var n=this.data_cache.get_data(B,a,this.mode);if(n===undefined||n==="pending"||(this.mode!=="Auto"&&n.dataset_type==="summary_tree")){this.data_queue[[B,a]]=true;this.get_data(B,a);return}var s=Math.ceil(p*l),q=this.mode,D=25,e=this.left_offset,o,g,v;var c=document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(c)}c=$(c);if(q==="Auto"){if(n.dataset_type==="summary_tree"){q=n.dataset_type}else{if(n.extra_info==="no_detail"){q="no_detail"}else{var C=n.data;if((C.length&&C.length<4)||(this.view.high-this.view.low>MIN_SQUISH_VIEW_WIDTH)){q="Squish"}else{q="Pack"}}}}if(q==="summary_tree"){g=this.summary_draw_height}if(q==="Dense"){g=D;v=DENSE_TRACK_HEIGHT}else{if(q==="no_detail"){v=NO_DETAIL_TRACK_HEIGHT}else{if(q==="Squish"){v=SQUISH_TRACK_HEIGHT}else{v=PACK_TRACK_HEIGHT}}}if(q==="no_detail"||q==="Squish"||q==="Pack"){g=this.incremental_slots(l,n.data,q)*v+D;o=this.inc_slots[l]}c.get(0).width=s+e;c.get(0).height=g;if(n.dataset_type=="summary_tree"){c.get(0).height+=LABEL_SPACING+CHAR_HEIGHT_PX}j.parent().css("height",Math.max(this.height_px,g)+"px");var t=c.get(0).getContext("2d");t.fillStyle=this.prefs.block_color;t.font=this.default_font;t.textAlign="right";this.container_div.find(".yaxislabel").remove();if(q==="summary_tree"){this.draw_summary_tree(c,n.data,n.delta,n.max,l,g,B,e);return c}if(n.message){c.css({"border-color":"red"});t.fillStyle="red";t.textAlign="left";t.fillText(n.message,100+e,v);if(!n.data){return c}}for(var A=0;A<this.filters.length;A++){if(n.data.length&&this.filters[A].applies_to(n.data[0])){c.addClass(FILTERABLE_CLASS);break}}var C=n.data;for(var w=0,y=C.length;w<y;w++){var h=C[w],k=h[0],r=h[1],b=h[2],d=(o&&o[k]!==undefined?o[k]:null);var x=false;var m;for(var A=0;A<this.filters.length;A++){m=this.filters[A];m.update_attrs(h);if(!m.keep(h)){x=true;break}}if(x){continue}if(is_overlap([r,b],[B,a])&&d!==null){this.draw_element(t,z,q,h,d,B,a,l,v,s,e)}}return c}});var VcfTrack=function(d,b,f,a,c,e){FeatureTrack.call(this,d,b,f,a,c,e);this.track_type="VcfTrack"};$.extend(VcfTrack.prototype,TiledTrack.prototype,FeatureTrack.prototype,{draw_element:function(u,p,j,e,x,c,m,v,s){var j=data[i],l=j[0],t=j[1],d=j[2]-1,o=j[3],g=Math.floor(Math.max(0,(t-x)*m)),k=Math.ceil(Math.min(s,Math.max(0,(d-x)*m))),f=(p==="Dense"?1:(1+e))*v,a,y,b=null,n=null;if(no_label){u.fillStyle=block_color;u.fillRect(g+left_offset,f+5,k-g,1)}else{var w=j[4],r=j[5],h=j[6];a=9;y=1;u.fillRect(g+left_offset,f,k-g,a);if(p!=="Dense"&&o!==undefined&&t>x){u.fillStyle=label_color;if(tile_index===0&&g-u.measureText(o).width<0){u.textAlign="left";u.fillText(o,k+2+left_offset,f+8)}else{u.textAlign="right";u.fillText(o,g-2+left_offset,f+8)}u.fillStyle=block_color}var q=w+" / "+r;if(t>x&&u.measureText(q).width<(k-g)){u.fillStyle="white";u.textAlign="center";u.fillText(q,left_offset+g+(k-g)/2,f+8);u.fillStyle=block_color}}}});var ReadTrack=function(d,b,f,a,c,e){FeatureTrack.call(this,d,b,f,a,c,e);this.track_type="ReadTrack"};$.extend(ReadTrack.prototype,TiledTrack.prototype,FeatureTrack.prototype,{draw_read:function(w,s,n,A,d,v,l,h,g){w.textAlign="center";var b=[A,d],q=0,x=0,u=Math.round(n/2);var F=[];for(var o=0,z=l.length;o<z;o++){var m=l[o],e="MIDNSHP=X"[m[0]],p=m[1];if(e==="H"||e==="S"){q-=p}var j=v+q,E=Math.floor(Math.max(0,(j-A)*n)),k=Math.floor(Math.max(0,(j+p-A)*n));switch(e){case"H":break;case"S":case"M":case"=":var r=compute_overlap([j,j+p],b);if(r!=NO_OVERLAP){var t=h.slice(x,x+p);if((s==="Pack"||this.mode==="Auto")&&h!==undefined&&n>CHAR_WIDTH_PX){w.fillStyle=this.prefs.block_color;w.fillRect(E+this.left_offset,g+1,k-E,9);w.fillStyle=CONNECTOR_COLOR;for(var C=0,a=t.length;C<a;C++){if(j+C>=A&&j+C<=d){var D=Math.floor(Math.max(0,(j+C-A)*n));w.fillText(t[C],D+this.left_offset+u,g+9)}}}else{w.fillStyle=this.prefs.block_color;w.fillRect(E+this.left_offset,g+(this.mode!="Dense"?4:5),k-E,(s!="Dense"?SQUISH_FEATURE_HEIGHT:DENSE_FEATURE_HEIGHT))}}x+=p;q+=p;break;case"N":w.fillStyle=CONNECTOR_COLOR;w.fillRect(E+this.left_offset,g+5,k-E,1);q+=p;break;case"D":w.fillStyle="red";w.fillRect(E+this.left_offset,g+4,k-E,3);q+=p;break;case"P":break;case"I":var r=compute_overlap([j,j+p],b);if(r!=NO_OVERLAP){var t=h.slice(x,x+p);var f=this.left_offset+E-(k-E)/2;if((s==="Pack"||this.mode==="Auto")&&h!==undefined&&n>CHAR_WIDTH_PX){w.fillStyle="yellow";w.fillRect(f,g-9,k-E,9);F[F.length]=[f+(k-E)/2,g+4,5];w.fillStyle=CONNECTOR_COLOR;switch(r){case (OVERLAP_START):t=t.slice(A-j);break;case (OVERLAP_END):t=t.slice(0,j-d);break;case (CONTAINED_BY):break;case (CONTAINS):t=t.slice(A-j,j-d);break}for(var C=0,a=t.length;C<a;C++){var D=Math.floor(Math.max(0,(j+C-A)*n));w.fillText(t[C],D+this.left_offset+u-(k-E)/2,g)}}else{w.fillStyle="yellow";w.fillRect(f,g+(this.mode!="Dense"?2:5),k-E,(s!="Dense"?SQUISH_FEATURE_HEIGHT:DENSE_FEATURE_HEIGHT))}}x+=p;break;case"X":x+=p;break}}var B;for(var y=0;y<F.length;y++){B=F[y];w.fillStyle="yellow";w.drawDownwardEquilateralTriangle(B[0],B[1],B[2])}},draw_element:function(u,w,q,h,d,y,b,m,v,s,e){var l=h[0],t=h[1],c=h[2],n=h[3],g=Math.floor(Math.max(0,(t-y)*m)),j=Math.ceil(Math.min(s,Math.max(0,(c-y)*m))),f=(q==="Dense"?1:(1+d))*v,x=this.prefs.block_color,k=this.prefs.label_color;u.fillStyle=x;if(h[5] instanceof Array){var r=Math.floor(Math.max(0,(h[4][0]-y)*m)),p=Math.ceil(Math.min(s,Math.max(0,(h[4][1]-y)*m))),o=Math.floor(Math.max(0,(h[5][0]-y)*m)),a=Math.ceil(Math.min(s,Math.max(0,(h[5][1]-y)*m)));if(h[4][1]>=y&&h[4][0]<=b&&h[4][2]){this.draw_read(u,q,m,y,b,h[4][0],h[4][2],h[4][3],f)}if(h[5][1]>=y&&h[5][0]<=b&&h[5][2]){this.draw_read(u,q,m,y,b,h[5][0],h[5][2],h[5][3],f)}if(o>p){u.fillStyle=CONNECTOR_COLOR;u.dashedLine(p+e,f+5,e+o,f+5)}}else{u.fillStyle=x;this.draw_read(u,q,m,y,b,t,h[4],h[5],f)}if(q==="Pack"&&t>y){u.fillStyle=this.prefs.label_color;if(w===0&&g-u.measureText(n).width<0){u.textAlign="left";u.fillText(n,j+e+LABEL_SPACING,f+8)}else{u.textAlign="right";u.fillText(n,g+e-LABEL_SPACING,f+8)}u.fillStyle=x}}});var ToolDataFeatureTrack=function(e,c,g,a,d,f,b){FeatureTrack.call(this,e,c,g,a,d,f,{},b);this.track_type="ToolDataFeatureTrack";this.data_url=raw_data_url;this.data_query_wait=1000;this.dataset_check_url=dataset_state_url};$.extend(ToolDataFeatureTrack.prototype,TiledTrack.prototype,FeatureTrack.prototype,{predraw_init:function(){var b=this;var a=function(){if(b.data_cache.size()==0){setTimeout(a,300)}else{b.data_url=default_data_url;b.data_query_wait=DEFAULT_DATA_QUERY_WAIT;b.dataset_state_url=converted_datasets_state_url;$.getJSON(b.dataset_state_url,{dataset_id:b.dataset_id},function(c){})}};a()}});
\ No newline at end of file
--- a/static/scripts/trackster.js Tue Feb 22 10:38:35 2011 -0500
+++ b/static/scripts/trackster.js Tue Feb 22 11:00:03 2011 -0500
@@ -134,6 +134,8 @@
PACK_FEATURE_HEIGHT = 9,
LABEL_SPACING = 2,
PACK_SPACING = 5,
+ // Minimum width for window for squish to be used.
+ MIN_SQUISH_VIEW_WIDTH = 12000,
// Other constants.
DEFAULT_FONT = "9px Monaco, Lucida Console, monospace",
@@ -2120,7 +2122,7 @@
// with keys 'slot' and 'text'.
// Returns the number of slots used to pack features.
//
- incremental_slots: function(level, features, no_label, mode) {
+ incremental_slots: function(level, features, mode) {
//
// Get/create incremental slots for level. If display mode changed,
// need to create new slots.
@@ -2200,7 +2202,7 @@
// Update start, end drawing locations to include feature name.
// Try to put the name on the left, if not, put on right.
- if (feature_name !== undefined && !no_label) {
+ if (feature_name !== undefined && mode === "Pack") {
// Add gap for label spacing and extra pack space padding
text_len += (LABEL_SPACING + PACK_SPACING);
if (f_start - text_len >= 0) {
@@ -2248,7 +2250,7 @@
else {
// TODO: remove this warning when skipped features are handled.
// Show warning for skipped feature.
- // console.log("WARNING: not displaying feature"); // , feature_uid, f_start, f_end);
+ //console.log("WARNING: not displaying feature", feature_uid, f_start, f_end);
}
}
@@ -2267,6 +2269,180 @@
return highest_slot;
},
/**
+ * Draw summary tree on canvas.
+ */
+ draw_summary_tree: function(canvas, points, delta, max, w_scale, required_height, tile_low, left_offset) {
+ var
+ // Set base Y so that max label and data do not overlap. Base Y is where rectangle bases
+ // start. However, height of each rectangle is relative to required_height; hence, the
+ // max rectangle is required_height.
+ base_y = required_height + LABEL_SPACING + CHAR_HEIGHT_PX;
+ delta_x_px = Math.ceil(delta * w_scale);
+
+ var max_label = $("<div />").addClass('yaxislabel');
+ max_label.text(max);
+
+ max_label.css({ position: "absolute", top: "22px", left: "10px" });
+ max_label.prependTo(this.container_div);
+
+ var ctx = canvas.get(0).getContext("2d");
+ for (var i = 0, len = points.length; i < len; i++) {
+ var x = Math.floor( (points[i][0] - tile_low) * w_scale );
+ var y = points[i][1];
+
+ if (!y) { continue; }
+ var y_px = y / max * required_height;
+
+ ctx.fillStyle = "black";
+ ctx.fillRect(x + left_offset, base_y - y_px, delta_x_px, y_px);
+
+ // Draw number count if it can fit the number with some padding, otherwise things clump up
+ var text_padding_req_x = 4;
+ if (this.prefs.show_counts && (ctx.measureText(y).width + text_padding_req_x) < delta_x_px) {
+ ctx.fillStyle = "#666";
+ ctx.textAlign = "center";
+ ctx.fillText(y, x + left_offset + (delta_x_px/2), 10);
+ }
+ }
+ },
+ /**
+ * Draw feature.
+ */
+ draw_element: function(ctx, tile_index, mode, feature, slot, tile_low, tile_high, w_scale, y_scale, width, left_offset) {
+ var
+ feature_uid = feature[0],
+ feature_start = feature[1],
+ feature_end = feature[2],
+ feature_name = feature[3],
+ f_start = Math.floor( Math.max(0, (feature_start - tile_low) * w_scale) ),
+ f_end = Math.ceil( Math.min(width, Math.max(0, (feature_end - tile_low) * w_scale)) ),
+ y_center = (mode === "Dense" ? 1 : (1 + slot)) * y_scale,
+ thickness, y_start, thick_start = null, thick_end = null,
+ block_color = this.prefs.block_color,
+ label_color = this.prefs.label_color;
+
+ // Dense mode displays the same for all data.
+ if (mode === "Dense") {
+ ctx.fillStyle = block_color;
+ ctx.fillRect(f_start + left_offset, y_center + 5, f_end - f_start, DENSE_FEATURE_HEIGHT);
+ }
+ else if (mode === "no_detail") {
+ // No details for feature, so only one way to display.
+ ctx.fillStyle = block_color;
+ // TODO: what should width be here?
+ ctx.fillRect(f_start + left_offset, y_center + 5, f_end - f_start, DENSE_FEATURE_HEIGHT);
+ }
+ else { // Mode is either Squish or Pack:
+ // Feature has details.
+ var feature_strand = feature[5],
+ feature_ts = feature[6],
+ feature_te = feature[7],
+ feature_blocks = feature[8];
+
+ if (feature_ts && feature_te) {
+ thick_start = Math.floor( Math.max(0, (feature_ts - tile_low) * w_scale) );
+ thick_end = Math.ceil( Math.min(width, Math.max(0, (feature_te - tile_low) * w_scale)) );
+ }
+
+ // Set vars that depend on mode.
+ var thin_height, thick_height;
+ if (mode == "Squish") {
+ thin_height = 1;
+ thick_height = SQUISH_FEATURE_HEIGHT;
+ }
+ else { // mode == "Pack"
+ thin_height = 5;
+ thick_height = PACK_FEATURE_HEIGHT;
+ }
+
+ // Draw feature/feature blocks + connectors.
+ if (!feature_blocks) {
+ // If there are no blocks, treat the feature as one big exon.
+ if ( feature.strand ) {
+ if (feature.strand == "+") {
+ ctx.fillStyle = RIGHT_STRAND_INV;
+ } else if (feature.strand == "-") {
+ ctx.fillStyle = LEFT_STRAND_INV;
+ }
+ }
+ else { // No strand.
+ ctx.fillStyle = CONNECTOR_COLOR;
+ }
+ ctx.fillRect(f_start + left_offset, y_center + (thick_height-thin_height)/2 + 1,
+ f_end - f_start, thick_height);
+ }
+ else {
+ // There are feature blocks and mode is either Squish or Pack.
+ //
+ // Approach: (a) draw whole feature as connector/intron and (b) draw blocks as
+ // needed. This ensures that whole feature, regardless of whether it starts with
+ // a block, is visible.
+ //
+
+ // Draw whole feature as connector/intron.
+ var cur_y_center, cur_height;
+ if (mode == "Squish") {
+ ctx.fillStyle = CONNECTOR_COLOR;
+ cur_y_center = y_center + Math.floor(SQUISH_FEATURE_HEIGHT/2) + 1;
+ cur_height = 1;
+ }
+ else { // mode == "Pack"
+ if (feature_strand) {
+ var cur_y_center = y_center;
+ var cur_height = thick_height;
+ if (feature_strand == "+") {
+ ctx.fillStyle = RIGHT_STRAND;
+ } else if (feature_strand == "-") {
+ ctx.fillStyle = LEFT_STRAND;
+ }
+ }
+ else {
+ ctx.fillStyle = CONNECTOR_COLOR;
+ cur_y_center += (SQUISH_FEATURE_HEIGHT/2) + 1;
+ cur_height = 1;
+ }
+ }
+ ctx.fillRect(f_start + left_offset, cur_y_center, f_end - f_start, cur_height);
+
+ for (var k = 0, k_len = feature_blocks.length; k < k_len; k++) {
+ var block = feature_blocks[k],
+ block_start = Math.floor( Math.max(0, (block[0] - tile_low) * w_scale) ),
+ block_end = Math.ceil( Math.min(width, Math.max((block[1] - tile_low) * w_scale)) );
+
+ // Skip drawing if block not on tile.
+ if (block_start > block_end) { continue; }
+
+ // Draw thin block.
+ ctx.fillStyle = block_color;
+ ctx.fillRect(block_start + left_offset, y_center + (thick_height-thin_height)/2 + 1,
+ block_end - block_start, thin_height);
+
+ // If block intersects with thick region, draw block as thick.
+ if (thick_start !== undefined && !(block_start > thick_end || block_end < thick_start) ) {
+ var block_thick_start = Math.max(block_start, thick_start),
+ // -1 b/c intervals are half-open.
+ block_thick_end = Math.min(block_end, thick_end-1);
+ ctx.fillRect(block_thick_start + left_offset, y_center + 1,
+ block_thick_end - block_thick_start, thick_height);
+ }
+ }
+ }
+
+ // Draw label for Pack mode.
+ if (mode === "Pack" && feature_start > tile_low) {
+ 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 + left_offset + LABEL_SPACING, y_center + 8);
+ } else {
+ ctx.textAlign = "right";
+ ctx.fillText(feature_name, f_start + left_offset - LABEL_SPACING, y_center + 8);
+ }
+ ctx.fillStyle = block_color;
+ }
+ }
+ },
+ /**
* Draw FeatureTrack tile.
*/
draw_tile: function(resolution, tile_index, parent_element, w_scale) {
@@ -2297,11 +2473,8 @@
// Create/set/compute some useful vars.
//
var width = Math.ceil( tile_span * w_scale ),
- label_color = this.prefs.label_color,
- block_color = this.prefs.block_color,
mode = this.mode,
min_height = 25,
- no_label,
left_offset = this.left_offset,
slots, required_height, y_scale;
@@ -2309,33 +2482,68 @@
if (window.G_vmlCanvasManager) { G_vmlCanvasManager.initElement(canvas); } // EXCANVAS HACK
canvas = $(canvas);
- if (result.dataset_type === "summary_tree") {
+ //
+ // Set mode if Auto.
+ //
+ if (mode === "Auto") {
+ if (result.dataset_type === "summary_tree") {
+ mode = result.dataset_type;
+ } else if (result.extra_info === "no_detail") {
+ mode = "no_detail";
+ }
+ else {
+ // Choose b/t Squish and Pack.
+ // Proxy measures for using Squish:
+ // (a) error message re: limiting number of features shown;
+ // (b) X number of features shown;
+ // (c) size of view shown.
+ // TODO: cannot use (a) and (b) because it requires coordinating mode across tiles;
+ // fix this so that tiles are redrawn as necessary to use the same mode.
+ //if ( (result.message && result.message.match(/^Only the first [\d]+/)) ||
+ // (result.data && result.data.length > 2000) ||
+ var data = result.data;
+ if ( (data.length && data.length < 4) ||
+ (this.view.high - this.view.low > MIN_SQUISH_VIEW_WIDTH) ) {
+ mode = "Squish";
+ }
+ else {
+ mode = "Pack";
+ }
+ }
+ }
+
+ //
+ // Set required height, y_scale.
+ //
+ if (mode === "summary_tree") {
required_height = this.summary_draw_height;
- } else if (mode === "Dense") {
+ }
+ if (mode === "Dense") {
required_height = min_height;
- y_scale = DENSE_TRACK_HEIGHT;
- } else {
- // Set y_scale based on mode and result data.
- if (mode === "Squish") {
- y_scale = SQUISH_TRACK_HEIGHT;
- no_label = true;
- } else if (mode === "Pack") {
- y_scale = PACK_TRACK_HEIGHT;
- // TODO: is there data where there is no label even in pack mode?
- no_label = false;
- } else if (result.extra_info === "no_detail") { // mode == "Auto"
- y_scale = NO_DETAIL_TRACK_HEIGHT;
- no_label = true;
- } else {
- y_scale = PACK_TRACK_HEIGHT;
- no_label = false;
- }
-
+ y_scale = DENSE_TRACK_HEIGHT;
+ }
+ else if (mode === "no_detail") {
+ y_scale = NO_DETAIL_TRACK_HEIGHT;
+ }
+ else if (mode === "Squish") {
+ y_scale = SQUISH_TRACK_HEIGHT;
+ }
+ else { // mode === "Pack"
+ y_scale = PACK_TRACK_HEIGHT;
+ }
+
+ //
+ // Pack reads.
+ //
+ if (mode === "no_detail" || mode === "Squish" || mode === "Pack") {
// Calculate new slots incrementally for this new chunk of data and update height if necessary.
- required_height = this.incremental_slots(w_scale, result.data, no_label, mode) * y_scale + min_height;
+ required_height = this.incremental_slots(w_scale, result.data, mode) * y_scale + min_height;
slots = this.inc_slots[w_scale];
}
-
+
+ //
+ // Set up for drawing.
+ //
canvas.get(0).width = width + left_offset;
canvas.get(0).height = required_height;
if (result.dataset_type == "summary_tree") {
@@ -2345,7 +2553,7 @@
parent_element.parent().css("height", Math.max(this.height_px, required_height) + "px");
// console.log(( tile_low - this.view.low ) * w_scale, tile_index, w_scale);
var ctx = canvas.get(0).getContext("2d");
- ctx.fillStyle = block_color;
+ ctx.fillStyle = this.prefs.block_color;
ctx.font = this.default_font;
ctx.textAlign = "right";
this.container_div.find(".yaxislabel").remove();
@@ -2353,40 +2561,9 @@
//
// Draw summary tree. If tree is drawn, canvas is returned.
//
- if (result.dataset_type == "summary_tree") {
- var
- // Set base Y so that max label and data do not overlap. Base Y is where rectangle bases
- // start. However, height of each rectangle is relative to required_height; hence, the
- // max rectangle is required_height.
- base_y = required_height + LABEL_SPACING + CHAR_HEIGHT_PX;
- points = result.data,
- max = result.max,
- delta_x_px = Math.ceil(result.delta * w_scale);
-
- var max_label = $("<div />").addClass('yaxislabel');
- max_label.text(max);
-
- max_label.css({ position: "absolute", top: "22px", left: "10px" });
- max_label.prependTo(this.container_div);
-
- for (var i = 0, len = points.length; i < len; i++) {
- var x = Math.floor( (points[i][0] - tile_low) * w_scale );
- var y = points[i][1];
-
- if (!y) { continue; }
- var y_px = y / max * required_height;
-
- ctx.fillStyle = "black";
- ctx.fillRect(x + left_offset, base_y - y_px, delta_x_px, y_px);
-
- // Draw number count if it can fit the number with some padding, otherwise things clump up
- var text_padding_req_x = 4;
- if (this.prefs.show_counts && (ctx.measureText(y).width + text_padding_req_x) < delta_x_px) {
- ctx.fillStyle = "#666";
- ctx.textAlign = "center";
- ctx.fillText(y, x + left_offset + (delta_x_px/2), 10);
- }
- }
+ if (mode === "summary_tree") {
+ this.draw_summary_tree(canvas, result.data, result.delta, result.max, w_scale, required_height,
+ tile_low, left_offset);
return canvas;
}
@@ -2419,32 +2596,17 @@
}
//
- // Draw data points.
+ // Draw elements.
//
var data = result.data;
-
- // Set mode in Auto; never use Dense, so decide b/t Squish and Pack.
- if (mode == "Auto" && data.length > 0) {
- if (feature.length <= 4) {
- mode = "Squish";
- }
- else {
- mode = "Pack";
- }
- }
-
for (var i = 0, len = data.length; i < len; i++) {
var feature = data[i],
feature_uid = feature[0],
feature_start = feature[1],
- // -1 b/c intervals are half-open.
- feature_end = feature[2] - 1,
- feature_name = feature[3];
-
- // TODO: why is this necessary? Without explicitly short-circuiting it, it prevents dense mode from rendering.
- if (this.mode != "Dense" && slots[feature_uid] === undefined) {
- continue;
- }
+ feature_end = feature[2],
+ // Slot valid only if features are slotted and this feature is slotted;
+ // feature may not be due to lack of space.
+ slot = (slots && slots[feature_uid] !== undefined ? slots[feature_uid] : null);
// Apply filters to feature.
var hide_feature = false;
@@ -2459,143 +2621,15 @@
}
if (hide_feature) {
continue;
- }
-
- if (feature_start <= tile_high && feature_end >= tile_low) {
- // All features need a start, end, and vertical center.
- var f_start = Math.floor( Math.max(0, (feature_start - tile_low) * w_scale) ),
- f_end = Math.ceil( Math.min(width, Math.max(0, (feature_end - tile_low) * w_scale)) ),
- y_center = (mode === "Dense" ? 1 : (1 + slots[feature_uid])) * y_scale;
- var thickness, y_start, thick_start = null, thick_end = null;
-
- //
- // There are really four modes for interval indices:
- // dense, no_detail, squish, pack.
- //
-
- // Dense mode displays the same for all data.
- if (mode == "Dense") {
- ctx.fillStyle = block_color;
- ctx.fillRect(f_start + left_offset, y_center + 5, f_end - f_start, DENSE_FEATURE_HEIGHT);
- }
- // Mode is either Squish or Pack:
- else if (feature.length <= 4) {
- // No details for feature, so only one way to display.
- ctx.fillStyle = block_color;
- // TODO: what should width be here?
- ctx.fillRect(f_start + left_offset, y_center + 5, f_end - f_start, DENSE_FEATURE_HEIGHT);
- } else {
- // Feature has details.
- var feature_strand = feature[5],
- feature_ts = feature[6],
- feature_te = feature[7],
- feature_blocks = feature[8];
-
- if (feature_ts && feature_te) {
- thick_start = Math.floor( Math.max(0, (feature_ts - tile_low) * w_scale) );
- thick_end = Math.ceil( Math.min(width, Math.max(0, (feature_te - tile_low) * w_scale)) );
- }
-
- // Set vars that depend on mode.
- var thin_height, thick_height;
- if (mode == "Squish") {
- thin_height = 1;
- thick_height = SQUISH_FEATURE_HEIGHT;
- }
- else { // mode == "Pack"
- thin_height = 5;
- thick_height = PACK_FEATURE_HEIGHT;
- }
-
- // Draw feature/feature blocks + connectors.
- if (!feature_blocks) {
- // If there are no blocks, treat the feature as one big exon.
- if ( feature.strand ) {
- if (feature.strand == "+") {
- ctx.fillStyle = RIGHT_STRAND_INV;
- } else if (feature.strand == "-") {
- ctx.fillStyle = LEFT_STRAND_INV;
- }
- }
- else { // No strand.
- ctx.fillStyle = CONNECTOR_COLOR;
- }
- ctx.fillRect(f_start + left_offset, y_center + (thick_height-thin_height)/2 + 1,
- f_end - f_start, thick_height);
- }
- else {
- // There are feature blocks and mode is either Squish or Pack.
- //
- // Approach: (a) draw whole feature as connector/intron and (b) draw blocks as
- // needed. This ensures that whole feature, regardless of whether it starts with
- // a block, is visible.
- //
-
- // Draw whole feature as connector/intron.
- var cur_y_center, cur_height;
- if (mode == "Squish") {
- ctx.fillStyle = CONNECTOR_COLOR;
- cur_y_center = y_center + Math.floor(SQUISH_FEATURE_HEIGHT/2) + 1;
- cur_height = 1;
- }
- else { // mode == "Pack"
- if (feature_strand) {
- var cur_y_center = y_center;
- var cur_height = thick_height;
- if (feature_strand == "+") {
- ctx.fillStyle = RIGHT_STRAND;
- } else if (feature_strand == "-") {
- ctx.fillStyle = LEFT_STRAND;
- }
- }
- else {
- ctx.fillStyle = CONNECTOR_COLOR;
- cur_y_center += (SQUISH_FEATURE_HEIGHT/2) + 1;
- cur_height = 1;
- }
- }
- ctx.fillRect(f_start + left_offset, cur_y_center, f_end - f_start, cur_height);
-
- for (var k = 0, k_len = feature_blocks.length; k < k_len; k++) {
- var block = feature_blocks[k],
- block_start = Math.floor( Math.max(0, (block[0] - tile_low) * w_scale) ),
- block_end = Math.ceil( Math.min(width, Math.max((block[1] - tile_low) * w_scale)) );
-
- // Skip drawing if block not on tile.
- if (block_start > block_end) { continue; }
-
- // Draw thin block.
- ctx.fillStyle = block_color;
- ctx.fillRect(block_start + left_offset, y_center + (thick_height-thin_height)/2 + 1,
- block_end - block_start, thin_height);
-
- // If block intersects with thick region, draw block as thick.
- if (thick_start !== undefined && !(block_start > thick_end || block_end < thick_start) ) {
- var block_thick_start = Math.max(block_start, thick_start),
- // -1 b/c intervals are half-open.
- block_thick_end = Math.min(block_end, thick_end-1);
- ctx.fillRect(block_thick_start + left_offset, y_center + 1,
- block_thick_end - block_thick_start, thick_height);
- }
- }
- }
-
- // Draw label for Pack mode.
- if (mode == "Pack" && feature_start > tile_low) {
- 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 + left_offset + LABEL_SPACING, y_center + 8);
- } else {
- ctx.textAlign = "right";
- ctx.fillText(feature_name, f_start + left_offset - LABEL_SPACING, y_center + 8);
- }
- ctx.fillStyle = block_color;
- }
- }
+ }
+
+ // Draw feature.
+ if (is_overlap([feature_start, feature_end], [tile_low, tile_high]) && slot !== null) {
+ this.draw_element(ctx, tile_index, mode, feature, slot, tile_low, tile_high, w_scale, y_scale,
+ width, left_offset);
}
}
- return canvas;
+ return canvas;
}
});
@@ -2606,236 +2640,57 @@
$.extend(VcfTrack.prototype, TiledTrack.prototype, FeatureTrack.prototype, {
/**
- * Draw VcfTrack tile.
+ * Draw a VCF entry.
*/
- draw_tile: function(resolution, tile_index, parent_element, w_scale) {
- var tile_low = tile_index * DENSITY * resolution,
- tile_high = ( tile_index + 1 ) * DENSITY * resolution,
- tile_span = tile_high - tile_low;
- //console.log("drawing " + tile_low + " to " + tile_high);
-
- /*for (var k in this.data_cache.obj_cache) {
- var k_split = k.split("_"), k_low = k_split[0], k_high = k_split[1];
- if (k_low <= tile_low && k_high >= tile_high) {
- data = this.data_cache.get(k);
- break;
+ draw_element: function(ctx, mode, feature, slot, tile_low, tile_high, w_scale, y_scale, width) {
+ var feature = data[i],
+ feature_uid = feature[0],
+ feature_start = feature[1],
+ // -1 b/c intervals are half-open.
+ feature_end = feature[2] - 1,
+ feature_name = feature[3],
+ // All features need a start, end, and vertical center.
+ f_start = Math.floor( Math.max(0, (feature_start - tile_low) * w_scale) ),
+ f_end = Math.ceil( Math.min(width, Math.max(0, (feature_end - tile_low) * w_scale)) ),
+ y_center = (mode === "Dense" ? 1 : (1 + slot)) * y_scale,
+ thickness, y_start, thick_start = null, thick_end = null;
+
+ if (no_label) {
+ 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;
}
- }*/
- //
- // Get tile data; if data not available, issue get_data request and return.
- //
- var result = this.data_cache.get_data(tile_low, tile_high, this.mode);
- if (result === undefined || result === "pending" ||
- (this.mode !== "Auto" && result.dataset_type === "summary_tree")) {
- this.data_queue[ [tile_low, tile_high] ] = true;
- this.get_data(tile_low, tile_high);
- return;
- }
- //
- // Create/set/compute some useful vars.
- //
- var width = Math.ceil( tile_span * w_scale ),
- label_color = this.prefs.label_color,
- block_color = this.prefs.block_color,
- mode = this.mode,
- min_height = 25,
- no_label,
- left_offset = this.left_offset,
- slots, required_height, y_scale;
-
- var canvas = document.createElement("canvas");
- if (window.G_vmlCanvasManager) { G_vmlCanvasManager.initElement(canvas); } // EXCANVAS HACK
- canvas = $(canvas);
-
- if (result.dataset_type === "summary_tree") {
- required_height = this.summary_draw_height;
- } else if (mode === "Dense") {
- required_height = min_height;
- y_scale = DENSE_TRACK_HEIGHT;
- } else {
- // Set y_scale based on mode and result data.
- if (mode === "Squish") {
- y_scale = SQUISH_TRACK_HEIGHT;
- no_label = true;
- } else if (mode === "Pack") {
- y_scale = PACK_TRACK_HEIGHT;
- // TODO: is there data where there is no label even in pack mode?
- no_label = false;
- } else if (result.extra_info === "no_detail") { // mode == "Auto"
- y_scale = NO_DETAIL_TRACK_HEIGHT;
- no_label = true;
- } else {
- y_scale = PACK_TRACK_HEIGHT;
- no_label = false;
- }
-
- // Calculate new slots incrementally for this new chunk of data and update height if necessary.
- required_height = this.incremental_slots(w_scale, result.data, no_label, mode) * y_scale + min_height;
- slots = this.inc_slots[w_scale];
- }
-
- canvas.get(0).width = width + left_offset;
- canvas.get(0).height = required_height;
- if (result.dataset_type == "summary_tree") {
- // Increase canvas height in order to display max label.
- canvas.get(0).height += LABEL_SPACING + CHAR_HEIGHT_PX;
- }
- parent_element.parent().css("height", Math.max(this.height_px, required_height) + "px");
- // console.log(( tile_low - this.view.low ) * w_scale, tile_index, w_scale);
- var ctx = canvas.get(0).getContext("2d");
- ctx.fillStyle = block_color;
- ctx.font = this.default_font;
- ctx.textAlign = "right";
- this.container_div.find(".yaxislabel").remove();
-
- //
- // Draw summary tree. If tree is drawn, canvas is returned.
- //
- if (result.dataset_type == "summary_tree") {
- var
- // Set base Y so that max label and data do not overlap. Base Y is where rectangle bases
- // start. However, height of each rectangle is relative to required_height; hence, the
- // max rectangle is required_height.
- base_y = required_height + LABEL_SPACING + CHAR_HEIGHT_PX;
- points = result.data,
- max = result.max,
- delta_x_px = Math.ceil(result.delta * w_scale);
-
- var max_label = $("<div />").addClass('yaxislabel');
- max_label.text(max);
-
- max_label.css({ position: "absolute", top: "22px", left: "10px" });
- max_label.prependTo(this.container_div);
-
- for (var i = 0, len = points.length; i < len; i++) {
- var x = Math.floor( (points[i][0] - tile_low) * w_scale );
- var y = points[i][1];
-
- if (!y) { continue; }
- var y_px = y / max * required_height;
-
- ctx.fillStyle = "black";
- ctx.fillRect(x + left_offset, base_y - y_px, delta_x_px, y_px);
-
- // Draw number count if it can fit the number with some padding, otherwise things clump up
- var text_padding_req_x = 4;
- if (this.prefs.show_counts && (ctx.measureText(y).width + text_padding_req_x) < delta_x_px) {
- ctx.fillStyle = "#666";
- ctx.textAlign = "center";
- ctx.fillText(y, x + left_offset + (delta_x_px/2), 10);
- }
- }
- return canvas;
- }
-
- //
- // If there is a message, show it; also, return if there's no data to draw.
- // FIXME: Why is this drawn on a canvas instead of a div?
- if (result.message) {
- canvas.css({
- "border-color": "red"
- });
-
- ctx.fillStyle = "red";
- ctx.textAlign = "left";
- ctx.fillText(result.message, 100 + left_offset, y_scale);
-
- // If there's no data, return.
- if (!result.data) {
- return canvas;
+ // 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;
}
}
-
- //
- // If tile is filterable, add class to canvas.
- //
- for (var f = 0; f < this.filters.length; f++) {
- if (result.data.length && this.filters[f].applies_to(result.data[0])) {
- canvas.addClass(FILTERABLE_CLASS);
- break;
- }
- }
-
- //
- // Draw data points.
- //
- var data = result.data;
- for (var i = 0, len = data.length; i < len; i++) {
- var feature = data[i],
- feature_uid = feature[0],
- feature_start = feature[1],
- // -1 b/c intervals are half-open.
- feature_end = feature[2] - 1,
- feature_name = feature[3];
-
- // TODO: why is this necessary? Without explicitly short-circuiting it, it prevents dense mode from rendering.
- if (this.mode != "Dense" && slots[feature_uid] === undefined) {
- continue;
- }
-
- // Apply filters to feature.
- var hide_feature = false;
- var filter;
- for (var f = 0; f < this.filters.length; f++) {
- filter = this.filters[f];
- filter.update_attrs( feature );
- if ( !filter.keep( feature ) ) {
- hide_feature = true;
- break;
- }
- }
- if (hide_feature) {
- continue;
- }
-
- if (feature_start <= tile_high && feature_end >= tile_low) {
- // All features need a start, end, and vertical center.
- var f_start = Math.floor( Math.max(0, (feature_start - tile_low) * w_scale) ),
- f_end = Math.ceil( Math.min(width, Math.max(0, (feature_end - tile_low) * w_scale)) ),
- y_center = (mode === "Dense" ? 1 : (1 + slots[feature_uid])) * y_scale;
- var thickness, y_start, thick_start = null, thick_end = null;
-
-
- if (no_label) {
- 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;
- }
- }
- }
- }
- return canvas;
}
});
@@ -2847,7 +2702,7 @@
/**
* Draw a single read.
*/
- draw_read: function(ctx, w_scale, tile_low, tile_high, feature_start, cigar, orig_seq, y_center) {
+ draw_read: function(ctx, mode, w_scale, tile_low, tile_high, feature_start, cigar, orig_seq, y_center) {
ctx.textAlign = "center";
var
tile_region = [tile_low, tile_high],
@@ -2885,7 +2740,7 @@
if (seq_tile_overlap != NO_OVERLAP) {
// Draw.
var seq = orig_seq.slice(seq_offset, seq_offset + cig_len);
- if ( (this.mode === "Pack" || this.mode === "Auto") && orig_seq !== undefined && w_scale > CHAR_WIDTH_PX) {
+ if ( (mode === "Pack" || this.mode === "Auto") && orig_seq !== undefined && w_scale > CHAR_WIDTH_PX) {
ctx.fillStyle = this.prefs.block_color;
ctx.fillRect(s_start + this.left_offset, y_center + 1, s_end - s_start, 9);
ctx.fillStyle = CONNECTOR_COLOR;
@@ -2903,7 +2758,7 @@
ctx.fillRect(s_start + this.left_offset,
y_center + (this.mode != "Dense" ? 4 : 5),
s_end - s_start,
- (this.mode != "Dense" ? SQUISH_FEATURE_HEIGHT : DENSE_FEATURE_HEIGHT) );
+ (mode != "Dense" ? SQUISH_FEATURE_HEIGHT : DENSE_FEATURE_HEIGHT) );
}
}
seq_offset += cig_len;
@@ -2938,7 +2793,7 @@
var seq = orig_seq.slice(seq_offset, seq_offset + cig_len);
// X center is offset + start - <half_sequence_length>
var x_center = this.left_offset + s_start - (s_end - s_start)/2;
- if ( (this.mode === "Pack" || this.mode === "Auto") && orig_seq !== undefined && w_scale > CHAR_WIDTH_PX) {
+ if ( (mode === "Pack" || this.mode === "Auto") && orig_seq !== undefined && w_scale > CHAR_WIDTH_PX) {
// Draw sequence container.
ctx.fillStyle = "yellow";
ctx.fillRect(x_center, y_center - 9, s_end - s_start, 9);
@@ -2970,7 +2825,7 @@
ctx.fillStyle = "yellow";
// TODO: This is a pretty hack-ish way to fill rectangle based on mode.
ctx.fillRect(x_center, y_center + (this.mode != "Dense" ? 2 : 5),
- s_end - s_start, (this.mode != "Dense" ? SQUISH_FEATURE_HEIGHT : DENSE_FEATURE_HEIGHT));
+ s_end - s_start, (mode != "Dense" ? SQUISH_FEATURE_HEIGHT : DENSE_FEATURE_HEIGHT));
}
}
seq_offset += cig_len;
@@ -2992,213 +2847,61 @@
}
},
/**
- * Draw ReadTrack tile.
+ * Draw a complete read.
*/
- draw_tile: function(resolution, tile_index, parent_element, w_scale) {
- var tile_low = tile_index * DENSITY * resolution,
- tile_high = ( tile_index + 1 ) * DENSITY * resolution,
- tile_span = tile_high - tile_low;
- //console.log("ReadTrack: drawing " + tile_low + " to " + tile_high);
+ draw_element: function(ctx, tile_index, mode, feature, slot, tile_low, tile_high, w_scale, y_scale, width, left_offset) {
+ // All features need a start, end, and vertical center.
+ var
+ feature_uid = feature[0],
+ feature_start = feature[1],
+ feature_end = feature[2],
+ feature_name = feature[3],
+ f_start = Math.floor( Math.max(0, (feature_start - tile_low) * w_scale) ),
+ f_end = Math.ceil( Math.min(width, Math.max(0, (feature_end - tile_low) * w_scale)) ),
+ y_center = (mode === "Dense" ? 1 : (1 + slot)) * y_scale,
+ block_color = this.prefs.block_color,
+ label_color = this.prefs.label_color;
+
+ // Draw read.
+ ctx.fillStyle = block_color;
+ if (feature[5] instanceof Array) {
+ // Read is paired.
+ var b1_start = Math.floor( Math.max(0, (feature[4][0] - tile_low) * w_scale) ),
+ b1_end = Math.ceil( Math.min(width, Math.max(0, (feature[4][1] - tile_low) * w_scale)) ),
+ b2_start = Math.floor( Math.max(0, (feature[5][0] - tile_low) * w_scale) ),
+ b2_end = Math.ceil( Math.min(width, Math.max(0, (feature[5][1] - tile_low) * w_scale)) );
- /*for (var k in this.data_cache.obj_cache) {
- var k_split = k.split("_"), k_low = k_split[0], k_high = k_split[1];
- if (k_low <= tile_low && k_high >= tile_high) {
- data = this.data_cache.get(k);
- break;
+ // Draw left/forward read.
+ if (feature[4][1] >= tile_low && feature[4][0] <= tile_high && feature[4][2]) {
+ this.draw_read(ctx, mode, w_scale, tile_low, tile_high, feature[4][0], feature[4][2], feature[4][3], y_center);
}
- }*/
-
- //
- // Get tile data; if data not available, issue get_data request and return.
- //
- var result = this.data_cache.get_data(tile_low, tile_high, this.mode);
- if (result === undefined || result === "pending" ||
- (this.mode !== "Auto" && result.dataset_type === "summary_tree")) {
- this.data_queue[ [tile_low, tile_high] ] = true;
- this.get_data(tile_low, tile_high);
- return;
+ // Draw right/reverse read.
+ if (feature[5][1] >= tile_low && feature[5][0] <= tile_high && feature[5][2]) {
+ this.draw_read(ctx, mode, w_scale, tile_low, tile_high, feature[5][0], feature[5][2], feature[5][3], y_center);
+ }
+ // Draw connector.
+ if (b2_start > b1_end) {
+ ctx.fillStyle = CONNECTOR_COLOR;
+ //ctx.fillRect(b1_end + left_offset, y_center + 5, b2_start - b1_end, 1);
+ ctx.dashedLine(b1_end + left_offset, y_center + 5, left_offset + b2_start, y_center + 5);
+ }
+ } else {
+ // Read is single.
+ ctx.fillStyle = block_color;
+ this.draw_read(ctx, mode, w_scale, tile_low, tile_high, feature_start, feature[4], feature[5], y_center);
}
- //
- // Create/set/compute some useful vars.
- //
- var width = Math.ceil( tile_span * w_scale ),
- label_color = this.prefs.label_color,
- block_color = this.prefs.block_color,
- mode = this.mode,
- min_height = 25,
- no_label,
- left_offset = this.left_offset,
- slots, required_height, y_scale;
-
- var canvas = document.createElement("canvas");
- if (window.G_vmlCanvasManager) { G_vmlCanvasManager.initElement(canvas); } // EXCANVAS HACK
- canvas = $(canvas);
-
- if (result.dataset_type === "summary_tree") {
- required_height = this.summary_draw_height;
- } else if (mode === "Dense") {
- required_height = min_height;
- y_scale = DENSE_TRACK_HEIGHT;
- } else {
- // Set y_scale based on mode and result data.
- if (mode === "Squish") {
- y_scale = SQUISH_TRACK_HEIGHT;
- no_label = true;
- } else if (mode === "Pack") {
- y_scale = PACK_TRACK_HEIGHT;
- // TODO: is there data where there is no label even in pack mode?
- no_label = false;
- } else if (result.extra_info === "no_detail") { // mode == "Auto"
- y_scale = SQUISH_TRACK_HEIGHT;
- no_label = true;
+ if (mode === "Pack" && feature_start > tile_low) {
+ // Draw label.
+ ctx.fillStyle = this.prefs.label_color;
+ if (tile_index === 0 && f_start - ctx.measureText(feature_name).width < 0) {
+ ctx.textAlign = "left";
+ ctx.fillText(feature_name, f_end + left_offset + LABEL_SPACING, y_center + 8);
} else {
- y_scale = PACK_TRACK_HEIGHT;
- no_label = false;
+ ctx.textAlign = "right";
+ ctx.fillText(feature_name, f_start + left_offset - LABEL_SPACING, y_center + 8);
}
-
- // Calculate new slots incrementally for this new chunk of data and update height if necessary.
- required_height = this.incremental_slots(w_scale, result.data, no_label, mode) * y_scale + min_height;
- slots = this.inc_slots[w_scale];
+ ctx.fillStyle = block_color;
}
-
- canvas.get(0).width = width + left_offset;
- canvas.get(0).height = required_height;
- if (result.dataset_type == "summary_tree") {
- // Increase canvas height in order to display max label.
- canvas.get(0).height += LABEL_SPACING + CHAR_HEIGHT_PX;
- }
- parent_element.parent().css("height", Math.max(this.height_px, required_height) + "px");
- // console.log(( tile_low - this.view.low ) * w_scale, tile_index, w_scale);
- var ctx = canvas.get(0).getContext("2d");
- ctx.fillStyle = block_color;
- ctx.font = this.default_font;
- ctx.textAlign = "right";
- this.container_div.find(".yaxislabel").remove();
-
- //
- // Draw summary tree. If tree is drawn, canvas is returned.
- //
- if (result.dataset_type == "summary_tree") {
- var
- // Set base Y so that max label and data do not overlap. Base Y is where rectangle bases
- // start. However, height of each rectangle is relative to required_height; hence, the
- // max rectangle is required_height.
- base_y = required_height + LABEL_SPACING + CHAR_HEIGHT_PX;
- points = result.data,
- max = result.max,
- delta_x_px = Math.ceil(result.delta * w_scale);
-
- var max_label = $("<div />").addClass('yaxislabel');
- max_label.text(max);
-
- max_label.css({ position: "absolute", top: "22px", left: "10px" });
- max_label.prependTo(this.container_div);
-
- for (var i = 0, len = points.length; i < len; i++) {
- var x = Math.floor( (points[i][0] - tile_low) * w_scale );
- var y = points[i][1];
-
- if (!y) { continue; }
- var y_px = y / max * required_height;
-
- ctx.fillStyle = "black";
- ctx.fillRect(x + left_offset, base_y - y_px, delta_x_px, y_px);
-
- // Draw number count if it can fit the number with some padding, otherwise things clump up
- var text_padding_req_x = 4;
- if (this.prefs.show_counts && (ctx.measureText(y).width + text_padding_req_x) < delta_x_px) {
- ctx.fillStyle = "#666";
- ctx.textAlign = "center";
- ctx.fillText(y, x + left_offset + (delta_x_px/2), 10);
- }
- }
- return canvas;
- }
-
- //
- // If there is a message, show it; also, return if there's no data to draw.
- // FIXME: Why is this drawn on a canvas instead of a div?
- if (result.message) {
- canvas.css({
- "border-color": "red"
- });
-
- ctx.fillStyle = "red";
- ctx.textAlign = "left";
- ctx.fillText(result.message, 100 + left_offset, y_scale);
-
- // If there's no data, return.
- if (!result.data) {
- return canvas;
- }
- }
-
- //
- // Draw reads.
- //
- var data = result.data;
- for (var i = 0, len = data.length; i < len; i++) {
- var feature = data[i],
- feature_uid = feature[0],
- feature_start = feature[1],
- feature_end = feature[2],
- feature_name = feature[3];
-
- // TODO: why is this necessary? Without explicitly short-circuiting it, it prevents dense mode from rendering.
- if (this.mode != "Dense" && slots[feature_uid] === undefined) {
- continue;
- }
-
- if (feature_start <= tile_high && feature_end >= tile_low) {
- // All features need a start, end, and vertical center.
- var f_start = Math.floor( Math.max(0, (feature_start - tile_low) * w_scale) ),
- f_end = Math.ceil( Math.min(width, Math.max(0, (feature_end - tile_low) * w_scale)) ),
- y_center = (mode === "Dense" ? 1 : (1 + slots[feature_uid])) * y_scale;
- var thickness, y_start, thick_start = null, thick_end = null;
-
- // Draw read.
- ctx.fillStyle = block_color;
- if (feature[5] instanceof Array) {
- // Read is paired.
- var b1_start = Math.floor( Math.max(0, (feature[4][0] - tile_low) * w_scale) ),
- b1_end = Math.ceil( Math.min(width, Math.max(0, (feature[4][1] - tile_low) * w_scale)) ),
- b2_start = Math.floor( Math.max(0, (feature[5][0] - tile_low) * w_scale) ),
- b2_end = Math.ceil( Math.min(width, Math.max(0, (feature[5][1] - tile_low) * w_scale)) );
-
- // Draw left/forward read.
- if (feature[4][1] >= tile_low && feature[4][0] <= tile_high && feature[4][2]) {
- this.draw_read(ctx, w_scale, tile_low, tile_high, feature[4][0], feature[4][2], feature[4][3], y_center);
- }
- // Draw right/reverse read.
- if (feature[5][1] >= tile_low && feature[5][0] <= tile_high && feature[5][2]) {
- this.draw_read(ctx, w_scale, tile_low, tile_high, feature[5][0], feature[5][2], feature[5][3], y_center);
- }
- // Draw connector.
- if (b2_start > b1_end) {
- ctx.fillStyle = CONNECTOR_COLOR;
- //ctx.fillRect(b1_end + left_offset, y_center + 5, b2_start - b1_end, 1);
- ctx.dashedLine(b1_end + left_offset, y_center + 5, left_offset + b2_start, y_center + 5);
- }
- } else {
- // Read is single.
- ctx.fillStyle = block_color;
- this.draw_read(ctx, w_scale, tile_low, tile_high, feature_start, feature[4], feature[5], y_center);
- }
- if (mode !== "Dense" && !no_label && feature_start > tile_low) {
- // Draw label.
- ctx.fillStyle = this.prefs.label_color;
- if (tile_index === 0 && f_start - ctx.measureText(feature_name).width < 0) {
- ctx.textAlign = "left";
- ctx.fillText(feature_name, f_end + left_offset + LABEL_SPACING, y_center + 8);
- } else {
- ctx.textAlign = "right";
- ctx.fillText(feature_name, f_start + left_offset - LABEL_SPACING, y_center + 8);
- }
- ctx.fillStyle = block_color;
- }
- }
- }
- return canvas;
}
});
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/9ec73a5b31a4/
changeset: r5102:9ec73a5b31a4
user: greg
date: 2011-02-22 16:38:35
summary: (no commit message)
affected #: 2 files (173 bytes)
--- a/lib/galaxy/web/controllers/library_common.py Mon Feb 21 16:25:35 2011 -0500
+++ b/lib/galaxy/web/controllers/library_common.py Tue Feb 22 10:38:35 2011 -0500
@@ -1585,6 +1585,7 @@
message += '(%s)' % ldda.name
message += '. '
if valid_ldda_ids:
+ encoded_ldda_ids = [ trans.security.encode_id( ldda_id ) for ldda_id in valid_ldda_ids ]
folder_id = trans.security.encode_id( valid_lddas[0].library_dataset.folder.id )
trans.response.send_redirect( web.url_for( controller='library_common',
action='ldda_permissions',
@@ -1592,7 +1593,7 @@
use_panels=use_panels,
library_id=library_id,
folder_id=folder_id,
- id=",".join( valid_ldda_ids ),
+ id=",".join( encoded_ldda_ids ),
show_deleted=show_deleted,
message=util.sanitize_text( message ),
status=status ) )
--- a/templates/library/common/browse_library.mako Mon Feb 21 16:25:35 2011 -0500
+++ b/templates/library/common/browse_library.mako Tue Feb 22 10:38:35 2011 -0500
@@ -361,9 +361,7 @@
<div style="float: left; margin-left: 2px;" class="menubutton split popup" id="folder_img-${folder.id}-popup"><a class="folder-${encoded_id}-click" href="javascript:void(0);">
%if folder.deleted:
- <span class="libraryItem-error">
- ${folder.name}
- </span>
+ <span class="libraryItem-error">${folder.name}</span>
%else:
${folder.name}
%endif
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: natefoo: Update bowtie_wrapper and bowtie_color_wrapper to use test data from the external test data repository
by Bitbucket 21 Feb '11
by Bitbucket 21 Feb '11
21 Feb '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/b26e5c6ff96d/
changeset: r5101:b26e5c6ff96d
user: natefoo
date: 2011-02-21 22:25:35
summary: Update bowtie_wrapper and bowtie_color_wrapper to use test data from the external test data repository
affected #: 2 files (428 bytes)
--- a/tools/sr_mapping/bowtie_color_wrapper.xml Mon Feb 21 15:54:22 2011 -0500
+++ b/tools/sr_mapping/bowtie_color_wrapper.xml Mon Feb 21 16:25:35 2011 -0500
@@ -396,8 +396,7 @@
chrM_color needs to be the base location/name of the index files.
--><param name="genomeSource" value="indexed" />
- <!-- this is the backwards-compatible "unique value" for this index, not an actual path -->
- <param name="index" value="/galaxy/data/equCab2_chrM/bowtie_index/cs/chrM" />
+ <param name="index" value="equCab2chrM" /><param name="sPaired" value="single" /><param name="sInput1" ftype="fastqcssanger" value="bowtie_in1.fastqcssanger" /><param name="sSettingsType" value="preSet" />
@@ -466,8 +465,7 @@
chrM_base is the index files' location/base name.
--><param name="genomeSource" value="indexed" />
- <!-- this is the backwards-compatible "unique value" for this index, not an actual path -->
- <param name="index" value="/galaxy/data/equCab2_chrM/bowtie_index/cs/chrM" />
+ <param name="index" value="equCab2chrM" /><param name="sPaired" value="single" /><param name="sInput1" ftype="fastqcssanger" value="bowtie_in1.fastqcssanger" /><param name="sSettingsType" value="full" />
--- a/tools/sr_mapping/bowtie_wrapper.xml Mon Feb 21 15:54:22 2011 -0500
+++ b/tools/sr_mapping/bowtie_wrapper.xml Mon Feb 21 16:25:35 2011 -0500
@@ -379,8 +379,7 @@
chrM_base needs to be the base location/name of the index files.
--><param name="genomeSource" value="indexed" />
- <!-- this is the backwards-compatible "unique value" for this index, not an actual path -->
- <param name="index" value="/galaxy/data/equCab2_chrM/bowtie_index/chrM" />
+ <param name="index" value="equCab2chrM" /><param name="sPaired" value="single" /><param name="sInput1" ftype="fastqsanger" value="bowtie_in2.fastqsanger" /><param name="sSettingsType" value="preSet" />
@@ -448,7 +447,7 @@
--><param name="genomeSource" value="indexed" /><!-- this is the backwards-compatible "unique value" for this index, not an actual path -->
- <param name="index" value="/galaxy/data/equCab2_chrM/bowtie_index/chrM" />
+ <param name="index" value="equCab2chrM" /><param name="sPaired" value="single" /><param name="sInput1" ftype="fastqsanger" value="bowtie_in2.fastqsanger" /><param name="sSettingsType" value="full" />
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/89df419a7e21/
changeset: r5100:89df419a7e21
user: jgoecks
date: 2011-02-21 21:54:22
summary: Trackster refactoring: (a) move ReadTrack-specific code out of FeatureTrack and into ReadTrack; (b) move VCFTrack-specific code of out FeatureTrack and into VcfTTrack. This makes it easier to modify drawing for each track type but creates some repeated code in draw_tile() for different classes that needs to be cleaned up.
affected #: 2 files (13.8 KB)
--- a/lib/galaxy/visualization/tracks/data_providers.py Mon Feb 21 15:10:22 2011 -0500
+++ b/lib/galaxy/visualization/tracks/data_providers.py Mon Feb 21 15:54:22 2011 -0500
@@ -285,7 +285,7 @@
paired_pending = {}
for read in data:
if len(results) > MAX_VALS:
- message = "Only the first %s pairs are being displayed." % MAX_VALS
+ message = "Only the first %s reads are being displayed." % MAX_VALS
break
qname = read.qname
seq = read.seq
--- a/static/scripts/trackster.js Mon Feb 21 15:10:22 2011 -0500
+++ b/static/scripts/trackster.js Mon Feb 21 15:54:22 2011 -0500
@@ -2266,8 +2266,588 @@
*/
return highest_slot;
},
- // Right now this function is used only for rendering BAM reads.
- rect_or_text: function(ctx, w_scale, tile_low, tile_high, feature_start, cigar, orig_seq, y_center) {
+ /**
+ * Draw FeatureTrack tile.
+ */
+ draw_tile: function(resolution, tile_index, parent_element, w_scale) {
+ var tile_low = tile_index * DENSITY * resolution,
+ tile_high = ( tile_index + 1 ) * DENSITY * resolution,
+ tile_span = tile_high - tile_low;
+ //console.log("drawing " + tile_low + " to " + tile_high);
+
+ /*for (var k in this.data_cache.obj_cache) {
+ var k_split = k.split("_"), k_low = k_split[0], k_high = k_split[1];
+ if (k_low <= tile_low && k_high >= tile_high) {
+ data = this.data_cache.get(k);
+ break;
+ }
+ }*/
+
+ //
+ // Get tile data; if data not available, issue get_data request and return.
+ //
+ var result = this.data_cache.get_data(tile_low, tile_high, this.mode);
+ if (result === undefined || result === "pending" ||
+ (this.mode !== "Auto" && result.dataset_type === "summary_tree")) {
+ this.data_queue[ [tile_low, tile_high] ] = true;
+ this.get_data(tile_low, tile_high);
+ return;
+ }
+ //
+ // Create/set/compute some useful vars.
+ //
+ var width = Math.ceil( tile_span * w_scale ),
+ label_color = this.prefs.label_color,
+ block_color = this.prefs.block_color,
+ mode = this.mode,
+ min_height = 25,
+ no_label,
+ left_offset = this.left_offset,
+ slots, required_height, y_scale;
+
+ var canvas = document.createElement("canvas");
+ if (window.G_vmlCanvasManager) { G_vmlCanvasManager.initElement(canvas); } // EXCANVAS HACK
+ canvas = $(canvas);
+
+ if (result.dataset_type === "summary_tree") {
+ required_height = this.summary_draw_height;
+ } else if (mode === "Dense") {
+ required_height = min_height;
+ y_scale = DENSE_TRACK_HEIGHT;
+ } else {
+ // Set y_scale based on mode and result data.
+ if (mode === "Squish") {
+ y_scale = SQUISH_TRACK_HEIGHT;
+ no_label = true;
+ } else if (mode === "Pack") {
+ y_scale = PACK_TRACK_HEIGHT;
+ // TODO: is there data where there is no label even in pack mode?
+ no_label = false;
+ } else if (result.extra_info === "no_detail") { // mode == "Auto"
+ y_scale = NO_DETAIL_TRACK_HEIGHT;
+ no_label = true;
+ } else {
+ y_scale = PACK_TRACK_HEIGHT;
+ no_label = false;
+ }
+
+ // Calculate new slots incrementally for this new chunk of data and update height if necessary.
+ required_height = this.incremental_slots(w_scale, result.data, no_label, mode) * y_scale + min_height;
+ slots = this.inc_slots[w_scale];
+ }
+
+ canvas.get(0).width = width + left_offset;
+ canvas.get(0).height = required_height;
+ if (result.dataset_type == "summary_tree") {
+ // Increase canvas height in order to display max label.
+ canvas.get(0).height += LABEL_SPACING + CHAR_HEIGHT_PX;
+ }
+ parent_element.parent().css("height", Math.max(this.height_px, required_height) + "px");
+ // console.log(( tile_low - this.view.low ) * w_scale, tile_index, w_scale);
+ var ctx = canvas.get(0).getContext("2d");
+ ctx.fillStyle = block_color;
+ ctx.font = this.default_font;
+ ctx.textAlign = "right";
+ this.container_div.find(".yaxislabel").remove();
+
+ //
+ // Draw summary tree. If tree is drawn, canvas is returned.
+ //
+ if (result.dataset_type == "summary_tree") {
+ var
+ // Set base Y so that max label and data do not overlap. Base Y is where rectangle bases
+ // start. However, height of each rectangle is relative to required_height; hence, the
+ // max rectangle is required_height.
+ base_y = required_height + LABEL_SPACING + CHAR_HEIGHT_PX;
+ points = result.data,
+ max = result.max,
+ delta_x_px = Math.ceil(result.delta * w_scale);
+
+ var max_label = $("<div />").addClass('yaxislabel');
+ max_label.text(max);
+
+ max_label.css({ position: "absolute", top: "22px", left: "10px" });
+ max_label.prependTo(this.container_div);
+
+ for (var i = 0, len = points.length; i < len; i++) {
+ var x = Math.floor( (points[i][0] - tile_low) * w_scale );
+ var y = points[i][1];
+
+ if (!y) { continue; }
+ var y_px = y / max * required_height;
+
+ ctx.fillStyle = "black";
+ ctx.fillRect(x + left_offset, base_y - y_px, delta_x_px, y_px);
+
+ // Draw number count if it can fit the number with some padding, otherwise things clump up
+ var text_padding_req_x = 4;
+ if (this.prefs.show_counts && (ctx.measureText(y).width + text_padding_req_x) < delta_x_px) {
+ ctx.fillStyle = "#666";
+ ctx.textAlign = "center";
+ ctx.fillText(y, x + left_offset + (delta_x_px/2), 10);
+ }
+ }
+ return canvas;
+ }
+
+ //
+ // If there is a message, show it; also, return if there's no data to draw.
+ // FIXME: Why is this drawn on a canvas instead of a div?
+ if (result.message) {
+ canvas.css({
+ "border-color": "red"
+ });
+
+ ctx.fillStyle = "red";
+ ctx.textAlign = "left";
+ ctx.fillText(result.message, 100 + left_offset, y_scale);
+
+ // If there's no data, return.
+ if (!result.data) {
+ return canvas;
+ }
+ }
+
+ //
+ // If tile is filterable, add class to canvas.
+ //
+ for (var f = 0; f < this.filters.length; f++) {
+ if (result.data.length && this.filters[f].applies_to(result.data[0])) {
+ canvas.addClass(FILTERABLE_CLASS);
+ break;
+ }
+ }
+
+ //
+ // Draw data points.
+ //
+ var data = result.data;
+
+ // Set mode in Auto; never use Dense, so decide b/t Squish and Pack.
+ if (mode == "Auto" && data.length > 0) {
+ if (feature.length <= 4) {
+ mode = "Squish";
+ }
+ else {
+ mode = "Pack";
+ }
+ }
+
+ for (var i = 0, len = data.length; i < len; i++) {
+ var feature = data[i],
+ feature_uid = feature[0],
+ feature_start = feature[1],
+ // -1 b/c intervals are half-open.
+ feature_end = feature[2] - 1,
+ feature_name = feature[3];
+
+ // TODO: why is this necessary? Without explicitly short-circuiting it, it prevents dense mode from rendering.
+ if (this.mode != "Dense" && slots[feature_uid] === undefined) {
+ continue;
+ }
+
+ // Apply filters to feature.
+ var hide_feature = false;
+ var filter;
+ for (var f = 0; f < this.filters.length; f++) {
+ filter = this.filters[f];
+ filter.update_attrs( feature );
+ if ( !filter.keep( feature ) ) {
+ hide_feature = true;
+ break;
+ }
+ }
+ if (hide_feature) {
+ continue;
+ }
+
+ if (feature_start <= tile_high && feature_end >= tile_low) {
+ // All features need a start, end, and vertical center.
+ var f_start = Math.floor( Math.max(0, (feature_start - tile_low) * w_scale) ),
+ f_end = Math.ceil( Math.min(width, Math.max(0, (feature_end - tile_low) * w_scale)) ),
+ y_center = (mode === "Dense" ? 1 : (1 + slots[feature_uid])) * y_scale;
+ var thickness, y_start, thick_start = null, thick_end = null;
+
+ //
+ // There are really four modes for interval indices:
+ // dense, no_detail, squish, pack.
+ //
+
+ // Dense mode displays the same for all data.
+ if (mode == "Dense") {
+ ctx.fillStyle = block_color;
+ ctx.fillRect(f_start + left_offset, y_center + 5, f_end - f_start, DENSE_FEATURE_HEIGHT);
+ }
+ // Mode is either Squish or Pack:
+ else if (feature.length <= 4) {
+ // No details for feature, so only one way to display.
+ ctx.fillStyle = block_color;
+ // TODO: what should width be here?
+ ctx.fillRect(f_start + left_offset, y_center + 5, f_end - f_start, DENSE_FEATURE_HEIGHT);
+ } else {
+ // Feature has details.
+ var feature_strand = feature[5],
+ feature_ts = feature[6],
+ feature_te = feature[7],
+ feature_blocks = feature[8];
+
+ if (feature_ts && feature_te) {
+ thick_start = Math.floor( Math.max(0, (feature_ts - tile_low) * w_scale) );
+ thick_end = Math.ceil( Math.min(width, Math.max(0, (feature_te - tile_low) * w_scale)) );
+ }
+
+ // Set vars that depend on mode.
+ var thin_height, thick_height;
+ if (mode == "Squish") {
+ thin_height = 1;
+ thick_height = SQUISH_FEATURE_HEIGHT;
+ }
+ else { // mode == "Pack"
+ thin_height = 5;
+ thick_height = PACK_FEATURE_HEIGHT;
+ }
+
+ // Draw feature/feature blocks + connectors.
+ if (!feature_blocks) {
+ // If there are no blocks, treat the feature as one big exon.
+ if ( feature.strand ) {
+ if (feature.strand == "+") {
+ ctx.fillStyle = RIGHT_STRAND_INV;
+ } else if (feature.strand == "-") {
+ ctx.fillStyle = LEFT_STRAND_INV;
+ }
+ }
+ else { // No strand.
+ ctx.fillStyle = CONNECTOR_COLOR;
+ }
+ ctx.fillRect(f_start + left_offset, y_center + (thick_height-thin_height)/2 + 1,
+ f_end - f_start, thick_height);
+ }
+ else {
+ // There are feature blocks and mode is either Squish or Pack.
+ //
+ // Approach: (a) draw whole feature as connector/intron and (b) draw blocks as
+ // needed. This ensures that whole feature, regardless of whether it starts with
+ // a block, is visible.
+ //
+
+ // Draw whole feature as connector/intron.
+ var cur_y_center, cur_height;
+ if (mode == "Squish") {
+ ctx.fillStyle = CONNECTOR_COLOR;
+ cur_y_center = y_center + Math.floor(SQUISH_FEATURE_HEIGHT/2) + 1;
+ cur_height = 1;
+ }
+ else { // mode == "Pack"
+ if (feature_strand) {
+ var cur_y_center = y_center;
+ var cur_height = thick_height;
+ if (feature_strand == "+") {
+ ctx.fillStyle = RIGHT_STRAND;
+ } else if (feature_strand == "-") {
+ ctx.fillStyle = LEFT_STRAND;
+ }
+ }
+ else {
+ ctx.fillStyle = CONNECTOR_COLOR;
+ cur_y_center += (SQUISH_FEATURE_HEIGHT/2) + 1;
+ cur_height = 1;
+ }
+ }
+ ctx.fillRect(f_start + left_offset, cur_y_center, f_end - f_start, cur_height);
+
+ for (var k = 0, k_len = feature_blocks.length; k < k_len; k++) {
+ var block = feature_blocks[k],
+ block_start = Math.floor( Math.max(0, (block[0] - tile_low) * w_scale) ),
+ block_end = Math.ceil( Math.min(width, Math.max((block[1] - tile_low) * w_scale)) );
+
+ // Skip drawing if block not on tile.
+ if (block_start > block_end) { continue; }
+
+ // Draw thin block.
+ ctx.fillStyle = block_color;
+ ctx.fillRect(block_start + left_offset, y_center + (thick_height-thin_height)/2 + 1,
+ block_end - block_start, thin_height);
+
+ // If block intersects with thick region, draw block as thick.
+ if (thick_start !== undefined && !(block_start > thick_end || block_end < thick_start) ) {
+ var block_thick_start = Math.max(block_start, thick_start),
+ // -1 b/c intervals are half-open.
+ block_thick_end = Math.min(block_end, thick_end-1);
+ ctx.fillRect(block_thick_start + left_offset, y_center + 1,
+ block_thick_end - block_thick_start, thick_height);
+ }
+ }
+ }
+
+ // Draw label for Pack mode.
+ if (mode == "Pack" && feature_start > tile_low) {
+ 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 + left_offset + LABEL_SPACING, y_center + 8);
+ } else {
+ ctx.textAlign = "right";
+ ctx.fillText(feature_name, f_start + left_offset - LABEL_SPACING, y_center + 8);
+ }
+ ctx.fillStyle = block_color;
+ }
+ }
+ }
+ }
+ return canvas;
+ }
+});
+
+var VcfTrack = function(name, view, hda_ldda, dataset_id, prefs, filters) {
+ FeatureTrack.call(this, name, view, hda_ldda, dataset_id, prefs, filters);
+ this.track_type = "VcfTrack";
+};
+
+$.extend(VcfTrack.prototype, TiledTrack.prototype, FeatureTrack.prototype, {
+ /**
+ * Draw VcfTrack tile.
+ */
+ draw_tile: function(resolution, tile_index, parent_element, w_scale) {
+ var tile_low = tile_index * DENSITY * resolution,
+ tile_high = ( tile_index + 1 ) * DENSITY * resolution,
+ tile_span = tile_high - tile_low;
+ //console.log("drawing " + tile_low + " to " + tile_high);
+
+ /*for (var k in this.data_cache.obj_cache) {
+ var k_split = k.split("_"), k_low = k_split[0], k_high = k_split[1];
+ if (k_low <= tile_low && k_high >= tile_high) {
+ data = this.data_cache.get(k);
+ break;
+ }
+ }*/
+
+ //
+ // Get tile data; if data not available, issue get_data request and return.
+ //
+ var result = this.data_cache.get_data(tile_low, tile_high, this.mode);
+ if (result === undefined || result === "pending" ||
+ (this.mode !== "Auto" && result.dataset_type === "summary_tree")) {
+ this.data_queue[ [tile_low, tile_high] ] = true;
+ this.get_data(tile_low, tile_high);
+ return;
+ }
+ //
+ // Create/set/compute some useful vars.
+ //
+ var width = Math.ceil( tile_span * w_scale ),
+ label_color = this.prefs.label_color,
+ block_color = this.prefs.block_color,
+ mode = this.mode,
+ min_height = 25,
+ no_label,
+ left_offset = this.left_offset,
+ slots, required_height, y_scale;
+
+ var canvas = document.createElement("canvas");
+ if (window.G_vmlCanvasManager) { G_vmlCanvasManager.initElement(canvas); } // EXCANVAS HACK
+ canvas = $(canvas);
+
+ if (result.dataset_type === "summary_tree") {
+ required_height = this.summary_draw_height;
+ } else if (mode === "Dense") {
+ required_height = min_height;
+ y_scale = DENSE_TRACK_HEIGHT;
+ } else {
+ // Set y_scale based on mode and result data.
+ if (mode === "Squish") {
+ y_scale = SQUISH_TRACK_HEIGHT;
+ no_label = true;
+ } else if (mode === "Pack") {
+ y_scale = PACK_TRACK_HEIGHT;
+ // TODO: is there data where there is no label even in pack mode?
+ no_label = false;
+ } else if (result.extra_info === "no_detail") { // mode == "Auto"
+ y_scale = NO_DETAIL_TRACK_HEIGHT;
+ no_label = true;
+ } else {
+ y_scale = PACK_TRACK_HEIGHT;
+ no_label = false;
+ }
+
+ // Calculate new slots incrementally for this new chunk of data and update height if necessary.
+ required_height = this.incremental_slots(w_scale, result.data, no_label, mode) * y_scale + min_height;
+ slots = this.inc_slots[w_scale];
+ }
+
+ canvas.get(0).width = width + left_offset;
+ canvas.get(0).height = required_height;
+ if (result.dataset_type == "summary_tree") {
+ // Increase canvas height in order to display max label.
+ canvas.get(0).height += LABEL_SPACING + CHAR_HEIGHT_PX;
+ }
+ parent_element.parent().css("height", Math.max(this.height_px, required_height) + "px");
+ // console.log(( tile_low - this.view.low ) * w_scale, tile_index, w_scale);
+ var ctx = canvas.get(0).getContext("2d");
+ ctx.fillStyle = block_color;
+ ctx.font = this.default_font;
+ ctx.textAlign = "right";
+ this.container_div.find(".yaxislabel").remove();
+
+ //
+ // Draw summary tree. If tree is drawn, canvas is returned.
+ //
+ if (result.dataset_type == "summary_tree") {
+ var
+ // Set base Y so that max label and data do not overlap. Base Y is where rectangle bases
+ // start. However, height of each rectangle is relative to required_height; hence, the
+ // max rectangle is required_height.
+ base_y = required_height + LABEL_SPACING + CHAR_HEIGHT_PX;
+ points = result.data,
+ max = result.max,
+ delta_x_px = Math.ceil(result.delta * w_scale);
+
+ var max_label = $("<div />").addClass('yaxislabel');
+ max_label.text(max);
+
+ max_label.css({ position: "absolute", top: "22px", left: "10px" });
+ max_label.prependTo(this.container_div);
+
+ for (var i = 0, len = points.length; i < len; i++) {
+ var x = Math.floor( (points[i][0] - tile_low) * w_scale );
+ var y = points[i][1];
+
+ if (!y) { continue; }
+ var y_px = y / max * required_height;
+
+ ctx.fillStyle = "black";
+ ctx.fillRect(x + left_offset, base_y - y_px, delta_x_px, y_px);
+
+ // Draw number count if it can fit the number with some padding, otherwise things clump up
+ var text_padding_req_x = 4;
+ if (this.prefs.show_counts && (ctx.measureText(y).width + text_padding_req_x) < delta_x_px) {
+ ctx.fillStyle = "#666";
+ ctx.textAlign = "center";
+ ctx.fillText(y, x + left_offset + (delta_x_px/2), 10);
+ }
+ }
+ return canvas;
+ }
+
+ //
+ // If there is a message, show it; also, return if there's no data to draw.
+ // FIXME: Why is this drawn on a canvas instead of a div?
+ if (result.message) {
+ canvas.css({
+ "border-color": "red"
+ });
+
+ ctx.fillStyle = "red";
+ ctx.textAlign = "left";
+ ctx.fillText(result.message, 100 + left_offset, y_scale);
+
+ // If there's no data, return.
+ if (!result.data) {
+ return canvas;
+ }
+ }
+
+ //
+ // If tile is filterable, add class to canvas.
+ //
+ for (var f = 0; f < this.filters.length; f++) {
+ if (result.data.length && this.filters[f].applies_to(result.data[0])) {
+ canvas.addClass(FILTERABLE_CLASS);
+ break;
+ }
+ }
+
+ //
+ // Draw data points.
+ //
+ var data = result.data;
+ for (var i = 0, len = data.length; i < len; i++) {
+ var feature = data[i],
+ feature_uid = feature[0],
+ feature_start = feature[1],
+ // -1 b/c intervals are half-open.
+ feature_end = feature[2] - 1,
+ feature_name = feature[3];
+
+ // TODO: why is this necessary? Without explicitly short-circuiting it, it prevents dense mode from rendering.
+ if (this.mode != "Dense" && slots[feature_uid] === undefined) {
+ continue;
+ }
+
+ // Apply filters to feature.
+ var hide_feature = false;
+ var filter;
+ for (var f = 0; f < this.filters.length; f++) {
+ filter = this.filters[f];
+ filter.update_attrs( feature );
+ if ( !filter.keep( feature ) ) {
+ hide_feature = true;
+ break;
+ }
+ }
+ if (hide_feature) {
+ continue;
+ }
+
+ if (feature_start <= tile_high && feature_end >= tile_low) {
+ // All features need a start, end, and vertical center.
+ var f_start = Math.floor( Math.max(0, (feature_start - tile_low) * w_scale) ),
+ f_end = Math.ceil( Math.min(width, Math.max(0, (feature_end - tile_low) * w_scale)) ),
+ y_center = (mode === "Dense" ? 1 : (1 + slots[feature_uid])) * y_scale;
+ var thickness, y_start, thick_start = null, thick_end = null;
+
+
+ if (no_label) {
+ 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;
+ }
+ }
+ }
+ }
+ return canvas;
+ }
+});
+
+var ReadTrack = function (name, view, hda_ldda, dataset_id, prefs, filters) {
+ FeatureTrack.call(this, name, view, hda_ldda, dataset_id, prefs, filters);
+ this.track_type = "ReadTrack";
+};
+$.extend(ReadTrack.prototype, TiledTrack.prototype, FeatureTrack.prototype, {
+ /**
+ * Draw a single read.
+ */
+ draw_read: function(ctx, w_scale, tile_low, tile_high, feature_start, cigar, orig_seq, y_center) {
ctx.textAlign = "center";
var
tile_region = [tile_low, tile_high],
@@ -2411,11 +2991,14 @@
ctx.drawDownwardEquilateralTriangle(item[0], item[1], item[2]);
}
},
+ /**
+ * Draw ReadTrack tile.
+ */
draw_tile: function(resolution, tile_index, parent_element, w_scale) {
var tile_low = tile_index * DENSITY * resolution,
tile_high = ( tile_index + 1 ) * DENSITY * resolution,
tile_span = tile_high - tile_low;
- //console.log("drawing " + tile_low + " to " + tile_high);
+ //console.log("ReadTrack: drawing " + tile_low + " to " + tile_high);
/*for (var k in this.data_cache.obj_cache) {
var k_split = k.split("_"), k_low = k_split[0], k_high = k_split[1];
@@ -2466,7 +3049,7 @@
// TODO: is there data where there is no label even in pack mode?
no_label = false;
} else if (result.extra_info === "no_detail") { // mode == "Auto"
- y_scale = (result.track_type === "bai" ? SQUISH_TRACK_HEIGHT : NO_DETAIL_TRACK_HEIGHT);
+ y_scale = SQUISH_TRACK_HEIGHT;
no_label = true;
} else {
y_scale = PACK_TRACK_HEIGHT;
@@ -2532,9 +3115,8 @@
return canvas;
}
-
//
- // Show message. If there is a message, return canvas.
+ // If there is a message, show it; also, return if there's no data to draw.
// FIXME: Why is this drawn on a canvas instead of a div?
if (result.message) {
canvas.css({
@@ -2551,21 +3133,10 @@
}
}
- //
- // If tile is filterable, add class to canvas.
//
- for (var f = 0; f < this.filters.length; f++) {
- if (result.data.length && this.filters[f].applies_to(result.data[0])) {
- canvas.addClass(FILTERABLE_CLASS);
- break;
- }
- }
-
- //
- // Draw data points.
+ // Draw reads.
//
var data = result.data;
- var j = 0;
for (var i = 0, len = data.length; i < len; i++) {
var feature = data[i],
feature_uid = feature[0],
@@ -2577,268 +3148,60 @@
if (this.mode != "Dense" && slots[feature_uid] === undefined) {
continue;
}
-
- // Apply filters to feature.
- var hide_feature = false;
- var filter;
- for (var f = 0; f < this.filters.length; f++) {
- filter = this.filters[f];
- filter.update_attrs( feature );
- if ( !filter.keep( feature ) ) {
- hide_feature = true;
- break;
- }
- }
- if (hide_feature) {
- continue;
- }
-
+
if (feature_start <= tile_high && feature_end >= tile_low) {
- // -1 b/c intervals are half-open.
- if (result.dataset_type == "interval_index") {
- feature_end -= 1;
- }
-
// All features need a start, end, and vertical center.
var f_start = Math.floor( Math.max(0, (feature_start - tile_low) * w_scale) ),
f_end = Math.ceil( Math.min(width, Math.max(0, (feature_end - tile_low) * w_scale)) ),
y_center = (mode === "Dense" ? 1 : (1 + slots[feature_uid])) * y_scale;
var thickness, y_start, thick_start = null, thick_end = null;
- // BAM/read drawing.
- if (result.dataset_type === "bai") {
+ // Draw read.
+ ctx.fillStyle = block_color;
+ if (feature[5] instanceof Array) {
+ // Read is paired.
+ var b1_start = Math.floor( Math.max(0, (feature[4][0] - tile_low) * w_scale) ),
+ b1_end = Math.ceil( Math.min(width, Math.max(0, (feature[4][1] - tile_low) * w_scale)) ),
+ b2_start = Math.floor( Math.max(0, (feature[5][0] - tile_low) * w_scale) ),
+ b2_end = Math.ceil( Math.min(width, Math.max(0, (feature[5][1] - tile_low) * w_scale)) );
+
+ // Draw left/forward read.
+ if (feature[4][1] >= tile_low && feature[4][0] <= tile_high && feature[4][2]) {
+ this.draw_read(ctx, w_scale, tile_low, tile_high, feature[4][0], feature[4][2], feature[4][3], y_center);
+ }
+ // Draw right/reverse read.
+ if (feature[5][1] >= tile_low && feature[5][0] <= tile_high && feature[5][2]) {
+ this.draw_read(ctx, w_scale, tile_low, tile_high, feature[5][0], feature[5][2], feature[5][3], y_center);
+ }
+ // Draw connector.
+ if (b2_start > b1_end) {
+ ctx.fillStyle = CONNECTOR_COLOR;
+ //ctx.fillRect(b1_end + left_offset, y_center + 5, b2_start - b1_end, 1);
+ ctx.dashedLine(b1_end + left_offset, y_center + 5, left_offset + b2_start, y_center + 5);
+ }
+ } else {
+ // Read is single.
ctx.fillStyle = block_color;
- if (feature[5] instanceof Array) {
- // Read is paired.
- var b1_start = Math.floor( Math.max(0, (feature[4][0] - tile_low) * w_scale) ),
- b1_end = Math.ceil( Math.min(width, Math.max(0, (feature[4][1] - tile_low) * w_scale)) ),
- b2_start = Math.floor( Math.max(0, (feature[5][0] - tile_low) * w_scale) ),
- b2_end = Math.ceil( Math.min(width, Math.max(0, (feature[5][1] - tile_low) * w_scale)) );
-
- // Draw left/forward read.
- if (feature[4][1] >= tile_low && feature[4][0] <= tile_high && feature[4][2]) {
- this.rect_or_text(ctx, w_scale, tile_low, tile_high, feature[4][0], feature[4][2], feature[4][3], y_center);
- }
- // Draw right/reverse read.
- if (feature[5][1] >= tile_low && feature[5][0] <= tile_high && feature[5][2]) {
- this.rect_or_text(ctx, w_scale, tile_low, tile_high, feature[5][0], feature[5][2], feature[5][3], y_center);
- }
- // Draw connector.
- if (b2_start > b1_end) {
- ctx.fillStyle = CONNECTOR_COLOR;
- //ctx.fillRect(b1_end + left_offset, y_center + 5, b2_start - b1_end, 1);
- ctx.dashedLine(b1_end + left_offset, y_center + 5, left_offset + b2_start, y_center + 5);
- }
+ this.draw_read(ctx, w_scale, tile_low, tile_high, feature_start, feature[4], feature[5], y_center);
+ }
+ if (mode !== "Dense" && !no_label && feature_start > tile_low) {
+ // Draw label.
+ ctx.fillStyle = this.prefs.label_color;
+ if (tile_index === 0 && f_start - ctx.measureText(feature_name).width < 0) {
+ ctx.textAlign = "left";
+ ctx.fillText(feature_name, f_end + left_offset + LABEL_SPACING, y_center + 8);
} else {
- // Read is single.
- ctx.fillStyle = block_color;
- this.rect_or_text(ctx, w_scale, tile_low, tile_high, feature_start, feature[4], feature[5], y_center);
+ ctx.textAlign = "right";
+ ctx.fillText(feature_name, f_start + left_offset - LABEL_SPACING, y_center + 8);
}
- if (mode !== "Dense" && !no_label && feature_start > tile_low) {
- // Draw label.
- ctx.fillStyle = this.prefs.label_color;
- if (tile_index === 0 && f_start - ctx.measureText(feature_name).width < 0) {
- ctx.textAlign = "left";
- ctx.fillText(feature_name, f_end + left_offset + LABEL_SPACING, y_center + 8);
- } else {
- ctx.textAlign = "right";
- ctx.fillText(feature_name, f_start + left_offset - LABEL_SPACING, y_center + 8);
- }
- ctx.fillStyle = block_color;
- }
+ ctx.fillStyle = block_color;
}
- // Interval index drawing.
- else if (result.dataset_type === "interval_index") {
- //
- // There are really four modes for interval indices:
- // dense, no_detail, squish, pack.
- //
-
- // TODO: move this code out of loop.
- // Set mode in Auto
- if (mode == "Auto") {
- // Never use dense when in auto mode.
- // TODO: decide when to use squish and when to use pack.
- if (feature.length <= 4) {
- mode = "Squish";
- }
- else {
- mode = "Pack";
- }
- }
-
- // Dense mode displays the same for all data.
- if (mode == "Dense") {
- ctx.fillStyle = block_color;
- ctx.fillRect(f_start + left_offset, y_center + 5, f_end - f_start, DENSE_FEATURE_HEIGHT);
- }
- // Mode is either Squish or Pack:
- else if (feature.length <= 4) {
- // No details for feature, so only one way to display.
- ctx.fillStyle = block_color;
- // TODO: what should width be here?
- ctx.fillRect(f_start + left_offset, y_center + 5, f_end - f_start, DENSE_FEATURE_HEIGHT);
- } else {
- // Feature has details.
- var feature_strand = feature[5],
- feature_ts = feature[6],
- feature_te = feature[7],
- feature_blocks = feature[8];
-
- if (feature_ts && feature_te) {
- thick_start = Math.floor( Math.max(0, (feature_ts - tile_low) * w_scale) );
- thick_end = Math.ceil( Math.min(width, Math.max(0, (feature_te - tile_low) * w_scale)) );
- }
-
- // Set vars that depend on mode.
- var thin_height, thick_height;
- if (mode == "Squish") {
- thin_height = 1;
- thick_height = SQUISH_FEATURE_HEIGHT;
- }
- else { // mode == "Pack"
- thin_height = 5;
- thick_height = PACK_FEATURE_HEIGHT;
- }
-
- // Draw feature/feature blocks + connectors.
- if (!feature_blocks) {
- // If there are no blocks, treat the feature as one big exon.
- if ( feature.strand ) {
- if (feature.strand == "+") {
- ctx.fillStyle = RIGHT_STRAND_INV;
- } else if (feature.strand == "-") {
- ctx.fillStyle = LEFT_STRAND_INV;
- }
- }
- else { // No strand.
- ctx.fillStyle = CONNECTOR_COLOR;
- }
- ctx.fillRect(f_start + left_offset, y_center + (thick_height-thin_height)/2 + 1,
- f_end - f_start, thick_height);
- }
- else {
- // There are feature blocks and mode is either Squish or Pack.
- //
- // Approach: (a) draw whole feature as connector/intron and (b) draw blocks as
- // needed. This ensures that whole feature, regardless of whether it starts with
- // a block, is visible.
- //
-
- // Draw whole feature as connector/intron.
- var cur_y_center, cur_height;
- if (mode == "Squish") {
- ctx.fillStyle = CONNECTOR_COLOR;
- cur_y_center = y_center + Math.floor(SQUISH_FEATURE_HEIGHT/2) + 1;
- cur_height = 1;
- }
- else { // mode == "Pack"
- if (feature_strand) {
- var cur_y_center = y_center;
- var cur_height = thick_height;
- if (feature_strand == "+") {
- ctx.fillStyle = RIGHT_STRAND;
- } else if (feature_strand == "-") {
- ctx.fillStyle = LEFT_STRAND;
- }
- }
- else {
- ctx.fillStyle = CONNECTOR_COLOR;
- cur_y_center += (SQUISH_FEATURE_HEIGHT/2) + 1;
- cur_height = 1;
- }
- }
- ctx.fillRect(f_start + left_offset, cur_y_center, f_end - f_start, cur_height);
-
- for (var k = 0, k_len = feature_blocks.length; k < k_len; k++) {
- var block = feature_blocks[k],
- block_start = Math.floor( Math.max(0, (block[0] - tile_low) * w_scale) ),
- block_end = Math.ceil( Math.min(width, Math.max((block[1] - tile_low) * w_scale)) );
-
- // Skip drawing if block not on tile.
- if (block_start > block_end) { continue; }
-
- // Draw thin block.
- ctx.fillStyle = block_color;
- ctx.fillRect(block_start + left_offset, y_center + (thick_height-thin_height)/2 + 1,
- block_end - block_start, thin_height);
-
- // If block intersects with thick region, draw block as thick.
- if (thick_start !== undefined && !(block_start > thick_end || block_end < thick_start) ) {
- var block_thick_start = Math.max(block_start, thick_start),
- // -1 b/c intervals are half-open.
- block_thick_end = Math.min(block_end, thick_end-1);
- ctx.fillRect(block_thick_start + left_offset, y_center + 1,
- block_thick_end - block_thick_start, thick_height);
- }
- }
- }
-
- // Draw label for Pack mode.
- if (mode == "Pack" && feature_start > tile_low) {
- 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 + left_offset + LABEL_SPACING, y_center + 8);
- } else {
- ctx.textAlign = "right";
- ctx.fillText(feature_name, f_start + left_offset - LABEL_SPACING, y_center + 8);
- }
- ctx.fillStyle = block_color;
- }
- }
- } else if (result.dataset_type === 'vcf') {
- // VCF track.
- if (no_label) {
- 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++;
}
}
return canvas;
}
});
-var ReadTrack = function (name, view, hda_ldda, dataset_id, prefs, filters) {
- FeatureTrack.call(this, name, view, hda_ldda, dataset_id, prefs, filters);
- this.track_type = "ReadTrack";
-};
-$.extend( ReadTrack.prototype, TiledTrack.prototype, FeatureTrack.prototype, {});
-
/**
* Feature track that displays data generated from tool.
*/
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: greg: Fix the folder popup menu when browsing a deleted folder in a data library, and fis the broken display of deleted library items.
by Bitbucket 21 Feb '11
by Bitbucket 21 Feb '11
21 Feb '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/ca53c664778e/
changeset: r5099:ca53c664778e
user: greg
date: 2011-02-21 21:10:22
summary: Fix the folder popup menu when browsing a deleted folder in a data library, and fis the broken display of deleted library items.
affected #: 1 file (153 bytes)
--- a/templates/library/common/browse_library.mako Mon Feb 21 14:00:39 2011 -0500
+++ b/templates/library/common/browse_library.mako Mon Feb 21 15:10:22 2011 -0500
@@ -357,55 +357,55 @@
><td style="padding-left: ${folder_pad}px;"><input type="checkbox" class="folderCheckbox"/>
- %if folder.deleted:
- <span class="libraryItem-error">
- %endif
- <span class="expandLink folder-${encoded_id}-click"><span class="rowIcon"></span>
+ <span class="expandLink folder-${encoded_id}-click"><div style="float: left; margin-left: 2px;" class="menubutton split popup" id="folder_img-${folder.id}-popup">
- <a class="folder-${encoded_id}-click" href="javascript:void(0);">${folder.name}</a>
+ <a class="folder-${encoded_id}-click" href="javascript:void(0);">
+ %if folder.deleted:
+ <span class="libraryItem-error">
+ ${folder.name}
+ </span>
+ %else:
+ ${folder.name}
+ %endif
+ </a></div>
- %if folder.deleted:
- </span>
- %endif
- %if not branch_deleted( folder ):
- %if not library.deleted:
- <div popupmenu="folder_img-${folder.id}-popup">
- %if not branch_deleted( folder ) and can_add:
- <a class="action-button" href="${h.url_for( controller='library_common', action='upload_library_dataset', cntrller=cntrller, library_id=trans.security.encode_id( library.id ), folder_id=trans.security.encode_id( folder.id ), use_panels=use_panels, show_deleted=show_deleted )}">Add datasets</a>
- <a class="action-button" href="${h.url_for( controller='library_common', action='create_folder', cntrller=cntrller, parent_id=trans.security.encode_id( folder.id ), library_id=trans.security.encode_id( library.id ), use_panels=use_panels, show_deleted=show_deleted )}">Add sub-folder</a>
- %endif
- %if not branch_deleted( folder ):
- %if self.has_accessible_datasets:
- <a class="action-button" href="${h.url_for( controller='library_common', action='import_datasets_to_histories', cntrller=cntrller, library_id=trans.security.encode_id( library.id ), folder_id=trans.security.encode_id( folder.id ), use_panels=use_panels, show_deleted=show_deleted )}">Select datasets for import into selected histories</a>
- %endif
- %if can_modify:
- <a class="action-button" href="${h.url_for( controller='library_common', action='folder_info', cntrller=cntrller, id=trans.security.encode_id( folder.id ), library_id=trans.security.encode_id( library.id ), use_panels=use_panels, show_deleted=show_deleted )}">Edit information</a>
- %else:
- <a class="action-button" class="view-info" href="${h.url_for( controller='library_common', action='folder_info', cntrller=cntrller, id=trans.security.encode_id( folder.id ), library_id=trans.security.encode_id( library.id ), use_panels=use_panels, show_deleted=show_deleted )}">View information</a>
- %endif
- %endif
- %if not branch_deleted( folder ) and can_modify and not info_association:
- <a class="action-button" href="${h.url_for( controller='library_common', action='add_template', cntrller=cntrller, item_type='folder', form_type=form_type, library_id=trans.security.encode_id( library.id ), folder_id=trans.security.encode_id( folder.id ), use_panels=use_panels, show_deleted=show_deleted )}">Use template</a>
- %endif
- %if not branch_deleted( folder ) and can_modify and info_association:
- <a class="action-button" href="${h.url_for( controller='library_common', action='edit_template', cntrller=cntrller, item_type='folder', form_type=form_type, library_id=trans.security.encode_id( library.id ), folder_id=trans.security.encode_id( folder.id ), use_panels=use_panels, show_deleted=show_deleted )}">Edit template</a>
- <a class="action-button" href="${h.url_for( controller='library_common', action='delete_template', cntrller=cntrller, item_type='folder', form_type=form_type, library_id=trans.security.encode_id( library.id ), folder_id=trans.security.encode_id( folder.id ), use_panels=use_panels, show_deleted=show_deleted )}">Unuse template</a>
- %endif
- %if not branch_deleted( folder ) and can_manage:
- %if not trans.app.security_agent.folder_is_public( folder ):
- <a class="action-button" href="${h.url_for( controller='library_common', action='make_library_item_public', cntrller=cntrller, library_id=trans.security.encode_id( library.id ), item_type='folder', id=trans.security.encode_id( folder.id ), use_panels=use_panels, show_deleted=show_deleted )}">Make public</a>
- %endif
- <a class="action-button" href="${h.url_for( controller='library_common', action='folder_permissions', cntrller=cntrller, id=trans.security.encode_id( folder.id ), library_id=trans.security.encode_id( library.id ), use_panels=use_panels, show_deleted=show_deleted )}">Edit permissions</a>
+ %if not library.deleted:
+ <div popupmenu="folder_img-${folder.id}-popup">
+ %if not branch_deleted( folder ) and can_add:
+ <a class="action-button" href="${h.url_for( controller='library_common', action='upload_library_dataset', cntrller=cntrller, library_id=trans.security.encode_id( library.id ), folder_id=trans.security.encode_id( folder.id ), use_panels=use_panels, show_deleted=show_deleted )}">Add datasets</a>
+ <a class="action-button" href="${h.url_for( controller='library_common', action='create_folder', cntrller=cntrller, parent_id=trans.security.encode_id( folder.id ), library_id=trans.security.encode_id( library.id ), use_panels=use_panels, show_deleted=show_deleted )}">Add sub-folder</a>
+ %endif
+ %if not branch_deleted( folder ):
+ %if self.has_accessible_datasets:
+ <a class="action-button" href="${h.url_for( controller='library_common', action='import_datasets_to_histories', cntrller=cntrller, library_id=trans.security.encode_id( library.id ), folder_id=trans.security.encode_id( folder.id ), use_panels=use_panels, show_deleted=show_deleted )}">Select datasets for import into selected histories</a>
%endif
%if can_modify:
- %if not library.deleted and not folder.deleted:
- <a class="action-button" confirm="Click OK to delete the folder '${folder.name}.'" href="${h.url_for( controller='library_common', action='delete_library_item', cntrller=cntrller, library_id=trans.security.encode_id( library.id ), item_id=trans.security.encode_id( folder.id ), item_type='folder', show_deleted=show_deleted )}">Delete this folder</a>
- %elif not library.deleted and folder.deleted and not folder.purged:
- <a class="action-button" href="${h.url_for( controller='library_common', action='undelete_library_item', cntrller=cntrller, library_id=trans.security.encode_id( library.id ), item_id=trans.security.encode_id( folder.id ), item_type='folder', show_deleted=show_deleted )}">Undelete this folder</a>
- %endif
+ <a class="action-button" href="${h.url_for( controller='library_common', action='folder_info', cntrller=cntrller, id=trans.security.encode_id( folder.id ), library_id=trans.security.encode_id( library.id ), use_panels=use_panels, show_deleted=show_deleted )}">Edit information</a>
+ %else:
+ <a class="action-button" class="view-info" href="${h.url_for( controller='library_common', action='folder_info', cntrller=cntrller, id=trans.security.encode_id( folder.id ), library_id=trans.security.encode_id( library.id ), use_panels=use_panels, show_deleted=show_deleted )}">View information</a>
%endif
- </div>
- %endif
+ %endif
+ %if not branch_deleted( folder ) and can_modify and not info_association:
+ <a class="action-button" href="${h.url_for( controller='library_common', action='add_template', cntrller=cntrller, item_type='folder', form_type=form_type, library_id=trans.security.encode_id( library.id ), folder_id=trans.security.encode_id( folder.id ), use_panels=use_panels, show_deleted=show_deleted )}">Use template</a>
+ %endif
+ %if not branch_deleted( folder ) and can_modify and info_association:
+ <a class="action-button" href="${h.url_for( controller='library_common', action='edit_template', cntrller=cntrller, item_type='folder', form_type=form_type, library_id=trans.security.encode_id( library.id ), folder_id=trans.security.encode_id( folder.id ), use_panels=use_panels, show_deleted=show_deleted )}">Edit template</a>
+ <a class="action-button" href="${h.url_for( controller='library_common', action='delete_template', cntrller=cntrller, item_type='folder', form_type=form_type, library_id=trans.security.encode_id( library.id ), folder_id=trans.security.encode_id( folder.id ), use_panels=use_panels, show_deleted=show_deleted )}">Unuse template</a>
+ %endif
+ %if not branch_deleted( folder ) and can_manage:
+ %if not trans.app.security_agent.folder_is_public( folder ):
+ <a class="action-button" href="${h.url_for( controller='library_common', action='make_library_item_public', cntrller=cntrller, library_id=trans.security.encode_id( library.id ), item_type='folder', id=trans.security.encode_id( folder.id ), use_panels=use_panels, show_deleted=show_deleted )}">Make public</a>
+ %endif
+ <a class="action-button" href="${h.url_for( controller='library_common', action='folder_permissions', cntrller=cntrller, id=trans.security.encode_id( folder.id ), library_id=trans.security.encode_id( library.id ), use_panels=use_panels, show_deleted=show_deleted )}">Edit permissions</a>
+ %endif
+ %if can_modify:
+ %if not library.deleted and not folder.deleted:
+ <a class="action-button" confirm="Click OK to delete the folder '${folder.name}.'" href="${h.url_for( controller='library_common', action='delete_library_item', cntrller=cntrller, library_id=trans.security.encode_id( library.id ), item_id=trans.security.encode_id( folder.id ), item_type='folder', show_deleted=show_deleted )}">Delete this folder</a>
+ %elif not library.deleted and folder.deleted and not folder.purged:
+ <a class="action-button" href="${h.url_for( controller='library_common', action='undelete_library_item', cntrller=cntrller, library_id=trans.security.encode_id( library.id ), item_id=trans.security.encode_id( folder.id ), item_type='folder', show_deleted=show_deleted )}">Undelete this folder</a>
+ %endif
+ %endif
+ </div>
%endif
<td>
%if folder.description:
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: jgoecks: Trackster: save and restore mode for feature and read tracks.
by Bitbucket 21 Feb '11
by Bitbucket 21 Feb '11
21 Feb '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/54dc9beb30ea/
changeset: r5098:54dc9beb30ea
user: jgoecks
date: 2011-02-21 20:00:39
summary: Trackster: save and restore mode for feature and read tracks.
affected #: 1 file (553 bytes)
--- a/static/scripts/trackster.js Mon Feb 21 11:49:24 2011 -0500
+++ b/static/scripts/trackster.js Mon Feb 21 14:00:39 2011 -0500
@@ -1318,13 +1318,16 @@
if (track.display_modes !== undefined) {
if (track.mode_div === undefined) {
track.mode_div = $("<div class='right-float menubutton popup' />").appendTo(track.header_div);
- var init_mode = track.display_modes[0];
+ var init_mode = (track.track_config && track.track_config.values['mode'] ?
+ track.track_config.values['mode'] : track.display_modes[0]);
track.mode = init_mode;
track.mode_div.text(init_mode);
var change_mode = function(name) {
track.mode_div.text(name);
+ // TODO: is it necessary to store the mode in two places (.mode and track_config)?
track.mode = name;
+ track.track_config.values['mode'] = name;
track.tile_cache.clear();
track.draw();
};
@@ -2046,9 +2049,33 @@
});
var FeatureTrack = function (name, view, hda_ldda, dataset_id, prefs, filters, tool, parent_track) {
+ //
+ // Preinitialization: do things that need to be done before calling Track and TiledTrack
+ // initialization code.
+ //
var track = this;
this.track_type = "FeatureTrack";
this.display_modes = ["Auto", "Dense", "Squish", "Pack"];
+ // Define and restore track configuration.
+ this.track_config = new TrackConfig( {
+ track: this,
+ params: [
+ { key: 'block_color', label: 'Block color', type: 'color', default_value: '#444' },
+ { key: 'label_color', label: 'Label color', type: 'color', default_value: 'black' },
+ { key: 'show_counts', label: 'Show summary counts', type: 'bool', default_value: true },
+ { key: 'mode', type: 'string', default_value: this.mode, hidden: true },
+ ],
+ saved_values: prefs,
+ onchange: function() {
+ track.tile_cache.clear();
+ track.draw();
+ }
+ });
+ this.prefs = this.track_config.values;
+
+ //
+ // Initialization.
+ //
Track.call(this, name, view, view.viewport_container);
TiledTrack.call(this, filters, tool, parent_track);
@@ -2068,23 +2095,6 @@
this.tile_cache = new Cache(CACHED_TILES_FEATURE);
this.data_cache = new DataCache(20);
this.left_offset = 200;
-
- // Define track configuration
- this.track_config = new TrackConfig( {
- track: this,
- params: [
- { key: 'block_color', label: 'Block color', type: 'color', default_value: '#444' },
- { key: 'label_color', label: 'Label color', type: 'color', default_value: 'black' },
- { key: 'show_counts', label: 'Show summary counts', type: 'bool', default_value: true }
- ],
- saved_values: prefs,
- onchange: function() {
- track.tile_cache.clear();
- track.draw();
- }
- });
-
- this.prefs = this.track_config.values;
};
$.extend( FeatureTrack.prototype, TiledTrack.prototype, {
get_data: function( low, high ) {
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
21 Feb '11
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/fda57df0aa20/
changeset: r5097:fda57df0aa20
user: jgoecks
date: 2011-02-21 17:49:24
summary: Trackster: enhancements to read track display: insertions and deletions now shown correctly, and some efficiency improvements made using overlap calculations. Added function to compute the type of overlap between two regions.
affected #: 2 files (8.0 KB)
--- a/static/scripts/packed/trackster.js Mon Feb 21 09:46:54 2011 -0500
+++ b/static/scripts/packed/trackster.js Mon Feb 21 11:49:24 2011 -0500
@@ -1,1 +1,1 @@
-CanvasRenderingContext2D.prototype.dashedLine=function(c,i,b,h,f){if(f==undefined){f=4}var e=b-c;var d=h-i;var g=Math.floor(Math.sqrt(e*e+d*d)/f);var k=e/g;var j=d/g;for(var a=0;a<g;a++,c+=k,i+=j){if(a%2!=0){continue}this.fillRect(c,i,f,1)}};function sortable(a,b){a.bind("drag",{handle:b,relative:true},function(h,j){var g=$(this).parent();var f=g.children();for(var c=0;c<f.length;c++){if(j.offsetY<$(f.get(c)).position().top){break}}if(c==f.length){if(this!=f.get(c-1)){g.append(this)}}else{if(this!=f.get(c)){$(this).insertBefore(f.get(c))}}})}var DENSE_TRACK_HEIGHT=10,NO_DETAIL_TRACK_HEIGHT=3,SQUISH_TRACK_HEIGHT=5,PACK_TRACK_HEIGHT=10,NO_DETAIL_FEATURE_HEIGHT=DENSE_FEATURE_HEIGHT=1,SQUISH_FEATURE_HEIGHT=3,PACK_FEATURE_HEIGHT=9,LABEL_SPACING=2,PACK_SPACING=5,DEFAULT_FONT="9px Monaco, Lucida Console, monospace",DENSITY=200,FEATURE_LEVELS=10,MAX_FEATURE_DEPTH=100,DEFAULT_DATA_QUERY_WAIT=5000,MAX_CHROMS_SELECTABLE=100,CONNECTOR_COLOR="#ccc",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_CANNOT_RUN_TOOL="Tool cannot be rerun: ",DATA_LOADING="Loading data...",DATA_OK="Ready for display",FILTERABLE_CLASS="filterable",CACHED_TILES_FEATURE=10,CACHED_TILES_LINE=5,CACHED_DATA=5,DUMMY_CANVAS=document.createElement("canvas"),RIGHT_STRAND,LEFT_STRAND;if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(DUMMY_CANVAS)}var CONTEXT=DUMMY_CANVAS.getContext("2d");CONTEXT.font=DEFAULT_FONT;var CHAR_WIDTH_PX=CONTEXT.measureText("A").width,CHAR_HEIGHT_PX=9;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.move_key_to_end(b,a)}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},move_key_to_end:function(b,a){this.key_ary.splice(a,1);this.key_ary.push(b)},clear:function(){this.obj_cache={};this.key_ary=[]},size:function(){return this.key_ary.length}});var DataCache=function(a){Cache.call(this,a)};$.extend(DataCache.prototype,Cache.prototype,{get_data:function(g,b,e){var h=this.get(this.gen_key(g,b,e));if(h){return h}var j,f,a,d,e,h;for(var c=0;c<this.key_ary.length;c++){j=this.key_ary[c];f=this.split_key(j);a=f[0];d=f[1];if(g>=a&&b<=d){h=this.obj_cache[j];if(h.dataset_type!=="summary_tree"&&h.extra_info!=="no_detail"){this.move_key_to_end(j,c);return h}}}return undefined},set_data:function(b,c,d,a){return this.set(this.gen_key(b,c,d),a)},gen_key:function(a,c,d){var b=a+"_"+c+"_"+d;return b},split_key:function(a){return a.split("_")}});var View=function(a,d,c,b,e){this.container=a;this.chrom=null;this.vis_id=c;this.dbkey=b;this.title=d;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(e);this.reset()};$.extend(View.prototype,{init:function(d){var c=this.container,a=this;this.top_container=$("<div/>").addClass("top-container").appendTo(c);this.content_div=$("<div/>").addClass("content").css("position","relative").appendTo(c);this.bottom_container=$("<div/>").addClass("bottom-container").appendTo(c);this.top_labeltrack=$("<div/>").addClass("top-labeltrack").appendTo(this.top_container);this.viewport_container=$("<div/>").addClass("viewport-container").addClass("viewport-container").appendTo(this.content_div);this.intro_div=$("<div/>").addClass("intro").text("Select a chrom from the dropdown below").hide();this.nav_labeltrack=$("<div/>").addClass("nav-labeltrack").appendTo(this.bottom_container);this.nav_container=$("<div/>").addClass("nav-container").prependTo(this.top_container);this.nav=$("<div/>").addClass("nav").appendTo(this.nav_container);this.overview=$("<div/>").addClass("overview").appendTo(this.bottom_container);this.overview_viewport=$("<div/>").addClass("overview-viewport").appendTo(this.overview);this.overview_close=$("<a href='javascript:void(0);'>Close Overview</a>").addClass("overview-close").hide().appendTo(this.overview_viewport);this.overview_highlight=$("<div/>").addClass("overview-highlight").hide().appendTo(this.overview_viewport);this.overview_box_background=$("<div/>").addClass("overview-boxback").appendTo(this.overview_viewport);this.overview_box=$("<div/>").addClass("overview-box").appendTo(this.overview_viewport);this.default_overview_height=this.overview_box.height();this.nav_controls=$("<div/>").addClass("nav-controls").appendTo(this.nav);this.chrom_form=$("<form/>").attr("action",function(){}).appendTo(this.nav_controls);this.chrom_select=$("<select/>").attr({name:"chrom"}).css("width","15em").addClass("no-autocomplete").append("<option value=''>Loading</option>").appendTo(this.chrom_form);var b=function(f){if(f.type==="focusout"||(f.keyCode||f.which)===13||(f.keyCode||f.which)===27){if((f.keyCode||f.which)!==27){a.go_to($(this).val())}$(this).hide();a.location_span.show();a.chrom_select.show();return false}};this.nav_input=$("<input/>").addClass("nav-input").hide().bind("keypress focusout",b).appendTo(this.chrom_form);this.location_span=$("<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=$("<input/>").attr("type","hidden").val(this.vis_id).appendTo(this.chrom_form)}this.zo_link=$("<a id='zoom-out' />").click(function(){a.zoom_out();a.redraw()}).appendTo(this.chrom_form);this.zi_link=$("<a id='zoom-in' />").click(function(){a.zoom_in();a.redraw()}).appendTo(this.chrom_form);this.load_chroms({low:0},d);this.chrom_select.bind("change",function(){a.change_chrom(a.chrom_select.val())});this.intro_div.show();this.content_div.bind("click",function(f){$(this).find("input").trigger("blur")});this.content_div.bind("dblclick",function(f){a.zoom_in(f.pageX,this.viewport_container)});this.overview_box.bind("dragstart",function(f,g){this.current_x=g.offsetX}).bind("drag",function(f,h){var i=h.offsetX-this.current_x;this.current_x=h.offsetX;var g=Math.round(i/a.viewport_container.width()*(a.max_high-a.max_low));a.move_delta(-g)});this.overview_close.bind("click",function(){for(var f=0,e=a.tracks.length;f<e;f++){a.tracks[f].is_overview=false}$(this).siblings().filter("canvas").remove();$(this).parent().css("height",a.overview_box.height());a.overview_highlight.hide();$(this).hide()});this.viewport_container.bind("draginit",function(f,g){if(f.clientX>a.viewport_container.width()-16){return false}}).bind("dragstart",function(f,g){g.original_low=a.low;g.current_height=f.clientY;g.current_x=g.offsetX}).bind("drag",function(h,j){var f=$(this);var k=j.offsetX-j.current_x;var g=f.scrollTop()-(h.clientY-j.current_height);f.scrollTop(g);j.current_height=h.clientY;j.current_x=j.offsetX;var i=Math.round(k/a.viewport_container.width()*(a.high-a.low));a.move_delta(i)}).bind("mousewheel",function(h,j,g,f){if(g){var i=Math.round(-g/a.viewport_container.width()*(a.high-a.low));a.move_delta(i)}});this.top_labeltrack.bind("dragstart",function(f,g){return $("<div />").css({height:a.content_div.height()+a.top_labeltrack.height()+a.nav_labeltrack.height()+1,top:"0px",position:"absolute","background-color":"#ccf",opacity:0.5,"z-index":1000}).appendTo($(this))}).bind("drag",function(j,k){$(k.proxy).css({left:Math.min(j.pageX,k.startX),width:Math.abs(j.pageX-k.startX)});var g=Math.min(j.pageX,k.startX)-a.container.offset().left,f=Math.max(j.pageX,k.startX)-a.container.offset().left,i=(a.high-a.low),h=a.viewport_container.width();a.update_location(Math.round(g/h*i)+a.low,Math.round(f/h*i)+a.low)}).bind("dragend",function(k,l){var g=Math.min(k.pageX,l.startX),f=Math.max(k.pageX,l.startX),i=(a.high-a.low),h=a.viewport_container.width(),j=a.low;a.low=Math.round(g/h*i)+j;a.high=Math.round(f/h*i)+j;$(l.proxy).remove();a.redraw()});this.add_label_track(new LabelTrack(this,this.top_labeltrack));this.add_label_track(new LabelTrack(this,this.nav_labeltrack));$(window).bind("resize",function(){a.resize_window()});$(document).bind("redraw",function(){a.redraw()});this.reset();$(window).trigger("resize")},update_location:function(a,b){this.location_span.text(commatize(a)+" - "+commatize(b));this.nav_input.val(this.chrom+":"+commatize(a)+"-"+commatize(b))},load_chroms:function(b,c){b.num=MAX_CHROMS_SELECTABLE;$.extend(b,(this.vis_id!==undefined?{vis_id:this.vis_id}:{dbkey:this.dbkey}));var a=this;$.ajax({url:chrom_url,data:b,dataType:"json",success:function(e){if(e.reference){a.add_label_track(new ReferenceTrack(a))}a.chrom_data=e.chrom_info;var h='<option value="">Select Chrom/Contig</option>';for(var g=0,d=a.chrom_data.length;g<d;g++){var f=a.chrom_data[g].chrom;h+='<option value="'+f+'">'+f+"</option>"}if(e.prev_chroms){h+='<option value="previous">Previous '+MAX_CHROMS_SELECTABLE+"</option>"}if(e.next_chroms){h+='<option value="next">Next '+MAX_CHROMS_SELECTABLE+"</option>"}a.chrom_select.html(h);if(c){c()}a.chrom_start_index=e.start_index},error:function(){alert("Could not load chroms for this dbkey:",a.dbkey)}})},change_chrom:function(e,b,g){if(!e||e==="None"){return}var d=this;if(e=="previous"){d.load_chroms({low:this.chrom_start_index-MAX_CHROMS_SELECTABLE});return}if(e=="next"){d.load_chroms({low:this.chrom_start_index+MAX_CHROMS_SELECTABLE});return}var f=$.grep(d.chrom_data,function(j,k){return j.chrom===e})[0];if(f===undefined){d.load_chroms({chrom:e},function(){d.change_chrom(e,b,g)});return}else{if(e!==d.chrom){d.chrom=e;if(!d.chrom){d.intro_div.show()}else{d.intro_div.hide()}d.chrom_select.val(d.chrom);d.max_high=f.len-1;d.reset();d.redraw(true);for(var h=0,a=d.tracks.length;h<a;h++){var c=d.tracks[h];if(c.init){c.init()}}}if(b!==undefined&&g!==undefined){d.low=Math.max(b,0);d.high=Math.min(g,d.max_high)}d.reset_overview();d.redraw()}},go_to:function(f){var j=this,a,d,b=f.split(":"),h=b[0],i=b[1];if(i!==undefined){try{var g=i.split("-");a=parseInt(g[0].replace(/,/g,""),10);d=parseInt(g[1].replace(/,/g,""),10)}catch(c){return false}}j.change_chrom(h,a,d)},move_fraction:function(c){var a=this;var b=a.high-a.low;this.move_delta(c*b)},move_delta:function(c){var a=this;var b=a.high-a.low;if(a.low-c<a.max_low){a.low=a.max_low;a.high=a.max_low+b}else{if(a.high-c>a.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);sortable(a.container_div,".draghandle");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 g=this.high-this.low,f=this.low,b=this.high;if(f<this.max_low){f=this.max_low}if(b>this.max_high){b=this.max_high}if(this.high!==0&&g<this.min_separation){b=f+this.min_separation}this.low=Math.floor(f);this.high=Math.ceil(b);this.resolution=Math.pow(10,Math.ceil(Math.log((this.high-this.low)/200)/Math.LN10));this.zoom_res=Math.pow(FEATURE_LEVELS,Math.max(0,Math.ceil(Math.log(this.resolution,FEATURE_LEVELS)/Math.log(FEATURE_LEVELS))));var a=(this.low/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var e=((this.high-this.low)/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var j=13;this.overview_box.css({left:a,width:Math.max(j,e)}).show();if(e<j){this.overview_box.css("left",a-(j-e)/2)}if(this.overview_highlight){this.overview_highlight.css({left:a,width:e})}this.update_location(this.low,this.high);if(!h){for(var c=0,d=this.tracks.length;c<d;c++){if(this.tracks[c]&&this.tracks[c].enabled){this.tracks[c].draw()}}for(c=0,d=this.label_tracks.length;c<d;c++){this.label_tracks[c].draw()}}},zoom_in:function(b,c){if(this.max_high===0||this.high-this.low<this.min_separation){return}var d=this.high-this.low,e=d/2+this.low,a=(d/this.zoom_factor)/2;if(b){e=b/this.viewport_container.width()*(this.high-this.low)+this.low}this.low=Math.round(e-a);this.high=Math.round(e+a);this.redraw()},zoom_out:function(){if(this.max_high===0){return}var b=this.high-this.low,c=b/2+this.low,a=(b*this.zoom_factor)/2;this.low=Math.round(c-a);this.high=Math.round(c+a);this.redraw()},resize_window:function(){this.viewport_container.height(this.container.height()-this.top_container.height()-this.bottom_container.height());this.nav_container.width(this.container.width());this.redraw()},reset_overview:function(){this.overview_viewport.find("canvas").remove();this.overview_viewport.height(this.default_overview_height);this.overview_box.height(this.default_overview_height);this.overview_close.hide();this.overview_highlight.hide()}});var Tool=function(a,b){this.name=a;this.params=b};$.extend(Tool.prototype,{get_param_values_dict:function(){var b={};for(var a=0;a<this.params.length;a++){var c=this.params[a];b[c.name]=c.value}return b},get_param_values:function(){var b=[];for(var a=0;a<this.params.length;a++){b[a]=this.params[a].value}return b}});var NumberToolParameter=function(c,b,e,a,d){this.name=c;this.label=b;this.min=e;this.max=a;this.value=d};var get_tool_from_dict=function(f){if(obj_length(f)==0){return undefined}var b=f.name;var l=f.params;var c=Array();for(var e=0;e<l.length;e++){var g=l[e];var a=g.name,k=g.label,h=g.type,d=g.min,j=g.max,m=g.value;c[c.length]=new NumberToolParameter(a,k,d,j,m)}return new Tool(b,c)};var Filter=function(b,a,c){this.name=b;this.index=a;this.value=c};var NumberFilter=function(b,a){this.name=b;this.index=a;this.low=-Number.MAX_VALUE;this.high=Number.MAX_VALUE;this.slider_min=Number.MAX_VALUE;this.slider_max=-Number.MAX_VALUE;this.slider=null;this.slider_label=null};$.extend(NumberFilter.prototype,{applies_to:function(a){if(a.length>this.index){return true}return false},keep:function(a){if(!this.applies_to(a)){return true}return(a[this.index]>=this.low&&a[this.index]<=this.high)},update_attrs:function(b){var a=false;if(!this.applies_to(b)){return a}if(b[this.index]<this.slider_min){this.slider_min=b[this.index];a=true}if(b[this.index]>this.slider_max){this.slider_max=b[this.index];a=false}return a},update_ui_elt:function(){var b=this.slider.slider("option","min"),a=this.slider.slider("option","max");if(this.slider_min<b||this.slider_max>a){this.slider.slider("option","min",this.slider_min);this.slider.slider("option","max",this.slider_max);this.slider.slider("option","values",[this.slider_min,this.slider_max])}}});var get_filters_from_dict=function(a){var g=[];for(var d=0;d<a.length;d++){var f=a[d];var c=f.name,e=f.type,b=f.index;if(e=="int"||e=="float"){g[d]=new NumberFilter(c,b)}else{g[d]=new Filter(c,b,e)}}return g};var TrackConfig=function(a){this.track=a.track;this.params=a.params;this.values={};if(a.saved_values){this.restore_values(a.saved_values)}this.onchange=a.onchange};$.extend(TrackConfig.prototype,{restore_values:function(a){var b=this;$.each(this.params,function(c,d){if(a[d.key]!==undefined){b.values[d.key]=a[d.key]}else{b.values[d.key]=d.default_value}})},build_form:function(){var b=this;var a=$("<div />");$.each(this.params,function(f,d){if(!d.hidden){var c="param_"+f;var k=$("<div class='form-row' />").appendTo(a);k.append($("<label />").attr("for",c).text(d.label+":"));if(d.type=="bool"){k.append($('<input type="checkbox" />').attr("id",c).attr("name",c).attr("checked",b.values[d.key]))}else{if(d.type=="color"){var h=b.values[d.key];var g=$("<input />").attr("id",c).attr("name",c).val(h);var i=$("<div class='tipsy tipsy-north' style='position: absolute;' />").hide();var e=$("<div style='background-color: black; padding: 10px;'></div>").appendTo(i);var j=$("<div/>").appendTo(e).farbtastic({width:100,height:100,callback:g,color:h});$("<div />").append(g).append(i).appendTo(k).bind("click",function(l){i.css({left:$(this).position().left+($(g).width()/2)-60,top:$(this).position().top+$(this.height)}).show();$(document).bind("click.color-picker",function(){i.hide();$(document).unbind("click.color-picker")});l.stopPropagation()})}else{k.append($("<input />").attr("id",c).attr("name",c).val(b.values[d.key]))}}}});return a},update_from_form:function(a){var c=this;var b=false;$.each(this.params,function(d,f){if(!f.hidden){var g="param_"+d;var e=a.find("#"+g).val();if(f.type=="float"){e=parseFloat(e)}else{if(f.type=="int"){e=parseInt(e)}else{if(f.type=="bool"){e=a.find("#"+g).is(":checked")}}}if(e!==c.values[f.key]){c.values[f.key]=e;b=true}}});if(b){this.onchange()}}});var Track=function(b,a,e,c,d){this.name=b;this.view=a;this.parent_element=e;this.data_url=(c?c:default_data_url);this.data_query_wait=(d?d:DEFAULT_DATA_QUERY_WAIT);this.dataset_check_url=converted_datasets_state_url;this.container_div=$("<div />").addClass("track").css("position","relative");if(!this.hidden){this.header_div=$("<div class='track-header' />").appendTo(this.container_div);if(this.view.editor){this.drag_div=$("<div class='draghandle' />").appendTo(this.header_div)}this.name_div=$("<div class='menubutton popup' />").appendTo(this.header_div);this.name_div.text(this.name);this.name_div.attr("id",this.name.replace(/\s+/g,"-").replace(/[^a-zA-Z0-9\-]/g,"").toLowerCase())}this.content_div=$("<div class='track-content'>").appendTo(this.container_div);this.parent_element.append(this.container_div)};$.extend(Track.prototype,{init:function(){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");a.container_div.removeClass("nodata error pending");if(!a.dataset_id){return}if(a.view.chrom!=null){$.getJSON(converted_datasets_state_url,{hda_ldda:a.hda_ldda,dataset_id:a.dataset_id,chrom:a.view.chrom},function(b){if(!b||b==="error"||b.kind==="error"){a.container_div.addClass("error");a.content_div.text(DATA_ERROR);if(b.message){var d=a.view.tracks.indexOf(a);var c=$(" <a href='javascript:void(0);'></a>").text("View error").bind("click",function(){show_modal("Trackster Error","<pre>"+b.message+"</pre>",{Close:hide_modal})});a.content_div.append(c)}}else{if(b==="no converter"){a.container_div.addClass("error");a.content_div.text(DATA_NOCONVERTER)}else{if(b==="no data"||(b.data!==undefined&&(b.data===null||b.data.length===0))){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()},a.data_query_wait)}else{if(b.status==="data"){if(b.valid_chroms){a.valid_chroms=b.valid_chroms;a.name_div.data("menu_options")["List chrom/contigs with data"]=function(){show_modal("Chrom/contigs with data","<p>"+a.valid_chroms.join("<br/>")+"</p>",{Close:function(){hide_modal()}})}}a.content_div.text(DATA_OK);if(a.view.chrom){a.content_div.text("");a.content_div.css("height",a.height_px+"px");a.enabled=true;$.when(a.predraw_init()).done(function(){a.draw()})}}}}}}})}},predraw_init:function(){},update_name:function(a){this.old_name=this.name;this.name=a;this.name_div.text(this.name)},revert_name:function(){this.name=this.old_name;this.name_div.text(this.name)}});var TiledTrack=function(g,d,s){var o=this,j=o.view;this.filters=(g!==undefined?get_filters_from_dict(g):[]);this.tool=(d!==undefined?get_tool_from_dict(d):undefined);this.parent_track=s;this.child_tracks=[];if(o.hidden){return}if(this.parent_track){this.header_div.find(".draghandle").removeClass("draghandle").addClass("child-track-icon").addClass("icon-button");this.parent_element.addClass("child-track");this.tool=undefined}this.filtering_div=$("<div/>").addClass("track-filters").hide();this.header_div.after(this.filtering_div);this.filtering_div.bind("drag",function(i){i.stopPropagation()}).bind("dblclick",function(i){i.stopPropagation()});var t=$("<table class='filters'>").appendTo(this.filtering_div);$.each(this.filters,function(w,z){var v=$("<tr>").appendTo(t);var y=$("<th class='filter-info'>").appendTo(v);var u=$("<span class='name'>").appendTo(y);u.text(z.name+" ");var i=$("<span class='values'>").appendTo(y);var x=$("<td>").appendTo(v);z.control_element=$("<div id='"+z.name+"-filter-control' style='width: 200px; position: relative'>").appendTo(x);z.control_element.slider({range:true,min:Number.MAX_VALUE,max:-Number.MIN_VALUE,values:[0,0],slide:function(B,C){var A=C.values;i.text("["+A[0]+"-"+A[1]+"]");z.low=A[0];z.high=A[1];o.draw(true)},change:function(A,B){z.control_element.slider("option","slide").call(z.control_element,A,B)}});z.slider=z.control_element;z.slider_label=i});if(this.tool){this.dynamic_tool_div=$("<div/>").addClass("dynamic-tool").hide();this.header_div.after(this.dynamic_tool_div);this.dynamic_tool_div.bind("drag",function(i){i.stopPropagation()}).bind("click",function(i){i.stopPropagation()}).bind("dblclick",function(i){i.stopPropagation()});var l=$("<div class='tool-name'>").appendTo(this.dynamic_tool_div).text(this.tool.name);var e=this.tool.params;var o=this;$.each(this.tool.params,function(A,v){var y=$("<div>").addClass("param-row").appendTo(o.dynamic_tool_div);var x=$("<div>").addClass("slider-label").appendTo(y);var C=$("<span class='param-name'>").text(v.label+" ").appendTo(x);var w=$("<span/>").text(v.value);var z=$("<span class='param-value'>").appendTo(x).append("[").append(w).append("]");var B=$("<div/>").addClass("slider").appendTo(y);var i=$("<div id='"+v.name+"-param-control'>").appendTo(B);var u=(v.max<=1?0.01:(v.max<=1000?1:5));i.slider({min:v.min,max:v.max,step:u,value:v.value,slide:function(D,F){var E=F.value;v.value=E;if(0<E&&E<1){E=parseFloat(E).toFixed(2)}w.text(E)},change:function(D,E){v.value=E.value}});z.click(function(){var F=w,E=F.text(),D=(v.max<=1?4:v.max.length);F.text("");$("<input type='text'/>").attr("size",D).attr("maxlength",D).attr("value",E).appendTo(F).focus().select().click(function(G){G.stopPropagation()}).blur(function(){$(this).remove();F.text(E)}).keyup(function(I){if(I.keyCode===27){$(this).trigger("blur")}else{if(I.keyCode===13){var G=$(this),H=parseFloat(G.val());if(isNaN(H)||H>v.max||H<v.min){alert("Parameter value must be in the range ["+v.min+"-"+v.max+"]");return $(this)}F.text(H);i.slider("value",H);v.value=H}}})});$("<div style='clear: both;'/>").appendTo(y)});var b=$("<div>").addClass("param-row").appendTo(this.dynamic_tool_div);var n=$("<input type='submit'>").attr("value","Run").appendTo(b);var o=this;n.click(function(){o.run_tool()})}o.child_tracks_container=$("<div/>").addClass("child-tracks-container").hide();o.container_div.append(o.child_tracks_container);if(o.display_modes!==undefined){if(o.mode_div===undefined){o.mode_div=$("<div class='right-float menubutton popup' />").appendTo(o.header_div);var m=o.display_modes[0];o.mode=m;o.mode_div.text(m);var a=function(i){o.mode_div.text(i);o.mode=i;o.tile_cache.clear();o.draw()};var f={};for(var q=0,r=o.display_modes.length;q<r;q++){var k=o.display_modes[q];f[k]=function(i){return function(){a(i)}}(k)}make_popupmenu(o.mode_div,f)}else{o.mode_div.hide()}}var h={};h["Edit configuration"]=function(){var v=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},i=function(){o.track_config.update_from_form($(".dialog-box"));hide_modal();$(window).unbind("keypress.check_enter_esc")},u=function(w){if((w.keyCode||w.which)===27){v()}else{if((w.keyCode||w.which)===13){i()}}};$(window).bind("keypress.check_enter_esc",u);show_modal("Configure Track",o.track_config.build_form(),{Cancel:v,OK:i})};if(o.filters.length>0){h["Show filters"]=function(){var i;if(!o.filtering_div.is(":visible")){i="Hide filters";o.filters_visible=true}else{i="Show filters";o.filters_visible=false}o.filtering_div.toggle()}}if(o.tool){h["Toggle Tool"]=function(){var i;if(!o.dynamic_tool_div.is(":visible")){i="Hide dynamic tool";o.update_name(o.name+o.tool_region_and_parameters_str())}else{i="Show dynamic tool";o.revert_name()}o.dynamic_tool_div.toggle()}}var c=j;var p=function(){$("#no-tracks").show()};if(this.parent_track){c=this.parent_track;p=function(){}}h.Remove=function(){c.remove_track(o);if(c.num_tracks===0){p()}};o.popup_menu=make_popupmenu(o.name_div,h)};$.extend(TiledTrack.prototype,Track.prototype,{draw:function(b){var m=this.view.low,g=this.view.high,j=g-m,c=this.view.container.width(),f=this.view.resolution;var p=$("<div style='position: relative;'></div>"),r=c/j;this.content_div.append(p);this.max_height=0;var a=Math.floor(m/f/DENSITY);var l=0;while((a*DENSITY*f)<g){var n=c+"_"+r+"_"+a;var e=this.tile_cache.get(n);var k=a*DENSITY*this.view.resolution;var q=k+DENSITY*this.view.resolution;if(!b&&e){this.show_tile(e,p,k,r)}else{this.delayed_draw(b,n,k,q,a,f,p,r)}a+=1}var d=this;var o=setInterval(function(){if(l===0){var u=d.content_div.children();var t=false;for(var v=u.length-1,s=0;v>=s;v--){var x=$(u[v]);if(t){x.remove()}else{if(x.children().length!==0){t=true}}}for(var w=0;w<d.filters.length;w++){d.filters[w].update_ui_elt()}clearInterval(o)}},50);for(var h=0;h<this.child_tracks.length;h++){this.child_tracks[h].draw(b)}},delayed_draw:function(b,g,f,i,c,e,h,j){var d=this;var a=setTimeout(function(){if(f<=d.view.high&&i>=d.view.low){var k;if(!b){k=d.tile_cache.get(g)}if(!k){k=d.draw_tile(e,c,h,j);if(k){var l=$("<div class='track-tile'>").prepend(k);if(k.hasClass(FILTERABLE_CLASS)){l.addClass(FILTERABLE_CLASS)}k=l}}if(k){d.tile_cache.set(g,k);d.show_tile(k,h,f,j)}}},50)},show_tile:function(a,f,d,g){var b=this;var c=this.view.high-this.view.low,e=(d-this.view.low)*g;if(this.left_offset){e-=this.left_offset}a.css({position:"absolute",top:0,left:e,height:""});f.append(a);b.max_height=Math.max(b.max_height,a.height());b.content_div.css("height",b.max_height+"px");f.children().css("height",b.max_height+"px");if(b.hidden){return}if(a.hasClass(FILTERABLE_CLASS)){show_hide_popupmenu_options(b.popup_menu,"(Show|Hide) filters");if(b.filters_visible){b.filtering_div.show()}}else{show_hide_popupmenu_options(b.popup_menu,"(Show|Hide) filters",false);b.filtering_div.hide()}},set_overview:function(){var a=this.view;if(this.initial_canvas&&this.is_overview){a.overview_close.show();a.overview_viewport.append(this.initial_canvas);a.overview_highlight.show().height(this.initial_canvas.height());a.overview_viewport.height(this.initial_canvas.height()+a.overview_box.height())}$(window).trigger("resize")},run_tool:function(){var b={dataset_id:this.original_dataset_id,chrom:this.view.chrom,low:this.view.low,high:this.view.high,tool_id:this.tool.name};$.extend(b,this.tool.get_param_values_dict());var d=this,c=b.tool_id+d.tool_region_and_parameters_str(b.chrom,b.low,b.high),e;if(d.track_type=="FeatureTrack"){e=new ToolDataFeatureTrack(c,view,undefined,{},{},d)}this.add_track(e);e.content_div.text("Starting job.");view.has_changes=true;var a=function(){$.getJSON(run_tool_url,b,function(f){if(f=="no converter"){e.container_div.addClass("error");e.content_div.text(DATA_NOCONVERTER)}else{if(f.error){e.container_div.addClass("error");e.content_div.text(DATA_CANNOT_RUN_TOOL+f.message)}else{if(f=="pending"){e.container_div.addClass("pending");e.content_div.text("Converting input data so that it can be easily reused.");setTimeout(a,2000)}else{e.dataset_id=f.dataset_id;e.content_div.text("Running job.");e.init()}}}})};a()},tool_region_and_parameters_str:function(c,a,d){var b=this,e=(c!==undefined&&a!==undefined&&d!==undefined?c+":"+a+"-"+d:"all");return" - region=["+e+"], parameters=["+b.tool.get_param_values().join(", ")+"]"},add_track:function(a){a.track_id=this.track_id+"_"+this.child_tracks.length;a.container_div.attr("id","track_"+a.track_id);this.child_tracks_container.append(a.container_div);sortable(a.container_div,".child-track-icon");if(!$(this.child_tracks_container).is(":visible")){this.child_tracks_container.show()}this.child_tracks.push(a)},remove_track:function(a){a.container_div.fadeOut("slow",function(){$(this).remove()})}});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.view.container.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 ReferenceTrack=function(a){this.track_type="ReferenceTrack";this.hidden=true;Track.call(this,null,a,a.top_labeltrack);TiledTrack.call(this);this.left_offset=200;this.height_px=12;this.container_div.addClass("reference-track");this.content_div.css("background","none");this.content_div.css("min-height","0px");this.content_div.css("border","none");this.data_queue={};this.data_cache=new DataCache(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,i){console.log(h,g,i)}})}},draw_tile:function(f,b,k,o){var g=b*DENSITY*f,d=DENSITY*f,j=f+"_"+b;var e=document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(e)}e=$(e);var n=e.get(0).getContext("2d");if(o>CHAR_WIDTH_PX){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;for(var h=0,l=m.length;h<l;h++){var a=Math.round(h*o),i=Math.round(o/2);n.fillText(m[h],a+this.left_offset+i,10)}k.append(e);return e}this.content_div.css("height","0px")}});var LineTrack=function(e,c,f,a,d){var b=this;this.track_type="LineTrack";this.display_modes=["Histogram","Line","Filled","Intensity"];this.mode="Histogram";Track.call(this,e,c,c.viewport_container);TiledTrack.call(this);this.min_height_px=16;this.max_height_px=400;this.height_px=80;this.hda_ldda=f;this.dataset_id=a;this.original_dataset_id=a;this.data_cache=new DataCache(CACHED_DATA);this.tile_cache=new Cache(CACHED_TILES_LINE);this.track_config=new TrackConfig({track:this,params:[{key:"color",label:"Color",type:"color",default_value:"black"},{key:"min_value",label:"Min Value",type:"float",default_value:undefined},{key:"max_value",label:"Max Value",type:"float",default_value:undefined},{key:"mode",type:"string",default_value:this.mode,hidden:true},{key:"height",type:"int",default_value:this.height_px,hidden:true}],saved_values:d,onchange:function(){b.vertical_range=b.prefs.max_value-b.prefs.min_value;$("#linetrack_"+b.track_id+"_minval").text(b.prefs.min_value);$("#linetrack_"+b.track_id+"_maxval").text(b.prefs.max_value);b.tile_cache.clear();b.draw()}});this.prefs=this.track_config.values;this.height_px=this.track_config.values.height;this.vertical_range=this.track_config.values.max_value-this.track_config.values.min_value;(function(g){var j=false;var i=false;var h=$("<div class='track-resize'>");$(g.container_div).hover(function(){j=true;h.show()},function(){j=false;if(!i){h.hide()}});h.hide().bind("dragstart",function(k,l){i=true;l.original_height=$(g.content_div).height()}).bind("drag",function(l,m){var k=Math.min(Math.max(m.original_height+m.deltaY,g.min_height_px),g.max_height_px);$(g.content_div).css("height",k);g.height_px=k;g.draw(true)}).bind("dragend",function(k,l){g.tile_cache.clear();i=false;if(!j){h.hide()}g.track_config.values.height=g.height_px}).appendTo(g.container_div)})(this)};$.extend(LineTrack.prototype,TiledTrack.prototype,{predraw_init:function(){var a=this,b=a.view.tracks.indexOf(a);a.vertical_range=undefined;return $.getJSON(a.data_url,{stats:true,chrom:a.view.chrom,low:null,high:null,hda_ldda:a.hda_ldda,dataset_id:a.dataset_id},function(c){a.container_div.addClass("line-track");var e=c.data;if(isNaN(parseFloat(a.prefs.min_value))||isNaN(parseFloat(a.prefs.max_value))){a.prefs.min_value=e.min;a.prefs.max_value=e.max;$("#track_"+b+"_minval").val(a.prefs.min_value);$("#track_"+b+"_maxval").val(a.prefs.max_value)}a.vertical_range=a.prefs.max_value-a.prefs.min_value;a.total_frequency=e.total_frequency;a.container_div.find(".yaxislabel").remove();var f=$("<div />").addClass("yaxislabel").attr("id","linetrack_"+b+"_minval").text(round_1000(a.prefs.min_value));var d=$("<div />").addClass("yaxislabel").attr("id","linetrack_"+b+"_maxval").text(round_1000(a.prefs.max_value));d.css({position:"absolute",top:"24px",left:"10px"});d.prependTo(a.container_div);f.css({position:"absolute",bottom:"2px",left:"10px"});f.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:this.data_url,dataType:"json",data:{chrom:this.view.chrom,low:a,high:f,hda_ldda:this.hda_ldda,dataset_id:this.dataset_id,resolution:this.view.resolution},success:function(g){var h=g.data;c.data_cache.set(e,h);delete c.data_queue[e];c.draw()},error:function(h,g,i){console.log(h,g,i)}})}},draw_tile:function(o,r,c,e){if(this.vertical_range===undefined){return}var s=r*DENSITY*o,a=DENSITY*o,x=o+"_"+r;var b=document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(b)}b=$(b);if(this.data_cache.get(x)===undefined){this.get_data(o,r);return}var v=this.data_cache.get(x);if(!v){return}b.get(0).width=Math.ceil(a*e);b.get(0).height=this.height_px;var n=b.get(0).getContext("2d"),j=false,k=this.prefs.min_value,g=this.prefs.max_value,m=this.vertical_range,t=this.total_frequency,d=this.height_px,l=this.mode;var w=Math.round(d+k/m*d);n.beginPath();n.moveTo(0,w);n.lineTo(a*e,w);n.fillStyle="#aaa";n.stroke();n.beginPath();n.fillStyle=this.prefs.color;var u,h,f;if(v.length>1){f=Math.ceil((v[1][0]-v[0][0])*e)}else{f=10}for(var p=0,q=v.length;p<q;p++){u=Math.round((v[p][0]-s)*e);h=v[p][1];if(h===null){if(j&&l==="Filled"){n.lineTo(u,d)}j=false;continue}if(h<k){h=k}else{if(h>g){h=g}}if(l==="Histogram"){h=Math.round(h/m*d);n.fillRect(u,w,f,-h)}else{if(l==="Intensity"){h=255-Math.floor((h-k)/m*255);n.fillStyle="rgb("+h+","+h+","+h+")";n.fillRect(u,0,f,d)}else{h=Math.round(d-(h-k)/m*d);if(j){n.lineTo(u,h)}else{j=true;if(l==="Filled"){n.moveTo(u,d);n.lineTo(u,h)}else{n.moveTo(u,h)}}}}}if(l==="Filled"){if(j){n.lineTo(u,w);n.lineTo(0,w)}n.fill()}else{n.stroke()}return b}});var FeatureTrack=function(a,f,e,i,h,c,d,g){var b=this;this.track_type="FeatureTrack";this.display_modes=["Auto","Dense","Squish","Pack"];Track.call(this,a,f,f.viewport_container);TiledTrack.call(this,c,d,g);this.height_px=0;this.container_div.addClass("feature-track");this.hda_ldda=e;this.dataset_id=i;this.original_dataset_id=i;this.zo_slots={};this.show_labels_scale=0.001;this.showing_details=false;this.summary_draw_height=30;this.default_font=DEFAULT_FONT;this.inc_slots={};this.data_queue={};this.start_end_dct={};this.tile_cache=new Cache(CACHED_TILES_FEATURE);this.data_cache=new DataCache(20);this.left_offset=200;this.track_config=new TrackConfig({track:this,params:[{key:"block_color",label:"Block color",type:"color",default_value:"#444"},{key:"label_color",label:"Label color",type:"color",default_value:"black"},{key:"show_counts",label:"Show summary counts",type:"bool",default_value:true}],saved_values:h,onchange:function(){b.tile_cache.clear();b.draw()}});this.prefs=this.track_config.values};$.extend(FeatureTrack.prototype,TiledTrack.prototype,{get_data:function(a,d){var b=this,c=a+"_"+d;if(!b.data_queue[c]){b.data_queue[c]=true;$.getJSON(b.data_url,{chrom:b.view.chrom,low:a,high:d,hda_ldda:b.hda_ldda,dataset_id:b.dataset_id,resolution:this.view.resolution,mode:this.mode},function(e){b.data_cache.set_data(a,d,b.mode,e);delete b.data_queue[c];b.draw()})}},incremental_slots:function(a,j,d,q){var r=this.inc_slots[a];if(!r||(r.mode!==q)){r={};r.w_scale=a;r.mode=q;this.inc_slots[a]=r;this.start_end_dct[a]={}}var m=r.w_scale,x=[],y=[],k=0,o=this.view.max_low;for(var v=0,w=j.length;v<w;v++){var h=j[v],l=h[0];if(r[l]!==undefined){k=Math.max(k,r[l]);y.push(r[l])}else{x.push(v)}}var e=this.start_end_dct[a];var n=function(D,E){for(var C=0;C<=MAX_FEATURE_DEPTH;C++){var A=false,F=e[C];if(F!==undefined){for(var z=0,B=F.length;z<B;z++){var i=F[z];if(E>i[0]&&D<i[1]){A=true;break}}}if(!A){return C}}return -1};for(var v=0,w=x.length;v<w;v++){var h=j[x[v]],l=h[0],t=h[1],b=h[2],p=h[3],c=Math.floor((t-o)*m),g=Math.ceil((b-o)*m),u=CONTEXT.measureText(p).width,f;if(p!==undefined&&!d){u+=(LABEL_SPACING+PACK_SPACING);if(c-u>=0){c-=u;f="left"}else{g+=u;f="right"}}var s=n(c,g);if(s>=0){if(e[s]===undefined){e[s]=[]}e[s].push([c,g]);r[l]=s;k=Math.max(k,s)}else{}}return k},rect_or_text:function(r,l,u,b,q,j,g,f){r.textAlign="center";var d=0,s=0,p=Math.round(l/2);for(var m=0,t=j.length;m<t;m++){var k=j[m],e="MIDNSHP=X"[k[0]],n=k[1];if(e==="H"||e==="S"){d-=n}var h=q+d,x=Math.floor(Math.max(0,(h-u)*l)),i=Math.floor(Math.max(0,(h+n-u)*l));switch(e){case"H":break;case"S":case"M":case"=":var o=g.slice(s,s+n);if((this.mode==="Pack"||this.mode==="Auto")&&g!==undefined&&l>CHAR_WIDTH_PX){r.fillStyle=this.prefs.block_color;r.fillRect(x+this.left_offset,f+1,i-x,9);r.fillStyle=CONNECTOR_COLOR;for(var v=0,a=o.length;v<a;v++){if(h+v>=u&&h+v<=b){var w=Math.floor(Math.max(0,(h+v-u)*l));r.fillText(o[v],w+this.left_offset+p,f+9)}}}else{r.fillStyle=this.prefs.block_color;r.fillRect(x+this.left_offset,f+(this.mode!="Dense"?4:5),i-x,(this.mode!="Dense"?SQUISH_FEATURE_HEIGHT:DENSE_FEATURE_HEIGHT))}s+=n;break;case"N":r.fillStyle=CONNECTOR_COLOR;r.fillRect(x+this.left_offset,f+5,i-x,1);break;case"D":r.fillStyle="red";r.fillRect(x+this.left_offset,f+4,i-x,3);break;case"P":break;case"I":s+=n;break;case"X":s+=n;break}d+=n}},draw_tile:function(ae,m,q,au){var K=m*DENSITY*ae,aj=(m+1)*DENSITY*ae,J=aj-K;var G=this.data_cache.get_data(K,aj,this.mode);if(G===undefined||G==="pending"||(this.mode!=="Auto"&&G.dataset_type==="summary_tree")){this.data_queue[[K,aj]]=true;this.get_data(K,aj);return}var a=Math.ceil(J*au),ag=this.prefs.label_color,g=this.prefs.block_color,p=this.mode,u=25,aa,V=this.left_offset,at,B,av;var o=document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(o)}o=$(o);if(G.dataset_type==="summary_tree"){B=this.summary_draw_height}else{if(p==="Dense"){B=u;av=DENSE_TRACK_HEIGHT}else{if(p==="Squish"){av=SQUISH_TRACK_HEIGHT;aa=true}else{if(p==="Pack"){av=PACK_TRACK_HEIGHT;aa=false}else{if(G.extra_info==="no_detail"){av=(G.track_type==="bai"?SQUISH_TRACK_HEIGHT:NO_DETAIL_TRACK_HEIGHT);aa=true}else{av=PACK_TRACK_HEIGHT;aa=false}}}B=this.incremental_slots(au,G.data,aa,p)*av+u;at=this.inc_slots[au]}}o.get(0).width=a+V;o.get(0).height=B;if(G.dataset_type=="summary_tree"){o.get(0).height+=LABEL_SPACING+CHAR_HEIGHT_PX}q.parent().css("height",Math.max(this.height_px,B)+"px");var H=o.get(0).getContext("2d");H.fillStyle=g;H.font=this.default_font;H.textAlign="right";this.container_div.find(".yaxislabel").remove();if(G.dataset_type=="summary_tree"){var v=B+LABEL_SPACING+CHAR_HEIGHT_PX;points=G.data,max=G.max,delta_x_px=Math.ceil(G.delta*au);var n=$("<div />").addClass("yaxislabel");n.text(max);n.css({position:"absolute",top:"22px",left:"10px"});n.prependTo(this.container_div);for(var an=0,F=points.length;an<F;an++){var Z=Math.floor((points[an][0]-K)*au);var Y=points[an][1];if(!Y){continue}var ak=Y/max*B;H.fillStyle="black";H.fillRect(Z+V,v-ak,delta_x_px,ak);var X=4;if(this.prefs.show_counts&&(H.measureText(Y).width+X)<delta_x_px){H.fillStyle="#666";H.textAlign="center";H.fillText(Y,Z+V+(delta_x_px/2),10)}}return o}if(G.message){o.css({"border-color":"red"});H.fillStyle="red";H.textAlign="left";H.fillText(G.message,100+V,av);if(!G.data){return o}}for(var aq=0;aq<this.filters.length;aq++){if(G.data.length&&this.filters[aq].applies_to(G.data[0])){o.addClass(FILTERABLE_CLASS);break}}var ar=G.data;var am=0;for(var an=0,F=ar.length;an<F;an++){var R=ar[an],O=R[0],ap=R[1],ac=R[2],L=R[3];if(this.mode!="Dense"&&at[O]===undefined){continue}var ab=false;var T;for(var aq=0;aq<this.filters.length;aq++){T=this.filters[aq];T.update_attrs(R);if(!T.keep(R)){ab=true;break}}if(ab){continue}if(ap<=aj&&ac>=K){if(G.dataset_type=="interval_index"){ac-=1}var ad=Math.floor(Math.max(0,(ap-K)*au)),I=Math.ceil(Math.min(a,Math.max(0,(ac-K)*au))),W=(p==="Dense"?1:(1+at[O]))*av;var E,ah,M=null,aw=null;if(G.dataset_type==="bai"){H.fillStyle=g;if(R[5] instanceof Array){var C=Math.floor(Math.max(0,(R[4][0]-K)*au)),N=Math.ceil(Math.min(a,Math.max(0,(R[4][1]-K)*au))),A=Math.floor(Math.max(0,(R[5][0]-K)*au)),t=Math.ceil(Math.min(a,Math.max(0,(R[5][1]-K)*au)));if(R[4][1]>=K&&R[4][0]<=aj&&R[4][2]){this.rect_or_text(H,au,K,aj,R[4][0],R[4][2],R[4][3],W)}if(R[5][1]>=K&&R[5][0]<=aj&&R[5][2]){this.rect_or_text(H,au,K,aj,R[5][0],R[5][2],R[5][3],W)}if(A>N){H.fillStyle=CONNECTOR_COLOR;H.dashedLine(N+V,W+5,V+A,W+5)}}else{H.fillStyle=g;this.rect_or_text(H,au,K,aj,ap,R[4],R[5],W)}if(p!=="Dense"&&!aa&&ap>K){H.fillStyle=this.prefs.label_color;if(m===0&&ad-H.measureText(L).width<0){H.textAlign="left";H.fillText(L,I+V+LABEL_SPACING,W+8)}else{H.textAlign="right";H.fillText(L,ad+V-LABEL_SPACING,W+8)}H.fillStyle=g}}else{if(G.dataset_type==="interval_index"){if(p=="Auto"){if(R.length<=4){p="Squish"}else{p="Pack"}}if(p=="Dense"){H.fillStyle=g;H.fillRect(ad+V,W+5,I-ad,DENSE_FEATURE_HEIGHT)}else{if(R.length<=4){H.fillStyle=g;H.fillRect(ad+V,W+5,I-ad,DENSE_FEATURE_HEIGHT)}else{var D=R[5],U=R[6],af=R[7],e=R[8];if(U&&af){M=Math.floor(Math.max(0,(U-K)*au));aw=Math.ceil(Math.min(a,Math.max(0,(af-K)*au)))}var ao,P;if(p=="Squish"){ao=1;P=SQUISH_FEATURE_HEIGHT}else{ao=5;P=PACK_FEATURE_HEIGHT}if(!e){if(R.strand){if(R.strand=="+"){H.fillStyle=RIGHT_STRAND_INV}else{if(R.strand=="-"){H.fillStyle=LEFT_STRAND_INV}}}else{H.fillStyle=CONNECTOR_COLOR}H.fillRect(ad+V,W+(P-ao)/2+1,I-ad,P)}else{var z,Q;if(p=="Squish"){H.fillStyle=CONNECTOR_COLOR;z=W+Math.floor(SQUISH_FEATURE_HEIGHT/2)+1;Q=1}else{if(D){var z=W;var Q=P;if(D=="+"){H.fillStyle=RIGHT_STRAND}else{if(D=="-"){H.fillStyle=LEFT_STRAND}}}else{H.fillStyle=CONNECTOR_COLOR;z+=(SQUISH_FEATURE_HEIGHT/2)+1;Q=1}}H.fillRect(ad+V,z,I-ad,Q);for(var al=0,d=e.length;al<d;al++){var s=e[al],c=Math.floor(Math.max(0,(s[0]-K)*au)),S=Math.ceil(Math.min(a,Math.max((s[1]-K)*au)));if(c>S){continue}H.fillStyle=g;H.fillRect(c+V,W+(P-ao)/2+1,S-c,ao);if(M!==undefined&&!(c>aw||S<M)){var ai=Math.max(c,M),w=Math.min(S,aw-1);H.fillRect(ai+V,W+1,w-ai,P)}}}if(p=="Pack"&&ap>K){H.fillStyle=ag;if(m===0&&ad-H.measureText(L).width<0){H.textAlign="left";H.fillText(L,I+V+LABEL_SPACING,W+8)}else{H.textAlign="right";H.fillText(L,ad+V-LABEL_SPACING,W+8)}H.fillStyle=g}}}}else{if(G.dataset_type==="vcf"){if(aa){H.fillStyle=g;H.fillRect(ad+V,W+5,I-ad,1)}else{var r=R[4],l=R[5],b=R[6];E=9;ah=1;H.fillRect(ad+V,W,I-ad,E);if(p!=="Dense"&&L!==undefined&&ap>K){H.fillStyle=ag;if(m===0&&ad-H.measureText(L).width<0){H.textAlign="left";H.fillText(L,I+2+V,W+8)}else{H.textAlign="right";H.fillText(L,ad-2+V,W+8)}H.fillStyle=g}var h=r+" / "+l;if(ap>K&&H.measureText(h).width<(I-ad)){H.fillStyle="white";H.textAlign="center";H.fillText(h,V+ad+(I-ad)/2,W+8);H.fillStyle=g}}}}}am++}}return o}});var ReadTrack=function(d,b,f,a,c,e){FeatureTrack.call(this,d,b,f,a,c,e);this.track_type="ReadTrack"};$.extend(ReadTrack.prototype,TiledTrack.prototype,FeatureTrack.prototype,{});var ToolDataFeatureTrack=function(e,c,g,a,d,f,b){FeatureTrack.call(this,e,c,g,a,d,f,{},b);this.track_type="ToolDataFeatureTrack";this.data_url=raw_data_url;this.data_query_wait=1000;this.dataset_check_url=dataset_state_url};$.extend(ToolDataFeatureTrack.prototype,TiledTrack.prototype,FeatureTrack.prototype,{predraw_init:function(){var b=this;var a=function(){if(b.data_cache.size()==0){setTimeout(a,300)}else{b.data_url=default_data_url;b.data_query_wait=DEFAULT_DATA_QUERY_WAIT;b.dataset_state_url=converted_datasets_state_url;$.getJSON(b.dataset_state_url,{dataset_id:b.dataset_id},function(c){})}};a()}});
\ No newline at end of file
+CanvasRenderingContext2D.prototype.dashedLine=function(c,i,b,h,f){if(f==undefined){f=4}var e=b-c;var d=h-i;var g=Math.floor(Math.sqrt(e*e+d*d)/f);var k=e/g;var j=d/g;for(var a=0;a<g;a++,c+=k,i+=j){if(a%2!=0){continue}this.fillRect(c,i,f,1)}};CanvasRenderingContext2D.prototype.drawDownwardEquilateralTriangle=function(b,a,e){var d=b-e/2,c=b+e/2,f=a-Math.sqrt(e*3/2);this.beginPath();this.moveTo(d,f);this.lineTo(c,f);this.lineTo(b,a);this.lineTo(d,f);this.strokeStyle=this.fillStyle;this.fill();this.stroke();this.closePath()};function sortable(a,b){a.bind("drag",{handle:b,relative:true},function(h,j){var g=$(this).parent();var f=g.children();for(var c=0;c<f.length;c++){if(j.offsetY<$(f.get(c)).position().top){break}}if(c==f.length){if(this!=f.get(c-1)){g.append(this)}}else{if(this!=f.get(c)){$(this).insertBefore(f.get(c))}}})}var NO_OVERLAP=1001,CONTAINS=1002,OVERLAP_START=1003,OVERLAP_END=1004,CONTAINED_BY=1005;function compute_overlap(e,b){var g=e[0],f=e[1],d=b[0],c=b[1],a;if(g<d){if(f<d){a=NO_OVERLAP}else{if(f<=c){a=OVERLAP_START}else{a=CONTAINS}}}else{if(g>c){a=NO_OVERLAP}else{if(f<=c){a=CONTAINED_BY}else{a=OVERLAP_END}}}return a}function is_overlap(b,a){return(compute_overlap(b,a)!=NO_OVERLAP)}var DENSE_TRACK_HEIGHT=10,NO_DETAIL_TRACK_HEIGHT=3,SQUISH_TRACK_HEIGHT=5,PACK_TRACK_HEIGHT=10,NO_DETAIL_FEATURE_HEIGHT=DENSE_FEATURE_HEIGHT=1,SQUISH_FEATURE_HEIGHT=3,PACK_FEATURE_HEIGHT=9,LABEL_SPACING=2,PACK_SPACING=5,DEFAULT_FONT="9px Monaco, Lucida Console, monospace",DENSITY=200,FEATURE_LEVELS=10,MAX_FEATURE_DEPTH=100,DEFAULT_DATA_QUERY_WAIT=5000,MAX_CHROMS_SELECTABLE=100,CONNECTOR_COLOR="#ccc",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_CANNOT_RUN_TOOL="Tool cannot be rerun: ",DATA_LOADING="Loading data...",DATA_OK="Ready for display",FILTERABLE_CLASS="filterable",CACHED_TILES_FEATURE=10,CACHED_TILES_LINE=5,CACHED_DATA=5,DUMMY_CANVAS=document.createElement("canvas"),RIGHT_STRAND,LEFT_STRAND;if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(DUMMY_CANVAS)}var CONTEXT=DUMMY_CANVAS.getContext("2d");CONTEXT.font=DEFAULT_FONT;var CHAR_WIDTH_PX=CONTEXT.measureText("A").width,CHAR_HEIGHT_PX=9;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.move_key_to_end(b,a)}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},move_key_to_end:function(b,a){this.key_ary.splice(a,1);this.key_ary.push(b)},clear:function(){this.obj_cache={};this.key_ary=[]},size:function(){return this.key_ary.length}});var DataCache=function(a){Cache.call(this,a)};$.extend(DataCache.prototype,Cache.prototype,{get_data:function(g,b,e){var h=this.get(this.gen_key(g,b,e));if(h){return h}var j,f,a,d,e,h;for(var c=0;c<this.key_ary.length;c++){j=this.key_ary[c];f=this.split_key(j);a=f[0];d=f[1];if(g>=a&&b<=d){h=this.obj_cache[j];if(h.dataset_type!=="summary_tree"&&h.extra_info!=="no_detail"){this.move_key_to_end(j,c);return h}}}return undefined},set_data:function(b,c,d,a){return this.set(this.gen_key(b,c,d),a)},gen_key:function(a,c,d){var b=a+"_"+c+"_"+d;return b},split_key:function(a){return a.split("_")}});var View=function(a,d,c,b,e){this.container=a;this.chrom=null;this.vis_id=c;this.dbkey=b;this.title=d;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(e);this.reset()};$.extend(View.prototype,{init:function(d){var c=this.container,a=this;this.top_container=$("<div/>").addClass("top-container").appendTo(c);this.content_div=$("<div/>").addClass("content").css("position","relative").appendTo(c);this.bottom_container=$("<div/>").addClass("bottom-container").appendTo(c);this.top_labeltrack=$("<div/>").addClass("top-labeltrack").appendTo(this.top_container);this.viewport_container=$("<div/>").addClass("viewport-container").addClass("viewport-container").appendTo(this.content_div);this.intro_div=$("<div/>").addClass("intro").text("Select a chrom from the dropdown below").hide();this.nav_labeltrack=$("<div/>").addClass("nav-labeltrack").appendTo(this.bottom_container);this.nav_container=$("<div/>").addClass("nav-container").prependTo(this.top_container);this.nav=$("<div/>").addClass("nav").appendTo(this.nav_container);this.overview=$("<div/>").addClass("overview").appendTo(this.bottom_container);this.overview_viewport=$("<div/>").addClass("overview-viewport").appendTo(this.overview);this.overview_close=$("<a href='javascript:void(0);'>Close Overview</a>").addClass("overview-close").hide().appendTo(this.overview_viewport);this.overview_highlight=$("<div/>").addClass("overview-highlight").hide().appendTo(this.overview_viewport);this.overview_box_background=$("<div/>").addClass("overview-boxback").appendTo(this.overview_viewport);this.overview_box=$("<div/>").addClass("overview-box").appendTo(this.overview_viewport);this.default_overview_height=this.overview_box.height();this.nav_controls=$("<div/>").addClass("nav-controls").appendTo(this.nav);this.chrom_form=$("<form/>").attr("action",function(){}).appendTo(this.nav_controls);this.chrom_select=$("<select/>").attr({name:"chrom"}).css("width","15em").addClass("no-autocomplete").append("<option value=''>Loading</option>").appendTo(this.chrom_form);var b=function(f){if(f.type==="focusout"||(f.keyCode||f.which)===13||(f.keyCode||f.which)===27){if((f.keyCode||f.which)!==27){a.go_to($(this).val())}$(this).hide();a.location_span.show();a.chrom_select.show();return false}};this.nav_input=$("<input/>").addClass("nav-input").hide().bind("keypress focusout",b).appendTo(this.chrom_form);this.location_span=$("<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=$("<input/>").attr("type","hidden").val(this.vis_id).appendTo(this.chrom_form)}this.zo_link=$("<a id='zoom-out' />").click(function(){a.zoom_out();a.redraw()}).appendTo(this.chrom_form);this.zi_link=$("<a id='zoom-in' />").click(function(){a.zoom_in();a.redraw()}).appendTo(this.chrom_form);this.load_chroms({low:0},d);this.chrom_select.bind("change",function(){a.change_chrom(a.chrom_select.val())});this.intro_div.show();this.content_div.bind("click",function(f){$(this).find("input").trigger("blur")});this.content_div.bind("dblclick",function(f){a.zoom_in(f.pageX,this.viewport_container)});this.overview_box.bind("dragstart",function(f,g){this.current_x=g.offsetX}).bind("drag",function(f,h){var i=h.offsetX-this.current_x;this.current_x=h.offsetX;var g=Math.round(i/a.viewport_container.width()*(a.max_high-a.max_low));a.move_delta(-g)});this.overview_close.bind("click",function(){for(var f=0,e=a.tracks.length;f<e;f++){a.tracks[f].is_overview=false}$(this).siblings().filter("canvas").remove();$(this).parent().css("height",a.overview_box.height());a.overview_highlight.hide();$(this).hide()});this.viewport_container.bind("draginit",function(f,g){if(f.clientX>a.viewport_container.width()-16){return false}}).bind("dragstart",function(f,g){g.original_low=a.low;g.current_height=f.clientY;g.current_x=g.offsetX}).bind("drag",function(h,j){var f=$(this);var k=j.offsetX-j.current_x;var g=f.scrollTop()-(h.clientY-j.current_height);f.scrollTop(g);j.current_height=h.clientY;j.current_x=j.offsetX;var i=Math.round(k/a.viewport_container.width()*(a.high-a.low));a.move_delta(i)}).bind("mousewheel",function(h,j,g,f){if(g){var i=Math.round(-g/a.viewport_container.width()*(a.high-a.low));a.move_delta(i)}});this.top_labeltrack.bind("dragstart",function(f,g){return $("<div />").css({height:a.content_div.height()+a.top_labeltrack.height()+a.nav_labeltrack.height()+1,top:"0px",position:"absolute","background-color":"#ccf",opacity:0.5,"z-index":1000}).appendTo($(this))}).bind("drag",function(j,k){$(k.proxy).css({left:Math.min(j.pageX,k.startX),width:Math.abs(j.pageX-k.startX)});var g=Math.min(j.pageX,k.startX)-a.container.offset().left,f=Math.max(j.pageX,k.startX)-a.container.offset().left,i=(a.high-a.low),h=a.viewport_container.width();a.update_location(Math.round(g/h*i)+a.low,Math.round(f/h*i)+a.low)}).bind("dragend",function(k,l){var g=Math.min(k.pageX,l.startX),f=Math.max(k.pageX,l.startX),i=(a.high-a.low),h=a.viewport_container.width(),j=a.low;a.low=Math.round(g/h*i)+j;a.high=Math.round(f/h*i)+j;$(l.proxy).remove();a.redraw()});this.add_label_track(new LabelTrack(this,this.top_labeltrack));this.add_label_track(new LabelTrack(this,this.nav_labeltrack));$(window).bind("resize",function(){a.resize_window()});$(document).bind("redraw",function(){a.redraw()});this.reset();$(window).trigger("resize")},update_location:function(a,b){this.location_span.text(commatize(a)+" - "+commatize(b));this.nav_input.val(this.chrom+":"+commatize(a)+"-"+commatize(b))},load_chroms:function(b,c){b.num=MAX_CHROMS_SELECTABLE;$.extend(b,(this.vis_id!==undefined?{vis_id:this.vis_id}:{dbkey:this.dbkey}));var a=this;$.ajax({url:chrom_url,data:b,dataType:"json",success:function(e){if(e.reference){a.add_label_track(new ReferenceTrack(a))}a.chrom_data=e.chrom_info;var h='<option value="">Select Chrom/Contig</option>';for(var g=0,d=a.chrom_data.length;g<d;g++){var f=a.chrom_data[g].chrom;h+='<option value="'+f+'">'+f+"</option>"}if(e.prev_chroms){h+='<option value="previous">Previous '+MAX_CHROMS_SELECTABLE+"</option>"}if(e.next_chroms){h+='<option value="next">Next '+MAX_CHROMS_SELECTABLE+"</option>"}a.chrom_select.html(h);if(c){c()}a.chrom_start_index=e.start_index},error:function(){alert("Could not load chroms for this dbkey:",a.dbkey)}})},change_chrom:function(e,b,g){if(!e||e==="None"){return}var d=this;if(e=="previous"){d.load_chroms({low:this.chrom_start_index-MAX_CHROMS_SELECTABLE});return}if(e=="next"){d.load_chroms({low:this.chrom_start_index+MAX_CHROMS_SELECTABLE});return}var f=$.grep(d.chrom_data,function(j,k){return j.chrom===e})[0];if(f===undefined){d.load_chroms({chrom:e},function(){d.change_chrom(e,b,g)});return}else{if(e!==d.chrom){d.chrom=e;if(!d.chrom){d.intro_div.show()}else{d.intro_div.hide()}d.chrom_select.val(d.chrom);d.max_high=f.len-1;d.reset();d.redraw(true);for(var h=0,a=d.tracks.length;h<a;h++){var c=d.tracks[h];if(c.init){c.init()}}}if(b!==undefined&&g!==undefined){d.low=Math.max(b,0);d.high=Math.min(g,d.max_high)}d.reset_overview();d.redraw()}},go_to:function(f){var j=this,a,d,b=f.split(":"),h=b[0],i=b[1];if(i!==undefined){try{var g=i.split("-");a=parseInt(g[0].replace(/,/g,""),10);d=parseInt(g[1].replace(/,/g,""),10)}catch(c){return false}}j.change_chrom(h,a,d)},move_fraction:function(c){var a=this;var b=a.high-a.low;this.move_delta(c*b)},move_delta:function(c){var a=this;var b=a.high-a.low;if(a.low-c<a.max_low){a.low=a.max_low;a.high=a.max_low+b}else{if(a.high-c>a.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);sortable(a.container_div,".draghandle");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 g=this.high-this.low,f=this.low,b=this.high;if(f<this.max_low){f=this.max_low}if(b>this.max_high){b=this.max_high}if(this.high!==0&&g<this.min_separation){b=f+this.min_separation}this.low=Math.floor(f);this.high=Math.ceil(b);this.resolution=Math.pow(10,Math.ceil(Math.log((this.high-this.low)/200)/Math.LN10));this.zoom_res=Math.pow(FEATURE_LEVELS,Math.max(0,Math.ceil(Math.log(this.resolution,FEATURE_LEVELS)/Math.log(FEATURE_LEVELS))));var a=(this.low/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var e=((this.high-this.low)/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var j=13;this.overview_box.css({left:a,width:Math.max(j,e)}).show();if(e<j){this.overview_box.css("left",a-(j-e)/2)}if(this.overview_highlight){this.overview_highlight.css({left:a,width:e})}this.update_location(this.low,this.high);if(!h){for(var c=0,d=this.tracks.length;c<d;c++){if(this.tracks[c]&&this.tracks[c].enabled){this.tracks[c].draw()}}for(c=0,d=this.label_tracks.length;c<d;c++){this.label_tracks[c].draw()}}},zoom_in:function(b,c){if(this.max_high===0||this.high-this.low<this.min_separation){return}var d=this.high-this.low,e=d/2+this.low,a=(d/this.zoom_factor)/2;if(b){e=b/this.viewport_container.width()*(this.high-this.low)+this.low}this.low=Math.round(e-a);this.high=Math.round(e+a);this.redraw()},zoom_out:function(){if(this.max_high===0){return}var b=this.high-this.low,c=b/2+this.low,a=(b*this.zoom_factor)/2;this.low=Math.round(c-a);this.high=Math.round(c+a);this.redraw()},resize_window:function(){this.viewport_container.height(this.container.height()-this.top_container.height()-this.bottom_container.height());this.nav_container.width(this.container.width());this.redraw()},reset_overview:function(){this.overview_viewport.find("canvas").remove();this.overview_viewport.height(this.default_overview_height);this.overview_box.height(this.default_overview_height);this.overview_close.hide();this.overview_highlight.hide()}});var Tool=function(a,b){this.name=a;this.params=b};$.extend(Tool.prototype,{get_param_values_dict:function(){var b={};for(var a=0;a<this.params.length;a++){var c=this.params[a];b[c.name]=c.value}return b},get_param_values:function(){var b=[];for(var a=0;a<this.params.length;a++){b[a]=this.params[a].value}return b}});var NumberToolParameter=function(c,b,e,a,d){this.name=c;this.label=b;this.min=e;this.max=a;this.value=d};var get_tool_from_dict=function(f){if(obj_length(f)==0){return undefined}var b=f.name;var l=f.params;var c=Array();for(var e=0;e<l.length;e++){var g=l[e];var a=g.name,k=g.label,h=g.type,d=g.min,j=g.max,m=g.value;c[c.length]=new NumberToolParameter(a,k,d,j,m)}return new Tool(b,c)};var Filter=function(b,a,c){this.name=b;this.index=a;this.value=c};var NumberFilter=function(b,a){this.name=b;this.index=a;this.low=-Number.MAX_VALUE;this.high=Number.MAX_VALUE;this.slider_min=Number.MAX_VALUE;this.slider_max=-Number.MAX_VALUE;this.slider=null;this.slider_label=null};$.extend(NumberFilter.prototype,{applies_to:function(a){if(a.length>this.index){return true}return false},keep:function(a){if(!this.applies_to(a)){return true}return(a[this.index]>=this.low&&a[this.index]<=this.high)},update_attrs:function(b){var a=false;if(!this.applies_to(b)){return a}if(b[this.index]<this.slider_min){this.slider_min=b[this.index];a=true}if(b[this.index]>this.slider_max){this.slider_max=b[this.index];a=false}return a},update_ui_elt:function(){var b=this.slider.slider("option","min"),a=this.slider.slider("option","max");if(this.slider_min<b||this.slider_max>a){this.slider.slider("option","min",this.slider_min);this.slider.slider("option","max",this.slider_max);this.slider.slider("option","values",[this.slider_min,this.slider_max])}}});var get_filters_from_dict=function(a){var g=[];for(var d=0;d<a.length;d++){var f=a[d];var c=f.name,e=f.type,b=f.index;if(e=="int"||e=="float"){g[d]=new NumberFilter(c,b)}else{g[d]=new Filter(c,b,e)}}return g};var TrackConfig=function(a){this.track=a.track;this.params=a.params;this.values={};if(a.saved_values){this.restore_values(a.saved_values)}this.onchange=a.onchange};$.extend(TrackConfig.prototype,{restore_values:function(a){var b=this;$.each(this.params,function(c,d){if(a[d.key]!==undefined){b.values[d.key]=a[d.key]}else{b.values[d.key]=d.default_value}})},build_form:function(){var b=this;var a=$("<div />");$.each(this.params,function(f,d){if(!d.hidden){var c="param_"+f;var k=$("<div class='form-row' />").appendTo(a);k.append($("<label />").attr("for",c).text(d.label+":"));if(d.type=="bool"){k.append($('<input type="checkbox" />').attr("id",c).attr("name",c).attr("checked",b.values[d.key]))}else{if(d.type=="color"){var h=b.values[d.key];var g=$("<input />").attr("id",c).attr("name",c).val(h);var i=$("<div class='tipsy tipsy-north' style='position: absolute;' />").hide();var e=$("<div style='background-color: black; padding: 10px;'></div>").appendTo(i);var j=$("<div/>").appendTo(e).farbtastic({width:100,height:100,callback:g,color:h});$("<div />").append(g).append(i).appendTo(k).bind("click",function(l){i.css({left:$(this).position().left+($(g).width()/2)-60,top:$(this).position().top+$(this.height)}).show();$(document).bind("click.color-picker",function(){i.hide();$(document).unbind("click.color-picker")});l.stopPropagation()})}else{k.append($("<input />").attr("id",c).attr("name",c).val(b.values[d.key]))}}}});return a},update_from_form:function(a){var c=this;var b=false;$.each(this.params,function(d,f){if(!f.hidden){var g="param_"+d;var e=a.find("#"+g).val();if(f.type=="float"){e=parseFloat(e)}else{if(f.type=="int"){e=parseInt(e)}else{if(f.type=="bool"){e=a.find("#"+g).is(":checked")}}}if(e!==c.values[f.key]){c.values[f.key]=e;b=true}}});if(b){this.onchange()}}});var Track=function(b,a,e,c,d){this.name=b;this.view=a;this.parent_element=e;this.data_url=(c?c:default_data_url);this.data_query_wait=(d?d:DEFAULT_DATA_QUERY_WAIT);this.dataset_check_url=converted_datasets_state_url;this.container_div=$("<div />").addClass("track").css("position","relative");if(!this.hidden){this.header_div=$("<div class='track-header' />").appendTo(this.container_div);if(this.view.editor){this.drag_div=$("<div class='draghandle' />").appendTo(this.header_div)}this.name_div=$("<div class='menubutton popup' />").appendTo(this.header_div);this.name_div.text(this.name);this.name_div.attr("id",this.name.replace(/\s+/g,"-").replace(/[^a-zA-Z0-9\-]/g,"").toLowerCase())}this.content_div=$("<div class='track-content'>").appendTo(this.container_div);this.parent_element.append(this.container_div)};$.extend(Track.prototype,{init:function(){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");a.container_div.removeClass("nodata error pending");if(!a.dataset_id){return}if(a.view.chrom!=null){$.getJSON(converted_datasets_state_url,{hda_ldda:a.hda_ldda,dataset_id:a.dataset_id,chrom:a.view.chrom},function(b){if(!b||b==="error"||b.kind==="error"){a.container_div.addClass("error");a.content_div.text(DATA_ERROR);if(b.message){var d=a.view.tracks.indexOf(a);var c=$(" <a href='javascript:void(0);'></a>").text("View error").bind("click",function(){show_modal("Trackster Error","<pre>"+b.message+"</pre>",{Close:hide_modal})});a.content_div.append(c)}}else{if(b==="no converter"){a.container_div.addClass("error");a.content_div.text(DATA_NOCONVERTER)}else{if(b==="no data"||(b.data!==undefined&&(b.data===null||b.data.length===0))){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()},a.data_query_wait)}else{if(b.status==="data"){if(b.valid_chroms){a.valid_chroms=b.valid_chroms;a.name_div.data("menu_options")["List chrom/contigs with data"]=function(){show_modal("Chrom/contigs with data","<p>"+a.valid_chroms.join("<br/>")+"</p>",{Close:function(){hide_modal()}})}}a.content_div.text(DATA_OK);if(a.view.chrom){a.content_div.text("");a.content_div.css("height",a.height_px+"px");a.enabled=true;$.when(a.predraw_init()).done(function(){a.draw()})}}}}}}})}},predraw_init:function(){},update_name:function(a){this.old_name=this.name;this.name=a;this.name_div.text(this.name)},revert_name:function(){this.name=this.old_name;this.name_div.text(this.name)}});var TiledTrack=function(g,d,s){var o=this,j=o.view;this.filters=(g!==undefined?get_filters_from_dict(g):[]);this.tool=(d!==undefined?get_tool_from_dict(d):undefined);this.parent_track=s;this.child_tracks=[];if(o.hidden){return}if(this.parent_track){this.header_div.find(".draghandle").removeClass("draghandle").addClass("child-track-icon").addClass("icon-button");this.parent_element.addClass("child-track");this.tool=undefined}this.filtering_div=$("<div/>").addClass("track-filters").hide();this.header_div.after(this.filtering_div);this.filtering_div.bind("drag",function(i){i.stopPropagation()}).bind("dblclick",function(i){i.stopPropagation()});var t=$("<table class='filters'>").appendTo(this.filtering_div);$.each(this.filters,function(w,z){var v=$("<tr>").appendTo(t);var y=$("<th class='filter-info'>").appendTo(v);var u=$("<span class='name'>").appendTo(y);u.text(z.name+" ");var i=$("<span class='values'>").appendTo(y);var x=$("<td>").appendTo(v);z.control_element=$("<div id='"+z.name+"-filter-control' style='width: 200px; position: relative'>").appendTo(x);z.control_element.slider({range:true,min:Number.MAX_VALUE,max:-Number.MIN_VALUE,values:[0,0],slide:function(B,C){var A=C.values;i.text("["+A[0]+"-"+A[1]+"]");z.low=A[0];z.high=A[1];o.draw(true)},change:function(A,B){z.control_element.slider("option","slide").call(z.control_element,A,B)}});z.slider=z.control_element;z.slider_label=i});if(this.tool){this.dynamic_tool_div=$("<div/>").addClass("dynamic-tool").hide();this.header_div.after(this.dynamic_tool_div);this.dynamic_tool_div.bind("drag",function(i){i.stopPropagation()}).bind("click",function(i){i.stopPropagation()}).bind("dblclick",function(i){i.stopPropagation()});var l=$("<div class='tool-name'>").appendTo(this.dynamic_tool_div).text(this.tool.name);var e=this.tool.params;var o=this;$.each(this.tool.params,function(A,v){var y=$("<div>").addClass("param-row").appendTo(o.dynamic_tool_div);var x=$("<div>").addClass("slider-label").appendTo(y);var C=$("<span class='param-name'>").text(v.label+" ").appendTo(x);var w=$("<span/>").text(v.value);var z=$("<span class='param-value'>").appendTo(x).append("[").append(w).append("]");var B=$("<div/>").addClass("slider").appendTo(y);var i=$("<div id='"+v.name+"-param-control'>").appendTo(B);var u=(v.max<=1?0.01:(v.max<=1000?1:5));i.slider({min:v.min,max:v.max,step:u,value:v.value,slide:function(D,F){var E=F.value;v.value=E;if(0<E&&E<1){E=parseFloat(E).toFixed(2)}w.text(E)},change:function(D,E){v.value=E.value}});z.click(function(){var F=w,E=F.text(),D=(v.max<=1?4:v.max.length);F.text("");$("<input type='text'/>").attr("size",D).attr("maxlength",D).attr("value",E).appendTo(F).focus().select().click(function(G){G.stopPropagation()}).blur(function(){$(this).remove();F.text(E)}).keyup(function(I){if(I.keyCode===27){$(this).trigger("blur")}else{if(I.keyCode===13){var G=$(this),H=parseFloat(G.val());if(isNaN(H)||H>v.max||H<v.min){alert("Parameter value must be in the range ["+v.min+"-"+v.max+"]");return $(this)}F.text(H);i.slider("value",H);v.value=H}}})});$("<div style='clear: both;'/>").appendTo(y)});var b=$("<div>").addClass("param-row").appendTo(this.dynamic_tool_div);var n=$("<input type='submit'>").attr("value","Run").appendTo(b);var o=this;n.click(function(){o.run_tool()})}o.child_tracks_container=$("<div/>").addClass("child-tracks-container").hide();o.container_div.append(o.child_tracks_container);if(o.display_modes!==undefined){if(o.mode_div===undefined){o.mode_div=$("<div class='right-float menubutton popup' />").appendTo(o.header_div);var m=o.display_modes[0];o.mode=m;o.mode_div.text(m);var a=function(i){o.mode_div.text(i);o.mode=i;o.tile_cache.clear();o.draw()};var f={};for(var q=0,r=o.display_modes.length;q<r;q++){var k=o.display_modes[q];f[k]=function(i){return function(){a(i)}}(k)}make_popupmenu(o.mode_div,f)}else{o.mode_div.hide()}}var h={};h["Edit configuration"]=function(){var v=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},i=function(){o.track_config.update_from_form($(".dialog-box"));hide_modal();$(window).unbind("keypress.check_enter_esc")},u=function(w){if((w.keyCode||w.which)===27){v()}else{if((w.keyCode||w.which)===13){i()}}};$(window).bind("keypress.check_enter_esc",u);show_modal("Configure Track",o.track_config.build_form(),{Cancel:v,OK:i})};if(o.filters.length>0){h["Show filters"]=function(){var i;if(!o.filtering_div.is(":visible")){i="Hide filters";o.filters_visible=true}else{i="Show filters";o.filters_visible=false}o.filtering_div.toggle()}}if(o.tool){h["Toggle Tool"]=function(){var i;if(!o.dynamic_tool_div.is(":visible")){i="Hide dynamic tool";o.update_name(o.name+o.tool_region_and_parameters_str())}else{i="Show dynamic tool";o.revert_name()}o.dynamic_tool_div.toggle()}}var c=j;var p=function(){$("#no-tracks").show()};if(this.parent_track){c=this.parent_track;p=function(){}}h.Remove=function(){c.remove_track(o);if(c.num_tracks===0){p()}};o.popup_menu=make_popupmenu(o.name_div,h)};$.extend(TiledTrack.prototype,Track.prototype,{draw:function(b){var m=this.view.low,g=this.view.high,j=g-m,c=this.view.container.width(),f=this.view.resolution;var p=$("<div style='position: relative;'></div>"),r=c/j;this.content_div.append(p);this.max_height=0;var a=Math.floor(m/f/DENSITY);var l=0;while((a*DENSITY*f)<g){var n=c+"_"+r+"_"+a;var e=this.tile_cache.get(n);var k=a*DENSITY*this.view.resolution;var q=k+DENSITY*this.view.resolution;if(!b&&e){this.show_tile(e,p,k,r)}else{this.delayed_draw(b,n,k,q,a,f,p,r)}a+=1}var d=this;var o=setInterval(function(){if(l===0){var u=d.content_div.children();var t=false;for(var v=u.length-1,s=0;v>=s;v--){var x=$(u[v]);if(t){x.remove()}else{if(x.children().length!==0){t=true}}}for(var w=0;w<d.filters.length;w++){d.filters[w].update_ui_elt()}clearInterval(o)}},50);for(var h=0;h<this.child_tracks.length;h++){this.child_tracks[h].draw(b)}},delayed_draw:function(b,g,f,i,c,e,h,j){var d=this;var a=setTimeout(function(){if(f<=d.view.high&&i>=d.view.low){var k;if(!b){k=d.tile_cache.get(g)}if(!k){k=d.draw_tile(e,c,h,j);if(k){var l=$("<div class='track-tile'>").prepend(k);if(k.hasClass(FILTERABLE_CLASS)){l.addClass(FILTERABLE_CLASS)}k=l}}if(k){d.tile_cache.set(g,k);d.show_tile(k,h,f,j)}}},50)},show_tile:function(a,f,d,g){var b=this;var c=this.view.high-this.view.low,e=(d-this.view.low)*g;if(this.left_offset){e-=this.left_offset}a.css({position:"absolute",top:0,left:e,height:""});f.append(a);b.max_height=Math.max(b.max_height,a.height());b.content_div.css("height",b.max_height+"px");f.children().css("height",b.max_height+"px");if(b.hidden){return}if(a.hasClass(FILTERABLE_CLASS)){show_hide_popupmenu_options(b.popup_menu,"(Show|Hide) filters");if(b.filters_visible){b.filtering_div.show()}}else{show_hide_popupmenu_options(b.popup_menu,"(Show|Hide) filters",false);b.filtering_div.hide()}},set_overview:function(){var a=this.view;if(this.initial_canvas&&this.is_overview){a.overview_close.show();a.overview_viewport.append(this.initial_canvas);a.overview_highlight.show().height(this.initial_canvas.height());a.overview_viewport.height(this.initial_canvas.height()+a.overview_box.height())}$(window).trigger("resize")},run_tool:function(){var b={dataset_id:this.original_dataset_id,chrom:this.view.chrom,low:this.view.low,high:this.view.high,tool_id:this.tool.name};$.extend(b,this.tool.get_param_values_dict());var d=this,c=b.tool_id+d.tool_region_and_parameters_str(b.chrom,b.low,b.high),e;if(d.track_type=="FeatureTrack"){e=new ToolDataFeatureTrack(c,view,undefined,{},{},d)}this.add_track(e);e.content_div.text("Starting job.");view.has_changes=true;var a=function(){$.getJSON(run_tool_url,b,function(f){if(f=="no converter"){e.container_div.addClass("error");e.content_div.text(DATA_NOCONVERTER)}else{if(f.error){e.container_div.addClass("error");e.content_div.text(DATA_CANNOT_RUN_TOOL+f.message)}else{if(f=="pending"){e.container_div.addClass("pending");e.content_div.text("Converting input data so that it can be easily reused.");setTimeout(a,2000)}else{e.dataset_id=f.dataset_id;e.content_div.text("Running job.");e.init()}}}})};a()},tool_region_and_parameters_str:function(c,a,d){var b=this,e=(c!==undefined&&a!==undefined&&d!==undefined?c+":"+a+"-"+d:"all");return" - region=["+e+"], parameters=["+b.tool.get_param_values().join(", ")+"]"},add_track:function(a){a.track_id=this.track_id+"_"+this.child_tracks.length;a.container_div.attr("id","track_"+a.track_id);this.child_tracks_container.append(a.container_div);sortable(a.container_div,".child-track-icon");if(!$(this.child_tracks_container).is(":visible")){this.child_tracks_container.show()}this.child_tracks.push(a)},remove_track:function(a){a.container_div.fadeOut("slow",function(){$(this).remove()})}});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.view.container.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 ReferenceTrack=function(a){this.track_type="ReferenceTrack";this.hidden=true;Track.call(this,null,a,a.top_labeltrack);TiledTrack.call(this);this.left_offset=200;this.height_px=12;this.container_div.addClass("reference-track");this.content_div.css("background","none");this.content_div.css("min-height","0px");this.content_div.css("border","none");this.data_queue={};this.data_cache=new DataCache(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,i){console.log(h,g,i)}})}},draw_tile:function(f,b,k,o){var g=b*DENSITY*f,d=DENSITY*f,j=f+"_"+b;var e=document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(e)}e=$(e);var n=e.get(0).getContext("2d");if(o>CHAR_WIDTH_PX){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;for(var h=0,l=m.length;h<l;h++){var a=Math.round(h*o),i=Math.round(o/2);n.fillText(m[h],a+this.left_offset+i,10)}k.append(e);return e}this.content_div.css("height","0px")}});var LineTrack=function(e,c,f,a,d){var b=this;this.track_type="LineTrack";this.display_modes=["Histogram","Line","Filled","Intensity"];this.mode="Histogram";Track.call(this,e,c,c.viewport_container);TiledTrack.call(this);this.min_height_px=16;this.max_height_px=400;this.height_px=80;this.hda_ldda=f;this.dataset_id=a;this.original_dataset_id=a;this.data_cache=new DataCache(CACHED_DATA);this.tile_cache=new Cache(CACHED_TILES_LINE);this.track_config=new TrackConfig({track:this,params:[{key:"color",label:"Color",type:"color",default_value:"black"},{key:"min_value",label:"Min Value",type:"float",default_value:undefined},{key:"max_value",label:"Max Value",type:"float",default_value:undefined},{key:"mode",type:"string",default_value:this.mode,hidden:true},{key:"height",type:"int",default_value:this.height_px,hidden:true}],saved_values:d,onchange:function(){b.vertical_range=b.prefs.max_value-b.prefs.min_value;$("#linetrack_"+b.track_id+"_minval").text(b.prefs.min_value);$("#linetrack_"+b.track_id+"_maxval").text(b.prefs.max_value);b.tile_cache.clear();b.draw()}});this.prefs=this.track_config.values;this.height_px=this.track_config.values.height;this.vertical_range=this.track_config.values.max_value-this.track_config.values.min_value;(function(g){var j=false;var i=false;var h=$("<div class='track-resize'>");$(g.container_div).hover(function(){j=true;h.show()},function(){j=false;if(!i){h.hide()}});h.hide().bind("dragstart",function(k,l){i=true;l.original_height=$(g.content_div).height()}).bind("drag",function(l,m){var k=Math.min(Math.max(m.original_height+m.deltaY,g.min_height_px),g.max_height_px);$(g.content_div).css("height",k);g.height_px=k;g.draw(true)}).bind("dragend",function(k,l){g.tile_cache.clear();i=false;if(!j){h.hide()}g.track_config.values.height=g.height_px}).appendTo(g.container_div)})(this)};$.extend(LineTrack.prototype,TiledTrack.prototype,{predraw_init:function(){var a=this,b=a.view.tracks.indexOf(a);a.vertical_range=undefined;return $.getJSON(a.data_url,{stats:true,chrom:a.view.chrom,low:null,high:null,hda_ldda:a.hda_ldda,dataset_id:a.dataset_id},function(c){a.container_div.addClass("line-track");var e=c.data;if(isNaN(parseFloat(a.prefs.min_value))||isNaN(parseFloat(a.prefs.max_value))){a.prefs.min_value=e.min;a.prefs.max_value=e.max;$("#track_"+b+"_minval").val(a.prefs.min_value);$("#track_"+b+"_maxval").val(a.prefs.max_value)}a.vertical_range=a.prefs.max_value-a.prefs.min_value;a.total_frequency=e.total_frequency;a.container_div.find(".yaxislabel").remove();var f=$("<div />").addClass("yaxislabel").attr("id","linetrack_"+b+"_minval").text(round_1000(a.prefs.min_value));var d=$("<div />").addClass("yaxislabel").attr("id","linetrack_"+b+"_maxval").text(round_1000(a.prefs.max_value));d.css({position:"absolute",top:"24px",left:"10px"});d.prependTo(a.container_div);f.css({position:"absolute",bottom:"2px",left:"10px"});f.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:this.data_url,dataType:"json",data:{chrom:this.view.chrom,low:a,high:f,hda_ldda:this.hda_ldda,dataset_id:this.dataset_id,resolution:this.view.resolution},success:function(g){var h=g.data;c.data_cache.set(e,h);delete c.data_queue[e];c.draw()},error:function(h,g,i){console.log(h,g,i)}})}},draw_tile:function(o,r,c,e){if(this.vertical_range===undefined){return}var s=r*DENSITY*o,a=DENSITY*o,x=o+"_"+r;var b=document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(b)}b=$(b);if(this.data_cache.get(x)===undefined){this.get_data(o,r);return}var v=this.data_cache.get(x);if(!v){return}b.get(0).width=Math.ceil(a*e);b.get(0).height=this.height_px;var n=b.get(0).getContext("2d"),j=false,k=this.prefs.min_value,g=this.prefs.max_value,m=this.vertical_range,t=this.total_frequency,d=this.height_px,l=this.mode;var w=Math.round(d+k/m*d);n.beginPath();n.moveTo(0,w);n.lineTo(a*e,w);n.fillStyle="#aaa";n.stroke();n.beginPath();n.fillStyle=this.prefs.color;var u,h,f;if(v.length>1){f=Math.ceil((v[1][0]-v[0][0])*e)}else{f=10}for(var p=0,q=v.length;p<q;p++){u=Math.round((v[p][0]-s)*e);h=v[p][1];if(h===null){if(j&&l==="Filled"){n.lineTo(u,d)}j=false;continue}if(h<k){h=k}else{if(h>g){h=g}}if(l==="Histogram"){h=Math.round(h/m*d);n.fillRect(u,w,f,-h)}else{if(l==="Intensity"){h=255-Math.floor((h-k)/m*255);n.fillStyle="rgb("+h+","+h+","+h+")";n.fillRect(u,0,f,d)}else{h=Math.round(d-(h-k)/m*d);if(j){n.lineTo(u,h)}else{j=true;if(l==="Filled"){n.moveTo(u,d);n.lineTo(u,h)}else{n.moveTo(u,h)}}}}}if(l==="Filled"){if(j){n.lineTo(u,w);n.lineTo(0,w)}n.fill()}else{n.stroke()}return b}});var FeatureTrack=function(a,f,e,i,h,c,d,g){var b=this;this.track_type="FeatureTrack";this.display_modes=["Auto","Dense","Squish","Pack"];Track.call(this,a,f,f.viewport_container);TiledTrack.call(this,c,d,g);this.height_px=0;this.container_div.addClass("feature-track");this.hda_ldda=e;this.dataset_id=i;this.original_dataset_id=i;this.zo_slots={};this.show_labels_scale=0.001;this.showing_details=false;this.summary_draw_height=30;this.default_font=DEFAULT_FONT;this.inc_slots={};this.data_queue={};this.start_end_dct={};this.tile_cache=new Cache(CACHED_TILES_FEATURE);this.data_cache=new DataCache(20);this.left_offset=200;this.track_config=new TrackConfig({track:this,params:[{key:"block_color",label:"Block color",type:"color",default_value:"#444"},{key:"label_color",label:"Label color",type:"color",default_value:"black"},{key:"show_counts",label:"Show summary counts",type:"bool",default_value:true}],saved_values:h,onchange:function(){b.tile_cache.clear();b.draw()}});this.prefs=this.track_config.values};$.extend(FeatureTrack.prototype,TiledTrack.prototype,{get_data:function(a,d){var b=this,c=a+"_"+d;if(!b.data_queue[c]){b.data_queue[c]=true;$.getJSON(b.data_url,{chrom:b.view.chrom,low:a,high:d,hda_ldda:b.hda_ldda,dataset_id:b.dataset_id,resolution:this.view.resolution,mode:this.mode},function(e){b.data_cache.set_data(a,d,b.mode,e);delete b.data_queue[c];b.draw()})}},incremental_slots:function(a,j,d,q){var r=this.inc_slots[a];if(!r||(r.mode!==q)){r={};r.w_scale=a;r.mode=q;this.inc_slots[a]=r;this.start_end_dct[a]={}}var m=r.w_scale,x=[],y=[],k=0,o=this.view.max_low;for(var v=0,w=j.length;v<w;v++){var h=j[v],l=h[0];if(r[l]!==undefined){k=Math.max(k,r[l]);y.push(r[l])}else{x.push(v)}}var e=this.start_end_dct[a];var n=function(D,E){for(var C=0;C<=MAX_FEATURE_DEPTH;C++){var A=false,F=e[C];if(F!==undefined){for(var z=0,B=F.length;z<B;z++){var i=F[z];if(E>i[0]&&D<i[1]){A=true;break}}}if(!A){return C}}return -1};for(var v=0,w=x.length;v<w;v++){var h=j[x[v]],l=h[0],t=h[1],b=h[2],p=h[3],c=Math.floor((t-o)*m),g=Math.ceil((b-o)*m),u=CONTEXT.measureText(p).width,f;if(p!==undefined&&!d){u+=(LABEL_SPACING+PACK_SPACING);if(c-u>=0){c-=u;f="left"}else{g+=u;f="right"}}var s=n(c,g);if(s>=0){if(e[s]===undefined){e[s]=[]}e[s].push([c,g]);r[l]=s;k=Math.max(k,s)}else{}}return k},rect_or_text:function(v,n,z,d,u,l,h,g){v.textAlign="center";var b=[z,d],q=0,w=0,t=Math.round(n/2);var E=[];for(var o=0,y=l.length;o<y;o++){var m=l[o],e="MIDNSHP=X"[m[0]],p=m[1];if(e==="H"||e==="S"){q-=p}var j=u+q,D=Math.floor(Math.max(0,(j-z)*n)),k=Math.floor(Math.max(0,(j+p-z)*n));switch(e){case"H":break;case"S":case"M":case"=":var r=compute_overlap([j,j+p],b);if(r!=NO_OVERLAP){var s=h.slice(w,w+p);if((this.mode==="Pack"||this.mode==="Auto")&&h!==undefined&&n>CHAR_WIDTH_PX){v.fillStyle=this.prefs.block_color;v.fillRect(D+this.left_offset,g+1,k-D,9);v.fillStyle=CONNECTOR_COLOR;for(var B=0,a=s.length;B<a;B++){if(j+B>=z&&j+B<=d){var C=Math.floor(Math.max(0,(j+B-z)*n));v.fillText(s[B],C+this.left_offset+t,g+9)}}}else{v.fillStyle=this.prefs.block_color;v.fillRect(D+this.left_offset,g+(this.mode!="Dense"?4:5),k-D,(this.mode!="Dense"?SQUISH_FEATURE_HEIGHT:DENSE_FEATURE_HEIGHT))}}w+=p;q+=p;break;case"N":v.fillStyle=CONNECTOR_COLOR;v.fillRect(D+this.left_offset,g+5,k-D,1);q+=p;break;case"D":v.fillStyle="red";v.fillRect(D+this.left_offset,g+4,k-D,3);q+=p;break;case"P":break;case"I":var r=compute_overlap([j,j+p],b);if(r!=NO_OVERLAP){var s=h.slice(w,w+p);var f=this.left_offset+D-(k-D)/2;if((this.mode==="Pack"||this.mode==="Auto")&&h!==undefined&&n>CHAR_WIDTH_PX){v.fillStyle="yellow";v.fillRect(f,g-9,k-D,9);E[E.length]=[f+(k-D)/2,g+4,5];v.fillStyle=CONNECTOR_COLOR;switch(r){case (OVERLAP_START):s=s.slice(z-j);break;case (OVERLAP_END):s=s.slice(0,j-d);break;case (CONTAINED_BY):break;case (CONTAINS):s=s.slice(z-j,j-d);break}for(var B=0,a=s.length;B<a;B++){var C=Math.floor(Math.max(0,(j+B-z)*n));v.fillText(s[B],C+this.left_offset+t-(k-D)/2,g)}}else{v.fillStyle="yellow";v.fillRect(f,g+(this.mode!="Dense"?2:5),k-D,(this.mode!="Dense"?SQUISH_FEATURE_HEIGHT:DENSE_FEATURE_HEIGHT))}}w+=p;break;case"X":w+=p;break}}var A;for(var x=0;x<E.length;x++){A=E[x];v.fillStyle="yellow";v.drawDownwardEquilateralTriangle(A[0],A[1],A[2])}},draw_tile:function(ae,m,q,au){var K=m*DENSITY*ae,aj=(m+1)*DENSITY*ae,J=aj-K;var G=this.data_cache.get_data(K,aj,this.mode);if(G===undefined||G==="pending"||(this.mode!=="Auto"&&G.dataset_type==="summary_tree")){this.data_queue[[K,aj]]=true;this.get_data(K,aj);return}var a=Math.ceil(J*au),ag=this.prefs.label_color,g=this.prefs.block_color,p=this.mode,u=25,aa,V=this.left_offset,at,B,av;var o=document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(o)}o=$(o);if(G.dataset_type==="summary_tree"){B=this.summary_draw_height}else{if(p==="Dense"){B=u;av=DENSE_TRACK_HEIGHT}else{if(p==="Squish"){av=SQUISH_TRACK_HEIGHT;aa=true}else{if(p==="Pack"){av=PACK_TRACK_HEIGHT;aa=false}else{if(G.extra_info==="no_detail"){av=(G.track_type==="bai"?SQUISH_TRACK_HEIGHT:NO_DETAIL_TRACK_HEIGHT);aa=true}else{av=PACK_TRACK_HEIGHT;aa=false}}}B=this.incremental_slots(au,G.data,aa,p)*av+u;at=this.inc_slots[au]}}o.get(0).width=a+V;o.get(0).height=B;if(G.dataset_type=="summary_tree"){o.get(0).height+=LABEL_SPACING+CHAR_HEIGHT_PX}q.parent().css("height",Math.max(this.height_px,B)+"px");var H=o.get(0).getContext("2d");H.fillStyle=g;H.font=this.default_font;H.textAlign="right";this.container_div.find(".yaxislabel").remove();if(G.dataset_type=="summary_tree"){var v=B+LABEL_SPACING+CHAR_HEIGHT_PX;points=G.data,max=G.max,delta_x_px=Math.ceil(G.delta*au);var n=$("<div />").addClass("yaxislabel");n.text(max);n.css({position:"absolute",top:"22px",left:"10px"});n.prependTo(this.container_div);for(var an=0,F=points.length;an<F;an++){var Z=Math.floor((points[an][0]-K)*au);var Y=points[an][1];if(!Y){continue}var ak=Y/max*B;H.fillStyle="black";H.fillRect(Z+V,v-ak,delta_x_px,ak);var X=4;if(this.prefs.show_counts&&(H.measureText(Y).width+X)<delta_x_px){H.fillStyle="#666";H.textAlign="center";H.fillText(Y,Z+V+(delta_x_px/2),10)}}return o}if(G.message){o.css({"border-color":"red"});H.fillStyle="red";H.textAlign="left";H.fillText(G.message,100+V,av);if(!G.data){return o}}for(var aq=0;aq<this.filters.length;aq++){if(G.data.length&&this.filters[aq].applies_to(G.data[0])){o.addClass(FILTERABLE_CLASS);break}}var ar=G.data;var am=0;for(var an=0,F=ar.length;an<F;an++){var R=ar[an],O=R[0],ap=R[1],ac=R[2],L=R[3];if(this.mode!="Dense"&&at[O]===undefined){continue}var ab=false;var T;for(var aq=0;aq<this.filters.length;aq++){T=this.filters[aq];T.update_attrs(R);if(!T.keep(R)){ab=true;break}}if(ab){continue}if(ap<=aj&&ac>=K){if(G.dataset_type=="interval_index"){ac-=1}var ad=Math.floor(Math.max(0,(ap-K)*au)),I=Math.ceil(Math.min(a,Math.max(0,(ac-K)*au))),W=(p==="Dense"?1:(1+at[O]))*av;var E,ah,M=null,aw=null;if(G.dataset_type==="bai"){H.fillStyle=g;if(R[5] instanceof Array){var C=Math.floor(Math.max(0,(R[4][0]-K)*au)),N=Math.ceil(Math.min(a,Math.max(0,(R[4][1]-K)*au))),A=Math.floor(Math.max(0,(R[5][0]-K)*au)),t=Math.ceil(Math.min(a,Math.max(0,(R[5][1]-K)*au)));if(R[4][1]>=K&&R[4][0]<=aj&&R[4][2]){this.rect_or_text(H,au,K,aj,R[4][0],R[4][2],R[4][3],W)}if(R[5][1]>=K&&R[5][0]<=aj&&R[5][2]){this.rect_or_text(H,au,K,aj,R[5][0],R[5][2],R[5][3],W)}if(A>N){H.fillStyle=CONNECTOR_COLOR;H.dashedLine(N+V,W+5,V+A,W+5)}}else{H.fillStyle=g;this.rect_or_text(H,au,K,aj,ap,R[4],R[5],W)}if(p!=="Dense"&&!aa&&ap>K){H.fillStyle=this.prefs.label_color;if(m===0&&ad-H.measureText(L).width<0){H.textAlign="left";H.fillText(L,I+V+LABEL_SPACING,W+8)}else{H.textAlign="right";H.fillText(L,ad+V-LABEL_SPACING,W+8)}H.fillStyle=g}}else{if(G.dataset_type==="interval_index"){if(p=="Auto"){if(R.length<=4){p="Squish"}else{p="Pack"}}if(p=="Dense"){H.fillStyle=g;H.fillRect(ad+V,W+5,I-ad,DENSE_FEATURE_HEIGHT)}else{if(R.length<=4){H.fillStyle=g;H.fillRect(ad+V,W+5,I-ad,DENSE_FEATURE_HEIGHT)}else{var D=R[5],U=R[6],af=R[7],e=R[8];if(U&&af){M=Math.floor(Math.max(0,(U-K)*au));aw=Math.ceil(Math.min(a,Math.max(0,(af-K)*au)))}var ao,P;if(p=="Squish"){ao=1;P=SQUISH_FEATURE_HEIGHT}else{ao=5;P=PACK_FEATURE_HEIGHT}if(!e){if(R.strand){if(R.strand=="+"){H.fillStyle=RIGHT_STRAND_INV}else{if(R.strand=="-"){H.fillStyle=LEFT_STRAND_INV}}}else{H.fillStyle=CONNECTOR_COLOR}H.fillRect(ad+V,W+(P-ao)/2+1,I-ad,P)}else{var z,Q;if(p=="Squish"){H.fillStyle=CONNECTOR_COLOR;z=W+Math.floor(SQUISH_FEATURE_HEIGHT/2)+1;Q=1}else{if(D){var z=W;var Q=P;if(D=="+"){H.fillStyle=RIGHT_STRAND}else{if(D=="-"){H.fillStyle=LEFT_STRAND}}}else{H.fillStyle=CONNECTOR_COLOR;z+=(SQUISH_FEATURE_HEIGHT/2)+1;Q=1}}H.fillRect(ad+V,z,I-ad,Q);for(var al=0,d=e.length;al<d;al++){var s=e[al],c=Math.floor(Math.max(0,(s[0]-K)*au)),S=Math.ceil(Math.min(a,Math.max((s[1]-K)*au)));if(c>S){continue}H.fillStyle=g;H.fillRect(c+V,W+(P-ao)/2+1,S-c,ao);if(M!==undefined&&!(c>aw||S<M)){var ai=Math.max(c,M),w=Math.min(S,aw-1);H.fillRect(ai+V,W+1,w-ai,P)}}}if(p=="Pack"&&ap>K){H.fillStyle=ag;if(m===0&&ad-H.measureText(L).width<0){H.textAlign="left";H.fillText(L,I+V+LABEL_SPACING,W+8)}else{H.textAlign="right";H.fillText(L,ad+V-LABEL_SPACING,W+8)}H.fillStyle=g}}}}else{if(G.dataset_type==="vcf"){if(aa){H.fillStyle=g;H.fillRect(ad+V,W+5,I-ad,1)}else{var r=R[4],l=R[5],b=R[6];E=9;ah=1;H.fillRect(ad+V,W,I-ad,E);if(p!=="Dense"&&L!==undefined&&ap>K){H.fillStyle=ag;if(m===0&&ad-H.measureText(L).width<0){H.textAlign="left";H.fillText(L,I+2+V,W+8)}else{H.textAlign="right";H.fillText(L,ad-2+V,W+8)}H.fillStyle=g}var h=r+" / "+l;if(ap>K&&H.measureText(h).width<(I-ad)){H.fillStyle="white";H.textAlign="center";H.fillText(h,V+ad+(I-ad)/2,W+8);H.fillStyle=g}}}}}am++}}return o}});var ReadTrack=function(d,b,f,a,c,e){FeatureTrack.call(this,d,b,f,a,c,e);this.track_type="ReadTrack"};$.extend(ReadTrack.prototype,TiledTrack.prototype,FeatureTrack.prototype,{});var ToolDataFeatureTrack=function(e,c,g,a,d,f,b){FeatureTrack.call(this,e,c,g,a,d,f,{},b);this.track_type="ToolDataFeatureTrack";this.data_url=raw_data_url;this.data_query_wait=1000;this.dataset_check_url=dataset_state_url};$.extend(ToolDataFeatureTrack.prototype,TiledTrack.prototype,FeatureTrack.prototype,{predraw_init:function(){var b=this;var a=function(){if(b.data_cache.size()==0){setTimeout(a,300)}else{b.data_url=default_data_url;b.data_query_wait=DEFAULT_DATA_QUERY_WAIT;b.dataset_state_url=converted_datasets_state_url;$.getJSON(b.dataset_state_url,{dataset_id:b.dataset_id},function(c){})}};a()}});
\ No newline at end of file
--- a/static/scripts/trackster.js Mon Feb 21 09:46:54 2011 -0500
+++ b/static/scripts/trackster.js Mon Feb 21 11:49:24 2011 -0500
@@ -24,6 +24,29 @@
}
};
+/**
+ * Draw an isosceles triangle that points down.
+ */
+CanvasRenderingContext2D.prototype.drawDownwardEquilateralTriangle = function(down_vertex_x, down_vertex_y, side_len) {
+ // Compute other two points of triangle.
+ var
+ x1 = down_vertex_x - side_len/2,
+ x2 = down_vertex_x + side_len/2,
+ y = down_vertex_y - Math.sqrt( side_len*3/2 );
+
+ // Draw and fill.
+ this.beginPath();
+ this.moveTo(x1, y);
+ this.lineTo(x2, y);
+ this.lineTo(down_vertex_x, down_vertex_y);
+ this.lineTo(x1, y);
+
+ this.strokeStyle = this.fillStyle;
+ this.fill();
+ this.stroke();
+ this.closePath();
+}
+
/**
* Make `element` sortable in parent by dragging `handle` (a selector)
*/
@@ -51,7 +74,49 @@
});
}
+/**
+ * Compute the type of overlap between two regions. They are assumed to be on the same chrom/contig.
+ * The overlap is computed relative to the second region; hence, OVERLAP_START indicates that the first
+ * region overlaps the start (but not the end) of the second region.
+ */
+var NO_OVERLAP = 1001, CONTAINS = 1002, OVERLAP_START = 1003, OVERLAP_END = 1004, CONTAINED_BY = 1005;
+function compute_overlap(first_region, second_region) {
+ var
+ first_start = first_region[0], first_end = first_region[1],
+ second_start = second_region[0], second_end = second_region[1],
+ overlap;
+ if (first_start < second_start) {
+ if (first_end < second_start) {
+ overlap = NO_OVERLAP;
+ }
+ else if (first_end <= second_end) {
+ overlap = OVERLAP_START;
+ }
+ else { // first_end > second_end
+ overlap = CONTAINS;
+ }
+ }
+ else { // first_start >= second_start
+ if (first_start > second_end) {
+ overlap = NO_OVERLAP;
+ }
+ else if (first_end <= second_end) {
+ overlap = CONTAINED_BY;
+ }
+ else {
+ overlap = OVERLAP_END;
+ }
+ }
+
+ return overlap;
+}
+/**
+ * Returns true if there is any overlap between regions.
+ */
+function is_overlap(first_region, second_region) {
+ return (compute_overlap(first_region, second_region) != NO_OVERLAP);
+}
/**
* Init constants & functions used throughout trackster.
@@ -2192,11 +2257,18 @@
return highest_slot;
},
// Right now this function is used only for rendering BAM reads.
- rect_or_text: function( ctx, w_scale, tile_low, tile_high, feature_start, cigar, orig_seq, y_center ) {
+ rect_or_text: function(ctx, w_scale, tile_low, tile_high, feature_start, cigar, orig_seq, y_center) {
ctx.textAlign = "center";
- var draw_offset = 0,
+ var
+ tile_region = [tile_low, tile_high],
+ base_offset = 0,
seq_offset = 0,
gap = Math.round(w_scale / 2);
+
+ // Keep list of triangles that need to be drawn on top of initial drawing layer.
+ // TODO: Eventually, we'll probably want to keep an ordered list of items to draw and then draw all
+ // items at once.
+ var draw_last = [];
for (var cig_id = 0, len = cigar.length; cig_id < len; cig_id++) {
var cig = cigar[cig_id],
@@ -2205,69 +2277,135 @@
if (cig_op === "H" || cig_op === "S") {
// Go left if it clips
- draw_offset -= cig_len;
+ base_offset -= cig_len;
}
- var seq_start = feature_start + draw_offset,
+ var seq_start = feature_start + base_offset,
s_start = Math.floor( Math.max(0, (seq_start - tile_low) * w_scale) ),
s_end = Math.floor( Math.max(0, (seq_start + cig_len - tile_low) * w_scale) );
switch (cig_op) {
- case "H": // Hard clipping
+ case "H": // Hard clipping.
// TODO: draw anything?
// Sequence not present, so do not increment seq_offset.
break;
- case "S": // Soft clipping
- case "M": // Match
- case "=":
- var seq = orig_seq.slice(seq_offset, seq_offset + cig_len);
- if ( (this.mode === "Pack" || this.mode === "Auto") && orig_seq !== undefined && w_scale > CHAR_WIDTH_PX) {
- ctx.fillStyle = this.prefs.block_color;
- ctx.fillRect(s_start + this.left_offset, y_center + 1, s_end - s_start, 9);
- ctx.fillStyle = CONNECTOR_COLOR;
- for (var c = 0, str_len = seq.length; c < str_len; c++) {
- if (seq_start + c >= tile_low && seq_start + c <= tile_high) {
- var c_start = Math.floor( Math.max(0, (seq_start + c - tile_low) * w_scale) );
- ctx.fillText(seq[c], c_start + this.left_offset + gap, y_center + 9);
+ case "S": // Soft clipping.
+ case "M": // Match.
+ case "=": // Equals.
+ var seq_tile_overlap = compute_overlap([seq_start, seq_start + cig_len], tile_region);
+ if (seq_tile_overlap != NO_OVERLAP) {
+ // Draw.
+ var seq = orig_seq.slice(seq_offset, seq_offset + cig_len);
+ if ( (this.mode === "Pack" || this.mode === "Auto") && orig_seq !== undefined && w_scale > CHAR_WIDTH_PX) {
+ ctx.fillStyle = this.prefs.block_color;
+ ctx.fillRect(s_start + this.left_offset, y_center + 1, s_end - s_start, 9);
+ ctx.fillStyle = CONNECTOR_COLOR;
+ // TODO: this can be made much more efficient by computing the complete sequence
+ // to draw and then drawing it.
+ for (var c = 0, str_len = seq.length; c < str_len; c++) {
+ if (seq_start + c >= tile_low && seq_start + c <= tile_high) {
+ var c_start = Math.floor( Math.max(0, (seq_start + c - tile_low) * w_scale) );
+ ctx.fillText(seq[c], c_start + this.left_offset + gap, y_center + 9);
+ }
}
+ } else {
+ ctx.fillStyle = this.prefs.block_color;
+ // TODO: This is a pretty hack-ish way to fill rectangle based on mode.
+ ctx.fillRect(s_start + this.left_offset,
+ y_center + (this.mode != "Dense" ? 4 : 5),
+ s_end - s_start,
+ (this.mode != "Dense" ? SQUISH_FEATURE_HEIGHT : DENSE_FEATURE_HEIGHT) );
}
- } else {
- ctx.fillStyle = this.prefs.block_color;
- // TODO: This is a pretty hack-ish way to fill rectangle based on mode.
- ctx.fillRect(s_start + this.left_offset,
- y_center + (this.mode != "Dense" ? 4 : 5),
- s_end - s_start,
- (this.mode != "Dense" ? SQUISH_FEATURE_HEIGHT : DENSE_FEATURE_HEIGHT) );
}
seq_offset += cig_len;
+ base_offset += cig_len;
break;
- case "N": // Skipped bases
+ case "N": // Skipped bases.
ctx.fillStyle = CONNECTOR_COLOR;
ctx.fillRect(s_start + this.left_offset, y_center + 5, s_end - s_start, 1);
//ctx.dashedLine(s_start + this.left_offset, y_center + 5, this.left_offset + s_end, y_center + 5);
+ // No change in seq_offset because sequence not used when skipping.
+ base_offset += cig_len;
break;
- case "D": // Deletion
+ case "D": // Deletion.
ctx.fillStyle = "red";
ctx.fillRect(s_start + this.left_offset, y_center + 4, s_end - s_start, 3);
+ // TODO: is this true? No change in seq_offset because sequence not used when skipping.
+ base_offset += cig_len;
break;
case "P": // TODO: No good way to draw insertions/padding right now, so ignore
// Sequences not present, so do not increment seq_offset.
break;
- case "I":
+ case "I": // Insertion.
+ //
+ // Show insertion above, centered on insertion point.
+ //
+
+ // Check to see if sequence should be drawn at all by looking at the overlap between
+ // the sequence region and the tile region.
+ var seq_tile_overlap = compute_overlap([seq_start, seq_start + cig_len], tile_region);
+ if (seq_tile_overlap != NO_OVERLAP) {
+ // Draw sequence.
+ var seq = orig_seq.slice(seq_offset, seq_offset + cig_len);
+ // X center is offset + start - <half_sequence_length>
+ var x_center = this.left_offset + s_start - (s_end - s_start)/2;
+ if ( (this.mode === "Pack" || this.mode === "Auto") && orig_seq !== undefined && w_scale > CHAR_WIDTH_PX) {
+ // Draw sequence container.
+ ctx.fillStyle = "yellow";
+ ctx.fillRect(x_center, y_center - 9, s_end - s_start, 9);
+ draw_last[draw_last.length] = [x_center + (s_end - s_start)/2, y_center + 4, 5];
+ ctx.fillStyle = CONNECTOR_COLOR;
+ // Based on overlap b/t sequence and tile, get sequence to be drawn.
+ switch(seq_tile_overlap) {
+ case(OVERLAP_START):
+ seq = seq.slice(tile_low-seq_start);
+ break;
+ case(OVERLAP_END):
+ seq = seq.slice(0, seq_start-tile_high);
+ break;
+ case(CONTAINED_BY):
+ // All of sequence drawn.
+ break;
+ case(CONTAINS):
+ seq = seq.slice(tile_low-seq_start, seq_start-tile_high);
+ break;
+ }
+ // Draw sequence.
+ for (var c = 0, str_len = seq.length; c < str_len; c++) {
+ var c_start = Math.floor( Math.max(0, (seq_start + c - tile_low) * w_scale) );
+ ctx.fillText(seq[c], c_start + this.left_offset + gap - (s_end - s_start)/2, y_center);
+ }
+ }
+ else {
+ // Draw block.
+ ctx.fillStyle = "yellow";
+ // TODO: This is a pretty hack-ish way to fill rectangle based on mode.
+ ctx.fillRect(x_center, y_center + (this.mode != "Dense" ? 2 : 5),
+ s_end - s_start, (this.mode != "Dense" ? SQUISH_FEATURE_HEIGHT : DENSE_FEATURE_HEIGHT));
+ }
+ }
seq_offset += cig_len;
+ // No change to base offset because insertions are drawn above sequence/read.
break;
case "X":
// TODO: draw something?
seq_offset += cig_len;
break;
}
- draw_offset += cig_len;
+ }
+
+ // Draw last items.
+ var item;
+ for (var i = 0; i < draw_last.length; i++) {
+ item = draw_last[i];
+ ctx.fillStyle = "yellow";
+ ctx.drawDownwardEquilateralTriangle(item[0], item[1], item[2]);
}
},
draw_tile: function(resolution, tile_index, parent_element, w_scale) {
var tile_low = tile_index * DENSITY * resolution,
tile_high = ( tile_index + 1 ) * DENSITY * resolution,
tile_span = tile_high - tile_low;
- // console.log("drawing " + tile_low + " to " + tile_high);
+ //console.log("drawing " + tile_low + " to " + tile_high);
/*for (var k in this.data_cache.obj_cache) {
var k_split = k.split("_"), k_low = k_split[0], k_high = k_split[1];
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0