3 new changesets in galaxy-central: http://bitbucket.org/galaxy/galaxy-central/changeset/0cd9402d5845/ changeset: r5327:0cd9402d5845 user: james_taylor date: 2011-04-02 20:36:52 summary: trackster: draw intron/exon structure in dense mode, also restore border top for all tracks affected #: 3 files (188 bytes) --- a/static/june_2007_style/blue/trackster.css Sat Apr 02 13:34:08 2011 -0400 +++ b/static/june_2007_style/blue/trackster.css Sat Apr 02 14:36:52 2011 -0400 @@ -22,7 +22,7 @@ .track{background:white;} .track-header{text-align:left;padding:4px 0px;color:#666;} .track-header .menubutton{margin-left:0px;} -.track-content{overflow:hidden;text-align:center;border-bottom:1px solid #bbb;background:#eee url('/static/images/tracks/diag_bg.gif');min-height:16px;} +.track-content{overflow:hidden;text-align:center;border-top:1px solid #eee;border-bottom:1px solid #eee;background:#eee url('/static/images/tracks/diag_bg.gif');min-height:16px;} .label-track .track-content{background:white;} .track-tile{background:white;} .track-tile canvas{position:relative;z-index:100;border:solid white;border-width:2px 0px 0px 0px;} --- a/static/june_2007_style/trackster.css.tmpl Sat Apr 02 13:34:08 2011 -0400 +++ b/static/june_2007_style/trackster.css.tmpl Sat Apr 02 14:36:52 2011 -0400 @@ -146,8 +146,8 @@ .track-content { overflow: hidden; text-align: center; -/* border-top: 1px solid #eee; */ - border-bottom: 1px solid #bbb; + border-top: 1px solid #eee; + border-bottom: 1px solid #eee; background: #eee url('/static/images/tracks/diag_bg.gif'); min-height: 16px; } --- a/static/scripts/trackster.js Sat Apr 02 13:34:08 2011 -0400 +++ b/static/scripts/trackster.js Sat Apr 02 14:36:52 2011 -0400 @@ -2841,7 +2841,7 @@ // Contstants specific to feature tracks moved here (HACKING, these should // basically all be configuration options) -var DENSE_TRACK_HEIGHT = 3, +var DENSE_TRACK_HEIGHT = 10, NO_DETAIL_TRACK_HEIGHT = 3, SQUISH_TRACK_HEIGHT = 5, PACK_TRACK_HEIGHT = 10, @@ -2898,11 +2898,18 @@ 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, y_center, f_end - f_start, DENSE_FEATURE_HEIGHT); } - else if (mode === "no_detail") { + */ + + if ( mode == "Dense" ) { + slot = 1; + } + + if (mode === "no_detail") { // No details for feature, so only one way to display. ctx.fillStyle = block_color; // TODO: what should width be here? @@ -2922,7 +2929,7 @@ // Set vars that depend on mode. var thin_height, thick_height; - if (mode === "Squish") { + if (mode === "Squish" || mode === "Dense" ) { thin_height = 1; thick_height = SQUISH_FEATURE_HEIGHT; } else { // mode === "Pack" @@ -2954,7 +2961,7 @@ // Draw whole feature as connector/intron. var cur_y_center, cur_height; - if (mode === "Squish") { + if (mode === "Squish" || mode === "Dense") { ctx.fillStyle = CONNECTOR_COLOR; cur_y_center = y_center + Math.floor(SQUISH_FEATURE_HEIGHT/2) + 1; cur_height = 1; @@ -2998,8 +3005,9 @@ block_thick_end = Math.min(block_end, thick_end); ctx.fillRect(block_thick_start, y_center + 1, block_thick_end - block_thick_start, thick_height); - if ( feature_blocks.length == 1 ) { - // Exactly one block means we have no introns, but do have a distinct "thick" region + if ( feature_blocks.length == 1 && mode == "Pack") { + // Exactly one block means we have no introns, but do have a distinct "thick" region, + // draw arrows over it if in pack mode if (feature_strand === "+") { ctx.fillStyle = ctx.canvas.manager.get_pattern( 'right_strand_inv' ); } else if (feature_strand === "-") { http://bitbucket.org/galaxy/galaxy-central/changeset/fba5ff42c4fe/ changeset: r5328:fba5ff42c4fe user: james_taylor date: 2011-04-02 20:46:42 summary: Use extend everywhere instead of $.extend affected #: 1 file (96 bytes) --- a/static/scripts/trackster.js Sat Apr 02 14:36:52 2011 -0400 +++ b/static/scripts/trackster.js Sat Apr 02 14:46:42 2011 -0400 @@ -2,6 +2,17 @@ 2010-2011: James Taylor, Kanwei Li, Jeremy Goecks */ +/** Simple extend function for inheritence */ +var extend = function() { + var target = arguments[0]; + for ( var i = 1; i < arguments.length; i++ ) { + var other = arguments[i]; + for ( key in other ) { + target[key] = other[key]; + } + } +}; + // Encapsulate -- anything to be availabe outside this block is added to exports (function(exports){ @@ -30,30 +41,30 @@ this.load_pattern( 'left_strand_inv', "/visualization/strand_left_inv.png" ); } -CanvasManager.prototype.load_pattern = function( key, path ) { - var patterns = this.patterns, - dummy_context = this.dummy_context, - image = new Image(); - // FIXME: where does image_path come from? not in browser.mako... - image.src = image_path + path; - image.onload = function() { - patterns[key] = dummy_context.createPattern( image, "repeat" ); +extend( CanvasManager.prototype, { + load_pattern: function( key, path ) { + var patterns = this.patterns, + dummy_context = this.dummy_context, + image = new Image(); + // FIXME: where does image_path come from? not in browser.mako... + image.src = image_path + path; + image.onload = function() { + patterns[key] = dummy_context.createPattern( image, "repeat" ); + } + }, + get_pattern: function( key ) { + return this.patterns[key]; + }, + new_canvas: function() { + var canvas = this.document.createElement("canvas"); + // If using excanvas in IE, we need to explicately attach the canvas + // methods to the DOM element + if (window.G_vmlCanvasManager) { G_vmlCanvasManager.initElement(canvas); } + // Keep a reference back to the manager + canvas.manager = this; + return canvas; } -} - -CanvasManager.prototype.get_pattern = function( key ) { - return this.patterns[key]; -} - -CanvasManager.prototype.new_canvas = function() { - var canvas = this.document.createElement("canvas"); - // If using excanvas in IE, we need to explicately attach the canvas - // methods to the DOM element - if (window.G_vmlCanvasManager) { G_vmlCanvasManager.initElement(canvas); } - // Keep a reference back to the manager - canvas.manager = this; - return canvas; -} +}); /** * Draw a dashed line on a canvas using filled rectangles. This function is based on: @@ -181,7 +192,7 @@ this.num_elements = num_elements; this.clear(); }; -$.extend(Cache.prototype, { +extend(Cache.prototype, { get: function(key) { var index = this.key_ary.indexOf(key); if (index !== -1) { @@ -225,7 +236,7 @@ this.track = track; this.subset = (subset !== undefined ? subset : true); }; -$.extend(DataManager.prototype, Cache.prototype, { +extend(DataManager.prototype, Cache.prototype, { /** * Load data from server; returns AJAX object so that use of Deferred is possible. */ @@ -342,7 +353,7 @@ this.canvas_manager = new CanvasManager( container.get(0).ownerDocument ); this.reset(); }; -$.extend( View.prototype, { +extend( View.prototype, { init: function( callback ) { // Create DOM elements var parent_element = this.container, @@ -807,7 +818,7 @@ } } }; -$.extend(Tool.prototype, { +extend(Tool.prototype, { // Returns a dictionary of parameter values; key is parameter name, value // is parameter value. get_param_values_dict: function() { @@ -871,7 +882,7 @@ this.slider = null; this.slider_label = null; }; -$.extend(NumberFilter.prototype, { +extend(NumberFilter.prototype, { /** * Returns true if filter can be applied to element. */ @@ -963,7 +974,7 @@ } this.onchange = options.onchange } -$.extend( TrackConfig.prototype, { +extend( TrackConfig.prototype, { restore_values: function( values ) { var track_config = this; $.each( this.params, function( index, param ) { @@ -1094,7 +1105,7 @@ this.content_div = $("<div class='track-content'>").appendTo(this.container_div); this.parent_element.append(this.container_div); }; -$.extend(Track.prototype, { +extend(Track.prototype, { /** * Initialize and draw the track. */ @@ -1481,7 +1492,7 @@ } */ }; -$.extend(TiledTrack.prototype, Track.prototype, { +extend(TiledTrack.prototype, Track.prototype, { /** * Make popup menu for track name. */ @@ -1890,7 +1901,7 @@ Track.call( this, null, view, parent_element ); this.container_div.addClass( "label-track" ); }; -$.extend( LabelTrack.prototype, Track.prototype, { +extend( LabelTrack.prototype, Track.prototype, { draw: function() { var view = this.view, range = view.high - view.low, @@ -1930,7 +1941,7 @@ this.data_cache = new DataManager(CACHED_DATA, this, false); this.tile_cache = new Cache(CACHED_TILES_LINE); }; -$.extend(ReferenceTrack.prototype, TiledTrack.prototype, { +extend(ReferenceTrack.prototype, TiledTrack.prototype, { /** * Draw ReferenceTrack tile. */ @@ -2003,7 +2014,7 @@ this.add_resize_handle(); }; -$.extend(LineTrack.prototype, TiledTrack.prototype, { +extend(LineTrack.prototype, TiledTrack.prototype, { add_resize_handle: function () { // Add control for resizing // Trickery here to deal with the hovering drag handle, can probably be @@ -2145,7 +2156,7 @@ this.painter = LinkedFeaturePainter; }; -$.extend(FeatureTrack.prototype, TiledTrack.prototype, { +extend(FeatureTrack.prototype, TiledTrack.prototype, { update_auto_mode: function( mode ) { if ( this.mode == "Auto" ) { if ( mode == "no_detail" ) { @@ -2332,7 +2343,7 @@ this.painter = VariantPainter; }; -$.extend(VcfTrack.prototype, TiledTrack.prototype, FeatureTrack.prototype); +extend(VcfTrack.prototype, TiledTrack.prototype, FeatureTrack.prototype); var ReadTrack = function (name, view, hda_ldda, dataset_id, prefs, filters) { @@ -2360,7 +2371,7 @@ this.painter = ReadPainter; this.make_name_popup_menu(); }; -$.extend(ReadTrack.prototype, TiledTrack.prototype, FeatureTrack.prototype); +extend(ReadTrack.prototype, TiledTrack.prototype, FeatureTrack.prototype); /** * Feature track that displays data generated from tool. @@ -2376,7 +2387,7 @@ this.dataset_check_url = dataset_state_url; }; -$.extend(ToolDataFeatureTrack.prototype, TiledTrack.prototype, FeatureTrack.prototype, { +extend(ToolDataFeatureTrack.prototype, TiledTrack.prototype, FeatureTrack.prototype, { /** * For this track type, the predraw init sets up postdraw init. */ @@ -2414,18 +2425,6 @@ // ---- To be extracted ------------------------------------------------------ -// ---- Simple extend function for inheritence ---- - -var extend = function() { - var target = arguments[0]; - for ( var i = 1; i < arguments.length; i++ ) { - var other = arguments[i]; - for ( key in other ) { - target[key] = other[key]; - } - } -} - // ---- Feature Packing ---- /** http://bitbucket.org/galaxy/galaxy-central/changeset/60f02d9f79af/ changeset: r5329:60f02d9f79af user: james_taylor date: 2011-04-02 22:02:30 summary: trackster: everything now contained in three distinct modules using CommonJS exports/require style, more fixing coupling and global variables affected #: 1 file (568 bytes) --- a/static/scripts/trackster.js Sat Apr 02 14:46:42 2011 -0400 +++ b/static/scripts/trackster.js Sat Apr 02 16:02:30 2011 -0400 @@ -14,8 +14,11 @@ }; // Encapsulate -- anything to be availabe outside this block is added to exports -(function(exports){ +var trackster_module = function(require, exports){ +var slotting = require('slotting'), + painters = require('painters'); + // ---- Canvas management and extensions ---- /** @@ -160,7 +163,8 @@ CHAR_HEIGHT_PX = 9, // FIXME: font size may not be static ERROR_PADDING = 10, // Padding at the top of tracks for error messages SUMMARY_TREE_TOP_PADDING = CHAR_HEIGHT_PX + 2, - + // Maximum number of rows un a slotted track + MAX_FEATURE_DEPTH = 100, // Minimum width for window for squish to be used. MIN_SQUISH_VIEW_WIDTH = 12000, @@ -2100,8 +2104,8 @@ // Paint line onto full canvas var ctx = canvas.getContext("2d"); - var painter = new LinePainter( result.data, tile_low, tile_low + tile_length, - this.prefs.min_value, this.prefs.max_value, this.prefs.color, this.mode ); + var painter = new painters.LinePainter( result.data, tile_low, tile_low + tile_length, + this.prefs.min_value, this.prefs.max_value, this.prefs.color, this.mode ); painter.draw( ctx, width, height ); return canvas; @@ -2154,7 +2158,7 @@ this.data_cache = new DataManager(20, this); this.left_offset = 200; - this.painter = LinkedFeaturePainter; + this.painter = painters.LinkedFeaturePainter; }; extend(FeatureTrack.prototype, TiledTrack.prototype, { update_auto_mode: function( mode ) { @@ -2182,11 +2186,11 @@ var dummy_context = this.view.canvas_manager.dummy_context, inc_slots = this.inc_slots[level]; if (!inc_slots || (inc_slots.mode !== mode)) { - inc_slots = new FeatureSlotter( level, mode === "Pack", function ( x ) { return dummy_context.measureText( x ) } ); - inc_slots.mode = mode; + inc_slots = new (slotting.FeatureSlotter)( level, mode === "Pack", MAX_FEATURE_DEPTH, function ( x ) { return dummy_context.measureText( x ) } ); + inc_slots.mode = mode; this.inc_slots[level] = inc_slots; } - + return inc_slots.slot_features( features ); }, /** @@ -2249,7 +2253,7 @@ // Extra padding at top of summary tree canvas.height = required_height + SUMMARY_TREE_TOP_PADDING; // Paint summary tree into canvas - var painter = new SummaryTreePainter( result.data, result.delta, result.max, tile_low, tile_high, this.prefs.show_counts ); + var painter = new painters.SummaryTreePainter( result.data, result.delta, result.max, tile_low, tile_high, this.prefs.show_counts ); var ctx = canvas.getContext("2d"); // Deal with left_offset by translating ctx.translate( left_offset, SUMMARY_TREE_TOP_PADDING ); @@ -2340,7 +2344,7 @@ 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"; - this.painter = VariantPainter; + this.painter = painters.VariantPainter; }; extend(VcfTrack.prototype, TiledTrack.prototype, FeatureTrack.prototype); @@ -2368,7 +2372,7 @@ this.prefs = this.track_config.values; this.track_type = "ReadTrack"; - this.painter = ReadPainter; + this.painter = painters.ReadPainter; this.make_name_popup_menu(); }; extend(ReadTrack.prototype, TiledTrack.prototype, FeatureTrack.prototype); @@ -2419,57 +2423,19 @@ exports.FeatureTrack = FeatureTrack; exports.ReadTrack = ReadTrack; -// End encapsulation, this line is browser specific, globals are added to the -// window object -})(window); +// End trackster_module encapsulation +}; // ---- To be extracted ------------------------------------------------------ // ---- Feature Packing ---- -/** - * 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; -var compute_overlap = function(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; -} +// Encapsulation +var slotting_module = function(require, exports) { -/** - * Returns true if there is any overlap between regions. - */ -var is_overlap = function(first_region, second_region) { - return (compute_overlap(first_region, second_region) !== NO_OVERLAP); -} +// HACK: LABEL_SPACING is currently duplicated between here and painters +var LABEL_SPACING = 2, + PACK_SPACING = 5; /** * FeatureSlotter determines slots in which to draw features for vertical @@ -2478,11 +2444,12 @@ * This implementation is incremental, any feature assigned a slot will be * retained for slotting future features. */ -var FeatureSlotter = function ( w_scale, include_label, measureText ) { +exports.FeatureSlotter = function ( w_scale, include_label, max_rows, measureText ) { this.slots = {}; this.start_end_dct = {}; this.w_scale = w_scale; this.include_label = include_label; + this.max_rows = max_rows; this.measureText = measureText; } @@ -2490,139 +2457,147 @@ * Slot a set of features, `this.slots` will be updated with slots by id, and * the largest slot required for the passed set of features is returned */ -FeatureSlotter.prototype.slot_features = function( features ) { - var w_scale = this.w_scale, inc_slots = this.slots, start_end_dct = this.start_end_dct, - undone = [], slotted = [], highest_slot = 0; +extend( exports.FeatureSlotter.prototype, { + slot_features: function( features ) { + var w_scale = this.w_scale, inc_slots = this.slots, start_end_dct = this.start_end_dct, + undone = [], slotted = [], highest_slot = 0, max_rows = this.max_rows; + + // If feature already exists in slots (from previously seen tiles), use the same slot, + // otherwise if not seen, add to "undone" list for slot calculation. - // If feature already exists in slots (from previously seen tiles), use the same slot, - // otherwise if not seen, add to "undone" list for slot calculation. + // TODO: Should calculate zoom tile index, which will improve performance + // by only having to look at a smaller subset + // if (this.start_end_dct[0] === undefined) { this.start_end_dct[0] = []; } + for (var i = 0, len = features.length; i < len; i++) { + var feature = features[i], + feature_uid = feature[0]; + if (inc_slots[feature_uid] !== undefined) { + highest_slot = Math.max(highest_slot, inc_slots[feature_uid]); + slotted.push(inc_slots[feature_uid]); + } else { + undone.push(i); + } + } + + // Slot unslotted features. + + // Find the first slot such that current feature doesn't overlap any other features in that slot. + // Returns -1 if no slot was found. + var find_slot = function(f_start, f_end) { + // TODO: Fix constants + for (var slot_num = 0; slot_num <= max_rows; slot_num++) { + var has_overlap = false, + slot = start_end_dct[slot_num]; + if (slot !== undefined) { + // Iterate through features already in slot to see if current feature will fit. + for (var k = 0, k_len = slot.length; k < k_len; k++) { + var s_e = slot[k]; + if (f_end > s_e[0] && f_start < s_e[1]) { + // There is overlap + has_overlap = true; + break; + } + } + } + if (!has_overlap) { + return slot_num; + } + } + return -1; + }; + + // Do slotting. + for (var i = 0, len = undone.length; i < len; i++) { + var feature = features[undone[i]], + feature_uid = feature[0], + feature_start = feature[1], + feature_end = feature[2], + feature_name = feature[3], + // Where to start, end drawing on screen. + f_start = Math.floor( feature_start * w_scale ), + f_end = Math.ceil( feature_end * w_scale ), + text_len = this.measureText(feature_name).width, + text_align; + + // 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 && this.include_label ) { + // Add gap for label spacing and extra pack space padding + // TODO: Fix constants + text_len += (LABEL_SPACING + PACK_SPACING); + if (f_start - text_len >= 0) { + f_start -= text_len; + text_align = "left"; + } else { + f_end += text_len; + text_align = "right"; + } + } + + // Find slot. + var slot_num = find_slot(f_start, f_end); - // TODO: Should calculate zoom tile index, which will improve performance - // by only having to look at a smaller subset - // if (this.start_end_dct[0] === undefined) { this.start_end_dct[0] = []; } - for (var i = 0, len = features.length; i < len; i++) { - var feature = features[i], - feature_uid = feature[0]; - if (inc_slots[feature_uid] !== undefined) { - highest_slot = Math.max(highest_slot, inc_slots[feature_uid]); - slotted.push(inc_slots[feature_uid]); - } else { - undone.push(i); - } + /* + if (slot_num < 0) { + + TODO: this is not yet working -- + console.log(feature_uid, "looking for slot with text on the right"); + // Slot not found. If text was on left, try on right and see + // if slot can be found. + // TODO: are there any checks we need to do to ensure that text + // will fit on tile? + if (text_align === "left") { + f_start -= text_len; + f_end -= text_len; + text_align = "right"; + slot_num = find_slot(f_start, f_end); + } + if (slot_num >= 0) { + console.log(feature_uid, "found slot with text on the right"); + } + + } + */ + // Do slotting. + if (slot_num >= 0) { + // Add current feature to slot. + if (start_end_dct[slot_num] === undefined) { + start_end_dct[slot_num] = []; + } + start_end_dct[slot_num].push([f_start, f_end]); + inc_slots[feature_uid] = slot_num; + highest_slot = Math.max(highest_slot, slot_num); + } + 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); + } + } + + // Debugging: view slots data. + /* + for (var i = 0; i < MAX_FEATURE_DEPTH; i++) { + var slot = start_end_dct[i]; + if (slot !== undefined) { + console.log(i, "*************"); + for (var k = 0, k_len = slot.length; k < k_len; k++) { + console.log("\t", slot[k][0], slot[k][1]); + } + } + } + */ + return highest_slot + 1; } - - // Slot unslotted features. - - // Find the first slot such that current feature doesn't overlap any other features in that slot. - // Returns -1 if no slot was found. - var find_slot = function(f_start, f_end) { - // TODO: Fix constants - for (var slot_num = 0; slot_num <= MAX_FEATURE_DEPTH; slot_num++) { - var has_overlap = false, - slot = start_end_dct[slot_num]; - if (slot !== undefined) { - // Iterate through features already in slot to see if current feature will fit. - for (var k = 0, k_len = slot.length; k < k_len; k++) { - var s_e = slot[k]; - if (f_end > s_e[0] && f_start < s_e[1]) { - // There is overlap - has_overlap = true; - break; - } - } - } - if (!has_overlap) { - return slot_num; - } - } - return -1; - }; - - // Do slotting. - for (var i = 0, len = undone.length; i < len; i++) { - var feature = features[undone[i]], - feature_uid = feature[0], - feature_start = feature[1], - feature_end = feature[2], - feature_name = feature[3], - // Where to start, end drawing on screen. - f_start = Math.floor( feature_start * w_scale ), - f_end = Math.ceil( feature_end * w_scale ), - text_len = this.measureText(feature_name).width, - text_align; - - // 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 && this.include_label ) { - // Add gap for label spacing and extra pack space padding - // TODO: Fix constants - text_len += (LABEL_SPACING + PACK_SPACING); - if (f_start - text_len >= 0) { - f_start -= text_len; - text_align = "left"; - } else { - f_end += text_len; - text_align = "right"; - } - } - - // Find slot. - var slot_num = find_slot(f_start, f_end); - /* - if (slot_num < 0) { - - TODO: this is not yet working -- - console.log(feature_uid, "looking for slot with text on the right"); - // Slot not found. If text was on left, try on right and see - // if slot can be found. - // TODO: are there any checks we need to do to ensure that text - // will fit on tile? - if (text_align === "left") { - f_start -= text_len; - f_end -= text_len; - text_align = "right"; - slot_num = find_slot(f_start, f_end); - } - if (slot_num >= 0) { - console.log(feature_uid, "found slot with text on the right"); - } +}); - } - */ - // Do slotting. - if (slot_num >= 0) { - // Add current feature to slot. - if (start_end_dct[slot_num] === undefined) { - start_end_dct[slot_num] = []; - } - start_end_dct[slot_num].push([f_start, f_end]); - inc_slots[feature_uid] = slot_num; - highest_slot = Math.max(highest_slot, slot_num); - } - 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); - } - } - - // Debugging: view slots data. - /* - for (var i = 0; i < MAX_FEATURE_DEPTH; i++) { - var slot = start_end_dct[i]; - if (slot !== undefined) { - console.log(i, "*************"); - for (var k = 0, k_len = slot.length; k < k_len; k++) { - console.log("\t", slot[k][0], slot[k][1]); - } - } - } - */ - return highest_slot + 1; -} +// End slotting_module encapsulation +}; // ---- Painters ---- +var painters_module = function(require, exports){ + /** * SummaryTreePainter, a histogram showing number of intervals in a region */ @@ -2826,9 +2801,9 @@ // 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); - + // Draw feature if there's overlap and mode is dense or feature is slotted (as it must be for all non-dense modes). - if (is_overlap([feature_start, feature_end], [view_start, view_end]) && (this.mode == "Dense" || slot !== null)) { + if ( ( feature_start < view_end && feature_end > view_start ) && (this.mode == "Dense" || slot !== null)) { this.draw_element(ctx, this.mode, feature, slot, view_start, view_end, w_scale, y_scale, width ); } @@ -2849,8 +2824,6 @@ SQUISH_FEATURE_HEIGHT = 3, PACK_FEATURE_HEIGHT = 9, LABEL_SPACING = 2, - PACK_SPACING = 5, - MAX_FEATURE_DEPTH = 100, CONNECTOR_COLOR = "#ccc"; var LinkedFeaturePainter = function( data, view_start, view_end, prefs, mode ) { @@ -3099,6 +3072,43 @@ } }); +/** + * 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; +var compute_overlap = function(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; +} + var ReadPainter = function( data, view_start, view_end, prefs, mode, ref_seq ) { FeaturePainter.call( this, data, view_start, view_end, prefs, mode ); this.ref_seq = ref_seq; @@ -3381,3 +3391,39 @@ } } }); + +exports.SummaryTreePainter = SummaryTreePainter; +exports.LinePainter = LinePainter; +exports.LinkedFeaturePainter = LinkedFeaturePainter; +exports.ReadPainter = ReadPainter; +exports.VariantPainter = VariantPainter; + +// End painters_module encapsulation +}; + +// Finally, compose and export trackster module exports into globals +// These will be replaced with require statements in CommonJS +(function(target){ + // Faking up a CommonJS like loader here, each module gets a require and + // and exports. We avoid resolution problems by just ordering carefully. + var modules = {}; + // Provide a require function + var require = function( name ) { + return modules[name]; + }; + // Run module will run the module_function provided and store in the + // require dict using key + var run_module = function( key, module_function ) { + var exports = {}; + module_function( require, exports ); + modules[key] = exports; + }; + // Run all modules + run_module( 'slotting', slotting_module ); + run_module( 'painters', painters_module ); + run_module( 'trackster', trackster_module ); + // Export trackster stuff + for ( key in modules.trackster ) { + target[key] = modules.trackster[key]; + } +})(window); \ No newline at end of file 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.