galaxy-commits
Threads by month
- ----- 2026 -----
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 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
- 15302 discussions
commit/galaxy-central: inithello: Account for condition where output filename is not defined.
by commits-noreply@bitbucket.org 17 Apr '13
by commits-noreply@bitbucket.org 17 Apr '13
17 Apr '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/392b82ef5b56/
Changeset: 392b82ef5b56
User: inithello
Date: 2013-04-17 22:11:20
Summary: Account for condition where output filename is not defined.
Affected #: 1 file
diff -r 6e7ad33e263d821e82dce33054b9e10c1357f0e3 -r 392b82ef5b56ebb98b8802f94bd00b5761e5924d lib/tool_shed/scripts/check_repositories_for_functional_tests.py
--- a/lib/tool_shed/scripts/check_repositories_for_functional_tests.py
+++ b/lib/tool_shed/scripts/check_repositories_for_functional_tests.py
@@ -382,6 +382,9 @@
required_test_files.append( input_file )
for output in test_dict[ 'outputs' ]:
fieldname, filename = output
+ # In rare cases, the filename may be None. If that is the case, skip that output definition.
+ if filename is None:
+ continue
if filename not in required_test_files:
required_test_files.append( filename )
# Make sure each specified file actually does exist in the test data path of the cloned repository.
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: inithello: Added some checks, making buildbot setup more useful for standalone buildbots.
by commits-noreply@bitbucket.org 17 Apr '13
by commits-noreply@bitbucket.org 17 Apr '13
17 Apr '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/6e7ad33e263d/
Changeset: 6e7ad33e263d
User: inithello
Date: 2013-04-17 21:34:32
Summary: Added some checks, making buildbot setup more useful for standalone buildbots.
Affected #: 1 file
diff -r ed6525e548289cb9ca2675dc3bc0530e8dad3345 -r 6e7ad33e263d821e82dce33054b9e10c1357f0e3 buildbot_setup.sh
--- a/buildbot_setup.sh
+++ b/buildbot_setup.sh
@@ -93,26 +93,49 @@
JARS="/galaxy/software/jars"
-for link in $LINKS; do
- echo "Linking $link"
- rm -f tool-data/`basename $link`
- ln -sf $link tool-data
-done
-
-if [ -d "$HYPHY" ]; then
- echo "Linking $HYPHY"
- rm -f tool-data/HYPHY
- ln -sf $HYPHY tool-data/HYPHY
+if [ ! $1 ]; then
+ type="standard"
+elif [ $1 == "-ec2" ]; then
+ type="external-ec2"
+else
+ type="unknown"
fi
-if [ -d "$JARS" ]; then
- echo "Linking $JARS"
- rm -f tool-data/shared/jars
- ln -sf $JARS tool-data/shared/jars
-fi
+case $type in
+ external*)
+ echo "Running standalone buildbot setup..."
+ for sample in tool-data/*.sample; do
+ basename=${sample%.sample}
+ if [ ! -f $basename ]; then
+ echo "Copying $sample to $basename"
+ cp "$sample" "$basename"
+ fi
+ done
+ ;;
+ *)
+ echo "Running standard buildbot setup..."
+ for link in $LINKS; do
+ echo "Linking $link"
+ rm -f tool-data/`basename $link`
+ ln -sf $link tool-data
+ done
+
+ if [ -d "$HYPHY" ]; then
+ echo "Linking $HYPHY"
+ rm -f tool-data/HYPHY
+ ln -sf $HYPHY tool-data/HYPHY
+ fi
+
+ if [ -d "$JARS" ]; then
+ echo "Linking $JARS"
+ rm -f tool-data/shared/jars
+ ln -sf $JARS tool-data/shared/jars
+ fi
+ ;;
+esac
for sample in $SAMPLES; do
- file=`echo $sample | sed -e 's/\.sample$//'`
+ file=${sample%.sample}
echo "Copying $sample to $file"
cp $sample $file
done
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: add summary and sample labels to variant track + small style adjustments.
by commits-noreply@bitbucket.org 17 Apr '13
by commits-noreply@bitbucket.org 17 Apr '13
17 Apr '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/ed6525e54828/
Changeset: ed6525e54828
User: jgoecks
Date: 2013-04-17 21:10:03
Summary: Trackster: add summary and sample labels to variant track + small style adjustments.
Affected #: 2 files
diff -r 9e49d3b25e1b7cc2172f09ae59d93bd173f56d6c -r ed6525e548289cb9ca2675dc3bc0530e8dad3345 static/scripts/viz/trackster/painters.js
--- a/static/scripts/viz/trackster/painters.js
+++ b/static/scripts/viz/trackster/painters.js
@@ -1616,7 +1616,7 @@
// Draw divider between summary and samples.
if (this.prefs.show_sample_data) {
- ctx.fillStyle = '#DDDDDD';
+ ctx.fillStyle = '#F3F3F3';
ctx.globalAlpha = 1;
ctx.fillRect(0, this.prefs.summary_height - this.divider_height, width, this.divider_height);
}
@@ -1636,7 +1636,7 @@
char_x_start = Math.floor( Math.max(0, (pos - this.view_start) * w_scale) );
// Draw summary.
- ctx.fillStyle = '#AAAAAA';
+ ctx.fillStyle = '#999999';
// Draw background for summary.
ctx.fillRect(draw_x_start, 0, base_px, this.prefs.summary_height);
draw_y_start = this.prefs.summary_height;
diff -r 9e49d3b25e1b7cc2172f09ae59d93bd173f56d6c -r ed6525e548289cb9ca2675dc3bc0530e8dad3345 static/scripts/viz/trackster/tracks.js
--- a/static/scripts/viz/trackster/tracks.js
+++ b/static/scripts/viz/trackster/tracks.js
@@ -4166,6 +4166,7 @@
params: [
{ key: 'name', label: 'Name', type: 'text', default_value: this.name },
{ key: 'show_sample_data', label: 'Show sample data', type: 'bool', default_value: true },
+ { key: 'show_labels', label: 'Show summary and sample labels', type: 'bool', default_value: true },
{ key: 'summary_height', label: 'Locus summary height', type: 'float', default_value: 20 },
{ key: 'mode', type: 'string', default_value: this.mode, hidden: true }
],
@@ -4224,6 +4225,61 @@
before_draw: function() {
// Clear because this is set when drawing.
this.max_height_px = 0;
+ },
+
+ /**
+ * Actions to be taken after draw has been completed. Draw is completed when all tiles have been
+ * drawn/fetched and shown.
+ */
+ postdraw_actions: function(tiles, width, w_scale, clear_after) {
+ TiledTrack.prototype.postdraw_actions.call(this, tiles, width, w_scale, clear_after);
+
+ // Add labels if needed and not already included.
+ if (this.prefs.show_labels) {
+ // Add and/or style labels.
+ if (this.container_div.find('.yaxislabel').length === 0) {
+ // Add summary and sample labels.
+
+ // FIXME: label attributes could be cleaner by using CSS classes.
+
+ // Add summary label.
+ var summary_div_font_size = 10,
+ summary_div = $("<div/>").text('Summary').addClass('yaxislabel top').css({
+ 'font-size': summary_div_font_size + 'px'
+ });
+ this.container_div.prepend(summary_div);
+
+ // Adjust summary label to middle of summary.
+ var base_offset = summary_div.position().top;
+ summary_div.css('top', base_offset + (this.prefs.summary_height - summary_div_font_size) / 2 + 'px');
+
+ // Show sample labels.
+ if (this.prefs.show_sample_data) {
+ var samples_div_html = '';
+ _.each(this.dataset.get('metadata').get('sample_names'), function(name) {
+ samples_div_html += (name + '<br>');
+ });
+
+ var samples_div = $("<div/>").html(samples_div_html).addClass('yaxislabel top sample').css({
+ // +2 for padding
+ 'top': base_offset + this.prefs.summary_height + 2,
+ });
+ this.container_div.prepend(samples_div);
+ }
+ }
+
+ // Style labels.
+
+ // Match sample font size to mode.
+ $(this.container_div).find('.sample').css('font-size', (this.mode === 'Squish' ? 5 : 10) + 'px');
+ // Color labels to preference color.
+ $(this.container_div).find('.yaxislabel').css('color', this.prefs.label_color);
+
+ }
+ else {
+ // Remove all labels.
+ this.container_div.find('.yaxislabel').remove();
+ }
}
});
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: inithello: Improve recording of invalid tests. Check for the existence each file required by functional tests.
by commits-noreply@bitbucket.org 17 Apr '13
by commits-noreply@bitbucket.org 17 Apr '13
17 Apr '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/9e49d3b25e1b/
Changeset: 9e49d3b25e1b
User: inithello
Date: 2013-04-17 20:31:27
Summary: Improve recording of invalid tests. Check for the existence each file required by functional tests.
Affected #: 1 file
diff -r da5a5077ef1ebffa9e0ad9039ca4463298815de1 -r 9e49d3b25e1b7cc2172f09ae59d93bd173f56d6c lib/tool_shed/scripts/check_repositories_for_functional_tests.py
--- a/lib/tool_shed/scripts/check_repositories_for_functional_tests.py
+++ b/lib/tool_shed/scripts/check_repositories_for_functional_tests.py
@@ -167,21 +167,22 @@
no_tools = 0
valid_revisions = 0
invalid_revisions = 0
- # Get the list of metadata records to check for functional tests and test data. Limit this to records that have not been flagged do_not_test
- # or tools_functionally_correct. Also filter out changeset revisions that are not downloadable, because it's redundant to test a revision that
- # a user can't install.
- # Initialize the repository_status dict with the test environment, but leave the test_errors empty.
- repository_status = {}
- repository_status[ 'invalid_tests' ] = []
+ # Get the list of metadata records to check for functional tests and test data. Limit this to records that have not been flagged do_not_test,
+ # since there's no need to check them again if they won't be tested anyway. Also filter out changeset revisions that are not downloadable,
+ # because it's redundant to test a revision that a user can't install.
metadata_records_to_check = app.sa_session.query( app.model.RepositoryMetadata ) \
.filter( and_( app.model.RepositoryMetadata.table.c.downloadable == True,
app.model.RepositoryMetadata.table.c.includes_tools == True,
- app.model.RepositoryMetadata.table.c.do_not_test == False,
- app.model.RepositoryMetadata.table.c.tools_functionally_correct == False ) ) \
+ app.model.RepositoryMetadata.table.c.do_not_test == False ) ) \
.all()
for metadata_record in metadata_records_to_check:
+ # Initialize the repository_status dict with the test environment, but leave the test_errors empty.
+ repository_status = {}
if metadata_record.tool_test_errors:
repository_status = metadata_record.tool_test_errors
+ # Clear any old invalid tests for this metadata revision, since this could lead to duplication of invalid test rows,
+ # or tests incorrectly labeled as invalid.
+ repository_status[ 'invalid_tests' ] = []
if 'test_environment' in repository_status:
repository_status[ 'test_environment' ] = get_test_environment( repository_status[ 'test_environment' ] )
else:
@@ -192,7 +193,6 @@
name = metadata_record.repository.name
owner = metadata_record.repository.user.username
changeset_revision = str( metadata_record.changeset_revision )
- repository_status[ 'invalid_tests' ] = []
if metadata_record.repository.id not in checked_repository_ids:
checked_repository_ids.append( metadata_record.repository.id )
if verbosity >= 1:
@@ -218,15 +218,13 @@
dirs.remove( '.hg' )
if 'test-data' in dirs:
has_test_data = True
+ test_data_path = os.path.join( root, dirs[ dirs.index( 'test-data' ) ] )
break
- # Remove the cloned repository path.
- if os.path.exists( work_dir ):
- shutil.rmtree( work_dir )
if verbosity >= 1:
if not has_test_data:
- print '# Test data missing in changeset revision %s of repository %s owned by %s.' % ( changeset_revision, name, owner )
+ print '# Test data directory missing in changeset revision %s of repository %s owned by %s.' % ( changeset_revision, name, owner )
else:
- print '# Test data found in changeset revision %s of repository %s owned by %s.' % ( changeset_revision, name, owner )
+ print '# Test data directory found in changeset revision %s of repository %s owned by %s.' % ( changeset_revision, name, owner )
print '# Checking for functional tests in changeset revision %s of %s, owned by %s.' % \
( changeset_revision, name, owner )
# Loop through all the tools in this metadata record, checking each one for defined functional tests.
@@ -255,12 +253,22 @@
has_tests += 1
failure_reason = ''
problem_found = False
+ missing_test_files = []
+ if tool_has_tests and has_test_data:
+ missing_test_files = check_for_missing_test_files( tool_metadata[ 'tests' ], test_data_path )
+ if missing_test_files:
+ if verbosity >= 2:
+ print "# Tool ID '%s' in changeset revision %s of %s is missing one or more required test files: %s" % \
+ ( tool_id, changeset_revision, name, ', '.join( missing_test_files ) )
if not has_test_data:
failure_reason += 'Repository does not have a test-data directory. '
problem_found = True
if not tool_has_tests:
failure_reason += 'Functional test definitions missing for %s. ' % tool_id
problem_found = True
+ if missing_test_files:
+ failure_reason += 'One or more test files are missing for tool %s: %s' % ( tool_id, ', '.join( missing_test_files ) )
+ problem_found = True
test_errors = dict( tool_id=tool_id, tool_version=tool_version, tool_guid=tool_guid,
reason_test_is_invalid=failure_reason )
# The repository_metadata.tool_test_errors attribute should always have the following structure:
@@ -312,6 +320,9 @@
if problem_found:
if test_errors not in repository_status[ 'invalid_tests' ]:
repository_status[ 'invalid_tests' ].append( test_errors )
+ # Remove the cloned repository path. This has to be done after the check for required test files, for obvious reasons.
+ if os.path.exists( work_dir ):
+ shutil.rmtree( work_dir )
if not repository_status[ 'invalid_tests' ]:
valid_revisions += 1
if verbosity >= 1:
@@ -319,17 +330,21 @@
else:
invalid_revisions += 1
if verbosity >= 1:
- print '# Some tools missing functional tests in changeset revision %s of repository %s owned by %s.' % ( changeset_revision, name, owner )
+ print '# Some tools have problematic functional tests in changeset revision %s of repository %s owned by %s.' % ( changeset_revision, name, owner )
+ if verbosity >= 2:
+ for invalid_test in repository_status[ 'invalid_tests' ]:
+ if 'reason_test_is_invalid' in invalid_test:
+ print '# %s' % invalid_test[ 'reason_test_is_invalid' ]
if not info_only:
# If repository_status[ 'test_errors' ] is empty, no issues were found, and we can just update time_last_tested with the platform
# on which this script was run.
if repository_status[ 'invalid_tests' ]:
# If functional test definitions or test data are missing, set do_not_test = True if and only if:
- # a) There are multiple downloadable revisions, and the revision being tested is not the most recent downloadable revision. In this case,
- # the revision will never be updated with correct data, and re-testing it would be redundant.
- # b) There are one or more downloadable revisions, and the revision being tested is the most recent downloadable revision. In this case, if
- # the repository is updated with test data or functional tests, the downloadable changeset revision that was tested will be replaced
- # with the new changeset revision, which will be automatically tested.
+ # a) There are multiple downloadable revisions, and the revision being tested is not the most recent downloadable revision.
+ # In this case, the revision will never be updated with correct data, and re-testing it would be redundant.
+ # b) There are one or more downloadable revisions, and the revision being tested is the most recent downloadable revision.
+ # In this case, if the repository is updated with test data or functional tests, the downloadable changeset revision
+ # that was tested will be replaced with the new changeset revision, which will be automatically tested.
if should_set_do_not_test_flag( app, metadata_record.repository, changeset_revision ):
metadata_record.do_not_test = True
metadata_record.tools_functionally_correct = False
@@ -357,6 +372,25 @@
changelog_tuples.append( ( ctx.rev(), str( ctx ) ) )
return changelog_tuples
+def check_for_missing_test_files( test_definition, test_data_path ):
+ '''Process the tool's functional test definitions and check for each file specified as an input or output.'''
+ missing_test_files = []
+ required_test_files = []
+ for test_dict in test_definition:
+ for input_file in test_dict[ 'required_files' ]:
+ if input_file not in required_test_files:
+ required_test_files.append( input_file )
+ for output in test_dict[ 'outputs' ]:
+ fieldname, filename = output
+ if filename not in required_test_files:
+ required_test_files.append( filename )
+ # Make sure each specified file actually does exist in the test data path of the cloned repository.
+ for required_file in required_test_files:
+ required_file_full_path = os.path.join( test_data_path, required_file )
+ if not os.path.exists( required_file_full_path ):
+ missing_test_files.append( required_file )
+ return missing_test_files
+
def is_most_recent_downloadable_revision( app, repository, changeset_revision, downloadable_revisions ):
# Get a list of ( numeric revision, changeset hash ) tuples from the changelog.
changelog = get_repo_changelog_tuples( repository.repo_path( app ) )
@@ -376,8 +410,10 @@
a) There are multiple downloadable revisions, and the provided changeset revision is not the most recent downloadable revision. In this case,
the revision will never be updated with correct data, and re-testing it would be redundant.
b) There are one or more downloadable revisions, and the provided changeset revision is the most recent downloadable revision. In this case, if
- the repository is updated with test data or functional tests, the downloadable changeset revision that was tested will be replaced
- with the new changeset revision, which will be automatically tested.
+ the repository is updated with test data or functional tests, the downloadable changeset revision that was tested will either be replaced
+ with the new changeset revision, or a new downloadable changeset revision will be created, either of which will be automatically checked and
+ flagged as appropriate. In the install and test script, this behavior is slightly different, since we do want to always run functional tests
+ on the most recent downloadable changeset revision.
'''
metadata_records = app.sa_session.query( app.model.RepositoryMetadata ) \
.filter( and_( app.model.RepositoryMetadata.table.c.downloadable == True,
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: dannon: Strip whitespace from version_string_cmd, contributed by Peter Cock
by commits-noreply@bitbucket.org 17 Apr '13
by commits-noreply@bitbucket.org 17 Apr '13
17 Apr '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/da5a5077ef1e/
Changeset: da5a5077ef1e
User: dannon
Date: 2013-04-17 16:55:50
Summary: Strip whitespace from version_string_cmd, contributed by Peter Cock
Affected #: 1 file
diff -r 28edc7bec4048b5ef1564396ab3e6f91b03f62d6 -r da5a5077ef1ebffa9e0ad9039ca4463298815de1 lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -1094,7 +1094,7 @@
self.version_string_cmd = None
version_cmd = root.find("version_command")
if version_cmd is not None:
- self.version_string_cmd = version_cmd.text
+ self.version_string_cmd = version_cmd.text.strip()
version_cmd_interpreter = version_cmd.get( "interpreter", None )
if version_cmd_interpreter:
executable = self.version_string_cmd.split()[0]
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
2 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/6c7a8e5d45e0/
Changeset: 6c7a8e5d45e0
User: dannon
Date: 2013-04-17 16:19:07
Summary: Transactions won't always have a session (or history), handle returning None appropriately.
Affected #: 1 file
diff -r 57b64ceac4b5eaef10eb0f6c3cf94a87646901c2 -r 6c7a8e5d45e0bec70ec90d6bfdcc538b072bcf11 lib/galaxy/web/framework/__init__.py
--- a/lib/galaxy/web/framework/__init__.py
+++ b/lib/galaxy/web/framework/__init__.py
@@ -811,16 +811,18 @@
def get_history( self, create=False ):
"""
Load the current history, creating a new one only if there is not
- current history and we're told to create"
+ current history and we're told to create.
+ Transactions will not always have an active history (API requests), so
+ None is a valid response.
"""
- history = self.galaxy_session.current_history
- if not history:
- if util.string_as_bool( create ):
- history = self.new_history()
- else:
- # Perhaps a bot is running a tool without having logged in to get a history
- log.debug( "This request returned None from get_history(): %s" % self.request.browser_url )
- return None
+ history = None
+ if self.galaxy_session:
+ history = self.galaxy_session.current_history
+ if not history and util.string_as_bool( create ):
+ history = self.new_history()
+ else:
+ # Perhaps a bot is running a tool without having logged in to get a history
+ log.debug( "This request returned None from get_history(): %s" % self.request.browser_url )
return history
def set_history( self, history ):
https://bitbucket.org/galaxy/galaxy-central/commits/28edc7bec404/
Changeset: 28edc7bec404
User: dannon
Date: 2013-04-17 16:40:15
Summary: Merge changes
Affected #: 4 files
diff -r 6c7a8e5d45e0bec70ec90d6bfdcc538b072bcf11 -r 28edc7bec4048b5ef1564396ab3e6f91b03f62d6 lib/galaxy/datatypes/tabular.py
--- a/lib/galaxy/datatypes/tabular.py
+++ b/lib/galaxy/datatypes/tabular.py
@@ -543,7 +543,8 @@
MetadataElement( name="columns", default=10, desc="Number of columns", readonly=True, visible=False )
MetadataElement( name="column_types", default=['str','int','str','str','str','int','str','list','str','str'], param=metadata.ColumnTypesParameter, desc="Column types", readonly=True, visible=False )
- MetadataElement( name="viz_filter_cols", desc="Score column for visualization", default=[5], param=metadata.ColumnParameter, multiple=True )
+ MetadataElement( name="viz_filter_cols", desc="Score column for visualization", default=[5], param=metadata.ColumnParameter, multiple=True, visible=False )
+ MetadataElement( name="sample_names", default=[], desc="Sample names", readonly=True, visible=False, optional=True, no_value=[] )
def sniff( self, filename ):
headers = get_headers( filename, '\n', count=1 )
@@ -553,6 +554,21 @@
"""Returns formated html of peek"""
return Tabular.make_html_table( self, dataset, column_names=self.column_names )
+ def set_meta( self, dataset, **kwd ):
+ Tabular.set_meta( self, dataset, **kwd )
+ source = open( dataset.file_name )
+
+ # Skip comments.
+ line = None
+ for line in source:
+ if not line.startswith( '##' ):
+ break
+
+ if line and line.startswith( '#' ):
+ # Found header line, get sample names.
+ dataset.metadata.sample_names = line.split()[ 9: ]
+
+
class Eland( Tabular ):
"""Support for the export.txt.gz file used by Illumina's ELANDv2e aligner"""
file_ext = '_export.txt.gz'
diff -r 6c7a8e5d45e0bec70ec90d6bfdcc538b072bcf11 -r 28edc7bec4048b5ef1564396ab3e6f91b03f62d6 lib/galaxy/web/base/controller.py
--- a/lib/galaxy/web/base/controller.py
+++ b/lib/galaxy/web/base/controller.py
@@ -595,9 +595,8 @@
source='data' )
return {
"track_type": dataset.datatype.track_type,
+ "dataset": trans.security.encode_dict_ids( dataset.get_api_value() ),
"name": track_dict['name'],
- "hda_ldda": track_dict.get("hda_ldda", "hda"),
- "dataset_id": trans.security.encode_id( dataset.id ),
"prefs": prefs,
"mode": track_dict.get( 'mode', 'Auto' ),
"filters": track_dict.get( 'filters', { 'filters' : track_data_provider.get_filters() } ),
@@ -676,8 +675,7 @@
return {
"track_type": dataset.datatype.track_type,
"name": dataset.name,
- "hda_ldda": hda_ldda,
- "dataset_id": trans.security.encode_id( dataset.id ),
+ "dataset": trans.security.encode_dict_ids( dataset.get_api_value() ),
"prefs": {},
"filters": { 'filters' : track_data_provider.get_filters() },
"tool": get_tool_def( trans, dataset ),
diff -r 6c7a8e5d45e0bec70ec90d6bfdcc538b072bcf11 -r 28edc7bec4048b5ef1564396ab3e6f91b03f62d6 static/scripts/viz/trackster/tracks.js
--- a/static/scripts/viz/trackster/tracks.js
+++ b/static/scripts/viz/trackster/tracks.js
@@ -2248,10 +2248,7 @@
//
// Attribute init.
//
- this.dataset = new data.Dataset({
- id: obj_dict.dataset_id,
- hda_ldda: obj_dict.hda_ldda
- });
+ this.dataset = new data.Dataset(obj_dict.dataset);
this.dataset_id = this.dataset.get('id');
this.hda_ldda = this.dataset.get('hda_ldda');
this.dataset_check_type = 'converted_datasets_state';
diff -r 6c7a8e5d45e0bec70ec90d6bfdcc538b072bcf11 -r 28edc7bec4048b5ef1564396ab3e6f91b03f62d6 templates/webapps/galaxy/tracks/browser.mako
--- a/templates/webapps/galaxy/tracks/browser.mako
+++ b/templates/webapps/galaxy/tracks/browser.mako
@@ -76,9 +76,9 @@
vis_id: "${config.get('vis_id')}",
dbkey: "${config.get('dbkey')}"
},
- JSON.parse('${ h.to_json_string( config.get( 'viewport', dict() ) ) }'),
- JSON.parse('${ h.to_json_string( config['tracks'] ).replace("'", "\\'") }'),
- JSON.parse('${ h.to_json_string( config['bookmarks'] ) }'),
+ ${ h.to_json_string( config.get( 'viewport', dict() ) ) },
+ ${ h.to_json_string( config['tracks'] ) },
+ ${ h.to_json_string( config['bookmarks'] ) },
true
);
init_editor();
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
2 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/4e5ab1d17d7d/
Changeset: 4e5ab1d17d7d
User: jgoecks
Date: 2013-04-17 16:24:43
Summary: Add sample names to VCF metadata.
Affected #: 1 file
diff -r 57b64ceac4b5eaef10eb0f6c3cf94a87646901c2 -r 4e5ab1d17d7d00e34b12b61fa8b846d1d612b132 lib/galaxy/datatypes/tabular.py
--- a/lib/galaxy/datatypes/tabular.py
+++ b/lib/galaxy/datatypes/tabular.py
@@ -543,7 +543,8 @@
MetadataElement( name="columns", default=10, desc="Number of columns", readonly=True, visible=False )
MetadataElement( name="column_types", default=['str','int','str','str','str','int','str','list','str','str'], param=metadata.ColumnTypesParameter, desc="Column types", readonly=True, visible=False )
- MetadataElement( name="viz_filter_cols", desc="Score column for visualization", default=[5], param=metadata.ColumnParameter, multiple=True )
+ MetadataElement( name="viz_filter_cols", desc="Score column for visualization", default=[5], param=metadata.ColumnParameter, multiple=True, visible=False )
+ MetadataElement( name="sample_names", default=[], desc="Sample names", readonly=True, visible=False, optional=True, no_value=[] )
def sniff( self, filename ):
headers = get_headers( filename, '\n', count=1 )
@@ -553,6 +554,21 @@
"""Returns formated html of peek"""
return Tabular.make_html_table( self, dataset, column_names=self.column_names )
+ def set_meta( self, dataset, **kwd ):
+ Tabular.set_meta( self, dataset, **kwd )
+ source = open( dataset.file_name )
+
+ # Skip comments.
+ line = None
+ for line in source:
+ if not line.startswith( '##' ):
+ break
+
+ if line and line.startswith( '#' ):
+ # Found header line, get sample names.
+ dataset.metadata.sample_names = line.split()[ 9: ]
+
+
class Eland( Tabular ):
"""Support for the export.txt.gz file used by Illumina's ELANDv2e aligner"""
file_ext = '_export.txt.gz'
https://bitbucket.org/galaxy/galaxy-central/commits/df9c639133ff/
Changeset: df9c639133ff
User: jgoecks
Date: 2013-04-17 16:25:36
Summary: Use full HDA/LDDA dict to get data into Trackster.
Affected #: 3 files
diff -r 4e5ab1d17d7d00e34b12b61fa8b846d1d612b132 -r df9c639133ff04b39a9da8cdb1083d899cb4e19d lib/galaxy/web/base/controller.py
--- a/lib/galaxy/web/base/controller.py
+++ b/lib/galaxy/web/base/controller.py
@@ -595,9 +595,8 @@
source='data' )
return {
"track_type": dataset.datatype.track_type,
+ "dataset": trans.security.encode_dict_ids( dataset.get_api_value() ),
"name": track_dict['name'],
- "hda_ldda": track_dict.get("hda_ldda", "hda"),
- "dataset_id": trans.security.encode_id( dataset.id ),
"prefs": prefs,
"mode": track_dict.get( 'mode', 'Auto' ),
"filters": track_dict.get( 'filters', { 'filters' : track_data_provider.get_filters() } ),
@@ -676,8 +675,7 @@
return {
"track_type": dataset.datatype.track_type,
"name": dataset.name,
- "hda_ldda": hda_ldda,
- "dataset_id": trans.security.encode_id( dataset.id ),
+ "dataset": trans.security.encode_dict_ids( dataset.get_api_value() ),
"prefs": {},
"filters": { 'filters' : track_data_provider.get_filters() },
"tool": get_tool_def( trans, dataset ),
diff -r 4e5ab1d17d7d00e34b12b61fa8b846d1d612b132 -r df9c639133ff04b39a9da8cdb1083d899cb4e19d static/scripts/viz/trackster/tracks.js
--- a/static/scripts/viz/trackster/tracks.js
+++ b/static/scripts/viz/trackster/tracks.js
@@ -2248,10 +2248,7 @@
//
// Attribute init.
//
- this.dataset = new data.Dataset({
- id: obj_dict.dataset_id,
- hda_ldda: obj_dict.hda_ldda
- });
+ this.dataset = new data.Dataset(obj_dict.dataset);
this.dataset_id = this.dataset.get('id');
this.hda_ldda = this.dataset.get('hda_ldda');
this.dataset_check_type = 'converted_datasets_state';
diff -r 4e5ab1d17d7d00e34b12b61fa8b846d1d612b132 -r df9c639133ff04b39a9da8cdb1083d899cb4e19d templates/webapps/galaxy/tracks/browser.mako
--- a/templates/webapps/galaxy/tracks/browser.mako
+++ b/templates/webapps/galaxy/tracks/browser.mako
@@ -76,9 +76,9 @@
vis_id: "${config.get('vis_id')}",
dbkey: "${config.get('dbkey')}"
},
- JSON.parse('${ h.to_json_string( config.get( 'viewport', dict() ) ) }'),
- JSON.parse('${ h.to_json_string( config['tracks'] ).replace("'", "\\'") }'),
- JSON.parse('${ h.to_json_string( config['bookmarks'] ) }'),
+ ${ h.to_json_string( config.get( 'viewport', dict() ) ) },
+ ${ h.to_json_string( config['tracks'] ) },
+ ${ h.to_json_string( config['bookmarks'] ) },
true
);
init_editor();
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: dannon: Fix more broken tooltips from the tipsy->bootstrap.tooltip() swap
by commits-noreply@bitbucket.org 17 Apr '13
by commits-noreply@bitbucket.org 17 Apr '13
17 Apr '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/57b64ceac4b5/
Changeset: 57b64ceac4b5
User: dannon
Date: 2013-04-17 14:40:24
Summary: Fix more broken tooltips from the tipsy->bootstrap.tooltip() swap
Affected #: 1 file
diff -r ec36ff4ec0f6baf7c6dc7af436b70a711cab94aa -r 57b64ceac4b5eaef10eb0f6c3cf94a87646901c2 templates/webapps/galaxy/workflow/editor.mako
--- a/templates/webapps/galaxy/workflow/editor.mako
+++ b/templates/webapps/galaxy/workflow/editor.mako
@@ -1015,7 +1015,7 @@
## Workflow name.
<div id="workflow-name-area" class="form-row"><label>Name:</label>
- <span id="workflow-name" class="tooltip editable-text" original-title="Click to rename workflow">${h.to_unicode( stored.name ) | h}</span>
+ <span id="workflow-name" class="tooltip editable-text" title="Click to rename workflow">${h.to_unicode( stored.name ) | h}</span></div>
## Workflow tags.
<%namespace file="/tagging_common.mako" import="render_individual_tagging_element" />
@@ -1037,7 +1037,7 @@
## Annotation elt.
<div id="workflow-annotation-area" class="form-row"><label>Annotation / Notes:</label>
- <div id="workflow-annotation" class="tooltip editable-text" original-title="Click to edit annotation">
+ <div id="workflow-annotation" class="tooltip editable-text" title="Click to edit annotation">
%if annotation:
${h.to_unicode( annotation ) | h}
%else:
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
7 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/83b09f742d31/
Changeset: 83b09f742d31
User: dannon
Date: 2013-04-17 01:01:32
Summary: Refactor api auth logic, again. This should resolve remote_user API issues and correctly allow access by key or session. This also re-allows access to the API *without* a session in the case of key auth -- probably need to review and make sure we fail gracefully if we were counting on that anywhere
Affected #: 2 files
diff -r 46133ca43f322fe8b042ac0c0b393fe72579cecc -r 83b09f742d3134168ef3925c712e1c0e54f0aeb7 lib/galaxy/web/framework/__init__.py
--- a/lib/galaxy/web/framework/__init__.py
+++ b/lib/galaxy/web/framework/__init__.py
@@ -112,34 +112,25 @@
def expose_api_anonymous( func, to_json=True ):
"""
- Expose this function via the API but don't require an API key.
+ Expose this function via the API but don't require a set user.
"""
- return expose_api( func, to_json=to_json, key_required=False )
+ return expose_api( func, to_json=to_json, user_required=False )
-def expose_api( func, to_json=True, key_required=True ):
+def expose_api( func, to_json=True, user_required=True ):
+ """
+ Expose this function via the API.
+ """
@wraps(func)
def decorator( self, trans, *args, **kwargs ):
def error( environ, start_response ):
start_response( error_status, [('Content-type', 'text/plain')] )
return error_message
error_status = '403 Forbidden'
- #If no key supplied, we use the existing session which may be an anonymous user.
- if key_required and not trans.user:
- try:
- if 'key' not in kwargs:
- raise NoResultFound( 'No key provided' )
- provided_key = trans.sa_session.query( trans.app.model.APIKeys ).filter( trans.app.model.APIKeys.table.c.key == kwargs['key'] ).one()
- except NoResultFound:
- error_message = 'Provided API key is not valid.'
- return error
- if provided_key.user.deleted:
- error_message = 'User account is deactivated, please contact an administrator.'
- return error
- newest_key = provided_key.user.api_keys[0]
- if newest_key.key != provided_key.key:
- error_message = 'Provided API key has expired.'
- return error
- trans.set_user( provided_key.user )
+ if trans.error_message:
+ return trans.error_message
+ if user_required and trans.user is None:
+ error_message = "API Authentication Required for this request"
+ return error
if trans.request.body:
def extract_payload_from_request(trans, func, kwargs):
content_type = trans.request.headers['content-type']
@@ -238,6 +229,7 @@
def form( *args, **kwargs ):
return FormBuilder( *args, **kwargs )
+
class WebApplication( base.WebApplication ):
def __init__( self, galaxy_app, session_cookie='galaxysession', name=None ):
@@ -326,6 +318,7 @@
controller_name = getattr( T, "controller_name", name )
self.add_api_controller( controller_name, T( app ) )
+
class GalaxyWebTransaction( base.DefaultWebTransaction ):
"""
Encapsulates web transaction specific state for the Galaxy application
@@ -346,13 +339,26 @@
# Flag indicating whether this is an API call and the API key user is an administrator
self.api_inherit_admin = False
self.__user = None
- # Always have a valid galaxy session
- self._ensure_valid_session( session_cookie )
- # Prevent deleted users from accessing Galaxy
- if self.app.config.use_remote_user and self.galaxy_session.user.deleted:
- self.response.send_redirect( url_for( '/static/user_disabled.html' ) )
- if self.app.config.require_login:
- self._ensure_logged_in_user( environ, session_cookie )
+ self.galaxy_session = None
+ self.error_message = None
+ if self.environ.get('is_api_request', False):
+ # With API requests, if there's a key, use it and associate the
+ # user with the transaction.
+ # If not, check for an active session but do not create one.
+ # If an error message is set here, it's sent back using
+ # trans.show_error in the response -- in expose_api.
+ self.error_message = self._authenticate_api( session_cookie )
+ else:
+ #This is a web request, get or create session.
+ self._ensure_valid_session( session_cookie )
+ if self.galaxy_session:
+ # When we've authenticated by session, we have to check the
+ # following.
+ # Prevent deleted users from accessing Galaxy
+ if self.app.config.use_remote_user and self.galaxy_session.user.deleted:
+ self.response.send_redirect( url_for( '/static/user_disabled.html' ) )
+ if self.app.config.require_login:
+ self._ensure_logged_in_user( environ, session_cookie )
def setup_i18n( self ):
locales = []
@@ -382,16 +388,17 @@
def get_user( self ):
"""Return the current user if logged in or None."""
- if self.__user:
+ if self.galaxy_session:
+ return self.galaxy_session.user
+ else:
return self.__user
- else:
- return self.galaxy_session.user
def set_user( self, user ):
"""Set the current user."""
- self.galaxy_session.user = user
- self.sa_session.add( self.galaxy_session )
- self.sa_session.flush()
+ if self.galaxy_session:
+ self.galaxy_session.user = user
+ self.sa_session.add( self.galaxy_session )
+ self.sa_session.flush()
self.__user = user
user = property( get_user, set_user )
@@ -473,6 +480,33 @@
except CookieError, e:
log.warning( "Error setting httponly attribute in cookie '%s': %s" % ( name, e ) )
+ def _authenticate_api( self, session_cookie ):
+ """
+ Authenticate for the API via key or session (if available).
+ """
+ api_key = self.request.params.get('key', None)
+ secure_id = self.get_cookie( name=session_cookie )
+ if self.environ.get('is_api_request', False) and api_key:
+ # Sessionless API transaction, we just need to associate a user.
+ try:
+ provided_key = self.sa_session.query( self.app.model.APIKeys ).filter( self.app.model.APIKeys.table.c.key == api_key ).one()
+ except NoResultFound:
+ return 'Provided API key is not valid.'
+ if provided_key.user.deleted:
+ return 'User account is deactivated, please contact an administrator.'
+ newest_key = provided_key.user.api_keys[0]
+ if newest_key.key != provided_key.key:
+ return 'Provided API key has expired.'
+ self.set_user( provided_key.user )
+ elif secure_id:
+ # API authentication via active session
+ # Associate user using existing session
+ self._ensure_valid_session( session_cookie )
+ else:
+ # Anonymous API interaction -- anything but @expose_api_anonymous will fail past here.
+ self.user = None
+ self.galaxy_session = None
+
def _ensure_valid_session( self, session_cookie, create=True):
"""
Ensure that a valid Galaxy session exists and is available as
@@ -505,26 +539,27 @@
.filter( and_( self.app.model.GalaxySession.table.c.session_key==session_key,
self.app.model.GalaxySession.table.c.is_valid==True ) ) \
.first()
- # If remote user is in use it can invalidate the session, so we need to to check some things now.
- if self.app.config.use_remote_user:
- assert "HTTP_REMOTE_USER" in self.environ, \
- "use_remote_user is set but no HTTP_REMOTE_USER variable"
- remote_user_email = self.environ[ 'HTTP_REMOTE_USER' ]
- if galaxy_session:
- # An existing session, make sure correct association exists
- if galaxy_session.user is None:
- # No user, associate
- galaxy_session.user = self.get_or_create_remote_user( remote_user_email )
- galaxy_session_requires_flush = True
- elif galaxy_session.user.email != remote_user_email:
- # Session exists but is not associated with the correct remote user
- invalidate_existing_session = True
+ # If remote user is in use it can invalidate the session, so we need to to check some things now.
+ if self.app.config.use_remote_user:
+ #If this is an api request, and they've passed a key, we let this go.
+ assert "HTTP_REMOTE_USER" in self.environ, \
+ "use_remote_user is set but no HTTP_REMOTE_USER variable"
+ remote_user_email = self.environ[ 'HTTP_REMOTE_USER' ]
+ if galaxy_session:
+ # An existing session, make sure correct association exists
+ if galaxy_session.user is None:
+ # No user, associate
+ galaxy_session.user = self.get_or_create_remote_user( remote_user_email )
+ galaxy_session_requires_flush = True
+ elif galaxy_session.user.email != remote_user_email:
+ # Session exists but is not associated with the correct remote user
+ invalidate_existing_session = True
+ user_for_new_session = self.get_or_create_remote_user( remote_user_email )
+ log.warning( "User logged in as '%s' externally, but has a cookie as '%s' invalidating session",
+ remote_user_email, galaxy_session.user.email )
+ else:
+ # No session exists, get/create user for new session
user_for_new_session = self.get_or_create_remote_user( remote_user_email )
- log.warning( "User logged in as '%s' externally, but has a cookie as '%s' invalidating session",
- remote_user_email, galaxy_session.user.email )
- else:
- # No session exists, get/create user for new session
- user_for_new_session = self.get_or_create_remote_user( remote_user_email )
else:
if galaxy_session is not None and galaxy_session.user and galaxy_session.user.external:
# Remote user support is not enabled, but there is an existing
@@ -605,6 +640,7 @@
pass
if self.request.path not in allowed_paths:
self.response.send_redirect( url_for( controller='root', action='index' ) )
+
def __create_new_session( self, prev_galaxy_session=None, user_for_new_session=None ):
"""
Create a new GalaxySession for this request, possibly with a connection
@@ -627,6 +663,7 @@
# The new session should be associated with the user
galaxy_session.user = user_for_new_session
return galaxy_session
+
def get_or_create_remote_user( self, remote_user_email ):
"""
Create a remote user with the email remote_user_email and return it
@@ -671,11 +708,13 @@
self.app.security_agent.user_set_default_permissions( user )
#self.log_event( "Automatically created account '%s'", user.email )
return user
+
def __update_session_cookie( self, name='galaxysession' ):
"""
Update the session cookie to match the current session.
"""
self.set_cookie( self.security.encode_guid( self.galaxy_session.session_key ), name=name, path=self.app.config.cookie_path )
+
def handle_user_login( self, user ):
"""
Login a new user (possibly newly created)
@@ -701,9 +740,9 @@
except:
users_last_session = None
last_accessed = False
- if prev_galaxy_session.current_history and \
- not prev_galaxy_session.current_history.deleted and \
- prev_galaxy_session.current_history.datasets:
+ if (prev_galaxy_session.current_history and not
+ prev_galaxy_session.current_history.deleted and
+ prev_galaxy_session.current_history.datasets):
if prev_galaxy_session.current_history.user is None or prev_galaxy_session.current_history.user == user:
# If the previous galaxy session had a history, associate it with the new
# session, but only if it didn't belong to a different user.
@@ -714,10 +753,9 @@
user.total_disk_usage += hda.quota_amount( user )
elif self.galaxy_session.current_history:
history = self.galaxy_session.current_history
- if not history and \
- users_last_session and \
- users_last_session.current_history and \
- not users_last_session.current_history.deleted:
+ if (not history and users_last_session and
+ users_last_session.current_history and not
+ users_last_session.current_history.deleted):
history = users_last_session.current_history
elif not history:
history = self.get_history( create=True )
@@ -736,6 +774,8 @@
self.sa_session.flush()
# This method is not called from the Galaxy reports, so the cookie will always be galaxysession
self.__update_session_cookie( name=cookie_name )
+
+
def handle_user_logout( self, logout_all=False ):
"""
Logout the current user:
@@ -988,6 +1028,7 @@
return True
return False
+
class FormBuilder( object ):
"""
Simple class describing an HTML form
@@ -999,17 +1040,22 @@
self.submit_text = submit_text
self.inputs = []
self.use_panels = use_panels
+
def add_input( self, type, name, label, value=None, error=None, help=None, use_label=True ):
self.inputs.append( FormInput( type, label, name, value, error, help, use_label ) )
return self
+
def add_text( self, name, label, value=None, error=None, help=None ):
return self.add_input( 'text', label, name, value, error, help )
+
def add_password( self, name, label, value=None, error=None, help=None ):
return self.add_input( 'password', label, name, value, error, help )
+
def add_select( self, name, label, value=None, options=[], error=None, help=None, use_label=True ):
self.inputs.append( SelectInput( name, label, value=value, options=options, error=error, help=help, use_label=use_label ) )
return self
+
class FormInput( object ):
"""
Simple class describing a form input element
@@ -1023,12 +1069,14 @@
self.help = help
self.use_label = use_label
+
class SelectInput( FormInput ):
""" A select form input. """
def __init__( self, name, label, value=None, options=[], error=None, help=None, use_label=True ):
FormInput.__init__( self, "select", name, label, value=value, error=error, help=help, use_label=use_label )
self.options = options
+
class FormData( object ):
"""
Class for passing data about a form to a template, very rudimentary, could
@@ -1038,6 +1086,7 @@
self.values = Bunch()
self.errors = Bunch()
+
class Bunch( dict ):
"""
Bunch based on a dict
@@ -1047,3 +1096,4 @@
return self[key]
def __setattr__( self, key, value ):
self[key] = value
+
diff -r 46133ca43f322fe8b042ac0c0b393fe72579cecc -r 83b09f742d3134168ef3925c712e1c0e54f0aeb7 lib/galaxy/web/framework/base.py
--- a/lib/galaxy/web/framework/base.py
+++ b/lib/galaxy/web/framework/base.py
@@ -138,6 +138,7 @@
environ[ 'is_api_request' ] = True
controllers = self.api_controllers
else:
+ environ[ 'is_api_request' ] = False
controllers = self.controllers
if map == None:
raise httpexceptions.HTTPNotFound( "No route for " + path_info )
https://bitbucket.org/galaxy/galaxy-central/commits/bf323c3cf3c2/
Changeset: bf323c3cf3c2
User: dannon
Date: 2013-04-17 01:03:39
Summary: Cleanup spacing in framework/base.py
Affected #: 1 file
diff -r 83b09f742d3134168ef3925c712e1c0e54f0aeb7 -r bf323c3cf3c28ebbecb7491abb87e58bf7f7a028 lib/galaxy/web/framework/base.py
--- a/lib/galaxy/web/framework/base.py
+++ b/lib/galaxy/web/framework/base.py
@@ -44,20 +44,21 @@
self.resource( member_name, collection_name, **kwargs )
routes.Mapper.resource_with_deleted = __resource_with_deleted
+
class WebApplication( object ):
"""
A simple web application which maps requests to objects using routes,
- and to methods on those objects in the CherryPy style. Thus simple
+ and to methods on those objects in the CherryPy style. Thus simple
argument mapping in the CherryPy style occurs automatically, but more
complicated encoding of arguments in the PATH_INFO can be performed
with routes.
"""
def __init__( self ):
"""
- Create a new web application object. To actually connect some
- controllers use `add_controller` and `add_route`. Call
+ Create a new web application object. To actually connect some
+ controllers use `add_controller` and `add_route`. Call
`finalize_config` when all controllers and routes have been added
- and `__call__` to handle a request (WSGI style).
+ and `__call__` to handle a request (WSGI style).
"""
self.controllers = dict()
self.api_controllers = dict()
@@ -69,36 +70,41 @@
self.transaction_factory = DefaultWebTransaction
# Set if trace logging is enabled
self.trace_logger = None
+
def add_ui_controller( self, controller_name, controller ):
"""
Add a controller class to this application. A controller class has
methods which handle web requests. To connect a URL to a controller's
method use `add_route`.
"""
- log.debug( "Enabling '%s' controller, class: %s",
+ log.debug( "Enabling '%s' controller, class: %s",
controller_name, controller.__class__.__name__ )
self.controllers[ controller_name ] = controller
+
def add_api_controller( self, controller_name, controller ):
log.debug( "Enabling '%s' API controller, class: %s",
controller_name, controller.__class__.__name__ )
self.api_controllers[ controller_name ] = controller
+
def add_route( self, route, **kwargs ):
"""
Add a route to match a URL with a method. Accepts all keyword
arguments of `routes.Mapper.connect`. Every route should result in
- at least a controller value which corresponds to one of the
- objects added with `add_controller`. It optionally may yield an
+ at least a controller value which corresponds to one of the
+ objects added with `add_controller`. It optionally may yield an
`action` argument which will be used to locate the method to call
on the controller. Additional arguments will be passed to the
- method as keyword args.
+ method as keyword args.
"""
self.mapper.connect( route, **kwargs )
+
def set_transaction_factory( self, transaction_factory ):
"""
Use the callable `transaction_factory` to create the transaction
which will be passed to requests.
"""
self.transaction_factory = transaction_factory
+
def finalize_config( self ):
"""
Call when application is completely configured and ready to serve
@@ -106,6 +112,7 @@
"""
# Create/compile the regular expressions for route mapping
self.mapper.create_regs( self.controllers.keys() )
+
def trace( self, **fields ):
if self.trace_logger:
self.trace_logger.log( "WebApplication", **fields )
@@ -173,7 +180,7 @@
raise httpexceptions.HTTPNotFound( "Action not exposed for " + path_info )
# Is the method callable
if not callable( method ):
- raise httpexceptions.HTTPNotFound( "Action not callable for " + path_info )
+ raise httpexceptions.HTTPNotFound( "Action not callable for " + path_info )
# Combine mapper args and query string / form args and call
kwargs = trans.request.params.mixed()
kwargs.update( map )
@@ -196,14 +203,14 @@
elif isinstance( body, tarfile.ExFileObject ):
# Stream the tarfile member back to the browser
body = iterate_file( body )
- start_response( trans.response.wsgi_status(),
+ start_response( trans.response.wsgi_status(),
trans.response.wsgi_headeritems() )
return body
else:
- start_response( trans.response.wsgi_status(),
+ start_response( trans.response.wsgi_status(),
trans.response.wsgi_headeritems() )
return self.make_body_iterable( trans, body )
-
+
def make_body_iterable( self, trans, body ):
if isinstance( body, ( types.GeneratorType, list, tuple ) ):
# Recursively stream the iterable
@@ -223,7 +230,8 @@
Allow handling of exceptions raised in controller methods.
"""
return False
-
+
+
class WSGIEnvironmentProperty( object ):
"""
Descriptor that delegates a property to a key in the environ member of the
@@ -237,6 +245,7 @@
if obj is None: return self
return obj.environ.get( self.key, self.default )
+
class LazyProperty( object ):
"""
Property that replaces itself with a calculated value the first time
@@ -250,12 +259,13 @@
setattr( obj, self.func.func_name, value )
return value
lazy_property = LazyProperty
-
+
+
class DefaultWebTransaction( object ):
"""
- Wraps the state of a single web transaction (request/response cycle).
+ Wraps the state of a single web transaction (request/response cycle).
- TODO: Provide hooks to allow application specific state to be included
+ TODO: Provide hooks to allow application specific state to be included
in here.
"""
def __init__( self, environ ):
@@ -274,7 +284,7 @@
return self.environ['beaker.session']
else:
return None
-
+
# For request.params, override cgi.FieldStorage.make_file to create persistent
# tempfiles. Necessary for externalizing the upload tool. It's a little hacky
# but for performance reasons it's way better to use Paste's tempfile than to
@@ -290,12 +300,13 @@
if self.outerboundary:
self.read_lines_to_outerboundary()
else:
- self.read_lines_to_eof()
+ self.read_lines_to_eof()
cgi.FieldStorage = FieldStorage
+
class Request( webob.Request ):
"""
- Encapsulates an HTTP request.
+ Encapsulates an HTTP request.
"""
def __init__( self, environ ):
"""
@@ -330,7 +341,7 @@
return self.environ['SCRIPT_NAME'] + self.environ['PATH_INFO']
@lazy_property
def browser_url( self ):
- return self.base + self.path
+ return self.base + self.path
# Descriptors that map properties to the associated environment
## scheme = WSGIEnvironmentProperty( 'wsgi.url_scheme' )
## remote_addr = WSGIEnvironmentProperty( 'REMOTE_ADDR' )
@@ -341,6 +352,7 @@
## query_string = WSGIEnvironmentProperty( 'QUERY_STRING' )
## path_info = WSGIEnvironmentProperty( 'PATH_INFO' )
+
class Response( object ):
"""
Describes an HTTP response. Currently very simple since the actual body
@@ -353,18 +365,22 @@
self.status = "200 OK"
self.headers = HeaderDict( { "content-type": "text/html" } )
self.cookies = SimpleCookie()
+
def set_content_type( self, type ):
"""
Sets the Content-Type header
"""
self.headers[ "content-type" ] = type
+
def get_content_type( self ):
return self.headers[ "content-type" ]
+
def send_redirect( self, url ):
"""
Send an HTTP redirect response to (target `url`)
"""
raise httpexceptions.HTTPFound( url, headers=self.wsgi_headeritems() )
+
def wsgi_headeritems( self ):
"""
Return headers in format appropriate for WSGI `start_response`
@@ -376,10 +392,11 @@
header, value = str( crumb ).split( ': ', 1 )
result.append( ( header, value ) )
return result
+
def wsgi_status( self ):
"""
Return status line in format appropriate for WSGI `start_response`
- """
+ """
if isinstance( self.status, int ):
exception = httpexceptions.get_exception( self.status )
return "%d %s" % ( exception.code, exception.title )
@@ -404,7 +421,7 @@
# Fall back on sending the file in chunks
else:
body = iterate_file( body )
- start_response( trans.response.wsgi_status(),
+ start_response( trans.response.wsgi_status(),
trans.response.wsgi_headeritems() )
return body
https://bitbucket.org/galaxy/galaxy-central/commits/356965791008/
Changeset: 356965791008
User: dannon
Date: 2013-04-17 01:06:42
Summary: Cleanup in framework/__init__.py
Affected #: 1 file
diff -r bf323c3cf3c28ebbecb7491abb87e58bf7f7a028 -r 356965791008f24aa26dc8043259765dcc0e7f7e lib/galaxy/web/framework/__init__.py
--- a/lib/galaxy/web/framework/__init__.py
+++ b/lib/galaxy/web/framework/__init__.py
@@ -713,7 +713,8 @@
"""
Update the session cookie to match the current session.
"""
- self.set_cookie( self.security.encode_guid( self.galaxy_session.session_key ), name=name, path=self.app.config.cookie_path )
+ self.set_cookie( self.security.encode_guid(self.galaxy_session.session_key ),
+ name=name, path=self.app.config.cookie_path )
def handle_user_login( self, user ):
"""
@@ -800,11 +801,13 @@
self.__update_session_cookie( name='galaxysession' )
elif self.webapp.name == 'tool_shed':
self.__update_session_cookie( name='galaxycommunitysession' )
+
def get_galaxy_session( self ):
"""
Return the current galaxy session
"""
return self.galaxy_session
+
def get_history( self, create=False ):
"""
Load the current history, creating a new one only if there is not
@@ -819,12 +822,15 @@
log.debug( "This request returned None from get_history(): %s" % self.request.browser_url )
return None
return history
+
def set_history( self, history ):
if history and not history.deleted:
self.galaxy_session.current_history = history
self.sa_session.add( self.galaxy_session )
self.sa_session.flush()
+
history = property( get_history, set_history )
+
def new_history( self, name=None ):
"""
Create a new history and associate it with the current session and
@@ -849,6 +855,7 @@
self.sa_session.add_all( ( self.galaxy_session, history ) )
self.sa_session.flush()
return history
+
def get_current_user_roles( self ):
user = self.get_user()
if user:
@@ -856,27 +863,34 @@
else:
roles = []
return roles
+
def user_is_admin( self ):
if self.api_inherit_admin:
return True
admin_users = [ x.strip() for x in self.app.config.get( "admin_users", "" ).split( "," ) ]
return self.user and admin_users and self.user.email in admin_users
+
def user_can_do_run_as( self ):
run_as_users = self.app.config.get( "api_allow_run_as", "" ).split( "," )
return self.user and run_as_users and self.user.email in run_as_users
+
def get_toolbox(self):
"""Returns the application toolbox"""
return self.app.toolbox
+
@base.lazy_property
def template_context( self ):
return dict()
+
@property
def model( self ):
return self.app.model
+
def make_form_data( self, name, **kwargs ):
rval = self.template_context[name] = FormData()
rval.values.update( kwargs )
return rval
+
def set_message( self, message, type=None ):
"""
Convenience method for setting the 'message' and 'message_type'
@@ -885,12 +899,14 @@
self.template_context['message'] = message
if type:
self.template_context['status'] = type
+
def get_message( self ):
"""
Convenience method for getting the 'message' element of the template
context.
"""
return self.template_context['message']
+
def show_message( self, message, type='info', refresh_frames=[], cont=None, use_panels=False, active_view="" ):
"""
Convenience method for displaying a simple page with a single message.
@@ -902,21 +918,25 @@
refreshed when the message is displayed
"""
return self.fill_template( "message.mako", status=type, message=message, refresh_frames=refresh_frames, cont=cont, use_panels=use_panels, active_view=active_view )
+
def show_error_message( self, message, refresh_frames=[], use_panels=False, active_view="" ):
"""
Convenience method for displaying an error message. See `show_message`.
"""
return self.show_message( message, 'error', refresh_frames, use_panels=use_panels, active_view=active_view )
+
def show_ok_message( self, message, refresh_frames=[], use_panels=False, active_view="" ):
"""
Convenience method for displaying an ok message. See `show_message`.
"""
return self.show_message( message, 'done', refresh_frames, use_panels=use_panels, active_view=active_view )
+
def show_warn_message( self, message, refresh_frames=[], use_panels=False, active_view="" ):
"""
Convenience method for displaying an warn message. See `show_message`.
"""
return self.show_message( message, 'warning', refresh_frames, use_panels=use_panels, active_view=active_view )
+
def show_form( self, form, header=None, template="form.mako", use_panels=False, active_view="" ):
"""
Convenience method for displaying a simple page with a single HTML
@@ -924,6 +944,7 @@
"""
return self.fill_template( template, form=form, header=header, use_panels=( form.use_panels or use_panels ),
active_view=active_view )
+
def fill_template(self, filename, **kwargs):
"""
Fill in a template, putting any keyword arguments on the context.
@@ -937,6 +958,7 @@
template = Template( file=os.path.join(self.app.config.template_path, filename),
searchList=[kwargs, self.template_context, dict(caller=self, t=self, h=helpers, util=util, request=self.request, response=self.response, app=self.app)] )
return str( template )
+
def fill_template_mako( self, filename, **kwargs ):
template = self.webapp.mako_template_lookup.get_template( filename )
template.output_encoding = 'utf-8'
@@ -944,6 +966,7 @@
data.update( self.template_context )
data.update( kwargs )
return template.render( **data )
+
def stream_template_mako( self, filename, **kwargs ):
template = self.webapp.mako_template_lookup.get_template( filename )
template.output_encoding = 'utf-8'
@@ -961,6 +984,7 @@
template.render_context( context )
return []
return render
+
def fill_template_string(self, template_string, context=None, **kwargs):
"""
Fill in a template, putting any keyword arguments on the context.
https://bitbucket.org/galaxy/galaxy-central/commits/18c73eeb77fe/
Changeset: 18c73eeb77fe
User: dannon
Date: 2013-04-17 01:07:02
Summary: Merge with galaxy-central
Affected #: 1 file
diff -r 356965791008f24aa26dc8043259765dcc0e7f7e -r 18c73eeb77feba055b2240412006dc3ce2e49fb0 lib/galaxy/visualization/data_providers/genome.py
--- a/lib/galaxy/visualization/data_providers/genome.py
+++ b/lib/galaxy/visualization/data_providers/genome.py
@@ -770,6 +770,10 @@
else:
pos = source.tell()
+ # If last line is a comment, there are no data lines.
+ if line.startswith( "#" ):
+ return []
+
# Match chrom naming format.
if line:
dataset_chrom = line.split()[0]
@@ -1272,7 +1276,7 @@
class IntervalIndexDataProvider( FilterableMixin, GenomeDataProvider ):
"""
- Interval index files used only for GFF files.
+ Interval index files used for GFF, Pileup files.
"""
col_name_data_attr_mapping = { 4 : { 'index': 4 , 'name' : 'Score' } }
@@ -1282,20 +1286,26 @@
source = open( self.original_dataset.file_name )
index = Indexes( self.converted_dataset.file_name )
out = open( filename, 'w' )
-
+
for region in regions:
# Write data from region.
chrom = region.chrom
start = region.start
end = region.end
- for start, end, offset in index.find(chrom, start, end):
+ for start, end, offset in index.find( chrom, start, end ):
source.seek( offset )
-
- reader = GFFReaderWrapper( source, fix_strand=True )
- feature = reader.next()
- for interval in feature.intervals:
- out.write( '\t'.join( interval.fields ) + '\n' )
-
+
+ # HACK: write differently depending on original dataset format.
+ if self.original_dataset.ext not in [ 'gff', 'gff3', 'gtf' ]:
+ line = source.readline()
+ out.write( line )
+ else:
+ reader = GFFReaderWrapper( source, fix_strand=True )
+ feature = reader.next()
+ for interval in feature.intervals:
+ out.write( '\t'.join( interval.fields ) + '\n' )
+
+ source.close()
out.close()
def get_iterator( self, chrom, start, end, **kwargs ):
https://bitbucket.org/galaxy/galaxy-central/commits/94caae7433a7/
Changeset: 94caae7433a7
User: dannon
Date: 2013-04-17 03:38:38
Summary: Disable select2 for Input Dataset steps on the run workflow page.
Affected #: 1 file
Diff not available.
https://bitbucket.org/galaxy/galaxy-central/commits/60d7b1a9ebec/
Changeset: 60d7b1a9ebec
User: dannon
Date: 2013-04-17 03:47:17
Summary: Update multiselect tooltip, now functional. Was still using tipsy's 'original-title' attribute.
Affected #: 1 file
Diff not available.
https://bitbucket.org/galaxy/galaxy-central/commits/ec36ff4ec0f6/
Changeset: ec36ff4ec0f6
User: dannon
Date: 2013-04-17 04:27:07
Summary: Add tooltips for (un)linking icon on run workflow page.
Affected #: 1 file
Diff not available.
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: Enable IntervalIndex data provider to work with pileup datasets.
by commits-noreply@bitbucket.org 16 Apr '13
by commits-noreply@bitbucket.org 16 Apr '13
16 Apr '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/98b6216e42f5/
Changeset: 98b6216e42f5
User: jgoecks
Date: 2013-04-17 01:01:50
Summary: Enable IntervalIndex data provider to work with pileup datasets.
Affected #: 1 file
diff -r 46133ca43f322fe8b042ac0c0b393fe72579cecc -r 98b6216e42f5beec89052cccf7c98820b978bf92 lib/galaxy/visualization/data_providers/genome.py
--- a/lib/galaxy/visualization/data_providers/genome.py
+++ b/lib/galaxy/visualization/data_providers/genome.py
@@ -770,6 +770,10 @@
else:
pos = source.tell()
+ # If last line is a comment, there are no data lines.
+ if line.startswith( "#" ):
+ return []
+
# Match chrom naming format.
if line:
dataset_chrom = line.split()[0]
@@ -1272,7 +1276,7 @@
class IntervalIndexDataProvider( FilterableMixin, GenomeDataProvider ):
"""
- Interval index files used only for GFF files.
+ Interval index files used for GFF, Pileup files.
"""
col_name_data_attr_mapping = { 4 : { 'index': 4 , 'name' : 'Score' } }
@@ -1282,20 +1286,26 @@
source = open( self.original_dataset.file_name )
index = Indexes( self.converted_dataset.file_name )
out = open( filename, 'w' )
-
+
for region in regions:
# Write data from region.
chrom = region.chrom
start = region.start
end = region.end
- for start, end, offset in index.find(chrom, start, end):
+ for start, end, offset in index.find( chrom, start, end ):
source.seek( offset )
-
- reader = GFFReaderWrapper( source, fix_strand=True )
- feature = reader.next()
- for interval in feature.intervals:
- out.write( '\t'.join( interval.fields ) + '\n' )
-
+
+ # HACK: write differently depending on original dataset format.
+ if self.original_dataset.ext not in [ 'gff', 'gff3', 'gtf' ]:
+ line = source.readline()
+ out.write( line )
+ else:
+ reader = GFFReaderWrapper( source, fix_strand=True )
+ feature = reader.next()
+ for interval in feature.intervals:
+ out.write( '\t'.join( interval.fields ) + '\n' )
+
+ source.close()
out.close()
def get_iterator( self, chrom, start, end, **kwargs ):
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: Make a data_sources attribute for data types and remove get_track_type because it is no longer needed.
by commits-noreply@bitbucket.org 16 Apr '13
by commits-noreply@bitbucket.org 16 Apr '13
16 Apr '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/46133ca43f32/
Changeset: 46133ca43f32
User: jgoecks
Date: 2013-04-17 00:11:09
Summary: Make a data_sources attribute for data types and remove get_track_type because it is no longer needed.
Affected #: 8 files
diff -r da3b931de04c93ddae85e4999b6911948fdf0b34 -r 46133ca43f322fe8b042ac0c0b393fe72579cecc lib/galaxy/datatypes/binary.py
--- a/lib/galaxy/datatypes/binary.py
+++ b/lib/galaxy/datatypes/binary.py
@@ -95,6 +95,7 @@
"""Class describing a BAM binary file"""
file_ext = "bam"
track_type = "ReadTrack"
+ data_sources = { "data": "bai", "index": [ "bigwig", "summary_tree" ] }
MetadataElement( name="bam_index", desc="BAM Index File", param=metadata.FileParameter, file_ext="bai", readonly=True, no_value=None, visible=False, optional=True )
@@ -246,9 +247,7 @@
return dataset.peek
except:
return "Binary bam alignments file (%s)" % ( data.nice_size( dataset.get_size() ) )
- def get_track_type( self ):
- return self.track_type, { "data": "bai", "index": [ "bigwig", "summary_tree" ] }
-
+
Binary.register_sniffable_binary_format("bam", "bam", Bam)
class H5( Binary ):
@@ -327,6 +326,7 @@
http://bioinformatics.oxfordjournals.org/cgi/content/abstract/btq351v1
"""
track_type = "LineTrack"
+ data_sources = { "data_standalone": "bigwig" }
def __init__( self, **kwd ):
Binary.__init__( self, **kwd )
@@ -352,20 +352,18 @@
return dataset.peek
except:
return "Binary UCSC %s file (%s)" % ( self._name, data.nice_size( dataset.get_size() ) )
- def get_track_type( self ):
- return self.track_type, {"data_standalone": "bigwig"}
-
+
Binary.register_sniffable_binary_format("bigwig", "bigwig", BigWig)
class BigBed(BigWig):
"""BigBed support from UCSC."""
+ data_sources = { "data_standalone": "bigbed" }
+
def __init__( self, **kwd ):
Binary.__init__( self, **kwd )
self._magic = 0x8789F2EB
self._name = "BigBed"
- def get_track_type( self ):
- return self.track_type, {"data_standalone": "bigbed"}
Binary.register_sniffable_binary_format("bigbed", "bigbed", BigBed)
diff -r da3b931de04c93ddae85e4999b6911948fdf0b34 -r 46133ca43f322fe8b042ac0c0b393fe72579cecc lib/galaxy/datatypes/data.py
--- a/lib/galaxy/datatypes/data.py
+++ b/lib/galaxy/datatypes/data.py
@@ -100,6 +100,9 @@
# Trackster track type.
track_type = None
+ # Data sources.
+ data_sources = {}
+
def __init__(self, **kwd):
"""Initialize the datatype"""
object.__init__(self, **kwd)
diff -r da3b931de04c93ddae85e4999b6911948fdf0b34 -r 46133ca43f322fe8b042ac0c0b393fe72579cecc lib/galaxy/datatypes/interval.py
--- a/lib/galaxy/datatypes/interval.py
+++ b/lib/galaxy/datatypes/interval.py
@@ -47,6 +47,7 @@
file_ext = "interval"
line_class = "region"
track_type = "FeatureTrack"
+ data_sources = { "data": "tabix", "index": "summary_tree" }
"""Add metadata elements"""
MetadataElement( name="chromCol", default=1, desc="Chrom column", param=metadata.ColumnParameter )
@@ -329,18 +330,13 @@
def get_track_resolution( self, dataset, start, end):
return None
-
- def get_track_type( self ):
- return self.track_type, {"data": "tabix", "index": "summary_tree"}
class BedGraph( Interval ):
"""Tab delimited chrom/start/end/datavalue dataset"""
file_ext = "bedgraph"
track_type = "LineTrack"
-
- def get_track_type( self ):
- return self.track_type, { "data": "bigwig", "index": "bigwig" }
+ data_sources = { "data": "bigwig", "index": "bigwig" }
def as_ucsc_display_file( self, dataset, **kwd ):
"""
@@ -358,6 +354,7 @@
class Bed( Interval ):
"""Tab delimited data in BED format"""
file_ext = "bed"
+ data_sources = {"data": "tabix", "index": "summary_tree", "feature_search": "fli"}
"""Add metadata elements"""
MetadataElement( name="chromCol", default=1, desc="Chrom column", param=metadata.ColumnParameter )
@@ -512,9 +509,6 @@
else: return False
return True
except: return False
-
- def get_track_type( self ):
- return self.track_type, {"data": "tabix", "index": "summary_tree", "feature_search": "fli"}
class BedStrict( Bed ):
"""Tab delimited data in strict BED format - no non-standard columns allowed"""
@@ -574,6 +568,7 @@
"""Tab delimited data in Gff format"""
file_ext = "gff"
column_names = [ 'Seqname', 'Source', 'Feature', 'Start', 'End', 'Score', 'Strand', 'Frame', 'Group' ]
+ data_sources = { "data": "interval_index", "index": "summary_tree", "feature_search": "fli" }
"""Add metadata elements"""
MetadataElement( name="columns", default=9, desc="Number of columns", readonly=True, visible=False )
@@ -785,10 +780,6 @@
return True
except:
return False
-
- def get_track_type( self ):
- return self.track_type, {"data": "interval_index", "index": "summary_tree", "feature_search": "fli"}
-
class Gff3( Gff ):
"""Tab delimited data in Gff3 format"""
@@ -969,6 +960,7 @@
"""Tab delimited data in wiggle format"""
file_ext = "wig"
track_type = "LineTrack"
+ data_sources = { "data": "bigwig", "index": "bigwig" }
MetadataElement( name="columns", default=3, desc="Number of columns", readonly=True, visible=False )
@@ -1149,9 +1141,6 @@
resolution = min( resolution, 100000 )
resolution = max( resolution, 1 )
return resolution
-
- def get_track_type( self ):
- return self.track_type, { "data": "bigwig", "index": "bigwig" }
class CustomTrack ( Tabular ):
"""UCSC CustomTrack"""
@@ -1295,6 +1284,7 @@
file_ext = "encodepeak"
column_names = [ 'Chrom', 'Start', 'End', 'Name', 'Score', 'Strand', 'SignalValue', 'pValue', 'qValue', 'Peak' ]
+ data_sources = { "data": "tabix", "index": "summary_tree" }
"""Add metadata elements"""
MetadataElement( name="chromCol", default=1, desc="Chrom column", param=metadata.ColumnParameter )
@@ -1306,9 +1296,6 @@
def sniff( self, filename ):
return False
- def get_track_type( self ):
- return self.track_type, {"data": "tabix", "index": "summary_tree"}
-
class ChromatinInteractions( Interval ):
'''
Chromatin interactions obtained from 3C/5C/Hi-C experiments.
@@ -1316,6 +1303,7 @@
file_ext = "chrint"
track_type = "DiagonalHeatmapTrack"
+ data_sources = { "data": "tabix", "index": "summary_tree" }
column_names = [ 'Chrom1', 'Start1', 'End1', 'Chrom2', 'Start2', 'End2', 'Value' ]
@@ -1332,11 +1320,6 @@
def sniff( self, filename ):
return False
-
- def get_track_type( self ):
- return self.track_type, {"data": "tabix", "index": "summary_tree"}
-
-
if __name__ == '__main__':
import doctest, sys
diff -r da3b931de04c93ddae85e4999b6911948fdf0b34 -r 46133ca43f322fe8b042ac0c0b393fe72579cecc lib/galaxy/datatypes/tabular.py
--- a/lib/galaxy/datatypes/tabular.py
+++ b/lib/galaxy/datatypes/tabular.py
@@ -359,6 +359,7 @@
class Sam( Tabular ):
file_ext = 'sam'
track_type = "ReadTrack"
+ data_sources = { "data": "bam", "index": "summary_tree" }
def __init__(self, **kwd):
"""Initialize taxonomy datatype"""
@@ -469,13 +470,11 @@
raise Exception('Result %s from %s' % (result, cmd))
merge = staticmethod(merge)
- def get_track_type( self ):
- return self.track_type, {"data": "bam", "index": "summary_tree"}
-
class Pileup( Tabular ):
"""Tab delimited data in pileup (6- or 10-column) format"""
file_ext = "pileup"
line_class = "genomic coordinate"
+ data_sources = { "data": "interval_index" }
"""Add metadata elements"""
MetadataElement( name="chromCol", default=1, desc="Chrom column", param=metadata.ColumnParameter )
@@ -527,10 +526,6 @@
return True
except:
return False
-
- def get_track_type( self ):
- return self.track_type, { "data": "interval_index" }
-
class ElandMulti( Tabular ):
file_ext = 'elandmulti'
@@ -541,6 +536,7 @@
class Vcf( Tabular ):
""" Variant Call Format for describing SNPs and other simple genome variations. """
track_type = "VariantTrack"
+ data_sources = { "data": "tabix", "index": "summary_tree" }
file_ext = 'vcf'
column_names = [ 'Chrom', 'Pos', 'ID', 'Ref', 'Alt', 'Qual', 'Filter', 'Info', 'Format', 'data' ]
@@ -557,9 +553,6 @@
"""Returns formated html of peek"""
return Tabular.make_html_table( self, dataset, column_names=self.column_names )
- def get_track_type( self ):
- return self.track_type, { "data": "tabix", "index": "summary_tree" }
-
class Eland( Tabular ):
"""Support for the export.txt.gz file used by Illumina's ELANDv2e aligner"""
file_ext = '_export.txt.gz'
diff -r da3b931de04c93ddae85e4999b6911948fdf0b34 -r 46133ca43f322fe8b042ac0c0b393fe72579cecc lib/galaxy/model/__init__.py
--- a/lib/galaxy/model/__init__.py
+++ b/lib/galaxy/model/__init__.py
@@ -1333,10 +1333,9 @@
with entries of type
(<datasource_type> : {<datasource_name>, <indexing_message>}).
"""
- track_type, data_sources = self.datatype.get_track_type()
data_sources_dict = {}
msg = None
- for source_type, source_list in data_sources.iteritems():
+ for source_type, source_list in self.datatype.data_sources.iteritems():
data_source = None
if source_type == "data_standalone":
# Nothing to do.
diff -r da3b931de04c93ddae85e4999b6911948fdf0b34 -r 46133ca43f322fe8b042ac0c0b393fe72579cecc lib/galaxy/visualization/data_providers/registry.py
--- a/lib/galaxy/visualization/data_providers/registry.py
+++ b/lib/galaxy/visualization/data_providers/registry.py
@@ -83,12 +83,12 @@
elif original_dataset:
# No name, so look up a provider name from datatype's information.
- # Dataset must have get_track_type function to get data.
- if not hasattr( original_dataset.datatype, 'get_track_type'):
+ # Dataset must have data sources to get data.
+ if not original_dataset.datatype.data_sources:
return None
# Get data provider mapping and data provider.
- _ , data_provider_mapping = original_dataset.datatype.get_track_type()
+ data_provider_mapping = original_dataset.datatype.data_sources
if 'data_standalone' in data_provider_mapping:
data_provider = self.get_data_provider( trans,
name=data_provider_mapping[ 'data_standalone' ],
diff -r da3b931de04c93ddae85e4999b6911948fdf0b34 -r 46133ca43f322fe8b042ac0c0b393fe72579cecc lib/galaxy/web/base/controller.py
--- a/lib/galaxy/web/base/controller.py
+++ b/lib/galaxy/web/base/controller.py
@@ -590,12 +590,11 @@
except KeyError:
prefs = {}
- track_type, _ = dataset.datatype.get_track_type()
track_data_provider = trans.app.data_provider_registry.get_data_provider( trans,
original_dataset=dataset,
source='data' )
return {
- "track_type": track_type,
+ "track_type": dataset.datatype.track_type,
"name": track_dict['name'],
"hda_ldda": track_dict.get("hda_ldda", "hda"),
"dataset_id": trans.security.encode_id( dataset.id ),
@@ -666,10 +665,8 @@
Returns track configuration dict for a dataset.
"""
# Get data provider.
- track_type, _ = dataset.datatype.get_track_type()
track_data_provider = trans.app.data_provider_registry.get_data_provider( trans, original_dataset=dataset )
-
if isinstance( dataset, trans.app.model.HistoryDatasetAssociation ):
hda_ldda = "hda"
elif isinstance( dataset, trans.app.model.LibraryDatasetDatasetAssociation ):
@@ -677,7 +674,7 @@
# Get track definition.
return {
- "track_type": track_type,
+ "track_type": dataset.datatype.track_type,
"name": dataset.name,
"hda_ldda": hda_ldda,
"dataset_id": trans.security.encode_id( dataset.id ),
diff -r da3b931de04c93ddae85e4999b6911948fdf0b34 -r 46133ca43f322fe8b042ac0c0b393fe72579cecc lib/galaxy/webapps/galaxy/api/tools.py
--- a/lib/galaxy/webapps/galaxy/api/tools.py
+++ b/lib/galaxy/webapps/galaxy/api/tools.py
@@ -225,7 +225,7 @@
data_provider = data_provider_registry.get_data_provider( trans, original_dataset=input_dataset, source='data' )
if data_provider and not data_provider.converted_dataset:
# Can convert but no converted dataset yet, so return message about why.
- _, data_sources = input_dataset.datatype.get_track_type()
+ data_sources = input_dataset.datatype.data_sources
msg = input_dataset.convert_dataset( trans, data_sources[ 'data' ] )
if msg is not None:
messages_list.append( msg )
@@ -311,7 +311,7 @@
input_dataset = jida.dataset
if input_dataset is None: #optional dataset and dataset wasn't selected
tool_params[ jida.name ] = None
- elif run_on_regions and hasattr( input_dataset.datatype, 'get_track_type' ):
+ elif run_on_regions and 'data' in input_dataset.datatype.data_sources:
# Dataset is indexed and hence a subset can be extracted and used
# as input.
@@ -324,8 +324,7 @@
subset_dataset = subset_dataset_association.subset
else:
# Need to create subset.
- track_type, data_sources = input_dataset.datatype.get_track_type()
- data_source = data_sources[ 'data' ]
+ data_source = input_dataset.datatype.data_sources[ 'data' ]
converted_dataset = input_dataset.get_converted_dataset( trans, data_source )
deps = input_dataset.get_converted_dataset_deps( trans, data_source )
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: Add pileup to interval_index converter.
by commits-noreply@bitbucket.org 16 Apr '13
by commits-noreply@bitbucket.org 16 Apr '13
16 Apr '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/da3b931de04c/
Changeset: da3b931de04c
User: jgoecks
Date: 2013-04-16 23:45:52
Summary: Add pileup to interval_index converter.
Affected #: 4 files
diff -r e0354c9d5497fa9d169df6a7aa44c8132718f92c -r da3b931de04c93ddae85e4999b6911948fdf0b34 datatypes_conf.xml.sample
--- a/datatypes_conf.xml.sample
+++ b/datatypes_conf.xml.sample
@@ -159,7 +159,9 @@
<converter file="encodepeak_to_summary_tree_converter.xml" target_datatype="summary_tree"/></datatype><datatype extension="pdf" type="galaxy.datatypes.images:Pdf" mimetype="application/pdf"/>
- <datatype extension="pileup" type="galaxy.datatypes.tabular:Pileup" display_in_upload="true" />
+ <datatype extension="pileup" type="galaxy.datatypes.tabular:Pileup" display_in_upload="true">
+ <converter file="pileup_to_interval_index_converter.xml" target_datatype="interval_index"/>
+ </datatype><datatype extension="png" type="galaxy.datatypes.images:Png" mimetype="image/png"/><datatype extension="qual" type="galaxy.datatypes.qualityscore:QualityScore" /><datatype extension="qualsolexa" type="galaxy.datatypes.qualityscore:QualityScoreSolexa" display_in_upload="true"/>
diff -r e0354c9d5497fa9d169df6a7aa44c8132718f92c -r da3b931de04c93ddae85e4999b6911948fdf0b34 lib/galaxy/datatypes/converters/pileup_to_interval_index_converter.py
--- /dev/null
+++ b/lib/galaxy/datatypes/converters/pileup_to_interval_index_converter.py
@@ -0,0 +1,39 @@
+#!/usr/bin/env python
+
+"""
+Convert from pileup file to interval index file.
+
+usage: %prog <options> in_file out_file
+"""
+
+from __future__ import division
+
+import sys, fileinput, optparse
+from galaxy import eggs
+import pkg_resources; pkg_resources.require( "bx-python" )
+from galaxy.visualization.tracks.summary import *
+from galaxy.datatypes.util.gff_util import convert_gff_coords_to_bed
+from bx.interval_index_file import Indexes
+
+def main():
+
+ # Read options, args.
+ parser = optparse.OptionParser()
+ (options, args) = parser.parse_args()
+ input_fname, output_fname = args
+
+ # Do conversion.
+ index = Indexes()
+ offset = 0
+ for line in open( input_fname, "r" ):
+ chrom, start = line.split()[ 0:2 ]
+ # Pileup format is 1-based.
+ start = int( start ) - 1
+ index.add( chrom, start, start + 1, offset )
+ offset += len( line )
+
+ index.write( open(output_fname, "w") )
+
+if __name__ == "__main__":
+ main()
+
\ No newline at end of file
diff -r e0354c9d5497fa9d169df6a7aa44c8132718f92c -r da3b931de04c93ddae85e4999b6911948fdf0b34 lib/galaxy/datatypes/converters/pileup_to_interval_index_converter.xml
--- /dev/null
+++ b/lib/galaxy/datatypes/converters/pileup_to_interval_index_converter.xml
@@ -0,0 +1,15 @@
+<tool id="CONVERTER_pileup_to_interval_index_0" name="Convert Pileup to Interval Index" version="1.0.0" hidden="true">
+<!-- <description>__NOT_USED_CURRENTLY_FOR_CONVERTERS__</description> -->
+ <command interpreter="python">pileup_to_interval_index_converter.py $input $output
+ </command>
+ <inputs>
+ <page>
+ <param format="pileup" name="input" type="data" label="Choose Pileup file"/>
+ </page>
+ </inputs>
+ <outputs>
+ <data format="interval_index" name="output"/>
+ </outputs>
+ <help>
+ </help>
+</tool>
diff -r e0354c9d5497fa9d169df6a7aa44c8132718f92c -r da3b931de04c93ddae85e4999b6911948fdf0b34 lib/galaxy/datatypes/tabular.py
--- a/lib/galaxy/datatypes/tabular.py
+++ b/lib/galaxy/datatypes/tabular.py
@@ -527,6 +527,10 @@
return True
except:
return False
+
+ def get_track_type( self ):
+ return self.track_type, { "data": "interval_index" }
+
class ElandMulti( Tabular ):
file_ext = 'elandmulti'
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
4 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/0a3c911778ae/
Changeset: 0a3c911778ae
User: jmchilton
Date: 2013-04-16 04:48:52
Summary: Consolidate logic for determining user's FTP directory.
Affected #: 3 files
diff -r 788cd3d065413b2611d82375a5d0d562775ea529 -r 0a3c911778aebded1d40c5e12b05959a761a0276 lib/galaxy/tools/parameters/basic.py
--- a/lib/galaxy/tools/parameters/basic.py
+++ b/lib/galaxy/tools/parameters/basic.py
@@ -475,7 +475,7 @@
if trans is None or trans.user is None:
user_ftp_dir = None
else:
- user_ftp_dir = os.path.join( trans.app.config.ftp_upload_dir, trans.user.email )
+ user_ftp_dir = trans.user_ftp_dir
return form_builder.FTPFileField( self.name, user_ftp_dir, trans.app.config.ftp_upload_site, value = value )
def from_html( self, value, trans=None, other_values={} ):
try:
diff -r 788cd3d065413b2611d82375a5d0d562775ea529 -r 0a3c911778aebded1d40c5e12b05959a761a0276 lib/galaxy/tools/parameters/grouping.py
--- a/lib/galaxy/tools/parameters/grouping.py
+++ b/lib/galaxy/tools/parameters/grouping.py
@@ -270,7 +270,7 @@
if file_bunch.path and ftp_files is not None:
warnings.append( "All FTP uploaded file selections were ignored." )
elif ftp_files is not None and trans.user is not None: # look for files uploaded via FTP
- user_ftp_dir = os.path.join( trans.app.config.ftp_upload_dir, trans.user.email )
+ user_ftp_dir = trans.user_ftp_dir
for ( dirpath, dirnames, filenames ) in os.walk( user_ftp_dir ):
for filename in filenames:
for ftp_filename in ftp_files:
@@ -318,7 +318,7 @@
ftp_files = []
# TODO: warning to the user (could happen if session has become invalid)
else:
- user_ftp_dir = os.path.join( trans.app.config.ftp_upload_dir, trans.user.email )
+ user_ftp_dir = trans.user_ftp_dir
for ( dirpath, dirnames, filenames ) in os.walk( user_ftp_dir ):
for filename in filenames:
path = relpath( os.path.join( dirpath, filename ), user_ftp_dir )
diff -r 788cd3d065413b2611d82375a5d0d562775ea529 -r 0a3c911778aebded1d40c5e12b05959a761a0276 lib/galaxy/web/framework/__init__.py
--- a/lib/galaxy/web/framework/__init__.py
+++ b/lib/galaxy/web/framework/__init__.py
@@ -958,6 +958,10 @@
def ncbi_builds( self ):
return util.dlnames['ncbi']
+ @property
+ def user_ftp_dir( self ):
+ return os.path.join( self.app.config.ftp_upload_dir, self.user.email )
+
def db_dataset_for( self, dbkey ):
"""
Returns the db_file dataset associated/needed by `dataset`, or `None`.
https://bitbucket.org/galaxy/galaxy-central/commits/0d2a9d0dbd2d/
Changeset: 0d2a9d0dbd2d
User: jmchilton
Date: 2013-04-16 05:00:14
Summary: Implement new property ftp_uplod_dir_identifier which defaults to 'email' but can be changed to 'username' to allow FTP directories based on usernames instead of e-mail addresses. I setup ProFTP + mod_ldap and it does not have the same flexibility the SQL driver has so this change is required at the Galaxy level.
Affected #: 2 files
diff -r 0a3c911778aebded1d40c5e12b05959a761a0276 -r 0d2a9d0dbd2db8a31f570b13acaf0caa9b245b09 lib/galaxy/config.py
--- a/lib/galaxy/config.py
+++ b/lib/galaxy/config.py
@@ -166,6 +166,7 @@
self.enable_whoosh_library_search = string_as_bool( kwargs.get( 'enable_whoosh_library_search', False ) )
self.whoosh_index_dir = resolve_path( kwargs.get( "whoosh_index_dir", "database/whoosh_indexes" ), self.root )
self.ftp_upload_dir = kwargs.get( 'ftp_upload_dir', None )
+ self.ftp_upload_dir_identifier = kwargs.get( 'ftp_uplod_dir_identifier', 'email' ) # attribute on user - email, username, id, etc...
self.ftp_upload_site = kwargs.get( 'ftp_upload_site', None )
self.allow_library_path_paste = kwargs.get( 'allow_library_path_paste', False )
self.disable_library_comptypes = kwargs.get( 'disable_library_comptypes', '' ).lower().split( ',' )
diff -r 0a3c911778aebded1d40c5e12b05959a761a0276 -r 0d2a9d0dbd2db8a31f570b13acaf0caa9b245b09 lib/galaxy/web/framework/__init__.py
--- a/lib/galaxy/web/framework/__init__.py
+++ b/lib/galaxy/web/framework/__init__.py
@@ -960,7 +960,8 @@
@property
def user_ftp_dir( self ):
- return os.path.join( self.app.config.ftp_upload_dir, self.user.email )
+ identifier = self.app.config.ftp_upload_dir_identifier
+ return os.path.join( self.app.config.ftp_upload_dir, getattr(self.user, identifier) )
def db_dataset_for( self, dbkey ):
"""
https://bitbucket.org/galaxy/galaxy-central/commits/8b74c635ca3b/
Changeset: 8b74c635ca3b
User: jmchilton
Date: 2013-04-16 14:44:54
Summary: Fix typo in previous FTP upload commit.
Affected #: 1 file
diff -r 0d2a9d0dbd2db8a31f570b13acaf0caa9b245b09 -r 8b74c635ca3bb266eb0ad2b08aa17836e500add2 lib/galaxy/config.py
--- a/lib/galaxy/config.py
+++ b/lib/galaxy/config.py
@@ -166,7 +166,7 @@
self.enable_whoosh_library_search = string_as_bool( kwargs.get( 'enable_whoosh_library_search', False ) )
self.whoosh_index_dir = resolve_path( kwargs.get( "whoosh_index_dir", "database/whoosh_indexes" ), self.root )
self.ftp_upload_dir = kwargs.get( 'ftp_upload_dir', None )
- self.ftp_upload_dir_identifier = kwargs.get( 'ftp_uplod_dir_identifier', 'email' ) # attribute on user - email, username, id, etc...
+ self.ftp_upload_dir_identifier = kwargs.get( 'ftp_upload_dir_identifier', 'email' ) # attribute on user - email, username, id, etc...
self.ftp_upload_site = kwargs.get( 'ftp_upload_site', None )
self.allow_library_path_paste = kwargs.get( 'allow_library_path_paste', False )
self.disable_library_comptypes = kwargs.get( 'disable_library_comptypes', '' ).lower().split( ',' )
https://bitbucket.org/galaxy/galaxy-central/commits/e0354c9d5497/
Changeset: e0354c9d5497
User: natefoo
Date: 2013-04-16 22:17:33
Summary: Merged in jmchilton/galaxy-central-multi-input-tool-fixes-2 (pull request #157)
Increased flexibility for FTP directory configuration.
Affected #: 4 files
diff -r bbb229927c688213e67ba62998a64526ca948a19 -r e0354c9d5497fa9d169df6a7aa44c8132718f92c lib/galaxy/config.py
--- a/lib/galaxy/config.py
+++ b/lib/galaxy/config.py
@@ -166,6 +166,7 @@
self.enable_whoosh_library_search = string_as_bool( kwargs.get( 'enable_whoosh_library_search', False ) )
self.whoosh_index_dir = resolve_path( kwargs.get( "whoosh_index_dir", "database/whoosh_indexes" ), self.root )
self.ftp_upload_dir = kwargs.get( 'ftp_upload_dir', None )
+ self.ftp_upload_dir_identifier = kwargs.get( 'ftp_upload_dir_identifier', 'email' ) # attribute on user - email, username, id, etc...
self.ftp_upload_site = kwargs.get( 'ftp_upload_site', None )
self.allow_library_path_paste = kwargs.get( 'allow_library_path_paste', False )
self.disable_library_comptypes = kwargs.get( 'disable_library_comptypes', '' ).lower().split( ',' )
diff -r bbb229927c688213e67ba62998a64526ca948a19 -r e0354c9d5497fa9d169df6a7aa44c8132718f92c lib/galaxy/tools/parameters/basic.py
--- a/lib/galaxy/tools/parameters/basic.py
+++ b/lib/galaxy/tools/parameters/basic.py
@@ -475,7 +475,7 @@
if trans is None or trans.user is None:
user_ftp_dir = None
else:
- user_ftp_dir = os.path.join( trans.app.config.ftp_upload_dir, trans.user.email )
+ user_ftp_dir = trans.user_ftp_dir
return form_builder.FTPFileField( self.name, user_ftp_dir, trans.app.config.ftp_upload_site, value = value )
def from_html( self, value, trans=None, other_values={} ):
try:
diff -r bbb229927c688213e67ba62998a64526ca948a19 -r e0354c9d5497fa9d169df6a7aa44c8132718f92c lib/galaxy/tools/parameters/grouping.py
--- a/lib/galaxy/tools/parameters/grouping.py
+++ b/lib/galaxy/tools/parameters/grouping.py
@@ -270,7 +270,7 @@
if file_bunch.path and ftp_files is not None:
warnings.append( "All FTP uploaded file selections were ignored." )
elif ftp_files is not None and trans.user is not None: # look for files uploaded via FTP
- user_ftp_dir = os.path.join( trans.app.config.ftp_upload_dir, trans.user.email )
+ user_ftp_dir = trans.user_ftp_dir
for ( dirpath, dirnames, filenames ) in os.walk( user_ftp_dir ):
for filename in filenames:
for ftp_filename in ftp_files:
@@ -318,7 +318,7 @@
ftp_files = []
# TODO: warning to the user (could happen if session has become invalid)
else:
- user_ftp_dir = os.path.join( trans.app.config.ftp_upload_dir, trans.user.email )
+ user_ftp_dir = trans.user_ftp_dir
for ( dirpath, dirnames, filenames ) in os.walk( user_ftp_dir ):
for filename in filenames:
path = relpath( os.path.join( dirpath, filename ), user_ftp_dir )
diff -r bbb229927c688213e67ba62998a64526ca948a19 -r e0354c9d5497fa9d169df6a7aa44c8132718f92c lib/galaxy/web/framework/__init__.py
--- a/lib/galaxy/web/framework/__init__.py
+++ b/lib/galaxy/web/framework/__init__.py
@@ -960,6 +960,11 @@
def ncbi_builds( self ):
return util.dlnames['ncbi']
+ @property
+ def user_ftp_dir( self ):
+ identifier = self.app.config.ftp_upload_dir_identifier
+ return os.path.join( self.app.config.ftp_upload_dir, getattr(self.user, identifier) )
+
def db_dataset_for( self, dbkey ):
"""
Returns the db_file dataset associated/needed by `dataset`, or `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
commit/galaxy-central: greg: Fixes to make support for recently introduced prior_installation_required atribute for ordering installation of tool shed repositories backward compatible to the 12/20/12 Galaxy release.
by commits-noreply@bitbucket.org 16 Apr '13
by commits-noreply@bitbucket.org 16 Apr '13
16 Apr '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/bbb229927c68/
Changeset: bbb229927c68
User: greg
Date: 2013-04-16 21:55:07
Summary: Fixes to make support for recently introduced prior_installation_required atribute for ordering installation of tool shed repositories backward compatible to the 12/20/12 Galaxy release.
Affected #: 5 files
diff -r cf7a0098c612499d03aafb2f62084ebbcf99e55f -r bbb229927c688213e67ba62998a64526ca948a19 lib/galaxy/webapps/tool_shed/util/container_util.py
--- a/lib/galaxy/webapps/tool_shed/util/container_util.py
+++ b/lib/galaxy/webapps/tool_shed/util/container_util.py
@@ -1031,14 +1031,18 @@
changeset_revision = items[ 3 ]
if len( items ) == 5:
prior_installation_required = asbool( str( items[ 4 ] ) )
+ return toolshed_base_url, repository_name, repository_owner, changeset_revision, prior_installation_required
else:
- # Metadata should have been reset on the repository that contains the definition for this repository_dependency. In the meantime we'll
- # default the prior_installation_required to False.
- prior_installation_required = False
- return toolshed_base_url, repository_name, repository_owner, changeset_revision, prior_installation_required
+ # For backward compatibility to the 12/20/12 Galaxy release we have to return the following, and callers must handle exceptions.
+ return toolshed_base_url, repository_name, repository_owner, changeset_revision
def handle_repository_dependencies_container_entry( trans, repository_dependencies_folder, rd_key, rd_value, folder_id, repository_dependency_id, folder_keys ):
- toolshed, repository_name, repository_owner, changeset_revision, prior_installation_required = get_components_from_key( rd_key )
+ try:
+ toolshed, repository_name, repository_owner, changeset_revision, prior_installation_required = get_components_from_key( rd_key )
+ except ValueError:
+ # For backward compatibility to the 12/20/12 Galaxy release, default prior_installation_required to False.
+ toolshed, repository_name, repository_owner, changeset_revision = get_components_from_key( rd_key )
+ prior_installation_required = False
folder = get_folder( repository_dependencies_folder, rd_key )
label = generate_repository_dependencies_folder_label_from_key( repository_name,
repository_owner,
@@ -1114,7 +1118,12 @@
return False
def key_is_current_repositorys_key( repository_name, repository_owner, changeset_revision, prior_installation_required, key ):
- toolshed_base_url, key_name, key_owner, key_changeset_revision, key_prior_installation_required = get_components_from_key( key )
+ try:
+ toolshed_base_url, key_name, key_owner, key_changeset_revision, key_prior_installation_required = get_components_from_key( key )
+ except ValueError:
+ # For backward compatibility to the 12/20/12 Galaxy release, default key_prior_installation_required to False.
+ toolshed_base_url, key_name, key_owner, key_changeset_revision = get_components_from_key( key )
+ key_prior_installation_required = False
return repository_name == key_name and \
repository_owner == key_owner and \
changeset_revision == key_changeset_revision and \
diff -r cf7a0098c612499d03aafb2f62084ebbcf99e55f -r bbb229927c688213e67ba62998a64526ca948a19 lib/tool_shed/galaxy_install/repository_util.py
--- a/lib/tool_shed/galaxy_install/repository_util.py
+++ b/lib/tool_shed/galaxy_install/repository_util.py
@@ -478,8 +478,12 @@
old_container_repository_dependencies_folder.id = folder_id
folder_id += 1
# Generate the label by retrieving the repository name.
- toolshed, name, owner, changeset_revision, prior_installation_required = \
- container_util.get_components_from_key( old_container_repository_dependencies_folder.key )
+ try:
+ toolshed, name, owner, changeset_revision, prior_installation_required = \
+ container_util.get_components_from_key( old_container_repository_dependencies_folder.key )
+ except ValueError:
+ # For backward compatibility to the 12/20/12 Galaxy release.
+ toolshed, name, owner, changeset_revision = container_util.get_components_from_key( old_container_repository_dependencies_folder.key )
old_container_repository_dependencies_folder.label = str( name )
repository_dependencies_folder.folders.append( old_container_repository_dependencies_folder )
# Merge tool_dependencies.
diff -r cf7a0098c612499d03aafb2f62084ebbcf99e55f -r bbb229927c688213e67ba62998a64526ca948a19 lib/tool_shed/tool_shed_registry.py
--- a/lib/tool_shed/tool_shed_registry.py
+++ b/lib/tool_shed/tool_shed_registry.py
@@ -42,9 +42,8 @@
Following more what galaxy.demo_sequencer.controllers.common does might be more appropriate at some stage...
"""
- log.debug( 'Looking for url %s' % url )
for shed_name, shed_url in self.tool_sheds.items():
if shed_url.find( url ) >= 0:
- log.debug( 'Found %s -> %s' % ( shed_name, shed_url ) )
return self.tool_sheds_auth[ shed_name ]
+ log.debug( "Invalid url '%s' received by tool shed registry's password_manager_for_url method." % str( url ) )
return None
diff -r cf7a0098c612499d03aafb2f62084ebbcf99e55f -r bbb229927c688213e67ba62998a64526ca948a19 lib/tool_shed/util/common_install_util.py
--- a/lib/tool_shed/util/common_install_util.py
+++ b/lib/tool_shed/util/common_install_util.py
@@ -263,8 +263,13 @@
for key, val in repository_dependencies.items():
if key in [ 'root_key', 'description' ]:
continue
- toolshed, name, owner, changeset_revision, prior_installation_required = container_util.get_components_from_key( key )
- components_list = [ toolshed, name, owner, changeset_revision, prior_installation_required ]
+ try:
+ toolshed, name, owner, changeset_revision, prior_installation_required = container_util.get_components_from_key( key )
+ components_list = [ toolshed, name, owner, changeset_revision, prior_installation_required ]
+ except ValueError:
+ # For backward compatibility to the 12/20/12 Galaxy release, default prior_installation_required to False in the caller.
+ toolshed, name, owner, changeset_revision = container_util.get_components_from_key( key )
+ components_list = [ toolshed, name, owner, changeset_revision ]
if components_list not in required_repository_tups:
required_repository_tups.append( components_list )
for components_list in val:
@@ -279,7 +284,7 @@
encoded_required_repository_tups.append( encoding_util.encoding_sep.join( required_repository_tup ) )
encoded_required_repository_str = encoding_util.encoding_sep2.join( encoded_required_repository_tups )
encoded_required_repository_str = encoding_util.tool_shed_encode( encoded_required_repository_str )
- url = suc.url_join( tool_shed_url, '/repository/get_required_repo_info_dict?encoded_str=%s' % encoded_required_repository_str )
+ url = suc.url_join( tool_shed_url, '/repository/get_required_repo_info_dict?encoded_str=%s' % encoded_required_repository_str )
text = common_util.tool_shed_get( trans.app, tool_shed_url, url )
if text:
required_repo_info_dict = json.from_json_string( text )
diff -r cf7a0098c612499d03aafb2f62084ebbcf99e55f -r bbb229927c688213e67ba62998a64526ca948a19 lib/tool_shed/util/repository_dependency_util.py
--- a/lib/tool_shed/util/repository_dependency_util.py
+++ b/lib/tool_shed/util/repository_dependency_util.py
@@ -33,8 +33,12 @@
if key in [ 'root_key', 'description' ]:
continue
dependent_repository = None
- dependent_toolshed, dependent_name, dependent_owner, dependent_changeset_revision, dependent_prior_installation_required = \
- container_util.get_components_from_key( key )
+ try:
+ dependent_toolshed, dependent_name, dependent_owner, dependent_changeset_revision, dependent_prior_installation_required = \
+ container_util.get_components_from_key( key )
+ except ValueError:
+ # For backward compatibility to the 12/20/12 Galaxy release.
+ dependent_toolshed, dependent_name, dependent_owner, dependent_changeset_revision = container_util.get_components_from_key( key )
for tsr in tool_shed_repositories:
# Get the the tool_shed_repository defined by name, owner and changeset_revision. This is the repository that will be
# dependent upon each of the tool shed repositories contained in val.
@@ -350,13 +354,22 @@
# We have the updated changset revision.
updated_key_rd_dicts.append( new_key_rd_dict )
else:
- toolshed, repository_name, repository_owner, repository_changeset_revision, prior_installation_required = \
- container_util.get_components_from_key( key )
+ try:
+ toolshed, repository_name, repository_owner, repository_changeset_revision, prior_installation_required = \
+ container_util.get_components_from_key( key )
+ except ValueError:
+ # For backward compatibility to the 12/20/12 Galaxy release.
+ toolshed, repository_name, repository_owner, repository_changeset_revision = container_util.get_components_from_key( key )
message = "The revision %s defined for repository %s owned by %s is invalid, so repository dependencies defined for repository %s will be ignored." % \
( str( rd_changeset_revision ), str( rd_name ), str( rd_owner ), str( repository_name ) )
log.debug( message )
else:
- toolshed, repository_name, repository_owner, repository_changeset_revision, prior_installation_required = container_util.get_components_from_key( key )
+ try:
+ toolshed, repository_name, repository_owner, repository_changeset_revision, prior_installation_required = \
+ container_util.get_components_from_key( key )
+ except ValueError:
+ # For backward compatibility to the 12/20/12 Galaxy release.
+ toolshed, repository_name, repository_owner, repository_changeset_revision = container_util.get_components_from_key( key )
message = "The revision %s defined for repository %s owned by %s is invalid, so repository dependencies defined for repository %s will be ignored." % \
( str( rd_changeset_revision ), str( rd_name ), str( rd_owner ), str( repository_name ) )
log.debug( message )
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: Add a track_type attribute to data types and use instead of burying track type in get_track_type function.
by commits-noreply@bitbucket.org 16 Apr '13
by commits-noreply@bitbucket.org 16 Apr '13
16 Apr '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/cf7a0098c612/
Changeset: cf7a0098c612
User: jgoecks
Date: 2013-04-16 21:32:46
Summary: Add a track_type attribute to data types and use instead of burying track type in get_track_type function.
Affected #: 5 files
diff -r 270ef5007ae876bfbaa3110d6666432751152323 -r cf7a0098c612499d03aafb2f62084ebbcf99e55f lib/galaxy/datatypes/binary.py
--- a/lib/galaxy/datatypes/binary.py
+++ b/lib/galaxy/datatypes/binary.py
@@ -94,6 +94,8 @@
class Bam( Binary ):
"""Class describing a BAM binary file"""
file_ext = "bam"
+ track_type = "ReadTrack"
+
MetadataElement( name="bam_index", desc="BAM Index File", param=metadata.FileParameter, file_ext="bai", readonly=True, no_value=None, visible=False, optional=True )
def _get_samtools_version( self ):
@@ -245,7 +247,7 @@
except:
return "Binary bam alignments file (%s)" % ( data.nice_size( dataset.get_size() ) )
def get_track_type( self ):
- return "ReadTrack", { "data": "bai", "index": [ "bigwig", "summary_tree" ] }
+ return self.track_type, { "data": "bai", "index": [ "bigwig", "summary_tree" ] }
Binary.register_sniffable_binary_format("bam", "bam", Bam)
@@ -324,6 +326,8 @@
The supplemental info in the paper has the binary details:
http://bioinformatics.oxfordjournals.org/cgi/content/abstract/btq351v1
"""
+ track_type = "LineTrack"
+
def __init__( self, **kwd ):
Binary.__init__( self, **kwd )
self._magic = 0x888FFC26
@@ -349,18 +353,19 @@
except:
return "Binary UCSC %s file (%s)" % ( self._name, data.nice_size( dataset.get_size() ) )
def get_track_type( self ):
- return "LineTrack", {"data_standalone": "bigwig"}
+ return self.track_type, {"data_standalone": "bigwig"}
Binary.register_sniffable_binary_format("bigwig", "bigwig", BigWig)
class BigBed(BigWig):
"""BigBed support from UCSC."""
+
def __init__( self, **kwd ):
Binary.__init__( self, **kwd )
self._magic = 0x8789F2EB
self._name = "BigBed"
def get_track_type( self ):
- return "LineTrack", {"data_standalone": "bigbed"}
+ return self.track_type, {"data_standalone": "bigbed"}
Binary.register_sniffable_binary_format("bigbed", "bigbed", BigBed)
diff -r 270ef5007ae876bfbaa3110d6666432751152323 -r cf7a0098c612499d03aafb2f62084ebbcf99e55f lib/galaxy/datatypes/data.py
--- a/lib/galaxy/datatypes/data.py
+++ b/lib/galaxy/datatypes/data.py
@@ -97,6 +97,9 @@
#A per datatype setting (inherited): max file size (in bytes) for setting optional metadata
_max_optional_metadata_filesize = None
+ # Trackster track type.
+ track_type = None
+
def __init__(self, **kwd):
"""Initialize the datatype"""
object.__init__(self, **kwd)
@@ -561,7 +564,7 @@
Returns a list of visualizations for datatype.
"""
- if hasattr( self, 'get_track_type' ):
+ if self.track_type:
return [ 'trackster', 'circster' ]
return []
diff -r 270ef5007ae876bfbaa3110d6666432751152323 -r cf7a0098c612499d03aafb2f62084ebbcf99e55f lib/galaxy/datatypes/interval.py
--- a/lib/galaxy/datatypes/interval.py
+++ b/lib/galaxy/datatypes/interval.py
@@ -46,6 +46,7 @@
"""Tab delimited data containing interval information"""
file_ext = "interval"
line_class = "region"
+ track_type = "FeatureTrack"
"""Add metadata elements"""
MetadataElement( name="chromCol", default=1, desc="Chrom column", param=metadata.ColumnParameter )
@@ -330,15 +331,16 @@
return None
def get_track_type( self ):
- return "FeatureTrack", {"data": "tabix", "index": "summary_tree"}
+ return self.track_type, {"data": "tabix", "index": "summary_tree"}
class BedGraph( Interval ):
"""Tab delimited chrom/start/end/datavalue dataset"""
file_ext = "bedgraph"
+ track_type = "LineTrack"
def get_track_type( self ):
- return "LineTrack", { "data": "bigwig", "index": "bigwig" }
+ return self.track_type, { "data": "bigwig", "index": "bigwig" }
def as_ucsc_display_file( self, dataset, **kwd ):
"""
@@ -512,7 +514,7 @@
except: return False
def get_track_type( self ):
- return "FeatureTrack", {"data": "tabix", "index": "summary_tree", "feature_search": "fli"}
+ return self.track_type, {"data": "tabix", "index": "summary_tree", "feature_search": "fli"}
class BedStrict( Bed ):
"""Tab delimited data in strict BED format - no non-standard columns allowed"""
@@ -785,7 +787,7 @@
return False
def get_track_type( self ):
- return "FeatureTrack", {"data": "interval_index", "index": "summary_tree", "feature_search": "fli"}
+ return self.track_type, {"data": "interval_index", "index": "summary_tree", "feature_search": "fli"}
class Gff3( Gff ):
@@ -966,6 +968,7 @@
class Wiggle( Tabular, _RemoteCallMixin ):
"""Tab delimited data in wiggle format"""
file_ext = "wig"
+ track_type = "LineTrack"
MetadataElement( name="columns", default=3, desc="Number of columns", readonly=True, visible=False )
@@ -1148,7 +1151,7 @@
return resolution
def get_track_type( self ):
- return "LineTrack", { "data": "bigwig", "index": "bigwig" }
+ return self.track_type, { "data": "bigwig", "index": "bigwig" }
class CustomTrack ( Tabular ):
"""UCSC CustomTrack"""
@@ -1304,7 +1307,7 @@
return False
def get_track_type( self ):
- return "FeatureTrack", {"data": "tabix", "index": "summary_tree"}
+ return self.track_type, {"data": "tabix", "index": "summary_tree"}
class ChromatinInteractions( Interval ):
'''
@@ -1312,6 +1315,7 @@
'''
file_ext = "chrint"
+ track_type = "DiagonalHeatmapTrack"
column_names = [ 'Chrom1', 'Start1', 'End1', 'Chrom2', 'Start2', 'End2', 'Value' ]
@@ -1330,7 +1334,7 @@
return False
def get_track_type( self ):
- return "DiagonalHeatmapTrack", {"data": "tabix", "index": "summary_tree"}
+ return self.track_type, {"data": "tabix", "index": "summary_tree"}
diff -r 270ef5007ae876bfbaa3110d6666432751152323 -r cf7a0098c612499d03aafb2f62084ebbcf99e55f lib/galaxy/datatypes/registry.py
--- a/lib/galaxy/datatypes/registry.py
+++ b/lib/galaxy/datatypes/registry.py
@@ -163,7 +163,7 @@
# Use default mime type as per datatype spec
mimetype = self.datatypes_by_extension[ extension ].get_mime()
self.mimetypes_by_extension[ extension ] = mimetype
- if hasattr( datatype_class, "get_track_type" ):
+ if datatype_class.track_type:
self.available_tracks.append( extension )
if display_in_upload:
self.upload_file_formats.append( extension )
diff -r 270ef5007ae876bfbaa3110d6666432751152323 -r cf7a0098c612499d03aafb2f62084ebbcf99e55f lib/galaxy/datatypes/tabular.py
--- a/lib/galaxy/datatypes/tabular.py
+++ b/lib/galaxy/datatypes/tabular.py
@@ -358,6 +358,8 @@
class Sam( Tabular ):
file_ext = 'sam'
+ track_type = "ReadTrack"
+
def __init__(self, **kwd):
"""Initialize taxonomy datatype"""
Tabular.__init__( self, **kwd )
@@ -468,7 +470,7 @@
merge = staticmethod(merge)
def get_track_type( self ):
- return "ReadTrack", {"data": "bam", "index": "summary_tree"}
+ return self.track_type, {"data": "bam", "index": "summary_tree"}
class Pileup( Tabular ):
"""Tab delimited data in pileup (6- or 10-column) format"""
@@ -525,8 +527,7 @@
return True
except:
return False
-
-
+
class ElandMulti( Tabular ):
file_ext = 'elandmulti'
@@ -535,6 +536,7 @@
class Vcf( Tabular ):
""" Variant Call Format for describing SNPs and other simple genome variations. """
+ track_type = "VariantTrack"
file_ext = 'vcf'
column_names = [ 'Chrom', 'Pos', 'ID', 'Ref', 'Alt', 'Qual', 'Filter', 'Info', 'Format', 'data' ]
@@ -552,7 +554,7 @@
return Tabular.make_html_table( self, dataset, column_names=self.column_names )
def get_track_type( self ):
- return "VariantTrack", { "data": "tabix", "index": "summary_tree" }
+ return self.track_type, { "data": "tabix", "index": "summary_tree" }
class Eland( Tabular ):
"""Support for the export.txt.gz file used by Illumina's ELANDv2e aligner"""
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: inithello: Added info_only option to install and test script.
by commits-noreply@bitbucket.org 16 Apr '13
by commits-noreply@bitbucket.org 16 Apr '13
16 Apr '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/270ef5007ae8/
Changeset: 270ef5007ae8
User: inithello
Date: 2013-04-16 21:28:23
Summary: Added info_only option to install and test script.
Affected #: 1 file
diff -r 95c90c1d90294032a0db5f3cb9312a967ac00e49 -r 270ef5007ae876bfbaa3110d6666432751152323 test/install_and_test_tool_shed_repositories/functional_tests.py
--- a/test/install_and_test_tool_shed_repositories/functional_tests.py
+++ b/test/install_and_test_tool_shed_repositories/functional_tests.py
@@ -265,9 +265,8 @@
tool_id = parts[ -2 ]
return tool_id, tool_version
-def get_tool_test_errors_from_api( tool_shed_url, metadata_dict ):
- params = dict()
- api_path = metadata_dict[ 'url' ].split( '/' )
+def get_tool_test_errors_from_api( tool_shed_url, metadata_revision_id ):
+ api_path = [ 'api', 'repository_revisions', metadata_revision_id ]
api_url = get_api_url( base=tool_shed_url, parts=api_path )
repository_metadata = json_from_url( api_url )
if repository_metadata[ 'tool_test_errors' ] is None:
@@ -292,7 +291,10 @@
params[ 'tools_functionally_correct' ] = 'false'
params[ 'do_not_test' ] = 'false'
params[ 'tool_test_errors' ] = test_results_dict
- return update( tool_shed_api_key, '%s' % ( url_join( galaxy_tool_shed_url, 'api', 'repository_revisions', metadata_id ) ), params, return_formatted=False )
+ if '-info_only' in sys.argv:
+ return {}
+ else:
+ return update( tool_shed_api_key, '%s' % ( url_join( galaxy_tool_shed_url, 'api', 'repository_revisions', metadata_id ) ), params, return_formatted=False )
def run_tests( test_config ):
loader = nose.loader.TestLoader( config=test_config )
@@ -332,8 +334,6 @@
galaxy_test_file_dir = os.environ.get( 'GALAXY_INSTALL_TEST_FILE_DIR', default_galaxy_test_file_dir )
if not os.path.isabs( galaxy_test_file_dir ):
galaxy_test_file_dir = os.path.abspath( galaxy_test_file_dir )
- # Set up the tool dependency path for the Galaxy instance.
- tool_dependency_dir = os.environ.get( 'GALAXY_INSTALL_TEST_TOOL_DEPENDENCY_DIR', None )
use_distributed_object_store = os.environ.get( 'GALAXY_INSTALL_TEST_USE_DISTRIBUTED_OBJECT_STORE', False )
if not os.path.isdir( galaxy_test_tmp_dir ):
os.mkdir( galaxy_test_tmp_dir )
@@ -363,9 +363,12 @@
new_repos_path = tempfile.mkdtemp( dir=galaxy_test_tmp_dir )
galaxy_tempfiles = tempfile.mkdtemp( dir=galaxy_test_tmp_dir )
galaxy_shed_tool_path = tempfile.mkdtemp( dir=galaxy_test_tmp_dir, prefix='shed_tools' )
- galaxy_migrated_tool_path = tempfile.mkdtemp( dir=galaxy_test_tmp_dir )
- galaxy_tool_dependency_dir = tempfile.mkdtemp( dir=galaxy_test_tmp_dir )
- os.environ[ 'GALAXY_INSTALL_TEST_TOOL_DEPENDENCY_DIR' ] = galaxy_tool_dependency_dir
+ galaxy_migrated_tool_path = tempfile.mkdtemp( dir=galaxy_test_tmp_dir )
+ # Set up the tool dependency path for the Galaxy instance.
+ tool_dependency_dir = os.environ.get( 'GALAXY_INSTALL_TEST_TOOL_DEPENDENCY_DIR', None )
+ if tool_dependency_dir is None:
+ tool_dependency_dir = tempfile.mkdtemp( dir=galaxy_test_tmp_dir )
+ os.environ[ 'GALAXY_INSTALL_TEST_TOOL_DEPENDENCY_DIR' ] = tool_dependency_dir
if 'GALAXY_INSTALL_TEST_DBURI' in os.environ:
database_connection = os.environ[ 'GALAXY_INSTALL_TEST_DBURI' ]
else:
@@ -422,7 +425,7 @@
tool_config_file = [ galaxy_tool_conf_file, galaxy_shed_tool_conf_file ],
tool_data_path = tool_data_path,
tool_data_table_config_path = galaxy_tool_data_table_conf_file,
- tool_dependency_dir = galaxy_tool_dependency_dir,
+ tool_dependency_dir = tool_dependency_dir,
tool_path = tool_path,
tool_parse_help = False,
tool_sheds_config_file = galaxy_tool_sheds_conf_file,
@@ -625,7 +628,7 @@
# },
# ]
# }
- repository_status = get_tool_test_errors_from_api( galaxy_tool_shed_url, repository_info_dict )
+ repository_status = get_tool_test_errors_from_api( galaxy_tool_shed_url, metadata_revision_id )
if 'test_environment' not in repository_status:
repository_status[ 'test_environment' ] = {}
test_environment = get_test_environment( repository_status[ 'test_environment' ] )
@@ -775,6 +778,8 @@
print "####################################################################################"
print "# %s - repository installation and testing script completed." % now
print "# Repository revisions tested: %d" % repositories_tested
+ if '-info_only' in sys.argv:
+ print "# -info_only set, not updating the tool shed."
if repositories_tested > 0:
if repositories_passed:
print '# ----------------------------------------------------------------------------------'
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: Rewrite RawVcfDataProvider for completeness and efficiency.
by commits-noreply@bitbucket.org 16 Apr '13
by commits-noreply@bitbucket.org 16 Apr '13
16 Apr '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/95c90c1d9029/
Changeset: 95c90c1d9029
User: jgoecks
Date: 2013-04-16 20:36:27
Summary: Rewrite RawVcfDataProvider for completeness and efficiency.
Affected #: 1 file
diff -r 6e91867769eab9e97353cd0e6363393c8077aadc -r 95c90c1d90294032a0db5f3cb9312a967ac00e49 lib/galaxy/visualization/data_providers/genome.py
--- a/lib/galaxy/visualization/data_providers/genome.py
+++ b/lib/galaxy/visualization/data_providers/genome.py
@@ -759,29 +759,41 @@
"""
def get_iterator( self, chrom, start, end, **kwargs ):
- # Read first line in order to match chrom naming format.
- line = source.readline()
- dataset_chrom = line.split()[0]
- if not _chrom_naming_matches( chrom, dataset_chrom ):
- chrom = _convert_between_ucsc_and_ensemble_naming( chrom )
- # Undo read.
- source.seek( 0 )
+ source = open( self.original_dataset.file_name )
+
+ # Skip comments.
+ pos = 0
+ line = None
+ for line in source:
+ if not line.startswith("#"):
+ break
+ else:
+ pos = source.tell()
+
+ # Match chrom naming format.
+ if line:
+ dataset_chrom = line.split()[0]
+ if not _chrom_naming_matches( chrom, dataset_chrom ):
+ chrom = _convert_between_ucsc_and_ensemble_naming( chrom )
+
+ def line_in_region( vcf_line, chrom, start, end ):
+ """ Returns true if line is in region. """
+ variant_chrom, variant_start = vcf_line.split()[ 0:2 ]
+ # VCF format is 1-based.
+ variant_start = int( variant_start ) - 1
+ return variant_chrom == chrom and variant_start >= start and variant_start <= end
def line_filter_iter():
- for line in open( self.original_dataset.file_name ):
- if line.startswith("#"):
- continue
- variant = line.split()
- variant_chrom, variant_start, id, ref, alts = variant[ 0:5 ]
- variant_start = int( variant_start )
- longest_alt = -1
- for alt in alts:
- if len( alt ) > longest_alt:
- longest_alt = len( alt )
- variant_end = variant_start + abs( len( ref ) - longest_alt )
- if variant_chrom != chrom or variant_start > end or variant_end < start:
- continue
+ """ Yields lines in source that are in region chrom:start-end """
+ # Yield data line read above.
+ if line_in_region( line, chrom, start, end ):
yield line
+
+ # Search for and yield other data lines.
+ for data_line in source:
+ if line_in_region( data_line, chrom, start, end ):
+ print chrom, start, end, ">>>", data_line,
+ yield data_line
return line_filter_iter()
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: Import fixes, code cleanup and white space changes to follow Galaxy dev team standards related to pull request # 155.
by commits-noreply@bitbucket.org 16 Apr '13
by commits-noreply@bitbucket.org 16 Apr '13
16 Apr '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/6e91867769ea/
Changeset: 6e91867769ea
User: greg
Date: 2013-04-16 20:27:09
Summary: Import fixes, code cleanup and white space changes to follow Galaxy dev team standards related to pull request # 155.
Affected #: 14 files
diff -r 494837c4fe5b6554a4c8cb1e93547ec45413f2df -r 6e91867769eab9e97353cd0e6363393c8077aadc lib/galaxy/webapps/galaxy/api/tool_shed_repositories.py
--- a/lib/galaxy/webapps/galaxy/api/tool_shed_repositories.py
+++ b/lib/galaxy/webapps/galaxy/api/tool_shed_repositories.py
@@ -1,5 +1,4 @@
import logging
-import urllib2
from paste.httpexceptions import HTTPBadRequest, HTTPForbidden
diff -r 494837c4fe5b6554a4c8cb1e93547ec45413f2df -r 6e91867769eab9e97353cd0e6363393c8077aadc lib/galaxy/webapps/galaxy/controllers/admin.py
--- a/lib/galaxy/webapps/galaxy/controllers/admin.py
+++ b/lib/galaxy/webapps/galaxy/controllers/admin.py
@@ -712,7 +712,7 @@
tool_dependencies_dict = {}
repository_name = elem.get( 'name' )
changeset_revision = elem.get( 'changeset_revision' )
- url = '%s/repository/get_tool_dependencies?name=%s&owner=devteam&changeset_revision=%s&from_install_manager=True' % \
+ url = '%s/repository/get_tool_dependencies?name=%s&owner=devteam&changeset_revision=%s&from_install_manager=True' % \
( tool_shed_url, repository_name, changeset_revision )
text = common_util.tool_shed_get( trans.app, tool_shed_url, url )
if text:
diff -r 494837c4fe5b6554a4c8cb1e93547ec45413f2df -r 6e91867769eab9e97353cd0e6363393c8077aadc lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py
--- a/lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py
+++ b/lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py
@@ -1010,7 +1010,11 @@
tool_shed_repository.installed_changeset_revision,
tool_shed_repository.owner,
tool_shed_repository.dist_to_shed )
- ctx_rev = suc.get_ctx_rev( trans.app, tool_shed_url, tool_shed_repository.name, tool_shed_repository.owner, tool_shed_repository.installed_changeset_revision )
+ ctx_rev = suc.get_ctx_rev( trans.app,
+ tool_shed_url,
+ tool_shed_repository.name,
+ tool_shed_repository.owner,
+ tool_shed_repository.installed_changeset_revision )
repo_info_dicts = []
repo_info_dict = kwd.get( 'repo_info_dict', None )
if repo_info_dict:
@@ -1372,7 +1376,7 @@
message ++ "from the installed repository's <b>Repository Actions</b> menu. "
status = 'error'
shed_tool_conf, tool_path, relative_install_dir = suc.get_tool_panel_config_tool_path_install_dir( trans.app, repository )
- repo_files_dir = os.path.abspath( os.path.join( relative_install_dir, repository.name ) )
+ repo_files_dir = os.path.abspath( os.path.join( relative_install_dir, repository.name ) )
containers_dict = metadata_util.populate_containers_dict_from_repository_metadata( trans=trans,
tool_shed_url=tool_shed_url,
tool_path=tool_path,
diff -r 494837c4fe5b6554a4c8cb1e93547ec45413f2df -r 6e91867769eab9e97353cd0e6363393c8077aadc lib/galaxy/webapps/galaxy/controllers/workflow.py
--- a/lib/galaxy/webapps/galaxy/controllers/workflow.py
+++ b/lib/galaxy/webapps/galaxy/controllers/workflow.py
@@ -12,7 +12,8 @@
import urllib2
from sqlalchemy import and_
-from tool_shed.util import encoding_util, common_util
+from tool_shed.util import common_util
+from tool_shed.util import encoding_util
from galaxy import model
from galaxy import util
@@ -1070,7 +1071,7 @@
import_button = True
if tool_shed_url and not import_button:
# Use urllib (send another request to the tool shed) to retrieve the workflow.
- workflow_url = '%s/workflow/import_workflow?repository_metadata_id=%s&workflow_name=%s&open_for_url=true' % \
+ workflow_url = '%s/workflow/import_workflow?repository_metadata_id=%s&workflow_name=%s&open_for_url=true' % \
( tool_shed_url, repository_metadata_id, encoding_util.tool_shed_encode( workflow_name ) )
workflow_text = common_util.tool_shed_get( trans.app, tool_shed_url, workflow_url )
import_button = True
diff -r 494837c4fe5b6554a4c8cb1e93547ec45413f2df -r 6e91867769eab9e97353cd0e6363393c8077aadc lib/tool_shed/galaxy_install/install_manager.py
--- a/lib/tool_shed/galaxy_install/install_manager.py
+++ b/lib/tool_shed/galaxy_install/install_manager.py
@@ -2,15 +2,24 @@
Manage automatic installation of tools configured in the xxx.xml files in ~/scripts/migrate_tools (e.g., 0002_tools.xml).
All of the tools were at some point included in the Galaxy distribution, but are now hosted in the main Galaxy tool shed.
"""
-import os, tempfile
+import os
+import tempfile
from galaxy import util
from galaxy.tools import ToolSection
-from galaxy.util.json import from_json_string, to_json_string
+from galaxy.util.json import from_json_string
+from galaxy.util.json import to_json_string
import tool_shed.util.shed_util_common as suc
-from tool_shed.util import common_install_util, common_util, datatype_util, metadata_util, tool_dependency_util, tool_util
+from tool_shed.util import common_install_util
+from tool_shed.util import common_util
+from tool_shed.util import datatype_util
+from tool_shed.util import metadata_util
+from tool_shed.util import tool_dependency_util
+from tool_shed.util import tool_util
from galaxy.util.odict import odict
+
class InstallManager( object ):
+
def __init__( self, app, latest_migration_script_number, tool_shed_install_config, migrated_tools_config, install_dependencies ):
"""
Check tool settings in tool_shed_install_config and install all repositories that are not already installed. The tool
@@ -72,6 +81,7 @@
message = "\nThe main Galaxy tool shed is not currently available, so skipped migration stage %s.\n" % str( latest_migration_script_number )
message += "Try again later.\n"
print message
+
def get_guid( self, repository_clone_url, relative_install_dir, tool_config ):
if self.shed_config_dict.get( 'tool_path' ):
relative_install_dir = os.path.join( self.shed_config_dict['tool_path'], relative_install_dir )
@@ -89,6 +99,7 @@
full_path = str( os.path.abspath( os.path.join( root, name ) ) )
tool = self.toolbox.load_tool( full_path )
return suc.generate_tool_guid( repository_clone_url, tool )
+
def get_proprietary_tool_panel_elems( self, latest_tool_migration_script_number ):
# Parse each config in self.proprietary_tool_confs (the default is tool_conf.xml) and generate a list of Elements that are
# either ToolSection elements or Tool elements. These will be used to generate new entries in the migrated_tools_conf.xml
@@ -128,6 +139,7 @@
if elem not in tool_panel_elems:
tool_panel_elems.append( elem )
return tool_panel_elems
+
def get_containing_tool_sections( self, tool_config ):
"""
If tool_config is defined somewhere in self.proprietary_tool_panel_elems, return True and a list of ToolSections in which the
@@ -158,6 +170,7 @@
if not is_displayed:
is_displayed = True
return is_displayed, tool_sections
+
def handle_repository_contents( self, tool_shed_repository, repository_clone_url, relative_install_dir, repository_elem, install_dependencies ):
"""Generate the metadata for the installed tool shed repository, among other things."""
tool_panel_dict_for_display = odict()
@@ -268,6 +281,7 @@
shutil.rmtree( work_dir )
except:
pass
+
def install_repository( self, repository_elem, install_dependencies ):
# Install a single repository, loading contained tools into the tool panel.
name = repository_elem.get( 'name' )
@@ -310,7 +324,7 @@
tool_shed_repository,
self.app.model.ToolShedRepository.installation_status.SETTING_TOOL_VERSIONS )
# Get the tool_versions from the tool shed for each tool in the installed change set.
- url = '%s/repository/get_tool_versions?name=%s&owner=%s&changeset_revision=%s' % \
+ url = '%s/repository/get_tool_versions?name=%s&owner=%s&changeset_revision=%s' % \
( tool_shed_url, tool_shed_repository.name, self.repository_owner, installed_changeset_revision )
text = common_util.tool_shed_get( self.app, tool_shed_url, url )
if text:
@@ -346,9 +360,11 @@
self.app.sa_session.add( tool_version_association )
self.app.sa_session.flush()
suc.update_tool_shed_repository_status( self.app, tool_shed_repository, self.app.model.ToolShedRepository.installation_status.INSTALLED )
+
@property
def non_shed_tool_panel_configs( self ):
return common_util.get_non_shed_tool_panel_configs( self.app )
+
def __isinstalled( self, clone_dir ):
full_path = os.path.abspath( clone_dir )
if os.path.exists( full_path ):
diff -r 494837c4fe5b6554a4c8cb1e93547ec45413f2df -r 6e91867769eab9e97353cd0e6363393c8077aadc lib/tool_shed/galaxy_install/tool_dependencies/common_util.py
--- a/lib/tool_shed/galaxy_install/tool_dependencies/common_util.py
+++ b/lib/tool_shed/galaxy_install/tool_dependencies/common_util.py
@@ -28,6 +28,7 @@
# </environment_variable>
return dict( name=env_var_name, action=env_var_action, value=elem.text)
return None
+
def create_or_update_env_shell_file( install_dir, env_var_dict ):
env_var_name = env_var_dict[ 'name' ]
env_var_action = env_var_dict[ 'action' ]
@@ -50,6 +51,7 @@
env_shell_file_path,
env_shell_file_path )
return cmd
+
def extract_tar( file_name, file_path ):
if isgzip( file_name ) or isbz2( file_name ):
# Open for reading with transparent compression.
@@ -58,6 +60,7 @@
tar = tarfile.open( file_name )
tar.extractall( path=file_path )
tar.close()
+
def extract_zip( archive_path, extraction_path ):
# TODO: change this method to use zipfile.Zipfile.extractall() when we stop supporting Python 2.5.
if not zipfile_ok( archive_path ):
@@ -72,17 +75,23 @@
file( uncompressed_path, 'wb' ).write( zip_archive.read( name ) )
zip_archive.close()
return True
+
def isbz2( file_path ):
return checkers.is_bz2( file_path )
+
def isgzip( file_path ):
return checkers.is_gzip( file_path )
+
def istar( file_path ):
return tarfile.is_tarfile( file_path )
+
def iszip( file_path ):
return checkers.check_zip( file_path )
+
def make_directory( full_path ):
if not os.path.exists( full_path ):
os.makedirs( full_path )
+
def move_directory_files( current_dir, source_dir, destination_dir ):
source_directory = os.path.abspath( os.path.join( current_dir, source_dir ) )
destination_directory = os.path.join( destination_dir )
@@ -92,12 +101,14 @@
source_file = os.path.join( source_directory, file_name )
destination_file = os.path.join( destination_directory, file_name )
shutil.move( source_file, destination_file )
+
def move_file( current_dir, source, destination_dir ):
source_file = os.path.abspath( os.path.join( current_dir, source ) )
destination_directory = os.path.join( destination_dir )
if not os.path.isdir( destination_directory ):
os.makedirs( destination_directory )
shutil.move( source_file, destination_directory )
+
def tar_extraction_directory( file_path, file_name ):
"""Try to return the correct extraction directory."""
file_name = file_name.strip()
@@ -110,6 +121,7 @@
if os.path.exists( os.path.abspath( os.path.join( file_path, file_name ) ) ):
return os.path.abspath( file_path )
raise ValueError( 'Could not find path to file %s' % os.path.abspath( os.path.join( file_path, file_name ) ) )
+
def url_download( install_dir, downloaded_file_name, download_url ):
file_path = os.path.join( install_dir, downloaded_file_name )
src = None
@@ -125,6 +137,7 @@
if dst:
dst.close()
return os.path.abspath( file_path )
+
def zip_extraction_directory( file_path, file_name ):
"""Try to return the correct extraction directory."""
files = [ filename for filename in os.listdir( file_path ) if not filename.endswith( '.zip' ) ]
@@ -135,6 +148,7 @@
if os.path.isdir( os.path.join( file_path, files[ 0 ] ) ):
return os.path.abspath( os.path.join( file_path, files[ 0 ] ) )
raise ValueError( 'Could not find directory for the extracted file %s' % os.path.abspath( os.path.join( file_path, file_name ) ) )
+
def zipfile_ok( path_to_archive ):
"""
This function is a bit pedantic and not functionally necessary. It checks whether there is no file pointing outside of the extraction,
diff -r 494837c4fe5b6554a4c8cb1e93547ec45413f2df -r 6e91867769eab9e97353cd0e6363393c8077aadc lib/tool_shed/galaxy_install/tool_dependencies/install_util.py
--- a/lib/tool_shed/galaxy_install/tool_dependencies/install_util.py
+++ b/lib/tool_shed/galaxy_install/tool_dependencies/install_util.py
@@ -1,7 +1,13 @@
-import sys, os, subprocess, tempfile
+import os
+import sys
+import subprocess
+import tempfile
import common_util
import fabric_util
-from tool_shed.util import encoding_util, tool_dependency_util, common_util
+import tool_shed.util.shed_util_common as suc
+import tool_shed.util.common_util as cu
+from tool_shed.util import encoding_util
+from tool_shed.util import tool_dependency_util
from galaxy.model.orm import and_
from galaxy.web import url_for
@@ -9,21 +15,20 @@
import pkg_resources
pkg_resources.require( 'elementtree' )
-from elementtree import ElementTree, ElementInclude
-from elementtree.ElementTree import Element, SubElement
+from elementtree import ElementTree
+from elementtree import ElementInclude
+from elementtree.ElementTree import Element
+from elementtree.ElementTree import SubElement
def clean_tool_shed_url( base_url ):
protocol, base = base_url.split( '://' )
return base.rstrip( '/' )
def create_temporary_tool_dependencies_config( app, tool_shed_url, name, owner, changeset_revision ):
- """
- Make a call to the tool shed to get the required repository's tool_dependencies.xml file.
- """
- url = url_join( tool_shed_url,
- 'repository/get_tool_dependencies_config_contents?name=%s&owner=%s&changeset_revision=%s' % \
- ( name, owner, changeset_revision ) )
- text = common_util.tool_shed_get( app, tool_shed_url, url )
+ """Make a call to the tool shed to get the required repository's tool_dependencies.xml file."""
+ url = url_join( tool_shed_url,
+ 'repository/get_tool_dependencies_config_contents?name=%s&owner=%s&changeset_revision=%s' % ( name, owner, changeset_revision ) )
+ text = cu.tool_shed_get( app, tool_shed_url, url )
if text:
# Write the contents to a temporary file on disk so it can be reloaded and parsed.
fh = tempfile.NamedTemporaryFile( 'wb' )
@@ -102,13 +107,11 @@
Get all appropriate newer changeset revisions for the repository defined by
the received tool_shed_url / name / owner combination.
"""
- url = suc.url_join( tool_shed_url,
- 'repository/updated_changeset_revisions?name=%s&owner=%s&changeset_revision=%s' %
- ( name, owner, changeset_revision ) )
- text = common_util.tool_shed_get( app, tool_shed_url, url )
+ url = suc.url_join( tool_shed_url,
+ 'repository/updated_changeset_revisions?name=%s&owner=%s&changeset_revision=%s' % ( name, owner, changeset_revision ) )
+ text = cu.tool_shed_get( app, tool_shed_url, url )
return text
-
def handle_set_environment_entry_for_package( app, install_dir, tool_shed_repository, package_name, package_version, elem ):
action_dict = {}
actions = []
@@ -220,7 +223,8 @@
else:
# Make a call to the tool shed to get the changeset revision to which the current value of required_repository_changeset_revision
# should be updated if it's not current.
- text = get_updated_changeset_revisions_from_tool_shed( app, tool_shed_url=tool_shed,
+ text = get_updated_changeset_revisions_from_tool_shed( app=app,
+ tool_shed_url=tool_shed,
name=required_repository_name,
owner=required_repository_owner,
changeset_revision=required_repository_changeset_revision )
@@ -238,7 +242,8 @@
tool_dependency_name=package_name,
tool_dependency_version=package_version )
# Make a call to the tool shed to get the required repository's tool_dependencies.xml file.
- tmp_filename = create_temporary_tool_dependencies_config( app, tool_shed,
+ tmp_filename = create_temporary_tool_dependencies_config( app,
+ tool_shed,
required_repository_name,
required_repository_owner,
required_repository_changeset_revision )
diff -r 494837c4fe5b6554a4c8cb1e93547ec45413f2df -r 6e91867769eab9e97353cd0e6363393c8077aadc lib/tool_shed/galaxy_install/update_manager.py
--- a/lib/tool_shed/galaxy_install/update_manager.py
+++ b/lib/tool_shed/galaxy_install/update_manager.py
@@ -1,15 +1,18 @@
"""
Determine if installed tool shed repositories have updates available in their respective tool sheds.
"""
-import threading, logging
+import logging
+import threading
from galaxy.util import string_as_bool
import tool_shed.util.shed_util_common as suc
+from tool_shed.util import common_util
from galaxy.model.orm import and_
-from tool_shed.util import common_util
log = logging.getLogger( __name__ )
+
class UpdateManager( object ):
+
def __init__( self, app ):
self.app = app
self.sa_session = self.app.model.context.current
@@ -19,6 +22,7 @@
self.restarter = threading.Thread( target=self.__restarter )
self.restarter.start()
self.seconds_to_sleep = int( app.config.hours_between_check * 3600 )
+
def __restarter( self ):
log.info( 'Update manager restarter starting up...' )
while self.running:
@@ -34,6 +38,7 @@
self.sa_session.flush()
self.sleeper.sleep( self.seconds_to_sleep )
log.info( 'Transfer job restarter shutting down...' )
+
def check_for_update( self, repository ):
tool_shed_url = suc.get_url_from_tool_shed( self.app, repository.tool_shed )
url = '%s/repository/check_for_updates?name=%s&owner=%s&changeset_revision=%s&from_update_manager=True' % \
@@ -44,21 +49,23 @@
# The required tool shed may be unavailable.
text = 'False'
return string_as_bool( text )
+
def shutdown( self ):
self.running = False
self.sleeper.wake()
+
class Sleeper( object ):
- """
- Provides a 'sleep' method that sleeps for a number of seconds *unless*
- the notify method is called (from a different thread).
- """
+ """Provides a 'sleep' method that sleeps for a number of seconds *unless* the notify method is called (from a different thread)."""
+
def __init__( self ):
self.condition = threading.Condition()
+
def sleep( self, seconds ):
self.condition.acquire()
self.condition.wait( seconds )
self.condition.release()
+
def wake( self ):
self.condition.acquire()
self.condition.notify()
diff -r 494837c4fe5b6554a4c8cb1e93547ec45413f2df -r 6e91867769eab9e97353cd0e6363393c8077aadc lib/tool_shed/tool_shed_registry.py
--- a/lib/tool_shed/tool_shed_registry.py
+++ b/lib/tool_shed/tool_shed_registry.py
@@ -1,13 +1,15 @@
+import logging
+import sys
import urllib2
-import sys, logging
from galaxy.util import parse_xml
from galaxy.util.odict import odict
+from xml.etree import ElementTree
log = logging.getLogger( __name__ )
-from xml.etree import ElementTree
class Registry( object ):
+
def __init__( self, root_dir=None, config=None ):
self.tool_sheds = odict()
self.tool_sheds_auth = odict()
@@ -33,34 +35,16 @@
except Exception, e:
log.warning( 'Error loading reference to tool shed "%s", problem: %s' % ( name, str( e ) ) )
- def url_from_tool_shed( self, tool_shed ):
+ def password_manager_for_url( self, url ):
"""
- The value of tool_shed is something like: toolshed.g2.bx.psu.edu
- We need the URL to this tool shed, which is something like:
- http://toolshed.g2.bx.psu.edu/
- """
- for shed_name, shed_url in self.tool_sheds.items():
- if shed_url.find( tool_shed ) >= 0:
- if shed_url.endswith( '/' ):
- shed_url = shed_url.rstrip( '/' )
- return shed_url
- # The tool shed from which the repository was originally installed
- # must no longer be configured in tool_sheds_conf.xml.
- return None
-
- def password_manager_for_url(self, url):
- """
- If the tool shed is using external auth, the client to the toolshed must
- authenticate to that as well. This provides access to the
+ If the tool shed is using external auth, the client to the tool shed must authenticate to that as well. This provides access to the
urllib2.HTTPPasswordMgrWithdefaultRealm() object for the url passed in.
- Following more what galaxy.demo_sequencer.controllers.common does might
- be more appropriate at some stage...
+ Following more what galaxy.demo_sequencer.controllers.common does might be more appropriate at some stage...
"""
log.debug( 'Looking for url %s' % url )
-
for shed_name, shed_url in self.tool_sheds.items():
if shed_url.find( url ) >= 0:
- log.debug( 'Found %s -> %s' % (shed_name, shed_url) )
+ log.debug( 'Found %s -> %s' % ( shed_name, shed_url ) )
return self.tool_sheds_auth[ shed_name ]
return None
diff -r 494837c4fe5b6554a4c8cb1e93547ec45413f2df -r 6e91867769eab9e97353cd0e6363393c8077aadc lib/tool_shed/util/common_install_util.py
--- a/lib/tool_shed/util/common_install_util.py
+++ b/lib/tool_shed/util/common_install_util.py
@@ -282,7 +282,7 @@
url = suc.url_join( tool_shed_url, '/repository/get_required_repo_info_dict?encoded_str=%s' % encoded_required_repository_str )
text = common_util.tool_shed_get( trans.app, tool_shed_url, url )
if text:
- required_repo_info_dict = json.from_json_string( text )
+ required_repo_info_dict = json.from_json_string( text )
required_repo_info_dicts = []
encoded_dict_strings = required_repo_info_dict[ 'repo_info_dicts' ]
for encoded_dict_str in encoded_dict_strings:
diff -r 494837c4fe5b6554a4c8cb1e93547ec45413f2df -r 6e91867769eab9e97353cd0e6363393c8077aadc lib/tool_shed/util/common_util.py
--- a/lib/tool_shed/util/common_util.py
+++ b/lib/tool_shed/util/common_util.py
@@ -94,17 +94,15 @@
return shed_url
return None
-def tool_shed_get(app, tool_shed_url, uri):
- """
- Make contact with the tool shed via the uri provided.
- """
- registry = app.tool_shed_registry
- urlopener = urllib2.build_opener()
+def tool_shed_get( app, tool_shed_url, uri ):
+ """Make contact with the tool shed via the uri provided."""
+ registry = app.tool_shed_registry
+ urlopener = urllib2.build_opener()
password_mgr = registry.password_manager_for_url( tool_shed_url )
if ( password_mgr is not None ):
auth_handler = urllib2.HTTPBasicAuthHandler( password_mgr )
urlopener.add_handler( auth_handler )
- response = urlopener.open( uri )
- content = response.read()
+ response = urlopener.open( uri )
+ content = response.read()
response.close()
return content
diff -r 494837c4fe5b6554a4c8cb1e93547ec45413f2df -r 6e91867769eab9e97353cd0e6363393c8077aadc lib/tool_shed/util/metadata_util.py
--- a/lib/tool_shed/util/metadata_util.py
+++ b/lib/tool_shed/util/metadata_util.py
@@ -1010,8 +1010,7 @@
def get_updated_changeset_revisions_from_tool_shed( app, tool_shed_url, name, owner, changeset_revision ):
"""
- Get all appropriate newer changeset revisions for the repository defined by
- the received tool_shed_url / name / owner combination.
+ Get all appropriate newer changeset revisions for the repository defined by the received tool_shed_url / name / owner combination.
"""
url = suc.url_join( tool_shed_url,
'repository/updated_changeset_revisions?name=%s&owner=%s&changeset_revision=%s' %
diff -r 494837c4fe5b6554a4c8cb1e93547ec45413f2df -r 6e91867769eab9e97353cd0e6363393c8077aadc lib/tool_shed/util/readme_util.py
--- a/lib/tool_shed/util/readme_util.py
+++ b/lib/tool_shed/util/readme_util.py
@@ -2,7 +2,7 @@
import os
from galaxy.util import json
import tool_shed.util.shed_util_common as suc
-from tool_shed.util import common_util
+from tool_shed.util import common_util
log = logging.getLogger( __name__ )
@@ -28,17 +28,16 @@
def get_readme_files_dict_for_display( trans, tool_shed_url, repo_info_dict ):
"""
- Return a dictionary of README files contained in the single repository
- being installed so they can be displayed on the tool panel section
+ Return a dictionary of README files contained in the single repository being installed so they can be displayed on the tool panel section
selection page.
"""
name = repo_info_dict.keys()[ 0 ]
repo_info_tuple = repo_info_dict[ name ]
- description, repository_clone_url, changeset_revision, ctx_rev, repository_owner, repository_dependencies, installed_td = suc.get_repo_info_tuple_contents( repo_info_tuple )
+ description, repository_clone_url, changeset_revision, ctx_rev, repository_owner, repository_dependencies, installed_td = \
+ suc.get_repo_info_tuple_contents( repo_info_tuple )
# Handle README files.
url = suc.url_join( tool_shed_url,
- 'repository/get_readme_files?name=%s&owner=%s&changeset_revision=%s' % \
- ( name, repository_owner, changeset_revision ) )
- raw_text = common_util.tool_shed_get( trans.app, tool_shed_url, url )
+ 'repository/get_readme_files?name=%s&owner=%s&changeset_revision=%s' % ( name, repository_owner, changeset_revision ) )
+ raw_text = common_util.tool_shed_get( trans.app, tool_shed_url, url )
readme_files_dict = json.from_json_string( raw_text )
return readme_files_dict
diff -r 494837c4fe5b6554a4c8cb1e93547ec45413f2df -r 6e91867769eab9e97353cd0e6363393c8077aadc lib/tool_shed/util/shed_util_common.py
--- a/lib/tool_shed/util/shed_util_common.py
+++ b/lib/tool_shed/util/shed_util_common.py
@@ -445,13 +445,12 @@
def get_ctx_rev( app, tool_shed_url, name, owner, changeset_revision ):
"""
- Send a request to the tool shed to retrieve the ctx_rev for a repository
- defined by the combination of a name, owner and changeset revision.
+ Send a request to the tool shed to retrieve the ctx_rev for a repository defined by the combination of a name, owner and changeset
+ revision.
"""
- url = url_join( tool_shed_url,
- 'repository/get_ctx_rev?name=%s&owner=%s&changeset_revision=%s' %
- ( name, owner, changeset_revision ) )
- ctx_rev = common_util.tool_shed_get( app, tool_shed_url, url)
+ url = url_join( tool_shed_url,
+ 'repository/get_ctx_rev?name=%s&owner=%s&changeset_revision=%s' % ( name, owner, changeset_revision ) )
+ ctx_rev = common_util.tool_shed_get( app, tool_shed_url, url )
return ctx_rev
def get_ctx_file_path_from_manifest( filename, repo, changeset_revision ):
@@ -546,8 +545,7 @@
if not repository:
tool_shed_url = get_url_from_tool_shed( trans.app, tool_shed )
repository_clone_url = os.path.join( tool_shed_url, 'repos', owner, name )
- ctx_rev = get_ctx_rev( trans.app,
- tool_shed_url, name, owner, changeset_revision )
+ ctx_rev = get_ctx_rev( trans.app, tool_shed_url, name, owner, changeset_revision )
repository = create_or_update_tool_shed_repository( app=trans.app,
name=name,
description=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
2 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/7f70ea89d5a9/
Changeset: 7f70ea89d5a9
User: carlfeberhard
Date: 2013-04-16 20:03:11
Summary: History panel: allow query val for hda_id to scroll specific hda into view, cleanup; browser tests: add download, info, and rerun button tests
Affected #: 10 files
diff -r b9bd0fae39cabc1ff55f374e026b7aa3f5687c77 -r 7f70ea89d5a92cba463b873de7535766bb8c7050 static/scripts/mvc/dataset/hda-base.js
--- a/static/scripts/mvc/dataset/hda-base.js
+++ b/static/scripts/mvc/dataset/hda-base.js
@@ -589,10 +589,12 @@
}
},
+ // ......................................................................... DELETION
remove : function( callback ){
var hdaView = this;
this.$el.fadeOut( 'fast', function(){
hdaView.$el.remove();
+ hdaView.off();
if( callback ){ callback(); }
});
},
diff -r b9bd0fae39cabc1ff55f374e026b7aa3f5687c77 -r 7f70ea89d5a92cba463b873de7535766bb8c7050 static/scripts/mvc/history/history-panel.js
--- a/static/scripts/mvc/history/history-panel.js
+++ b/static/scripts/mvc/history/history-panel.js
@@ -494,7 +494,8 @@
return false;
},
- /** display a message in the top of the panel
+ // ......................................................................... MISC
+ /** Display a message in the top of the panel.
* @param {String} type type of message ('done', 'error', 'warning')
* @param {String} msg the message to display
*/
@@ -504,14 +505,68 @@
$msgContainer.html( $msg );
},
- /** Remove a message from the panel
+ /** Remove a message from the panel.
*/
removeMessage : function(){
var $msgContainer = this.$el.find( '#message-container' );
$msgContainer.html( null );
},
- // ......................................................................... MISC
+ /** Scrolls the panel to the top.
+ * @returns {HistoryPanel} the panel
+ */
+ scrollToTop : function(){
+ $( document ).scrollTop( 0 );
+ return this;
+ },
+
+ /** Scrolls the panel (the enclosing container - in gen., the page) so that some object
+ * is displayed in the vertical middle.
+ * NOTE: if no size is given the panel will scroll to objTop (putting it at the top).
+ * @param {Number} objTop the top offset of the object to view
+ * @param {Number} objSize the size of the object to view
+ * @returns {HistoryPanel} the panel
+ */
+ scrollIntoView : function( where, size ){
+ if( !size ){
+ $( document ).scrollTop( where );
+ return this;
+ }
+ // otherwise, place the object in the vertical middle
+ var viewport = window,
+ panelContainer = this.$el.parent(),
+ containerHeight = $( viewport ).innerHeight(),
+ middleOffset = ( containerHeight / 2 ) - ( size / 2 );
+
+ $( panelContainer ).scrollTop( where - middleOffset );
+ return this;
+ },
+
+ /** Scrolls the panel to show the HDA with the given id.
+ * @param {String} id the id of HDA to scroll into view
+ * @returns {HistoryPanel} the panel
+ */
+ scrollToId : function( id ){
+ // do nothing if id not found
+ if( ( !id ) || ( !this.hdaViews[ id ] ) ){
+ return this;
+ }
+ var $viewEl = this.hdaViews[ id ].$el;
+ this.scrollIntoView( $viewEl.offset().top, $viewEl.outerHeight() );
+ return this;
+ },
+
+ /** Scrolls the panel to show the HDA with the given hid.
+ * @param {Integer} hid the hid of HDA to scroll into view
+ * @returns {HistoryPanel} the panel
+ */
+ scrollToHid : function( hid ){
+ var hda = this.model.hdas.getByHid( hid );
+ // do nothing if hid not found
+ if( !hda ){ return this; }
+ return this.scrollToId( hda.id );
+ },
+
/** Return a string rep of the history
*/
toString : function(){
diff -r b9bd0fae39cabc1ff55f374e026b7aa3f5687c77 -r 7f70ea89d5a92cba463b873de7535766bb8c7050 static/scripts/packed/mvc/dataset/hda-base.js
--- a/static/scripts/packed/mvc/dataset/hda-base.js
+++ b/static/scripts/packed/mvc/dataset/hda-base.js
@@ -1,1 +1,1 @@
-var HDABaseView=Backbone.View.extend(LoggableMixin).extend({tagName:"div",className:"historyItemContainer",initialize:function(a){if(a.logger){this.logger=this.model.logger=a.logger}this.log(this+".initialize:",a);this.defaultPrimaryActionButtonRenderers=[this._render_showParamsButton];if(!a.urlTemplates){throw ("HDAView needs urlTemplates on initialize")}this.urlTemplates=a.urlTemplates;this.expanded=a.expanded||false;this.model.bind("change",function(c,d){var b=_.without(_.keys(d.changes),"display_apps","display_types");if(b.length){this.render()}else{if(this.expanded){this._render_displayApps()}}},this)},render:function(){var b=this,e=this.model.get("id"),c=this.model.get("state"),a=$("<div/>").attr("id","historyItem-"+e),d=(this.$el.children().size()===0);this.$el.attr("id","historyItemContainer-"+e);this.urls=this._renderUrls(this.urlTemplates,this.model.toJSON());a.addClass("historyItemWrapper").addClass("historyItem").addClass("historyItem-"+c);a.append(this._render_warnings());a.append(this._render_titleBar());this._setUpBehaviors(a);this.body=$(this._render_body());a.append(this.body);this.$el.fadeOut("fast",function(){b.$el.children().remove();b.$el.append(a).fadeIn("fast",function(){b.log(b+" rendered:",b.$el);var f="rendered";if(d){f+=":initial"}else{if(b.model.inReadyState()){f+=":ready"}}b.trigger(f)})});return this},_renderUrls:function(d,a){var b=this,c={};_.each(d,function(e,f){if(_.isObject(e)){c[f]=b._renderUrls(e,a)}else{if(f==="meta_download"){c[f]=b._renderMetaDownloadUrls(e,a)}else{try{c[f]=_.template(e,a)}catch(g){throw (b+"._renderUrls error: "+g+"\n rendering:"+e+"\n with "+JSON.stringify(a))}}}});return c},_renderMetaDownloadUrls:function(b,a){return _.map(a.meta_files,function(c){return{url:_.template(b,{id:a.id,file_type:c.file_type}),file_type:c.file_type}})},_setUpBehaviors:function(a){a=a||this.$el;make_popup_menus(a);a.find(".tooltip").tooltip({placement:"bottom"})},_render_warnings:function(){return $(jQuery.trim(HDABaseView.templates.messages(this.model.toJSON())))},_render_titleBar:function(){var a=$('<div class="historyItemTitleBar" style="overflow: hidden"></div>');a.append(this._render_titleButtons());a.append('<span class="state-icon"></span>');a.append(this._render_titleLink());return a},_render_titleButtons:function(){var a=$('<div class="historyItemButtons"></div>');a.append(this._render_displayButton());return a},_render_displayButton:function(){if((this.model.get("state")===HistoryDatasetAssociation.STATES.NOT_VIEWABLE)||(this.model.get("state")===HistoryDatasetAssociation.STATES.NEW)||(!this.model.get("accessible"))){this.displayButton=null;return null}var a={icon_class:"display",target:"galaxy_main"};if(this.model.get("purged")){a.enabled=false;a.title=_l("Cannot display datasets removed from disk")}else{a.title=_l("View data");a.href=this.urls.display}this.displayButton=new IconButtonView({model:new IconButton(a)});return this.displayButton.render().$el},_render_titleLink:function(){return $(jQuery.trim(HDABaseView.templates.titleLink(_.extend(this.model.toJSON(),{urls:this.urls}))))},_render_hdaSummary:function(){var a=_.extend(this.model.toJSON(),{urls:this.urls});return HDABaseView.templates.hdaSummary(a)},_render_primaryActionButtons:function(c){var a=this,b=$("<div/>").attr("id","primary-actions-"+this.model.get("id"));_.each(c,function(d){b.append(d.call(a))});return b},_render_downloadButton:function(){if(this.model.get("purged")||!this.model.hasData()){return null}var a=HDABaseView.templates.downloadLinks(_.extend(this.model.toJSON(),{urls:this.urls}));return $(a)},_render_showParamsButton:function(){this.showParamsButton=new IconButtonView({model:new IconButton({title:_l("View details"),href:this.urls.show_params,target:"galaxy_main",icon_class:"information"})});return this.showParamsButton.render().$el},_render_displayAppArea:function(){return $("<div/>").addClass("display-apps")},_render_displayApps:function(c){c=c||this.$el;var d=c.find("div.display-apps"),a=this.model.get("display_types"),b=this.model.get("display_apps");if((!this.model.hasData())||(!c||!c.length)||(!d.length)){return}d.html(null);if(!_.isEmpty(a)){d.append(HDABaseView.templates.displayApps({displayApps:a}))}if(!_.isEmpty(b)){d.append(HDABaseView.templates.displayApps({displayApps:b}))}},_render_peek:function(){var a=this.model.get("peek");if(!a){return null}return $("<div/>").append($("<pre/>").attr("id","peek"+this.model.get("id")).addClass("peek").append(a))},_render_body:function(){var a=$("<div/>").attr("id","info-"+this.model.get("id")).addClass("historyItemBody").attr("style","display: none");if(this.expanded){this._render_body_html(a);a.css("display","block")}return a},_render_body_html:function(a){a.html("");switch(this.model.get("state")){case HistoryDatasetAssociation.STATES.NEW:this._render_body_new(a);break;case HistoryDatasetAssociation.STATES.NOT_VIEWABLE:this._render_body_not_viewable(a);break;case HistoryDatasetAssociation.STATES.UPLOAD:this._render_body_uploading(a);break;case HistoryDatasetAssociation.STATES.PAUSED:this._render_body_paused(a);break;case HistoryDatasetAssociation.STATES.QUEUED:this._render_body_queued(a);break;case HistoryDatasetAssociation.STATES.RUNNING:this._render_body_running(a);break;case HistoryDatasetAssociation.STATES.ERROR:this._render_body_error(a);break;case HistoryDatasetAssociation.STATES.DISCARDED:this._render_body_discarded(a);break;case HistoryDatasetAssociation.STATES.SETTING_METADATA:this._render_body_setting_metadata(a);break;case HistoryDatasetAssociation.STATES.EMPTY:this._render_body_empty(a);break;case HistoryDatasetAssociation.STATES.FAILED_METADATA:this._render_body_failed_metadata(a);break;case HistoryDatasetAssociation.STATES.OK:this._render_body_ok(a);break;default:a.append($('<div>Error: unknown dataset state "'+this.model.get("state")+'".</div>'))}a.append('<div style="clear: both"></div>');this._setUpBehaviors(a)},_render_body_new:function(b){var a=_l("This is a new dataset and not all of its data are available yet");b.append($("<div>"+_l(a)+"</div>"))},_render_body_not_viewable:function(a){a.append($("<div>"+_l("You do not have permission to view dataset")+"</div>"))},_render_body_uploading:function(a){a.append($("<div>"+_l("Dataset is uploading")+"</div>"))},_render_body_queued:function(a){a.append($("<div>"+_l("Job is waiting to run")+"</div>"));a.append(this._render_primaryActionButtons(this.defaultPrimaryActionButtonRenderers))},_render_body_paused:function(a){a.append($("<div>"+_l("Job is paused. Use the history menu to resume")+"</div>"));a.append(this._render_primaryActionButtons(this.defaultPrimaryActionButtonRenderers))},_render_body_running:function(a){a.append("<div>"+_l("Job is currently running")+"</div>");a.append(this._render_primaryActionButtons(this.defaultPrimaryActionButtonRenderers))},_render_body_error:function(a){if(!this.model.get("purged")){a.append($("<div>"+this.model.get("misc_blurb")+"</div>"))}a.append((_l("An error occurred with this dataset")+": <i>"+$.trim(this.model.get("misc_info"))+"</i>"));a.append(this._render_primaryActionButtons(this.defaultPrimaryActionButtonRenderers.concat([this._render_downloadButton])))},_render_body_discarded:function(a){a.append("<div>"+_l("The job creating this dataset was cancelled before completion")+".</div>");a.append(this._render_primaryActionButtons(this.defaultPrimaryActionButtonRenderers))},_render_body_setting_metadata:function(a){a.append($("<div>"+_l("Metadata is being auto-detected")+".</div>"))},_render_body_empty:function(a){a.append($("<div>"+_l("No data")+": <i>"+this.model.get("misc_blurb")+"</i></div>"));a.append(this._render_primaryActionButtons(this.defaultPrimaryActionButtonRenderers))},_render_body_failed_metadata:function(a){a.append($(HDABaseView.templates.failedMetadata(_.extend(this.model.toJSON(),{urls:this.urls}))));this._render_body_ok(a)},_render_body_ok:function(a){a.append(this._render_hdaSummary());if(this.model.isDeletedOrPurged()){a.append(this._render_primaryActionButtons([this._render_downloadButton,this._render_showParamsButton]));return}a.append(this._render_primaryActionButtons([this._render_downloadButton,this._render_showParamsButton]));a.append('<div class="clear"/>');a.append(this._render_displayAppArea());this._render_displayApps(a);a.append(this._render_peek())},events:{"click .historyItemTitle":"toggleBodyVisibility"},toggleBodyVisibility:function(c,a){var b=this;this.expanded=(a===undefined)?(!this.body.is(":visible")):(a);if(this.expanded){b._render_body_html(b.body);this.body.slideDown("fast",function(){b.trigger("body-expanded",b.model.get("id"))})}else{this.body.slideUp("fast",function(){b.trigger("body-collapsed",b.model.get("id"))})}},remove:function(b){var a=this;this.$el.fadeOut("fast",function(){a.$el.remove();if(b){b()}})},toString:function(){var a=(this.model)?(this.model+""):("(no model)");return"HDABaseView("+a+")"}});HDABaseView.templates={warningMsg:Handlebars.templates["template-warningmessagesmall"],messages:Handlebars.templates["template-hda-warning-messages"],titleLink:Handlebars.templates["template-hda-titleLink"],hdaSummary:Handlebars.templates["template-hda-hdaSummary"],downloadLinks:Handlebars.templates["template-hda-downloadLinks"],failedMetadata:Handlebars.templates["template-hda-failedMetadata"],displayApps:Handlebars.templates["template-hda-displayApps"]};
\ No newline at end of file
+var HDABaseView=Backbone.View.extend(LoggableMixin).extend({tagName:"div",className:"historyItemContainer",initialize:function(a){if(a.logger){this.logger=this.model.logger=a.logger}this.log(this+".initialize:",a);this.defaultPrimaryActionButtonRenderers=[this._render_showParamsButton];if(!a.urlTemplates){throw ("HDAView needs urlTemplates on initialize")}this.urlTemplates=a.urlTemplates;this.expanded=a.expanded||false;this.model.bind("change",function(c,d){var b=_.without(_.keys(d.changes),"display_apps","display_types");if(b.length){this.render()}else{if(this.expanded){this._render_displayApps()}}},this)},render:function(){var b=this,e=this.model.get("id"),c=this.model.get("state"),a=$("<div/>").attr("id","historyItem-"+e),d=(this.$el.children().size()===0);this.$el.attr("id","historyItemContainer-"+e);this.urls=this._renderUrls(this.urlTemplates,this.model.toJSON());a.addClass("historyItemWrapper").addClass("historyItem").addClass("historyItem-"+c);a.append(this._render_warnings());a.append(this._render_titleBar());this._setUpBehaviors(a);this.body=$(this._render_body());a.append(this.body);this.$el.fadeOut("fast",function(){b.$el.children().remove();b.$el.append(a).fadeIn("fast",function(){b.log(b+" rendered:",b.$el);var f="rendered";if(d){f+=":initial"}else{if(b.model.inReadyState()){f+=":ready"}}b.trigger(f)})});return this},_renderUrls:function(d,a){var b=this,c={};_.each(d,function(e,f){if(_.isObject(e)){c[f]=b._renderUrls(e,a)}else{if(f==="meta_download"){c[f]=b._renderMetaDownloadUrls(e,a)}else{try{c[f]=_.template(e,a)}catch(g){throw (b+"._renderUrls error: "+g+"\n rendering:"+e+"\n with "+JSON.stringify(a))}}}});return c},_renderMetaDownloadUrls:function(b,a){return _.map(a.meta_files,function(c){return{url:_.template(b,{id:a.id,file_type:c.file_type}),file_type:c.file_type}})},_setUpBehaviors:function(a){a=a||this.$el;make_popup_menus(a);a.find(".tooltip").tooltip({placement:"bottom"})},_render_warnings:function(){return $(jQuery.trim(HDABaseView.templates.messages(this.model.toJSON())))},_render_titleBar:function(){var a=$('<div class="historyItemTitleBar" style="overflow: hidden"></div>');a.append(this._render_titleButtons());a.append('<span class="state-icon"></span>');a.append(this._render_titleLink());return a},_render_titleButtons:function(){var a=$('<div class="historyItemButtons"></div>');a.append(this._render_displayButton());return a},_render_displayButton:function(){if((this.model.get("state")===HistoryDatasetAssociation.STATES.NOT_VIEWABLE)||(this.model.get("state")===HistoryDatasetAssociation.STATES.NEW)||(!this.model.get("accessible"))){this.displayButton=null;return null}var a={icon_class:"display",target:"galaxy_main"};if(this.model.get("purged")){a.enabled=false;a.title=_l("Cannot display datasets removed from disk")}else{a.title=_l("View data");a.href=this.urls.display}this.displayButton=new IconButtonView({model:new IconButton(a)});return this.displayButton.render().$el},_render_titleLink:function(){return $(jQuery.trim(HDABaseView.templates.titleLink(_.extend(this.model.toJSON(),{urls:this.urls}))))},_render_hdaSummary:function(){var a=_.extend(this.model.toJSON(),{urls:this.urls});return HDABaseView.templates.hdaSummary(a)},_render_primaryActionButtons:function(c){var a=this,b=$("<div/>").attr("id","primary-actions-"+this.model.get("id"));_.each(c,function(d){b.append(d.call(a))});return b},_render_downloadButton:function(){if(this.model.get("purged")||!this.model.hasData()){return null}var a=HDABaseView.templates.downloadLinks(_.extend(this.model.toJSON(),{urls:this.urls}));return $(a)},_render_showParamsButton:function(){this.showParamsButton=new IconButtonView({model:new IconButton({title:_l("View details"),href:this.urls.show_params,target:"galaxy_main",icon_class:"information"})});return this.showParamsButton.render().$el},_render_displayAppArea:function(){return $("<div/>").addClass("display-apps")},_render_displayApps:function(c){c=c||this.$el;var d=c.find("div.display-apps"),a=this.model.get("display_types"),b=this.model.get("display_apps");if((!this.model.hasData())||(!c||!c.length)||(!d.length)){return}d.html(null);if(!_.isEmpty(a)){d.append(HDABaseView.templates.displayApps({displayApps:a}))}if(!_.isEmpty(b)){d.append(HDABaseView.templates.displayApps({displayApps:b}))}},_render_peek:function(){var a=this.model.get("peek");if(!a){return null}return $("<div/>").append($("<pre/>").attr("id","peek"+this.model.get("id")).addClass("peek").append(a))},_render_body:function(){var a=$("<div/>").attr("id","info-"+this.model.get("id")).addClass("historyItemBody").attr("style","display: none");if(this.expanded){this._render_body_html(a);a.css("display","block")}return a},_render_body_html:function(a){a.html("");switch(this.model.get("state")){case HistoryDatasetAssociation.STATES.NEW:this._render_body_new(a);break;case HistoryDatasetAssociation.STATES.NOT_VIEWABLE:this._render_body_not_viewable(a);break;case HistoryDatasetAssociation.STATES.UPLOAD:this._render_body_uploading(a);break;case HistoryDatasetAssociation.STATES.PAUSED:this._render_body_paused(a);break;case HistoryDatasetAssociation.STATES.QUEUED:this._render_body_queued(a);break;case HistoryDatasetAssociation.STATES.RUNNING:this._render_body_running(a);break;case HistoryDatasetAssociation.STATES.ERROR:this._render_body_error(a);break;case HistoryDatasetAssociation.STATES.DISCARDED:this._render_body_discarded(a);break;case HistoryDatasetAssociation.STATES.SETTING_METADATA:this._render_body_setting_metadata(a);break;case HistoryDatasetAssociation.STATES.EMPTY:this._render_body_empty(a);break;case HistoryDatasetAssociation.STATES.FAILED_METADATA:this._render_body_failed_metadata(a);break;case HistoryDatasetAssociation.STATES.OK:this._render_body_ok(a);break;default:a.append($('<div>Error: unknown dataset state "'+this.model.get("state")+'".</div>'))}a.append('<div style="clear: both"></div>');this._setUpBehaviors(a)},_render_body_new:function(b){var a=_l("This is a new dataset and not all of its data are available yet");b.append($("<div>"+_l(a)+"</div>"))},_render_body_not_viewable:function(a){a.append($("<div>"+_l("You do not have permission to view dataset")+"</div>"))},_render_body_uploading:function(a){a.append($("<div>"+_l("Dataset is uploading")+"</div>"))},_render_body_queued:function(a){a.append($("<div>"+_l("Job is waiting to run")+"</div>"));a.append(this._render_primaryActionButtons(this.defaultPrimaryActionButtonRenderers))},_render_body_paused:function(a){a.append($("<div>"+_l("Job is paused. Use the history menu to resume")+"</div>"));a.append(this._render_primaryActionButtons(this.defaultPrimaryActionButtonRenderers))},_render_body_running:function(a){a.append("<div>"+_l("Job is currently running")+"</div>");a.append(this._render_primaryActionButtons(this.defaultPrimaryActionButtonRenderers))},_render_body_error:function(a){if(!this.model.get("purged")){a.append($("<div>"+this.model.get("misc_blurb")+"</div>"))}a.append((_l("An error occurred with this dataset")+": <i>"+$.trim(this.model.get("misc_info"))+"</i>"));a.append(this._render_primaryActionButtons(this.defaultPrimaryActionButtonRenderers.concat([this._render_downloadButton])))},_render_body_discarded:function(a){a.append("<div>"+_l("The job creating this dataset was cancelled before completion")+".</div>");a.append(this._render_primaryActionButtons(this.defaultPrimaryActionButtonRenderers))},_render_body_setting_metadata:function(a){a.append($("<div>"+_l("Metadata is being auto-detected")+".</div>"))},_render_body_empty:function(a){a.append($("<div>"+_l("No data")+": <i>"+this.model.get("misc_blurb")+"</i></div>"));a.append(this._render_primaryActionButtons(this.defaultPrimaryActionButtonRenderers))},_render_body_failed_metadata:function(a){a.append($(HDABaseView.templates.failedMetadata(_.extend(this.model.toJSON(),{urls:this.urls}))));this._render_body_ok(a)},_render_body_ok:function(a){a.append(this._render_hdaSummary());if(this.model.isDeletedOrPurged()){a.append(this._render_primaryActionButtons([this._render_downloadButton,this._render_showParamsButton]));return}a.append(this._render_primaryActionButtons([this._render_downloadButton,this._render_showParamsButton]));a.append('<div class="clear"/>');a.append(this._render_displayAppArea());this._render_displayApps(a);a.append(this._render_peek())},events:{"click .historyItemTitle":"toggleBodyVisibility"},toggleBodyVisibility:function(c,a){var b=this;this.expanded=(a===undefined)?(!this.body.is(":visible")):(a);if(this.expanded){b._render_body_html(b.body);this.body.slideDown("fast",function(){b.trigger("body-expanded",b.model.get("id"))})}else{this.body.slideUp("fast",function(){b.trigger("body-collapsed",b.model.get("id"))})}},remove:function(b){var a=this;this.$el.fadeOut("fast",function(){a.$el.remove();a.off();if(b){b()}})},toString:function(){var a=(this.model)?(this.model+""):("(no model)");return"HDABaseView("+a+")"}});HDABaseView.templates={warningMsg:Handlebars.templates["template-warningmessagesmall"],messages:Handlebars.templates["template-hda-warning-messages"],titleLink:Handlebars.templates["template-hda-titleLink"],hdaSummary:Handlebars.templates["template-hda-hdaSummary"],downloadLinks:Handlebars.templates["template-hda-downloadLinks"],failedMetadata:Handlebars.templates["template-hda-failedMetadata"],displayApps:Handlebars.templates["template-hda-displayApps"]};
\ No newline at end of file
diff -r b9bd0fae39cabc1ff55f374e026b7aa3f5687c77 -r 7f70ea89d5a92cba463b873de7535766bb8c7050 static/scripts/packed/mvc/history/history-panel.js
--- a/static/scripts/packed/mvc/history/history-panel.js
+++ b/static/scripts/packed/mvc/history/history-panel.js
@@ -1,1 +1,1 @@
-var HistoryPanel=Backbone.View.extend(LoggableMixin).extend({el:"body.historyPage",HDAView:HDAEditView,events:{"click #history-tag":"loadAndDisplayTags","click #message-container":"removeMessage"},initialize:function(a){if(a.logger){this.logger=this.model.logger=a.logger}this.log(this+".initialize:",a);if(!a.urlTemplates){throw (this+" needs urlTemplates on initialize")}if(!a.urlTemplates.history){throw (this+" needs urlTemplates.history on initialize")}if(!a.urlTemplates.hda){throw (this+" needs urlTemplates.hda on initialize")}this.urlTemplates=a.urlTemplates.history;this.hdaUrlTemplates=a.urlTemplates.hda;this._setUpWebStorage(a.initiallyExpanded,a.show_deleted,a.show_hidden);this._setUpEventHandlers();this.hdaViews={};this.urls={}},_setUpEventHandlers:function(){this.model.bind("change:nice_size",this.updateHistoryDiskSize,this);this.model.bind("error",function(d,c,b,a){this.displayMessage("error",d);this.model.attributes.error=undefined},this);this.model.hdas.bind("add",this.add,this);this.model.hdas.bind("reset",this.addAll,this);this.model.hdas.bind("change:deleted",this.handleHdaDeletionChange,this);this.model.hdas.bind("change:purged",function(a){this.model.fetch()},this);this.model.hdas.bind("state:ready",function(b,c,a){if((!b.get("visible"))&&(!this.storage.get("show_hidden"))){this.removeHdaView(b.get("id"))}},this);this.bind("error",function(d,c,b,a){this.displayMessage("error",d)});if(this.logger){this.bind("all",function(a){this.log(this+"",arguments)},this)}},_setUpWebStorage:function(b,a,c){this.storage=new PersistantStorage("HistoryView."+this.model.get("id"),{expandedHdas:{},show_deleted:false,show_hidden:false});this.log(this+" (prev) storage:",JSON.stringify(this.storage.get(),null,2));if(b){this.storage.set("exandedHdas",b)}if((a===true)||(a===false)){this.storage.set("show_deleted",a)}if((c===true)||(c===false)){this.storage.set("show_hidden",c)}this.show_deleted=this.storage.get("show_deleted");this.show_hidden=this.storage.get("show_hidden");this.log(this+" (init'd) storage:",this.storage.get())},add:function(a){this.render()},addAll:function(){this.render()},handleHdaDeletionChange:function(a){if(a.get("deleted")&&!this.storage.get("show_deleted")){this.removeHdaView(a.get("id"))}},removeHdaView:function(c,b){var a=this.hdaViews[c];if(!a){return}a.remove(b);delete this.hdaViews[c];if(_.isEmpty(this.hdaViews)){this.render()}},render:function(){var b=this,d=b.toString()+".set-up",c=$("<div/>"),a=this.model.toJSON(),e=(this.$el.children().size()===0);a.urls=this._renderUrls(a);c.append(HistoryPanel.templates.historyPanel(a));c.find(".tooltip").tooltip({placement:"bottom"});if(!this.model.hdas.length||!this.renderItems(c.find("#"+this.model.get("id")+"-datasets"))){c.find("#emptyHistoryMessage").show()}$(b).queue(d,function(f){b.$el.fadeOut("fast",function(){f()})});$(b).queue(d,function(f){b.$el.html("");b.$el.append(c.children());b.$el.fadeIn("fast",function(){f()})});$(b).queue(d,function(f){this.log(b+" rendered:",b.$el);b._setUpBehaviours();if(e){b.trigger("rendered:initial")}else{b.trigger("rendered")}f()});$(b).dequeue(d);return this},_renderUrls:function(a){var b=this;b.urls={};_.each(this.urlTemplates,function(d,c){b.urls[c]=_.template(d,a)});return b.urls},renderItems:function(b){this.hdaViews={};var a=this,c=this.model.hdas.getVisible(this.storage.get("show_deleted"),this.storage.get("show_hidden"));_.each(c,function(f){var e=f.get("id"),d=a.storage.get("expandedHdas").get(e);a.hdaViews[e]=new a.HDAView({model:f,expanded:d,urlTemplates:a.hdaUrlTemplates,logger:a.logger});a._setUpHdaListeners(a.hdaViews[e]);b.prepend(a.hdaViews[e].render().$el)});return c.length},_setUpHdaListeners:function(b){var a=this;b.bind("body-expanded",function(c){a.storage.get("expandedHdas").set(c,true)});b.bind("body-collapsed",function(c){a.storage.get("expandedHdas").deleteKey(c)});b.bind("error",function(f,e,c,d){a.displayMessage("error",f)})},_setUpBehaviours:function(){if(!(this.model.get("user")&&this.model.get("user").email)){return}var a=this.$("#history-annotation-area");this.$("#history-annotate").click(function(){if(a.is(":hidden")){a.slideDown("fast")}else{a.slideUp("fast")}return false});async_save_text("history-name-container","history-name",this.urls.rename,"new_name",18);async_save_text("history-annotation-container","history-annotation",this.urls.annotate,"new_annotation",18,true,4)},updateHistoryDiskSize:function(){this.$el.find("#history-size").text(this.model.get("nice_size"))},showQuotaMessage:function(){var a=this.$el.find("#quota-message-container");if(a.is(":hidden")){a.slideDown("fast")}},hideQuotaMessage:function(){var a=this.$el.find("#quota-message-container");if(!a.is(":hidden")){a.slideUp("fast")}},toggleShowDeleted:function(){this.storage.set("show_deleted",!this.storage.get("show_deleted"));this.render();return this.storage.get("show_deleted")},toggleShowHidden:function(){this.storage.set("show_hidden",!this.storage.get("show_hidden"));this.render();return this.storage.get("show_hidden")},collapseAllHdaBodies:function(){_.each(this.hdaViews,function(a){a.toggleBodyVisibility(null,false)});this.storage.set("expandedHdas",{})},loadAndDisplayTags:function(d){this.log(this+".loadAndDisplayTags",d);var b=this,e=this.$el.find("#history-tag-area"),c=e.find(".tag-elt");this.log("\t tagArea",e," tagElt",c);if(e.is(":hidden")){if(!jQuery.trim(c.html())){var a=this;$.ajax({url:a.urls.tag,error:function(h,g,f){b.log("Error loading tag area html",h,g,f);b.trigger("error",_l("Tagging failed"),h,g,f)},success:function(f){c.html(f);c.find(".tooltip").tooltip();e.slideDown("fast")}})}else{e.slideDown("fast")}}else{e.slideUp("fast")}return false},displayMessage:function(c,d){var b=this.$el.find("#message-container"),a=$("<div/>").addClass(c+"message").text(d);b.html(a)},removeMessage:function(){var a=this.$el.find("#message-container");a.html(null)},toString:function(){var a=this.model.get("name")||"";return"HistoryPanel("+a+")"}});HistoryPanel.templates={historyPanel:Handlebars.templates["template-history-historyPanel"]};
\ No newline at end of file
+var HistoryPanel=Backbone.View.extend(LoggableMixin).extend({el:"body.historyPage",HDAView:HDAEditView,events:{"click #history-tag":"loadAndDisplayTags","click #message-container":"removeMessage"},initialize:function(a){if(a.logger){this.logger=this.model.logger=a.logger}this.log(this+".initialize:",a);if(!a.urlTemplates){throw (this+" needs urlTemplates on initialize")}if(!a.urlTemplates.history){throw (this+" needs urlTemplates.history on initialize")}if(!a.urlTemplates.hda){throw (this+" needs urlTemplates.hda on initialize")}this.urlTemplates=a.urlTemplates.history;this.hdaUrlTemplates=a.urlTemplates.hda;this._setUpWebStorage(a.initiallyExpanded,a.show_deleted,a.show_hidden);this._setUpEventHandlers();this.hdaViews={};this.urls={}},_setUpEventHandlers:function(){this.model.bind("change:nice_size",this.updateHistoryDiskSize,this);this.model.bind("error",function(d,c,b,a){this.displayMessage("error",d);this.model.attributes.error=undefined},this);this.model.hdas.bind("add",this.add,this);this.model.hdas.bind("reset",this.addAll,this);this.model.hdas.bind("change:deleted",this.handleHdaDeletionChange,this);this.model.hdas.bind("change:purged",function(a){this.model.fetch()},this);this.model.hdas.bind("state:ready",function(b,c,a){if((!b.get("visible"))&&(!this.storage.get("show_hidden"))){this.removeHdaView(b.get("id"))}},this);this.bind("error",function(d,c,b,a){this.displayMessage("error",d)});if(this.logger){this.bind("all",function(a){this.log(this+"",arguments)},this)}},_setUpWebStorage:function(b,a,c){this.storage=new PersistantStorage("HistoryView."+this.model.get("id"),{expandedHdas:{},show_deleted:false,show_hidden:false});this.log(this+" (prev) storage:",JSON.stringify(this.storage.get(),null,2));if(b){this.storage.set("exandedHdas",b)}if((a===true)||(a===false)){this.storage.set("show_deleted",a)}if((c===true)||(c===false)){this.storage.set("show_hidden",c)}this.show_deleted=this.storage.get("show_deleted");this.show_hidden=this.storage.get("show_hidden");this.log(this+" (init'd) storage:",this.storage.get())},add:function(a){this.render()},addAll:function(){this.render()},handleHdaDeletionChange:function(a){if(a.get("deleted")&&!this.storage.get("show_deleted")){this.removeHdaView(a.get("id"))}},removeHdaView:function(c,b){var a=this.hdaViews[c];if(!a){return}a.remove(b);delete this.hdaViews[c];if(_.isEmpty(this.hdaViews)){this.render()}},render:function(){var b=this,d=b.toString()+".set-up",c=$("<div/>"),a=this.model.toJSON(),e=(this.$el.children().size()===0);a.urls=this._renderUrls(a);c.append(HistoryPanel.templates.historyPanel(a));c.find(".tooltip").tooltip({placement:"bottom"});if(!this.model.hdas.length||!this.renderItems(c.find("#"+this.model.get("id")+"-datasets"))){c.find("#emptyHistoryMessage").show()}$(b).queue(d,function(f){b.$el.fadeOut("fast",function(){f()})});$(b).queue(d,function(f){b.$el.html("");b.$el.append(c.children());b.$el.fadeIn("fast",function(){f()})});$(b).queue(d,function(f){this.log(b+" rendered:",b.$el);b._setUpBehaviours();if(e){b.trigger("rendered:initial")}else{b.trigger("rendered")}f()});$(b).dequeue(d);return this},_renderUrls:function(a){var b=this;b.urls={};_.each(this.urlTemplates,function(d,c){b.urls[c]=_.template(d,a)});return b.urls},renderItems:function(b){this.hdaViews={};var a=this,c=this.model.hdas.getVisible(this.storage.get("show_deleted"),this.storage.get("show_hidden"));_.each(c,function(f){var e=f.get("id"),d=a.storage.get("expandedHdas").get(e);a.hdaViews[e]=new a.HDAView({model:f,expanded:d,urlTemplates:a.hdaUrlTemplates,logger:a.logger});a._setUpHdaListeners(a.hdaViews[e]);b.prepend(a.hdaViews[e].render().$el)});return c.length},_setUpHdaListeners:function(b){var a=this;b.bind("body-expanded",function(c){a.storage.get("expandedHdas").set(c,true)});b.bind("body-collapsed",function(c){a.storage.get("expandedHdas").deleteKey(c)});b.bind("error",function(f,e,c,d){a.displayMessage("error",f)})},_setUpBehaviours:function(){if(!(this.model.get("user")&&this.model.get("user").email)){return}var a=this.$("#history-annotation-area");this.$("#history-annotate").click(function(){if(a.is(":hidden")){a.slideDown("fast")}else{a.slideUp("fast")}return false});async_save_text("history-name-container","history-name",this.urls.rename,"new_name",18);async_save_text("history-annotation-container","history-annotation",this.urls.annotate,"new_annotation",18,true,4)},updateHistoryDiskSize:function(){this.$el.find("#history-size").text(this.model.get("nice_size"))},showQuotaMessage:function(){var a=this.$el.find("#quota-message-container");if(a.is(":hidden")){a.slideDown("fast")}},hideQuotaMessage:function(){var a=this.$el.find("#quota-message-container");if(!a.is(":hidden")){a.slideUp("fast")}},toggleShowDeleted:function(){this.storage.set("show_deleted",!this.storage.get("show_deleted"));this.render();return this.storage.get("show_deleted")},toggleShowHidden:function(){this.storage.set("show_hidden",!this.storage.get("show_hidden"));this.render();return this.storage.get("show_hidden")},collapseAllHdaBodies:function(){_.each(this.hdaViews,function(a){a.toggleBodyVisibility(null,false)});this.storage.set("expandedHdas",{})},loadAndDisplayTags:function(d){this.log(this+".loadAndDisplayTags",d);var b=this,e=this.$el.find("#history-tag-area"),c=e.find(".tag-elt");this.log("\t tagArea",e," tagElt",c);if(e.is(":hidden")){if(!jQuery.trim(c.html())){var a=this;$.ajax({url:a.urls.tag,error:function(h,g,f){b.log("Error loading tag area html",h,g,f);b.trigger("error",_l("Tagging failed"),h,g,f)},success:function(f){c.html(f);c.find(".tooltip").tooltip();e.slideDown("fast")}})}else{e.slideDown("fast")}}else{e.slideUp("fast")}return false},displayMessage:function(c,d){var b=this.$el.find("#message-container"),a=$("<div/>").addClass(c+"message").text(d);b.html(a)},removeMessage:function(){var a=this.$el.find("#message-container");a.html(null)},scrollToTop:function(){$(document).scrollTop(0);return this},scrollIntoView:function(b,c){if(!c){$(document).scrollTop(b);return this}var a=window,d=this.$el.parent(),f=$(a).innerHeight(),e=(f/2)-(c/2);$(d).scrollTop(b-e);return this},scrollToId:function(b){if((!b)||(!this.hdaViews[b])){return this}var a=this.hdaViews[b].$el;this.scrollIntoView(a.offset().top,a.outerHeight());return this},scrollToHid:function(a){var b=this.model.hdas.getByHid(a);if(!b){return this}return this.scrollToId(b.id)},toString:function(){var a=this.model.get("name")||"";return"HistoryPanel("+a+")"}});HistoryPanel.templates={historyPanel:Handlebars.templates["template-history-historyPanel"]};
\ No newline at end of file
diff -r b9bd0fae39cabc1ff55f374e026b7aa3f5687c77 -r 7f70ea89d5a92cba463b873de7535766bb8c7050 static/scripts/packed/viz/trackster/painters.js
--- a/static/scripts/packed/viz/trackster/painters.js
+++ b/static/scripts/packed/viz/trackster/painters.js
@@ -1,1 +1,1 @@
-define(["libs/underscore"],function(_){var extend=_.extend;var BEFORE=1001,CONTAINS=1002,OVERLAP_START=1003,OVERLAP_END=1004,CONTAINED_BY=1005,AFTER=1006;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=BEFORE}else{if(first_end<=second_end){overlap=OVERLAP_START}else{overlap=CONTAINS}}}else{if(first_start>second_end){overlap=AFTER}else{if(first_end<=second_end){overlap=CONTAINED_BY}else{overlap=OVERLAP_END}}}return overlap};var is_overlap=function(first_region,second_region){var overlap=compute_overlap(first_region,second_region);return(overlap!==BEFORE&&overlap!==AFTER)};var dashedLine=function(ctx,x1,y1,x2,y2,dashLen){if(dashLen===undefined){dashLen=4}var dX=x2-x1;var dY=y2-y1;var dashes=Math.floor(Math.sqrt(dX*dX+dY*dY)/dashLen);var dashX=dX/dashes;var dashY=dY/dashes;var q;for(q=0;q<dashes;q++,x1+=dashX,y1+=dashY){if(q%2!==0){continue}ctx.fillRect(x1,y1,dashLen,1)}};var drawDownwardEquilateralTriangle=function(ctx,down_vertex_x,down_vertex_y,side_len){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);ctx.beginPath();ctx.moveTo(x1,y);ctx.lineTo(x2,y);ctx.lineTo(down_vertex_x,down_vertex_y);ctx.lineTo(x1,y);ctx.strokeStyle=this.fillStyle;ctx.fill();ctx.stroke();ctx.closePath()};var Scaler=function(default_val){this.default_val=(default_val?default_val:1)};Scaler.prototype.gen_val=function(input){return this.default_val};var Painter=function(data,view_start,view_end,prefs,mode){this.data=data;this.view_start=view_start;this.view_end=view_end;this.prefs=extend({},this.default_prefs,prefs);this.mode=mode};Painter.prototype.default_prefs={};Painter.prototype.draw=function(ctx,width,height,w_scale){};var SummaryTreePainter=function(data,view_start,view_end,prefs,mode){Painter.call(this,data,view_start,view_end,prefs,mode)};SummaryTreePainter.prototype.default_prefs={show_counts:false};SummaryTreePainter.prototype.draw=function(ctx,width,height,w_scale){var view_start=this.view_start,points=this.data.data,max=(this.prefs.histogram_max?this.prefs.histogram_max:this.data.max),base_y=height;delta_x_px=Math.ceil(this.data.delta*w_scale);ctx.save();for(var i=0,len=points.length;i<len;i++){var x=Math.floor((points[i][0]-view_start)*w_scale);var y=points[i][1];if(!y){continue}var y_px=y/max*height;if(y!==0&&y_px<1){y_px=1}ctx.fillStyle=this.prefs.block_color;ctx.fillRect(x,base_y-y_px,delta_x_px,y_px);var text_padding_req_x=4;if(this.prefs.show_counts&&(ctx.measureText(y).width+text_padding_req_x)<delta_x_px){ctx.fillStyle=this.prefs.label_color;ctx.textAlign="center";ctx.fillText(y,x+(delta_x_px/2),10)}}ctx.restore()};var LinePainter=function(data,view_start,view_end,prefs,mode){Painter.call(this,data,view_start,view_end,prefs,mode);var i,len;if(this.prefs.min_value===undefined){var min_value=Infinity;for(i=0,len=this.data.length;i<len;i++){min_value=Math.min(min_value,this.data[i][1])}this.prefs.min_value=min_value}if(this.prefs.max_value===undefined){var max_value=-Infinity;for(i=0,len=this.data.length;i<len;i++){max_value=Math.max(max_value,this.data[i][1])}this.prefs.max_value=max_value}};LinePainter.prototype.default_prefs={min_value:undefined,max_value:undefined,mode:"Histogram",color:"#000",overflow_color:"#F66"};LinePainter.prototype.draw=function(ctx,width,height,w_scale){var in_path=false,min_value=this.prefs.min_value,max_value=this.prefs.max_value,vertical_range=max_value-min_value,height_px=height,view_start=this.view_start,mode=this.mode,data=this.data;ctx.save();var y_zero=Math.round(height+min_value/vertical_range*height);if(mode!=="Intensity"){ctx.fillStyle="#aaa";ctx.fillRect(0,y_zero,width,1)}ctx.beginPath();var x_scaled,y,delta_x_px;if(data.length>1){delta_x_px=Math.ceil((data[1][0]-data[0][0])*w_scale)}else{delta_x_px=10}var pref_color=parseInt(this.prefs.color.slice(1),16),pref_r=(pref_color&16711680)>>16,pref_g=(pref_color&65280)>>8,pref_b=pref_color&255;for(var i=0,len=data.length;i<len;i++){ctx.fillStyle=ctx.strokeStyle=this.prefs.color;x_scaled=Math.round((data[i][0]-view_start-0.5)*w_scale);y=data[i][1];var top_overflow=false,bot_overflow=false;if(y===null){if(in_path&&mode==="Filled"){ctx.lineTo(x_scaled,height_px)}in_path=false;continue}if(y<min_value){bot_overflow=true;y=min_value}else{if(y>max_value){top_overflow=true;y=max_value}}if(mode==="Histogram"){y=Math.round(y/vertical_range*height_px);ctx.fillRect(x_scaled,y_zero,delta_x_px,-y)}else{if(mode==="Intensity"){var saturation=(y-min_value)/vertical_range,new_r=Math.round(pref_r+(255-pref_r)*(1-saturation)),new_g=Math.round(pref_g+(255-pref_g)*(1-saturation)),new_b=Math.round(pref_b+(255-pref_b)*(1-saturation));ctx.fillStyle="rgb("+new_r+","+new_g+","+new_b+")";ctx.fillRect(x_scaled,0,delta_x_px,height_px)}else{y=Math.round(height_px-(y-min_value)/vertical_range*height_px);if(in_path){ctx.lineTo(x_scaled,y)}else{in_path=true;if(mode==="Filled"){ctx.moveTo(x_scaled,height_px);ctx.lineTo(x_scaled,y)}else{ctx.moveTo(x_scaled,y)}}}}ctx.fillStyle=this.prefs.overflow_color;if(top_overflow||bot_overflow){var overflow_x;if(mode==="Histogram"||mode==="Intensity"){overflow_x=delta_x_px}else{x_scaled-=2;overflow_x=4}if(top_overflow){ctx.fillRect(x_scaled,0,overflow_x,3)}if(bot_overflow){ctx.fillRect(x_scaled,height_px-3,overflow_x,3)}}ctx.fillStyle=this.prefs.color}if(mode==="Filled"){if(in_path){ctx.lineTo(x_scaled,y_zero);ctx.lineTo(0,y_zero)}ctx.fill()}else{ctx.stroke()}ctx.restore()};var FeaturePositionMapper=function(slot_height){this.feature_positions={};this.slot_height=slot_height;this.translation=0;this.y_translation=0};FeaturePositionMapper.prototype.map_feature_data=function(feature_data,slot,x_start,x_end){if(!this.feature_positions[slot]){this.feature_positions[slot]=[]}this.feature_positions[slot].push({data:feature_data,x_start:x_start,x_end:x_end})};FeaturePositionMapper.prototype.get_feature_data=function(x,y){var slot=Math.floor((y-this.y_translation)/this.slot_height),feature_dict;if(!this.feature_positions[slot]){return null}x+=this.translation;for(var i=0;i<this.feature_positions[slot].length;i++){feature_dict=this.feature_positions[slot][i];if(x>=feature_dict.x_start&&x<=feature_dict.x_end){return feature_dict.data}}};var FeaturePainter=function(data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler){Painter.call(this,data,view_start,view_end,prefs,mode);this.alpha_scaler=(alpha_scaler?alpha_scaler:new Scaler());this.height_scaler=(height_scaler?height_scaler:new Scaler())};FeaturePainter.prototype.default_prefs={block_color:"#FFF",connector_color:"#FFF"};extend(FeaturePainter.prototype,{get_required_height:function(rows_required,width){var required_height=this.get_row_height(),y_scale=required_height,mode=this.mode;if(mode==="no_detail"||mode==="Squish"||mode==="Pack"){required_height=rows_required*y_scale}return required_height+this.get_top_padding(width)+this.get_bottom_padding(width)},get_top_padding:function(width){return 0},get_bottom_padding:function(width){return Math.max(Math.round(this.get_row_height()/2),5)},draw:function(ctx,width,height,w_scale,slots){var data=this.data,view_start=this.view_start,view_end=this.view_end;ctx.save();ctx.fillStyle=this.prefs.block_color;ctx.textAlign="right";var y_scale=this.get_row_height(),feature_mapper=new FeaturePositionMapper(y_scale),x_draw_coords;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],slot=(slots&&slots[feature_uid]!==undefined?slots[feature_uid]:null);if((feature_start<view_end&&feature_end>view_start)&&(this.mode==="Dense"||slot!==null)){x_draw_coords=this.draw_element(ctx,this.mode,feature,slot,view_start,view_end,w_scale,y_scale,width);feature_mapper.map_feature_data(feature,slot,x_draw_coords[0],x_draw_coords[1])}}ctx.restore();feature_mapper.y_translation=this.get_top_padding(width);return feature_mapper},draw_element:function(ctx,mode,feature,slot,tile_low,tile_high,w_scale,y_scale,width){console.log("WARNING: Unimplemented function.");return[0,0]}});var DENSE_TRACK_HEIGHT=10,NO_DETAIL_TRACK_HEIGHT=3,SQUISH_TRACK_HEIGHT=5,PACK_TRACK_HEIGHT=10,NO_DETAIL_FEATURE_HEIGHT=1,DENSE_FEATURE_HEIGHT=9,SQUISH_FEATURE_HEIGHT=3,PACK_FEATURE_HEIGHT=9,LABEL_SPACING=2,CONNECTOR_COLOR="#ccc";var LinkedFeaturePainter=function(data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler){FeaturePainter.call(this,data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler);this.draw_background_connector=true;this.draw_individual_connectors=false};extend(LinkedFeaturePainter.prototype,FeaturePainter.prototype,{get_row_height:function(){var mode=this.mode,height;if(mode==="Dense"){height=DENSE_TRACK_HEIGHT}else{if(mode==="no_detail"){height=NO_DETAIL_TRACK_HEIGHT}else{if(mode==="Squish"){height=SQUISH_TRACK_HEIGHT}else{height=PACK_TRACK_HEIGHT}}}return height},draw_element:function(ctx,mode,feature,slot,tile_low,tile_high,w_scale,y_scale,width){var feature_uid=feature[0],feature_start=feature[1],feature_end=feature[2],feature_name=feature[3],feature_strand=feature[4],f_start=Math.floor(Math.max(0,(feature_start-tile_low-0.5)*w_scale)),f_end=Math.ceil(Math.min(width,Math.max(0,(feature_end-tile_low-0.5)*w_scale))),draw_start=f_start,draw_end=f_end,y_center=(mode==="Dense"?0:(0+slot))*y_scale+this.get_top_padding(width),thickness,y_start,thick_start=null,thick_end=null,block_color=(!feature_strand||feature_strand==="+"||feature_strand==="."?this.prefs.block_color:this.prefs.reverse_strand_color);label_color=this.prefs.label_color;ctx.globalAlpha=this.alpha_scaler.gen_val(feature);if(mode==="Dense"){slot=1}if(mode==="no_detail"){ctx.fillStyle=block_color;ctx.fillRect(f_start,y_center+5,f_end-f_start,NO_DETAIL_FEATURE_HEIGHT)}else{var feature_ts=feature[5],feature_te=feature[6],feature_blocks=feature[7],full_height=true;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)))}var thin_height,thick_height;if(mode==="Squish"){thin_height=1;thick_height=SQUISH_FEATURE_HEIGHT;full_height=false}else{if(mode==="Dense"){thin_height=5;thick_height=DENSE_FEATURE_HEIGHT}else{thin_height=5;thick_height=PACK_FEATURE_HEIGHT}}if(!feature_blocks){ctx.fillStyle=block_color;ctx.fillRect(f_start,y_center+1,f_end-f_start,thick_height);if(feature_strand&&full_height){if(feature_strand==="+"){ctx.fillStyle=ctx.canvas.manager.get_pattern("right_strand_inv")}else{if(feature_strand==="-"){ctx.fillStyle=ctx.canvas.manager.get_pattern("left_strand_inv")}}ctx.fillRect(f_start,y_center+1,f_end-f_start,thick_height)}}else{var cur_y_center,cur_height;if(mode==="Squish"||mode==="Dense"){cur_y_center=y_center+Math.floor(SQUISH_FEATURE_HEIGHT/2)+1;cur_height=1}else{if(feature_strand){cur_y_center=y_center;cur_height=thick_height}else{cur_y_center+=(SQUISH_FEATURE_HEIGHT/2)+1;cur_height=1}}if(this.draw_background_connector){if(mode==="Squish"||mode==="Dense"){ctx.fillStyle=CONNECTOR_COLOR}else{if(feature_strand){if(feature_strand==="+"){ctx.fillStyle=ctx.canvas.manager.get_pattern("right_strand")}else{if(feature_strand==="-"){ctx.fillStyle=ctx.canvas.manager.get_pattern("left_strand")}}}else{ctx.fillStyle=CONNECTOR_COLOR}}ctx.fillRect(f_start,cur_y_center,f_end-f_start,cur_height)}var start_and_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-0.5)*w_scale)),block_end=Math.ceil(Math.min(width,Math.max((block[1]-tile_low-0.5)*w_scale))),last_block_start,last_block_end;if(block_start>block_end){continue}ctx.fillStyle=block_color;ctx.fillRect(block_start,y_center+(thick_height-thin_height)/2+1,block_end-block_start,thin_height);if(thick_start!==undefined&&feature_te>feature_ts&&!(block_start>thick_end||block_end<thick_start)){var block_thick_start=Math.max(block_start,thick_start),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&&mode==="Pack"){if(feature_strand==="+"){ctx.fillStyle=ctx.canvas.manager.get_pattern("right_strand_inv")}else{if(feature_strand==="-"){ctx.fillStyle=ctx.canvas.manager.get_pattern("left_strand_inv")}}if(block_thick_start+14<block_thick_end){block_thick_start+=2;block_thick_end-=2}ctx.fillRect(block_thick_start,y_center+1,block_thick_end-block_thick_start,thick_height)}}if(this.draw_individual_connectors&&last_block_start){this.draw_connector(ctx,last_block_start,last_block_end,block_start,block_end,y_center)}last_block_start=block_start;last_block_end=block_end}if(mode==="Pack"){ctx.globalAlpha=1;ctx.fillStyle="white";var hscale_factor=this.height_scaler.gen_val(feature),new_height=Math.ceil(thick_height*hscale_factor),ws_height=Math.round((thick_height-new_height)/2);if(hscale_factor!==1){ctx.fillRect(f_start,cur_y_center+1,f_end-f_start,ws_height);ctx.fillRect(f_start,cur_y_center+thick_height-ws_height+1,f_end-f_start,ws_height)}}}ctx.globalAlpha=1;if(feature_name&&mode==="Pack"&&feature_start>tile_low){ctx.fillStyle=label_color;if(tile_low===0&&f_start-ctx.measureText(feature_name).width<0){ctx.textAlign="left";ctx.fillText(feature_name,f_end+LABEL_SPACING,y_center+8);draw_end+=ctx.measureText(feature_name).width+LABEL_SPACING}else{ctx.textAlign="right";ctx.fillText(feature_name,f_start-LABEL_SPACING,y_center+8);draw_start-=ctx.measureText(feature_name).width+LABEL_SPACING}}}ctx.globalAlpha=1;return[draw_start,draw_end]}});var ReadPainter=function(data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler,ref_seq,base_color_fn){FeaturePainter.call(this,data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler);this.ref_seq=(ref_seq?ref_seq.data:null);this.base_color_fn=base_color_fn};extend(ReadPainter.prototype,FeaturePainter.prototype,{get_row_height:function(){var height,mode=this.mode;if(mode==="Dense"){height=DENSE_TRACK_HEIGHT}else{if(mode==="Squish"){height=SQUISH_TRACK_HEIGHT}else{height=PACK_TRACK_HEIGHT;if(this.prefs.show_insertions){height*=2}}}return height},_parse_cigar:function(cigar_str){var cigar_ops="MIDNSHP=X";var blocks=[[0,0]],cur_block=blocks[0],base_pos=0,parsed_cigar=_.map(cigar_str.match(/[0-9]+[MIDNSHP=X]/g),function(op){var op_len=parseInt(op.slice(0,-1),10),op_char=op.slice(-1);if(op_char==="N"){if(cur_block[1]!==0){cur_block=[base_pos+op_len,base_pos+op_len];blocks.push(cur_block)}}else{if("ISHP".indexOf(op_char)===-1){cur_block[1]+=op_len;base_pos+=op_len}}return[cigar_ops.indexOf(op_char),op_len]});return{blocks:blocks,cigar:parsed_cigar}},draw_read:function(ctx,mode,w_scale,y_center,tile_low,tile_high,feature_start,cigar,strand,read_seq){ctx.textAlign="center";var tile_region=[tile_low,tile_high],base_offset=0,seq_offset=0,gap=Math.round(w_scale/2),char_width_px=ctx.canvas.manager.char_width_px,block_color=(strand==="+"?this.prefs.block_color:this.prefs.reverse_strand_color),pack_mode=(mode==="Pack");var draw_last=[];if(!cigar){cigar=[[0,read_seq.length]]}for(var cig_id=0,len=cigar.length;cig_id<len;cig_id++){var cig=cigar[cig_id],cig_op="MIDNSHP=X"[cig[0]],cig_len=cig[1];var seq_start=feature_start+base_offset,s_start=Math.floor(Math.max(-0.5*w_scale,(seq_start-tile_low-0.5)*w_scale)),s_end=Math.floor(Math.max(0,(seq_start+cig_len-tile_low-0.5)*w_scale));if(s_start===s_end){s_end+=1}switch(cig_op){case"H":break;case"S":seq_offset+=cig_len;break;case"M":case"=":case"X":if(is_overlap([seq_start,seq_start+cig_len],tile_region)){ctx.fillStyle=block_color;ctx.fillRect(s_start,y_center+(pack_mode?1:4),s_end-s_start,(pack_mode?PACK_FEATURE_HEIGHT:SQUISH_FEATURE_HEIGHT));var seq=read_seq.slice(seq_offset,seq_offset+cig_len),ref_char,read_char;for(var c=0,str_len=seq.length;c<str_len;c++){if(seq_start+c>=tile_low&&seq_start+c<=tile_high){ref_char=(this.ref_seq?this.ref_seq[seq_start-tile_low+c]:null);read_char=seq[c];if((ref_char&&(!this.prefs.show_differences||(read_char.toLowerCase!=="n"&&(ref_char.toLowerCase()!==read_char.toLowerCase()))))||(!ref_char&&!this.prefs.show_differences)){var c_start=Math.floor(Math.max(0,(seq_start+c-tile_low)*w_scale));ctx.fillStyle=this.base_color_fn(seq[c]);if(pack_mode&&w_scale>char_width_px){ctx.fillText(seq[c],c_start,y_center+9)}else{if(w_scale>0.05){ctx.fillRect(c_start,y_center+(pack_mode?1:4),Math.max(1,Math.round(w_scale)),(pack_mode?PACK_FEATURE_HEIGHT:SQUISH_FEATURE_HEIGHT))}}}}}}seq_offset+=cig_len;base_offset+=cig_len;break;case"N":ctx.fillStyle=CONNECTOR_COLOR;ctx.fillRect(s_start,y_center+5,s_end-s_start,1);base_offset+=cig_len;break;case"D":ctx.fillStyle="black";ctx.fillRect(s_start,y_center+4,s_end-s_start,3);base_offset+=cig_len;break;case"P":break;case"I":var insert_x_coord=s_start-gap;if(is_overlap([seq_start,seq_start+cig_len],tile_region)){var seq=read_seq.slice(seq_offset,seq_offset+cig_len);if(this.prefs.show_insertions){var x_center=s_start-(s_end-s_start)/2;if((mode==="Pack"||this.mode==="Auto")&&read_seq!==undefined&&w_scale>char_width_px){ctx.fillStyle="yellow";ctx.fillRect(x_center-gap,y_center-9,s_end-s_start,9);draw_last[draw_last.length]={type:"triangle",data:[insert_x_coord,y_center+4,5]};ctx.fillStyle=CONNECTOR_COLOR;switch(compute_overlap([seq_start,seq_start+cig_len],tile_region)){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):break;case (CONTAINS):seq=seq.slice(tile_low-seq_start,seq_start-tile_high);break}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-(s_end-s_start)/2,y_center)}}else{ctx.fillStyle="yellow";ctx.fillRect(x_center,y_center+(this.mode!=="Dense"?2:5),s_end-s_start,(mode!=="Dense"?SQUISH_FEATURE_HEIGHT:DENSE_FEATURE_HEIGHT))}}else{if((mode==="Pack"||this.mode==="Auto")&&read_seq!==undefined&&w_scale>char_width_px){draw_last.push({type:"text",data:[seq.length,insert_x_coord,y_center+9]})}else{}}}seq_offset+=cig_len;break}}ctx.fillStyle="yellow";var item,type,data;for(var i=0;i<draw_last.length;i++){item=draw_last[i];type=item.type;data=item.data;if(type==="text"){ctx.save();ctx.font="bold "+ctx.font;ctx.fillText(data[0],data[1],data[2]);ctx.restore()}else{if(type==="triangle"){drawDownwardEquilateralTriangle(ctx,data[0],data[1],data[2])}}}},draw_element:function(ctx,mode,feature,slot,tile_low,tile_high,w_scale,y_scale,width){var feature_uid=feature[0],feature_start=feature[1],feature_end=feature[2],feature_name=feature[3],f_start=Math.floor(Math.max(-0.5*w_scale,(feature_start-tile_low-0.5)*w_scale)),f_end=Math.ceil(Math.min(width,Math.max(0,(feature_end-tile_low-0.5)*w_scale))),y_center=(mode==="Dense"?0:(0+slot))*y_scale,label_color=this.prefs.label_color;if(feature[5] instanceof Array){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))),connector=true;if(feature[4][1]>=tile_low&&feature[4][0]<=tile_high&&feature[4][2]){this.draw_read(ctx,mode,w_scale,y_center,tile_low,tile_high,feature[4][0],feature[4][2],feature[4][3],feature[4][4])}else{connector=false}if(feature[5][1]>=tile_low&&feature[5][0]<=tile_high&&feature[5][2]){this.draw_read(ctx,mode,w_scale,y_center,tile_low,tile_high,feature[5][0],feature[5][2],feature[5][3],feature[5][4])}else{connector=false}if(connector&&b2_start>b1_end){ctx.fillStyle=CONNECTOR_COLOR;dashedLine(ctx,b1_end,y_center+5,b2_start,y_center+5)}}else{this.draw_read(ctx,mode,w_scale,y_center,tile_low,tile_high,feature_start,feature[4],feature[5],feature[6])}if(mode==="Pack"&&feature_start>=tile_low&&feature_name!=="."){ctx.fillStyle=this.prefs.label_color;if(tile_low===0&&f_start-ctx.measureText(feature_name).width<0){ctx.textAlign="left";ctx.fillText(feature_name,f_end+LABEL_SPACING,y_center+8)}else{ctx.textAlign="right";ctx.fillText(feature_name,f_start-LABEL_SPACING,y_center+8)}}return[0,0]}});var RefBasedReadPainter=function(data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler,ref_seq,base_color_fn){ReadPainter.call(this,data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler,ref_seq,base_color_fn)};extend(RefBasedReadPainter.prototype,ReadPainter.prototype,FeaturePainter,{draw_read:function(ctx,mode,w_scale,y_center,tile_low,tile_high,feature_start,cigar,strand,read_seq){ctx.textAlign="center";var tile_region=[tile_low,tile_high],base_offset=0,seq_offset=0,gap=Math.round(w_scale/2),char_width_px=ctx.canvas.manager.char_width_px,block_color=(strand==="+"?this.prefs.block_color:this.prefs.reverse_strand_color),pack_mode=(mode==="Pack"),drawing_blocks=[];var draw_last=[];var t=this._parse_cigar(cigar);cigar=t.cigar;drawing_blocks=t.blocks;for(var i=0;i<drawing_blocks.length;i++){var block=drawing_blocks[i];if(is_overlap([feature_start+block[0],feature_start+block[1]],tile_region)){var s_start=Math.floor(Math.max(-0.5*w_scale,(feature_start+block[0]-tile_low-0.5)*w_scale)),s_end=Math.floor(Math.max(0,(feature_start+block[1]-tile_low-0.5)*w_scale));if(s_start===s_end){s_end+=1}ctx.fillStyle=block_color;ctx.fillRect(s_start,y_center+(pack_mode?1:4),s_end-s_start,(pack_mode?PACK_FEATURE_HEIGHT:SQUISH_FEATURE_HEIGHT))}}for(var cig_id=0,len=cigar.length;cig_id<len;cig_id++){var cig=cigar[cig_id],cig_op="MIDNSHP=X"[cig[0]],cig_len=cig[1];var seq_start=feature_start+base_offset,s_start=Math.floor(Math.max(0,-0.5*w_scale,(seq_start-tile_low-0.5)*w_scale)),s_end=Math.floor(Math.max(0,(seq_start+cig_len-tile_low-0.5)*w_scale));if(s_start===s_end){s_end+=1}switch(cig_op){case"H":case"S":case"P":break;case"M":base_offset+=cig_len;break;case"=":case"X":if(is_overlap([seq_start,seq_start+cig_len],tile_region)){var cur_seq="";if(cig_op==="X"){cur_seq=read_seq.slice(seq_offset,seq_offset+cig_len)}else{if(this.ref_seq){cur_seq=this.ref_seq.slice(Math.max(0,seq_start-tile_low),Math.min(seq_start-tile_low+cig_len,tile_high-tile_low))}}var start_pos=Math.max(seq_start,tile_low);for(var c=0;c<cur_seq.length;c++){if(cur_seq&&!this.prefs.show_differences||cig_op==="X"){var c_start=Math.floor(Math.max(0,(start_pos+c-tile_low)*w_scale));ctx.fillStyle=this.base_color_fn(cur_seq[c]);if(pack_mode&&w_scale>char_width_px){ctx.fillText(cur_seq[c],c_start,y_center+9)}else{if(w_scale>0.05){ctx.fillRect(c_start,y_center+(pack_mode?1:4),Math.max(1,Math.round(w_scale)),(pack_mode?PACK_FEATURE_HEIGHT:SQUISH_FEATURE_HEIGHT))}}}}}if(cig_op==="X"){seq_offset+=cig_len}base_offset+=cig_len;break;case"N":ctx.fillStyle=CONNECTOR_COLOR;ctx.fillRect(s_start,y_center+5,s_end-s_start,1);base_offset+=cig_len;break;case"D":ctx.fillStyle="black";ctx.fillRect(s_start,y_center+4,s_end-s_start,3);base_offset+=cig_len;break;case"I":var insert_x_coord=s_start-gap;if(is_overlap([seq_start,seq_start+cig_len],tile_region)){var seq=read_seq.slice(seq_offset,seq_offset+cig_len);if(this.prefs.show_insertions){var x_center=s_start-(s_end-s_start)/2;if((mode==="Pack"||this.mode==="Auto")&&read_seq!==undefined&&w_scale>char_width_px){ctx.fillStyle="yellow";ctx.fillRect(x_center-gap,y_center-9,s_end-s_start,9);draw_last[draw_last.length]={type:"triangle",data:[insert_x_coord,y_center+4,5]};ctx.fillStyle=CONNECTOR_COLOR;switch(compute_overlap([seq_start,seq_start+cig_len],tile_region)){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):break;case (CONTAINS):seq=seq.slice(tile_low-seq_start,seq_start-tile_high);break}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-(s_end-s_start)/2,y_center)}}else{ctx.fillStyle="yellow";ctx.fillRect(x_center,y_center+(this.mode!=="Dense"?2:5),s_end-s_start,(mode!=="Dense"?SQUISH_FEATURE_HEIGHT:DENSE_FEATURE_HEIGHT))}}else{if((mode==="Pack"||this.mode==="Auto")&&read_seq!==undefined&&w_scale>char_width_px){draw_last.push({type:"text",data:[seq.length,insert_x_coord,y_center+9]})}else{}}}seq_offset+=cig_len;break}}ctx.fillStyle="yellow";var item,type,data;for(var i=0;i<draw_last.length;i++){item=draw_last[i];type=item.type;data=item.data;if(type==="text"){ctx.save();ctx.font="bold "+ctx.font;ctx.fillText(data[0],data[1],data[2]);ctx.restore()}else{if(type==="triangle"){drawDownwardEquilateralTriangle(ctx,data[0],data[1],data[2])}}}},});var ArcLinkedFeaturePainter=function(data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler){LinkedFeaturePainter.call(this,data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler);this.longest_feature_length=this.calculate_longest_feature_length();this.draw_background_connector=false;this.draw_individual_connectors=true};extend(ArcLinkedFeaturePainter.prototype,FeaturePainter.prototype,LinkedFeaturePainter.prototype,{calculate_longest_feature_length:function(){var longest_feature_length=0;for(var i=0,len=this.data.length;i<len;i++){var feature=this.data[i],feature_start=feature[1],feature_end=feature[2];longest_feature_length=Math.max(longest_feature_length,feature_end-feature_start)}return longest_feature_length},get_top_padding:function(width){var view_range=this.view_end-this.view_start,w_scale=width/view_range;return Math.min(128,Math.ceil((this.longest_feature_length/2)*w_scale))},draw_connector:function(ctx,block1_start,block1_end,block2_start,block2_end,y_center){var x_center=(block1_end+block2_start)/2,radius=block2_start-x_center;var angle1=Math.PI,angle2=0;if(radius>0){ctx.beginPath();ctx.arc(x_center,y_center,block2_start-x_center,Math.PI,0);ctx.stroke()}}});var Color=function(rgb,a){if(Array.isArray(rgb)){this.rgb=rgb}else{if(rgb.length==6){this.rgb=rgb.match(/.{2}/g).map(function(c){return parseInt(c,16)})}else{if(rgb.length==7){this.rgb=rgb.substring(1,7).match(/.{2}/g).map(function(c){return parseInt(c,16)})}else{this.rgb=rgb.split("").map(function(c){return parseInt(c+c,16)})}}}this.alpha=typeof(a)==="number"?a:1};Color.prototype={eval:function(){return this},toCSS:function(){if(this.alpha<1){return"rgba("+this.rgb.map(function(c){return Math.round(c)}).concat(this.alpha).join(", ")+")"}else{return"#"+this.rgb.map(function(i){i=Math.round(i);i=(i>255?255:(i<0?0:i)).toString(16);return i.length===1?"0"+i:i}).join("")}},toHSL:function(){var r=this.rgb[0]/255,g=this.rgb[1]/255,b=this.rgb[2]/255,a=this.alpha;var max=Math.max(r,g,b),min=Math.min(r,g,b);var h,s,l=(max+min)/2,d=max-min;if(max===min){h=s=0}else{s=l>0.5?d/(2-max-min):d/(max+min);switch(max){case r:h=(g-b)/d+(g<b?6:0);break;case g:h=(b-r)/d+2;break;case b:h=(r-g)/d+4;break}h/=6}return{h:h*360,s:s,l:l,a:a}},toARGB:function(){var argb=[Math.round(this.alpha*255)].concat(this.rgb);return"#"+argb.map(function(i){i=Math.round(i);i=(i>255?255:(i<0?0:i)).toString(16);return i.length===1?"0"+i:i}).join("")},mix:function(color2,weight){color1=this;var p=weight;var w=p*2-1;var a=color1.toHSL().a-color2.toHSL().a;var w1=(((w*a==-1)?w:(w+a)/(1+w*a))+1)/2;var w2=1-w1;var rgb=[color1.rgb[0]*w1+color2.rgb[0]*w2,color1.rgb[1]*w1+color2.rgb[1]*w2,color1.rgb[2]*w1+color2.rgb[2]*w2];var alpha=color1.alpha*p+color2.alpha*(1-p);return new Color(rgb,alpha)}};var LinearRamp=function(start_color,end_color,start_value,end_value){this.start_color=new Color(start_color);this.end_color=new Color(end_color);this.start_value=start_value;this.end_value=end_value;this.value_range=end_value-start_value};LinearRamp.prototype.map_value=function(value){value=Math.max(value,this.start_value);value=Math.min(value,this.end_value);value=(value-this.start_value)/this.value_range;return this.start_color.mix(this.end_color,1-value).toCSS()};var SplitRamp=function(start_color,middle_color,end_color,start_value,end_value){this.positive_ramp=new LinearRamp(middle_color,end_color,0,end_value);this.negative_ramp=new LinearRamp(middle_color,start_color,0,-start_value);this.start_value=start_value;this.end_value=end_value};SplitRamp.prototype.map_value=function(value){value=Math.max(value,this.start_value);value=Math.min(value,this.end_value);if(value>=0){return this.positive_ramp.map_value(value)}else{return this.negative_ramp.map_value(-value)}};var DiagonalHeatmapPainter=function(data,view_start,view_end,prefs,mode){Painter.call(this,data,view_start,view_end,prefs,mode);var i,len;if(this.prefs.min_value===undefined){var min_value=Infinity;for(i=0,len=this.data.length;i<len;i++){min_value=Math.min(min_value,this.data[i][5])}this.prefs.min_value=min_value}if(this.prefs.max_value===undefined){var max_value=-Infinity;for(i=0,len=this.data.length;i<len;i++){max_value=Math.max(max_value,this.data[i][5])}this.prefs.max_value=max_value}};DiagonalHeatmapPainter.prototype.default_prefs={min_value:undefined,max_value:undefined,mode:"Heatmap",pos_color:"#FF8C00",neg_color:"#4169E1"};DiagonalHeatmapPainter.prototype.draw=function(ctx,width,height,w_scale){var min_value=this.prefs.min_value,max_value=this.prefs.max_value,value_range=max_value-min_value,height_px=height,view_start=this.view_start,mode=this.mode,data=this.data,invsqrt2=1/Math.sqrt(2);var ramp=(new SplitRamp(this.prefs.neg_color,"#FFFFFF",this.prefs.pos_color,min_value,max_value));var d,s1,e1,s2,e2,value;var scale=function(p){return(p-view_start)*w_scale};ctx.save();ctx.rotate(-45*Math.PI/180);ctx.scale(invsqrt2,invsqrt2);for(var i=0,len=data.length;i<len;i++){d=data[i];s1=scale(d[1]);e1=scale(d[2]);s2=scale(d[4]);e2=scale(d[5]);value=d[6];ctx.fillStyle=(ramp.map_value(value));ctx.fillRect(s1,s2,(e1-s1),(e2-s2))}ctx.restore()};return{Scaler:Scaler,SummaryTreePainter:SummaryTreePainter,LinePainter:LinePainter,LinkedFeaturePainter:LinkedFeaturePainter,ReadPainter:ReadPainter,RefBasedReadPainter:RefBasedReadPainter,ArcLinkedFeaturePainter:ArcLinkedFeaturePainter,DiagonalHeatmapPainter:DiagonalHeatmapPainter}});
\ No newline at end of file
+define(["libs/underscore"],function(_){var extend=_.extend;var BEFORE=1001,CONTAINS=1002,OVERLAP_START=1003,OVERLAP_END=1004,CONTAINED_BY=1005,AFTER=1006;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=BEFORE}else{if(first_end<=second_end){overlap=OVERLAP_START}else{overlap=CONTAINS}}}else{if(first_start>second_end){overlap=AFTER}else{if(first_end<=second_end){overlap=CONTAINED_BY}else{overlap=OVERLAP_END}}}return overlap};var is_overlap=function(first_region,second_region){var overlap=compute_overlap(first_region,second_region);return(overlap!==BEFORE&&overlap!==AFTER)};var dashedLine=function(ctx,x1,y1,x2,y2,dashLen){if(dashLen===undefined){dashLen=4}var dX=x2-x1;var dY=y2-y1;var dashes=Math.floor(Math.sqrt(dX*dX+dY*dY)/dashLen);var dashX=dX/dashes;var dashY=dY/dashes;var q;for(q=0;q<dashes;q++,x1+=dashX,y1+=dashY){if(q%2!==0){continue}ctx.fillRect(x1,y1,dashLen,1)}};var drawDownwardEquilateralTriangle=function(ctx,down_vertex_x,down_vertex_y,side_len){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);ctx.beginPath();ctx.moveTo(x1,y);ctx.lineTo(x2,y);ctx.lineTo(down_vertex_x,down_vertex_y);ctx.lineTo(x1,y);ctx.strokeStyle=this.fillStyle;ctx.fill();ctx.stroke();ctx.closePath()};var Scaler=function(default_val){this.default_val=(default_val?default_val:1)};Scaler.prototype.gen_val=function(input){return this.default_val};var Painter=function(data,view_start,view_end,prefs,mode){this.data=data;this.view_start=view_start;this.view_end=view_end;this.prefs=extend({},this.default_prefs,prefs);this.mode=mode};Painter.prototype.default_prefs={};Painter.prototype.draw=function(ctx,width,height,w_scale){};var SummaryTreePainter=function(data,view_start,view_end,prefs,mode){Painter.call(this,data,view_start,view_end,prefs,mode)};SummaryTreePainter.prototype.default_prefs={show_counts:false};SummaryTreePainter.prototype.draw=function(ctx,width,height,w_scale){var view_start=this.view_start,points=this.data.data,max=(this.prefs.histogram_max?this.prefs.histogram_max:this.data.max),base_y=height,delta_x_px=Math.ceil(this.data.delta*w_scale);ctx.save();for(var i=0,len=points.length;i<len;i++){var x=Math.floor((points[i][0]-view_start)*w_scale);var y=points[i][1];if(!y){continue}var y_px=y/max*height;if(y!==0&&y_px<1){y_px=1}ctx.fillStyle=this.prefs.block_color;ctx.fillRect(x,base_y-y_px,delta_x_px,y_px);var text_padding_req_x=4;if(this.prefs.show_counts&&(ctx.measureText(y).width+text_padding_req_x)<delta_x_px){ctx.fillStyle=this.prefs.label_color;ctx.textAlign="center";ctx.fillText(y,x+(delta_x_px/2),10)}}ctx.restore()};var LinePainter=function(data,view_start,view_end,prefs,mode){Painter.call(this,data,view_start,view_end,prefs,mode);var i,len;if(this.prefs.min_value===undefined){var min_value=Infinity;for(i=0,len=this.data.length;i<len;i++){min_value=Math.min(min_value,this.data[i][1])}this.prefs.min_value=min_value}if(this.prefs.max_value===undefined){var max_value=-Infinity;for(i=0,len=this.data.length;i<len;i++){max_value=Math.max(max_value,this.data[i][1])}this.prefs.max_value=max_value}};LinePainter.prototype.default_prefs={min_value:undefined,max_value:undefined,mode:"Histogram",color:"#000",overflow_color:"#F66"};LinePainter.prototype.draw=function(ctx,width,height,w_scale){var in_path=false,min_value=this.prefs.min_value,max_value=this.prefs.max_value,vertical_range=max_value-min_value,height_px=height,view_start=this.view_start,mode=this.mode,data=this.data;ctx.save();var y_zero=Math.round(height+min_value/vertical_range*height);if(mode!=="Intensity"){ctx.fillStyle="#aaa";ctx.fillRect(0,y_zero,width,1)}ctx.beginPath();var x_scaled,y,delta_x_px;if(data.length>1){delta_x_px=Math.ceil((data[1][0]-data[0][0])*w_scale)}else{delta_x_px=10}var pref_color=parseInt(this.prefs.color.slice(1),16),pref_r=(pref_color&16711680)>>16,pref_g=(pref_color&65280)>>8,pref_b=pref_color&255;for(var i=0,len=data.length;i<len;i++){ctx.fillStyle=ctx.strokeStyle=this.prefs.color;x_scaled=Math.round((data[i][0]-view_start-0.5)*w_scale);y=data[i][1];var top_overflow=false,bot_overflow=false;if(y===null){if(in_path&&mode==="Filled"){ctx.lineTo(x_scaled,height_px)}in_path=false;continue}if(y<min_value){bot_overflow=true;y=min_value}else{if(y>max_value){top_overflow=true;y=max_value}}if(mode==="Histogram"){y=Math.round(y/vertical_range*height_px);ctx.fillRect(x_scaled,y_zero,delta_x_px,-y)}else{if(mode==="Intensity"){var saturation=(y-min_value)/vertical_range,new_r=Math.round(pref_r+(255-pref_r)*(1-saturation)),new_g=Math.round(pref_g+(255-pref_g)*(1-saturation)),new_b=Math.round(pref_b+(255-pref_b)*(1-saturation));ctx.fillStyle="rgb("+new_r+","+new_g+","+new_b+")";ctx.fillRect(x_scaled,0,delta_x_px,height_px)}else{y=Math.round(height_px-(y-min_value)/vertical_range*height_px);if(in_path){ctx.lineTo(x_scaled,y)}else{in_path=true;if(mode==="Filled"){ctx.moveTo(x_scaled,height_px);ctx.lineTo(x_scaled,y)}else{ctx.moveTo(x_scaled,y)}}}}ctx.fillStyle=this.prefs.overflow_color;if(top_overflow||bot_overflow){var overflow_x;if(mode==="Histogram"||mode==="Intensity"){overflow_x=delta_x_px}else{x_scaled-=2;overflow_x=4}if(top_overflow){ctx.fillRect(x_scaled,0,overflow_x,3)}if(bot_overflow){ctx.fillRect(x_scaled,height_px-3,overflow_x,3)}}ctx.fillStyle=this.prefs.color}if(mode==="Filled"){if(in_path){ctx.lineTo(x_scaled,y_zero);ctx.lineTo(0,y_zero)}ctx.fill()}else{ctx.stroke()}ctx.restore()};var FeaturePositionMapper=function(slot_height){this.feature_positions={};this.slot_height=slot_height;this.translation=0;this.y_translation=0};FeaturePositionMapper.prototype.map_feature_data=function(feature_data,slot,x_start,x_end){if(!this.feature_positions[slot]){this.feature_positions[slot]=[]}this.feature_positions[slot].push({data:feature_data,x_start:x_start,x_end:x_end})};FeaturePositionMapper.prototype.get_feature_data=function(x,y){var slot=Math.floor((y-this.y_translation)/this.slot_height),feature_dict;if(!this.feature_positions[slot]){return null}x+=this.translation;for(var i=0;i<this.feature_positions[slot].length;i++){feature_dict=this.feature_positions[slot][i];if(x>=feature_dict.x_start&&x<=feature_dict.x_end){return feature_dict.data}}};var FeaturePainter=function(data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler){Painter.call(this,data,view_start,view_end,prefs,mode);this.alpha_scaler=(alpha_scaler?alpha_scaler:new Scaler());this.height_scaler=(height_scaler?height_scaler:new Scaler())};FeaturePainter.prototype.default_prefs={block_color:"#FFF",connector_color:"#FFF"};extend(FeaturePainter.prototype,{get_required_height:function(rows_required,width){var required_height=this.get_row_height(),y_scale=required_height,mode=this.mode;if(mode==="no_detail"||mode==="Squish"||mode==="Pack"){required_height=rows_required*y_scale}return required_height+this.get_top_padding(width)+this.get_bottom_padding(width)},get_top_padding:function(width){return 0},get_bottom_padding:function(width){return Math.max(Math.round(this.get_row_height()/2),5)},draw:function(ctx,width,height,w_scale,slots){var data=this.data,view_start=this.view_start,view_end=this.view_end;ctx.save();ctx.fillStyle=this.prefs.block_color;ctx.textAlign="right";var y_scale=this.get_row_height(),feature_mapper=new FeaturePositionMapper(y_scale),x_draw_coords;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],slot=(slots&&slots[feature_uid]!==undefined?slots[feature_uid]:null);if((feature_start<view_end&&feature_end>view_start)&&(this.mode==="Dense"||slot!==null)){x_draw_coords=this.draw_element(ctx,this.mode,feature,slot,view_start,view_end,w_scale,y_scale,width);feature_mapper.map_feature_data(feature,slot,x_draw_coords[0],x_draw_coords[1])}}ctx.restore();feature_mapper.y_translation=this.get_top_padding(width);return feature_mapper},draw_element:function(ctx,mode,feature,slot,tile_low,tile_high,w_scale,y_scale,width){console.log("WARNING: Unimplemented function.");return[0,0]}});var DENSE_TRACK_HEIGHT=10,NO_DETAIL_TRACK_HEIGHT=3,SQUISH_TRACK_HEIGHT=5,PACK_TRACK_HEIGHT=10,NO_DETAIL_FEATURE_HEIGHT=1,DENSE_FEATURE_HEIGHT=9,SQUISH_FEATURE_HEIGHT=3,PACK_FEATURE_HEIGHT=9,LABEL_SPACING=2,CONNECTOR_COLOR="#ccc";var LinkedFeaturePainter=function(data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler){FeaturePainter.call(this,data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler);this.draw_background_connector=true;this.draw_individual_connectors=false};extend(LinkedFeaturePainter.prototype,FeaturePainter.prototype,{get_row_height:function(){var mode=this.mode,height;if(mode==="Dense"){height=DENSE_TRACK_HEIGHT}else{if(mode==="no_detail"){height=NO_DETAIL_TRACK_HEIGHT}else{if(mode==="Squish"){height=SQUISH_TRACK_HEIGHT}else{height=PACK_TRACK_HEIGHT}}}return height},draw_element:function(ctx,mode,feature,slot,tile_low,tile_high,w_scale,y_scale,width){var feature_uid=feature[0],feature_start=feature[1],feature_end=feature[2],feature_name=feature[3],feature_strand=feature[4],f_start=Math.floor(Math.max(0,(feature_start-tile_low-0.5)*w_scale)),f_end=Math.ceil(Math.min(width,Math.max(0,(feature_end-tile_low-0.5)*w_scale))),draw_start=f_start,draw_end=f_end,y_center=(mode==="Dense"?0:(0+slot))*y_scale+this.get_top_padding(width),thickness,y_start,thick_start=null,thick_end=null,block_color=(!feature_strand||feature_strand==="+"||feature_strand==="."?this.prefs.block_color:this.prefs.reverse_strand_color);label_color=this.prefs.label_color;ctx.globalAlpha=this.alpha_scaler.gen_val(feature);if(mode==="Dense"){slot=1}if(mode==="no_detail"){ctx.fillStyle=block_color;ctx.fillRect(f_start,y_center+5,f_end-f_start,NO_DETAIL_FEATURE_HEIGHT)}else{var feature_ts=feature[5],feature_te=feature[6],feature_blocks=feature[7],full_height=true;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)))}var thin_height,thick_height;if(mode==="Squish"){thin_height=1;thick_height=SQUISH_FEATURE_HEIGHT;full_height=false}else{if(mode==="Dense"){thin_height=5;thick_height=DENSE_FEATURE_HEIGHT}else{thin_height=5;thick_height=PACK_FEATURE_HEIGHT}}if(!feature_blocks){ctx.fillStyle=block_color;ctx.fillRect(f_start,y_center+1,f_end-f_start,thick_height);if(feature_strand&&full_height){if(feature_strand==="+"){ctx.fillStyle=ctx.canvas.manager.get_pattern("right_strand_inv")}else{if(feature_strand==="-"){ctx.fillStyle=ctx.canvas.manager.get_pattern("left_strand_inv")}}ctx.fillRect(f_start,y_center+1,f_end-f_start,thick_height)}}else{var cur_y_center,cur_height;if(mode==="Squish"||mode==="Dense"){cur_y_center=y_center+Math.floor(SQUISH_FEATURE_HEIGHT/2)+1;cur_height=1}else{if(feature_strand){cur_y_center=y_center;cur_height=thick_height}else{cur_y_center+=(SQUISH_FEATURE_HEIGHT/2)+1;cur_height=1}}if(this.draw_background_connector){if(mode==="Squish"||mode==="Dense"){ctx.fillStyle=CONNECTOR_COLOR}else{if(feature_strand){if(feature_strand==="+"){ctx.fillStyle=ctx.canvas.manager.get_pattern("right_strand")}else{if(feature_strand==="-"){ctx.fillStyle=ctx.canvas.manager.get_pattern("left_strand")}}}else{ctx.fillStyle=CONNECTOR_COLOR}}ctx.fillRect(f_start,cur_y_center,f_end-f_start,cur_height)}var start_and_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-0.5)*w_scale)),block_end=Math.ceil(Math.min(width,Math.max((block[1]-tile_low-0.5)*w_scale))),last_block_start,last_block_end;if(block_start>block_end){continue}ctx.fillStyle=block_color;ctx.fillRect(block_start,y_center+(thick_height-thin_height)/2+1,block_end-block_start,thin_height);if(thick_start!==undefined&&feature_te>feature_ts&&!(block_start>thick_end||block_end<thick_start)){var block_thick_start=Math.max(block_start,thick_start),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&&mode==="Pack"){if(feature_strand==="+"){ctx.fillStyle=ctx.canvas.manager.get_pattern("right_strand_inv")}else{if(feature_strand==="-"){ctx.fillStyle=ctx.canvas.manager.get_pattern("left_strand_inv")}}if(block_thick_start+14<block_thick_end){block_thick_start+=2;block_thick_end-=2}ctx.fillRect(block_thick_start,y_center+1,block_thick_end-block_thick_start,thick_height)}}if(this.draw_individual_connectors&&last_block_start){this.draw_connector(ctx,last_block_start,last_block_end,block_start,block_end,y_center)}last_block_start=block_start;last_block_end=block_end}if(mode==="Pack"){ctx.globalAlpha=1;ctx.fillStyle="white";var hscale_factor=this.height_scaler.gen_val(feature),new_height=Math.ceil(thick_height*hscale_factor),ws_height=Math.round((thick_height-new_height)/2);if(hscale_factor!==1){ctx.fillRect(f_start,cur_y_center+1,f_end-f_start,ws_height);ctx.fillRect(f_start,cur_y_center+thick_height-ws_height+1,f_end-f_start,ws_height)}}}ctx.globalAlpha=1;if(feature_name&&mode==="Pack"&&feature_start>tile_low){ctx.fillStyle=label_color;if(tile_low===0&&f_start-ctx.measureText(feature_name).width<0){ctx.textAlign="left";ctx.fillText(feature_name,f_end+LABEL_SPACING,y_center+8);draw_end+=ctx.measureText(feature_name).width+LABEL_SPACING}else{ctx.textAlign="right";ctx.fillText(feature_name,f_start-LABEL_SPACING,y_center+8);draw_start-=ctx.measureText(feature_name).width+LABEL_SPACING}}}ctx.globalAlpha=1;return[draw_start,draw_end]}});var ReadPainter=function(data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler,ref_seq,base_color_fn){FeaturePainter.call(this,data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler);this.ref_seq=(ref_seq?ref_seq.data:null);this.base_color_fn=base_color_fn};extend(ReadPainter.prototype,FeaturePainter.prototype,{get_row_height:function(){var height,mode=this.mode;if(mode==="Dense"){height=DENSE_TRACK_HEIGHT}else{if(mode==="Squish"){height=SQUISH_TRACK_HEIGHT}else{height=PACK_TRACK_HEIGHT;if(this.prefs.show_insertions){height*=2}}}return height},_parse_cigar:function(cigar_str){var cigar_ops="MIDNSHP=X";var blocks=[[0,0]],cur_block=blocks[0],base_pos=0,parsed_cigar=_.map(cigar_str.match(/[0-9]+[MIDNSHP=X]/g),function(op){var op_len=parseInt(op.slice(0,-1),10),op_char=op.slice(-1);if(op_char==="N"){if(cur_block[1]!==0){cur_block=[base_pos+op_len,base_pos+op_len];blocks.push(cur_block)}}else{if("ISHP".indexOf(op_char)===-1){cur_block[1]+=op_len;base_pos+=op_len}}return[cigar_ops.indexOf(op_char),op_len]});return{blocks:blocks,cigar:parsed_cigar}},draw_read:function(ctx,mode,w_scale,y_center,tile_low,tile_high,feature_start,cigar,strand,read_seq){ctx.textAlign="center";var tile_region=[tile_low,tile_high],base_offset=0,seq_offset=0,gap=Math.round(w_scale/2),char_width_px=ctx.canvas.manager.char_width_px,block_color=(strand==="+"?this.prefs.block_color:this.prefs.reverse_strand_color),pack_mode=(mode==="Pack");var draw_last=[];if(!cigar){cigar=[[0,read_seq.length]]}for(var cig_id=0,len=cigar.length;cig_id<len;cig_id++){var cig=cigar[cig_id],cig_op="MIDNSHP=X"[cig[0]],cig_len=cig[1];var seq_start=feature_start+base_offset,s_start=Math.floor(Math.max(-0.5*w_scale,(seq_start-tile_low-0.5)*w_scale)),s_end=Math.floor(Math.max(0,(seq_start+cig_len-tile_low-0.5)*w_scale));if(s_start===s_end){s_end+=1}switch(cig_op){case"H":break;case"S":seq_offset+=cig_len;break;case"M":case"=":case"X":if(is_overlap([seq_start,seq_start+cig_len],tile_region)){ctx.fillStyle=block_color;ctx.fillRect(s_start,y_center+(pack_mode?1:4),s_end-s_start,(pack_mode?PACK_FEATURE_HEIGHT:SQUISH_FEATURE_HEIGHT));var seq=read_seq.slice(seq_offset,seq_offset+cig_len),ref_char,read_char;for(var c=0,str_len=seq.length;c<str_len;c++){if(seq_start+c>=tile_low&&seq_start+c<=tile_high){ref_char=(this.ref_seq?this.ref_seq[seq_start-tile_low+c]:null);read_char=seq[c];if((ref_char&&(!this.prefs.show_differences||(read_char.toLowerCase!=="n"&&(ref_char.toLowerCase()!==read_char.toLowerCase()))))||(!ref_char&&!this.prefs.show_differences)){var c_start=Math.floor(Math.max(0,(seq_start+c-tile_low)*w_scale));ctx.fillStyle=this.base_color_fn(seq[c]);if(pack_mode&&w_scale>char_width_px){ctx.fillText(seq[c],c_start,y_center+9)}else{if(w_scale>0.05){ctx.fillRect(c_start-gap,y_center+(pack_mode?1:4),Math.max(1,Math.round(w_scale)),(pack_mode?PACK_FEATURE_HEIGHT:SQUISH_FEATURE_HEIGHT))}}}}}}seq_offset+=cig_len;base_offset+=cig_len;break;case"N":ctx.fillStyle=CONNECTOR_COLOR;ctx.fillRect(s_start,y_center+5,s_end-s_start,1);base_offset+=cig_len;break;case"D":ctx.fillStyle="black";ctx.fillRect(s_start,y_center+4,s_end-s_start,3);base_offset+=cig_len;break;case"P":break;case"I":var insert_x_coord=s_start-gap;if(is_overlap([seq_start,seq_start+cig_len],tile_region)){var seq=read_seq.slice(seq_offset,seq_offset+cig_len);if(this.prefs.show_insertions){var x_center=s_start-(s_end-s_start)/2;if((mode==="Pack"||this.mode==="Auto")&&read_seq!==undefined&&w_scale>char_width_px){ctx.fillStyle="yellow";ctx.fillRect(x_center-gap,y_center-9,s_end-s_start,9);draw_last[draw_last.length]={type:"triangle",data:[insert_x_coord,y_center+4,5]};ctx.fillStyle=CONNECTOR_COLOR;switch(compute_overlap([seq_start,seq_start+cig_len],tile_region)){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):break;case (CONTAINS):seq=seq.slice(tile_low-seq_start,seq_start-tile_high);break}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-(s_end-s_start)/2,y_center)}}else{ctx.fillStyle="yellow";ctx.fillRect(x_center,y_center+(this.mode!=="Dense"?2:5),s_end-s_start,(mode!=="Dense"?SQUISH_FEATURE_HEIGHT:DENSE_FEATURE_HEIGHT))}}else{if((mode==="Pack"||this.mode==="Auto")&&read_seq!==undefined&&w_scale>char_width_px){draw_last.push({type:"text",data:[seq.length,insert_x_coord,y_center+9]})}else{}}}seq_offset+=cig_len;break}}ctx.fillStyle="yellow";var item,type,data;for(var i=0;i<draw_last.length;i++){item=draw_last[i];type=item.type;data=item.data;if(type==="text"){ctx.save();ctx.font="bold "+ctx.font;ctx.fillText(data[0],data[1],data[2]);ctx.restore()}else{if(type==="triangle"){drawDownwardEquilateralTriangle(ctx,data[0],data[1],data[2])}}}},draw_element:function(ctx,mode,feature,slot,tile_low,tile_high,w_scale,y_scale,width){var feature_uid=feature[0],feature_start=feature[1],feature_end=feature[2],feature_name=feature[3],f_start=Math.floor(Math.max(-0.5*w_scale,(feature_start-tile_low-0.5)*w_scale)),f_end=Math.ceil(Math.min(width,Math.max(0,(feature_end-tile_low-0.5)*w_scale))),y_center=(mode==="Dense"?0:(0+slot))*y_scale,label_color=this.prefs.label_color;if(feature[5] instanceof Array){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))),connector=true;if(feature[4][1]>=tile_low&&feature[4][0]<=tile_high&&feature[4][2]){this.draw_read(ctx,mode,w_scale,y_center,tile_low,tile_high,feature[4][0],feature[4][2],feature[4][3],feature[4][4])}else{connector=false}if(feature[5][1]>=tile_low&&feature[5][0]<=tile_high&&feature[5][2]){this.draw_read(ctx,mode,w_scale,y_center,tile_low,tile_high,feature[5][0],feature[5][2],feature[5][3],feature[5][4])}else{connector=false}if(connector&&b2_start>b1_end){ctx.fillStyle=CONNECTOR_COLOR;dashedLine(ctx,b1_end,y_center+5,b2_start,y_center+5)}}else{this.draw_read(ctx,mode,w_scale,y_center,tile_low,tile_high,feature_start,feature[4],feature[5],feature[6])}if(mode==="Pack"&&feature_start>=tile_low&&feature_name!=="."){ctx.fillStyle=this.prefs.label_color;if(tile_low===0&&f_start-ctx.measureText(feature_name).width<0){ctx.textAlign="left";ctx.fillText(feature_name,f_end+LABEL_SPACING,y_center+8)}else{ctx.textAlign="right";ctx.fillText(feature_name,f_start-LABEL_SPACING,y_center+8)}}return[0,0]}});var RefBasedReadPainter=function(data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler,ref_seq,base_color_fn){ReadPainter.call(this,data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler,ref_seq,base_color_fn)};extend(RefBasedReadPainter.prototype,ReadPainter.prototype,FeaturePainter,{draw_read:function(ctx,mode,w_scale,y_center,tile_low,tile_high,feature_start,cigar,strand,read_seq){ctx.textAlign="center";var tile_region=[tile_low,tile_high],base_offset=0,seq_offset=0,gap=Math.round(w_scale/2),char_width_px=ctx.canvas.manager.char_width_px,block_color=(strand==="+"?this.prefs.block_color:this.prefs.reverse_strand_color),pack_mode=(mode==="Pack"),drawing_blocks=[];var draw_last=[];var t=this._parse_cigar(cigar);cigar=t.cigar;drawing_blocks=t.blocks;for(var i=0;i<drawing_blocks.length;i++){var block=drawing_blocks[i];if(is_overlap([feature_start+block[0],feature_start+block[1]],tile_region)){var s_start=Math.floor(Math.max(-0.5*w_scale,(feature_start+block[0]-tile_low-0.5)*w_scale)),s_end=Math.floor(Math.max(0,(feature_start+block[1]-tile_low-0.5)*w_scale));if(s_start===s_end){s_end+=1}ctx.fillStyle=block_color;ctx.fillRect(s_start,y_center+(pack_mode?1:4),s_end-s_start,(pack_mode?PACK_FEATURE_HEIGHT:SQUISH_FEATURE_HEIGHT))}}for(var cig_id=0,len=cigar.length;cig_id<len;cig_id++){var cig=cigar[cig_id],cig_op="MIDNSHP=X"[cig[0]],cig_len=cig[1];var seq_start=feature_start+base_offset,s_start=Math.floor(Math.max(0,-0.5*w_scale,(seq_start-tile_low-0.5)*w_scale)),s_end=Math.floor(Math.max(0,(seq_start+cig_len-tile_low-0.5)*w_scale));if(s_start===s_end){s_end+=1}switch(cig_op){case"H":case"S":case"P":break;case"M":base_offset+=cig_len;break;case"=":case"X":if(is_overlap([seq_start,seq_start+cig_len],tile_region)){var cur_seq="";if(cig_op==="X"){cur_seq=read_seq.slice(seq_offset,seq_offset+cig_len)}else{if(this.ref_seq){cur_seq=this.ref_seq.slice(Math.max(0,seq_start-tile_low),Math.min(seq_start-tile_low+cig_len,tile_high-tile_low))}}var start_pos=Math.max(seq_start,tile_low);for(var c=0;c<cur_seq.length;c++){if(cur_seq&&!this.prefs.show_differences||cig_op==="X"){var c_start=Math.floor(Math.max(0,(start_pos+c-tile_low)*w_scale));ctx.fillStyle=this.base_color_fn(cur_seq[c]);if(pack_mode&&w_scale>char_width_px){ctx.fillText(cur_seq[c],c_start,y_center+9)}else{if(w_scale>0.05){ctx.fillRect(c_start-gap,y_center+(pack_mode?1:4),Math.max(1,Math.round(w_scale)),(pack_mode?PACK_FEATURE_HEIGHT:SQUISH_FEATURE_HEIGHT))}}}}}if(cig_op==="X"){seq_offset+=cig_len}base_offset+=cig_len;break;case"N":ctx.fillStyle=CONNECTOR_COLOR;ctx.fillRect(s_start,y_center+5,s_end-s_start,1);base_offset+=cig_len;break;case"D":ctx.fillStyle="black";ctx.fillRect(s_start,y_center+4,s_end-s_start,3);base_offset+=cig_len;break;case"I":var insert_x_coord=s_start-gap;if(is_overlap([seq_start,seq_start+cig_len],tile_region)){var seq=read_seq.slice(seq_offset,seq_offset+cig_len);if(this.prefs.show_insertions){var x_center=s_start-(s_end-s_start)/2;if((mode==="Pack"||this.mode==="Auto")&&read_seq!==undefined&&w_scale>char_width_px){ctx.fillStyle="yellow";ctx.fillRect(x_center-gap,y_center-9,s_end-s_start,9);draw_last[draw_last.length]={type:"triangle",data:[insert_x_coord,y_center+4,5]};ctx.fillStyle=CONNECTOR_COLOR;switch(compute_overlap([seq_start,seq_start+cig_len],tile_region)){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):break;case (CONTAINS):seq=seq.slice(tile_low-seq_start,seq_start-tile_high);break}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-(s_end-s_start)/2,y_center)}}else{ctx.fillStyle="yellow";ctx.fillRect(x_center,y_center+(this.mode!=="Dense"?2:5),s_end-s_start,(mode!=="Dense"?SQUISH_FEATURE_HEIGHT:DENSE_FEATURE_HEIGHT))}}else{if((mode==="Pack"||this.mode==="Auto")&&read_seq!==undefined&&w_scale>char_width_px){draw_last.push({type:"text",data:[seq.length,insert_x_coord,y_center+9]})}else{}}}seq_offset+=cig_len;break}}ctx.fillStyle="yellow";var item,type,data;for(var i=0;i<draw_last.length;i++){item=draw_last[i];type=item.type;data=item.data;if(type==="text"){ctx.save();ctx.font="bold "+ctx.font;ctx.fillText(data[0],data[1],data[2]);ctx.restore()}else{if(type==="triangle"){drawDownwardEquilateralTriangle(ctx,data[0],data[1],data[2])}}}}});var ArcLinkedFeaturePainter=function(data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler){LinkedFeaturePainter.call(this,data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler);this.longest_feature_length=this.calculate_longest_feature_length();this.draw_background_connector=false;this.draw_individual_connectors=true};extend(ArcLinkedFeaturePainter.prototype,FeaturePainter.prototype,LinkedFeaturePainter.prototype,{calculate_longest_feature_length:function(){var longest_feature_length=0;for(var i=0,len=this.data.length;i<len;i++){var feature=this.data[i],feature_start=feature[1],feature_end=feature[2];longest_feature_length=Math.max(longest_feature_length,feature_end-feature_start)}return longest_feature_length},get_top_padding:function(width){var view_range=this.view_end-this.view_start,w_scale=width/view_range;return Math.min(128,Math.ceil((this.longest_feature_length/2)*w_scale))},draw_connector:function(ctx,block1_start,block1_end,block2_start,block2_end,y_center){var x_center=(block1_end+block2_start)/2,radius=block2_start-x_center;var angle1=Math.PI,angle2=0;if(radius>0){ctx.beginPath();ctx.arc(x_center,y_center,block2_start-x_center,Math.PI,0);ctx.stroke()}}});var Color=function(rgb,a){if(Array.isArray(rgb)){this.rgb=rgb}else{if(rgb.length==6){this.rgb=rgb.match(/.{2}/g).map(function(c){return parseInt(c,16)})}else{if(rgb.length==7){this.rgb=rgb.substring(1,7).match(/.{2}/g).map(function(c){return parseInt(c,16)})}else{this.rgb=rgb.split("").map(function(c){return parseInt(c+c,16)})}}}this.alpha=typeof(a)==="number"?a:1};Color.prototype={eval:function(){return this},toCSS:function(){if(this.alpha<1){return"rgba("+this.rgb.map(function(c){return Math.round(c)}).concat(this.alpha).join(", ")+")"}else{return"#"+this.rgb.map(function(i){i=Math.round(i);i=(i>255?255:(i<0?0:i)).toString(16);return i.length===1?"0"+i:i}).join("")}},toHSL:function(){var r=this.rgb[0]/255,g=this.rgb[1]/255,b=this.rgb[2]/255,a=this.alpha;var max=Math.max(r,g,b),min=Math.min(r,g,b);var h,s,l=(max+min)/2,d=max-min;if(max===min){h=s=0}else{s=l>0.5?d/(2-max-min):d/(max+min);switch(max){case r:h=(g-b)/d+(g<b?6:0);break;case g:h=(b-r)/d+2;break;case b:h=(r-g)/d+4;break}h/=6}return{h:h*360,s:s,l:l,a:a}},toARGB:function(){var argb=[Math.round(this.alpha*255)].concat(this.rgb);return"#"+argb.map(function(i){i=Math.round(i);i=(i>255?255:(i<0?0:i)).toString(16);return i.length===1?"0"+i:i}).join("")},mix:function(color2,weight){color1=this;var p=weight;var w=p*2-1;var a=color1.toHSL().a-color2.toHSL().a;var w1=(((w*a==-1)?w:(w+a)/(1+w*a))+1)/2;var w2=1-w1;var rgb=[color1.rgb[0]*w1+color2.rgb[0]*w2,color1.rgb[1]*w1+color2.rgb[1]*w2,color1.rgb[2]*w1+color2.rgb[2]*w2];var alpha=color1.alpha*p+color2.alpha*(1-p);return new Color(rgb,alpha)}};var LinearRamp=function(start_color,end_color,start_value,end_value){this.start_color=new Color(start_color);this.end_color=new Color(end_color);this.start_value=start_value;this.end_value=end_value;this.value_range=end_value-start_value};LinearRamp.prototype.map_value=function(value){value=Math.max(value,this.start_value);value=Math.min(value,this.end_value);value=(value-this.start_value)/this.value_range;return this.start_color.mix(this.end_color,1-value).toCSS()};var SplitRamp=function(start_color,middle_color,end_color,start_value,end_value){this.positive_ramp=new LinearRamp(middle_color,end_color,0,end_value);this.negative_ramp=new LinearRamp(middle_color,start_color,0,-start_value);this.start_value=start_value;this.end_value=end_value};SplitRamp.prototype.map_value=function(value){value=Math.max(value,this.start_value);value=Math.min(value,this.end_value);if(value>=0){return this.positive_ramp.map_value(value)}else{return this.negative_ramp.map_value(-value)}};var DiagonalHeatmapPainter=function(data,view_start,view_end,prefs,mode){Painter.call(this,data,view_start,view_end,prefs,mode);var i,len;if(this.prefs.min_value===undefined){var min_value=Infinity;for(i=0,len=this.data.length;i<len;i++){min_value=Math.min(min_value,this.data[i][5])}this.prefs.min_value=min_value}if(this.prefs.max_value===undefined){var max_value=-Infinity;for(i=0,len=this.data.length;i<len;i++){max_value=Math.max(max_value,this.data[i][5])}this.prefs.max_value=max_value}};DiagonalHeatmapPainter.prototype.default_prefs={min_value:undefined,max_value:undefined,mode:"Heatmap",pos_color:"#FF8C00",neg_color:"#4169E1"};DiagonalHeatmapPainter.prototype.draw=function(ctx,width,height,w_scale){var min_value=this.prefs.min_value,max_value=this.prefs.max_value,value_range=max_value-min_value,height_px=height,view_start=this.view_start,mode=this.mode,data=this.data,invsqrt2=1/Math.sqrt(2);var ramp=(new SplitRamp(this.prefs.neg_color,"#FFFFFF",this.prefs.pos_color,min_value,max_value));var d,s1,e1,s2,e2,value;var scale=function(p){return(p-view_start)*w_scale};ctx.save();ctx.rotate(-45*Math.PI/180);ctx.scale(invsqrt2,invsqrt2);for(var i=0,len=data.length;i<len;i++){d=data[i];s1=scale(d[1]);e1=scale(d[2]);s2=scale(d[4]);e2=scale(d[5]);value=d[6];ctx.fillStyle=(ramp.map_value(value));ctx.fillRect(s1,s2,(e1-s1),(e2-s2))}ctx.restore()};var VariantPainter=function(data,view_start,view_end,prefs,mode,base_color_fn){Painter.call(this,data,view_start,view_end,prefs,mode);this.base_color_fn=base_color_fn;this.divider_height=1};extend(VariantPainter.prototype,Painter.prototype,{get_row_height:function(){var mode=this.mode,height;if(mode==="Dense"){height=DENSE_TRACK_HEIGHT}else{if(mode==="Squish"){height=SQUISH_TRACK_HEIGHT}else{height=PACK_TRACK_HEIGHT}}return height},get_required_height:function(rows_required,width){var height=this.prefs.summary_height;if(this.prefs.show_sample_data){height+=this.divider_height;if(this.data.length!==0){height+=(this.data[0][7].match(/,/g).length+1)*this.get_row_height()}}return height},draw:function(ctx,width,height,w_scale){var locus_data,pos,id,ref,alt,qual,filter,sample_gts,allele_counts,variant,draw_x_start,char_x_start,draw_y_start,genotype,base_px=Math.max(1,Math.floor(w_scale)),row_height=(this.mode==="Squish"?SQUISH_TRACK_HEIGHT:PACK_TRACK_HEIGHT),feature_height=(w_scale<0.1?row_height:(this.mode==="Squish"?SQUISH_FEATURE_HEIGHT:PACK_FEATURE_HEIGHT)),j;if(this.prefs.show_sample_data){ctx.fillStyle="#DDDDDD";ctx.globalAlpha=1;ctx.fillRect(0,this.prefs.summary_height-this.divider_height,width,this.divider_height)}ctx.textAlign="center";for(var i=0;i<this.data.length;i++){locus_data=this.data[i];pos=locus_data[1];alt=locus_data[4].split(",");sample_gts=locus_data[7].split(",");allele_counts=locus_data.slice(8);draw_x_start=Math.floor(Math.max(-0.5*w_scale,(pos-this.view_start-0.5)*w_scale));char_x_start=Math.floor(Math.max(0,(pos-this.view_start)*w_scale));ctx.fillStyle="#AAAAAA";ctx.fillRect(draw_x_start,0,base_px,this.prefs.summary_height);draw_y_start=this.prefs.summary_height;for(j=0;j<alt.length;j++){ctx.fillStyle=this.base_color_fn(alt[j]);allele_frac=allele_counts/sample_gts.length;draw_height=Math.ceil(this.prefs.summary_height*allele_frac);ctx.fillRect(draw_x_start,draw_y_start-draw_height,base_px,draw_height);draw_y_start-=draw_height}if(!this.prefs.show_sample_data){continue}draw_y_start=this.prefs.summary_height+this.divider_height;for(j=0;j<sample_gts.length;j++,draw_y_start+=row_height){genotype=(sample_gts[j]?sample_gts[j].split(/\/|\|/):["0","0"]);variant=null;if(genotype[0]===genotype[1]){if(genotype[0]==="."){}else{if(genotype[0]!=="0"){variant=alt[parseInt(genotype[0],10)-1];ctx.globalAlpha=1}}}else{variant=(genotype[0]!=="0"?genotype[0]:genotype[1]);variant=alt[parseInt(variant,10)-1];ctx.globalAlpha=0.4}if(variant){ctx.fillStyle=this.base_color_fn(variant);if(this.mode==="Squish"||w_scale<ctx.canvas.manager.char_width_px){ctx.fillRect(draw_x_start,draw_y_start+1,base_px,feature_height)}else{ctx.fillText(variant,char_x_start,draw_y_start+row_height)}}}}}});return{Scaler:Scaler,SummaryTreePainter:SummaryTreePainter,LinePainter:LinePainter,LinkedFeaturePainter:LinkedFeaturePainter,ReadPainter:ReadPainter,RefBasedReadPainter:RefBasedReadPainter,ArcLinkedFeaturePainter:ArcLinkedFeaturePainter,DiagonalHeatmapPainter:DiagonalHeatmapPainter,VariantPainter:VariantPainter}});
\ No newline at end of file
diff -r b9bd0fae39cabc1ff55f374e026b7aa3f5687c77 -r 7f70ea89d5a92cba463b873de7535766bb8c7050 static/scripts/packed/viz/trackster/tracks.js
--- a/static/scripts/packed/viz/trackster/tracks.js
+++ b/static/scripts/packed/viz/trackster/tracks.js
@@ -1,1 +1,1 @@
-define(["libs/underscore","viz/visualization","viz/trackster/util","viz/trackster/slotting","viz/trackster/painters","mvc/data","viz/trackster/filters"],function(ab,x,l,u,L,Y,i){var q=ab.extend;var V=function(ac){return("isResolved" in ac)};var n={};var k=function(ac,ad){n[ac.attr("id")]=ad};var m=function(ac,ae,ag,af){ag=".group";var ad={};n[ac.attr("id")]=af;ac.bind("drag",{handle:"."+ae,relative:true},function(ao,ap){var an=$(this),at=$(this).parent(),ak=at.children(),am=n[$(this).attr("id")],aj,ai,aq,ah,al;ai=$(this).parents(ag);if(ai.length!==0){aq=ai.position().top;ah=aq+ai.outerHeight();if(ap.offsetY<aq){$(this).insertBefore(ai);var ar=n[ai.attr("id")];ar.remove_drawable(am);ar.container.add_drawable_before(am,ar);return}else{if(ap.offsetY>ah){$(this).insertAfter(ai);var ar=n[ai.attr("id")];ar.remove_drawable(am);ar.container.add_drawable(am);return}}}ai=null;for(al=0;al<ak.length;al++){aj=$(ak.get(al));aq=aj.position().top;ah=aq+aj.outerHeight();if(aj.is(ag)&&this!==aj.get(0)&&ap.offsetY>=aq&&ap.offsetY<=ah){if(ap.offsetY-aq<ah-ap.offsetY){aj.find(".content-div").prepend(this)}else{aj.find(".content-div").append(this)}if(am.container){am.container.remove_drawable(am)}n[aj.attr("id")].add_drawable(am);return}}for(al=0;al<ak.length;al++){aj=$(ak.get(al));if(ap.offsetY<aj.position().top&&!(aj.hasClass("reference-track")||aj.hasClass("intro"))){break}}if(al===ak.length){if(this!==ak.get(al-1)){at.append(this);n[at.attr("id")].move_drawable(am,al)}}else{if(this!==ak.get(al)){$(this).insertBefore(ak.get(al));n[at.attr("id")].move_drawable(am,(ap.deltaY>0?al-1:al))}}}).bind("dragstart",function(){ad["border-top"]=ac.css("border-top");ad["border-bottom"]=ac.css("border-bottom");$(this).css({"border-top":"1px solid blue","border-bottom":"1px solid blue"})}).bind("dragend",function(){$(this).css(ad)})};var aa=16,G=9,D=20,A=100,I=12000,S=400,K=5000,w=100,o="Cannot display dataset due to an error. ",J="A converter for this dataset is not installed. Please check your datatypes_conf.xml file.",E="No data for this chrom/contig.",v="Preparing data. This can take a while for a large dataset. If the visualization is saved and closed, preparation will continue in the background.",y="Tool cannot be rerun: ",a="Loading data...",U="Ready for display",Q=10,H=20;function W(ad,ac){if(!ac){ac=0}var ae=Math.pow(10,ac);return Math.round(ad*ae)/ae}var r=function(ad,ac,af){if(!r.id_counter){r.id_counter=0}this.id=r.id_counter++;this.name=af.name;this.view=ad;this.container=ac;this.config=new F({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name}],saved_values:af.prefs,onchange:function(){this.track.set_name(this.track.config.values.name)}});this.prefs=this.config.values;this.drag_handle_class=af.drag_handle_class;this.is_overview=false;this.action_icons={};this.content_visible=true;this.container_div=this.build_container_div();this.header_div=this.build_header_div();if(this.header_div){this.container_div.append(this.header_div);this.icons_div=$("<div/>").css("float","left").hide().appendTo(this.header_div);this.build_action_icons(this.action_icons_def);this.header_div.append($("<div style='clear: both'/>"));this.header_div.dblclick(function(ag){ag.stopPropagation()});var ae=this;this.container_div.hover(function(){ae.icons_div.show()},function(){ae.icons_div.hide()});$("<div style='clear: both'/>").appendTo(this.container_div)}};r.prototype.action_icons_def=[{name:"toggle_icon",title:"Hide/show content",css_class:"toggle",on_click_fn:function(ac){if(ac.content_visible){ac.action_icons.toggle_icon.addClass("toggle-expand").removeClass("toggle");ac.hide_contents();ac.content_visible=false}else{ac.action_icons.toggle_icon.addClass("toggle").removeClass("toggle-expand");ac.content_visible=true;ac.show_contents()}}},{name:"settings_icon",title:"Edit settings",css_class:"settings-icon",on_click_fn:function(ad){var af=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},ac=function(){ad.config.update_from_form($(".dialog-box"));hide_modal();$(window).unbind("keypress.check_enter_esc")},ae=function(ag){if((ag.keyCode||ag.which)===27){af()}else{if((ag.keyCode||ag.which)===13){ac()}}};$(window).bind("keypress.check_enter_esc",ae);show_modal("Configure",ad.config.build_form(),{Cancel:af,OK:ac})}},{name:"remove_icon",title:"Remove",css_class:"remove-icon",on_click_fn:function(ac){$(".bs-tooltip").remove();ac.remove()}}];q(r.prototype,{init:function(){},changed:function(){this.view.changed()},can_draw:function(){if(this.enabled&&this.content_visible){return true}return false},request_draw:function(){},_draw:function(){},to_dict:function(){},set_name:function(ac){this.old_name=this.name;this.name=ac;this.name_div.text(this.name)},revert_name:function(){if(this.old_name){this.name=this.old_name;this.name_div.text(this.name)}},remove:function(){this.changed();this.container.remove_drawable(this);var ac=this.view;this.container_div.hide(0,function(){$(this).remove();ac.update_intro_div()})},build_container_div:function(){},build_header_div:function(){},add_action_icon:function(ad,ai,ah,ag,ac,af){var ae=this;this.action_icons[ad]=$("<a/>").attr("href","javascript:void(0);").attr("title",ai).addClass("icon-button").addClass(ah).tooltip().click(function(){ag(ae)}).appendTo(this.icons_div);if(af){this.action_icons[ad].hide()}},build_action_icons:function(ac){var ae;for(var ad=0;ad<ac.length;ad++){ae=ac[ad];this.add_action_icon(ae.name,ae.title,ae.css_class,ae.on_click_fn,ae.prepend,ae.hide)}},update_icons:function(){},hide_contents:function(){},show_contents:function(){},get_drawables:function(){}});var z=function(ad,ac,ae){r.call(this,ad,ac,ae);this.obj_type=ae.obj_type;this.drawables=[]};q(z.prototype,r.prototype,{unpack_drawables:function(ae){this.drawables=[];var ad;for(var ac=0;ac<ae.length;ac++){ad=p(ae[ac],this.view,this);this.add_drawable(ad)}},init:function(){for(var ac=0;ac<this.drawables.length;ac++){this.drawables[ac].init()}},_draw:function(){for(var ac=0;ac<this.drawables.length;ac++){this.drawables[ac]._draw()}},to_dict:function(){var ad=[];for(var ac=0;ac<this.drawables.length;ac++){ad.push(this.drawables[ac].to_dict())}return{name:this.name,prefs:this.prefs,obj_type:this.obj_type,drawables:ad}},add_drawable:function(ac){this.drawables.push(ac);ac.container=this;this.changed()},add_drawable_before:function(ae,ac){this.changed();var ad=this.drawables.indexOf(ac);if(ad!==-1){this.drawables.splice(ad,0,ae);return true}return false},replace_drawable:function(ae,ac,ad){var af=this.drawables.indexOf(ae);if(af!==-1){this.drawables[af]=ac;if(ad){ae.container_div.replaceWith(ac.container_div)}this.changed()}return af},remove_drawable:function(ad){var ac=this.drawables.indexOf(ad);if(ac!==-1){this.drawables.splice(ac,1);ad.container=null;this.changed();return true}return false},move_drawable:function(ad,ae){var ac=this.drawables.indexOf(ad);if(ac!==-1){this.drawables.splice(ac,1);this.drawables.splice(ae,0,ad);this.changed();return true}return false},get_drawables:function(){return this.drawables}});var P=function(ad,ac,af){q(af,{obj_type:"DrawableGroup",drag_handle_class:"group-handle"});z.call(this,ad,ac,af);this.content_div=$("<div/>").addClass("content-div").attr("id","group_"+this.id+"_content_div").appendTo(this.container_div);k(this.container_div,this);k(this.content_div,this);m(this.container_div,this.drag_handle_class,".group",this);this.filters_manager=new i.FiltersManager(this);this.header_div.after(this.filters_manager.parent_div);this.saved_filters_managers=[];if("drawables" in af){this.unpack_drawables(af.drawables)}if("filters" in af){var ae=this.filters_manager;this.filters_manager=new i.FiltersManager(this,af.filters);ae.parent_div.replaceWith(this.filters_manager.parent_div);if(af.filters.visible){this.setup_multitrack_filtering()}}};q(P.prototype,r.prototype,z.prototype,{action_icons_def:[r.prototype.action_icons_def[0],r.prototype.action_icons_def[1],{name:"composite_icon",title:"Show composite track",css_class:"layers-stack",on_click_fn:function(ac){$(".bs-tooltip").remove();ac.show_composite_track()}},{name:"filters_icon",title:"Filters",css_class:"filters-icon",on_click_fn:function(ac){if(ac.filters_manager.visible()){ac.filters_manager.clear_filters();ac._restore_filter_managers()}else{ac.setup_multitrack_filtering();ac.request_draw(true)}ac.filters_manager.toggle()}},r.prototype.action_icons_def[2]],build_container_div:function(){var ac=$("<div/>").addClass("group").attr("id","group_"+this.id);if(this.container){this.container.content_div.append(ac)}return ac},build_header_div:function(){var ac=$("<div/>").addClass("track-header");ac.append($("<div/>").addClass(this.drag_handle_class));this.name_div=$("<div/>").addClass("track-name").text(this.name).appendTo(ac);return ac},hide_contents:function(){this.tiles_div.hide()},show_contents:function(){this.tiles_div.show();this.request_draw()},update_icons:function(){var ae=this.drawables.length;if(ae===0){this.action_icons.composite_icon.hide();this.action_icons.filters_icon.hide()}else{if(ae===1){if(this.drawables[0] instanceof f){this.action_icons.composite_icon.show()}this.action_icons.filters_icon.hide()}else{var al,ak,ai,ao=true,ag=this.drawables[0].get_type(),ac=0;for(al=0;al<ae;al++){ai=this.drawables[al];if(ai.get_type()!==ag){can_composite=false;break}if(ai instanceof c){ac++}}if(ao||ac===1){this.action_icons.composite_icon.show()}else{this.action_icons.composite_icon.hide();$(".bs-tooltip").remove()}if(ac>1&&ac===this.drawables.length){var ap={},ad;ai=this.drawables[0];for(ak=0;ak<ai.filters_manager.filters.length;ak++){ad=ai.filters_manager.filters[ak];ap[ad.name]=[ad]}for(al=1;al<this.drawables.length;al++){ai=this.drawables[al];for(ak=0;ak<ai.filters_manager.filters.length;ak++){ad=ai.filters_manager.filters[ak];if(ad.name in ap){ap[ad.name].push(ad)}}}this.filters_manager.remove_all();var af,ah,aj,am;for(var an in ap){af=ap[an];if(af.length===ac){ah=new i.NumberFilter({name:af[0].name,index:af[0].index});this.filters_manager.add_filter(ah)}}if(this.filters_manager.filters.length>0){this.action_icons.filters_icon.show()}else{this.action_icons.filters_icon.hide()}}else{this.action_icons.filters_icon.hide()}}}},_restore_filter_managers:function(){for(var ac=0;ac<this.drawables.length;ac++){this.drawables[ac].filters_manager=this.saved_filters_managers[ac]}this.saved_filters_managers=[]},setup_multitrack_filtering:function(){if(this.filters_manager.filters.length>0){this.saved_filters_managers=[];for(var ac=0;ac<this.drawables.length;ac++){drawable=this.drawables[ac];this.saved_filters_managers.push(drawable.filters_manager);drawable.filters_manager=this.filters_manager}}this.filters_manager.init_filters()},show_composite_track:function(){var af=[];for(var ad=0;ad<this.drawables.length;ad++){af.push(this.drawables[ad].name)}var ae=new f(this.view,this.view,{name:this.name,drawables:this.drawables});var ac=this.container.replace_drawable(this,ae,true);ae.request_draw()},add_drawable:function(ac){z.prototype.add_drawable.call(this,ac);this.update_icons()},remove_drawable:function(ac){z.prototype.remove_drawable.call(this,ac);this.update_icons()},to_dict:function(){if(this.filters_manager.visible()){this._restore_filter_managers()}var ac=q(z.prototype.to_dict.call(this),{filters:this.filters_manager.to_dict()});if(this.filters_manager.visible()){this.setup_multitrack_filtering()}return ac},request_draw:function(ac,ae){for(var ad=0;ad<this.drawables.length;ad++){this.drawables[ad].request_draw(ac,ae)}}});var Z=Backbone.View.extend({initialize:function(ac){q(ac,{obj_type:"View"});z.call(this,"View",ac.container,ac);this.chrom=null;this.vis_id=ac.vis_id;this.dbkey=ac.dbkey;this.label_tracks=[];this.tracks_to_be_redrawn=[];this.max_low=0;this.max_high=0;this.zoom_factor=3;this.min_separation=30;this.has_changes=false;this.load_chroms_deferred=null;this.render();this.canvas_manager=new x.CanvasManager(this.container.get(0).ownerDocument);this.reset();this.config=new F({track:this,params:[{key:"a_color",label:"A Color",type:"color",default_value:"#FF0000"},{key:"c_color",label:"C Color",type:"color",default_value:"#00FF00"},{key:"g_color",label:"G Color",type:"color",default_value:"#0000FF"},{key:"t_color",label:"T Color",type:"color",default_value:"#FF00FF"},{key:"n_color",label:"N Color",type:"color",default_value:"#AAAAAA"},],saved_values:ac.prefs,onchange:function(){track.request_redraw(false,true)}})},render:function(){this.requested_redraw=false;var ae=this.container,ac=this;this.top_container=$("<div/>").addClass("top-container").appendTo(ae);this.browser_content_div=$("<div/>").addClass("content").css("position","relative").appendTo(ae);this.bottom_container=$("<div/>").addClass("bottom-container").appendTo(ae);this.top_labeltrack=$("<div/>").addClass("top-labeltrack").appendTo(this.top_container);this.viewport_container=$("<div/>").addClass("viewport-container").attr("id","viewport-container").appendTo(this.browser_content_div);this.content_div=this.viewport_container;k(this.viewport_container,ac);this.intro_div=$("<div/>").addClass("intro").appendTo(this.viewport_container).hide();var af=$("<div/>").text("Add Datasets to Visualization").addClass("action-button").appendTo(this.intro_div).click(function(){x.select_datasets(select_datasets_url,add_track_async_url,{"f-dbkey":ac.dbkey},function(ag){ab.each(ag,function(ah){ac.add_drawable(p(ah,ac,ac))})})});this.nav_labeltrack=$("<div/>").addClass("nav-labeltrack").appendTo(this.bottom_container);this.nav_container=$("<div/>").addClass("trackster-nav-container").prependTo(this.top_container);this.nav=$("<div/>").addClass("trackster-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/>").attr("href","javascript:void(0);").attr("title","Close overview").addClass("icon-button overview-close tooltip").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_select=$("<select/>").attr({name:"chrom"}).css("width","15em").append("<option value=''>Loading</option>").appendTo(this.nav_controls);var ad=function(ag){if(ag.type==="focusout"||(ag.keyCode||ag.which)===13||(ag.keyCode||ag.which)===27){if((ag.keyCode||ag.which)!==27){ac.go_to($(this).val())}$(this).hide();$(this).val("");ac.location_span.show();ac.chrom_select.show()}};this.nav_input=$("<input/>").addClass("nav-input").hide().bind("keyup focusout",ad).appendTo(this.nav_controls);this.location_span=$("<span/>").addClass("location").attr("original-title","Click to change location").tooltip({placement:"bottom"}).appendTo(this.nav_controls);this.location_span.click(function(){ac.location_span.hide();ac.chrom_select.hide();ac.nav_input.val(ac.chrom+":"+ac.low+"-"+ac.high);ac.nav_input.css("display","inline-block");ac.nav_input.select();ac.nav_input.focus();ac.nav_input.autocomplete({source:function(ai,ag){var aj=[],ah=$.map(ac.get_drawables(),function(ak){return ak.data_manager.search_features(ai.term).success(function(al){aj=aj.concat(al)})});$.when.apply($,ah).done(function(){ag($.map(aj,function(ak){return{label:ak[0],value:ak[1]}}))})}})});if(this.vis_id!==undefined){this.hidden_input=$("<input/>").attr("type","hidden").val(this.vis_id).appendTo(this.nav_controls)}this.zo_link=$("<a/>").attr("id","zoom-out").attr("title","Zoom out").tooltip({placement:"bottom"}).click(function(){ac.zoom_out();ac.request_redraw()}).appendTo(this.nav_controls);this.zi_link=$("<a/>").attr("id","zoom-in").attr("title","Zoom in").tooltip({placement:"bottom"}).click(function(){ac.zoom_in();ac.request_redraw()}).appendTo(this.nav_controls);this.load_chroms_deferred=this.load_chroms({low:0});this.chrom_select.bind("change",function(){ac.change_chrom(ac.chrom_select.val())});this.browser_content_div.click(function(ag){$(this).find("input").trigger("blur")});this.browser_content_div.bind("dblclick",function(ag){ac.zoom_in(ag.pageX,this.viewport_container)});this.overview_box.bind("dragstart",function(ag,ah){this.current_x=ah.offsetX}).bind("drag",function(ag,ai){var aj=ai.offsetX-this.current_x;this.current_x=ai.offsetX;var ah=Math.round(aj/ac.viewport_container.width()*(ac.max_high-ac.max_low));ac.move_delta(-ah)});this.overview_close.click(function(){ac.reset_overview()});this.viewport_container.bind("draginit",function(ag,ah){if(ag.clientX>ac.viewport_container.width()-16){return false}}).bind("dragstart",function(ag,ah){ah.original_low=ac.low;ah.current_height=ag.clientY;ah.current_x=ah.offsetX}).bind("drag",function(ai,ak){var ag=$(this);var al=ak.offsetX-ak.current_x;var ah=ag.scrollTop()-(ai.clientY-ak.current_height);ag.scrollTop(ah);ak.current_height=ai.clientY;ak.current_x=ak.offsetX;var aj=Math.round(al/ac.viewport_container.width()*(ac.high-ac.low));ac.move_delta(aj)}).bind("mousewheel",function(ai,ak,ah,ag){if(ah){ah*=50;var aj=Math.round(-ah/ac.viewport_container.width()*(ac.high-ac.low));ac.move_delta(aj)}});this.top_labeltrack.bind("dragstart",function(ag,ah){return $("<div />").css({height:ac.browser_content_div.height()+ac.top_labeltrack.height()+ac.nav_labeltrack.height()+1,top:"0px",position:"absolute","background-color":"#ccf",opacity:0.5,"z-index":1000}).appendTo($(this))}).bind("drag",function(ak,al){$(al.proxy).css({left:Math.min(ak.pageX,al.startX)-ac.container.offset().left,width:Math.abs(ak.pageX-al.startX)});var ah=Math.min(ak.pageX,al.startX)-ac.container.offset().left,ag=Math.max(ak.pageX,al.startX)-ac.container.offset().left,aj=(ac.high-ac.low),ai=ac.viewport_container.width();ac.update_location(Math.round(ah/ai*aj)+ac.low,Math.round(ag/ai*aj)+ac.low)}).bind("dragend",function(al,am){var ah=Math.min(al.pageX,am.startX),ag=Math.max(al.pageX,am.startX),aj=(ac.high-ac.low),ai=ac.viewport_container.width(),ak=ac.low;ac.low=Math.round(ah/ai*aj)+ak;ac.high=Math.round(ag/ai*aj)+ak;$(am.proxy).remove();ac.request_redraw()});this.add_label_track(new X(this,{content_div:this.top_labeltrack}));this.add_label_track(new X(this,{content_div:this.nav_labeltrack}));$(window).bind("resize",function(){if(this.resize_timer){clearTimeout(this.resize_timer)}this.resize_timer=setTimeout(function(){ac.resize_window()},500)});$(document).bind("redraw",function(){ac.redraw()});this.reset();$(window).trigger("resize")},get_base_color:function(ac){return this.config.values[ac.toLowerCase()+"_color"]}});q(Z.prototype,z.prototype,{changed:function(){this.has_changes=true},update_intro_div:function(){if(this.drawables.length===0){this.intro_div.show()}else{this.intro_div.hide()}},trigger_navigate:function(ad,af,ac,ag){if(this.timer){clearTimeout(this.timer)}if(ag){var ae=this;this.timer=setTimeout(function(){ae.trigger("navigate",ad+":"+af+"-"+ac)},500)}else{view.trigger("navigate",ad+":"+af+"-"+ac)}},update_location:function(ac,ae){this.location_span.text(commatize(ac)+" - "+commatize(ae));this.nav_input.val(this.chrom+":"+commatize(ac)+"-"+commatize(ae));var ad=view.chrom_select.val();if(ad!==""){this.trigger_navigate(ad,view.low,view.high,true)}},load_chroms:function(ae){ae.num=w;var ac=this,ad=$.Deferred();$.ajax({url:chrom_url+"/"+this.dbkey,data:ae,dataType:"json",success:function(ag){if(ag.chrom_info.length===0){return}if(ag.reference){ac.add_label_track(new B(ac))}ac.chrom_data=ag.chrom_info;var aj='<option value="">Select Chrom/Contig</option>';for(var ai=0,af=ac.chrom_data.length;ai<af;ai++){var ah=ac.chrom_data[ai].chrom;aj+='<option value="'+ah+'">'+ah+"</option>"}if(ag.prev_chroms){aj+='<option value="previous">Previous '+w+"</option>"}if(ag.next_chroms){aj+='<option value="next">Next '+w+"</option>"}ac.chrom_select.html(aj);ac.chrom_start_index=ag.start_index;ad.resolve(ag.chrom_info)},error:function(){alert("Could not load chroms for this dbkey:",ac.dbkey)}});return ad},change_chrom:function(ah,ad,aj){var ae=this;if(!ae.chrom_data){ae.load_chroms_deferred.then(function(){ae.change_chrom(ah,ad,aj)});return}if(!ah||ah==="None"){return}if(ah==="previous"){ae.load_chroms({low:this.chrom_start_index-w});return}if(ah==="next"){ae.load_chroms({low:this.chrom_start_index+w});return}var ai=$.grep(ae.chrom_data,function(ak,al){return ak.chrom===ah})[0];if(ai===undefined){ae.load_chroms({chrom:ah},function(){ae.change_chrom(ah,ad,aj)});return}else{if(ah!==ae.chrom){ae.chrom=ah;ae.chrom_select.val(ae.chrom);ae.max_high=ai.len-1;ae.reset();ae.request_redraw(true);for(var ag=0,ac=ae.drawables.length;ag<ac;ag++){var af=ae.drawables[ag];if(af.init){af.init()}}if(ae.reference_track){ae.reference_track.init()}}if(ad&&aj){ae.low=Math.max(ad,0);ae.high=Math.min(aj,ae.max_high)}else{ae.low=0;ae.high=ae.max_high}ae.reset_overview();ae.request_redraw()}},go_to:function(ag){ag=ag.replace(/,/g,"");ag=ag.replace(/:|\-/g," ");var ad=ag.split(/\s+/),af=ad[0],ae=(ad[1]?parseInt(ad[1],10):null),ac=(ad[2]?parseInt(ad[2],10):null);if(!ac){ae=ae-15;ac=ae+15}this.change_chrom(af,ae,ac)},move_fraction:function(ae){var ac=this;var ad=ac.high-ac.low;this.move_delta(ae*ad)},move_delta:function(af){var ac=this;var ae=ac.high-ac.low;if(ac.low-af<ac.max_low){ac.low=ac.max_low;ac.high=ac.max_low+ae}else{if(ac.high-af>ac.max_high){ac.high=ac.max_high;ac.low=ac.max_high-ae}else{ac.high-=af;ac.low-=af}}ac.request_redraw();var ad=ac.chrom_select.val();this.trigger_navigate(ad,ac.low,ac.high,true)},add_drawable:function(ac){z.prototype.add_drawable.call(this,ac);ac.init();this.changed();this.update_intro_div()},add_label_track:function(ac){ac.view=this;ac.init();this.label_tracks.push(ac)},remove_drawable:function(ae,ad){z.prototype.remove_drawable.call(this,ae);if(ad){var ac=this;ae.container_div.hide(0,function(){$(this).remove();ac.update_intro_div()})}},reset:function(){this.low=this.max_low;this.high=this.max_high;this.viewport_container.find(".yaxislabel").remove()},request_redraw:function(ak,ac,aj,al){var ai=this,ah=(al?[al]:ai.drawables),ae;var ad;for(var ag=0;ag<ah.length;ag++){ad=ah[ag];ae=-1;for(var af=0;af<ai.tracks_to_be_redrawn.length;af++){if(ai.tracks_to_be_redrawn[af][0]===ad){ae=af;break}}if(ae<0){ai.tracks_to_be_redrawn.push([ad,ac,aj])}else{ai.tracks_to_be_redrawn[ag][1]=ac;ai.tracks_to_be_redrawn[ag][2]=aj}}if(!this.requested_redraw){requestAnimationFrame(function(){ai._redraw(ak)});this.requested_redraw=true}},_redraw:function(am){this.requested_redraw=false;var aj=this.low,af=this.high;if(aj<this.max_low){aj=this.max_low}if(af>this.max_high){af=this.max_high}var al=this.high-this.low;if(this.high!==0&&al<this.min_separation){af=aj+this.min_separation}this.low=Math.floor(aj);this.high=Math.ceil(af);this.update_location(this.low,this.high);this.resolution_b_px=(this.high-this.low)/this.viewport_container.width();this.resolution_px_b=1/this.resolution_b_px;var ac=(this.low/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var ai=((this.high-this.low)/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var an=13;this.overview_box.css({left:ac,width:Math.max(an,ai)}).show();if(ai<an){this.overview_box.css("left",ac-(an-ai)/2)}if(this.overview_highlight){this.overview_highlight.css({left:ac,width:ai})}if(!am){var ae,ad,ak;for(var ag=0,ah=this.tracks_to_be_redrawn.length;ag<ah;ag++){ae=this.tracks_to_be_redrawn[ag][0];ad=this.tracks_to_be_redrawn[ag][1];ak=this.tracks_to_be_redrawn[ag][2];if(ae){ae._draw(ad,ak)}}this.tracks_to_be_redrawn=[];for(ag=0,ah=this.label_tracks.length;ag<ah;ag++){this.label_tracks[ag]._draw()}}},zoom_in:function(ad,ae){if(this.max_high===0||this.high-this.low<=this.min_separation){return}var af=this.high-this.low,ag=af/2+this.low,ac=(af/this.zoom_factor)/2;if(ad){ag=ad/this.viewport_container.width()*(this.high-this.low)+this.low}this.low=Math.round(ag-ac);this.high=Math.round(ag+ac);this.changed();this.request_redraw()},zoom_out:function(){if(this.max_high===0){return}var ad=this.high-this.low,ae=ad/2+this.low,ac=(ad*this.zoom_factor)/2;this.low=Math.round(ae-ac);this.high=Math.round(ae+ac);this.changed();this.request_redraw()},resize_window:function(){this.viewport_container.height(this.container.height()-this.top_container.height()-this.bottom_container.height());this.request_redraw()},set_overview:function(ae){if(this.overview_drawable){if(this.overview_drawable.dataset_id===ae.dataset_id){return}this.overview_viewport.find(".track").remove()}var ad=ae.copy({content_div:this.overview_viewport}),ac=this;ad.header_div.hide();ad.is_overview=true;ac.overview_drawable=ad;this.overview_drawable.postdraw_actions=function(){ac.overview_highlight.show().height(ac.overview_drawable.content_div.height());ac.overview_viewport.height(ac.overview_drawable.content_div.height()+ac.overview_box.outerHeight());ac.overview_close.show();ac.resize_window()};ac.overview_drawable.request_draw();this.changed()},reset_overview:function(){$(".bs-tooltip").remove();this.overview_viewport.find(".track-tile").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();view.resize_window();view.overview_drawable=null}});var s=function(ae,aj,af){this.track=ae;this.id=aj.id;this.name=aj.name;this.params=[];var aq=aj.params;for(var ag=0;ag<aq.length;ag++){var al=aq[ag],ad=al.name,ap=al.label,ah=unescape(al.html),ar=al.value,an=al.type;if(an==="number"){this.params.push(new e(ad,ap,ah,(ad in af?af[ad]:ar),al.min,al.max))}else{if(an==="select"){this.params.push(new N(ad,ap,ah,(ad in af?af[ad]:ar)))}else{console.log("WARNING: unrecognized tool parameter type:",ad,an)}}}this.parent_div=$("<div/>").addClass("dynamic-tool").hide();this.parent_div.bind("drag",function(au){au.stopPropagation()}).click(function(au){au.stopPropagation()}).bind("dblclick",function(au){au.stopPropagation()});var ao=$("<div class='tool-name'>").appendTo(this.parent_div).text(this.name);var am=this.params;var ak=this;$.each(this.params,function(av,ay){var ax=$("<div>").addClass("param-row").appendTo(ak.parent_div);var au=$("<div>").addClass("param-label").text(ay.label).appendTo(ax);var aw=$("<div/>").addClass("param-input").html(ay.html).appendTo(ax);aw.find(":input").val(ay.value);$("<div style='clear: both;'/>").appendTo(ax)});this.parent_div.find("input").click(function(){$(this).select()});var at=$("<div>").addClass("param-row").appendTo(this.parent_div);var ai=$("<input type='submit'>").attr("value","Run on complete dataset").appendTo(at);var ac=$("<input type='submit'>").attr("value","Run on visible region").css("margin-left","3em").appendTo(at);ac.click(function(){ak.run_on_region()});ai.click(function(){ak.run_on_dataset()});if("visible" in af&&af.visible){this.parent_div.show()}};q(s.prototype,{update_params:function(){for(var ac=0;ac<this.params.length;ac++){this.params[ac].update_value()}},state_dict:function(){var ad={};for(var ac=0;ac<this.params.length;ac++){ad[this.params[ac].name]=this.params[ac].value}ad.visible=this.parent_div.is(":visible");return ad},get_param_values_dict:function(){var ac={};this.parent_div.find(":input").each(function(){var ad=$(this).attr("name"),ae=$(this).val();ac[ad]=ae});return ac},get_param_values:function(){var ac=[];this.parent_div.find(":input").each(function(){var ad=$(this).attr("name"),ae=$(this).val();if(ad){ac[ac.length]=ae}});return ac},run_on_dataset:function(){var ac=this;ac.run({target_dataset_id:this.track.original_dataset_id,action:"rerun",tool_id:ac.id},null,function(ad){show_modal(ac.name+" is Running",ac.name+" is running on the complete dataset. Tool outputs are in dataset's history.",{Close:hide_modal})})},run_on_region:function(){var ai=new x.GenomeRegion({chrom:this.track.view.chrom,start:this.track.view.low,end:this.track.view.high}),ad={target_dataset_id:this.track.original_dataset_id,action:"rerun",tool_id:this.id,regions:[ai.toJSON()]},ah=this.track,ae=ad.tool_id+ah.tool_region_and_parameters_str(ai),ac;if(ah.container===view){var ag=new P(view,view,{name:this.name});var af=ah.container.replace_drawable(ah,ag,false);ag.container_div.insertBefore(ah.view.content_div.children()[af]);ag.add_drawable(ah);ah.container_div.appendTo(ag.content_div);ac=ag}else{ac=ah.container}var aj=new ah.constructor(view,ac,{name:ae,hda_ldda:"hda"});aj.init_for_tool_data();aj.change_mode(ah.mode);aj.set_filters_manager(ah.filters_manager.copy(aj));aj.update_icons();ac.add_drawable(aj);aj.tiles_div.text("Starting job.");this.update_params();this.run(ad,aj,function(ak){aj.set_dataset(new Y.Dataset(ak));aj.tiles_div.text("Running job.");aj.init()})},run:function(ac,ae,af){ac.inputs=this.get_param_values_dict();var ad=new l.ServerStateDeferred({ajax_settings:{url:galaxy_paths.get("tool_url"),data:JSON.stringify(ac),dataType:"json",contentType:"application/json",type:"POST"},interval:2000,success_fn:function(ag){return ag!=="pending"}});$.when(ad.go()).then(function(ag){if(ag==="no converter"){ae.container_div.addClass("error");ae.content_div.text(J)}else{if(ag.error){ae.container_div.addClass("error");ae.content_div.text(y+ag.message)}else{af(ag)}}})}});var N=function(ad,ac,ae,af){this.name=ad;this.label=ac;this.html=$(ae);this.value=af};q(N.prototype,{update_value:function(){this.value=$(this.html).val()}});var e=function(ae,ad,ag,ah,af,ac){N.call(this,ae,ad,ag,ah);this.min=af;this.max=ac};q(e.prototype,N.prototype,{update_value:function(){N.prototype.update_value.call(this);this.value=parseFloat(this.value)}});var C=function(ac,ad){L.Scaler.call(this,ad);this.filter=ac};C.prototype.gen_val=function(ac){if(this.filter.high===Number.MAX_VALUE||this.filter.low===-Number.MAX_VALUE||this.filter.low===this.filter.high){return this.default_val}return((parseFloat(ac[this.filter.index])-this.filter.low)/(this.filter.high-this.filter.low))};var F=function(ac){this.track=ac.track;this.params=ac.params;this.values={};this.restore_values((ac.saved_values?ac.saved_values:{}));this.onchange=ac.onchange};q(F.prototype,{restore_values:function(ac){var ad=this;$.each(this.params,function(ae,af){if(ac[af.key]!==undefined){ad.values[af.key]=ac[af.key]}else{ad.values[af.key]=af.default_value}})},build_form:function(){var af=this;var ac=$("<div />");var ae;function ad(ak,ag){for(var ao=0;ao<ak.length;ao++){ae=ak[ao];if(ae.hidden){continue}var ai="param_"+ao;var at=af.values[ae.key];var av=$("<div class='form-row' />").appendTo(ag);av.append($("<label />").attr("for",ai).text(ae.label+":"));if(ae.type==="bool"){av.append($('<input type="checkbox" />').attr("id",ai).attr("name",ai).attr("checked",at))}else{if(ae.type==="text"){av.append($('<input type="text"/>').attr("id",ai).val(at).click(function(){$(this).select()}))}else{if(ae.type==="select"){var aq=$("<select />").attr("id",ai);for(var am=0;am<ae.options.length;am++){$("<option/>").text(ae.options[am].label).attr("value",ae.options[am].value).appendTo(aq)}aq.val(at);av.append(aq)}else{if(ae.type==="color"){var au=$("<div/>").appendTo(av),ap=$("<input />").attr("id",ai).attr("name",ai).val(at).css("float","left").appendTo(au).click(function(ax){$(".bs-tooltip").removeClass("in");var aw=$(this).siblings(".bs-tooltip").addClass("in");aw.css({left:$(this).position().left+$(this).width()+5,top:$(this).position().top-($(aw).height()/2)+($(this).height()/2)}).show();aw.click(function(ay){ay.stopPropagation()});$(document).bind("click.color-picker",function(){aw.hide();$(document).unbind("click.color-picker")});ax.stopPropagation()}),an=$("<a href='javascript:void(0)'/>").addClass("icon-button arrow-circle").appendTo(au).attr("title","Set new random color").tooltip(),ar=$("<div class='bs-tooltip right' style='position: absolute;' />").appendTo(au).hide(),aj=$("<div class='tooltip-inner' style='text-align: inherit'></div>").appendTo(ar),ah=$("<div class='tooltip-arrow'></div>").appendTo(ar),al=$.farbtastic(aj,{width:100,height:100,callback:ap,color:at});au.append($("<div/>").css("clear","both"));(function(aw){an.click(function(){aw.setColor(l.get_random_color())})})(al)}else{av.append($("<input />").attr("id",ai).attr("name",ai).val(at))}}}}if(ae.help){av.append($("<div class='help'/>").text(ae.help))}}}ad(this.params,ac);return ac},update_from_form:function(ac){var ae=this;var ad=false;$.each(this.params,function(af,ah){if(!ah.hidden){var ai="param_"+af;var ag=ac.find("#"+ai).val();if(ah.type==="float"){ag=parseFloat(ag)}else{if(ah.type==="int"){ag=parseInt(ag,10)}else{if(ah.type==="bool"){ag=ac.find("#"+ai).is(":checked")}}}if(ag!==ae.values[ah.key]){ae.values[ah.key]=ag;ad=true}}});if(ad){this.onchange();this.track.changed()}}});var b=function(ac,ag,ae,ad,af){this.track=ac;this.region=ag;this.low=ag.get("start");this.high=ag.get("end");this.resolution=ae;this.html_elt=$("<div class='track-tile'/>").append(ad).height($(ad).attr("height"));this.data=af;this.stale=false};b.prototype.predisplay_actions=function(){};var j=function(ac,ah,ae,ad,af,ag){b.call(this,ac,ah,ae,ad,af);this.max_val=ag};q(j.prototype,b.prototype);var O=function(af,an,ag,ae,ai,ap,aj,aq,ad,am){b.call(this,af,an,ag,ae,ai);this.mode=aj;this.all_slotted=ad;this.feature_mapper=am;this.has_icons=false;if(aq){this.has_icons=true;var ak=this;ae=this.html_elt.children()[0],message_div=$("<div/>").addClass("tile-message").css({height:D-1,width:ae.width}).prependTo(this.html_elt);var al=new x.GenomeRegion({chrom:af.view.chrom,start:this.low,end:this.high}),ao=ai.length,ah=$("<a href='javascript:void(0);'/>").addClass("icon more-down").attr("title","For speed, only the first "+ao+" features in this region were obtained from server. Click to get more data including depth").tooltip().appendTo(message_div),ac=$("<a href='javascript:void(0);'/>").addClass("icon more-across").attr("title","For speed, only the first "+ao+" features in this region were obtained from server. Click to get more data excluding depth").tooltip().appendTo(message_div);ah.click(function(){ak.stale=true;af.data_manager.get_more_data(al,af.mode,ak.resolution,{},af.data_manager.DEEP_DATA_REQ);$(".bs-tooltip").hide();af.request_draw(true)}).dblclick(function(ar){ar.stopPropagation()});ac.click(function(){ak.stale=true;af.data_manager.get_more_data(al,af.mode,ak.resolution,{},af.data_manager.BROAD_DATA_REQ);$(".bs-tooltip").hide();af.request_draw(true)}).dblclick(function(ar){ar.stopPropagation()})}};q(O.prototype,b.prototype);O.prototype.predisplay_actions=function(){var ad=this,ac={};if(ad.mode!=="Pack"){return}$(this.html_elt).hover(function(){this.hovered=true;$(this).mousemove()},function(){this.hovered=false;$(this).parents(".track-content").children(".overlay").children(".feature-popup").remove()}).mousemove(function(ao){if(!this.hovered){return}var aj=$(this).offset(),an=ao.pageX-aj.left,am=ao.pageY-aj.top,at=ad.feature_mapper.get_feature_data(an,am),ak=(at?at[0]:null);$(this).parents(".track-content").children(".overlay").children(".feature-popup").each(function(){if(!ak||$(this).attr("id")!==ak.toString()){$(this).remove()}});if(at){var af=ac[ak];if(!af){var ak=at[0],ap={name:at[3],start:at[1],end:at[2],strand:at[4]},ai=ad.track.filters_manager.filters,ah;for(var al=0;al<ai.length;al++){ah=ai[al];ap[ah.name]=at[ah.index]}var af=$("<div/>").attr("id",ak).addClass("feature-popup"),au=$("<table/>"),ar,aq,av;for(ar in ap){aq=ap[ar];av=$("<tr/>").appendTo(au);$("<th/>").appendTo(av).text(ar);$("<td/>").attr("align","left").appendTo(av).text(typeof(aq)==="number"?W(aq,2):aq)}af.append($("<div class='feature-popup-inner'>").append(au));ac[ak]=af}af.appendTo($(this).parents(".track-content").children(".overlay"));var ag=an+parseInt(ad.html_elt.css("left"))-af.width()/2,ae=am+parseInt(ad.html_elt.css("top"))+7;af.css("left",ag+"px").css("top",ae+"px")}else{if(!ao.isPropagationStopped()){ao.stopPropagation();$(this).siblings().each(function(){$(this).trigger(ao)})}}}).mouseleave(function(){$(this).parents(".track-content").children(".overlay").children(".feature-popup").remove()})};var g=function(ad,ac,ae){q(ae,{drag_handle_class:"draghandle"});r.call(this,ad,ac,ae);this.dataset=new Y.Dataset({id:ae.dataset_id,hda_ldda:ae.hda_ldda});this.dataset_check_type="converted_datasets_state";this.data_url_extra_params={};this.data_query_wait=("data_query_wait" in ae?ae.data_query_wait:K);this.data_manager=("data_manager" in ae?ae.data_manager:new x.GenomeDataManager({dataset:this.dataset,genome:new x.Genome({key:ad.dbkey,chroms_info:{chrom_info:ad.chrom_data}}),data_mode_compatible:this.data_and_mode_compatible,can_subset:this.can_subset}));this.min_height_px=16;this.max_height_px=800;this.visible_height_px=0;this.content_div=$("<div class='track-content'>").appendTo(this.container_div);if(this.container){this.container.content_div.append(this.container_div);if(!("resize" in ae)||ae.resize){this.add_resize_handle()}}};q(g.prototype,r.prototype,{action_icons_def:[{name:"mode_icon",title:"Set display mode",css_class:"chevron-expand",on_click_fn:function(){}},r.prototype.action_icons_def[0],{name:"overview_icon",title:"Set as overview",css_class:"overview-icon",on_click_fn:function(ac){ac.view.set_overview(ac)}},r.prototype.action_icons_def[1],{name:"filters_icon",title:"Filters",css_class:"filters-icon",on_click_fn:function(ac){if(ac.filters_manager.visible()){ac.filters_manager.clear_filters()}else{ac.filters_manager.init_filters()}ac.filters_manager.toggle()}},{name:"tools_icon",title:"Tool",css_class:"hammer",on_click_fn:function(ac){ac.dynamic_tool_div.toggle();if(ac.dynamic_tool_div.is(":visible")){ac.set_name(ac.name+ac.tool_region_and_parameters_str())}else{ac.revert_name()}$(".bs-tooltip").remove()}},{name:"param_space_viz_icon",title:"Tool parameter space visualization",css_class:"arrow-split",on_click_fn:function(ac){var af='<strong>Tool</strong>: <%= track.tool.name %><br/><strong>Dataset</strong>: <%= track.name %><br/><strong>Region(s)</strong>: <select name="regions"><option value="cur">current viewing area</option><option value="bookmarks">bookmarks</option><option value="both">current viewing area and bookmarks</option></select>',ae=ab.template(af,{track:ac});var ah=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},ad=function(){var aj=$('select[name="regions"] option:selected').val(),al,ai=new x.GenomeRegion({chrom:view.chrom,start:view.low,end:view.high}),ak=ab.map($(".bookmark"),function(am){return new x.GenomeRegion({from_str:$(am).children(".position").text()})});if(aj==="cur"){al=[ai]}else{if(aj==="bookmarks"){al=ak}else{al=[ai].concat(ak)}}hide_modal();window.location.href=galaxy_paths.get("sweepster_url")+"?"+$.param({dataset_id:ac.dataset_id,hda_ldda:ac.hda_ldda,regions:JSON.stringify(new Backbone.Collection(al).toJSON())})},ag=function(ai){if((ai.keyCode||ai.which)===27){ah()}else{if((ai.keyCode||ai.which)===13){ad()}}};show_modal("Visualize tool parameter space and output from different parameter settings?",ae,{No:ah,Yes:ad})}},r.prototype.action_icons_def[2]],can_draw:function(){if(this.dataset_id&&r.prototype.can_draw.call(this)){return true}return false},build_container_div:function(){return $("<div/>").addClass("track").attr("id","track_"+this.id).css("position","relative")},build_header_div:function(){var ac=$("<div class='track-header'/>");if(this.view.editor){this.drag_div=$("<div/>").addClass(this.drag_handle_class).appendTo(ac)}this.name_div=$("<div/>").addClass("track-name").appendTo(ac).text(this.name).attr("id",this.name.replace(/\s+/g,"-").replace(/[^a-zA-Z0-9\-]/g,"").toLowerCase());return ac},on_resize:function(){},add_resize_handle:function(){var ac=this;var af=false;var ae=false;var ad=$("<div class='track-resize'>");$(ac.container_div).hover(function(){if(ac.content_visible){af=true;ad.show()}},function(){af=false;if(!ae){ad.hide()}});ad.hide().bind("dragstart",function(ag,ah){ae=true;ah.original_height=$(ac.content_div).height()}).bind("drag",function(ah,ai){var ag=Math.min(Math.max(ai.original_height+ai.deltaY,ac.min_height_px),ac.max_height_px);$(ac.tiles_div).css("height",ag);ac.visible_height_px=(ac.max_height_px===ag?0:ag);ac.on_resize()}).bind("dragend",function(ag,ah){ac.tile_cache.clear();ae=false;if(!af){ad.hide()}ac.config.values.height=ac.visible_height_px;ac.changed()}).appendTo(ac.container_div)},set_display_modes:function(af,ai){this.display_modes=af;this.mode=(ai?ai:(this.config&&this.config.values.mode?this.config.values.mode:this.display_modes[0]));this.action_icons.mode_icon.attr("title","Set display mode (now: "+this.mode+")");var ad=this,ag={};for(var ae=0,ac=ad.display_modes.length;ae<ac;ae++){var ah=ad.display_modes[ae];ag[ah]=function(aj){return function(){ad.change_mode(aj);ad.icons_div.show();ad.container_div.mouseleave(function(){ad.icons_div.hide()})}}(ah)}make_popupmenu(this.action_icons.mode_icon,ag)},build_action_icons:function(){r.prototype.build_action_icons.call(this,this.action_icons_def);if(this.display_modes!==undefined){this.set_display_modes(this.display_modes)}},hide_contents:function(){this.tiles_div.hide();this.container_div.find(".yaxislabel, .track-resize").hide()},show_contents:function(){this.tiles_div.show();this.container_div.find(".yaxislabel, .track-resize").show();this.request_draw()},get_type:function(){if(this instanceof X){return"LabelTrack"}else{if(this instanceof B){return"ReferenceTrack"}else{if(this instanceof h){return"LineTrack"}else{if(this instanceof T){return"ReadTrack"}else{if(this instanceof R){return"VcfTrack"}else{if(this instanceof f){return"CompositeTrack"}else{if(this instanceof c){return"FeatureTrack"}}}}}}}return""},init:function(ae){var ad=this;ad.enabled=false;ad.tile_cache.clear();ad.data_manager.clear();ad.content_div.css("height","auto");ad.tiles_div.text("").children().remove();ad.container_div.removeClass("nodata error pending");if(!ad.dataset_id){return}var ac=$.Deferred(),af={hda_ldda:ad.hda_ldda,data_type:this.dataset_check_type,chrom:ad.view.chrom,retry:ae};$.getJSON(this.dataset.url(),af,function(ag){if(!ag||ag==="error"||ag.kind==="error"){ad.container_div.addClass("error");ad.tiles_div.text(o);if(ag.message){ad.tiles_div.append($("<a href='javascript:void(0);'></a>").text("View error").click(function(){show_modal("Trackster Error","<pre>"+ag.message+"</pre>",{Close:hide_modal})}));ad.tiles_div.append($("<span/>").text(" "));ad.tiles_div.append($("<a href='javascript:void(0);'></a>").text("Try again").click(function(){ad.init(true)}))}}else{if(ag==="no converter"){ad.container_div.addClass("error");ad.tiles_div.text(J)}else{if(ag==="no data"||(ag.data!==undefined&&(ag.data===null||ag.data.length===0))){ad.container_div.addClass("nodata");ad.tiles_div.text(E)}else{if(ag==="pending"){ad.container_div.addClass("pending");ad.tiles_div.html(v);setTimeout(function(){ad.init()},ad.data_query_wait)}else{if(ag==="data"||ag.status==="data"){if(ag.valid_chroms){ad.valid_chroms=ag.valid_chroms;ad.update_icons()}ad.tiles_div.text(U);if(ad.view.chrom){ad.tiles_div.text("");ad.tiles_div.css("height",ad.visible_height_px+"px");ad.enabled=true;$.when(ad.predraw_init()).done(function(){ac.resolve();ad.container_div.removeClass("nodata error pending");ad.request_draw()})}else{ac.resolve()}}}}}}});this.update_icons();return ac},predraw_init:function(){},get_drawables:function(){return this}});var M=function(ae,ad,af){g.call(this,ae,ad,af);var ac=this;m(ac.container_div,ac.drag_handle_class,".group",ac);this.filters_manager=new i.FiltersManager(this,("filters" in af?af.filters:null));this.data_manager.set("filters_manager",this.filters_manager);this.filters_available=false;this.tool=("tool" in af&&af.tool?new s(this,af.tool,af.tool_state):null);this.tile_cache=new x.Cache(Q);if(this.header_div){this.set_filters_manager(this.filters_manager);if(this.tool){this.dynamic_tool_div=this.tool.parent_div;this.header_div.after(this.dynamic_tool_div)}}this.tiles_div=$("<div/>").addClass("tiles").appendTo(this.content_div);this.overlay_div=$("<div/>").addClass("overlay").appendTo(this.content_div);if(af.mode){this.change_mode(af.mode)}};q(M.prototype,r.prototype,g.prototype,{action_icons_def:g.prototype.action_icons_def.concat([{name:"show_more_rows_icon",title:"To minimize track height, not all feature rows are displayed. Click to display more rows.",css_class:"exclamation",on_click_fn:function(ac){$(".bs-tooltip").remove();ac.slotters[ac.view.resolution_px_b].max_rows*=2;ac.request_draw(true)},hide:true}]),copy:function(ac){var ad=this.to_dict();q(ad,{data_manager:this.data_manager});var ae=new this.constructor(this.view,ac,ad);ae.change_mode(this.mode);ae.enabled=this.enabled;return ae},set_filters_manager:function(ac){this.filters_manager=ac;this.header_div.after(this.filters_manager.parent_div)},to_dict:function(){return{track_type:this.get_type(),name:this.name,hda_ldda:this.hda_ldda,dataset_id:this.dataset_id,prefs:this.prefs,mode:this.mode,filters:this.filters_manager.to_dict(),tool_state:(this.tool?this.tool.state_dict():{})}},change_mode:function(ad){var ac=this;ac.mode=ad;ac.config.values.mode=ad;ac.tile_cache.clear();ac.request_draw();this.action_icons.mode_icon.attr("title","Set display mode (now: "+ac.mode+")");return ac},update_icons:function(){var ac=this;if(ac.filters_available){ac.action_icons.filters_icon.show()}else{ac.action_icons.filters_icon.hide()}if(ac.tool){ac.action_icons.tools_icon.show();ac.action_icons.param_space_viz_icon.show()}else{ac.action_icons.tools_icon.hide();ac.action_icons.param_space_viz_icon.hide()}},_gen_tile_cache_key:function(ad,ac){return ad+"_"+ac},request_draw:function(ad,ac){this.view.request_redraw(false,ad,ac,this)},before_draw:function(){},_draw:function(ad,ao){if(!this.can_draw()){return}var al=this.view.low,ah=this.view.high,aj=ah-al,ae=this.view.container.width(),aq=this.view.resolution_px_b,ag=this.view.resolution_b_px;if(this.is_overview){al=this.view.max_low;ah=this.view.max_high;ag=(view.max_high-view.max_low)/ae;aq=1/ag}this.before_draw();this.tiles_div.children().addClass("remove");var ac=Math.floor(al/(ag*S)),ak=true,ap=[],ai=function(ar){return(ar&&"track" in ar)};while((ac*S*ag)<ah){var am=this._get_tile_bounds(ac,ag),an=this.draw_helper(ad,am,ag,this.tiles_div,aq);if(ai(an)){ap.push(an)}else{ak=false}ac+=1}if(!ao){this.tiles_div.children(".remove").removeClass("remove").remove()}var af=this;if(ak){this.tiles_div.children(".remove").remove();af.postdraw_actions(ap,ae,aq,ao)}},postdraw_actions:function(ad,ae,ag,ac){var af=ab.find(ad,function(ah){return ah.has_icons});if(af){ab.each(ad,function(ah){if(!ah.has_icons){ah.html_elt.css("padding-top",D)}})}},draw_helper:function(ac,af,ar,ah,ai,ao){var an=this,aw=this._gen_tile_cache_key(ai,af);if(!ao){ao={}}var av=(ac?undefined:an.tile_cache.get_elt(aw));if(av){an.show_tile(av,ah,ai);return av}var al=true;var at=an.data_manager.get_data(af,an.mode,ar,an.data_url_extra_params);if(V(at)){al=false}var aj;if(view.reference_track){aj=view.reference_track.data_manager.get_data(af,an.mode,ar,view.reference_track.data_url_extra_params);if(V(aj)){al=false}else{aj=view.reference_track.data_manager.subset_entry(aj,af)}}if(al){q(at,ao.more_tile_data);var ak=an.mode;if(ak==="Auto"){ak=an.get_mode(at);an.update_auto_mode(ak)}var ae=an.view.canvas_manager.new_canvas(),au=af.get("start"),ad=af.get("end"),ap=Math.ceil((ad-au)*ai)+an.left_offset,am=an.get_canvas_height(at,ak,ai,ap);ae.width=ap;ae.height=am;var aq=ae.getContext("2d");aq.translate(this.left_offset,0);var av=an.draw_tile(at,aq,ak,ar,af,ai,aj);if(av!==undefined){an.tile_cache.set_elt(aw,av);an.show_tile(av,ah,ai)}return av}var ag=$.Deferred();$.when(at,aj).then(function(){view.request_redraw(false,false,false,an);ag.resolve()});return ag},get_canvas_height:function(ac,ae,af,ad){return this.visible_height_px},draw_tile:function(ac,ad,ah,af,ag,ai,ae){console.log("Warning: TiledTrack.draw_tile() not implemented.")},show_tile:function(ae,ah,ai){var ad=this,ac=ae.html_elt;ae.predisplay_actions();var ag=(ae.low-(this.is_overview?this.view.max_low:this.view.low))*ai;if(this.left_offset){ag-=this.left_offset}ac.css({position:"absolute",top:0,left:ag});if(ac.hasClass("remove")){ac.removeClass("remove")}else{ah.append(ac)}ae.html_elt.height("auto");this.max_height_px=Math.max(this.max_height_px,ae.html_elt.height());ae.html_elt.parent().children().css("height",this.max_height_px+"px");var af=this.max_height_px;if(this.visible_height_px!==0){af=Math.min(this.max_height_px,this.visible_height_px)}this.tiles_div.css("height",af+"px")},_get_tile_bounds:function(ac,ad){var af=Math.floor(ac*S*ad),ag=Math.ceil(S*ad),ae=(af+ag<=this.view.max_high?af+ag:this.view.max_high);return new x.GenomeRegion({chrom:this.view.chrom,start:af,end:ae})},tool_region_and_parameters_str:function(ae){var ac=this,ad=(ae!==undefined?ae.toString():"all");return" - region=["+ad+"], parameters=["+ac.tool.get_param_values().join(", ")+"]"},data_and_mode_compatible:function(ac,ad){return true},can_subset:function(ac){return false},init_for_tool_data:function(){this.data_manager.set("data_type","raw_data");this.data_query_wait=1000;this.dataset_check_type="state";this.normal_postdraw_actions=this.postdraw_actions;this.postdraw_actions=function(ae,af,ah,ac){var ad=this;ad.normal_postdraw_actions(ae,af,ah,ac);ad.dataset_check_type="converted_datasets_state";ad.data_query_wait=K;var ag=new l.ServerStateDeferred({url:ad.dataset_state_url,url_params:{dataset_id:ad.dataset_id,hda_ldda:ad.hda_ldda},interval:ad.data_query_wait,success_fn:function(ai){return ai!=="pending"}});$.when(ag.go()).then(function(){ad.data_manager.set("data_type","data")});ad.postdraw_actions=ad.normal_postdraw_actions}}});var X=function(ad,ac){var ae={resize:false};g.call(this,ad,ac,ae);this.container_div.addClass("label-track")};q(X.prototype,g.prototype,{build_header_div:function(){},init:function(){this.enabled=true},_draw:function(){var ae=this.view,af=ae.high-ae.low,ai=Math.floor(Math.pow(10,Math.floor(Math.log(af)/Math.log(10)))),ac=Math.floor(ae.low/ai)*ai,ag=this.view.container.width(),ad=$("<div style='position: relative; height: 1.3em;'></div>");while(ac<ae.high){var ah=(ac-ae.low)/af*ag;ad.append($("<div class='label'>"+commatize(ac)+"</div>").css({position:"absolute",left:ah-1}));ac+=ai}this.content_div.children(":first").remove();this.content_div.append(ad)}});var f=function(ad,ac,ag){M.call(this,ad,ac,ag);this.drawables=[];this.left_offset=0;if("drawables" in ag){var af;for(var ae=0;ae<ag.drawables.length;ae++){af=ag.drawables[ae];this.drawables[ae]=p(af,ad,null);if(af.left_offset>this.left_offset){this.left_offset=af.left_offset}}this.enabled=true}if(this.drawables.length!==0){this.set_display_modes(this.drawables[0].display_modes,this.drawables[0].mode)}this.update_icons();this.obj_type="CompositeTrack"};q(f.prototype,M.prototype,{action_icons_def:[{name:"composite_icon",title:"Show individual tracks",css_class:"layers-stack",on_click_fn:function(ac){$(".bs-tooltip").remove();ac.show_group()}}].concat(M.prototype.action_icons_def),to_dict:z.prototype.to_dict,add_drawable:z.prototype.add_drawable,unpack_drawables:z.prototype.unpack_drawables,change_mode:function(ac){M.prototype.change_mode.call(this,ac);for(var ad=0;ad<this.drawables.length;ad++){this.drawables[ad].change_mode(ac)}},init:function(){var ae=[];for(var ad=0;ad<this.drawables.length;ad++){ae.push(this.drawables[ad].init())}var ac=this;$.when.apply($,ae).then(function(){ac.enabled=true;ac.request_draw()})},update_icons:function(){this.action_icons.filters_icon.hide();this.action_icons.tools_icon.hide();this.action_icons.param_space_viz_icon.hide()},can_draw:r.prototype.can_draw,draw_helper:function(ad,ah,av,aj,al,at){var aq=this,aB=this._gen_tile_cache_key(al,ah);if(!at){at={}}var aA=(ad?undefined:aq.tile_cache.get_elt(aB));if(aA){aq.show_tile(aA,aj,al);return aA}var ak=[],aq,ao=true,aw,am;for(var ax=0;ax<this.drawables.length;ax++){aq=this.drawables[ax];aw=aq.data_manager.get_data(ah,aq.mode,av,aq.data_url_extra_params);if(V(aw)){ao=false}ak.push(aw);am=null;if(view.reference_track&&al>view.canvas_manager.char_width_px){am=view.reference_track.data_manager.get_data(ah,aq.mode,av,view.reference_track.data_url_extra_params);if(V(am)){ao=false}}ak.push(am)}if(ao){q(aw,at.more_tile_data);this.tile_predraw_init();var ag=aq.view.canvas_manager.new_canvas(),ay=ah.get("start"),ae=ah.get("end"),az=0,ar=Math.ceil((ae-ay)*al)+this.left_offset,ap=0,af=[],ax;var ac=0;for(ax=0;ax<this.drawables.length;ax++,az+=2){aq=this.drawables[ax];aw=ak[az];var an=aq.mode;if(an==="Auto"){an=aq.get_mode(aw);aq.update_auto_mode(an)}af.push(an);ac=aq.get_canvas_height(aw,an,al,ar);if(ac>ap){ap=ac}}ag.width=ar;ag.height=(at.height?at.height:ap);az=0;var au=ag.getContext("2d");au.translate(this.left_offset,0);au.globalAlpha=0.5;au.globalCompositeOperation="source-over";for(ax=0;ax<this.drawables.length;ax++,az+=2){aq=this.drawables[ax];aw=ak[az];am=ak[az+1];aA=aq.draw_tile(aw,au,af[ax],av,ah,al,am)}this.tile_cache.set_elt(aB,aA);this.show_tile(aA,aj,al);return aA}var ai=$.Deferred(),aq=this;$.when.apply($,ak).then(function(){view.request_redraw(false,false,false,aq);ai.resolve()});return ai},show_group:function(){var af=new P(this.view,this.container,{name:this.name}),ac;for(var ae=0;ae<this.drawables.length;ae++){ac=this.drawables[ae];ac.update_icons();af.add_drawable(ac);ac.container=af;af.content_div.append(ac.container_div)}var ad=this.container.replace_drawable(this,af,true);af.request_draw()},tile_predraw_init:function(){var af=Number.MAX_VALUE,ac=-af,ad;for(var ae=0;ae<this.drawables.length;ae++){ad=this.drawables[ae];if(ad instanceof h){if(ad.prefs.min_value<af){af=ad.prefs.min_value}if(ad.prefs.max_value>ac){ac=ad.prefs.max_value}}}for(var ae=0;ae<this.drawables.length;ae++){ad=this.drawables[ae];ad.prefs.min_value=af;ad.prefs.max_value=ac}},postdraw_actions:function(ae,ah,aj,ad){M.prototype.postdraw_actions.call(this,ae,ah,aj,ad);var ag=-1;for(var af=0;af<ae.length;af++){var ac=ae[af].html_elt.find("canvas").height();if(ac>ag){ag=ac}}for(var af=0;af<ae.length;af++){var ai=ae[af];if(ai.html_elt.find("canvas").height()!==ag){this.draw_helper(true,ai.index,ai.resolution,ai.html_elt.parent(),aj,{height:ag});ai.html_elt.remove()}}}});var B=function(ac){M.call(this,ac,{content_div:ac.top_labeltrack},{resize:false});ac.reference_track=this;this.left_offset=200;this.visible_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_url=reference_url+"/"+this.view.dbkey;this.data_url_extra_params={reference:true};this.data_manager=new x.GenomeReferenceDataManager({data_url:this.data_url,can_subset:this.can_subset});this.hide_contents()};q(B.prototype,r.prototype,M.prototype,{build_header_div:function(){},init:function(){this.data_manager.clear();this.enabled=true},can_draw:r.prototype.can_draw,draw_helper:function(ae,af,ac,ag,ah,ad){if(ah>this.view.canvas_manager.char_width_px){this.tiles_div.show();return M.prototype.draw_helper.call(this,ae,af,ac,ag,ah,ad)}else{this.tiles_div.hide();return null}},can_subset:function(ac){return true},draw_tile:function(af,al,ag,ad,ai,am){var ae=this.data_manager.subset_entry(af,ai),ak=ae.data;var ac=al.canvas;al.font=al.canvas.manager.default_font;al.textAlign="center";for(var ah=0,aj=ak.length;ah<aj;ah++){al.fillStyle=this.view.get_base_color(ak[ah]);al.fillText(ak[ah],Math.floor(ah*am),10)}return new b(this,ai,ad,ac,ae)}});var h=function(ae,ad,af){var ac=this;this.display_modes=["Histogram","Line","Filled","Intensity"];this.mode="Histogram";M.call(this,ae,ad,af);this.hda_ldda=af.hda_ldda;this.dataset_id=af.dataset_id;this.original_dataset_id=this.dataset_id;this.left_offset=0;this.config=new F({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"color",label:"Color",type:"color",default_value:l.get_random_color()},{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:32,hidden:true}],saved_values:af.prefs,onchange:function(){ac.set_name(ac.prefs.name);ac.vertical_range=ac.prefs.max_value-ac.prefs.min_value;ac.set_min_value(ac.prefs.min_value);ac.set_max_value(ac.prefs.max_value)}});this.prefs=this.config.values;this.visible_height_px=this.config.values.height;this.vertical_range=this.config.values.max_value-this.config.values.min_value};q(h.prototype,r.prototype,M.prototype,{on_resize:function(){this.request_draw(true)},set_min_value:function(ac){this.prefs.min_value=ac;$("#linetrack_"+this.dataset_id+"_minval").text(this.prefs.min_value);this.tile_cache.clear();this.request_draw()},set_max_value:function(ac){this.prefs.max_value=ac;$("#linetrack_"+this.dataset_id+"_maxval").text(this.prefs.max_value);this.tile_cache.clear();this.request_draw()},predraw_init:function(){var ac=this;ac.vertical_range=undefined;return $.getJSON(ac.dataset.url(),{data_type:"data",stats:true,chrom:ac.view.chrom,low:0,high:ac.view.max_high,hda_ldda:ac.hda_ldda},function(ad){ac.container_div.addClass("line-track");var ag=ad.data;if(isNaN(parseFloat(ac.prefs.min_value))||isNaN(parseFloat(ac.prefs.max_value))){var ae=ag.min,ai=ag.max;ae=Math.floor(Math.min(0,Math.max(ae,ag.mean-2*ag.sd)));ai=Math.ceil(Math.max(0,Math.min(ai,ag.mean+2*ag.sd)));ac.prefs.min_value=ae;ac.prefs.max_value=ai;$("#track_"+ac.dataset_id+"_minval").val(ac.prefs.min_value);$("#track_"+ac.dataset_id+"_maxval").val(ac.prefs.max_value)}ac.vertical_range=ac.prefs.max_value-ac.prefs.min_value;ac.total_frequency=ag.total_frequency;ac.container_div.find(".yaxislabel").remove();var ah=$("<div/>").text(W(ac.prefs.min_value,3)).make_text_editable({num_cols:6,on_finish:function(aj){$(".bs-tooltip").remove();var aj=parseFloat(aj);if(!isNaN(aj)){ac.set_min_value(aj)}},help_text:"Set min value"}).addClass("yaxislabel bottom").attr("id","linetrack_"+ac.dataset_id+"_minval").prependTo(ac.container_div),af=$("<div/>").text(W(ac.prefs.max_value,3)).make_text_editable({num_cols:6,on_finish:function(aj){$(".bs-tooltip").remove();var aj=parseFloat(aj);if(!isNaN(aj)){ac.set_max_value(aj)}},help_text:"Set max value"}).addClass("yaxislabel top").attr("id","linetrack_"+ac.dataset_id+"_maxval").prependTo(ac.container_div)})},draw_tile:function(al,aj,ae,ad,ag,ak){var ac=aj.canvas,af=ag.get("start"),ai=ag.get("end"),ah=new L.LinePainter(al.data,af,ai,this.prefs,ae);ah.draw(aj,ac.width,ac.height,ak);return new b(this,ag,ad,ac,al.data)},can_subset:function(ac){return(ac.data[1][0]-ac.data[0][0]===1)}});var t=function(ae,ad,af){var ac=this;this.display_modes=["Heatmap"];this.mode="Heatmap";M.call(this,ae,ad,af);this.hda_ldda=af.hda_ldda;this.dataset_id=af.dataset_id;this.original_dataset_id=this.dataset_id;this.left_offset=0;this.config=new F({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"pos_color",label:"Positive Color",type:"color",default_value:"#FF8C00"},{key:"neg_color",label:"Negative Color",type:"color",default_value:"#4169E1"},{key:"min_value",label:"Min Value",type:"float",default_value:-1},{key:"max_value",label:"Max Value",type:"float",default_value:1},{key:"mode",type:"string",default_value:this.mode,hidden:true},{key:"height",type:"int",default_value:500,hidden:true}],saved_values:af.prefs,onchange:function(){ac.set_name(ac.prefs.name);ac.vertical_range=ac.prefs.max_value-ac.prefs.min_value;ac.set_min_value(ac.prefs.min_value);ac.set_max_value(ac.prefs.max_value)}});this.prefs=this.config.values;this.visible_height_px=this.config.values.height;this.vertical_range=this.config.values.max_value-this.config.values.min_value};q(t.prototype,r.prototype,M.prototype,{on_resize:function(){this.request_draw(true)},set_min_value:function(ac){this.prefs.min_value=ac;this.tile_cache.clear();this.request_draw()},set_max_value:function(ac){this.prefs.max_value=ac;this.tile_cache.clear();this.request_draw()},draw_tile:function(ac,ae,ai,ag,ah,aj){var af=ae.canvas,ad=new L.DiagonalHeatmapPainter(ac.data,ah.get("start"),ah.get("end"),this.prefs,ai);ad.draw(ae,af.width,af.height,aj);return new b(this,ah,ag,af,ac.data)}});var c=function(af,ae,ah){var ad=this;this.display_modes=["Auto","Coverage","Dense","Squish","Pack"];M.call(this,af,ae,ah);var ag=l.get_random_color(),ac=l.get_random_color([ag,"#FFFFFF"]);this.config=new F({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"block_color",label:"Block color",type:"color",default_value:ag},{key:"reverse_strand_color",label:"Antisense strand color",type:"color",default_value:ac},{key:"label_color",label:"Label color",type:"color",default_value:"black"},{key:"show_counts",label:"Show summary counts",type:"bool",default_value:true,help:"Show the number of items in each bin when drawing summary histogram"},{key:"histogram_max",label:"Histogram maximum",type:"float",default_value:null,help:"clear value to set automatically"},{key:"connector_style",label:"Connector style",type:"select",default_value:"fishbones",options:[{label:"Line with arrows",value:"fishbone"},{label:"Arcs",value:"arcs"}]},{key:"mode",type:"string",default_value:this.mode,hidden:true},{key:"height",type:"int",default_value:this.visible_height_px,hidden:true}],saved_values:ah.prefs,onchange:function(){ad.set_name(ad.prefs.name);ad.tile_cache.clear();ad.set_painter_from_config();ad.request_draw()}});this.prefs=this.config.values;this.visible_height_px=this.config.values.height;this.container_div.addClass("feature-track");this.hda_ldda=ah.hda_ldda;this.dataset_id=ah.dataset_id;this.original_dataset_id=ah.dataset_id;this.show_labels_scale=0.001;this.showing_details=false;this.summary_draw_height=30;this.slotters={};this.start_end_dct={};this.left_offset=200;this.set_painter_from_config()};q(c.prototype,r.prototype,M.prototype,{set_dataset:function(ac){this.dataset_id=ac.get("id");this.hda_ldda=ac.get("hda_ldda");this.dataset=ac;this.data_manager.set("dataset",ac)},set_painter_from_config:function(){if(this.config.values.connector_style==="arcs"){this.painter=L.ArcLinkedFeaturePainter}else{this.painter=L.LinkedFeaturePainter}},before_draw:function(){this.max_height_px=0},postdraw_actions:function(ar,am,ah,ag){M.prototype.postdraw_actions.call(this,ar,ag);var al=this,ao;if(al.mode==="Coverage"){var ad=-1;for(ao=0;ao<ar.length;ao++){var an=ar[ao].max_val;if(an>ad){ad=an}}for(ao=0;ao<ar.length;ao++){var au=ar[ao];if(au.max_val!==ad){au.html_elt.remove();al.draw_helper(true,au.index,au.resolution,au.html_elt.parent(),ah,{more_tile_data:{max:ad}})}}}if(al.filters_manager){var ai=al.filters_manager.filters;for(var aq=0;aq<ai.length;aq++){ai[aq].update_ui_elt()}var at=false,ac,aj;for(ao=0;ao<ar.length;ao++){if(ar[ao].data.length){ac=ar[ao].data[0];for(var aq=0;aq<ai.length;aq++){aj=ai[aq];if(aj.applies_to(ac)&&aj.min!==aj.max){at=true;break}}}}if(al.filters_available!==at){al.filters_available=at;if(!al.filters_available){al.filters_manager.hide()}al.update_icons()}}this.container_div.find(".yaxislabel").remove();var af=ar[0];if(af instanceof j){var ak=(this.prefs.histogram_max?this.prefs.histogram_max:af.max_val),ae=$("<div/>").text(ak).make_text_editable({num_cols:12,on_finish:function(av){$(".bs-tooltip").remove();var av=parseFloat(av);al.prefs.histogram_max=(!isNaN(av)?av:null);al.tile_cache.clear();al.request_draw()},help_text:"Set max value; leave blank to use default"}).addClass("yaxislabel top").css("color",this.prefs.label_color);this.container_div.prepend(ae)}if(af instanceof O){var ap=true;for(ao=0;ao<ar.length;ao++){if(!ar[ao].all_slotted){ap=false;break}}if(!ap){this.action_icons.show_more_rows_icon.show()}else{this.action_icons.show_more_rows_icon.hide()}}else{this.action_icons.show_more_rows_icon.hide()}},update_auto_mode:function(ac){var ac;if(this.mode==="Auto"){if(ac==="no_detail"){ac="feature spans"}else{if(ac==="summary_tree"){ac="coverage histogram"}}this.action_icons.mode_icon.attr("title","Set display mode (now: Auto/"+ac+")")}},incremental_slots:function(ag,ac,af){var ad=this.view.canvas_manager.dummy_context,ae=this.slotters[ag];if(!ae||(ae.mode!==af)){ae=new (u.FeatureSlotter)(ag,af,A,function(ah){return ad.measureText(ah)});this.slotters[ag]=ae}return ae.slot_features(ac)},get_mode:function(ac){if(ac.dataset_type==="summary_tree"){mode="summary_tree"}else{if(ac.extra_info==="no_detail"||this.is_overview){mode="no_detail"}else{if(this.view.high-this.view.low>I){mode="Squish"}else{mode="Pack"}}}return mode},get_canvas_height:function(ac,ag,ah,ad){if(ag==="summary_tree"||ag==="Coverage"){return this.summary_draw_height}else{var af=this.incremental_slots(ah,ac.data,ag);var ae=new (this.painter)(null,null,null,this.prefs,ag);return Math.max(aa,ae.get_required_height(af,ad))}},draw_tile:function(am,aq,ao,ar,af,aj,ae){var ap=this,ad=aq.canvas,ay=af.get("start"),ac=af.get("end"),ag=this.left_offset;if(ao==="summary_tree"||ao==="Coverage"){var aA=new L.SummaryTreePainter(am,ay,ac,this.prefs);aA.draw(aq,ad.width,ad.height,aj);return new j(ap,af,ar,ad,am.data,am.max)}var ai=[],an=this.slotters[aj].slots;all_slotted=true;if(am.data){var ak=this.filters_manager.filters;for(var at=0,av=am.data.length;at<av;at++){var ah=am.data[at];var au=false;var al;for(var ax=0,aC=ak.length;ax<aC;ax++){al=ak[ax];al.update_attrs(ah);if(!al.keep(ah)){au=true;break}}if(!au){ai.push(ah);if(!(ah[0] in an)){all_slotted=false}}}}var aB=(this.filters_manager.alpha_filter?new C(this.filters_manager.alpha_filter):null),az=(this.filters_manager.height_filter?new C(this.filters_manager.height_filter):null),aA=new (this.painter)(ai,ay,ac,this.prefs,ao,aB,az,ae,function(aD){return ap.view.get_base_color(aD)});var aw=null;aq.fillStyle=this.prefs.block_color;aq.font=aq.canvas.manager.default_font;aq.textAlign="right";if(am.data){aw=aA.draw(aq,ad.width,ad.height,aj,an);aw.translation=-ag}return new O(ap,af,ar,ad,am.data,aj,ao,am.message,all_slotted,aw)},data_and_mode_compatible:function(ac,ad){if(ad==="Auto"){return true}else{if(ad==="Coverage"){return ac.dataset_type==="summary_tree"}else{if(ac.extra_info==="no_detail"||ac.dataset_type==="summary_tree"){return false}else{return true}}}},can_subset:function(ac){if(ac.dataset_type==="summary_tree"||ac.message||ac.extra_info==="no_detail"){return false}return true}});var R=function(ad,ac,ae){c.call(this,ad,ac,ae);this.config=new F({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"block_color",label:"Block color",type:"color",default_value:l.get_random_color()},{key:"label_color",label:"Label color",type:"color",default_value:"black"},{key:"show_insertions",label:"Show insertions",type:"bool",default_value:false},{key:"show_counts",label:"Show summary counts",type:"bool",default_value:true},{key:"mode",type:"string",default_value:this.mode,hidden:true}],saved_values:ae.prefs,onchange:function(){this.track.set_name(this.track.prefs.name);this.track.tile_cache.clear();this.track.request_draw()}});this.prefs=this.config.values;this.painter=L.ReadPainter};q(R.prototype,r.prototype,M.prototype,c.prototype);var T=function(ae,ad,ag){c.call(this,ae,ad,ag);var af=l.get_random_color(),ac=l.get_random_color([af,"#ffffff"]);this.config=new F({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"block_color",label:"Block and sense strand color",type:"color",default_value:af},{key:"reverse_strand_color",label:"Antisense strand color",type:"color",default_value:ac},{key:"label_color",label:"Label color",type:"color",default_value:"black"},{key:"show_insertions",label:"Show insertions",type:"bool",default_value:false},{key:"show_differences",label:"Show differences only",type:"bool",default_value:true},{key:"show_counts",label:"Show summary counts",type:"bool",default_value:true},{key:"histogram_max",label:"Histogram maximum",type:"float",default_value:null,help:"Clear value to set automatically"},{key:"mode",type:"string",default_value:this.mode,hidden:true}],saved_values:ag.prefs,onchange:function(){this.track.set_name(this.track.prefs.name);this.track.tile_cache.clear();this.track.request_draw()}});this.prefs=this.config.values;this.painter=(ae.reference_track?L.RefBasedReadPainter:L.ReadPainter);this.update_icons()};q(T.prototype,r.prototype,M.prototype,c.prototype);var d={LineTrack:h,FeatureTrack:c,VcfTrack:R,ReadTrack:T,DiagonalHeatmapTrack:t,CompositeTrack:f,DrawableGroup:P};var p=function(ae,ad,ac){if("copy" in ae){return ae.copy(ac)}else{var af=ae.obj_type;if(!af){af=ae.track_type}return new d[af](ad,ac,ae)}};return{TracksterView:Z,DrawableGroup:P,LineTrack:h,FeatureTrack:c,DiagonalHeatmapTrack:t,ReadTrack:T,VcfTrack:R,CompositeTrack:f,object_from_template:p}});
\ No newline at end of file
+define(["libs/underscore","viz/visualization","viz/trackster/util","viz/trackster/slotting","viz/trackster/painters","mvc/data","viz/trackster/filters"],function(ab,x,l,u,L,X,i){var q=ab.extend;var U=function(ac){return("isResolved" in ac)};var n={};var k=function(ac,ad){n[ac.attr("id")]=ad};var m=function(ac,ae,ag,af){ag=".group";var ad={};n[ac.attr("id")]=af;ac.bind("drag",{handle:"."+ae,relative:true},function(ao,ap){var an=$(this),at=$(this).parent(),ak=at.children(),am=n[$(this).attr("id")],aj,ai,aq,ah,al;ai=$(this).parents(ag);if(ai.length!==0){aq=ai.position().top;ah=aq+ai.outerHeight();if(ap.offsetY<aq){$(this).insertBefore(ai);var ar=n[ai.attr("id")];ar.remove_drawable(am);ar.container.add_drawable_before(am,ar);return}else{if(ap.offsetY>ah){$(this).insertAfter(ai);var ar=n[ai.attr("id")];ar.remove_drawable(am);ar.container.add_drawable(am);return}}}ai=null;for(al=0;al<ak.length;al++){aj=$(ak.get(al));aq=aj.position().top;ah=aq+aj.outerHeight();if(aj.is(ag)&&this!==aj.get(0)&&ap.offsetY>=aq&&ap.offsetY<=ah){if(ap.offsetY-aq<ah-ap.offsetY){aj.find(".content-div").prepend(this)}else{aj.find(".content-div").append(this)}if(am.container){am.container.remove_drawable(am)}n[aj.attr("id")].add_drawable(am);return}}for(al=0;al<ak.length;al++){aj=$(ak.get(al));if(ap.offsetY<aj.position().top&&!(aj.hasClass("reference-track")||aj.hasClass("intro"))){break}}if(al===ak.length){if(this!==ak.get(al-1)){at.append(this);n[at.attr("id")].move_drawable(am,al)}}else{if(this!==ak.get(al)){$(this).insertBefore(ak.get(al));n[at.attr("id")].move_drawable(am,(ap.deltaY>0?al-1:al))}}}).bind("dragstart",function(){ad["border-top"]=ac.css("border-top");ad["border-bottom"]=ac.css("border-bottom");$(this).css({"border-top":"1px solid blue","border-bottom":"1px solid blue"})}).bind("dragend",function(){$(this).css(ad)})};var aa=16,G=9,D=20,A=100,I=12000,R=400,K=5000,w=100,o="Cannot display dataset due to an error. ",J="A converter for this dataset is not installed. Please check your datatypes_conf.xml file.",E="No data for this chrom/contig.",v="Preparing data. This can take a while for a large dataset. If the visualization is saved and closed, preparation will continue in the background.",y="Tool cannot be rerun: ",a="Loading data...",T="Ready for display",Q=10,H=20;function V(ad,ac){if(!ac){ac=0}var ae=Math.pow(10,ac);return Math.round(ad*ae)/ae}var r=function(ad,ac,af){if(!r.id_counter){r.id_counter=0}this.id=r.id_counter++;this.name=af.name;this.view=ad;this.container=ac;this.config=new F({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name}],saved_values:af.prefs,onchange:function(){this.track.set_name(this.track.config.values.name)}});this.prefs=this.config.values;this.drag_handle_class=af.drag_handle_class;this.is_overview=false;this.action_icons={};this.content_visible=true;this.container_div=this.build_container_div();this.header_div=this.build_header_div();if(this.header_div){this.container_div.append(this.header_div);this.icons_div=$("<div/>").css("float","left").hide().appendTo(this.header_div);this.build_action_icons(this.action_icons_def);this.header_div.append($("<div style='clear: both'/>"));this.header_div.dblclick(function(ag){ag.stopPropagation()});var ae=this;this.container_div.hover(function(){ae.icons_div.show()},function(){ae.icons_div.hide()});$("<div style='clear: both'/>").appendTo(this.container_div)}};r.prototype.action_icons_def=[{name:"toggle_icon",title:"Hide/show content",css_class:"toggle",on_click_fn:function(ac){if(ac.content_visible){ac.action_icons.toggle_icon.addClass("toggle-expand").removeClass("toggle");ac.hide_contents();ac.content_visible=false}else{ac.action_icons.toggle_icon.addClass("toggle").removeClass("toggle-expand");ac.content_visible=true;ac.show_contents()}}},{name:"settings_icon",title:"Edit settings",css_class:"settings-icon",on_click_fn:function(ad){var af=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},ac=function(){ad.config.update_from_form($(".dialog-box"));hide_modal();$(window).unbind("keypress.check_enter_esc")},ae=function(ag){if((ag.keyCode||ag.which)===27){af()}else{if((ag.keyCode||ag.which)===13){ac()}}};$(window).bind("keypress.check_enter_esc",ae);show_modal("Configure",ad.config.build_form(),{Cancel:af,OK:ac})}},{name:"remove_icon",title:"Remove",css_class:"remove-icon",on_click_fn:function(ac){$(".bs-tooltip").remove();ac.remove()}}];q(r.prototype,{init:function(){},changed:function(){this.view.changed()},can_draw:function(){if(this.enabled&&this.content_visible){return true}return false},request_draw:function(){},_draw:function(){},to_dict:function(){},set_name:function(ac){this.old_name=this.name;this.name=ac;this.name_div.text(this.name)},revert_name:function(){if(this.old_name){this.name=this.old_name;this.name_div.text(this.name)}},remove:function(){this.changed();this.container.remove_drawable(this);var ac=this.view;this.container_div.hide(0,function(){$(this).remove();ac.update_intro_div()})},build_container_div:function(){},build_header_div:function(){},add_action_icon:function(ad,ai,ah,ag,ac,af){var ae=this;this.action_icons[ad]=$("<a/>").attr("href","javascript:void(0);").attr("title",ai).addClass("icon-button").addClass(ah).tooltip().click(function(){ag(ae)}).appendTo(this.icons_div);if(af){this.action_icons[ad].hide()}},build_action_icons:function(ac){var ae;for(var ad=0;ad<ac.length;ad++){ae=ac[ad];this.add_action_icon(ae.name,ae.title,ae.css_class,ae.on_click_fn,ae.prepend,ae.hide)}},update_icons:function(){},hide_contents:function(){},show_contents:function(){},get_drawables:function(){}});var z=function(ad,ac,ae){r.call(this,ad,ac,ae);this.obj_type=ae.obj_type;this.drawables=[]};q(z.prototype,r.prototype,{unpack_drawables:function(ae){this.drawables=[];var ad;for(var ac=0;ac<ae.length;ac++){ad=p(ae[ac],this.view,this);this.add_drawable(ad)}},init:function(){for(var ac=0;ac<this.drawables.length;ac++){this.drawables[ac].init()}},_draw:function(){for(var ac=0;ac<this.drawables.length;ac++){this.drawables[ac]._draw()}},to_dict:function(){var ad=[];for(var ac=0;ac<this.drawables.length;ac++){ad.push(this.drawables[ac].to_dict())}return{name:this.name,prefs:this.prefs,obj_type:this.obj_type,drawables:ad}},add_drawable:function(ac){this.drawables.push(ac);ac.container=this;this.changed()},add_drawable_before:function(ae,ac){this.changed();var ad=this.drawables.indexOf(ac);if(ad!==-1){this.drawables.splice(ad,0,ae);return true}return false},replace_drawable:function(ae,ac,ad){var af=this.drawables.indexOf(ae);if(af!==-1){this.drawables[af]=ac;if(ad){ae.container_div.replaceWith(ac.container_div)}this.changed()}return af},remove_drawable:function(ad){var ac=this.drawables.indexOf(ad);if(ac!==-1){this.drawables.splice(ac,1);ad.container=null;this.changed();return true}return false},move_drawable:function(ad,ae){var ac=this.drawables.indexOf(ad);if(ac!==-1){this.drawables.splice(ac,1);this.drawables.splice(ae,0,ad);this.changed();return true}return false},get_drawables:function(){return this.drawables}});var P=function(ad,ac,af){q(af,{obj_type:"DrawableGroup",drag_handle_class:"group-handle"});z.call(this,ad,ac,af);this.content_div=$("<div/>").addClass("content-div").attr("id","group_"+this.id+"_content_div").appendTo(this.container_div);k(this.container_div,this);k(this.content_div,this);m(this.container_div,this.drag_handle_class,".group",this);this.filters_manager=new i.FiltersManager(this);this.header_div.after(this.filters_manager.parent_div);this.saved_filters_managers=[];if("drawables" in af){this.unpack_drawables(af.drawables)}if("filters" in af){var ae=this.filters_manager;this.filters_manager=new i.FiltersManager(this,af.filters);ae.parent_div.replaceWith(this.filters_manager.parent_div);if(af.filters.visible){this.setup_multitrack_filtering()}}};q(P.prototype,r.prototype,z.prototype,{action_icons_def:[r.prototype.action_icons_def[0],r.prototype.action_icons_def[1],{name:"composite_icon",title:"Show composite track",css_class:"layers-stack",on_click_fn:function(ac){$(".bs-tooltip").remove();ac.show_composite_track()}},{name:"filters_icon",title:"Filters",css_class:"filters-icon",on_click_fn:function(ac){if(ac.filters_manager.visible()){ac.filters_manager.clear_filters();ac._restore_filter_managers()}else{ac.setup_multitrack_filtering();ac.request_draw(true)}ac.filters_manager.toggle()}},r.prototype.action_icons_def[2]],build_container_div:function(){var ac=$("<div/>").addClass("group").attr("id","group_"+this.id);if(this.container){this.container.content_div.append(ac)}return ac},build_header_div:function(){var ac=$("<div/>").addClass("track-header");ac.append($("<div/>").addClass(this.drag_handle_class));this.name_div=$("<div/>").addClass("track-name").text(this.name).appendTo(ac);return ac},hide_contents:function(){this.tiles_div.hide()},show_contents:function(){this.tiles_div.show();this.request_draw()},update_icons:function(){var ae=this.drawables.length;if(ae===0){this.action_icons.composite_icon.hide();this.action_icons.filters_icon.hide()}else{if(ae===1){if(this.drawables[0] instanceof f){this.action_icons.composite_icon.show()}this.action_icons.filters_icon.hide()}else{var al,ak,ai,ao=true,ag=this.drawables[0].get_type(),ac=0;for(al=0;al<ae;al++){ai=this.drawables[al];if(ai.get_type()!==ag){can_composite=false;break}if(ai instanceof c){ac++}}if(ao||ac===1){this.action_icons.composite_icon.show()}else{this.action_icons.composite_icon.hide();$(".bs-tooltip").remove()}if(ac>1&&ac===this.drawables.length){var ap={},ad;ai=this.drawables[0];for(ak=0;ak<ai.filters_manager.filters.length;ak++){ad=ai.filters_manager.filters[ak];ap[ad.name]=[ad]}for(al=1;al<this.drawables.length;al++){ai=this.drawables[al];for(ak=0;ak<ai.filters_manager.filters.length;ak++){ad=ai.filters_manager.filters[ak];if(ad.name in ap){ap[ad.name].push(ad)}}}this.filters_manager.remove_all();var af,ah,aj,am;for(var an in ap){af=ap[an];if(af.length===ac){ah=new i.NumberFilter({name:af[0].name,index:af[0].index});this.filters_manager.add_filter(ah)}}if(this.filters_manager.filters.length>0){this.action_icons.filters_icon.show()}else{this.action_icons.filters_icon.hide()}}else{this.action_icons.filters_icon.hide()}}}},_restore_filter_managers:function(){for(var ac=0;ac<this.drawables.length;ac++){this.drawables[ac].filters_manager=this.saved_filters_managers[ac]}this.saved_filters_managers=[]},setup_multitrack_filtering:function(){if(this.filters_manager.filters.length>0){this.saved_filters_managers=[];for(var ac=0;ac<this.drawables.length;ac++){drawable=this.drawables[ac];this.saved_filters_managers.push(drawable.filters_manager);drawable.filters_manager=this.filters_manager}}this.filters_manager.init_filters()},show_composite_track:function(){var af=[];for(var ad=0;ad<this.drawables.length;ad++){af.push(this.drawables[ad].name)}var ae=new f(this.view,this.view,{name:this.name,drawables:this.drawables});var ac=this.container.replace_drawable(this,ae,true);ae.request_draw()},add_drawable:function(ac){z.prototype.add_drawable.call(this,ac);this.update_icons()},remove_drawable:function(ac){z.prototype.remove_drawable.call(this,ac);this.update_icons()},to_dict:function(){if(this.filters_manager.visible()){this._restore_filter_managers()}var ac=q(z.prototype.to_dict.call(this),{filters:this.filters_manager.to_dict()});if(this.filters_manager.visible()){this.setup_multitrack_filtering()}return ac},request_draw:function(ac,ae){for(var ad=0;ad<this.drawables.length;ad++){this.drawables[ad].request_draw(ac,ae)}}});var Y=Backbone.View.extend({initialize:function(ac){q(ac,{obj_type:"View"});z.call(this,"View",ac.container,ac);this.chrom=null;this.vis_id=ac.vis_id;this.dbkey=ac.dbkey;this.label_tracks=[];this.tracks_to_be_redrawn=[];this.max_low=0;this.max_high=0;this.zoom_factor=3;this.min_separation=30;this.has_changes=false;this.load_chroms_deferred=null;this.render();this.canvas_manager=new x.CanvasManager(this.container.get(0).ownerDocument);this.reset();this.config=new F({track:this,params:[{key:"a_color",label:"A Color",type:"color",default_value:"#FF0000"},{key:"c_color",label:"C Color",type:"color",default_value:"#00FF00"},{key:"g_color",label:"G Color",type:"color",default_value:"#0000FF"},{key:"t_color",label:"T Color",type:"color",default_value:"#FF00FF"},{key:"n_color",label:"N Color",type:"color",default_value:"#AAAAAA"},],saved_values:ac.prefs,onchange:function(){track.request_redraw(false,true)}})},render:function(){this.requested_redraw=false;var ae=this.container,ac=this;this.top_container=$("<div/>").addClass("top-container").appendTo(ae);this.browser_content_div=$("<div/>").addClass("content").css("position","relative").appendTo(ae);this.bottom_container=$("<div/>").addClass("bottom-container").appendTo(ae);this.top_labeltrack=$("<div/>").addClass("top-labeltrack").appendTo(this.top_container);this.viewport_container=$("<div/>").addClass("viewport-container").attr("id","viewport-container").appendTo(this.browser_content_div);this.content_div=this.viewport_container;k(this.viewport_container,ac);this.intro_div=$("<div/>").addClass("intro").appendTo(this.viewport_container).hide();var af=$("<div/>").text("Add Datasets to Visualization").addClass("action-button").appendTo(this.intro_div).click(function(){x.select_datasets(select_datasets_url,add_track_async_url,{"f-dbkey":ac.dbkey},function(ag){ab.each(ag,function(ah){ac.add_drawable(p(ah,ac,ac))})})});this.nav_labeltrack=$("<div/>").addClass("nav-labeltrack").appendTo(this.bottom_container);this.nav_container=$("<div/>").addClass("trackster-nav-container").prependTo(this.top_container);this.nav=$("<div/>").addClass("trackster-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/>").attr("href","javascript:void(0);").attr("title","Close overview").addClass("icon-button overview-close tooltip").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_select=$("<select/>").attr({name:"chrom"}).css("width","15em").append("<option value=''>Loading</option>").appendTo(this.nav_controls);var ad=function(ag){if(ag.type==="focusout"||(ag.keyCode||ag.which)===13||(ag.keyCode||ag.which)===27){if((ag.keyCode||ag.which)!==27){ac.go_to($(this).val())}$(this).hide();$(this).val("");ac.location_span.show();ac.chrom_select.show()}};this.nav_input=$("<input/>").addClass("nav-input").hide().bind("keyup focusout",ad).appendTo(this.nav_controls);this.location_span=$("<span/>").addClass("location").attr("original-title","Click to change location").tooltip({placement:"bottom"}).appendTo(this.nav_controls);this.location_span.click(function(){ac.location_span.hide();ac.chrom_select.hide();ac.nav_input.val(ac.chrom+":"+ac.low+"-"+ac.high);ac.nav_input.css("display","inline-block");ac.nav_input.select();ac.nav_input.focus();ac.nav_input.autocomplete({source:function(ai,ag){var aj=[],ah=$.map(ac.get_drawables(),function(ak){return ak.data_manager.search_features(ai.term).success(function(al){aj=aj.concat(al)})});$.when.apply($,ah).done(function(){ag($.map(aj,function(ak){return{label:ak[0],value:ak[1]}}))})}})});if(this.vis_id!==undefined){this.hidden_input=$("<input/>").attr("type","hidden").val(this.vis_id).appendTo(this.nav_controls)}this.zo_link=$("<a/>").attr("id","zoom-out").attr("title","Zoom out").tooltip({placement:"bottom"}).click(function(){ac.zoom_out();ac.request_redraw()}).appendTo(this.nav_controls);this.zi_link=$("<a/>").attr("id","zoom-in").attr("title","Zoom in").tooltip({placement:"bottom"}).click(function(){ac.zoom_in();ac.request_redraw()}).appendTo(this.nav_controls);this.load_chroms_deferred=this.load_chroms({low:0});this.chrom_select.bind("change",function(){ac.change_chrom(ac.chrom_select.val())});this.browser_content_div.click(function(ag){$(this).find("input").trigger("blur")});this.browser_content_div.bind("dblclick",function(ag){ac.zoom_in(ag.pageX,this.viewport_container)});this.overview_box.bind("dragstart",function(ag,ah){this.current_x=ah.offsetX}).bind("drag",function(ag,ai){var aj=ai.offsetX-this.current_x;this.current_x=ai.offsetX;var ah=Math.round(aj/ac.viewport_container.width()*(ac.max_high-ac.max_low));ac.move_delta(-ah)});this.overview_close.click(function(){ac.reset_overview()});this.viewport_container.bind("draginit",function(ag,ah){if(ag.clientX>ac.viewport_container.width()-16){return false}}).bind("dragstart",function(ag,ah){ah.original_low=ac.low;ah.current_height=ag.clientY;ah.current_x=ah.offsetX}).bind("drag",function(ai,ak){var ag=$(this);var al=ak.offsetX-ak.current_x;var ah=ag.scrollTop()-(ai.clientY-ak.current_height);ag.scrollTop(ah);ak.current_height=ai.clientY;ak.current_x=ak.offsetX;var aj=Math.round(al/ac.viewport_container.width()*(ac.high-ac.low));ac.move_delta(aj)}).bind("mousewheel",function(ai,ak,ah,ag){if(ah){ah*=50;var aj=Math.round(-ah/ac.viewport_container.width()*(ac.high-ac.low));ac.move_delta(aj)}});this.top_labeltrack.bind("dragstart",function(ag,ah){return $("<div />").css({height:ac.browser_content_div.height()+ac.top_labeltrack.height()+ac.nav_labeltrack.height()+1,top:"0px",position:"absolute","background-color":"#ccf",opacity:0.5,"z-index":1000}).appendTo($(this))}).bind("drag",function(ak,al){$(al.proxy).css({left:Math.min(ak.pageX,al.startX)-ac.container.offset().left,width:Math.abs(ak.pageX-al.startX)});var ah=Math.min(ak.pageX,al.startX)-ac.container.offset().left,ag=Math.max(ak.pageX,al.startX)-ac.container.offset().left,aj=(ac.high-ac.low),ai=ac.viewport_container.width();ac.update_location(Math.round(ah/ai*aj)+ac.low,Math.round(ag/ai*aj)+ac.low)}).bind("dragend",function(al,am){var ah=Math.min(al.pageX,am.startX),ag=Math.max(al.pageX,am.startX),aj=(ac.high-ac.low),ai=ac.viewport_container.width(),ak=ac.low;ac.low=Math.round(ah/ai*aj)+ak;ac.high=Math.round(ag/ai*aj)+ak;$(am.proxy).remove();ac.request_redraw()});this.add_label_track(new W(this,{content_div:this.top_labeltrack}));this.add_label_track(new W(this,{content_div:this.nav_labeltrack}));$(window).bind("resize",function(){if(this.resize_timer){clearTimeout(this.resize_timer)}this.resize_timer=setTimeout(function(){ac.resize_window()},500)});$(document).bind("redraw",function(){ac.redraw()});this.reset();$(window).trigger("resize")},get_base_color:function(ac){return this.config.values[ac.toLowerCase()+"_color"]}});q(Y.prototype,z.prototype,{changed:function(){this.has_changes=true},update_intro_div:function(){if(this.drawables.length===0){this.intro_div.show()}else{this.intro_div.hide()}},trigger_navigate:function(ad,af,ac,ag){if(this.timer){clearTimeout(this.timer)}if(ag){var ae=this;this.timer=setTimeout(function(){ae.trigger("navigate",ad+":"+af+"-"+ac)},500)}else{view.trigger("navigate",ad+":"+af+"-"+ac)}},update_location:function(ac,ae){this.location_span.text(commatize(ac)+" - "+commatize(ae));this.nav_input.val(this.chrom+":"+commatize(ac)+"-"+commatize(ae));var ad=view.chrom_select.val();if(ad!==""){this.trigger_navigate(ad,view.low,view.high,true)}},load_chroms:function(ae){ae.num=w;var ac=this,ad=$.Deferred();$.ajax({url:chrom_url+"/"+this.dbkey,data:ae,dataType:"json",success:function(ag){if(ag.chrom_info.length===0){return}if(ag.reference){ac.add_label_track(new B(ac))}ac.chrom_data=ag.chrom_info;var aj='<option value="">Select Chrom/Contig</option>';for(var ai=0,af=ac.chrom_data.length;ai<af;ai++){var ah=ac.chrom_data[ai].chrom;aj+='<option value="'+ah+'">'+ah+"</option>"}if(ag.prev_chroms){aj+='<option value="previous">Previous '+w+"</option>"}if(ag.next_chroms){aj+='<option value="next">Next '+w+"</option>"}ac.chrom_select.html(aj);ac.chrom_start_index=ag.start_index;ad.resolve(ag.chrom_info)},error:function(){alert("Could not load chroms for this dbkey:",ac.dbkey)}});return ad},change_chrom:function(ah,ad,aj){var ae=this;if(!ae.chrom_data){ae.load_chroms_deferred.then(function(){ae.change_chrom(ah,ad,aj)});return}if(!ah||ah==="None"){return}if(ah==="previous"){ae.load_chroms({low:this.chrom_start_index-w});return}if(ah==="next"){ae.load_chroms({low:this.chrom_start_index+w});return}var ai=$.grep(ae.chrom_data,function(ak,al){return ak.chrom===ah})[0];if(ai===undefined){ae.load_chroms({chrom:ah},function(){ae.change_chrom(ah,ad,aj)});return}else{if(ah!==ae.chrom){ae.chrom=ah;ae.chrom_select.val(ae.chrom);ae.max_high=ai.len-1;ae.reset();ae.request_redraw(true);for(var ag=0,ac=ae.drawables.length;ag<ac;ag++){var af=ae.drawables[ag];if(af.init){af.init()}}if(ae.reference_track){ae.reference_track.init()}}if(ad&&aj){ae.low=Math.max(ad,0);ae.high=Math.min(aj,ae.max_high)}else{ae.low=0;ae.high=ae.max_high}ae.reset_overview();ae.request_redraw()}},go_to:function(ag){ag=ag.replace(/,/g,"");ag=ag.replace(/:|\-/g," ");var ad=ag.split(/\s+/),af=ad[0],ae=(ad[1]?parseInt(ad[1],10):null),ac=(ad[2]?parseInt(ad[2],10):null);if(!ac){ae=ae-15;ac=ae+15}this.change_chrom(af,ae,ac)},move_fraction:function(ae){var ac=this;var ad=ac.high-ac.low;this.move_delta(ae*ad)},move_delta:function(af){var ac=this;var ae=ac.high-ac.low;if(ac.low-af<ac.max_low){ac.low=ac.max_low;ac.high=ac.max_low+ae}else{if(ac.high-af>ac.max_high){ac.high=ac.max_high;ac.low=ac.max_high-ae}else{ac.high-=af;ac.low-=af}}ac.request_redraw();var ad=ac.chrom_select.val();this.trigger_navigate(ad,ac.low,ac.high,true)},add_drawable:function(ac){z.prototype.add_drawable.call(this,ac);ac.init();this.changed();this.update_intro_div()},add_label_track:function(ac){ac.view=this;ac.init();this.label_tracks.push(ac)},remove_drawable:function(ae,ad){z.prototype.remove_drawable.call(this,ae);if(ad){var ac=this;ae.container_div.hide(0,function(){$(this).remove();ac.update_intro_div()})}},reset:function(){this.low=this.max_low;this.high=this.max_high;this.viewport_container.find(".yaxislabel").remove()},request_redraw:function(ak,ac,aj,al){var ai=this,ah=(al?[al]:ai.drawables),ae;var ad;for(var ag=0;ag<ah.length;ag++){ad=ah[ag];ae=-1;for(var af=0;af<ai.tracks_to_be_redrawn.length;af++){if(ai.tracks_to_be_redrawn[af][0]===ad){ae=af;break}}if(ae<0){ai.tracks_to_be_redrawn.push([ad,ac,aj])}else{ai.tracks_to_be_redrawn[ag][1]=ac;ai.tracks_to_be_redrawn[ag][2]=aj}}if(!this.requested_redraw){requestAnimationFrame(function(){ai._redraw(ak)});this.requested_redraw=true}},_redraw:function(am){this.requested_redraw=false;var aj=this.low,af=this.high;if(aj<this.max_low){aj=this.max_low}if(af>this.max_high){af=this.max_high}var al=this.high-this.low;if(this.high!==0&&al<this.min_separation){af=aj+this.min_separation}this.low=Math.floor(aj);this.high=Math.ceil(af);this.update_location(this.low,this.high);this.resolution_b_px=(this.high-this.low)/this.viewport_container.width();this.resolution_px_b=1/this.resolution_b_px;var ac=(this.low/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var ai=((this.high-this.low)/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var an=13;this.overview_box.css({left:ac,width:Math.max(an,ai)}).show();if(ai<an){this.overview_box.css("left",ac-(an-ai)/2)}if(this.overview_highlight){this.overview_highlight.css({left:ac,width:ai})}if(!am){var ae,ad,ak;for(var ag=0,ah=this.tracks_to_be_redrawn.length;ag<ah;ag++){ae=this.tracks_to_be_redrawn[ag][0];ad=this.tracks_to_be_redrawn[ag][1];ak=this.tracks_to_be_redrawn[ag][2];if(ae){ae._draw(ad,ak)}}this.tracks_to_be_redrawn=[];for(ag=0,ah=this.label_tracks.length;ag<ah;ag++){this.label_tracks[ag]._draw()}}},zoom_in:function(ad,ae){if(this.max_high===0||this.high-this.low<=this.min_separation){return}var af=this.high-this.low,ag=af/2+this.low,ac=(af/this.zoom_factor)/2;if(ad){ag=ad/this.viewport_container.width()*(this.high-this.low)+this.low}this.low=Math.round(ag-ac);this.high=Math.round(ag+ac);this.changed();this.request_redraw()},zoom_out:function(){if(this.max_high===0){return}var ad=this.high-this.low,ae=ad/2+this.low,ac=(ad*this.zoom_factor)/2;this.low=Math.round(ae-ac);this.high=Math.round(ae+ac);this.changed();this.request_redraw()},resize_window:function(){this.viewport_container.height(this.container.height()-this.top_container.height()-this.bottom_container.height());this.request_redraw()},set_overview:function(ae){if(this.overview_drawable){if(this.overview_drawable.dataset_id===ae.dataset_id){return}this.overview_viewport.find(".track").remove()}var ad=ae.copy({content_div:this.overview_viewport}),ac=this;ad.header_div.hide();ad.is_overview=true;ac.overview_drawable=ad;this.overview_drawable.postdraw_actions=function(){ac.overview_highlight.show().height(ac.overview_drawable.content_div.height());ac.overview_viewport.height(ac.overview_drawable.content_div.height()+ac.overview_box.outerHeight());ac.overview_close.show();ac.resize_window()};ac.overview_drawable.request_draw();this.changed()},reset_overview:function(){$(".bs-tooltip").remove();this.overview_viewport.find(".track-tile").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();view.resize_window();view.overview_drawable=null}});var s=function(ae,aj,af){this.track=ae;this.id=aj.id;this.name=aj.name;this.params=[];var aq=aj.params;for(var ag=0;ag<aq.length;ag++){var al=aq[ag],ad=al.name,ap=al.label,ah=unescape(al.html),ar=al.value,an=al.type;if(an==="number"){this.params.push(new e(ad,ap,ah,(ad in af?af[ad]:ar),al.min,al.max))}else{if(an==="select"){this.params.push(new N(ad,ap,ah,(ad in af?af[ad]:ar)))}else{console.log("WARNING: unrecognized tool parameter type:",ad,an)}}}this.parent_div=$("<div/>").addClass("dynamic-tool").hide();this.parent_div.bind("drag",function(au){au.stopPropagation()}).click(function(au){au.stopPropagation()}).bind("dblclick",function(au){au.stopPropagation()});var ao=$("<div class='tool-name'>").appendTo(this.parent_div).text(this.name);var am=this.params;var ak=this;$.each(this.params,function(av,ay){var ax=$("<div>").addClass("param-row").appendTo(ak.parent_div);var au=$("<div>").addClass("param-label").text(ay.label).appendTo(ax);var aw=$("<div/>").addClass("param-input").html(ay.html).appendTo(ax);aw.find(":input").val(ay.value);$("<div style='clear: both;'/>").appendTo(ax)});this.parent_div.find("input").click(function(){$(this).select()});var at=$("<div>").addClass("param-row").appendTo(this.parent_div);var ai=$("<input type='submit'>").attr("value","Run on complete dataset").appendTo(at);var ac=$("<input type='submit'>").attr("value","Run on visible region").css("margin-left","3em").appendTo(at);ac.click(function(){ak.run_on_region()});ai.click(function(){ak.run_on_dataset()});if("visible" in af&&af.visible){this.parent_div.show()}};q(s.prototype,{update_params:function(){for(var ac=0;ac<this.params.length;ac++){this.params[ac].update_value()}},state_dict:function(){var ad={};for(var ac=0;ac<this.params.length;ac++){ad[this.params[ac].name]=this.params[ac].value}ad.visible=this.parent_div.is(":visible");return ad},get_param_values_dict:function(){var ac={};this.parent_div.find(":input").each(function(){var ad=$(this).attr("name"),ae=$(this).val();ac[ad]=ae});return ac},get_param_values:function(){var ac=[];this.parent_div.find(":input").each(function(){var ad=$(this).attr("name"),ae=$(this).val();if(ad){ac[ac.length]=ae}});return ac},run_on_dataset:function(){var ac=this;ac.run({target_dataset_id:this.track.dataset_id,action:"rerun",tool_id:ac.id},null,function(ad){show_modal(ac.name+" is Running",ac.name+" is running on the complete dataset. Tool outputs are in dataset's history.",{Close:hide_modal})})},run_on_region:function(){var ai=new x.GenomeRegion({chrom:this.track.view.chrom,start:this.track.view.low,end:this.track.view.high}),ad={target_dataset_id:this.track.dataset_id,action:"rerun",tool_id:this.id,regions:[ai.toJSON()]},ah=this.track,ae=ad.tool_id+ah.tool_region_and_parameters_str(ai),ac;if(ah.container===view){var ag=new P(view,view,{name:this.name});var af=ah.container.replace_drawable(ah,ag,false);ag.container_div.insertBefore(ah.view.content_div.children()[af]);ag.add_drawable(ah);ah.container_div.appendTo(ag.content_div);ac=ag}else{ac=ah.container}var aj=new ah.constructor(view,ac,{name:ae,hda_ldda:"hda"});aj.init_for_tool_data();aj.change_mode(ah.mode);aj.set_filters_manager(ah.filters_manager.copy(aj));aj.update_icons();ac.add_drawable(aj);aj.tiles_div.text("Starting job.");this.update_params();this.run(ad,aj,function(ak){aj.set_dataset(new X.Dataset(ak));aj.tiles_div.text("Running job.");aj.init()})},run:function(ac,ae,af){ac.inputs=this.get_param_values_dict();var ad=new l.ServerStateDeferred({ajax_settings:{url:galaxy_paths.get("tool_url"),data:JSON.stringify(ac),dataType:"json",contentType:"application/json",type:"POST"},interval:2000,success_fn:function(ag){return ag!=="pending"}});$.when(ad.go()).then(function(ag){if(ag==="no converter"){ae.container_div.addClass("error");ae.content_div.text(J)}else{if(ag.error){ae.container_div.addClass("error");ae.content_div.text(y+ag.message)}else{af(ag)}}})}});var N=function(ad,ac,ae,af){this.name=ad;this.label=ac;this.html=$(ae);this.value=af};q(N.prototype,{update_value:function(){this.value=$(this.html).val()}});var e=function(ae,ad,ag,ah,af,ac){N.call(this,ae,ad,ag,ah);this.min=af;this.max=ac};q(e.prototype,N.prototype,{update_value:function(){N.prototype.update_value.call(this);this.value=parseFloat(this.value)}});var C=function(ac,ad){L.Scaler.call(this,ad);this.filter=ac};C.prototype.gen_val=function(ac){if(this.filter.high===Number.MAX_VALUE||this.filter.low===-Number.MAX_VALUE||this.filter.low===this.filter.high){return this.default_val}return((parseFloat(ac[this.filter.index])-this.filter.low)/(this.filter.high-this.filter.low))};var F=function(ac){this.track=ac.track;this.params=ac.params;this.values={};this.restore_values((ac.saved_values?ac.saved_values:{}));this.onchange=ac.onchange};q(F.prototype,{restore_values:function(ac){var ad=this;$.each(this.params,function(ae,af){if(ac[af.key]!==undefined){ad.values[af.key]=ac[af.key]}else{ad.values[af.key]=af.default_value}})},build_form:function(){var af=this;var ac=$("<div />");var ae;function ad(ak,ag){for(var ao=0;ao<ak.length;ao++){ae=ak[ao];if(ae.hidden){continue}var ai="param_"+ao;var at=af.values[ae.key];var av=$("<div class='form-row' />").appendTo(ag);av.append($("<label />").attr("for",ai).text(ae.label+":"));if(ae.type==="bool"){av.append($('<input type="checkbox" />').attr("id",ai).attr("name",ai).attr("checked",at))}else{if(ae.type==="text"){av.append($('<input type="text"/>').attr("id",ai).val(at).click(function(){$(this).select()}))}else{if(ae.type==="select"){var aq=$("<select />").attr("id",ai);for(var am=0;am<ae.options.length;am++){$("<option/>").text(ae.options[am].label).attr("value",ae.options[am].value).appendTo(aq)}aq.val(at);av.append(aq)}else{if(ae.type==="color"){var au=$("<div/>").appendTo(av),ap=$("<input />").attr("id",ai).attr("name",ai).val(at).css("float","left").appendTo(au).click(function(ax){$(".bs-tooltip").removeClass("in");var aw=$(this).siblings(".bs-tooltip").addClass("in");aw.css({left:$(this).position().left+$(this).width()+5,top:$(this).position().top-($(aw).height()/2)+($(this).height()/2)}).show();aw.click(function(ay){ay.stopPropagation()});$(document).bind("click.color-picker",function(){aw.hide();$(document).unbind("click.color-picker")});ax.stopPropagation()}),an=$("<a href='javascript:void(0)'/>").addClass("icon-button arrow-circle").appendTo(au).attr("title","Set new random color").tooltip(),ar=$("<div class='bs-tooltip right' style='position: absolute;' />").appendTo(au).hide(),aj=$("<div class='tooltip-inner' style='text-align: inherit'></div>").appendTo(ar),ah=$("<div class='tooltip-arrow'></div>").appendTo(ar),al=$.farbtastic(aj,{width:100,height:100,callback:ap,color:at});au.append($("<div/>").css("clear","both"));(function(aw){an.click(function(){aw.setColor(l.get_random_color())})})(al)}else{av.append($("<input />").attr("id",ai).attr("name",ai).val(at))}}}}if(ae.help){av.append($("<div class='help'/>").text(ae.help))}}}ad(this.params,ac);return ac},update_from_form:function(ac){var ae=this;var ad=false;$.each(this.params,function(af,ah){if(!ah.hidden){var ai="param_"+af;var ag=ac.find("#"+ai).val();if(ah.type==="float"){ag=parseFloat(ag)}else{if(ah.type==="int"){ag=parseInt(ag,10)}else{if(ah.type==="bool"){ag=ac.find("#"+ai).is(":checked")}}}if(ag!==ae.values[ah.key]){ae.values[ah.key]=ag;ad=true}}});if(ad){this.onchange();this.track.changed()}}});var b=function(ac,ag,ae,ad,af){this.track=ac;this.region=ag;this.low=ag.get("start");this.high=ag.get("end");this.resolution=ae;this.html_elt=$("<div class='track-tile'/>").append(ad).height($(ad).attr("height"));this.data=af;this.stale=false};b.prototype.predisplay_actions=function(){};var j=function(ac,ah,ae,ad,af,ag){b.call(this,ac,ah,ae,ad,af);this.max_val=ag};q(j.prototype,b.prototype);var O=function(af,an,ag,ae,ai,ap,aj,aq,ad,am){b.call(this,af,an,ag,ae,ai);this.mode=aj;this.all_slotted=ad;this.feature_mapper=am;this.has_icons=false;if(aq){this.has_icons=true;var ak=this;ae=this.html_elt.children()[0],message_div=$("<div/>").addClass("tile-message").css({height:D-1,width:ae.width}).prependTo(this.html_elt);var al=new x.GenomeRegion({chrom:af.view.chrom,start:this.low,end:this.high}),ao=ai.length,ah=$("<a href='javascript:void(0);'/>").addClass("icon more-down").attr("title","For speed, only the first "+ao+" features in this region were obtained from server. Click to get more data including depth").tooltip().appendTo(message_div),ac=$("<a href='javascript:void(0);'/>").addClass("icon more-across").attr("title","For speed, only the first "+ao+" features in this region were obtained from server. Click to get more data excluding depth").tooltip().appendTo(message_div);ah.click(function(){ak.stale=true;af.data_manager.get_more_data(al,af.mode,ak.resolution,{},af.data_manager.DEEP_DATA_REQ);$(".bs-tooltip").hide();af.request_draw(true)}).dblclick(function(ar){ar.stopPropagation()});ac.click(function(){ak.stale=true;af.data_manager.get_more_data(al,af.mode,ak.resolution,{},af.data_manager.BROAD_DATA_REQ);$(".bs-tooltip").hide();af.request_draw(true)}).dblclick(function(ar){ar.stopPropagation()})}};q(O.prototype,b.prototype);O.prototype.predisplay_actions=function(){var ad=this,ac={};if(ad.mode!=="Pack"){return}$(this.html_elt).hover(function(){this.hovered=true;$(this).mousemove()},function(){this.hovered=false;$(this).parents(".track-content").children(".overlay").children(".feature-popup").remove()}).mousemove(function(ao){if(!this.hovered){return}var aj=$(this).offset(),an=ao.pageX-aj.left,am=ao.pageY-aj.top,at=ad.feature_mapper.get_feature_data(an,am),ak=(at?at[0]:null);$(this).parents(".track-content").children(".overlay").children(".feature-popup").each(function(){if(!ak||$(this).attr("id")!==ak.toString()){$(this).remove()}});if(at){var af=ac[ak];if(!af){var ak=at[0],ap={name:at[3],start:at[1],end:at[2],strand:at[4]},ai=ad.track.filters_manager.filters,ah;for(var al=0;al<ai.length;al++){ah=ai[al];ap[ah.name]=at[ah.index]}var af=$("<div/>").attr("id",ak).addClass("feature-popup"),au=$("<table/>"),ar,aq,av;for(ar in ap){aq=ap[ar];av=$("<tr/>").appendTo(au);$("<th/>").appendTo(av).text(ar);$("<td/>").attr("align","left").appendTo(av).text(typeof(aq)==="number"?V(aq,2):aq)}af.append($("<div class='feature-popup-inner'>").append(au));ac[ak]=af}af.appendTo($(this).parents(".track-content").children(".overlay"));var ag=an+parseInt(ad.html_elt.css("left"))-af.width()/2,ae=am+parseInt(ad.html_elt.css("top"))+7;af.css("left",ag+"px").css("top",ae+"px")}else{if(!ao.isPropagationStopped()){ao.stopPropagation();$(this).siblings().each(function(){$(this).trigger(ao)})}}}).mouseleave(function(){$(this).parents(".track-content").children(".overlay").children(".feature-popup").remove()})};var g=function(ad,ac,ae){q(ae,{drag_handle_class:"draghandle"});r.call(this,ad,ac,ae);this.dataset=new X.Dataset({id:ae.dataset_id,hda_ldda:ae.hda_ldda});this.dataset_id=this.dataset.get("id");this.hda_ldda=this.dataset.get("hda_ldda");this.dataset_check_type="converted_datasets_state";this.data_url_extra_params={};this.data_query_wait=("data_query_wait" in ae?ae.data_query_wait:K);this.data_manager=("data_manager" in ae?ae.data_manager:new x.GenomeDataManager({dataset:this.dataset,genome:new x.Genome({key:ad.dbkey,chroms_info:{chrom_info:ad.chrom_data}}),data_mode_compatible:this.data_and_mode_compatible,can_subset:this.can_subset}));this.min_height_px=16;this.max_height_px=800;this.visible_height_px=0;this.content_div=$("<div class='track-content'>").appendTo(this.container_div);if(this.container){this.container.content_div.append(this.container_div);if(!("resize" in ae)||ae.resize){this.add_resize_handle()}}};q(g.prototype,r.prototype,{action_icons_def:[{name:"mode_icon",title:"Set display mode",css_class:"chevron-expand",on_click_fn:function(){}},r.prototype.action_icons_def[0],{name:"overview_icon",title:"Set as overview",css_class:"overview-icon",on_click_fn:function(ac){ac.view.set_overview(ac)}},r.prototype.action_icons_def[1],{name:"filters_icon",title:"Filters",css_class:"filters-icon",on_click_fn:function(ac){if(ac.filters_manager.visible()){ac.filters_manager.clear_filters()}else{ac.filters_manager.init_filters()}ac.filters_manager.toggle()}},{name:"tools_icon",title:"Tool",css_class:"hammer",on_click_fn:function(ac){ac.dynamic_tool_div.toggle();if(ac.dynamic_tool_div.is(":visible")){ac.set_name(ac.name+ac.tool_region_and_parameters_str())}else{ac.revert_name()}$(".bs-tooltip").remove()}},{name:"param_space_viz_icon",title:"Tool parameter space visualization",css_class:"arrow-split",on_click_fn:function(ac){var af='<strong>Tool</strong>: <%= track.tool.name %><br/><strong>Dataset</strong>: <%= track.name %><br/><strong>Region(s)</strong>: <select name="regions"><option value="cur">current viewing area</option><option value="bookmarks">bookmarks</option><option value="both">current viewing area and bookmarks</option></select>',ae=ab.template(af,{track:ac});var ah=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},ad=function(){var aj=$('select[name="regions"] option:selected').val(),al,ai=new x.GenomeRegion({chrom:view.chrom,start:view.low,end:view.high}),ak=ab.map($(".bookmark"),function(am){return new x.GenomeRegion({from_str:$(am).children(".position").text()})});if(aj==="cur"){al=[ai]}else{if(aj==="bookmarks"){al=ak}else{al=[ai].concat(ak)}}hide_modal();window.location.href=galaxy_paths.get("sweepster_url")+"?"+$.param({dataset_id:ac.dataset_id,hda_ldda:ac.hda_ldda,regions:JSON.stringify(new Backbone.Collection(al).toJSON())})},ag=function(ai){if((ai.keyCode||ai.which)===27){ah()}else{if((ai.keyCode||ai.which)===13){ad()}}};show_modal("Visualize tool parameter space and output from different parameter settings?",ae,{No:ah,Yes:ad})}},r.prototype.action_icons_def[2]],can_draw:function(){if(this.dataset_id&&r.prototype.can_draw.call(this)){return true}return false},build_container_div:function(){return $("<div/>").addClass("track").attr("id","track_"+this.id).css("position","relative")},build_header_div:function(){var ac=$("<div class='track-header'/>");if(this.view.editor){this.drag_div=$("<div/>").addClass(this.drag_handle_class).appendTo(ac)}this.name_div=$("<div/>").addClass("track-name").appendTo(ac).text(this.name).attr("id",this.name.replace(/\s+/g,"-").replace(/[^a-zA-Z0-9\-]/g,"").toLowerCase());return ac},set_dataset:function(ac){this.dataset=ac;this.data_manager.set("dataset",ac);this.dataset_id=ac.get("id");this.hda_ldda=ac.get("hda_ldda")},on_resize:function(){},add_resize_handle:function(){var ac=this;var af=false;var ae=false;var ad=$("<div class='track-resize'>");$(ac.container_div).hover(function(){if(ac.content_visible){af=true;ad.show()}},function(){af=false;if(!ae){ad.hide()}});ad.hide().bind("dragstart",function(ag,ah){ae=true;ah.original_height=$(ac.content_div).height()}).bind("drag",function(ah,ai){var ag=Math.min(Math.max(ai.original_height+ai.deltaY,ac.min_height_px),ac.max_height_px);$(ac.tiles_div).css("height",ag);ac.visible_height_px=(ac.max_height_px===ag?0:ag);ac.on_resize()}).bind("dragend",function(ag,ah){ac.tile_cache.clear();ae=false;if(!af){ad.hide()}ac.config.values.height=ac.visible_height_px;ac.changed()}).appendTo(ac.container_div)},set_display_modes:function(af,ai){this.display_modes=af;this.mode=(ai?ai:(this.config&&this.config.values.mode?this.config.values.mode:this.display_modes[0]));this.action_icons.mode_icon.attr("title","Set display mode (now: "+this.mode+")");var ad=this,ag={};for(var ae=0,ac=ad.display_modes.length;ae<ac;ae++){var ah=ad.display_modes[ae];ag[ah]=function(aj){return function(){ad.change_mode(aj);ad.icons_div.show();ad.container_div.mouseleave(function(){ad.icons_div.hide()})}}(ah)}make_popupmenu(this.action_icons.mode_icon,ag)},build_action_icons:function(){r.prototype.build_action_icons.call(this,this.action_icons_def);if(this.display_modes!==undefined){this.set_display_modes(this.display_modes)}},hide_contents:function(){this.tiles_div.hide();this.container_div.find(".yaxislabel, .track-resize").hide()},show_contents:function(){this.tiles_div.show();this.container_div.find(".yaxislabel, .track-resize").show();this.request_draw()},get_type:function(){if(this instanceof W){return"LabelTrack"}else{if(this instanceof B){return"ReferenceTrack"}else{if(this instanceof h){return"LineTrack"}else{if(this instanceof S){return"ReadTrack"}else{if(this instanceof Z){return"VariantTrack"}else{if(this instanceof f){return"CompositeTrack"}else{if(this instanceof c){return"FeatureTrack"}}}}}}}return""},init:function(ae){var ad=this;ad.enabled=false;ad.tile_cache.clear();ad.data_manager.clear();ad.content_div.css("height","auto");ad.tiles_div.text("").children().remove();ad.container_div.removeClass("nodata error pending");if(!ad.dataset_id){return}var ac=$.Deferred(),af={hda_ldda:ad.hda_ldda,data_type:this.dataset_check_type,chrom:ad.view.chrom,retry:ae};$.getJSON(this.dataset.url(),af,function(ag){if(!ag||ag==="error"||ag.kind==="error"){ad.container_div.addClass("error");ad.tiles_div.text(o);if(ag.message){ad.tiles_div.append($("<a href='javascript:void(0);'></a>").text("View error").click(function(){show_modal("Trackster Error","<pre>"+ag.message+"</pre>",{Close:hide_modal})}));ad.tiles_div.append($("<span/>").text(" "));ad.tiles_div.append($("<a href='javascript:void(0);'></a>").text("Try again").click(function(){ad.init(true)}))}}else{if(ag==="no converter"){ad.container_div.addClass("error");ad.tiles_div.text(J)}else{if(ag==="no data"||(ag.data!==undefined&&(ag.data===null||ag.data.length===0))){ad.container_div.addClass("nodata");ad.tiles_div.text(E)}else{if(ag==="pending"){ad.container_div.addClass("pending");ad.tiles_div.html(v);setTimeout(function(){ad.init()},ad.data_query_wait)}else{if(ag==="data"||ag.status==="data"){if(ag.valid_chroms){ad.valid_chroms=ag.valid_chroms;ad.update_icons()}ad.tiles_div.text(T);if(ad.view.chrom){ad.tiles_div.text("");ad.tiles_div.css("height",ad.visible_height_px+"px");ad.enabled=true;$.when(ad.predraw_init()).done(function(){ac.resolve();ad.container_div.removeClass("nodata error pending");ad.request_draw()})}else{ac.resolve()}}}}}}});this.update_icons();return ac},predraw_init:function(){},get_drawables:function(){return this}});var M=function(ae,ad,af){g.call(this,ae,ad,af);var ac=this;m(ac.container_div,ac.drag_handle_class,".group",ac);this.filters_manager=new i.FiltersManager(this,("filters" in af?af.filters:null));this.data_manager.set("filters_manager",this.filters_manager);this.filters_available=false;this.tool=("tool" in af&&af.tool?new s(this,af.tool,af.tool_state):null);this.tile_cache=new x.Cache(Q);this.left_offset=0;if(this.header_div){this.set_filters_manager(this.filters_manager);if(this.tool){this.dynamic_tool_div=this.tool.parent_div;this.header_div.after(this.dynamic_tool_div)}}this.tiles_div=$("<div/>").addClass("tiles").appendTo(this.content_div);this.overlay_div=$("<div/>").addClass("overlay").appendTo(this.content_div);if(af.mode){this.change_mode(af.mode)}};q(M.prototype,r.prototype,g.prototype,{action_icons_def:g.prototype.action_icons_def.concat([{name:"show_more_rows_icon",title:"To minimize track height, not all feature rows are displayed. Click to display more rows.",css_class:"exclamation",on_click_fn:function(ac){$(".bs-tooltip").remove();ac.slotters[ac.view.resolution_px_b].max_rows*=2;ac.request_draw(true)},hide:true}]),copy:function(ac){var ad=this.to_dict();q(ad,{data_manager:this.data_manager});var ae=new this.constructor(this.view,ac,ad);ae.change_mode(this.mode);ae.enabled=this.enabled;return ae},set_filters_manager:function(ac){this.filters_manager=ac;this.header_div.after(this.filters_manager.parent_div)},to_dict:function(){return{track_type:this.get_type(),name:this.name,hda_ldda:this.hda_ldda,dataset_id:this.dataset_id,prefs:this.prefs,mode:this.mode,filters:this.filters_manager.to_dict(),tool_state:(this.tool?this.tool.state_dict():{})}},change_mode:function(ad){var ac=this;ac.mode=ad;ac.config.values.mode=ad;ac.tile_cache.clear();ac.request_draw();this.action_icons.mode_icon.attr("title","Set display mode (now: "+ac.mode+")");return ac},update_icons:function(){var ac=this;if(ac.filters_available){ac.action_icons.filters_icon.show()}else{ac.action_icons.filters_icon.hide()}if(ac.tool){ac.action_icons.tools_icon.show();ac.action_icons.param_space_viz_icon.show()}else{ac.action_icons.tools_icon.hide();ac.action_icons.param_space_viz_icon.hide()}},_gen_tile_cache_key:function(ad,ac){return ad+"_"+ac},request_draw:function(ad,ac){this.view.request_redraw(false,ad,ac,this)},before_draw:function(){},_draw:function(ad,ao){if(!this.can_draw()){return}var al=this.view.low,ah=this.view.high,aj=ah-al,ae=this.view.container.width(),aq=this.view.resolution_px_b,ag=this.view.resolution_b_px;if(this.is_overview){al=this.view.max_low;ah=this.view.max_high;ag=(view.max_high-view.max_low)/ae;aq=1/ag}this.before_draw();this.tiles_div.children().addClass("remove");var ac=Math.floor(al/(ag*R)),ak=true,ap=[],ai=function(ar){return(ar&&"track" in ar)};while((ac*R*ag)<ah){var am=this._get_tile_bounds(ac,ag),an=this.draw_helper(ad,am,ag,this.tiles_div,aq);if(ai(an)){ap.push(an)}else{ak=false}ac+=1}if(!ao){this.tiles_div.children(".remove").removeClass("remove").remove()}var af=this;if(ak){this.tiles_div.children(".remove").remove();af.postdraw_actions(ap,ae,aq,ao)}},postdraw_actions:function(ad,ae,ag,ac){var af=ab.find(ad,function(ah){return ah.has_icons});if(af){ab.each(ad,function(ah){if(!ah.has_icons){ah.html_elt.css("padding-top",D)}})}},draw_helper:function(ac,af,ar,ah,ai,ao){var an=this,aw=this._gen_tile_cache_key(ai,af);if(!ao){ao={}}var av=(ac?undefined:an.tile_cache.get_elt(aw));if(av){an.show_tile(av,ah,ai);return av}var al=true;var at=an.data_manager.get_data(af,an.mode,ar,an.data_url_extra_params);if(U(at)){al=false}var aj;if(view.reference_track){aj=view.reference_track.data_manager.get_data(af,an.mode,ar,view.reference_track.data_url_extra_params);if(U(aj)){al=false}else{aj=view.reference_track.data_manager.subset_entry(aj,af)}}if(al){q(at,ao.more_tile_data);var ak=an.mode;if(ak==="Auto"&&an.get_mode){ak=an.get_mode(at);an.update_auto_mode(ak)}var ae=an.view.canvas_manager.new_canvas(),au=af.get("start"),ad=af.get("end"),ap=Math.ceil((ad-au)*ai)+an.left_offset,am=an.get_canvas_height(at,ak,ai,ap);ae.width=ap;ae.height=am;var aq=ae.getContext("2d");aq.translate(this.left_offset,0);var av=an.draw_tile(at,aq,ak,ar,af,ai,aj);if(av!==undefined){an.tile_cache.set_elt(aw,av);an.show_tile(av,ah,ai)}return av}var ag=$.Deferred();$.when(at,aj).then(function(){view.request_redraw(false,false,false,an);ag.resolve()});return ag},get_canvas_height:function(ac,ae,af,ad){return this.visible_height_px},_draw_summary_tree_tile:function(ac,ae,ag,af,ah){var ad=new L.SummaryTreePainter(ac,ag.get("start"),ag.get("end"),this.prefs);ad.draw(ae,ae.canvas.width,ae.canvas.height,ah);return new j(this,ag,af,ae.canvas,ac.data,ac.max)},draw_tile:function(ac,ad,ah,af,ag,ai,ae){console.log("Warning: TiledTrack.draw_tile() not implemented.")},show_tile:function(ae,ah,ai){var ad=this,ac=ae.html_elt;ae.predisplay_actions();var ag=(ae.low-(this.is_overview?this.view.max_low:this.view.low))*ai;if(this.left_offset){ag-=this.left_offset}ac.css({position:"absolute",top:0,left:ag});if(ac.hasClass("remove")){ac.removeClass("remove")}else{ah.append(ac)}ae.html_elt.height("auto");this.max_height_px=Math.max(this.max_height_px,ae.html_elt.height());ae.html_elt.parent().children().css("height",this.max_height_px+"px");var af=this.max_height_px;if(this.visible_height_px!==0){af=Math.min(this.max_height_px,this.visible_height_px)}this.tiles_div.css("height",af+"px")},_get_tile_bounds:function(ac,ad){var af=Math.floor(ac*R*ad),ag=Math.ceil(R*ad),ae=(af+ag<=this.view.max_high?af+ag:this.view.max_high);return new x.GenomeRegion({chrom:this.view.chrom,start:af,end:ae})},tool_region_and_parameters_str:function(ae){var ac=this,ad=(ae!==undefined?ae.toString():"all");return" - region=["+ad+"], parameters=["+ac.tool.get_param_values().join(", ")+"]"},data_and_mode_compatible:function(ac,ad){return true},can_subset:function(ac){return false},init_for_tool_data:function(){this.data_manager.set("data_type","raw_data");this.data_query_wait=1000;this.dataset_check_type="state";this.normal_postdraw_actions=this.postdraw_actions;this.postdraw_actions=function(ae,af,ah,ac){var ad=this;ad.normal_postdraw_actions(ae,af,ah,ac);ad.dataset_check_type="converted_datasets_state";ad.data_query_wait=K;var ag=new l.ServerStateDeferred({url:ad.dataset_state_url,url_params:{dataset_id:ad.dataset_id,hda_ldda:ad.hda_ldda},interval:ad.data_query_wait,success_fn:function(ai){return ai!=="pending"}});$.when(ag.go()).then(function(){ad.data_manager.set("data_type","data")});ad.postdraw_actions=ad.normal_postdraw_actions}}});var W=function(ad,ac){var ae={resize:false};g.call(this,ad,ac,ae);this.container_div.addClass("label-track")};q(W.prototype,g.prototype,{build_header_div:function(){},init:function(){this.enabled=true},_draw:function(){var ae=this.view,af=ae.high-ae.low,ai=Math.floor(Math.pow(10,Math.floor(Math.log(af)/Math.log(10)))),ac=Math.floor(ae.low/ai)*ai,ag=this.view.container.width(),ad=$("<div style='position: relative; height: 1.3em;'></div>");while(ac<ae.high){var ah=(ac-ae.low)/af*ag;ad.append($("<div class='label'>"+commatize(ac)+"</div>").css({position:"absolute",left:ah-1}));ac+=ai}this.content_div.children(":first").remove();this.content_div.append(ad)}});var f=function(ad,ac,ag){M.call(this,ad,ac,ag);this.drawables=[];if("drawables" in ag){var af;for(var ae=0;ae<ag.drawables.length;ae++){af=ag.drawables[ae];this.drawables[ae]=p(af,ad,null);if(af.left_offset>this.left_offset){this.left_offset=af.left_offset}}this.enabled=true}if(this.drawables.length!==0){this.set_display_modes(this.drawables[0].display_modes,this.drawables[0].mode)}this.update_icons();this.obj_type="CompositeTrack"};q(f.prototype,M.prototype,{action_icons_def:[{name:"composite_icon",title:"Show individual tracks",css_class:"layers-stack",on_click_fn:function(ac){$(".bs-tooltip").remove();ac.show_group()}}].concat(M.prototype.action_icons_def),to_dict:z.prototype.to_dict,add_drawable:z.prototype.add_drawable,unpack_drawables:z.prototype.unpack_drawables,change_mode:function(ac){M.prototype.change_mode.call(this,ac);for(var ad=0;ad<this.drawables.length;ad++){this.drawables[ad].change_mode(ac)}},init:function(){var ae=[];for(var ad=0;ad<this.drawables.length;ad++){ae.push(this.drawables[ad].init())}var ac=this;$.when.apply($,ae).then(function(){ac.enabled=true;ac.request_draw()})},update_icons:function(){this.action_icons.filters_icon.hide();this.action_icons.tools_icon.hide();this.action_icons.param_space_viz_icon.hide()},can_draw:r.prototype.can_draw,draw_helper:function(ad,ah,av,aj,al,at){var aq=this,aB=this._gen_tile_cache_key(al,ah);if(!at){at={}}var aA=(ad?undefined:aq.tile_cache.get_elt(aB));if(aA){aq.show_tile(aA,aj,al);return aA}var ak=[],aq,ao=true,aw,am;for(var ax=0;ax<this.drawables.length;ax++){aq=this.drawables[ax];aw=aq.data_manager.get_data(ah,aq.mode,av,aq.data_url_extra_params);if(U(aw)){ao=false}ak.push(aw);am=null;if(view.reference_track&&al>view.canvas_manager.char_width_px){am=view.reference_track.data_manager.get_data(ah,aq.mode,av,view.reference_track.data_url_extra_params);if(U(am)){ao=false}}ak.push(am)}if(ao){q(aw,at.more_tile_data);this.tile_predraw_init();var ag=aq.view.canvas_manager.new_canvas(),ay=ah.get("start"),ae=ah.get("end"),az=0,ar=Math.ceil((ae-ay)*al)+this.left_offset,ap=0,af=[],ax;var ac=0;for(ax=0;ax<this.drawables.length;ax++,az+=2){aq=this.drawables[ax];aw=ak[az];var an=aq.mode;if(an==="Auto"){an=aq.get_mode(aw);aq.update_auto_mode(an)}af.push(an);ac=aq.get_canvas_height(aw,an,al,ar);if(ac>ap){ap=ac}}ag.width=ar;ag.height=(at.height?at.height:ap);az=0;var au=ag.getContext("2d");au.translate(this.left_offset,0);au.globalAlpha=0.5;au.globalCompositeOperation="source-over";for(ax=0;ax<this.drawables.length;ax++,az+=2){aq=this.drawables[ax];aw=ak[az];am=ak[az+1];aA=aq.draw_tile(aw,au,af[ax],av,ah,al,am)}this.tile_cache.set_elt(aB,aA);this.show_tile(aA,aj,al);return aA}var ai=$.Deferred(),aq=this;$.when.apply($,ak).then(function(){view.request_redraw(false,false,false,aq);ai.resolve()});return ai},show_group:function(){var af=new P(this.view,this.container,{name:this.name}),ac;for(var ae=0;ae<this.drawables.length;ae++){ac=this.drawables[ae];ac.update_icons();af.add_drawable(ac);ac.container=af;af.content_div.append(ac.container_div)}var ad=this.container.replace_drawable(this,af,true);af.request_draw()},tile_predraw_init:function(){var af=Number.MAX_VALUE,ac=-af,ad;for(var ae=0;ae<this.drawables.length;ae++){ad=this.drawables[ae];if(ad instanceof h){if(ad.prefs.min_value<af){af=ad.prefs.min_value}if(ad.prefs.max_value>ac){ac=ad.prefs.max_value}}}for(var ae=0;ae<this.drawables.length;ae++){ad=this.drawables[ae];ad.prefs.min_value=af;ad.prefs.max_value=ac}},postdraw_actions:function(ae,ah,aj,ad){M.prototype.postdraw_actions.call(this,ae,ah,aj,ad);var ag=-1;for(var af=0;af<ae.length;af++){var ac=ae[af].html_elt.find("canvas").height();if(ac>ag){ag=ac}}for(var af=0;af<ae.length;af++){var ai=ae[af];if(ai.html_elt.find("canvas").height()!==ag){this.draw_helper(true,ai.index,ai.resolution,ai.html_elt.parent(),aj,{height:ag});ai.html_elt.remove()}}}});var B=function(ac){M.call(this,ac,{content_div:ac.top_labeltrack},{resize:false});ac.reference_track=this;this.left_offset=200;this.visible_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_url=reference_url+"/"+this.view.dbkey;this.data_url_extra_params={reference:true};this.data_manager=new x.GenomeReferenceDataManager({data_url:this.data_url,can_subset:this.can_subset});this.hide_contents()};q(B.prototype,r.prototype,M.prototype,{build_header_div:function(){},init:function(){this.data_manager.clear();this.enabled=true},can_draw:r.prototype.can_draw,draw_helper:function(ae,af,ac,ag,ah,ad){if(ah>this.view.canvas_manager.char_width_px){this.tiles_div.show();return M.prototype.draw_helper.call(this,ae,af,ac,ag,ah,ad)}else{this.tiles_div.hide();return null}},can_subset:function(ac){return true},draw_tile:function(af,al,ag,ad,ai,am){var ae=this.data_manager.subset_entry(af,ai),ak=ae.data;var ac=al.canvas;al.font=al.canvas.manager.default_font;al.textAlign="center";for(var ah=0,aj=ak.length;ah<aj;ah++){al.fillStyle=this.view.get_base_color(ak[ah]);al.fillText(ak[ah],Math.floor(ah*am),10)}return new b(this,ai,ad,ac,ae)}});var h=function(ae,ad,af){var ac=this;this.display_modes=["Histogram","Line","Filled","Intensity"];this.mode="Histogram";M.call(this,ae,ad,af);this.config=new F({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"color",label:"Color",type:"color",default_value:l.get_random_color()},{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:32,hidden:true}],saved_values:af.prefs,onchange:function(){ac.set_name(ac.prefs.name);ac.vertical_range=ac.prefs.max_value-ac.prefs.min_value;ac.set_min_value(ac.prefs.min_value);ac.set_max_value(ac.prefs.max_value)}});this.prefs=this.config.values;this.visible_height_px=this.config.values.height;this.vertical_range=this.config.values.max_value-this.config.values.min_value};q(h.prototype,r.prototype,M.prototype,{on_resize:function(){this.request_draw(true)},set_min_value:function(ac){this.prefs.min_value=ac;$("#linetrack_"+this.dataset_id+"_minval").text(this.prefs.min_value);this.tile_cache.clear();this.request_draw()},set_max_value:function(ac){this.prefs.max_value=ac;$("#linetrack_"+this.dataset_id+"_maxval").text(this.prefs.max_value);this.tile_cache.clear();this.request_draw()},predraw_init:function(){var ac=this;ac.vertical_range=undefined;return $.getJSON(ac.dataset.url(),{data_type:"data",stats:true,chrom:ac.view.chrom,low:0,high:ac.view.max_high,hda_ldda:ac.hda_ldda},function(ad){ac.container_div.addClass("line-track");var ag=ad.data;if(isNaN(parseFloat(ac.prefs.min_value))||isNaN(parseFloat(ac.prefs.max_value))){var ae=ag.min,ai=ag.max;ae=Math.floor(Math.min(0,Math.max(ae,ag.mean-2*ag.sd)));ai=Math.ceil(Math.max(0,Math.min(ai,ag.mean+2*ag.sd)));ac.prefs.min_value=ae;ac.prefs.max_value=ai;$("#track_"+ac.dataset_id+"_minval").val(ac.prefs.min_value);$("#track_"+ac.dataset_id+"_maxval").val(ac.prefs.max_value)}ac.vertical_range=ac.prefs.max_value-ac.prefs.min_value;ac.total_frequency=ag.total_frequency;ac.container_div.find(".yaxislabel").remove();var ah=$("<div/>").text(V(ac.prefs.min_value,3)).make_text_editable({num_cols:6,on_finish:function(aj){$(".bs-tooltip").remove();var aj=parseFloat(aj);if(!isNaN(aj)){ac.set_min_value(aj)}},help_text:"Set min value"}).addClass("yaxislabel bottom").attr("id","linetrack_"+ac.dataset_id+"_minval").prependTo(ac.container_div),af=$("<div/>").text(V(ac.prefs.max_value,3)).make_text_editable({num_cols:6,on_finish:function(aj){$(".bs-tooltip").remove();var aj=parseFloat(aj);if(!isNaN(aj)){ac.set_max_value(aj)}},help_text:"Set max value"}).addClass("yaxislabel top").attr("id","linetrack_"+ac.dataset_id+"_maxval").prependTo(ac.container_div)})},draw_tile:function(al,aj,ae,ad,ag,ak){var ac=aj.canvas,af=ag.get("start"),ai=ag.get("end"),ah=new L.LinePainter(al.data,af,ai,this.prefs,ae);ah.draw(aj,ac.width,ac.height,ak);return new b(this,ag,ad,ac,al.data)},can_subset:function(ac){return(ac.data[1][0]-ac.data[0][0]===1)}});var t=function(ae,ad,af){var ac=this;this.display_modes=["Heatmap"];this.mode="Heatmap";M.call(this,ae,ad,af);this.config=new F({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"pos_color",label:"Positive Color",type:"color",default_value:"#FF8C00"},{key:"neg_color",label:"Negative Color",type:"color",default_value:"#4169E1"},{key:"min_value",label:"Min Value",type:"float",default_value:-1},{key:"max_value",label:"Max Value",type:"float",default_value:1},{key:"mode",type:"string",default_value:this.mode,hidden:true},{key:"height",type:"int",default_value:500,hidden:true}],saved_values:af.prefs,onchange:function(){ac.set_name(ac.prefs.name);ac.vertical_range=ac.prefs.max_value-ac.prefs.min_value;ac.set_min_value(ac.prefs.min_value);ac.set_max_value(ac.prefs.max_value)}});this.prefs=this.config.values;this.visible_height_px=this.config.values.height;this.vertical_range=this.config.values.max_value-this.config.values.min_value};q(t.prototype,r.prototype,M.prototype,{on_resize:function(){this.request_draw(true)},set_min_value:function(ac){this.prefs.min_value=ac;this.tile_cache.clear();this.request_draw()},set_max_value:function(ac){this.prefs.max_value=ac;this.tile_cache.clear();this.request_draw()},draw_tile:function(ac,ae,ai,ag,ah,aj){var af=ae.canvas,ad=new L.DiagonalHeatmapPainter(ac.data,ah.get("start"),ah.get("end"),this.prefs,ai);ad.draw(ae,af.width,af.height,aj);return new b(this,ah,ag,af,ac.data)}});var c=function(af,ae,ah){var ad=this;this.display_modes=["Auto","Coverage","Dense","Squish","Pack"];M.call(this,af,ae,ah);var ag=l.get_random_color(),ac=l.get_random_color([ag,"#FFFFFF"]);this.config=new F({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"block_color",label:"Block color",type:"color",default_value:ag},{key:"reverse_strand_color",label:"Antisense strand color",type:"color",default_value:ac},{key:"label_color",label:"Label color",type:"color",default_value:"black"},{key:"show_counts",label:"Show summary counts",type:"bool",default_value:true,help:"Show the number of items in each bin when drawing summary histogram"},{key:"histogram_max",label:"Histogram maximum",type:"float",default_value:null,help:"clear value to set automatically"},{key:"connector_style",label:"Connector style",type:"select",default_value:"fishbones",options:[{label:"Line with arrows",value:"fishbone"},{label:"Arcs",value:"arcs"}]},{key:"mode",type:"string",default_value:this.mode,hidden:true},{key:"height",type:"int",default_value:this.visible_height_px,hidden:true}],saved_values:ah.prefs,onchange:function(){ad.set_name(ad.prefs.name);ad.tile_cache.clear();ad.set_painter_from_config();ad.request_draw()}});this.prefs=this.config.values;this.visible_height_px=this.config.values.height;this.container_div.addClass("feature-track");this.show_labels_scale=0.001;this.showing_details=false;this.summary_draw_height=30;this.slotters={};this.start_end_dct={};this.left_offset=200;this.set_painter_from_config()};q(c.prototype,r.prototype,M.prototype,{set_painter_from_config:function(){if(this.config.values.connector_style==="arcs"){this.painter=L.ArcLinkedFeaturePainter}else{this.painter=L.LinkedFeaturePainter}},before_draw:function(){this.max_height_px=0},postdraw_actions:function(ar,am,ah,ag){M.prototype.postdraw_actions.call(this,ar,ag);var al=this,ao;if(al.mode==="Coverage"){var ad=-1;for(ao=0;ao<ar.length;ao++){var an=ar[ao].max_val;if(an>ad){ad=an}}for(ao=0;ao<ar.length;ao++){var au=ar[ao];if(au.max_val!==ad){au.html_elt.remove();al.draw_helper(true,au.index,au.resolution,au.html_elt.parent(),ah,{more_tile_data:{max:ad}})}}}if(al.filters_manager){var ai=al.filters_manager.filters;for(var aq=0;aq<ai.length;aq++){ai[aq].update_ui_elt()}var at=false,ac,aj;for(ao=0;ao<ar.length;ao++){if(ar[ao].data.length){ac=ar[ao].data[0];for(var aq=0;aq<ai.length;aq++){aj=ai[aq];if(aj.applies_to(ac)&&aj.min!==aj.max){at=true;break}}}}if(al.filters_available!==at){al.filters_available=at;if(!al.filters_available){al.filters_manager.hide()}al.update_icons()}}this.container_div.find(".yaxislabel").remove();var af=ar[0];if(af instanceof j){var ak=(this.prefs.histogram_max?this.prefs.histogram_max:af.max_val),ae=$("<div/>").text(ak).make_text_editable({num_cols:12,on_finish:function(av){$(".bs-tooltip").remove();var av=parseFloat(av);al.prefs.histogram_max=(!isNaN(av)?av:null);al.tile_cache.clear();al.request_draw()},help_text:"Set max value; leave blank to use default"}).addClass("yaxislabel top").css("color",this.prefs.label_color);this.container_div.prepend(ae)}if(af instanceof O){var ap=true;for(ao=0;ao<ar.length;ao++){if(!ar[ao].all_slotted){ap=false;break}}if(!ap){this.action_icons.show_more_rows_icon.show()}else{this.action_icons.show_more_rows_icon.hide()}}else{this.action_icons.show_more_rows_icon.hide()}},update_auto_mode:function(ac){var ac;if(this.mode==="Auto"){if(ac==="no_detail"){ac="feature spans"}else{if(ac==="summary_tree"){ac="coverage histogram"}}this.action_icons.mode_icon.attr("title","Set display mode (now: Auto/"+ac+")")}},incremental_slots:function(ag,ac,af){var ad=this.view.canvas_manager.dummy_context,ae=this.slotters[ag];if(!ae||(ae.mode!==af)){ae=new (u.FeatureSlotter)(ag,af,A,function(ah){return ad.measureText(ah)});this.slotters[ag]=ae}return ae.slot_features(ac)},get_mode:function(ac){if(ac.dataset_type==="summary_tree"){mode="summary_tree"}else{if(ac.extra_info==="no_detail"||this.is_overview){mode="no_detail"}else{if(this.view.high-this.view.low>I){mode="Squish"}else{mode="Pack"}}}return mode},get_canvas_height:function(ac,ag,ah,ad){if(ag==="summary_tree"||ag==="Coverage"){return this.summary_draw_height}else{var af=this.incremental_slots(ah,ac.data,ag);var ae=new (this.painter)(null,null,null,this.prefs,ag);return Math.max(aa,ae.get_required_height(af,ad))}},draw_tile:function(am,aq,ao,ar,af,aj,ae){var ap=this,ad=aq.canvas,ay=af.get("start"),ac=af.get("end"),ag=this.left_offset;if(ao==="summary_tree"||ao==="Coverage"){return this._draw_summary_tree_tile(am,aq,af,ar,aj)}var ai=[],an=this.slotters[aj].slots;all_slotted=true;if(am.data){var ak=this.filters_manager.filters;for(var at=0,av=am.data.length;at<av;at++){var ah=am.data[at];var au=false;var al;for(var ax=0,aC=ak.length;ax<aC;ax++){al=ak[ax];al.update_attrs(ah);if(!al.keep(ah)){au=true;break}}if(!au){ai.push(ah);if(!(ah[0] in an)){all_slotted=false}}}}var aB=(this.filters_manager.alpha_filter?new C(this.filters_manager.alpha_filter):null),az=(this.filters_manager.height_filter?new C(this.filters_manager.height_filter):null),aA=new (this.painter)(ai,ay,ac,this.prefs,ao,aB,az,ae,function(aD){return ap.view.get_base_color(aD)});var aw=null;aq.fillStyle=this.prefs.block_color;aq.font=aq.canvas.manager.default_font;aq.textAlign="right";if(am.data){aw=aA.draw(aq,ad.width,ad.height,aj,an);aw.translation=-ag}return new O(ap,af,ar,ad,am.data,aj,ao,am.message,all_slotted,aw)},data_and_mode_compatible:function(ac,ad){if(ad==="Auto"){return true}else{if(ad==="Coverage"){return ac.dataset_type==="summary_tree"}else{if(ac.extra_info==="no_detail"||ac.dataset_type==="summary_tree"){return false}else{return true}}}},can_subset:function(ac){if(ac.dataset_type==="summary_tree"||ac.message||ac.extra_info==="no_detail"){return false}return true}});var Z=function(ad,ac,ae){this.display_modes=["Auto","Coverage","Dense","Squish","Pack"];M.call(this,ad,ac,ae);this.config=new F({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"show_sample_data",label:"Show sample data",type:"bool",default_value:true},{key:"summary_height",label:"Locus summary height",type:"float",default_value:20},{key:"mode",type:"string",default_value:this.mode,hidden:true}],saved_values:ae.prefs,onchange:function(){this.track.set_name(this.track.prefs.name);this.track.tile_cache.clear();this.track.request_draw()}});this.prefs=this.config.values;this.painter=L.VariantPainter;this.summary_draw_height=30;this.left_offset=30};q(Z.prototype,r.prototype,M.prototype,{draw_tile:function(ac,af,ai,ag,ah,aj){if(ac.dataset_type==="summary_tree"){return this._draw_summary_tree_tile(ac,af,ah,ag,aj)}else{var ae=this.view,ad=new (this.painter)(ac.data,ah.get("start"),ah.get("end"),this.prefs,ai,function(ak){return ae.get_base_color(ak)});ad.draw(af,af.canvas.width,af.canvas.height,aj);return new b(this,ah,ag,af.canvas,ac.data)}},get_canvas_height:function(ac,af,ag,ad){if(ac.dataset_type==="summary_tree"){return this.summary_draw_height}else{var ae=new (this.painter)(ac.data,null,null,this.prefs,af);return ae.get_required_height()}},before_draw:function(){this.max_height_px=0}});var S=function(ae,ad,ag){c.call(this,ae,ad,ag);var af=l.get_random_color(),ac=l.get_random_color([af,"#ffffff"]);this.config=new F({track:this,params:[{key:"name",label:"Name",type:"text",default_value:this.name},{key:"block_color",label:"Block and sense strand color",type:"color",default_value:af},{key:"reverse_strand_color",label:"Antisense strand color",type:"color",default_value:ac},{key:"label_color",label:"Label color",type:"color",default_value:"black"},{key:"show_insertions",label:"Show insertions",type:"bool",default_value:false},{key:"show_differences",label:"Show differences only",type:"bool",default_value:true},{key:"show_counts",label:"Show summary counts",type:"bool",default_value:true},{key:"histogram_max",label:"Histogram maximum",type:"float",default_value:null,help:"Clear value to set automatically"},{key:"mode",type:"string",default_value:this.mode,hidden:true}],saved_values:ag.prefs,onchange:function(){this.track.set_name(this.track.prefs.name);this.track.tile_cache.clear();this.track.request_draw()}});this.prefs=this.config.values;this.painter=(ae.reference_track?L.RefBasedReadPainter:L.ReadPainter);this.update_icons()};q(S.prototype,r.prototype,M.prototype,c.prototype);var d={CompositeTrack:f,DrawableGroup:P,DiagonalHeatmapTrack:t,FeatureTrack:c,LineTrack:h,ReadTrack:S,VariantTrack:Z,VcfTrack:Z};var p=function(ae,ad,ac){if("copy" in ae){return ae.copy(ac)}else{var af=ae.obj_type;if(!af){af=ae.track_type}return new d[af](ad,ac,ae)}};return{TracksterView:Y,DrawableGroup:P,LineTrack:h,FeatureTrack:c,DiagonalHeatmapTrack:t,ReadTrack:S,VariantTrack:Z,CompositeTrack:f,object_from_template:p}});
\ No newline at end of file
diff -r b9bd0fae39cabc1ff55f374e026b7aa3f5687c77 -r 7f70ea89d5a92cba463b873de7535766bb8c7050 templates/webapps/galaxy/root/history.mako
--- a/templates/webapps/galaxy/root/history.mako
+++ b/templates/webapps/galaxy/root/history.mako
@@ -15,40 +15,7 @@
## a list of localized strings used in the backbone views, etc. (to be loaded and cached)
##! change on per page basis
<%
- ## havent been localized
- ##[
- ## "anonymous user",
- ## "Click to rename history",
- ## "Click to see more actions",
- ## "Edit history tags",
- ## "Edit history annotation",
- ## "Tags",
- ## "Annotation",
- ## "Click to edit annotation",
- ## "You are over your disk ...w your allocated quota.",
- ## "Show deleted",
- ## "Show hidden",
- ## "View data",
- ## "Edit Attributes",
- ## "Download",
- ## "View details",
- ## "Run this job again",
- ## "Visualize",
- ## "Edit dataset tags",
- ## "Edit dataset annotation",
- ## "Trackster",
- ## "Circster",
- ## "Scatterplot",
- ## "GeneTrack",
- ## "Local",
- ## "Web",
- ## "Current",
- ## "main",
- ## "Using"
- ##]
strings_to_localize = [
-
- # from history.mako
# not needed?: "Galaxy History",
'refresh',
'collapse all',
@@ -288,6 +255,16 @@
});
historyPanel.render();
+ // set up messages passed in
+ %if hda_id:
+ var hdaId = "${hda_id}";
+ // have to fake 'once' here - simplify when bbone >= 1.0
+ historyPanel.on( 'rendered:initial', function scrollOnce(){
+ this.off( 'rendered:initial', scrollOnce, this );
+ this.scrollToId( hdaId );
+ }, historyPanel );
+ %endif
+
// QUOTA METER is a cross-frame ui element (meter in masthead, watches hist. size built here)
//TODO: the quota message (curr. in the history panel) belongs somewhere else
//TODO: does not display if in own tab
diff -r b9bd0fae39cabc1ff55f374e026b7aa3f5687c77 -r 7f70ea89d5a92cba463b873de7535766bb8c7050 test/casperjs/hda-state-tests.js
--- a/test/casperjs/hda-state-tests.js
+++ b/test/casperjs/hda-state-tests.js
@@ -44,11 +44,21 @@
var utils = require( 'utils' ),
historyFrameInfo = {},
+ filepathToUpload = '../../test-data/1.bam',
+ testUploadInfo = {},
+ //TODO: get from the api module - that doesn't exist yet
+
+ //summaryShouldBeArray = [ '3.5 KB', 'format: bam' ],
+ //infoShouldBe = 'uploaded bam file',
+ //metadataFiles = [ 'bam_index' ],
+ //peekShouldBeArray = [];
+
filepathToUpload = '../../test-data/1.txt',
testUploadInfo = {},
//TODO: get from the api module - that doesn't exist yet
summaryShouldBeArray = [ '10 lines', 'format: txt' ],
infoShouldBe = 'uploaded txt file',
+ metadataFiles = null,
peekShouldBeArray = [];
// ------------------------------------------------------------------- set up
@@ -74,6 +84,42 @@
'HDA contains name (' + name + '): ' + this.fetchText( titleSelector ) );
}
+function testIconButton( hdaDbId, containerSelector, buttonName, expectedButtonData ){
+ this.test.comment( buttonName + ' should exist, be visible, and well formed' );
+ this.debug( 'checking button "' + buttonName + '" within "' + containerSelector + '":\n' +
+ this.jsonStr( expectedButtonData ) );
+
+ if( !expectedButtonData.selector ){ this.test.fail( 'BAD TEST DATA: no selector given' ); }
+ var btnSelector = containerSelector + ' ' + expectedButtonData.selector;
+ this.test.assertExists( btnSelector, buttonName + ' button exists' );
+ this.test.assertVisible( btnSelector, buttonName + ' button is visible' );
+
+ var buttonElement = this.getElementInfo( btnSelector );
+ this.debug( 'buttonElement:' + this.jsonStr( this.quickInfo( buttonElement ) ) );
+
+ if( expectedButtonData.nodeName ){
+ this.test.assert( buttonElement.nodeName === expectedButtonData.nodeName,
+ buttonName + ' is proper node type (' + expectedButtonData.nodeName + '): ' + buttonElement.nodeName );
+ }
+
+ if( expectedButtonData.hrefTpl ){
+ var href = buttonElement.attributes.href,
+ hrefShouldBe = utils.format( expectedButtonData.hrefTpl, hdaDbId );
+ this.assertTextContains( href, hrefShouldBe,
+ buttonName + ' has proper href (' + hrefShouldBe + '): ' + href );
+ }
+
+ if( expectedButtonData.tooltip ){
+ this.historypanel.hoverOver( btnSelector );
+ var tooltipText = expectedButtonData.tooltip;
+ this.test.assertVisible( tooltipSelector, buttonName + ' button tooltip is visible when hovering' );
+ this.test.assertSelectorHasText( tooltipSelector, tooltipText,
+ buttonName + ' button has tooltip text: "' + tooltipText + '"' );
+ // clear the tooltip
+ this.page.sendEvent( 'mouseover', 0, 0 );
+ }
+}
+
function testTitleButtonStructure( hdaSelector, shouldHaveTheseButtons ){
// defaults to the current buttons most states should have
shouldHaveTheseButtons = shouldHaveTheseButtons || [ 'display', 'edit', 'delete' ];
@@ -84,37 +130,13 @@
this.test.assertVisible( buttonsArea, 'Button area is visible' );
- for( var i=0; i<shouldHaveTheseButtons.length; i++ ){
+ for( var i=0; i<shouldHaveTheseButtons.length; i += 1 ){
// don't use button names we don't have data for
var buttonName = shouldHaveTheseButtons[ i ];
if( !buttons.hasOwnProperty( buttonName ) ){ continue; }
+ var button = buttons[ buttonName ];
- this.test.comment( buttonName + ' should exist, be visible, and well formed' );
- var button = buttons[ buttonName ];
- this.debug( 'checking button "' + buttonName + '" on hda "' + hdaDbId + '":\n' + this.jsonStr( button ) );
- this.test.assertExists( button.selector, buttonName + ' button exists' );
- this.test.assertVisible( button.selector, buttonName + ' button is visible' );
-
- var buttonElement = this.getElementInfo( button.selector );
- this.debug( 'buttonElement:' + this.jsonStr( this.quickInfo( buttonElement ) ) );
-
- // should be an anchor
- this.test.assert( buttonElement.nodeName === button.nodeName,
- buttonName + ' is proper node type (' + button.nodeName + '): ' + buttonElement.nodeName );
-
- // should have a proper href
- var href = buttonElement.attributes.href,
- hrefShouldBe = utils.format( button.hrefTpl, hdaDbId );
- this.assertTextContains( href, hrefShouldBe,
- buttonName + ' has proper href (' + hrefShouldBe + '): ' + href );
-
- this.historypanel.hoverOver( button.selector );
- var tooltipText = button.tooltip;
- this.test.assertVisible( tooltipSelector, buttonName + ' button tooltip is visible when hovering' );
- this.test.assertSelectorHasText( tooltipSelector, tooltipText,
- buttonName + ' button has tooltip text: "' + tooltipText + '"' );
- // clear the tooltip
- this.page.sendEvent( 'mouseover', 0, 0 );
+ testIconButton.call( this, hdaDbId, buttonsArea, buttonName, button );
}
}
@@ -153,13 +175,80 @@
}
}
-function testPrimaryActionButtons( hdaSelector ){
- var buttonsSelector = hdaSelector + ' ' + this.historypanel.data.selectors.hda.body
- + ' ' + this.historypanel.data.selectors.hda.primaryActionButtons;
+function testDownloadMenu( hdaSelector, expectedMetadataFiles ){
+ var hdaDbId = this.getElementAttribute( hdaSelector, 'id' ).split( '-' )[1];
+
+ // assert has classes: menubutton split popup
+ // click popup
+}
+
+function testMetadataDownloadLink( menuSelector, metadataFile ){
+
+}
+
+function testPrimaryActionButtons( hdaSelector, expectedMetadataFiles ){
+ //TODO: not abstracted well for all states
+ var hdaDbId = this.getElementAttribute( hdaSelector, 'id' ).split( '-' )[1],
+ buttonsSelector = hdaSelector + ' ' + this.historypanel.data.selectors.hda.body
+ + ' ' + this.historypanel.data.selectors.hda.primaryActionButtons,
+ dropdownSelector = '#' + utils.format(
+ this.historypanel.data.hdaPrimaryActionButtons.downloadDropdownButtonIdTpl, hdaDbId );
+
this.test.comment( 'Primary action buttons div should exist and be visible' );
this.test.assertExists( buttonsSelector, 'Primary action buttons div exists' );
this.test.assertVisible( buttonsSelector, 'Primary action buttons div is visible' );
//TODO: ...
+ // different states, datatypes will have different action buttons
+ testIconButton.call( this, hdaDbId, buttonsSelector, 'info',
+ this.historypanel.data.hdaPrimaryActionButtons.info );
+ testIconButton.call( this, hdaDbId, buttonsSelector, 'rerun',
+ this.historypanel.data.hdaPrimaryActionButtons.rerun );
+
+ //TODO: move to testDownloadButton as its own step
+ if( !expectedMetadataFiles ){
+ this.test.comment( 'no expected metadata, download button should be an icon button' );
+ this.test.assertDoesntExist( dropdownSelector, 'no dropdown selector exists:' + dropdownSelector );
+ testIconButton.call( this, hdaDbId, buttonsSelector, 'download',
+ this.historypanel.data.hdaPrimaryActionButtons.download );
+
+ } else {
+ this.test.comment( 'expecting metadata, download button should be a popup menu' );
+
+ // will be a drop down and should contain links to all metadata files
+ this.test.assertVisible( dropdownSelector, 'dropdown menu button visible: ' + dropdownSelector );
+ testIconButton.call( this, hdaDbId, dropdownSelector, 'download',
+ this.historypanel.data.hdaPrimaryActionButtons.download );
+
+ this.test.comment( 'clicking the button should show a popup menu with download links' );
+ this.click( dropdownSelector );
+ this.wait( 100, function(){
+ //TODO: abstract to popup menu checker
+ var menuSelector = '#' + utils.format(
+ this.historypanel.data.hdaPrimaryActionButtons.downloadDropdownMenuIdTpl, hdaDbId );
+ this.test.assertVisible( menuSelector, 'menu visible: ' + menuSelector );
+
+ var liCounter = 1;
+ var mainDataSelector = menuSelector + ' ' + 'li:nth-child(' + liCounter + ') a';
+ this.assertVisibleWithText( mainDataSelector, 'Download Dataset',
+ mainDataSelector + ' (main data download) has proper text: ' + 'Download Dataset' );
+ liCounter += 1;
+
+ var splitLabelSelector = menuSelector + ' ' + 'li:nth-child(' + liCounter + ') a';
+ this.test.assertVisible( splitLabelSelector, 'split label visible' );
+ this.test.assertSelectorHasText( splitLabelSelector, 'Additional Files',
+ 'split label has proper text' );
+ liCounter += 1;
+
+ var self = this;
+ expectedMetadataFiles.forEach( function( file ){
+ var linkSelector = menuSelector + ' ' + 'li:nth-child(' + liCounter + ') a';
+ self.test.assertVisible( linkSelector, '#' + liCounter + ' link visible' );
+ self.test.assertSelectorHasText( linkSelector, 'Download ' + file,
+ '#' + liCounter + ' link has proper text: Download ' + file );
+ liCounter += 1;
+ });
+ });
+ }
}
function testSecondaryActionButtons( hdaSelector ){
@@ -169,6 +258,7 @@
this.test.assertExists( buttonsSelector, 'Secondary action buttons div exists' );
this.test.assertVisible( buttonsSelector, 'Secondary action buttons div is visible' );
//TODO: ...
+ // tags, annotations
}
function testPeek( hdaSelector, expectedPeekArray ){
@@ -182,7 +272,7 @@
});
}
-function testExpandedBody( hdaSelector, expectedSummaryTextArray, expectedInfoText, dbkeySetTo ){
+function testExpandedBody( hdaSelector, expectedSummaryTextArray, expectedInfoText, dbkeySetTo, expectedMetadata ){
var body = hdaSelector + ' ' + this.historypanel.data.selectors.hda.body;
this.test.assertExists( body, 'body exists' );
this.test.assertVisible( body, 'body is visible' );
@@ -208,7 +298,7 @@
this.test.assertSelectorHasText( info, expectedInfoText,
'info has proper text (' + expectedInfoText + '): ' + this.fetchText( info ) );
- testPrimaryActionButtons.call( this, hdaSelector );
+ testPrimaryActionButtons.call( this, hdaSelector, expectedMetadata );
testSecondaryActionButtons.call( this, hdaSelector ); //TODO: isAnonymous
testPeek.call( this, hdaSelector, peekShouldBeArray );
}
@@ -241,7 +331,10 @@
this.historypanel.thenExpandHda( uploadSelector, function(){
// ugh.
this.jumpToHistory( function(){
- testExpandedBody.call( spaceghost, uploadSelector, summaryShouldBeArray, infoShouldBe, false );
+ testExpandedBody.call( spaceghost, uploadSelector,
+ summaryShouldBeArray, infoShouldBe, false, metadataFiles );
+ //testExpandedBody.call( spaceghost, uploadSelector,
+ // summaryShouldBeArray, infoShouldBe, false );
});
});
});
@@ -291,6 +384,29 @@
this.test.assertSelectorHasText( bodySelector, expectedBodyText,
'HDA body has text: ' + expectedBodyText );
});
+
+ this.historypanel.then( function(){
+ this.test.comment( 'a simulated error on a new dataset should appear in a message box' );
+ // datasets that error on fetching their data appear as 'new', so do this here
+ // more of a unit test, but ok
+ var errorString = 'Blah!';
+
+ this.evaluate( function( errorString ){
+ return Galaxy.currHistoryPanel.model.hdas.getByHid( 1 ).set( 'error', errorString );
+ }, errorString );
+
+ // wait for re-render
+ this.wait( 1000, function(){
+ var errorMessage = this.historypanel.data.selectors.hda.errorMessage;
+
+ this.test.assertExists( errorMessage, 'error message exists' );
+ this.test.assertVisible( errorMessage, 'error message is visible' );
+ this.test.assertSelectorHasText( errorMessage, this.historypanel.data.text.hda.datasetFetchErrorMsg,
+ 'error message has text: ' + this.historypanel.data.text.hda.datasetFetchErrorMsg );
+ this.test.assertSelectorHasText( errorMessage, errorString,
+ 'error message has error string: ' + errorString );
+ });
+ });
});
});
// restore state, collapse
@@ -299,6 +415,7 @@
this.historypanel.thenCollapseHda( uploadSelector, function(){
this.evaluate( function(){
+ Galaxy.currHistoryPanel.model.hdas.getByHid( 1 ).unset( 'error' );
return Galaxy.currHistoryPanel.model.hdas.at( 0 ).set( 'state', 'ok' );
});
});
diff -r b9bd0fae39cabc1ff55f374e026b7aa3f5687c77 -r 7f70ea89d5a92cba463b873de7535766bb8c7050 test/casperjs/modules/historypanel.js
--- a/test/casperjs/modules/historypanel.js
+++ b/test/casperjs/modules/historypanel.js
@@ -332,6 +332,28 @@
nodeName : 'a'
}
},
+ hdaPrimaryActionButtons : {
+ download : {
+ selector : '.icon-button.disk',
+ tooltip : 'Download',
+ hrefTpl : '/datasets/%s/display?to_ext=',
+ nodeName : 'a'
+ },
+ info : {
+ selector : '.icon-button.information',
+ tooltip : 'View details',
+ hrefTpl : '/datasets/%s/show_params',
+ nodeName : 'a'
+ },
+ rerun : {
+ selector : '.icon-button.arrow-circle',
+ tooltip : 'Run this job again',
+ hrefTpl : '/tool_runner/rerun?id=%s',
+ nodeName : 'a'
+ },
+ downloadDropdownButtonIdTpl : 'dataset-%s-popup',
+ downloadDropdownMenuIdTpl : 'dataset-%s-popup-menu'
+ },
selectors : {
history : {
name : 'div#history-name',
@@ -354,14 +376,18 @@
'new' : 'historyItem-new'
}
},
+ errorMessage : '.errormessagesmall',
+
title : '.historyItemTitle',
titleButtonArea : '.historyItemButtons',
body : '.historyItemBody',
summary : '.hda-summary',
dbkey : '.metadata-dbkey',
info : '.hda-info',
+
primaryActionButtons : 'div[id^="primary-actions"]',
secondaryActionButtons : 'div[id^="secondary-actions"]',
+
peek : 'pre.peek'
}
},
@@ -388,6 +414,9 @@
newName : 'Unnamed history',
newSize : '0 bytes',
emptyMsg : "Your history is empty. Click 'Get Data' on the left pane to start"
+ },
+ hda : {
+ datasetFetchErrorMsg : 'There was an error getting the data for this dataset'
}
}
};
diff -r b9bd0fae39cabc1ff55f374e026b7aa3f5687c77 -r 7f70ea89d5a92cba463b873de7535766bb8c7050 test/casperjs/spaceghost.js
--- a/test/casperjs/spaceghost.js
+++ b/test/casperjs/spaceghost.js
@@ -755,7 +755,17 @@
} else {
assertSelectorAndText( selector, text );
}
-}
+};
+
+/** Test helper - assert selector exists, is visible, and has text
+ * @param {CasperJS selector} selector what element in which to search for the text
+ * @param {String} text what text to search for (optional)
+ */
+SpaceGhost.prototype.assertVisibleWithText = function assertVisibleWithText( selector, text, msg ){
+ var visible = this.test.casper.visible( selector ),
+ hasText = this.test.casper.fetchText( selector ).indexOf( text ) !== -1;
+ this.test.assert( visible && hasText, msg );
+};
/** Test helper - within frame, assert errormessage, and assert text in errormessage
* *message is a common UI feedback motif in Galaxy (often displayed in the main panel)
https://bitbucket.org/galaxy/galaxy-central/commits/494837c4fe5b/
Changeset: 494837c4fe5b
User: carlfeberhard
Date: 2013-04-16 20:06:39
Summary: branch merge
Affected #: 0 files
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
2 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/ce528b16d630/
Changeset: ce528b16d630
User: natefoo
Date: 2013-04-16 19:50:46
Summary: Merge closed branch.
Affected #: 0 files
https://bitbucket.org/galaxy/galaxy-central/commits/518dc45c64c6/
Changeset: 518dc45c64c6
User: natefoo
Date: 2013-04-16 19:50:59
Summary: Merge closed branch.
Affected #: 0 files
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
4 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/bf819d50c9dd/
Changeset: bf819d50c9dd
Branch: feature/transact-with-ts
User: natefoo
Date: 2013-04-16 19:47:11
Summary: Close feature/trasact-with-ts branch.
Affected #: 0 files
https://bitbucket.org/galaxy/galaxy-central/commits/98055c5c428e/
Changeset: 98055c5c428e
Branch: next-stable
User: natefoo
Date: 2013-04-16 19:47:37
Summary: Close next-stable branch.
Affected #: 0 files
https://bitbucket.org/galaxy/galaxy-central/commits/69639fb0f2f5/
Changeset: 69639fb0f2f5
User: natefoo
Date: 2013-04-16 19:48:10
Summary: Merge branch close.
Affected #: 0 files
https://bitbucket.org/galaxy/galaxy-central/commits/c2c079a2bee4/
Changeset: c2c079a2bee4
User: natefoo
Date: 2013-04-16 19:48:34
Summary: Merge closed branch.
Affected #: 0 files
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
14 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/18eea1b2c803/
Changeset: 18eea1b2c803
Branch: next-stable
User: Galaxy
Date: 2013-03-27 00:29:49
Summary: hg flow init, add .hgflow file
Affected #: 1 file
diff -r c5d7d2bd7928c160a5163fe9fc9a5e20aa5470ae -r 18eea1b2c803ba307cea5a0f30850ff62d7d4d86 .hgflow
--- /dev/null
+++ b/.hgflow
@@ -0,0 +1,8 @@
+[Basic]
+develop = next-stable
+feature = feature/
+version_tag =
+publish = default
+release = release/
+hotfix = hotfix/
+
https://bitbucket.org/galaxy/galaxy-central/commits/60947fb5b3d3/
Changeset: 60947fb5b3d3
Branch: next-stable
User: Galaxy
Date: 2013-03-27 20:29:33
Summary: merge
Affected #: 41 files
diff -r 18eea1b2c803ba307cea5a0f30850ff62d7d4d86 -r 60947fb5b3d3c62417facc65f9e42eb930dded73 .hgignore
--- a/.hgignore
+++ b/.hgignore
@@ -24,15 +24,21 @@
# Python bytecode
*.pyc
+# Galaxy Runtime Files
+paster.lock
+paster.log
+paster.pid
+
# Tool Shed Runtime Files
-community_webapp.log
-community_webapp.pid
+tool_shed_webapp.lock
+tool_shed_webapp.log
+tool_shed_webapp.pid
hgweb.config*
# Config files
universe_wsgi.ini
reports_wsgi.ini
-community_wsgi.ini
+tool_shed_wsgi.ini
# Config files.
datatypes_conf.xml
diff -r 18eea1b2c803ba307cea5a0f30850ff62d7d4d86 -r 60947fb5b3d3c62417facc65f9e42eb930dded73 lib/galaxy/datatypes/display_applications/__init__.py
--- a/lib/galaxy/datatypes/display_applications/__init__.py
+++ b/lib/galaxy/datatypes/display_applications/__init__.py
@@ -1,1 +1,3 @@
-
+"""
+Contains functionality of the newer XML defined external display applications (not hardcoded into datatype classes).
+"""
diff -r 18eea1b2c803ba307cea5a0f30850ff62d7d4d86 -r 60947fb5b3d3c62417facc65f9e42eb930dded73 lib/galaxy/datatypes/display_applications/link_generator.py
--- a/lib/galaxy/datatypes/display_applications/link_generator.py
+++ b/lib/galaxy/datatypes/display_applications/link_generator.py
@@ -1,8 +1,11 @@
-"""Classes to generate links for display applications.
+"""Classes to generate links for old-style display applications.
Separating Transaction based elements of display applications from datatypes.
"""
+#FIXME: The code contained within this file is for old-style display applications, but
+#this module namespace is intended to only handle the new-style display applications.
+
import urllib
# for the url_for hack
@@ -19,6 +22,8 @@
#TODO: these could be extended to handle file_function and parse/contain the builds.txt files
+#HACK: these duplicate functionality from the individual datatype classes themselves
+
def get_display_app_link_generator( display_app_name ):
"""Returns an instance of the proper link generator class
based on the display_app_name or DisplayAppLinkGenerator
diff -r 18eea1b2c803ba307cea5a0f30850ff62d7d4d86 -r 60947fb5b3d3c62417facc65f9e42eb930dded73 lib/galaxy/model/__init__.py
--- a/lib/galaxy/model/__init__.py
+++ b/lib/galaxy/model/__init__.py
@@ -3040,9 +3040,9 @@
pass
class ToolShedRepository( object ):
- api_collection_visible_keys = ( 'id', 'name', 'tool_shed', 'owner', 'installed_changeset_revision', 'changeset_revision', 'ctx_rev', 'includes_datatypes',
+ api_collection_visible_keys = ( 'id', 'tool_shed', 'name', 'owner', 'installed_changeset_revision', 'changeset_revision', 'ctx_rev', 'includes_datatypes',
'update_available', 'deleted', 'uninstalled', 'dist_to_shed', 'status', 'error_message' )
- api_element_visible_keys = ( 'id', 'name', 'tool_shed', 'owner', 'installed_changeset_revision', 'changeset_revision', 'ctx_rev', 'includes_datatypes',
+ api_element_visible_keys = ( 'id', 'tool_shed', 'name', 'owner', 'installed_changeset_revision', 'changeset_revision', 'ctx_rev', 'includes_datatypes',
'update_available', 'deleted', 'uninstalled', 'dist_to_shed', 'status', 'error_message' )
installation_status = Bunch( NEW='New',
CLONING='Cloning',
@@ -3079,10 +3079,8 @@
self.dist_to_shed = dist_to_shed
self.status = status
self.error_message = error_message
- def as_dict( self, trans ):
- tsr_dict = self.get_api_value( view='element' )
- tsr_dict[ 'id' ] = trans.security.encode_id( self.id )
- return tsr_dict
+ def as_dict( self, value_mapper=None ):
+ return self.get_api_value( view='element', value_mapper=value_mapper )
def repo_files_directory( self, app ):
repo_path = self.repo_path( app )
if repo_path:
@@ -3182,7 +3180,7 @@
try:
rval[ key ] = self.__getattribute__( key )
if key in value_mapper:
- rval[ key ] = value_mapper.get( key )( rval[ key ] )
+ rval[ key ] = value_mapper.get( key, rval[ key ] )
except AttributeError:
rval[ key ] = None
return rval
diff -r 18eea1b2c803ba307cea5a0f30850ff62d7d4d86 -r 60947fb5b3d3c62417facc65f9e42eb930dded73 lib/galaxy/web/__init__.py
--- a/lib/galaxy/web/__init__.py
+++ b/lib/galaxy/web/__init__.py
@@ -1,7 +1,16 @@
"""
The Galaxy web application framework
"""
-
-from framework import expose, json, json_pretty, require_login, require_admin, url_for, error, form, FormBuilder, expose_api, expose_api_raw
+from framework import expose
+from framework import json
+from framework import json_pretty
+from framework import require_login
+from framework import require_admin
+from framework import url_for
+from framework import error
+from framework import form
+from framework import FormBuilder
+from framework import expose_api
+from framework import expose_api_anonymous
+from framework import expose_api_raw
from framework.base import httpexceptions
-
diff -r 18eea1b2c803ba307cea5a0f30850ff62d7d4d86 -r 60947fb5b3d3c62417facc65f9e42eb930dded73 lib/galaxy/web/framework/__init__.py
--- a/lib/galaxy/web/framework/__init__.py
+++ b/lib/galaxy/web/framework/__init__.py
@@ -106,7 +106,13 @@
"""
return expose_api( func, to_json=False )
-def expose_api( func, to_json=True ):
+def expose_api_anonymous( func, to_json=True ):
+ """
+ Expose this function via the API but don't require an API key.
+ """
+ return expose_api( func, to_json=to_json, key_required=False )
+
+def expose_api( func, to_json=True, key_required=True ):
@wraps(func)
def decorator( self, trans, *args, **kwargs ):
def error( environ, start_response ):
@@ -114,7 +120,7 @@
return error_message
error_status = '403 Forbidden'
## If there is a user, we've authenticated a session.
- if not trans.user and isinstance(trans.galaxy_session, Bunch):
+ if key_required and not trans.user and isinstance( trans.galaxy_session, Bunch ):
# If trans.user is already set, don't check for a key.
# This happens when we're authenticating using session instead of an API key.
# The Bunch clause is used to prevent the case where there's no user, but there is a real session.
diff -r 18eea1b2c803ba307cea5a0f30850ff62d7d4d86 -r 60947fb5b3d3c62417facc65f9e42eb930dded73 lib/galaxy/webapps/galaxy/api/tool_shed_repositories.py
--- /dev/null
+++ b/lib/galaxy/webapps/galaxy/api/tool_shed_repositories.py
@@ -0,0 +1,339 @@
+import logging
+import urllib2
+from galaxy.util import json
+from galaxy import util
+from galaxy import web
+from galaxy.web.base.controller import BaseAPIController
+from tool_shed.galaxy_install import repository_util
+import tool_shed.util.shed_util_common as suc
+
+log = logging.getLogger( __name__ )
+
+def default_tool_shed_repository_value_mapper( trans, tool_shed_repository ):
+ value_mapper={ 'id' : trans.security.encode_id( tool_shed_repository.id ),
+ 'error_message' : tool_shed_repository.error_message or '' }
+ return value_mapper
+
+def get_message_for_no_shed_tool_config():
+ # This Galaxy instance is not configured with a shed-related tool panel configuration file.
+ message = 'The tool_config_file setting in universe_wsgi.ini must include at least one shed tool configuration file name with a <toolbox> '
+ message += 'tag that includes a tool_path attribute value which is a directory relative to the Galaxy installation directory in order to '
+ message += 'automatically install tools from a tool shed into Galaxy (e.g., the file name shed_tool_conf.xml whose <toolbox> tag is '
+ message += '<toolbox tool_path="../shed_tools">). For details, see the "Installation of Galaxy tool shed repository tools into a local '
+ message += 'Galaxy instance" section of the Galaxy tool shed wiki at http://wiki.galaxyproject.org/InstallingRepositoriesToGalaxy#'
+ message += 'Installing_Galaxy_tool_shed_repository_tools_into_a_local_Galaxy_instance.'
+ return message
+
+class ToolShedRepositoriesController( BaseAPIController ):
+ """RESTful controller for interactions with tool shed repositories."""
+
+ @web.expose_api
+ def index( self, trans, **kwd ):
+ """
+ GET /api/tool_shed_repositories
+ Display a list of dictionaries containing information about installed tool shed repositories.
+ """
+ # Example URL: http://localhost:8763/api/tool_shed_repositories
+ tool_shed_repository_dicts = []
+ try:
+ query = trans.sa_session.query( trans.app.model.ToolShedRepository ) \
+ .order_by( trans.app.model.ToolShedRepository.table.c.name ) \
+ .all()
+ for tool_shed_repository in query:
+ tool_shed_repository_dict = tool_shed_repository.get_api_value( value_mapper=default_tool_shed_repository_value_mapper( trans, tool_shed_repository ) )
+ tool_shed_repository_dict[ 'url' ] = web.url_for( controller='tool_shed_repositories',
+ action='show',
+ id=trans.security.encode_id( tool_shed_repository.id ) )
+ tool_shed_repository_dicts.append( tool_shed_repository_dict )
+ return tool_shed_repository_dicts
+ except Exception, e:
+ message = "Error in the tool_shed_repositories API in index: %s" % str( e )
+ log.error( message, exc_info=True )
+ trans.response.status = 500
+ return message
+
+ @web.expose_api
+ def show( self, trans, id, **kwd ):
+ """
+ GET /api/tool_shed_repositories/{encoded_tool_shed_repsository_id}
+ Display a dictionary containing information about a specified tool_shed_repository.
+
+ :param id: the encoded id of the ToolShedRepository object
+ """
+ # Example URL: http://localhost:8763/api/tool_shed_repositories/df7a1f0c02a5b08e
+ try:
+ tool_shed_repository = suc.get_tool_shed_repository_by_id( trans, id )
+ tool_shed_repository_dict = tool_shed_repository.as_dict( value_mapper=default_tool_shed_repository_value_mapper( trans, tool_shed_repository ) )
+ tool_shed_repository_dict[ 'url' ] = web.url_for( controller='tool_shed_repositories',
+ action='show',
+ id=trans.security.encode_id( tool_shed_repository.id ) )
+ return tool_shed_repository_dict
+ except Exception, e:
+ message = "Error in tool_shed_repositories API in index: " + str( e )
+ log.error( message, exc_info=True )
+ trans.response.status = 500
+ return message
+
+ @web.expose_api
+ def install_repository_revision( self, trans, payload, **kwd ):
+ """
+ POST /api/tool_shed_repositories/install_repository_revision
+ Install a specified repository revision from a specified tool shed into Galaxy.
+
+ :param key: the current Galaxy admin user's API key
+
+ The following parameters are included in the payload.
+ :param tool_shed_url (required): the base URL of the Tool Shed from which to install the Repository
+ :param name (required): the name of the Repository
+ :param owner (required): the owner of the Repository
+ :param changset_revision (required): the changset_revision of the RepositoryMetadata object associated with the Repository
+ :param new_tool_panel_section_label (optional): label of a new section to be added to the Galaxy tool panel in which to load
+ tools contained in the Repository. Either this parameter must be an empty string or
+ the tool_panel_section_id parameter must be an empty string or both must be an empty
+ string (both cannot be used simultaneously).
+ :param tool_panel_section_id (optional): id of the Galaxy tool panel section in which to load tools contained in the Repository.
+ If this parameter is an empty string and the above new_tool_panel_section_label parameter is an
+ empty string, tools will be loaded outside of any sections in the tool panel. Either this
+ parameter must be an empty string or the tool_panel_section_id parameter must be an empty string
+ of both must be an empty string (both cannot be used simultaneously).
+ :param install_repository_dependencies (optional): Set to True if you want to install repository dependencies defined for the specified
+ repository being installed. The default setting is False.
+ :param install_tool_dependencies (optional): Set to True if you want to install tool dependencies defined for the specified repository being
+ installed. The default setting is False.
+ :param shed_tool_conf (optional): The shed-related tool panel configuration file configured in the "tool_config_file" setting in the Galaxy config file
+ (e.g., universe_wsgi.ini). At least one shed-related tool panel config file is required to be configured. Setting
+ this parameter to a specific file enables you to choose where the specified repository will be installed because
+ the tool_path attribute of the <toolbox> from the specified file is used as the installation location
+ (e.g., <toolbox tool_path="../shed_tools">). If this parameter is not set, a shed-related tool panel configuration
+ file will be selected automatically.
+ """
+ # Get the information about the repository to be installed from the payload.
+ tool_shed_url = payload.get( 'tool_shed_url', '' )
+ if not tool_shed_url:
+ raise HTTPBadRequest( detail="Missing required parameter 'tool_shed_url'." )
+ name = payload.get( 'name', '' )
+ if not name:
+ raise HTTPBadRequest( detail="Missing required parameter 'name'." )
+ owner = payload.get( 'owner', '' )
+ if not owner:
+ raise HTTPBadRequest( detail="Missing required parameter 'owner'." )
+ changeset_revision = payload.get( 'changeset_revision', '' )
+ if not changeset_revision:
+ raise HTTPBadRequest( detail="Missing required parameter 'changeset_revision'." )
+ # Make sure this Galaxy instance is configured with a shed-related tool panel configuration file.
+ if not suc.have_shed_tool_conf_for_install( trans ):
+ message = get_message_for_no_shed_tool_config()
+ log.error( message, exc_info=True )
+ trans.response.status = 500
+ return dict( status='error', error=message )
+ # Make sure the current user's API key proves he is an admin user in this Galaxy instance.
+ if not trans.user_is_admin():
+ raise HTTPForbidden( detail='You are not authorized to install a tool shed repository into this Galaxy instance.' )
+ # Keep track of all repositories that are installed - there may be more than one if repository dependencies are installed.
+ installed_tool_shed_repositories = []
+ # Get all of the information necessary for installing the repository from the specified tool shed.
+ url = suc.url_join( tool_shed_url,
+ 'api/repositories/get_repository_revision_install_info?name=%s&owner=%s&changeset_revision=%s' % \
+ ( name, owner, changeset_revision ) )
+ try:
+ response = urllib2.urlopen( url )
+ raw_text = response.read()
+ response.close()
+ except Exception, e:
+ message = "Error attempting to retrieve installation information from tool shed %s for revision %s of repository %s owned by %s: %s" % \
+ ( str( tool_shed_url ), str( name ), str( owner ), str( changeset_revision ), str( e ) )
+ log.error( message, exc_info=True )
+ trans.response.status = 500
+ return dict( status='error', error=message )
+ if raw_text:
+ items = json.from_json_string( raw_text )
+ repository_dict = items[ 0 ]
+ repository_revision_dict = items[ 1 ]
+ repo_info_dict = items[ 2 ]
+ else:
+ message = "Unable to retrieve installation information from tool shed %s for revision %s of repository %s owned by %s: %s" % \
+ ( str( tool_shed_url ), str( name ), str( owner ), str( changeset_revision ) )
+ log.error( message, exc_info=True )
+ trans.response.status = 500
+ return dict( status='error', error=message )
+ repo_info_dicts = [ repo_info_dict ]
+ # Make sure the tool shed returned everything we need for installing the repository.
+ try:
+ has_repository_dependencies = repository_revision_dict[ 'has_repository_dependencies' ]
+ except:
+ raise HTTPBadRequest( detail="Missing required parameter 'has_repository_dependencies'." )
+ try:
+ includes_tools = repository_revision_dict[ 'includes_tools' ]
+ except:
+ raise HTTPBadRequest( detail="Missing required parameter 'includes_tools'." )
+ try:
+ includes_tool_dependencies = repository_revision_dict[ 'includes_tool_dependencies' ]
+ except:
+ raise HTTPBadRequest( detail="Missing required parameter 'includes_tool_dependencies'." )
+ try:
+ includes_tools_for_display_in_tool_panel = repository_revision_dict[ 'includes_tools_for_display_in_tool_panel' ]
+ except:
+ raise HTTPBadRequest( detail="Missing required parameter 'includes_tools_for_display_in_tool_panel'." )
+ # Get the information about the Galaxy components (e.g., tool pane section, tool config file, etc) that will contain the repository information.
+ install_repository_dependencies = payload.get( 'install_repository_dependencies', False )
+ install_tool_dependencies = payload.get( 'install_tool_dependencies', False )
+ new_tool_panel_section = payload.get( 'new_tool_panel_section_label', '' )
+ shed_tool_conf = payload.get( 'shed_tool_conf', None )
+ if shed_tool_conf:
+ # Get the tool_path setting.
+ index, shed_conf_dict = suc.get_shed_tool_conf_dict( trans.app, shed_tool_conf )
+ tool_path = shed_config_dict[ 'tool_path' ]
+ else:
+ # Pick a semi-random shed-related tool panel configuration file and get the tool_path setting.
+ for shed_config_dict in trans.app.toolbox.shed_tool_confs:
+ # Don't use migrated_tools_conf.xml.
+ if shed_config_dict[ 'config_filename' ] != trans.app.config.migrated_tools_config:
+ break
+ shed_tool_conf = shed_config_dict[ 'config_filename' ]
+ tool_path = shed_config_dict[ 'tool_path' ]
+ if not shed_tool_conf:
+ raise HTTPBadRequest( detail="Missing required parameter 'shed_tool_conf'." )
+ tool_panel_section_id = payload.get( 'tool_panel_section_id', '' )
+ if tool_panel_section_id not in [ None, '' ]:
+ tool_panel_section = trans.app.toolbox.tool_panel[ tool_panel_section_id ]
+ else:
+ tool_panel_section = ''
+ # Build the dictionary of information necessary for creating tool_shed_repository database records for each repository being installed.
+ installation_dict = dict( install_repository_dependencies=install_repository_dependencies,
+ new_tool_panel_section=new_tool_panel_section,
+ no_changes_checked=False,
+ reinstalling=False,
+ repo_info_dicts=repo_info_dicts,
+ tool_panel_section=tool_panel_section,
+ tool_path=tool_path,
+ tool_shed_url=tool_shed_url )
+ # Create the tool_shed_repository database records and gather additional information for repository installation.
+ created_or_updated_tool_shed_repositories, tool_panel_section_keys, repo_info_dicts, filtered_repo_info_dicts, message = \
+ repository_util.handle_tool_shed_repositories( trans, installation_dict, using_api=True )
+ if message and len( repo_info_dicts ) == 1:
+ # We're attempting to install a single repository that has already been installed into this Galaxy instance.
+ log.error( message, exc_info=True )
+ trans.response.status = 500
+ return dict( status='error', error=message )
+ if created_or_updated_tool_shed_repositories:
+ # Build the dictionary of information necessary for installing the repositories.
+ installation_dict = dict( created_or_updated_tool_shed_repositories=created_or_updated_tool_shed_repositories,
+ filtered_repo_info_dicts=filtered_repo_info_dicts,
+ has_repository_dependencies=has_repository_dependencies,
+ includes_tool_dependencies=includes_tool_dependencies,
+ includes_tools=includes_tools,
+ includes_tools_for_display_in_tool_panel=includes_tools_for_display_in_tool_panel,
+ install_repository_dependencies=install_repository_dependencies,
+ install_tool_dependencies=install_tool_dependencies,
+ message='',
+ new_tool_panel_section=new_tool_panel_section,
+ shed_tool_conf=shed_tool_conf,
+ status='done',
+ tool_panel_section=tool_panel_section,
+ tool_panel_section_keys=tool_panel_section_keys,
+ tool_path=tool_path,
+ tool_shed_url=tool_shed_url )
+ # Prepare the repositories for installation. Even though this method receives a single combination of tool_shed_url, name, owner and
+ # changeset_revision, there may be multiple repositories for installation at this point because repository dependencies may have added
+ # additional repositories for installation along with the single specified repository.
+ encoded_kwd, query, tool_shed_repositories, encoded_repository_ids = repository_util.initiate_repository_installation( trans, installation_dict )
+ # Install the repositories, keeping track of each one for later display.
+ for index, tool_shed_repository in enumerate( tool_shed_repositories ):
+ repo_info_dict = repo_info_dicts[ index ]
+ tool_panel_section_key = tool_panel_section_keys[ index ]
+ repository_util.install_tool_shed_repository( trans,
+ tool_shed_repository,
+ repo_info_dict,
+ tool_panel_section_key,
+ shed_tool_conf,
+ tool_path,
+ install_tool_dependencies,
+ reinstalling=False )
+ tool_shed_repository_dict = tool_shed_repository.as_dict( value_mapper=default_tool_shed_repository_value_mapper( trans, tool_shed_repository ) )
+ tool_shed_repository_dict[ 'url' ] = web.url_for( controller='tool_shed_repositories',
+ action='show',
+ id=trans.security.encode_id( tool_shed_repository.id ) )
+ installed_tool_shed_repositories.append( tool_shed_repository_dict )
+ else:
+ log.error( message, exc_info=True )
+ trans.response.status = 500
+ return dict( status='error', error=message )
+ # Display the list of installed repositories.
+ return installed_tool_shed_repositories
+
+ @web.expose_api
+ def install_repository_revisions( self, trans, payload, **kwd ):
+ """
+ POST /api/tool_shed_repositories/install_repository_revisions
+ Install one or more specified repository revisions from one or more specified tool sheds into Galaxy. The received parameters
+ must be ordered lists so that positional values in tool_shed_urls, names, owners and changeset_revisions are associated.
+
+ It's questionable whether this method is needed as the above method for installing a single repository can probably cover all
+ desired scenarios. We'll keep this one around just in case...
+
+ :param tool_shed_urls: the base URLs of the Tool Sheds from which to install a specified Repository
+ :param names: the names of the Repositories to be installed
+ :param owners: the owners of the Repositories to be installed
+ :param changset_revisions: the changset_revisions of each RepositoryMetadata object associated with each Repository to be installed
+ :param key: the current Galaxy admin user's API key
+ :param new_tool_panel_section_label: optional label of a new section to be added to the Galaxy tool panel in which to load
+ tools contained in the Repository. Either this parameter must be an empty string or
+ the tool_panel_section_id parameter must be an empty string, as both cannot be used.
+ :param tool_panel_section_id: optional id of the Galaxy tool panel section in which to load tools contained in the Repository.
+ If not set, tools will be loaded outside of any sections in the tool panel. Either this
+ parameter must be an empty string or the tool_panel_section_id parameter must be an empty string,
+ as both cannot be used.
+ """
+ if not suc.have_shed_tool_conf_for_install( trans ):
+ # This Galaxy instance is not configured with a shed-related tool panel configuration file.
+ message = get_message_for_no_shed_tool_config()
+ log.error( message, exc_info=True )
+ trans.response.status = 500
+ return dict( status='error', error=message )
+ if not trans.user_is_admin():
+ raise HTTPForbidden( detail='You are not authorized to install a tool shed repository into this Galaxy instance.' )
+ # Get the information about all of the repositories to be installed.
+ tool_shed_urls = util.listify( payload.get( 'tool_shed_urls', '' ) )
+ names = util.listify( payload.get( 'names', '' ) )
+ owners = util.listify( payload.get( 'owners', '' ) )
+ changeset_revisions = util.listify( payload.get( 'changeset_revisions', '' ) )
+ num_specified_repositories = len( tool_shed_urls )
+ if len( names ) != num_specified_repositories or \
+ len( owners ) != num_specified_repositories or \
+ len( changeset_revisions ) != num_specified_repositories:
+ message = 'Error in tool_shed_repositories API in install_repository_revisions: the received parameters must be ordered '
+ message += 'lists so that positional values in tool_shed_urls, names, owners and changeset_revisions are associated.'
+ log.error( message, exc_info=True )
+ trans.response.status = 500
+ return dict( status='error', error=message )
+ # Get the information about the Galaxy components (e.g., tool pane section, tool config file, etc) that will contain information
+ # about each of the repositories being installed.
+ # TODO: we may want to enhance this method to allow for each of the following to be associated with each repository instead of
+ # forcing all repositories to use the same settings.
+ install_repository_dependencies = payload.get( 'install_repository_dependencies', False )
+ install_tool_dependencies = payload.get( 'install_tool_dependencies', False )
+ new_tool_panel_section = payload.get( 'new_tool_panel_section_label', '' )
+ shed_tool_conf = payload.get( 'shed_tool_conf', None )
+ tool_path = payload.get( 'tool_path', None )
+ tool_panel_section_id = payload.get( 'tool_panel_section_id', '' )
+ all_installed_tool_shed_repositories = []
+ for index, tool_shed_url in enumerate( tool_shed_urls ):
+ current_payload = {}
+ current_payload[ 'tool_shed_url' ] = tool_shed_url
+ current_payload[ 'name' ] = names[ index ]
+ current_payload[ 'owner' ] = owners[ index ]
+ current_payload[ 'changeset_revision' ] = changeset_revisions[ index ]
+ current_payload[ 'install_repository_dependencies' ] = install_repository_dependencies
+ current_payload[ 'install_tool_dependencies' ] = install_tool_dependencies
+ current_payload[ 'new_tool_panel_section' ] = new_tool_panel_section
+ current_payload[ 'shed_tool_conf' ] = shed_tool_conf
+ current_payload[ 'tool_path' ] = tool_path
+ current_payload[ 'tool_panel_section_id' ] = tool_panel_section_id
+ installed_tool_shed_repositories = self.install_repository_revision( trans, **current_payload )
+ if isinstance( installed_tool_shed_repositories, dict ):
+ # We encountered an error.
+ return installed_tool_shed_repositories
+ elif isinstance( installed_tool_shed_repositories, list ):
+ all_installed_tool_shed_repositories.extend( installed_tool_shed_repositories )
+ return all_installed_tool_shed_repositories
+
\ No newline at end of file
diff -r 18eea1b2c803ba307cea5a0f30850ff62d7d4d86 -r 60947fb5b3d3c62417facc65f9e42eb930dded73 lib/galaxy/webapps/galaxy/buildapp.py
--- a/lib/galaxy/webapps/galaxy/buildapp.py
+++ b/lib/galaxy/webapps/galaxy/buildapp.py
@@ -104,12 +104,6 @@
name_prefix='group_',
path_prefix='/api/groups/:group_id',
parent_resources=dict( member_name='group', collection_name='groups' ) )
- webapp.api_mapper.resource( 'content',
- 'contents',
- controller='tool_shed_repository_contents',
- name_prefix='tool_shed_repository_',
- path_prefix='/api/tool_shed_repositories/:tool_shed_repository_id',
- parent_resources=dict( member_name='tool_shed_repository', collection_name='tool_shed_repositories' ) )
_add_item_tags_controller( webapp,
name_prefix="history_content_",
path_prefix='/api/histories/:history_id/contents/:history_content_id' )
@@ -142,7 +136,6 @@
webapp.api_mapper.resource( 'tool', 'tools', path_prefix='/api' )
webapp.api_mapper.resource_with_deleted( 'user', 'users', path_prefix='/api' )
webapp.api_mapper.resource( 'genome', 'genomes', path_prefix='/api' )
- webapp.api_mapper.resource( 'tool_shed_repository', 'tool_shed_repositories', path_prefix='/api' )
webapp.api_mapper.resource( 'visualization', 'visualizations', path_prefix='/api' )
webapp.api_mapper.resource( 'workflow', 'workflows', path_prefix='/api' )
webapp.api_mapper.resource_with_deleted( 'history', 'histories', path_prefix='/api' )
@@ -155,7 +148,14 @@
webapp.api_mapper.connect("workflow_dict", '/api/workflows/{workflow_id}/download', controller='workflows', action='workflow_dict', conditions=dict(method=['GET']))
# Preserve the following download route for now for dependent applications -- deprecate at some point
webapp.api_mapper.connect("workflow_dict", '/api/workflows/download/{workflow_id}', controller='workflows', action='workflow_dict', conditions=dict(method=['GET']))
-
+ # Galaxy API for tool shed features.
+ webapp.api_mapper.resource( 'tool_shed_repository',
+ 'tool_shed_repositories',
+ controller='tool_shed_repositories',
+ name_prefix='tool_shed_repository_',
+ path_prefix='/api',
+ new={ 'install_repository_revision' : 'POST' },
+ parent_resources=dict( member_name='tool_shed_repository', collection_name='tool_shed_repositories' ) )
# Connect logger from app
if app.trace_logger:
webapp.trace_logger = app.trace_logger
diff -r 18eea1b2c803ba307cea5a0f30850ff62d7d4d86 -r 60947fb5b3d3c62417facc65f9e42eb930dded73 lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py
--- a/lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py
+++ b/lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py
@@ -1,19 +1,35 @@
-import logging, os, shutil, tempfile, urllib2
+import logging
+import os
+import shutil
+import urllib2
from admin import AdminGalaxy
-from galaxy import web, util, eggs, tools
-from galaxy.web.form_builder import SelectField, CheckboxField
-from galaxy.web.framework.helpers import iff, grids
+from galaxy import eggs
+from galaxy import web
+from galaxy import util
+from galaxy.web.form_builder import CheckboxField
+from galaxy.web.framework.helpers import grids
+from galaxy.web.framework.helpers import iff
from galaxy.util import json
from galaxy.model.orm import or_
import tool_shed.util.shed_util_common as suc
-from tool_shed.util import common_install_util, data_manager_util, datatype_util, encoding_util, metadata_util
-from tool_shed.util import readme_util, repository_dependency_util, tool_dependency_util, tool_util, workflow_util
+from tool_shed.util import common_install_util
+from tool_shed.util import data_manager_util
+from tool_shed.util import datatype_util
+from tool_shed.util import encoding_util
+from tool_shed.util import metadata_util
+from tool_shed.util import readme_util
+from tool_shed.util import repository_dependency_util
+from tool_shed.util import tool_dependency_util
+from tool_shed.util import tool_util
+from tool_shed.util import workflow_util
from tool_shed.galaxy_install import repository_util
import tool_shed.galaxy_install.grids.admin_toolshed_grids as admin_toolshed_grids
import pkg_resources
eggs.require( 'mercurial' )
-from mercurial import hg, ui, commands
+from mercurial import commands
+from mercurial import hg
+from mercurial import ui
pkg_resources.require( 'elementtree' )
from elementtree import ElementTree
@@ -373,91 +389,6 @@
tool_version = tool_util.get_tool_version( app, guid )
return tool_version.get_version_ids( app, reverse=True )
- def handle_repository_contents( self, trans, tool_shed_repository, tool_path, repository_clone_url, relative_install_dir, tool_shed=None,
- tool_section=None, shed_tool_conf=None, reinstalling=False ):
- """
- Generate the metadata for the installed tool shed repository, among other things. This method is called from Galaxy (never the tool shed)
- when an admin is installing a new repository or reinstalling an uninstalled repository.
- """
- shed_config_dict = trans.app.toolbox.get_shed_config_dict_by_filename( shed_tool_conf )
- metadata_dict, invalid_file_tups = metadata_util.generate_metadata_for_changeset_revision( app=trans.app,
- repository=tool_shed_repository,
- changeset_revision=tool_shed_repository.changeset_revision,
- repository_clone_url=repository_clone_url,
- shed_config_dict=shed_config_dict,
- relative_install_dir=relative_install_dir,
- repository_files_dir=None,
- resetting_all_metadata_on_repository=False,
- updating_installed_repository=False,
- persist=True )
- tool_shed_repository.metadata = metadata_dict
- trans.sa_session.add( tool_shed_repository )
- trans.sa_session.flush()
- if 'tool_dependencies' in metadata_dict and not reinstalling:
- tool_dependencies = tool_dependency_util.create_tool_dependency_objects( trans.app, tool_shed_repository, relative_install_dir, set_status=True )
- if 'tools' in metadata_dict:
- tool_panel_dict = tool_util.generate_tool_panel_dict_for_new_install( metadata_dict[ 'tools' ], tool_section )
- sample_files = metadata_dict.get( 'sample_files', [] )
- tool_index_sample_files = tool_util.get_tool_index_sample_files( sample_files )
- tool_util.copy_sample_files( trans.app, tool_index_sample_files, tool_path=tool_path )
- sample_files_copied = [ str( s ) for s in tool_index_sample_files ]
- repository_tools_tups = suc.get_repository_tools_tups( trans.app, metadata_dict )
- if repository_tools_tups:
- # Handle missing data table entries for tool parameters that are dynamically generated select lists.
- repository_tools_tups = tool_util.handle_missing_data_table_entry( trans.app, relative_install_dir, tool_path, repository_tools_tups )
- # Handle missing index files for tool parameters that are dynamically generated select lists.
- repository_tools_tups, sample_files_copied = tool_util.handle_missing_index_file( trans.app,
- tool_path,
- sample_files,
- repository_tools_tups,
- sample_files_copied )
- # Copy remaining sample files included in the repository to the ~/tool-data directory of the local Galaxy instance.
- tool_util.copy_sample_files( trans.app, sample_files, tool_path=tool_path, sample_files_copied=sample_files_copied )
- tool_util.add_to_tool_panel( app=trans.app,
- repository_name=tool_shed_repository.name,
- repository_clone_url=repository_clone_url,
- changeset_revision=tool_shed_repository.installed_changeset_revision,
- repository_tools_tups=repository_tools_tups,
- owner=tool_shed_repository.owner,
- shed_tool_conf=shed_tool_conf,
- tool_panel_dict=tool_panel_dict,
- new_install=True )
- if 'data_manager' in metadata_dict:
- new_data_managers = data_manager_util.install_data_managers( trans.app,
- trans.app.config.shed_data_manager_config_file,
- metadata_dict,
- shed_config_dict,
- relative_install_dir,
- tool_shed_repository,
- repository_tools_tups )
- if 'datatypes' in metadata_dict:
- tool_shed_repository.status = trans.model.ToolShedRepository.installation_status.LOADING_PROPRIETARY_DATATYPES
- if not tool_shed_repository.includes_datatypes:
- tool_shed_repository.includes_datatypes = True
- trans.sa_session.add( tool_shed_repository )
- trans.sa_session.flush()
- files_dir = relative_install_dir
- if shed_config_dict.get( 'tool_path' ):
- files_dir = os.path.join( shed_config_dict['tool_path'], files_dir )
- datatypes_config = suc.get_config_from_disk( 'datatypes_conf.xml', files_dir )
- # Load data types required by tools.
- converter_path, display_path = datatype_util.alter_config_and_load_prorietary_datatypes( trans.app, datatypes_config, files_dir, override=False )
- if converter_path or display_path:
- # Create a dictionary of tool shed repository related information.
- repository_dict = datatype_util.create_repository_dict_for_proprietary_datatypes( tool_shed=tool_shed,
- name=tool_shed_repository.name,
- owner=tool_shed_repository.owner,
- installed_changeset_revision=tool_shed_repository.installed_changeset_revision,
- tool_dicts=metadata_dict.get( 'tools', [] ),
- converter_path=converter_path,
- display_path=display_path )
- if converter_path:
- # Load proprietary datatype converters
- trans.app.datatypes_registry.load_datatype_converters( trans.app.toolbox, installed_repository_dict=repository_dict )
- if display_path:
- # Load proprietary datatype display applications
- trans.app.datatypes_registry.load_display_applications( installed_repository_dict=repository_dict )
-
@web.expose
@web.require_admin
def import_workflow( self, trans, workflow_name, repository_id, **kwd ):
@@ -605,96 +536,21 @@
"""Install specified tool shed repositories."""
shed_tool_conf = kwd.get( 'shed_tool_conf', '' )
tool_path = kwd[ 'tool_path' ]
- includes_tool_dependencies = util.string_as_bool( kwd[ 'includes_tool_dependencies' ] )
install_tool_dependencies = CheckboxField.is_checked( kwd.get( 'install_tool_dependencies', '' ) )
- # There must be a one-to-one mapping between items in the 3 lists:tool_shed_repositories, tool_panel_section_keys, repo_info_dicts.
+ # There must be a one-to-one mapping between items in the 3 lists: tool_shed_repositories, tool_panel_section_keys, repo_info_dicts.
tool_panel_section_keys = util.listify( kwd[ 'tool_panel_section_keys' ] )
repo_info_dicts = util.listify( kwd[ 'repo_info_dicts' ] )
for index, tool_shed_repository in enumerate( tool_shed_repositories ):
repo_info_dict = repo_info_dicts[ index ]
tool_panel_section_key = tool_panel_section_keys[ index ]
- if tool_panel_section_key:
- tool_section = trans.app.toolbox.tool_panel[ tool_panel_section_key ]
- else:
- tool_section = None
- if isinstance( repo_info_dict, basestring ):
- repo_info_dict = encoding_util.tool_shed_decode( repo_info_dict )
- # Clone each repository to the configured location.
- suc.update_tool_shed_repository_status( trans.app, tool_shed_repository, trans.model.ToolShedRepository.installation_status.CLONING )
- repo_info_tuple = repo_info_dict[ tool_shed_repository.name ]
- description, repository_clone_url, changeset_revision, ctx_rev, repository_owner, repository_dependencies, tool_dependencies = repo_info_tuple
- relative_clone_dir = suc.generate_tool_shed_repository_install_dir( repository_clone_url, tool_shed_repository.installed_changeset_revision )
- clone_dir = os.path.join( tool_path, relative_clone_dir )
- relative_install_dir = os.path.join( relative_clone_dir, tool_shed_repository.name )
- install_dir = os.path.join( tool_path, relative_install_dir )
- cloned_ok, error_message = suc.clone_repository( repository_clone_url, os.path.abspath( install_dir ), ctx_rev )
- if cloned_ok:
- if reinstalling:
- # Since we're reinstalling the repository we need to find the latest changeset revision to which is can be updated.
- changeset_revision_dict = repository_util.get_update_to_changeset_revision_and_ctx_rev( trans, tool_shed_repository )
- current_changeset_revision = changeset_revision_dict.get( 'changeset_revision', None )
- current_ctx_rev = changeset_revision_dict.get( 'ctx_rev', None )
- if current_ctx_rev != ctx_rev:
- repo = hg.repository( suc.get_configured_ui(), path=os.path.abspath( install_dir ) )
- repository_util.pull_repository( repo, repository_clone_url, current_changeset_revision )
- suc.update_repository( repo, ctx_rev=current_ctx_rev )
- self.handle_repository_contents( trans,
- tool_shed_repository=tool_shed_repository,
- tool_path=tool_path,
- repository_clone_url=repository_clone_url,
- relative_install_dir=relative_install_dir,
- tool_shed=tool_shed_repository.tool_shed,
- tool_section=tool_section,
- shed_tool_conf=shed_tool_conf,
- reinstalling=reinstalling )
- trans.sa_session.refresh( tool_shed_repository )
- metadata = tool_shed_repository.metadata
- if 'tools' in metadata:
- # Get the tool_versions from the tool shed for each tool in the installed change set.
- suc.update_tool_shed_repository_status( trans.app,
- tool_shed_repository,
- trans.model.ToolShedRepository.installation_status.SETTING_TOOL_VERSIONS )
- tool_shed_url = suc.get_url_from_tool_shed( trans.app, tool_shed_repository.tool_shed )
- url = suc.url_join( tool_shed_url,
- '/repository/get_tool_versions?name=%s&owner=%s&changeset_revision=%s' % \
- ( tool_shed_repository.name, tool_shed_repository.owner, tool_shed_repository.changeset_revision ) )
- response = urllib2.urlopen( url )
- text = response.read()
- response.close()
- if text:
- tool_version_dicts = json.from_json_string( text )
- tool_util.handle_tool_versions( trans.app, tool_version_dicts, tool_shed_repository )
- else:
- message += "Version information for the tools included in the <b>%s</b> repository is missing. " % name
- message += "Reset all of this repository's metadata in the tool shed, then set the installed tool versions "
- message += "from the installed repository's <b>Repository Actions</b> menu. "
- status = 'error'
- if install_tool_dependencies and tool_shed_repository.tool_dependencies and 'tool_dependencies' in metadata:
- work_dir = tempfile.mkdtemp()
- # Install tool dependencies.
- suc.update_tool_shed_repository_status( trans.app,
- tool_shed_repository,
- trans.model.ToolShedRepository.installation_status.INSTALLING_TOOL_DEPENDENCIES )
- # Get the tool_dependencies.xml file from the repository.
- tool_dependencies_config = suc.get_config_from_disk( 'tool_dependencies.xml', install_dir )#relative_install_dir )
- installed_tool_dependencies = common_install_util.handle_tool_dependencies( app=trans.app,
- tool_shed_repository=tool_shed_repository,
- tool_dependencies_config=tool_dependencies_config,
- tool_dependencies=tool_shed_repository.tool_dependencies )
- try:
- shutil.rmtree( work_dir )
- except:
- pass
- suc.update_tool_shed_repository_status( trans.app, tool_shed_repository, trans.model.ToolShedRepository.installation_status.INSTALLED )
- else:
- # An error occurred while cloning the repository, so reset everything necessary to enable another attempt.
- self.set_repository_attributes( trans,
- tool_shed_repository,
- status=trans.model.ToolShedRepository.installation_status.ERROR,
- error_message=error_message,
- deleted=False,
- uninstalled=False,
- remove_from_disk=True )
+ repository_util.install_tool_shed_repository( trans,
+ tool_shed_repository,
+ repo_info_dict,
+ tool_panel_section_key,
+ shed_tool_conf,
+ tool_path,
+ install_tool_dependencies,
+ reinstalling=reinstalling )
tsr_ids_for_monitoring = [ trans.security.encode_id( tsr.id ) for tsr in tool_shed_repositories ]
return trans.response.send_redirect( web.url_for( controller='admin_toolshed',
action='monitor_repository_installation',
@@ -929,7 +785,7 @@
@web.expose
@web.require_admin
def prepare_for_install( self, trans, **kwd ):
- if not have_shed_tool_conf_for_install( trans ):
+ if not suc.have_shed_tool_conf_for_install( trans ):
message = 'The <b>tool_config_file</b> setting in <b>universe_wsgi.ini</b> must include at least one shed tool configuration file name with a '
message += '<b><toolbox></b> tag that includes a <b>tool_path</b> attribute value which is a directory relative to the Galaxy installation '
message += 'directory in order to automatically install tools from a Galaxy tool shed (e.g., the file name <b>shed_tool_conf.xml</b> whose '
@@ -956,7 +812,7 @@
install_tool_dependencies = kwd.get( 'install_tool_dependencies', '' )
encoded_repo_info_dicts = util.listify( kwd.get( 'encoded_repo_info_dicts', None ) )
if not encoded_repo_info_dicts:
- # The request originated in the tool shed.
+ # The request originated in the tool shed via a tool search.
repository_ids = kwd.get( 'repository_ids', None )
changeset_revisions = kwd.get( 'changeset_revisions', None )
# Get the information necessary to install each repository.
@@ -981,78 +837,40 @@
else:
install_tool_dependencies = False
tool_path = suc.get_tool_path_by_shed_tool_conf_filename( trans, shed_tool_conf )
+ installation_dict = dict( install_repository_dependencies=install_repository_dependencies,
+ new_tool_panel_section=new_tool_panel_section,
+ no_changes_checked=False,
+ reinstalling=False,
+ repo_info_dicts=repo_info_dicts,
+ tool_panel_section=tool_panel_section,
+ tool_path=tool_path,
+ tool_shed_url=tool_shed_url )
created_or_updated_tool_shed_repositories, tool_panel_section_keys, repo_info_dicts, filtered_repo_info_dicts, message = \
- repository_dependency_util.create_repository_dependency_objects( trans,
- tool_path,
- tool_shed_url,
- repo_info_dicts,
- reinstalling=False,
- install_repository_dependencies=install_repository_dependencies,
- no_changes_checked=False,
- tool_panel_section=tool_panel_section,
- new_tool_panel_section=new_tool_panel_section )
+ repository_util.handle_tool_shed_repositories( trans, installation_dict, using_api=False )
if message and len( repo_info_dicts ) == 1:
- installed_tool_shed_repository = created_or_updated_tool_shed_repositories[ 0 ]
- message+= 'Click <a href="%s">here</a> to manage the repository. ' % \
- ( web.url_for( controller='admin_toolshed', action='manage_repository', id=trans.security.encode_id( installed_tool_shed_repository.id ) ) )
return trans.response.send_redirect( web.url_for( controller='admin_toolshed',
action='browse_repositories',
message=message,
status='error' ) )
+
if created_or_updated_tool_shed_repositories:
- # Handle contained tools.
- if includes_tools_for_display_in_tool_panel and ( new_tool_panel_section or tool_panel_section ):
- if new_tool_panel_section:
- section_id = new_tool_panel_section.lower().replace( ' ', '_' )
- tool_panel_section_key = 'section_%s' % str( section_id )
- if tool_panel_section_key in trans.app.toolbox.tool_panel:
- # Appending a tool to an existing section in trans.app.toolbox.tool_panel
- log.debug( "Appending to tool panel section: %s" % new_tool_panel_section )
- tool_section = trans.app.toolbox.tool_panel[ tool_panel_section_key ]
- else:
- # Appending a new section to trans.app.toolbox.tool_panel
- log.debug( "Loading new tool panel section: %s" % new_tool_panel_section )
- elem = Element( 'section' )
- elem.attrib[ 'name' ] = new_tool_panel_section
- elem.attrib[ 'id' ] = section_id
- elem.attrib[ 'version' ] = ''
- tool_section = tools.ToolSection( elem )
- trans.app.toolbox.tool_panel[ tool_panel_section_key ] = tool_section
- else:
- tool_panel_section_key = 'section_%s' % tool_panel_section
- tool_section = trans.app.toolbox.tool_panel[ tool_panel_section_key ]
- else:
- tool_panel_section_key = None
- tool_section = None
- encoded_repository_ids = [ trans.security.encode_id( tsr.id ) for tsr in created_or_updated_tool_shed_repositories ]
- # Create a one-to-one mapping of tool shed repository id and tool panel section key. All tools contained in the repositories
- # being installed will be loaded into the same section in the tool panel.
- for tsr in created_or_updated_tool_shed_repositories:
- tool_panel_section_keys.append( tool_panel_section_key )
- new_kwd = dict( includes_tools=includes_tools,
- includes_tools_for_display_in_tool_panel=includes_tools_for_display_in_tool_panel,
- has_repository_dependencies=has_repository_dependencies,
- install_repository_dependencies=install_repository_dependencies,
- includes_tool_dependencies=includes_tool_dependencies,
- install_tool_dependencies=install_tool_dependencies,
- message=message,
- repo_info_dicts=filtered_repo_info_dicts,
- shed_tool_conf=shed_tool_conf,
- status=status,
- tool_path=tool_path,
- tool_panel_section_keys=tool_panel_section_keys,
- tool_shed_repository_ids=encoded_repository_ids,
- tool_shed_url=tool_shed_url )
- encoded_kwd = encoding_util.tool_shed_encode( new_kwd )
- tsr_ids = [ r.id for r in created_or_updated_tool_shed_repositories ]
- tool_shed_repositories = []
- for tsr_id in tsr_ids:
- tsr = trans.sa_session.query( trans.model.ToolShedRepository ).get( tsr_id )
- tool_shed_repositories.append( tsr )
- clause_list = []
- for tsr_id in tsr_ids:
- clause_list.append( trans.model.ToolShedRepository.table.c.id == tsr_id )
- query = trans.sa_session.query( trans.model.ToolShedRepository ).filter( or_( *clause_list ) )
+ installation_dict = dict( created_or_updated_tool_shed_repositories=created_or_updated_tool_shed_repositories,
+ filtered_repo_info_dicts=filtered_repo_info_dicts,
+ has_repository_dependencies=has_repository_dependencies,
+ includes_tool_dependencies=includes_tool_dependencies,
+ includes_tools=includes_tools,
+ includes_tools_for_display_in_tool_panel=includes_tools_for_display_in_tool_panel,
+ install_repository_dependencies=install_repository_dependencies,
+ install_tool_dependencies=install_tool_dependencies,
+ message=message,
+ new_tool_panel_section=new_tool_panel_section,
+ shed_tool_conf=shed_tool_conf,
+ status=status,
+ tool_panel_section=tool_panel_section,
+ tool_panel_section_keys=tool_panel_section_keys,
+ tool_path=tool_path,
+ tool_shed_url=tool_shed_url )
+ encoded_kwd, query, tool_shed_repositories, encoded_repository_ids = repository_util.initiate_repository_installation( trans, installation_dict )
return trans.fill_template( 'admin/tool_shed_repository/initiate_repository_installation.mako',
encoded_kwd=encoded_kwd,
query=query,
@@ -1065,9 +883,9 @@
return trans.response.send_redirect( web.url_for( controller='admin_toolshed',
action='manage_repositories',
**kwd ) )
- shed_tool_conf_select_field = build_shed_tool_conf_select_field( trans )
+ shed_tool_conf_select_field = tool_util.build_shed_tool_conf_select_field( trans )
tool_path = suc.get_tool_path_by_shed_tool_conf_filename( trans, shed_tool_conf )
- tool_panel_section_select_field = build_tool_panel_section_select_field( trans )
+ tool_panel_section_select_field = tool_util.build_tool_panel_section_select_field( trans )
if len( repo_info_dicts ) == 1:
# If we're installing a single repository, see if it contains a readme or dependencies that we can display.
repo_info_dict = repo_info_dicts[ 0 ]
@@ -1401,7 +1219,7 @@
original_section_name = ''
else:
original_section_name = ''
- tool_panel_section_select_field = build_tool_panel_section_select_field( trans )
+ tool_panel_section_select_field = tool_util.build_tool_panel_section_select_field( trans )
no_changes_check_box = CheckboxField( 'no_changes', checked=True )
if original_section_name:
message += "The tools contained in your <b>%s</b> repository were last loaded into the tool panel section <b>%s</b>. " \
@@ -1417,7 +1235,7 @@
no_changes_check_box = None
original_section_name = ''
tool_panel_section_select_field = None
- shed_tool_conf_select_field = build_shed_tool_conf_select_field( trans )
+ shed_tool_conf_select_field = tool_util.build_shed_tool_conf_select_field( trans )
containers_dict = repository_util.populate_containers_dict_for_new_install( trans=trans,
tool_shed_url=tool_shed_url,
tool_path=tool_path,
@@ -1521,13 +1339,13 @@
"""An error occurred while cloning the repository, so reset everything necessary to enable another attempt."""
repository = suc.get_installed_tool_shed_repository( trans, kwd[ 'id' ] )
if kwd.get( 'reset_repository', False ):
- self.set_repository_attributes( trans,
- repository,
- status=trans.model.ToolShedRepository.installation_status.NEW,
- error_message=None,
- deleted=False,
- uninstalled=False,
- remove_from_disk=True )
+ suc.set_repository_attributes( trans,
+ repository,
+ status=trans.model.ToolShedRepository.installation_status.NEW,
+ error_message=None,
+ deleted=False,
+ uninstalled=False,
+ remove_from_disk=True )
new_kwd = {}
new_kwd[ 'message' ] = "You can now attempt to install the repository named <b>%s</b> again." % repository.name
new_kwd[ 'status' ] = "done"
@@ -1538,20 +1356,6 @@
action='manage_repository',
**kwd ) )
- def set_repository_attributes( self, trans, repository, status, error_message, deleted, uninstalled, remove_from_disk=False ):
- if remove_from_disk:
- relative_install_dir = repository.repo_path( trans.app )
- if relative_install_dir:
- clone_dir = os.path.abspath( relative_install_dir )
- shutil.rmtree( clone_dir )
- log.debug( "Removed repository installation directory: %s" % str( clone_dir ) )
- repository.error_message = error_message
- repository.status = status
- repository.deleted = deleted
- repository.uninstalled = uninstalled
- trans.sa_session.add( repository )
- trans.sa_session.flush()
-
@web.expose
@web.require_admin
def set_tool_versions( self, trans, **kwd ):
@@ -1803,46 +1607,3 @@
metadata=metadata,
message=message,
status=status )
-
-## ---- Utility methods -------------------------------------------------------
-
-def build_shed_tool_conf_select_field( trans ):
- """Build a SelectField whose options are the keys in trans.app.toolbox.shed_tool_confs."""
- options = []
- for shed_tool_conf_dict in trans.app.toolbox.shed_tool_confs:
- shed_tool_conf_filename = shed_tool_conf_dict[ 'config_filename' ]
- if shed_tool_conf_filename != trans.app.config.migrated_tools_config:
- if shed_tool_conf_filename.startswith( './' ):
- option_label = shed_tool_conf_filename.replace( './', '', 1 )
- else:
- option_label = shed_tool_conf_filename
- options.append( ( option_label, shed_tool_conf_filename ) )
- select_field = SelectField( name='shed_tool_conf' )
- for option_tup in options:
- select_field.add_option( option_tup[0], option_tup[1] )
- return select_field
-
-def build_tool_panel_section_select_field( trans ):
- """Build a SelectField whose options are the sections of the current in-memory toolbox."""
- options = []
- for k, v in trans.app.toolbox.tool_panel.items():
- if isinstance( v, tools.ToolSection ):
- options.append( ( v.name, v.id ) )
- select_field = SelectField( name='tool_panel_section', display='radio' )
- for option_tup in options:
- select_field.add_option( option_tup[0], option_tup[1] )
- return select_field
-
-def can_select_tool_panel_section():
- pass
-
-def have_shed_tool_conf_for_install( trans ):
- if not trans.app.toolbox.shed_tool_confs:
- return False
- migrated_tools_conf_path, migrated_tools_conf_name = os.path.split( trans.app.config.migrated_tools_config )
- for shed_tool_conf_dict in trans.app.toolbox.shed_tool_confs:
- shed_tool_conf = shed_tool_conf_dict[ 'config_filename' ]
- shed_tool_conf_path, shed_tool_conf_name = os.path.split( shed_tool_conf )
- if shed_tool_conf_name != migrated_tools_conf_name:
- return True
- return False
diff -r 18eea1b2c803ba307cea5a0f30850ff62d7d4d86 -r 60947fb5b3d3c62417facc65f9e42eb930dded73 lib/galaxy/webapps/galaxy/controllers/biostar.py
--- a/lib/galaxy/webapps/galaxy/controllers/biostar.py
+++ b/lib/galaxy/webapps/galaxy/controllers/biostar.py
@@ -8,26 +8,52 @@
from galaxy.util import json
import hmac
+# Slugifying from Armin Ronacher (http://flask.pocoo.org/snippets/5/)
+
+import re
+from unicodedata import normalize
+
+_punct_re = re.compile(r'[\t !"#$%&\'()*\-/<=>?(a)\[\\\]^_`{|},.]+')
+
+
+def slugify(text, delim=u'-'):
+ """Generates an slightly worse ASCII-only slug."""
+ result = []
+ for word in _punct_re.split(text.lower()):
+ word = normalize('NFKD', word).encode('ascii', 'ignore')
+ if word:
+ result.append(word)
+ return unicode(delim.join(result))
+
+
# Biostar requires all keys to be present, so we start with a template
DEFAULT_PAYLOAD = {
- 'email': "",
- 'title': "Question about Galaxy",
+ 'email': "",
+ 'title': "Question about Galaxy",
'tags': 'galaxy',
- 'tool_name': '',
- 'tool_version': '',
+ 'tool_name': '',
+ 'tool_version': '',
'tool_id': ''
}
+
def encode_data( key, data ):
"""
Encode data to send a question to Biostar
"""
- text = json.dumps(data)
+ text = json.to_json_string(data)
text = base64.urlsafe_b64encode(text)
digest = hmac.new(key, text).hexdigest()
return text, digest
+def tag_for_tool( tool ):
+ """
+ Generate a reasonavle biostar tag for a tool.
+ """
+ return slugify( unicode( tool.name ) )
+
+
class BiostarController( BaseUIController ):
"""
Provides integration with Biostar through external authentication, see: http://liondb.com/help/x/
@@ -81,6 +107,10 @@
if not tool:
return error( "No tool found matching '%s'" % tool_id )
# Tool specific information for payload
- payload = { 'title': "Question about Galaxy tool '%s'" % tool.name, 'tool_name': tool.name, 'tool_version': tool.version, 'tool_id': tool.id }
+ payload = { 'title': "Question about Galaxy tool '%s'" % tool.name,
+ 'tool_name': tool.name,
+ 'tool_version': tool.version,
+ 'tool_id': tool.id,
+ 'tags': 'galaxy ' + tag_for_tool( tool ) }
# Pass on to regular question method
return self.biostar_question_redirect( trans, payload )
\ No newline at end of file
diff -r 18eea1b2c803ba307cea5a0f30850ff62d7d4d86 -r 60947fb5b3d3c62417facc65f9e42eb930dded73 lib/galaxy/webapps/tool_shed/api/repositories.py
--- a/lib/galaxy/webapps/tool_shed/api/repositories.py
+++ b/lib/galaxy/webapps/tool_shed/api/repositories.py
@@ -1,20 +1,42 @@
import logging
+from galaxy.web.framework.helpers import time_ago
+from galaxy import web
+from galaxy import util
+from galaxy.web.base.controller import BaseAPIController
import tool_shed.util.shed_util_common as suc
-from galaxy import web, util
-from galaxy.web.base.controller import BaseAPIController
+from tool_shed.galaxy_install import repository_util
+
+from galaxy import eggs
+import pkg_resources
+
+pkg_resources.require( 'mercurial' )
+from mercurial import hg, ui, commands
log = logging.getLogger( __name__ )
+def default_repository_value_mapper( trans, repository ):
+ value_mapper={ 'id' : trans.security.encode_id( repository.id ),
+ 'user_id' : trans.security.encode_id( repository.user_id ) }
+ return value_mapper
+
+def default_repository_metadata_value_mapper( trans, repository_metadata ):
+ value_mapper = { 'id' : trans.security.encode_id( repository_metadata.id ),
+ 'repository_id' : trans.security.encode_id( repository_metadata.repository_id ) }
+ if repository_metadata.time_last_tested:
+ value_mapper[ 'time_last_tested' ] = time_ago( repository_metadata.time_last_tested )
+ return value_mapper
+
class RepositoriesController( BaseAPIController ):
"""RESTful controller for interactions with repositories in the Tool Shed."""
- @web.expose_api
+ @web.expose_api_anonymous
def index( self, trans, deleted=False, **kwd ):
"""
GET /api/repositories
Displays a collection (list) of repositories.
"""
+ # Example URL: http://localhost:9009/api/repositories
repository_dicts = []
deleted = util.string_as_bool( deleted )
try:
@@ -23,12 +45,10 @@
.order_by( trans.app.model.Repository.table.c.name ) \
.all()
for repository in query:
- value_mapper={ 'id' : trans.security.encode_id( repository.id ),
- 'user_id' : trans.security.encode_id( repository.user_id ) }
- repository_dict = repository.get_api_value( view='collection', value_mapper=value_mapper )
- repository_dict[ 'url' ] = web.url_for( controller='repository_contents',
- action='index',
- repository_id=trans.security.encode_id( repository.id ) )
+ repository_dict = repository.get_api_value( view='collection', value_mapper=default_repository_value_mapper( trans, repository ) )
+ repository_dict[ 'url' ] = web.url_for( controller='repositories',
+ action='show',
+ id=trans.security.encode_id( repository.id ) )
repository_dicts.append( repository_dict )
return repository_dicts
except Exception, e:
@@ -37,25 +57,117 @@
trans.response.status = 500
return message
- @web.expose_api
+ @web.expose_api_anonymous
def show( self, trans, id, **kwd ):
"""
GET /api/repositories/{encoded_repository_id}
- Displays information about a repository in the Tool Shed.
+ Returns information about a repository in the Tool Shed.
- :param id: the encoded id of the `Repository` object
+ :param id: the encoded id of the Repository object
"""
+ # Example URL: http://localhost:9009/api/repositories/f9cad7b01a472135
try:
repository = suc.get_repository_in_tool_shed( trans, id )
- value_mapper={ 'id' : trans.security.encode_id( repository.id ),
- 'user_id' : trans.security.encode_id( repository.user_id ) }
- repository_dict = repository.get_api_value( view='element', value_mapper=value_mapper )
- repository_dict[ 'url' ] = web.url_for( controller='repository_contents',
- action='index',
- repository_id=trans.security.encode_id( repository.id ) )
+ repository_dict = repository.get_api_value( view='element', value_mapper=default_repository_value_mapper( trans, repository ) )
+ repository_dict[ 'url' ] = web.url_for( controller='repositories',
+ action='show',
+ id=trans.security.encode_id( repository.id ) )
return repository_dict
except Exception, e:
message = "Error in the Tool Shed repositories API in show: %s" % str( e )
log.error( message, exc_info=True )
trans.response.status = 500
return message
+
+ @web.expose_api_anonymous
+ def get_repository_revision_install_info( self, trans, name, owner, changeset_revision, **kwd ):
+ """
+ GET /api/repository/get_repository_revision_install_info
+
+ :param name: the name of the Repository
+ :param owner: the owner of the Repository
+ :param changset_revision: the changset_revision of the RepositoryMetadata object associated with the Repository
+
+ Returns a list of the following dictionaries::
+ - a dictionary defining the Repository. For example:
+ {
+ "deleted": false,
+ "deprecated": false,
+ "description": "add_column hello",
+ "id": "f9cad7b01a472135",
+ "long_description": "add_column hello",
+ "name": "add_column",
+ "owner": "test",
+ "private": false,
+ "times_downloaded": 6,
+ "url": "/api/repositories/f9cad7b01a472135",
+ "user_id": "f9cad7b01a472135"
+ }
+ - a dictionary defining the Repsoitory revision (RepositoryMetadata). For example:
+ {
+ "changeset_revision": "3a08cc21466f",
+ "downloadable": true,
+ "has_repository_dependencies": false,
+ "id": "f9cad7b01a472135",
+ "includes_datatypes": false,
+ "includes_tool_dependencies": false,
+ "includes_tools": true,
+ "includes_tools_for_display_in_tool_panel": true,
+ "includes_workflows": false,
+ "malicious": false,
+ "repository_id": "f9cad7b01a472135",
+ "url": "/api/repository_revisions/f9cad7b01a472135"
+ }
+ - a dictionary including the additional information required to install the repository. For example:
+ {
+ "add_column": [
+ "add_column hello",
+ "http://test@localhost:9009/repos/test/add_column",
+ "3a08cc21466f",
+ "1",
+ "test",
+ {},
+ {}
+ ]
+ }
+ """
+ # Example URL: http://localhost:9009/api/repositories/get_repository_revision_install_info…
+ try:
+ # Get the repository information.
+ repository = suc.get_repository_by_name_and_owner( trans.app, name, owner )
+ encoded_repository_id = trans.security.encode_id( repository.id )
+ repository_dict = repository.get_api_value( view='element', value_mapper=default_repository_value_mapper( trans, repository ) )
+ repository_dict[ 'url' ] = web.url_for( controller='repositories',
+ action='show',
+ id=encoded_repository_id )
+ # Get the repository_metadata information.
+ repository_metadata = suc.get_repository_metadata_by_changeset_revision( trans, encoded_repository_id, changeset_revision )
+ if not repository_metadata:
+ # The changeset_revision column in the repository_metadata table has been updated with a new value value, so find the
+ # changeset_revision to which we need to update.
+ repo_dir = repository.repo_path( trans.app )
+ repo = hg.repository( suc.get_configured_ui(), repo_dir )
+ new_changeset_revision = suc.get_next_downloadable_changeset_revision( repository, repo, changeset_revision )
+ repository_metadata = suc.get_repository_metadata_by_changeset_revision( trans, encoded_repository_id, new_changeset_revision )
+ changeset_revision = new_changeset_revision
+ if repository_metadata:
+ encoded_repository_metadata_id = trans.security.encode_id( repository_metadata.id )
+ repository_metadata_dict = repository_metadata.get_api_value( view='collection',
+ value_mapper=default_repository_metadata_value_mapper( trans, repository_metadata ) )
+ repository_metadata_dict[ 'url' ] = web.url_for( controller='repository_revisions',
+ action='show',
+ id=encoded_repository_metadata_id )
+ # Get the repo_info_dict for installing the repository.
+ repo_info_dict, includes_tools, includes_tool_dependencies, includes_tools_for_display_in_tool_panel, has_repository_dependencies = \
+ repository_util.get_repo_info_dict( trans, encoded_repository_id, changeset_revision )
+ return repository_dict, repository_metadata_dict, repo_info_dict
+ else:
+ message = "Unable to locate repository_metadata record for repository id %d and changeset_revision %s" % ( repository.id, changeset_revision )
+ log.error( message, exc_info=True )
+ trans.response.status = 500
+ return repository_dict, {}, {}
+ except Exception, e:
+ message = "Error in the Tool Shed repositories API in get_repository_revision_install_info: %s" % str( e )
+ log.error( message, exc_info=True )
+ trans.response.status = 500
+ return message
diff -r 18eea1b2c803ba307cea5a0f30850ff62d7d4d86 -r 60947fb5b3d3c62417facc65f9e42eb930dded73 lib/galaxy/webapps/tool_shed/api/repository_contents.py
--- a/lib/galaxy/webapps/tool_shed/api/repository_contents.py
+++ /dev/null
@@ -1,33 +0,0 @@
-import logging
-import tool_shed.util.shed_util_common as suc
-from galaxy import web
-from galaxy.web.base.controller import BaseAPIController
-
-log = logging.getLogger( __name__ )
-
-
-class RepositoryContentsController( BaseAPIController ):
-
- @web.expose_api
- def index( self, trans, **kwd ):
- """
- GET /api/repositories/{encoded_repository_id}
- Displays a collection (dictionary) of repository contents.
-
- :param repository_id: the encoded id of the `Repository` object
- """
- try:
- repository_id = kwd[ 'repository_id' ]
- repository = suc.get_repository_in_tool_shed( trans, repository_id )
- value_mapper={ 'id' : trans.security.encode_id( repository.id ),
- 'user_id' : trans.security.encode_id( repository.user_id ) }
- repository_dict = repository.as_dict( value_mapper )
- repository_dict[ 'url' ] = web.url_for( controller='repository_contents',
- action='index',
- repository_id=repository_id )
- return repository_dict
- except Exception, e:
- message = "Error in the Tool Shed repository_contents API in index: %s" % str( e )
- log.error( message, exc_info=True )
- trans.response.status = 500
- return message
diff -r 18eea1b2c803ba307cea5a0f30850ff62d7d4d86 -r 60947fb5b3d3c62417facc65f9e42eb930dded73 lib/galaxy/webapps/tool_shed/api/repository_revision_contents.py
--- a/lib/galaxy/webapps/tool_shed/api/repository_revision_contents.py
+++ /dev/null
@@ -1,39 +0,0 @@
-import logging
-from galaxy import web
-from galaxy.web.framework.helpers import time_ago
-from tool_shed.util import metadata_util
-from galaxy.web.base.controller import BaseAPIController
-
-log = logging.getLogger( __name__ )
-
-def default_value_mapper( trans, repository_metadata ):
- value_mapper = { 'id' : trans.security.encode_id( repository_metadata.id ),
- 'repository_id' : trans.security.encode_id( repository_metadata.repository_id ) }
- if repository_metadata.time_last_tested:
- value_mapper[ 'time_last_tested' ] = time_ago( repository_metadata.time_last_tested )
- return value_mapper
-
-
-class RepositoryRevisionContentsController( BaseAPIController ):
-
- @web.expose_api
- def index( self, trans, **kwd ):
- """
- GET /api/repository_revisions/{encoded_repository_metadata_id}
- Displays a collection (dictionary) of repository_metadata contents.
-
- :param repository_metadata_id: the encoded id of the `RepositoryMetadata` object
- """
- try:
- repository_metadata_id = kwd.get( 'repository_metadata_id', None )
- repository_metadata = metadata_util.get_repository_metadata_by_id( trans, repository_metadata_id )
- repository_dict = repository_metadata.as_dict( value_mapper=default_value_mapper( trans, repository_metadata ) )
- repository_dict[ 'url' ] = web.url_for( controller='repository_revision_contents',
- action='index',
- repository_metadata_id=repository_metadata_id )
- return repository_dict
- except Exception, e:
- message = "Error in the Tool Shed repository_revision_contents API in index: %s" % str( e )
- log.error( message, exc_info=True )
- trans.response.status = 500
- return message
diff -r 18eea1b2c803ba307cea5a0f30850ff62d7d4d86 -r 60947fb5b3d3c62417facc65f9e42eb930dded73 lib/galaxy/webapps/tool_shed/api/repository_revisions.py
--- a/lib/galaxy/webapps/tool_shed/api/repository_revisions.py
+++ b/lib/galaxy/webapps/tool_shed/api/repository_revisions.py
@@ -1,7 +1,9 @@
-import datetime, logging
+import datetime
+import logging
from galaxy.web.framework.helpers import time_ago
from tool_shed.util import metadata_util
-from galaxy import web, util
+from galaxy import web
+from galaxy import util
from galaxy.model.orm import and_
from galaxy.web.base.controller import BaseAPIController
@@ -24,6 +26,7 @@
GET /api/repository_revisions
Displays a collection (list) of repository revisions.
"""
+ # Example URL: http://localhost:9009/api/repository_revisions
repository_metadata_dicts = []
# Build up an anded clause list of filters.
clause_list = []
@@ -55,9 +58,9 @@
for repository_metadata in query:
repository_metadata_dict = repository_metadata.get_api_value( view='collection',
value_mapper=default_value_mapper( trans, repository_metadata ) )
- repository_metadata_dict[ 'url' ] = web.url_for( controller='repository_revision_contents',
- action='index',
- repository_metadata_id=trans.security.encode_id( repository_metadata.id ) )
+ repository_metadata_dict[ 'url' ] = web.url_for( controller='repository_revisions',
+ action='show',
+ id=trans.security.encode_id( repository_metadata.id ) )
repository_metadata_dicts.append( repository_metadata_dict )
return repository_metadata_dicts
except Exception, e:
@@ -74,12 +77,13 @@
:param id: the encoded id of the `RepositoryMetadata` object
"""
+ # Example URL: http://localhost:9009/api/repository_revisions/bb125606ff9ea620
try:
repository_metadata = metadata_util.get_repository_metadata_by_id( trans, id )
repository_metadata_dict = repository_metadata.as_dict( value_mapper=default_value_mapper( trans, repository_metadata ) )
- repository_metadata_dict[ 'url' ] = web.url_for( controller='repository_revision_contents',
- action='index',
- repository_metadata_id=trans.security.encode_id( repository_metadata.id ) )
+ repository_metadata_dict[ 'url' ] = web.url_for( controller='repository_revisions',
+ action='show',
+ id=trans.security.encode_id( repository_metadata.id ) )
return repository_metadata_dict
except Exception, e:
message = "Error in the Tool Shed repository_revisions API in show: %s" % str( e )
@@ -114,7 +118,7 @@
trans.response.status = 500
return message
repository_metadata_dict = repository_metadata.as_dict( value_mapper=default_value_mapper( trans, repository_metadata ) )
- repository_metadata_dict[ 'url' ] = web.url_for( controller='repository_revision_contents',
- action='index',
- repository_metadata_id=trans.security.encode_id( repository_metadata.id ) )
+ repository_metadata_dict[ 'url' ] = web.url_for( controller='repository_revisions',
+ action='show',
+ id=trans.security.encode_id( repository_metadata.id ) )
return repository_metadata_dict
diff -r 18eea1b2c803ba307cea5a0f30850ff62d7d4d86 -r 60947fb5b3d3c62417facc65f9e42eb930dded73 lib/galaxy/webapps/tool_shed/buildapp.py
--- a/lib/galaxy/webapps/tool_shed/buildapp.py
+++ b/lib/galaxy/webapps/tool_shed/buildapp.py
@@ -1,8 +1,11 @@
"""
Provides factory methods to assemble the Galaxy web application
"""
-
-import logging, atexit, os, os.path, sys, config
+import atexit
+import config
+import logging
+import os
+import sys
from inspect import isclass
@@ -69,22 +72,21 @@
webapp.add_route( '/:controller/:action', action='index' )
webapp.add_route( '/:action', controller='repository', action='index' )
webapp.add_route( '/repos/*path_info', controller='hg', action='handle_request', path_info='/' )
- # Add the web API.
+ # Add the web API. # A good resource for RESTful services - http://routes.readthedocs.org/en/latest/restful.html
webapp.add_api_controllers( 'galaxy.webapps.tool_shed.api', app )
- webapp.api_mapper.resource( 'content',
- 'contents',
- controller='repository_contents',
+ webapp.api_mapper.resource( 'repository',
+ 'repositories',
+ controller='repositories',
+ collection={ 'get_repository_revision_install_info' : 'GET' },
name_prefix='repository_',
- path_prefix='/api/repositories/:repository_id',
+ path_prefix='/api',
parent_resources=dict( member_name='repository', collection_name='repositories' ) )
- webapp.api_mapper.resource( 'content',
- 'contents',
- controller='repository_revision_contents',
+ webapp.api_mapper.resource( 'repository_revision',
+ 'repository_revisions',
+ controller='repository_revisions',
name_prefix='repository_revision_',
- path_prefix='/api/repository_revisions/:repository_metadata_id',
+ path_prefix='/api',
parent_resources=dict( member_name='repository_revision', collection_name='repository_revisions' ) )
- webapp.api_mapper.resource( 'repository', 'repositories', path_prefix='/api' )
- webapp.api_mapper.resource( 'repository_revision', 'repository_revisions', path_prefix='/api' )
webapp.finalize_config()
# Wrap the webapp in some useful middleware
if kwargs.get( 'middleware', True ):
diff -r 18eea1b2c803ba307cea5a0f30850ff62d7d4d86 -r 60947fb5b3d3c62417facc65f9e42eb930dded73 lib/galaxy/webapps/tool_shed/controllers/repository.py
--- a/lib/galaxy/webapps/tool_shed/controllers/repository.py
+++ b/lib/galaxy/webapps/tool_shed/controllers/repository.py
@@ -1,26 +1,47 @@
-import os, logging, re, tempfile, ConfigParser, string
-from time import gmtime, strftime
+import ConfigParser
+import logging
+import os
+import re
+import string
+import tempfile
+from time import gmtime
+from time import strftime
from datetime import date, datetime
-from galaxy import util, web
+from galaxy import util
+from galaxy import web
from galaxy.util.odict import odict
from galaxy.web.base.controller import BaseUIController
-from galaxy.web.form_builder import CheckboxField, build_select_field
+from galaxy.web.form_builder import CheckboxField
+from galaxy.web.form_builder import build_select_field
from galaxy.webapps.tool_shed import model
from galaxy.webapps.tool_shed.model import directory_hash_id
from galaxy.web.framework.helpers import grids
from galaxy.util import json
-from galaxy.model.orm import and_, or_
+from galaxy.model.orm import and_
+from galaxy.model.orm import or_
import tool_shed.util.shed_util_common as suc
-from tool_shed.util import encoding_util, metadata_util, readme_util, repository_dependency_util, review_util, tool_dependency_util, tool_util, workflow_util
+from tool_shed.util import encoding_util
+from tool_shed.util import metadata_util
+from tool_shed.util import readme_util
+from tool_shed.util import repository_dependency_util
+from tool_shed.util import review_util
+from tool_shed.util import tool_dependency_util
+from tool_shed.util import tool_util
+from tool_shed.util import workflow_util
from tool_shed.galaxy_install import repository_util
-from galaxy.webapps.tool_shed.util import common_util, container_util
+from galaxy.webapps.tool_shed.util import common_util
+from galaxy.webapps.tool_shed.util import container_util
import galaxy.tools
import tool_shed.grids.repository_grids as repository_grids
import tool_shed.grids.util as grids_util
from galaxy import eggs
eggs.require('mercurial')
-from mercurial import hg, ui, patch, commands
+
+from mercurial import commands
+from mercurial import hg
+from mercurial import patch
+from mercurial import ui
log = logging.getLogger( __name__ )
@@ -1124,35 +1145,17 @@
includes_tool_dependencies = False
repo_info_dicts = []
for tup in zip( util.listify( repository_ids ), util.listify( changeset_revisions ) ):
- repository_id, changeset_revision = tup
- repository = suc.get_repository_in_tool_shed( trans, repository_id )
- repository_clone_url = suc.generate_clone_url_for_repository_in_tool_shed( trans, repository )
- repository_metadata = suc.get_repository_metadata_by_changeset_revision( trans, repository_id, changeset_revision )
- metadata = repository_metadata.metadata
- if not includes_tools:
- if 'tools' in metadata:
- includes_tools = True
- if not includes_tools_for_display_in_tool_panel:
- includes_tools_for_display_in_tool_panel = repository_metadata.includes_tools_for_display_in_tool_panel
- if not has_repository_dependencies:
- if 'repository_dependencies' in metadata:
- has_repository_dependencies = True
- if not includes_tool_dependencies:
- if 'tool_dependencies' in metadata:
- includes_tool_dependencies = True
- repo_dir = repository.repo_path( trans.app )
- repo = hg.repository( suc.get_configured_ui(), repo_dir )
- ctx = suc.get_changectx_for_changeset( repo, changeset_revision )
- repo_info_dict = repository_util.create_repo_info_dict( trans=trans,
- repository_clone_url=repository_clone_url,
- changeset_revision=changeset_revision,
- ctx_rev=str( ctx.rev() ),
- repository_owner=repository.user.username,
- repository_name=repository.name,
- repository=repository,
- repository_metadata=repository_metadata,
- tool_dependencies=None,
- repository_dependencies=None )
+ repository_id, changeset_revision = tup
+ repo_info_dict, cur_includes_tools, cur_includes_tool_dependencies, cur_includes_tools_for_display_in_tool_panel, cur_has_repository_dependencies = \
+ repository_util.get_repo_info_dict( trans, repository_id, changeset_revision )
+ if cur_has_repository_dependencies and not has_repository_dependencies:
+ has_repository_dependencies = True
+ if cur_includes_tools and not includes_tools:
+ includes_tools = True
+ if cur_includes_tool_dependencies and not includes_tool_dependencies:
+ includes_tool_dependencies = True
+ if cur_includes_tools_for_display_in_tool_panel and not includes_tools_for_display_in_tool_panel:
+ includes_tools_for_display_in_tool_panel = True
repo_info_dicts.append( encoding_util.tool_shed_encode( repo_info_dict ) )
return dict( includes_tools=includes_tools,
includes_tools_for_display_in_tool_panel=includes_tools_for_display_in_tool_panel,
diff -r 18eea1b2c803ba307cea5a0f30850ff62d7d4d86 -r 60947fb5b3d3c62417facc65f9e42eb930dded73 lib/galaxy/webapps/tool_shed/framework/middleware/hg.py
--- a/lib/galaxy/webapps/tool_shed/framework/middleware/hg.py
+++ b/lib/galaxy/webapps/tool_shed/framework/middleware/hg.py
@@ -4,7 +4,8 @@
import os, logging
import sqlalchemy
from paste.auth.basic import AuthBasicAuthenticator
-from paste.httpheaders import REMOTE_USER, AUTH_TYPE
+from paste.httpheaders import AUTH_TYPE
+from paste.httpheaders import REMOTE_USER
from galaxy.webapps.tool_shed import model
from galaxy.util.hash_util import new_secure_hash
@@ -12,13 +13,15 @@
log = logging.getLogger(__name__)
+
class Hg( object ):
+
def __init__( self, app, config ):
print "mercurial version is:", mercurial.__version__.version
self.app = app
self.config = config
# Authenticate this mercurial request using basic authentication
- self.authentication = AuthBasicAuthenticator( '', self.__basic_authentication )
+ self.authentication = AuthBasicAuthenticator( 'hgweb in the tool shed', self.__basic_authentication )
self.remote_address = None
self.repository = None
self.username = None
@@ -28,6 +31,7 @@
self.db_url = self.config[ 'database_connection' ]
else:
self.db_url = "sqlite:///%s?isolation_level=IMMEDIATE" % self.config[ 'database_file' ]
+
def __call__( self, environ, start_response ):
cmd = self.__get_hg_command( **environ )
if cmd == 'changegroup':
@@ -89,16 +93,23 @@
else:
return result.wsgi_application( environ, start_response )
return self.app( environ, start_response )
+
def __get_hg_command( self, **kwd ):
- # Pulls mercurial commands from environ[ 'QUERY_STRING" ] and returns them.
+ """Pulls mercurial commands from environ[ 'QUERY_STRING" ] and returns them."""
if 'QUERY_STRING' in kwd:
for qry in kwd[ 'QUERY_STRING' ].split( '&' ):
if qry.startswith( 'cmd' ):
return qry.split( '=' )[ -1 ]
return None
+
def __basic_authentication( self, environ, username, password ):
- # The environ parameter is needed in basic authentication.
- return self.__authenticate( username, password )
+ """The environ parameter is needed in basic authentication. We also check it if use_remote_user is true."""
+ if asbool( self.config.get( 'use_remote_user', False ) ):
+ assert "HTTP_REMOTE_USER" in environ, "use_remote_user is set but no HTTP_REMOTE_USER variable"
+ return self.__authenticate_remote_user( environ, username, password )
+ else:
+ return self.__authenticate( username, password )
+
def __authenticate( self, username, password ):
# Instantiate a database connection
engine = sqlalchemy.create_engine( self.db_url )
@@ -111,3 +122,26 @@
connection.close()
# Check if password matches db_password when hashed.
return new_secure_hash( text_type=password ) == db_password
+
+ def __authenticate_remote_user( self, environ, username, password ):
+ """
+ Look after a remote user and "authenticate" - upstream server should already have achieved this for us, but we check that the
+ user exists at least. Hg allow_push = must include username - some versions of mercurial blow up with 500 errors.
+ """
+ ru_email = environ[ 'HTTP_REMOTE_USER' ].lower()
+ ## Instantiate a database connection...
+ engine = sqlalchemy.create_engine( self.db_url )
+ connection = engine.connect()
+ result_set = connection.execute( "select email, username, password from galaxy_user where email = '%s'" % ru_email )
+ for row in result_set:
+ # Should only be 1 row...
+ db_email = row[ 'email' ]
+ db_password = row[ 'password' ]
+ db_username = row[ 'username' ]
+ connection.close()
+
+ """
+ We could check the password here except that the function galaxy.web.framework.get_or_create_remote_user() does some random generation of
+ a password - so that no-one knows the password and only the hash is stored...
+ """
+ return db_username == username
diff -r 18eea1b2c803ba307cea5a0f30850ff62d7d4d86 -r 60947fb5b3d3c62417facc65f9e42eb930dded73 lib/galaxy/webapps/tool_shed/model/__init__.py
--- a/lib/galaxy/webapps/tool_shed/model/__init__.py
+++ b/lib/galaxy/webapps/tool_shed/model/__init__.py
@@ -192,10 +192,10 @@
class RepositoryMetadata( object, APIItem ):
api_collection_visible_keys = ( 'id', 'repository_id', 'changeset_revision', 'malicious', 'downloadable', 'has_repository_dependencies', 'includes_datatypes',
- 'includes_tools', 'includes_tool_dependencies', 'includes_workflows' )
+ 'includes_tools', 'includes_tool_dependencies', 'includes_tools_for_display_in_tool_panel', 'includes_workflows' )
api_element_visible_keys = ( 'id', 'repository_id', 'changeset_revision', 'malicious', 'downloadable', 'tools_functionally_correct',
'do_not_test', 'time_last_tested', 'tool_test_errors', 'has_repository_dependencies', 'includes_datatypes', 'includes_tools',
- 'includes_tool_dependencies', 'includes_workflows' )
+ 'includes_tool_dependencies', 'includes_tools_for_display_in_tool_panel', 'includes_workflows' )
def __init__( self, id=None, repository_id=None, changeset_revision=None, metadata=None, tool_versions=None, malicious=False, downloadable=False,
tools_functionally_correct=False, do_not_test=False, time_last_tested=None, tool_test_errors=None, has_repository_dependencies=False,
includes_datatypes=False, includes_tools=False, includes_tool_dependencies=False, includes_workflows=False ):
This diff is so big that we needed to truncate the remainder.
https://bitbucket.org/galaxy/galaxy-central/commits/cdda54441004/
Changeset: cdda54441004
Branch: next-stable
User: Galaxy
Date: 2013-03-27 21:39:12
Summary: merge
Affected #: 1 file
diff -r 60947fb5b3d3c62417facc65f9e42eb930dded73 -r cdda54441004e7c84b0a3de41c51c879f962288d lib/galaxy/web/base/controller.py
--- a/lib/galaxy/web/base/controller.py
+++ b/lib/galaxy/web/base/controller.py
@@ -360,15 +360,16 @@
if meta_files:
hda_dict[ 'meta_files' ] = meta_files
- hda_dict[ 'display_apps' ] = self.get_display_apps( trans, hda )
hda_dict[ 'display_types' ] = self.get_old_display_applications( trans, hda )
+ #hda_dict[ 'display_apps' ] = self.get_display_apps( trans, hda )
hda_dict[ 'visualizations' ] = hda.get_visualizations()
# return here if deleted
if hda.deleted and not purged:
return trans.security.encode_dict_ids( hda_dict )
- if hda.creating_job and hda.creating_job.tool_id:
+ if( ( hda.state in [ 'running', 'queued' ] )
+ and ( hda.creating_job and hda.creating_job.tool_id ) ):
tool_used = trans.app.toolbox.get_tool( hda.creating_job.tool_id )
if tool_used and tool_used.force_history_refresh:
hda_dict[ 'force_history_refresh' ] = True
@@ -382,6 +383,7 @@
def get_display_app_url( display_app_link, hda, trans ):
web_url_for = routes.URLGenerator( trans.webapp.mapper, trans.environ )
dataset_hash, user_hash = da_util.encode_dataset_user( trans, hda, None )
+ return ''
return web_url_for( controller='dataset',
action="display_application",
dataset_id=dataset_hash,
https://bitbucket.org/galaxy/galaxy-central/commits/10cab33d22bd/
Changeset: 10cab33d22bd
Branch: next-stable
User: Galaxy
Date: 2013-03-27 21:43:08
Summary: remove .hgflow
Affected #: 1 file
diff -r cdda54441004e7c84b0a3de41c51c879f962288d -r 10cab33d22bd57e3286605e6b4b9b2331ef1f50b .hgflow
--- a/.hgflow
+++ /dev/null
@@ -1,8 +0,0 @@
-[Basic]
-develop = next-stable
-feature = feature/
-version_tag =
-publish = default
-release = release/
-hotfix = hotfix/
-
https://bitbucket.org/galaxy/galaxy-central/commits/97b5685eb8c5/
Changeset: 97b5685eb8c5
Branch: feature/transact-with-ts
User: Galaxy
Date: 2013-03-27 21:44:19
Summary: hg flow, add branch `feature/transact-with-ts`.
Affected #: 0 files
Diff not available.
https://bitbucket.org/galaxy/galaxy-central/commits/c15778e0f6e0/
Changeset: c15778e0f6e0
Branch: feature/transact-with-ts
User: Galaxy
Date: 2013-04-10 03:59:45
Summary: augment to allow for usernames and passwords in config with two additional functions for access
Affected #: 1 file
Diff not available.
https://bitbucket.org/galaxy/galaxy-central/commits/b8d46d9fdfef/
Changeset: b8d46d9fdfef
Branch: feature/transact-with-ts
User: Galaxy
Date: 2013-04-10 07:26:42
Summary: and now a way to talk to the tool shed
Affected #: 1 file
Diff not available.
https://bitbucket.org/galaxy/galaxy-central/commits/c16e6b233a2a/
Changeset: c16e6b233a2a
Branch: feature/transact-with-ts
User: Galaxy
Date: 2013-04-10 12:11:02
Summary: unified urllib2 access to tool shed
Affected #: 1 file
Diff not available.
https://bitbucket.org/galaxy/galaxy-central/commits/2621b01c2f8a/
Changeset: 2621b01c2f8a
Branch: feature/transact-with-ts
User: Galaxy
Date: 2013-04-10 12:14:08
Summary: remove transact_with_tool_shed in favour of tool_shed_get in common_utils
Affected #: 1 file
Diff not available.
https://bitbucket.org/galaxy/galaxy-central/commits/b24775f48b6e/
Changeset: b24775f48b6e
Branch: feature/transact-with-ts
User: Galaxy
Date: 2013-04-10 12:16:14
Summary: switch from urllib2 everywhere to common_util.tool_shed_get (external authd tool shed)
Affected #: 13 files
Diff not available.
https://bitbucket.org/galaxy/galaxy-central/commits/9e5e6d90a759/
Changeset: 9e5e6d90a759
Branch: feature/transact-with-ts
User: Galaxy
Date: 2013-04-10 12:31:07
Summary: coflict resolve?
Affected #: 1 file
Diff not available.
https://bitbucket.org/galaxy/galaxy-central/commits/a97feef9773f/
Changeset: a97feef9773f
Branch: feature/transact-with-ts
User: Galaxy
Date: 2013-04-10 13:11:41
Summary: merged in default - conflict resolve in metadata_util.py
Affected #: 224 files
Diff not available.
https://bitbucket.org/galaxy/galaxy-central/commits/33dc0df2837d/
Changeset: 33dc0df2837d
Branch: feature/transact-with-ts
User: kiwiroy
Date: 2013-04-10 23:59:30
Summary: Merged default into feature/transact-with-ts
Affected #: 17 files
Diff not available.
https://bitbucket.org/galaxy/galaxy-central/commits/b9bd0fae39ca/
Changeset: b9bd0fae39ca
User: greg
Date: 2013-04-16 19:15:50
Summary: Merged in kiwiroy/galaxy-central/feature/transact-with-ts (pull request #155)
Support for Toolsheds with external auth enabled
Affected #: 16 files
Diff not available.
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
2 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/190162796dee/
Changeset: 190162796dee
Branch: tool-shed-api
User: dan
Date: 2013-04-16 17:47:29
Summary: Close tool-shed-api branch.
Affected #: 0 files
https://bitbucket.org/galaxy/galaxy-central/commits/f03acd2cc3b4/
Changeset: f03acd2cc3b4
Branch: single-file-download
User: dan
Date: 2013-04-16 17:47:44
Summary: Close single-file-download branch.
Affected #: 0 files
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: Handle invalid tool panel section keys when installing tool shed repositories that contain tools to be displayed in the Galaxy tool panel.
by commits-noreply@bitbucket.org 16 Apr '13
by commits-noreply@bitbucket.org 16 Apr '13
16 Apr '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/3a073074d40e/
Changeset: 3a073074d40e
User: greg
Date: 2013-04-16 17:22:23
Summary: Handle invalid tool panel section keys when installing tool shed repositories that contain tools to be displayed in the Galaxy tool panel.
Affected #: 1 file
diff -r 49ca2f03569e75de83c87e8a43166732236d3d7a -r 3a073074d40ed9e40f09660be8d8afb562f041c8 lib/tool_shed/galaxy_install/repository_util.py
--- a/lib/tool_shed/galaxy_install/repository_util.py
+++ b/lib/tool_shed/galaxy_install/repository_util.py
@@ -354,7 +354,11 @@
def install_tool_shed_repository( trans, tool_shed_repository, repo_info_dict, tool_panel_section_key, shed_tool_conf, tool_path, install_tool_dependencies,
reinstalling=False ):
if tool_panel_section_key:
- tool_section = trans.app.toolbox.tool_panel[ tool_panel_section_key ]
+ try:
+ tool_section = trans.app.toolbox.tool_panel[ tool_panel_section_key ]
+ except KeyError:
+ log.debug( 'Invalid tool_panel_section_key "%s" specified. Tools will be loaded outside of sections in the tool panel.' )
+ tool_section = None
else:
tool_section = None
if isinstance( repo_info_dict, basestring ):
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
16 Apr '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/49ca2f03569e/
Changeset: 49ca2f03569e
User: greg
Date: 2013-04-16 16:38:58
Summary: White space changes.
Affected #: 1 file
diff -r e54bbcffc6d7b6918b4a65e6855460e235b44b83 -r 49ca2f03569e75de83c87e8a43166732236d3d7a scripts/api/install_repository_tools.py
--- a/scripts/api/install_repository_tools.py
+++ b/scripts/api/install_repository_tools.py
@@ -10,7 +10,7 @@
</section>
Here is a working example of how to use this script to install a repository from the test tool shed.
-./install_repository_tools.py -- api <api key> --local <galaxy base url> --url http://testtoolshed.g2.bx.psu.edu --name gregs_filter --owner greg --revision f28d5018f9cb --tool-deps
+./install_repository_tools.py --api <api key> --local <galaxy base url> --url http://testtoolshed.g2.bx.psu.edu --name gregs_filter --owner greg --revision f28d5018f9cb --tool-deps
"""
import os
@@ -19,11 +19,8 @@
sys.path.insert( 0, os.path.dirname( __file__ ) )
from common import submit
-
def main( options ):
- """
- collect all user data and install the tools via the Galaxy API
- """
+ """Collect all user data and install the tools via the Galaxy API."""
data = {}
data[ 'tool_shed_url' ] = options.tool_shed_url
data[ 'name' ] = options.name
@@ -32,63 +29,24 @@
if options.tool_panel_section_id:
data[ 'tool_panel_section_id' ] = options.tool_panel_section_id
elif options.new_tool_panel_section_label:
- data['new_tool_panel_section_label'] = options.new_tool_panel_section_label
+ data[ 'new_tool_panel_section_label' ] = options.new_tool_panel_section_label
if options.install_repository_dependencies:
data[ 'install_repository_dependencies' ] = options.install_repository_dependencies
if options.install_tool_dependencies:
data[ 'install_tool_dependencies' ] = options.install_tool_dependencies
-
- submit( options.api, '%s%s' % (options.local_url, '/api/tool_shed_repositories/new/install_repository_revision'), data )
-
+ submit( options.api, '%s%s' % ( options.local_url, '/api/tool_shed_repositories/new/install_repository_revision' ), data )
if __name__ == '__main__':
- parser = argparse.ArgumentParser(description='Installation of tools via the Galaxy API.')
-
- parser.add_argument("-u", "--url", dest="tool_shed_url",
- required=True,
- help="Tool Shed URL")
-
- parser.add_argument("-a", "--api", dest="api",
- required=True,
- help="API Key")
-
- parser.add_argument("-l", "--local", dest="local_url",
- required=True,
- help="URL of the galaxy instance.")
-
- parser.add_argument("-n", "--name",
- required=True,
- help="Repository name.")
-
- parser.add_argument("-o", "--owner",
- required=True,
- help="Repository owner.")
-
- parser.add_argument("-r", "--revision", dest="changeset_revision",
- required=True,
- help="Repository owner.")
-
- parser.add_argument("--panel-section-id", dest="tool_panel_section_id",
- help="Tool panel section id if you want to add your repo to an existing tool section.")
-
- parser.add_argument("--panel-section-name", dest="new_tool_panel_section_label",
- help="New tool panel section label. If specified a new tool section will be created.")
-
- parser.add_argument("--repository-deps", dest="install_repository_dependencies", action="store_true",
- default=False,
- help="Install repository dependencies. [False]")
-
- parser.add_argument("--tool-deps", dest="install_tool_dependencies", action="store_true",
- default=False,
- help="Install tool dependencies. [False]")
-
-
+ parser = argparse.ArgumentParser( description='Installation of tool shed repositories via the Galaxy API.' )
+ parser.add_argument( "-u", "--url", dest="tool_shed_url", required=True, help="Tool Shed URL" )
+ parser.add_argument( "-a", "--api", dest="api", required=True, help="API Key" )
+ parser.add_argument( "-l", "--local", dest="local_url", required=True, help="URL of the galaxy instance." )
+ parser.add_argument( "-n", "--name", required=True, help="Repository name." )
+ parser.add_argument( "-o", "--owner", required=True, help="Repository owner." )
+ parser.add_argument( "-r", "--revision", dest="changeset_revision", required=True, help="Repository owner." )
+ parser.add_argument( "--panel-section-id", dest="tool_panel_section_id", help="Tool panel section id if you want to add your repository to an existing tool section." )
+ parser.add_argument( "--panel-section-name", dest="new_tool_panel_section_label", help="New tool panel section label. If specified a new tool section will be created." )
+ parser.add_argument( "--repository-deps", dest="install_repository_dependencies", action="store_true", default=False, help="Install repository dependencies. [False]")
+ parser.add_argument( "--tool-deps", dest="install_tool_dependencies", action="store_true", default=False, help="Install tool dependencies. [False]" )
options = parser.parse_args()
main( options )
-
-
-
-
-
-
-
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