1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/62ff8937f739/
changeset: r5178:62ff8937f739
user: jgoecks
date: 2011-03-04 21:22:17
summary: Trackster: add another parameter to draw() method that determines whether to clear old tiles immediately or after new tiles have been drawn. This parameter enables draw() to clear a track quickly (e.g. when scrolling fast) or slowly (e.g. when using filters). Also included is a long comment about why clearing tiles after often fails and ways to address this issue.
affected #: 1 file (1.5 KB)
--- a/static/scripts/trackster.js Fri Mar 04 14:29:19 2011 -0500
+++ b/static/scripts/trackster.js Fri Mar 04 15:22:17 2011 -0500
@@ -1197,7 +1197,7 @@
filter.low = values[0];
filter.high = values[1];
// Redraw track.
- track.draw(true);
+ track.draw(true, true);
},
change: function( event, ui ) {
filter.control_element.slider("option", "slide").call( filter.control_element, event, ui );
@@ -1502,7 +1502,22 @@
}
});
},
- draw: function(force) {
+ /**
+ * Draw track. It is possible to force a redraw rather than use cached tiles and/or clear old
+ * tiles after drawing new tiles.
+ *
+ * NOTE/TODO: clear_after only works when no data needs to be loaded. Because tiles fetch their own
+ * data and then draw themselves, there's no way to determine when all track tiles have been drawn
+ * because a tile may be waiting on data or drawing itself and there is no way to track a tile's status
+ * when it requests data and subsequently draws itself. Without the ability to determine when
+ * a track has been drawn, clear_after may not clear old tiles because it may be called too soon and
+ * miss old tiles that are being/will be drawn over.
+ *
+ * This problem can be fixed by either (a) fetching the data before drawing tiles so that tile drawing
+ * status can be fully monitored; or (b) keeping a global dictionary of tiles being drawn and their
+ * status. (a) is probably the better approach.
+ */
+ draw: function(force, clear_after) {
var low = this.view.low,
high = this.view.high,
range = high - low,
@@ -1512,13 +1527,16 @@
var parent_element = $("<div style='position: relative;'></div>"),
w_scale = width / range;
+ if (!clear_after) {
+ this.content_div.children().remove();
+ }
this.content_div.append( parent_element );
this.max_height = 0;
// Index of first tile that overlaps visible region
var tile_index = Math.floor( low / resolution / DENSITY );
- // A list of setTimeout() ids used when drawing tiles. Each ID indicates
+ // A set of setTimeout() ids used when drawing tiles. Each ID indicates
// a tile has been requested to be drawn or is being drawn.
- var draw_tile_count = 0;
+ var draw_tile_dict = {};
while ( ( tile_index * DENSITY * resolution ) < high ) {
// Check in cache
var key = width + '_' + w_scale + '_' + tile_index;
@@ -1527,9 +1545,10 @@
var tile_high = tile_low + DENSITY * this.view.resolution;
// console.log(cached, this.tile_cache);
if ( !force && cached ) {
- this.show_tile( cached, parent_element, tile_low, w_scale );
+ this.show_tile(cached, parent_element, tile_low, w_scale);
} else {
- this.delayed_draw(force, key, tile_low, tile_high, tile_index, resolution, parent_element, w_scale);
+ this.delayed_draw(force, key, tile_low, tile_high, tile_index,
+ resolution, parent_element, w_scale, draw_tile_dict);
}
tile_index += 1;
}
@@ -1539,39 +1558,42 @@
// (1) remove old tile(s);
// (2) update filtering UI elements.
//
- var track = this;
- var intervalId = setInterval(function() {
- if (draw_tile_count === 0) {
- // All tiles have been drawn; clear out track content in order to show the most recent content.
- // Most recent content is the div with children (tiles) most recently appended to track.
- // However, do not delete recently-appended empty content as calls to draw() may still be active
- // and using these divs.
- var track_content = track.content_div.children();
- var remove = false;
- for (var i = track_content.length-1, len = 0; i >= len; i--) {
- var child = $(track_content[i]);
- if (remove) {
- child.remove();
+ if (clear_after) {
+ var track = this;
+ var intervalId = setInterval(function() {
+ console.log("draw_tile_dict_length:", obj_length(draw_tile_dict));
+ if (obj_length(draw_tile_dict) === 0) {
+ // All tiles have been drawn; clear out track content in order to show the most recent content.
+ // Most recent content is the div with children (tiles) most recently appended to track.
+ // However, do not delete recently-appended empty content as calls to draw() may still be active
+ // and using these divs.
+ var track_content = track.content_div.children();
+ var remove = false;
+ for (var i = track_content.length-1, len = 0; i >= len; i--) {
+ var child = $(track_content[i]);
+ if (remove) {
+ child.remove();
+ }
+ else if (child.children().length !== 0) {
+ // Found most recent content with tiles: set remove to start removing old elements.
+ remove = true;
+ }
}
- else if (child.children().length !== 0) {
- // Found most recent content with tiles: set remove to start removing old elements.
- remove = true;
- }
+
+ // Method complete; do not call it again.
+ clearInterval(intervalId);
}
-
- // Method complete; do not call it again.
- clearInterval(intervalId);
- }
- }, 50);
-
+ }, 50);
+ }
+
//
// Draw child tracks.
//
for (var i = 0; i < this.child_tracks.length; i++) {
- this.child_tracks[i].draw(force);
+ this.child_tracks[i].draw(force, clear_after);
}
},
- delayed_draw: function(force, key, tile_low, tile_high, tile_index, resolution, parent_element, w_scale) {
+ delayed_draw: function(force, key, tile_low, tile_high, tile_index, resolution, parent_element, w_scale, draw_tile_dict) {
var track = this;
// Put a 50ms delay on drawing so that if the user scrolls fast, we don't load extra data
var draw_tile = function(tile_element) {
@@ -1611,7 +1633,9 @@
draw_tile(tile_element);
}
}
+ delete draw_tile_dict[id];
}, 50);
+ draw_tile_dict[id] = true;
},
/**
* Show track tile and perform associated actions.
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 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/8f55a6d51d47/
changeset: r5177:8f55a6d51d47
user: jgoecks
date: 2011-03-04 20:29:19
summary: Trackster: refactor filtering functionality out of draw() method and do use CSS classes for information transfer. Also remove unused menu code.
affected #: 2 files (806 bytes)
--- a/static/scripts/galaxy.base.js Fri Mar 04 10:28:04 2011 -0500
+++ b/static/scripts/galaxy.base.js Fri Mar 04 14:29:19 2011 -0500
@@ -39,22 +39,7 @@
});
};
-// Toggle popup menu options using regular expression on option names.
-function show_hide_popupmenu_options( menu, option_name_re, show ) {
- show = (show === undefined ? true : show );
- var re = new RegExp(option_name_re);
- $(menu).find("li").each( function() {
- if ( re.exec($(this).text()) ) {
- if (show) {
- $(this).show();
- } else {
- $(this).hide();
- }
- }
- });
-}
-
-function make_popupmenu( button_element, initial_options ) {
+function make_popupmenu(button_element, initial_options) {
/* Use the $.data feature to store options with the link element.
This allows options to be changed at a later time
--- a/static/scripts/trackster.js Fri Mar 04 10:28:04 2011 -0500
+++ b/static/scripts/trackster.js Fri Mar 04 14:29:19 2011 -0500
@@ -157,7 +157,6 @@
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,
@@ -1133,7 +1132,11 @@
// Attribute init.
this.filters = (filters !== undefined ? get_filters_from_dict( filters ) : []);
+ // filters_available is determined by data, filters_visible is set by user.
+ this.filters_available = false;
+ this.filters_visible = false;
this.tool = (tool !== undefined ? get_tool_from_dict( tool ) : undefined);
+
//
// TODO: Right now there is only the notion of a parent track and multiple child tracks. However,
// a more general notion of a 'track group' is probably needed and can be easily created using
@@ -1415,7 +1418,7 @@
//
// Show/hide filters option.
//
- if (track.filters.length > 0) {
+ if (track.filters_available > 0) {
// Show/hide filters menu item.
var text = (track.filters_div.is(":visible") ? "Hide filters" : "Show filters");
track_dropdown[text] = function() {
@@ -1555,11 +1558,6 @@
remove = true;
}
}
-
- // Update filtering UI.
- for (var f = 0; f < track.filters.length; f++) {
- track.filters[f].update_ui_elt();
- }
// Method complete; do not call it again.
clearInterval(intervalId);
@@ -1592,10 +1590,6 @@
if ( returned_tile ) {
// Wrap element in div for background
var wrapper_element = $("<div class='track-tile'>").prepend( returned_tile );
- // HACK: filtering
- if ( returned_tile.hasClass( FILTERABLE_CLASS ) ) {
- wrapper_element.addClass( FILTERABLE_CLASS );
- }
tile_element = wrapper_element;
}
draw_tile(tile_element);
@@ -1619,10 +1613,16 @@
}
}, 50);
},
- // Show track tile and perform associated actions.
+ /**
+ * Show track tile and perform associated actions.
+ */
show_tile: function( tile_element, parent_element, tile_low, w_scale ) {
// Readability.
var track = this;
+
+ //
+ // Show tile element.
+ //
// Position tile element, recalculate left position at display time
var range = this.view.high - this.view.low,
@@ -1640,15 +1640,35 @@
if (track.hidden) { return; }
- // Show/hide filters based on whether tile is filterable.
- if ( tile_element.hasClass(FILTERABLE_CLASS) ) {
- show_hide_popupmenu_options(track.popup_menu, "(Show|Hide) filters");
- if (track.filters_visible) {
- track.filters_div.show();
+ //
+ // Update filter attributes, UI.
+ // TODO: this could be done after all tiles are drawn, but there's no reliable way to detect
+ // that right now.
+ //
+
+ // Update filtering UI.
+ for (var f = 0; f < track.filters.length; f++) {
+ track.filters[f].update_ui_elt();
+ }
+
+ // Determine if filters are available; this is based on the example feature.
+ var filters_available = false;
+ if (track.example_feature) {
+ for (var f = 0; f < track.filters.length; f++) {
+ if (track.filters[f].applies_to(track.example_feature)) {
+ filters_available = true;
+ break;
+ }
}
- } else {
- show_hide_popupmenu_options(track.popup_menu, "(Show|Hide) filters", false);
- track.filters_div.hide();
+ }
+
+ // If filter availability changed, hide filter div if necessary and update menu.
+ if (track.filters_available !== filters_available) {
+ track.filters_available = filters_available;
+ if (!track.filters_available) {
+ track.filters_div.hide();
+ }
+ track.make_name_popup_menu();
}
},
// Set track as the overview track in the visualization.
@@ -2565,14 +2585,9 @@
}
//
- // If tile is filterable, add class to canvas.
+ // Set example feature. This is needed so that track can update its UI based on feature attributes.
//
- 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;
- }
- }
+ this.example_feature = (result.data.length ? result.data[0] : undefined);
//
// Draw elements.
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 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/34d3fcd8037b/
changeset: r5176:34d3fcd8037b
user: dan
date: 2011-03-04 16:28:04
summary: Add a 'subclass' flag to datatype definitions in datatypes_conf.xml that allows dynamic creation of a subclass.
For example, to create a datatype that has the attributes of a Tabular file, but is more 'specific':
<datatype extension="more_than_tabular" type="galaxy.datatypes.tabular:Tabular" subclass="True" />
affected #: 1 file (281 bytes)
--- a/lib/galaxy/datatypes/registry.py Fri Mar 04 10:02:01 2011 -0500
+++ b/lib/galaxy/datatypes/registry.py Fri Mar 04 10:28:04 2011 -0500
@@ -48,20 +48,24 @@
dtype = elem.get( 'type', None )
mimetype = elem.get( 'mimetype', None )
display_in_upload = elem.get( 'display_in_upload', False )
+ make_subclass = galaxy.util.string_as_bool( elem.get( 'subclass', False ) )
if extension and dtype:
fields = dtype.split( ':' )
datatype_module = fields[0]
- datatype_class = fields[1]
+ datatype_class_name = fields[1]
fields = datatype_module.split( '.' )
module = __import__( fields.pop(0) )
for mod in fields:
module = getattr( module, mod )
- self.datatypes_by_extension[extension] = getattr( module, datatype_class )()
+ datatype_class = getattr( module, datatype_class_name )
+ if make_subclass:
+ datatype_class = type( datatype_class_name, (datatype_class,), {} )
+ self.datatypes_by_extension[extension] = datatype_class()
if mimetype is None:
# Use default mime type as per datatype spec
mimetype = self.datatypes_by_extension[extension].get_mime()
self.mimetypes_by_extension[extension] = mimetype
- if hasattr( getattr( module, datatype_class ), "get_track_type" ):
+ if hasattr( datatype_class, "get_track_type" ):
self.available_tracks.append( extension )
if display_in_upload:
self.upload_file_formats.append( extension )
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 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/90aafa9e685b/
changeset: r5174:90aafa9e685b
user: rc
date: 2011-03-04 15:59:06
summary: Backed out of changeset 5173:ac6b14ffc984
affected #: 1 file (0 bytes)
--- a/lib/galaxy/model/migrate/versions/0076_fix_form_values_data_corruption.py Fri Mar 04 07:28:23 2011 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-'''
-This migrate script fixes the data corruption caused in the form_values
-table (content json field) by migrate script 65.
-'''
-from sqlalchemy import *
-from sqlalchemy.orm import *
-from migrate import *
-from migrate.changeset import *
-from sqlalchemy.exc import *
-
-from galaxy.util.json import from_json_string, to_json_string
-
-import logging
-log = logging.getLogger( __name__ )
-
-metadata = MetaData( migrate_engine )
-db_session = scoped_session( sessionmaker( bind=migrate_engine, autoflush=False, autocommit=True ) )
-
-
-def upgrade():
- print __doc__
- metadata.reflect()
-
- cmd = "SELECT form_values.id as id, form_values.content as values, form_definition.fields as fields " \
- + " FROM form_definition, form_values " \
- + " WHERE form_values.form_definition_id=form_definition.id " \
- + " ORDER BY form_values.id"
- result = db_session.execute( cmd )
- for row in result:
- # first check if loading the dict from the json succeeds
- # if that fails, it means that the content field is corrupted.
- try:
- values_dict = from_json_string( str( row['values'] ) )
- except:
- fields_list = from_json_string( str( row['fields'] ) )
- values_str = str( row['values'] )
- values_dict = {}
- # look for each field name in the values and extract its value (string)
- for index in range( len(fields_list) ):
- field = fields_list[index]
- key = '"%s": "' % field['name']
- field_index = values_str.find( key )
- # check if this is the last field
- if index == len( fields_list )-1:
- # since this is the last field, the value string lies between the
- # field name and the '"}' string at the end, hence len(values_str)-2
- value = values_str[ field_index+len( key ):len( values_str )-2 ]
- else:
- # if this is not the last field then the value string lies between
- # this field name and the next field name
- next_field = fields_list[index+1]
- next_field_index = values_str.find( '", "%s": "' % next_field['name'] )
- value = values_str[ field_index+len(key):next_field_index ]
- # clean up the value string, escape the required quoutes and newline characters
- value = value.replace( "'", "\''" )\
- .replace( '"', '\\\\"' )\
- .replace( '\r', "\\\\r" )\
- .replace( '\n', "\\\\n" )\
- .replace( '\t', "\\\\t" )
- # add to the new values dict
- values_dict[ field['name'] ] = value
- # update the db
- json_values = to_json_string(values_dict)
- cmd = "UPDATE form_values SET content='%s' WHERE id=%i" %( json_values, int( row['id'] ) )
- db_session.execute( cmd )
-
-def downgrade():
- pass
\ 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.
1 new changeset in galaxy-central:
http://bitbucket.org/galaxy/galaxy-central/changeset/ac6b14ffc984/
changeset: r5173:ac6b14ffc984
user: rc
date: 2011-03-04 13:28:23
summary: Fixes the data corruption caused in the form_values table (content field) by the migrate script 65.
affected #: 1 file (0 bytes)
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.