galaxy-commits
Threads by month
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
January 2012
- 1 participants
- 95 discussions
24 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/1d0bb560bd3d/
changeset: 1d0bb560bd3d
user: ichorny
date: 2011-10-21 23:01:48
summary: add actual user changes to galaxy-central
affected #: 14 files
diff -r 070513d25b63110ef6569a9b09101864009f2ba4 -r 1d0bb560bd3d584708972001afd054774e9e89c5 lib/galaxy/jobs/__init__.py
--- a/lib/galaxy/jobs/__init__.py
+++ b/lib/galaxy/jobs/__init__.py
@@ -10,7 +10,7 @@
from galaxy.util.json import from_json_string
from galaxy.util.expressions import ExpressionContext
from galaxy.jobs.actions.post import ActionBox
-
+import subprocess, pwd
from sqlalchemy.sql.expression import and_, or_
import pkg_resources
@@ -362,6 +362,9 @@
self.sa_session.expunge_all() #this prevents the metadata reverting that has been seen in conjunction with the PBS job runner
if not os.path.exists( self.working_directory ):
os.mkdir( self.working_directory )
+ if self.app.config.drmaa_external_runjob_script:
+ os.chmod(self.working_directory , 0777)
+
# Restore parameters from the database
job = self.get_job()
if job.user is None and job.galaxy_session is None:
@@ -695,6 +698,16 @@
# fix permissions
for path in [ dp.real_path for dp in self.get_output_fnames() ]:
+ #change the ownership of the files in file_path directory back to galaxy user
+ if self.app.config.drmaa_external_runjob_script and self.app.config.external_chown_script:
+ galaxy_user_name = pwd.getpwuid(os.getuid())[0]
+ galaxy_group_id = str(pwd.getpwuid(os.getuid())[3])
+ p = subprocess.Popen([ '/usr/bin/sudo', '-E', self.app.config.external_chown_script, path,galaxy_user_name,galaxy_group_id], shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ (stdoutdata, stderrdata) = p.communicate()
+ exitcode = p.returncode
+ if exitcode != 0:
+ ## There was an error in the child process
+ raise RuntimeError("External_chown_script failed (exit code %s) with error %s" % (str(exitcode), stderrdata))
util.umask_fix_perms( path, self.app.config.umask, 0666, self.app.config.gid )
self.sa_session.flush()
log.debug( 'job %d ended' % self.job_id )
@@ -765,7 +778,7 @@
jeha_false_path = None
if self.app.config.outputs_to_working_directory:
self.output_paths = []
- self.output_dataset_paths = {}
+ output_dataset_paths = {}
for name, data in [ ( da.name, da.dataset.dataset ) for da in job.output_datasets + job.output_library_datasets ]:
false_path = os.path.abspath( os.path.join( self.working_directory, "galaxy_dataset_%d.dat" % data.id ) )
dsp = DatasetPath( data.id, data.file_name, false_path )
@@ -895,7 +908,7 @@
else:
self.prepare_input_files_cmds = None
self.status = task.states.NEW
-
+
def get_job( self ):
if self.job_id:
return self.sa_session.query( model.Job ).get( self.job_id )
@@ -1123,7 +1136,7 @@
def __get_runner_name( self, job_wrapper ):
if self.app.config.use_tasked_jobs and job_wrapper.tool.parallelism is not None and not isinstance(job_wrapper, TaskWrapper):
- runnner_name = "tasks"
+ runner_name = "tasks"
else:
runner_name = ( job_wrapper.get_job_runner().split(":", 1) )[0]
return runner_name
diff -r 070513d25b63110ef6569a9b09101864009f2ba4 -r 1d0bb560bd3d584708972001afd054774e9e89c5 lib/galaxy/jobs/runners/drmaa.py
--- a/lib/galaxy/jobs/runners/drmaa.py
+++ b/lib/galaxy/jobs/runners/drmaa.py
@@ -1,4 +1,10 @@
import os, sys, logging, threading, time
+import pprint, pwd
+from pwd import getpwnam
+import subprocess
+import inspect
+import simplejson as json
+
from Queue import Queue, Empty
from galaxy import model
@@ -8,6 +14,7 @@
import pkg_resources
+
if sys.version_info[:2] == ( 2, 4 ):
pkg_resources.require( "ctypes" )
pkg_resources.require( "drmaa" )
@@ -42,9 +49,23 @@
fi
export PYTHONPATH
fi
+%s
cd %s
%s
+%s
+%s
+%s
"""
+def __lineno__():
+ """Returns the current line number in our program."""
+ return inspect.currentframe().f_back.f_lineno
+
+def __filename__():
+ """Returns the current filename in our program."""
+ return inspect.currentframe().f_back.f_code.co_filename
+
+DRMAA_jobTemplate_attributes = [ 'args', 'remoteCommand', 'outputPath', 'errorPath', 'nativeSpecification',
+ 'name','email','project' ]
class DRMAAJobState( object ):
def __init__( self ):
@@ -90,6 +111,10 @@
worker.start()
self.work_threads.append( worker )
log.debug( "%d workers ready" % nworkers )
+ # external_runJob_script can be None, in which case it's not used.
+ self.external_runJob_script = app.config.drmaa_external_runjob_script
+ self.external_killJob_script = app.config.drmaa_external_killjob_script
+ self.TMPDIR = app.config.TMPDIR
def get_native_spec( self, url ):
"""Get any native DRM arguments specified by the site configuration"""
@@ -118,7 +143,6 @@
def queue_job( self, job_wrapper ):
"""Create job script and submit it to the DRM"""
-
try:
job_wrapper.prepare()
command_line = self.build_command_line( job_wrapper, include_metadata=True )
@@ -128,7 +152,7 @@
return
runner_url = job_wrapper.get_job_runner()
-
+
# This is silly, why would we queue a job with no command line?
if not command_line:
job_wrapper.finish( '', '' )
@@ -144,8 +168,8 @@
job_wrapper.change_state( model.Job.states.QUEUED )
# define job attributes
- ofile = "%s/%s.o" % (self.app.config.cluster_files_directory, job_wrapper.job_id)
- efile = "%s/%s.e" % (self.app.config.cluster_files_directory, job_wrapper.job_id)
+ ofile = "%s/%s.o" % (self.app.config.cluster_files_directory, job_wrapper.get_id_tag())
+ efile = "%s/%s.e" % (self.app.config.cluster_files_directory, job_wrapper.get_id_tag())
jt = self.ds.createJobTemplate()
jt.remoteCommand = "%s/database/pbs/galaxy_%s.sh" % (os.getcwd(), job_wrapper.get_id_tag())
jt.outputPath = ":%s" % ofile
@@ -153,17 +177,31 @@
native_spec = self.get_native_spec( runner_url )
if native_spec is not None:
jt.nativeSpecification = native_spec
+ #set and export galaxy user PATH enviroment to actual user if submitting jobs as actual user
+ try:
+ if self.external_runJob_script:
+ export_path = 'export PATH=%s:$PATH' %(os.environ['PATH'])
+ else:
+ export_path = ''
+ except:
+ export_path = ''
+
+ if self.TMPDIR:
+ export_tmp = 'export TMPDIR=%s' %self.TMPDIR
+ else:
+ export_tmp = ''
- script = drm_template % (job_wrapper.galaxy_lib_dir, os.path.abspath( job_wrapper.working_directory ), command_line)
- try:
- fh = file( jt.remoteCommand, "w" )
- fh.write( script )
- fh.close()
- os.chmod( jt.remoteCommand, 0750 )
- except:
- job_wrapper.fail( "failure preparing job script", exception=True )
- log.exception("failure running job %s" % job_wrapper.get_id_tag())
- return
+ if self.external_runJob_script == None:
+ script = drm_template % (job_wrapper.galaxy_lib_dir, export_path, os.path.abspath( job_wrapper.working_directory ),export_tmp, command_line,'','')
+ else:
+ touchcmd = 'touch ' + os.path.abspath( job_wrapper.working_directory ) + '/just_in_cases.txt'
+ chmodcmd = 'chmod -Rf a+rwx ' + os.path.abspath( job_wrapper.working_directory ) + '/*'
+ script = drm_template % (job_wrapper.galaxy_lib_dir, export_path, os.path.abspath( job_wrapper.working_directory ), export_tmp, command_line, touchcmd,chmodcmd)
+
+ fh = file( jt.remoteCommand, "w" )
+ fh.write( script )
+ fh.close()
+ os.chmod( jt.remoteCommand, 0755 )
# job was deleted while we were preparing it
if job_wrapper.get_state() == model.Job.states.DELETED:
@@ -178,7 +216,12 @@
log.debug("(%s) submitting file %s" % ( galaxy_id_tag, jt.remoteCommand ) )
log.debug("(%s) command is: %s" % ( galaxy_id_tag, command_line ) )
# runJob will raise if there's a submit problem
- job_id = self.ds.runJob(jt)
+ if self.external_runJob_script is None:
+ job_id = self.ds.runJob(jt)
+ else:
+ userid = self.get_qsub_user(job_wrapper)
+ filename = self.store_jobtemplate(job_wrapper, jt)
+ job_id = self.external_runjob(filename, userid)
log.info("(%s) queued as %s" % ( galaxy_id_tag, job_id ) )
# store runner information for tracking if Galaxy restarts
@@ -272,15 +315,23 @@
efile = drm_job_state.efile
job_file = drm_job_state.job_file
# collect the output
- try:
- ofh = file(ofile, "r")
- efh = file(efile, "r")
- stdout = ofh.read( 32768 )
- stderr = efh.read( 32768 )
- except:
- stdout = ''
- stderr = 'Job output not returned from cluster'
- log.debug(stderr)
+ # JED - HACK to wait for the files to appear
+ which_try = 0
+ while which_try < 60:
+ try:
+ ofh = file(ofile, "r")
+ efh = file(efile, "r")
+ stdout = ofh.read( 32768 )
+ stderr = efh.read( 32768 )
+ which_try = 60
+ except:
+ if which_try == 60:
+ stdout = ''
+ stderr = 'Job output not returned from cluster'
+ log.debug(stderr)
+ else:
+ which_try += 1
+ time.sleep(1)
try:
drm_job_state.job_wrapper.finish( stdout, stderr )
@@ -320,13 +371,20 @@
def stop_job( self, job ):
"""Attempts to delete a job from the DRM queue"""
- try:
- self.ds.control( job.job_runner_external_id, drmaa.JobControlAction.TERMINATE )
- log.debug( "(%s/%s) Removed from DRM queue at user's request" % ( job.id, job.job_runner_external_id ) )
- except drmaa.InvalidJobException:
- log.debug( "(%s/%s) User killed running job, but it was already dead" % ( job.id, job.job_runner_external_id ) )
- except Exception, e:
- log.debug( "(%s/%s) User killed running job, but error encountered removing from DRM queue: %s" % ( job.id, job.job_runner_external_id, e ) )
+ if self.external_killJob_script is None:
+ try:
+ self.ds.control( job.job_runner_external_id, drmaa.JobControlAction.TERMINATE )
+ log.debug( "(%s/%s) Removed from DRM queue at user's request" % ( job.id, job.job_runner_external_id ) )
+ except drmaa.InvalidJobException:
+ log.debug( "(%s/%s) User killed running job, but it was already dead" % ( job.id, job.job_runner_external_id ) )
+ except Exception, e:
+ log.debug( "(%s/%s) User killed running job, but error encountered removing from DRM queue: %s" % ( job.id, job.job_runner_external_id, e ) )
+ else:
+ try:
+ subprocess.Popen(['/usr/bin/sudo','-E', self.external_killJob_script, str(job.job_runner_external_id), str(self.job_user_uid[2])],shell=False)
+ log.debug( "(%s/%s) Removed from DRM queue at user's request" % ( job.id, job.job_runner_external_id ) )
+ except Exception, e:
+ log.debug( "(%s/%s) User killed running job, but error encountered removing from DRM queue: %s" % ( job.id, job.job_runner_external_id, e ) )
def recover( self, job, job_wrapper ):
"""Recovers jobs stuck in the queued/running state when Galaxy started"""
@@ -348,3 +406,52 @@
drm_job_state.old_state = drmaa.JobState.QUEUED_ACTIVE
drm_job_state.running = False
self.monitor_queue.put( drm_job_state )
+
+ def get_qsub_user(self, job_wrapper):
+ """ Returns the UserID (or Username) that should be used to execute the job. """
+ #TODO:
+ #add some logic to decide on an SGE user for the given job.
+ job_user_name = job_wrapper.user.split('@')
+ self.job_user_uid = getpwnam(job_user_name[0])
+ log.debug (" (%s) is the uid being passed to the DRM queu\n" % ( self.job_user_uid[2]) )
+ return self.job_user_uid[2]
+
+ def store_jobtemplate(self, job_wrapper, jt):
+ """ Stores the content of a DRMAA JobTemplate object in a file as a JSON string.
+ Path is hard-coded, but it's no worse than other path in this module.
+ Uses Galaxy's JobID, so file is expected to be unique."""
+ filename = "%s/database/pbs/%s.jt_json" % (os.getcwd(), job_wrapper.get_id_tag())
+ data = {}
+ for attr in DRMAA_jobTemplate_attributes:
+ try:
+ data[attr] = getattr(jt, attr)
+ except:
+ pass
+ s = json.dumps(data);
+ f = open(filename,'w')
+ f.write(s)
+ f.close()
+ return filename
+
+ def external_runjob(self, jobtemplate_filename, username):
+ """ runs an external script the will QSUB a new job.
+ The external script will be run with sudo, and will setuid() to the specified user.
+ Effectively, will QSUB as a different user (then the one used by Galaxy).
+ """
+ p = subprocess.Popen([ '/usr/bin/sudo', '-E', self.external_runJob_script, str(username), jobtemplate_filename ],
+ shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ (stdoutdata, stderrdata) = p.communicate()
+ exitcode = p.returncode
+ #os.unlink(jobtemplate_filename)
+ if exitcode != 0:
+ # There was an error in the child process
+ raise RuntimeError("External_runjob failed (exit code %s)\nCalled from %s:%d\nChild process reported error:\n%s" % (str(exitcode), __filename__(), __lineno__(), stderrdata))
+ if not stdoutdata.strip():
+ raise RuntimeError("External_runjob did return the job id: %s" % (stdoutdata))
+
+ # The expected output is a single line containing a single numeric value:
+ # the DRMAA job-ID. If not the case, will throw an error.
+ jobId = stdoutdata
+ return jobId;
+
+
diff -r 070513d25b63110ef6569a9b09101864009f2ba4 -r 1d0bb560bd3d584708972001afd054774e9e89c5 lib/galaxy/jobs/splitters/multi.py
--- a/lib/galaxy/jobs/splitters/multi.py
+++ b/lib/galaxy/jobs/splitters/multi.py
@@ -33,6 +33,7 @@
subdir_index[0] = subdir_index[0] + 1
if not os.path.exists(dir):
os.makedirs(dir)
+ os.chmod(dir,0777)
task_dirs.append(dir)
return dir
diff -r 070513d25b63110ef6569a9b09101864009f2ba4 -r 1d0bb560bd3d584708972001afd054774e9e89c5 lib/galaxy/model/__init__.py
--- a/lib/galaxy/model/__init__.py
+++ b/lib/galaxy/model/__init__.py
@@ -480,6 +480,23 @@
rval = galaxy.datatypes.data.nice_size( rval )
return rval
+ def get_api_value( self, view='collection', value_mapper = None ):
+ if value_mapper is None:
+ value_mapper = {}
+ rval = {}
+ try:
+ visible_keys = self.__getattribute__( 'api_' + view + '_visible_keys' )
+ except AttributeError:
+ raise Exception( 'Unknown API view: %s' % view )
+ for key in visible_keys:
+ try:
+ rval[key] = self.__getattribute__( key )
+ if key in value_mapper:
+ rval[key] = value_mapper.get( key )( rval[key] )
+ except AttributeError:
+ rval[key] = None
+ return rval
+
class HistoryUserShareAssociation( object ):
def __init__( self ):
self.history = None
@@ -632,7 +649,7 @@
permitted_actions = get_permitted_actions( filter='DATASET' )
file_path = "/tmp/"
engine = None
- def __init__( self, id=None, state=None, external_filename=None, extra_files_path=None, file_size=None, purgable=True ):
+ def __init__( self, id=None, state=None, external_filename=None, extra_files_path=None, file_size=None, purgable=True):
self.id = id
self.state = state
self.deleted = False
@@ -653,6 +670,7 @@
# Create directory if it does not exist
if not os.path.exists( dir ):
os.makedirs( dir )
+ os.chmod(dir, 0777)
# Return filename inside hashed directory
return os.path.abspath( os.path.join( dir, "dataset_%d.dat" % self.id ) )
else:
@@ -1131,6 +1149,28 @@
return hda_name
def get_access_roles( self, trans ):
return self.dataset.get_access_roles( trans )
+ def get_api_value( self, view='collection' ):
+ # Since this class is a proxy to rather complex attributes we want to
+ # display in other objects, we can't use the simpler method used by
+ # other model classes.
+ hda = self
+ rval = dict( name = hda.name,
+ extension = hda.extension,
+ deleted = hda.deleted,
+ visible = hda.visible,
+ state = hda.state,
+ file_size = int( hda.get_size() ),
+ genome_build = hda.dbkey,
+ misc_info = hda.info,
+ misc_blurb = hda.blurb )
+ for name, spec in hda.metadata.spec.items():
+ val = hda.metadata.get( name )
+ if isinstance( val, MetadataFile ):
+ val = val.file_name
+ elif isinstance( val, list ):
+ val = ', '.join( [str(v) for v in val] )
+ rval['metadata_' + name] = val
+ return rval
def quota_amount( self, user ):
"""
If the user has multiple instances of this dataset, it will not affect their disk usage statistic.
@@ -1794,6 +1834,8 @@
# File Exists is okay, otherwise reraise
if e.errno != errno.EEXIST:
raise
+
+ os.chmod(path, 0777)
# Return filename inside hashed directory
return os.path.abspath( os.path.join( path, "metadata_%d.dat" % self.id ) )
diff -r 070513d25b63110ef6569a9b09101864009f2ba4 -r 1d0bb560bd3d584708972001afd054774e9e89c5 lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -29,6 +29,9 @@
from cgi import FieldStorage
from galaxy.util.hash_util import *
from galaxy.util import listify
+from galaxy.web import security
+import socket
+
log = logging.getLogger( __name__ )
@@ -104,14 +107,6 @@
try:
path = elem.get( "file" )
tool = self.load_tool( os.path.join( tool_path, path ), guid=guid )
- if guid is not None:
- # Tool was installed from a Galaxy tool shed.
- tool.tool_shed = elem.find( "tool_shed" ).text
- tool.repository_name = elem.find( "repository_name" ).text
- tool.repository_owner = elem.find( "repository_owner" ).text
- tool.changeset_revision = elem.find( "changeset_revision" ).text
- tool.old_id = elem.find( "id" ).text
- tool.version = elem.find( "version" ).text
if self.app.config.get_bool( 'enable_tool_tags', False ):
tag_names = elem.get( "tags", "" ).split( "," )
for tag_name in tag_names:
@@ -372,7 +367,9 @@
# legacy basic mode - provide compatible defaults
self.attributes['split_size'] = 20
self.attributes['split_mode'] = 'number_of_parts'
-
+
+
+
class Tool:
"""
Represents a computational tool that can be executed through Galaxy.
@@ -393,15 +390,9 @@
# easily ensure that parameter dependencies like index files or
# tool_data_table_conf.xml entries exist.
self.input_params = []
- # Attributes of tools installed from Galaxy tool sheds.
- self.tool_shed = None
- self.repository_name = None
- self.repository_owner = None
- self.changeset_revision = None
- self.old_id = None
- self.version = None
# Parse XML element containing configuration
self.parse( root, guid=guid )
+ self.external_runJob_script = app.config.drmaa_external_runjob_script
@property
def sa_session( self ):
@@ -420,14 +411,14 @@
raise Exception, "Missing tool 'name'"
# Get the UNIQUE id for the tool
# TODO: can this be generated automatically?
- if guid is None:
+ if guid is not None:
+ self.id = guid
+ else:
self.id = root.get( "id" )
- self.version = root.get( "version" )
- else:
- self.id = guid
if not self.id:
- raise Exception, "Missing tool 'id'"
- if not self.version:
+ raise Exception, "Missing tool 'id'"
+ self.version = root.get( "version" )
+ if not self.version:
# For backward compatibility, some tools may not have versions yet.
self.version = "1.0.0"
# Support multi-byte tools
@@ -814,8 +805,7 @@
if elem.tag == "repeat":
group = Repeat()
group.name = elem.get( "name" )
- group.title = elem.get( "title" )
- group.help = elem.get( "help", None )
+ group.title = elem.get( "title" )
group.inputs = self.parse_input_elem( elem, enctypes, context )
group.default = int( elem.get( "default", 0 ) )
group.min = int( elem.get( "min", 0 ) )
@@ -1578,13 +1568,13 @@
DatasetFilenameWrapper( converted_dataset,
datatypes_registry = self.app.datatypes_registry,
tool = Bunch( conversion_name = Bunch( extensions = conv_ext ) ),
- name = conversion_name )
+ name = conversion_name, config_info = self.app.config )
# Wrap actual input dataset
input_values[ input.name ] = \
- DatasetFilenameWrapper( input_values[ input.name ],
+ DatasetFilenameWrapper( input_values[ input.name ],
datatypes_registry = self.app.datatypes_registry,
tool = self,
- name = input.name )
+ name = input.name, config_info = self.app.config )
elif isinstance( input, SelectToolParameter ):
input_values[ input.name ] = SelectToolParameterWrapper(
input, input_values[ input.name ], self.app, other_values = param_dict )
@@ -1622,28 +1612,28 @@
param_dict[name] = DatasetFilenameWrapper( data,
datatypes_registry = self.app.datatypes_registry,
tool = self,
- name = name )
+ name = name, config_info = self.app.config )
if data:
for child in data.children:
- param_dict[ "_CHILD___%s___%s" % ( name, child.designation ) ] = DatasetFilenameWrapper( child )
+ param_dict[ "_CHILD___%s___%s" % ( name, child.designation ) ] = DatasetFilenameWrapper( child,config_info = self.app.config )
for name, hda in output_datasets.items():
# Write outputs to the working directory (for security purposes)
# if desired.
if self.app.config.outputs_to_working_directory:
try:
false_path = [ dp.false_path for dp in output_paths if dp.real_path == hda.file_name ][0]
- param_dict[name] = DatasetFilenameWrapper( hda, false_path = false_path )
+ param_dict[name] = DatasetFilenameWrapper( hda, false_path = false_path, config_info = self.app.config )
open( false_path, 'w' ).close()
except IndexError:
log.warning( "Unable to determine alternate path for writing job outputs, outputs will be written to their real paths" )
- param_dict[name] = DatasetFilenameWrapper( hda )
+ param_dict[name] = DatasetFilenameWrapper( hda, config_info = self.app.config )
else:
- param_dict[name] = DatasetFilenameWrapper( hda )
+ param_dict[name] = DatasetFilenameWrapper( hda, config_info = self.app.config )
# Provide access to a path to store additional files
# TODO: path munging for cluster/dataset server relocatability
param_dict[name].files_path = os.path.abspath(os.path.join( job_working_directory, "dataset_%s_files" % (hda.dataset.id) ))
for child in hda.children:
- param_dict[ "_CHILD___%s___%s" % ( name, child.designation ) ] = DatasetFilenameWrapper( child )
+ param_dict[ "_CHILD___%s___%s" % ( name, child.designation ) ] = DatasetFilenameWrapper( child, config_info = self.app.config )
for out_name, output in self.outputs.iteritems():
if out_name not in param_dict and output.filters:
# Assume the reason we lack this output is because a filter
@@ -1702,8 +1692,10 @@
fd, config_filename = tempfile.mkstemp( dir=directory )
os.close( fd )
f = open( config_filename, "wt" )
+ os.chmod(config_filename, 0777)
f.write( fill_template( template_text, context=param_dict ) )
f.close()
+ os.chmod(config_filename, 0777)
param_dict[name] = config_filename
config_filenames.append( config_filename )
return config_filenames
@@ -1836,13 +1828,15 @@
"""
for name, hda in output.items():
temp_file_path = os.path.join( job_working_directory, "dataset_%s_files" % ( hda.dataset.id ) )
- try:
- if len( os.listdir( temp_file_path ) ) > 0:
- store_file_path = os.path.join(
- os.path.join( self.app.config.file_path, *directory_hash_id( hda.dataset.id ) ),
+ #try:
+ if os.path.exists(temp_file_path) and len( os.listdir( temp_file_path ) ) > 0:
+ store_file_path = os.path.join(
+ os.path.join( self.app.config.file_path, *directory_hash_id( hda.dataset.id ) ),
"dataset_%d_files" % hda.dataset.id )
- shutil.move( temp_file_path, store_file_path )
- # Fix permissions
+ os.mkdir(store_file_path)
+ os.system('mv %s/* %s/' %(temp_file_path ,store_file_path))
+ # Fix permissions
+ if self.external_runJob_script == None:
for basedir, dirs, files in os.walk( store_file_path ):
util.umask_fix_perms( basedir, self.app.config.umask, 0777, self.app.config.gid )
for file in files:
@@ -1851,8 +1845,8 @@
if os.path.islink( path ):
continue
util.umask_fix_perms( path, self.app.config.umask, 0666, self.app.config.gid )
- except:
- continue
+ #except:
+ #continue
def collect_child_datasets( self, output):
"""
@@ -2243,7 +2237,7 @@
def items( self ):
return iter( [ ( k, self.get( k ) ) for k, v in self.metadata.items() ] )
- def __init__( self, dataset, datatypes_registry = None, tool = None, name = None, false_path = None ):
+ def __init__( self, dataset, datatypes_registry = None, tool = None, name = None, false_path = None , config_info=None):
if not dataset:
try:
# TODO: allow this to work when working with grouping
@@ -2255,6 +2249,14 @@
self.dataset = dataset
self.metadata = self.MetadataWrapper( dataset.metadata )
self.false_path = false_path
+
+ # create web_display_url attribute
+ sec = security.SecurityHelper( id_secret=config_info.id_secret )
+ try:
+ url = 'http://' + socket.getfqdn() + config_info.cookie_path + '/datasets/' + sec.encode_id(dataset.id) + '/display/?preview=True'
+ self.web_display_url = url
+ except:
+ self.web_display_url = None
def __str__( self ):
if self.false_path is not None:
diff -r 070513d25b63110ef6569a9b09101864009f2ba4 -r 1d0bb560bd3d584708972001afd054774e9e89c5 lib/galaxy/tools/actions/__init__.py
--- a/lib/galaxy/tools/actions/__init__.py
+++ b/lib/galaxy/tools/actions/__init__.py
@@ -150,7 +150,7 @@
galaxy.tools.DatasetFilenameWrapper( input_values[ input.name ],
datatypes_registry = trans.app.datatypes_registry,
tool = tool,
- name = input.name )
+ name = input.name, config_info = trans.app.config)
elif isinstance( input, SelectToolParameter ):
input_values[ input.name ] = galaxy.tools.SelectToolParameterWrapper( input, input_values[ input.name ], tool.app, other_values = incoming )
else:
@@ -282,9 +282,12 @@
trans.sa_session.flush()
trans.app.security_agent.set_all_dataset_permissions( data.dataset, output_permissions )
# Create an empty file immediately
- open( data.file_name, "w" ).close()
- # Fix permissions
- util.umask_fix_perms( data.file_name, trans.app.config.umask, 0666 )
+ self.external_runJob_script = trans.app.config.drmaa_external_runjob_script
+ if self.external_runJob_script == None:
+ open( data.file_name, "w" ).close()
+ # Fix permissions
+ util.umask_fix_perms( data.file_name, trans.app.config.umask, 0666)
+ log.debug('.DAT file name = %s\n' %(data.file_name))
# This may not be neccesary with the new parent/child associations
data.designation = name
# Copy metadata from one of the inputs if requested.
diff -r 070513d25b63110ef6569a9b09101864009f2ba4 -r 1d0bb560bd3d584708972001afd054774e9e89c5 lib/galaxy/tools/actions/upload_common.py
--- a/lib/galaxy/tools/actions/upload_common.py
+++ b/lib/galaxy/tools/actions/upload_common.py
@@ -279,8 +279,10 @@
is_binary = None
try:
link_data_only = uploaded_dataset.link_data_only
+ chmod_flag = 1
except:
link_data_only = 'copy_files'
+ chmod_flag = 0
json = dict( file_type = uploaded_dataset.file_type,
ext = uploaded_dataset.ext,
name = uploaded_dataset.name,
@@ -291,8 +293,12 @@
link_data_only = link_data_only,
space_to_tab = uploaded_dataset.space_to_tab,
path = uploaded_dataset.path )
+ if chmod_flag == 0 and trans.app.config.drmaa_external_runjob_script:
+ os.chmod(uploaded_dataset.path, 0777)
json_file.write( to_json_string( json ) + '\n' )
json_file.close()
+ if trans.app.config.drmaa_external_runjob_script:
+ os.chmod(json_file_path, 0777)
return json_file_path
def create_job( trans, params, tool, json_file_path, data_list, folder=None, return_job=False ):
"""
@@ -325,12 +331,17 @@
# Create an empty file immediately
if not dataset.dataset.external_filename:
open( dataset.file_name, "w" ).close()
+ if trans.app.config.drmaa_external_runjob_script:
+ os.chmod(dataset.file_name, 0777)
else:
for i, dataset in enumerate( data_list ):
job.add_output_dataset( 'output%i' % i, dataset )
# Create an empty file immediately
if not dataset.dataset.external_filename:
open( dataset.file_name, "w" ).close()
+ if trans.app.config.drmaa_external_runjob_script:
+ os.chmod(dataset.file_name, 0777)
+
job.state = job.states.NEW
trans.sa_session.add( job )
trans.sa_session.flush()
diff -r 070513d25b63110ef6569a9b09101864009f2ba4 -r 1d0bb560bd3d584708972001afd054774e9e89c5 scripts/drmaa_external_killer.py
--- /dev/null
+++ b/scripts/drmaa_external_killer.py
@@ -0,0 +1,63 @@
+#!/usr/bin/env python
+import os
+import sys
+import errno
+import pwd
+#import drmaa
+new_path = [ os.path.join( os.getcwd(), "lib" ) ]
+new_path.extend( sys.path[1:] ) # remove scripts/ from the path
+sys.path = new_path
+
+from galaxy import eggs
+import pkg_resources
+pkg_resources.require("simplejson")
+import simplejson as json
+pkg_resources.require("drmaa")
+import drmaa
+
+
+
+def validate_paramters():
+ if len(sys.argv)<3:
+ sys.stderr.write("usage: %s [job ID] [user uid]\n" % sys.argv[0])
+ exit(1)
+
+ jobID = sys.argv[1]
+ uid = int(sys.argv[2])
+
+
+
+ return jobID, uid
+
+def set_user(uid):
+ try:
+ gid = pwd.getpwuid(uid).pw_gid
+ os.setgid(gid)
+ os.setuid(uid)
+ except OSError, e:
+ if e.errno == errno.EPERM:
+ sys.stderr.write("error: setuid(%d) failed: permission denied. Did you setup 'sudo' correctly for this script?\n" % uid )
+ exit(1)
+ else:
+ pass
+ if os.getuid()==0:
+ sys.stderr.write("error: UID is 0 (root) after changing user. This script should not be run as root. aborting.\n" )
+ exit(1)
+ if os.geteuid()==0:
+ sys.stderr.write("error: EUID is 0 (root) after changing user. This script should not be run as root. aborting.\n" )
+ exit(1)
+
+def main():
+ jobID, uid = validate_paramters()
+ set_user(uid)
+ s=drmaa.Session()
+ s.initialize()
+ s.control(jobID,drmaa.JobControlAction.TERMINATE)
+ s.exit()
+
+
+
+if __name__ == "__main__":
+ main()
+
+
diff -r 070513d25b63110ef6569a9b09101864009f2ba4 -r 1d0bb560bd3d584708972001afd054774e9e89c5 scripts/drmaa_external_runner.py
--- /dev/null
+++ b/scripts/drmaa_external_runner.py
@@ -0,0 +1,108 @@
+#!/usr/bin/env python
+import os
+import sys
+import errno
+import pwd
+
+#import simplejson as json
+#import drmaa
+new_path = [ os.path.join( os.getcwd(), "lib" ) ]
+new_path.extend( sys.path[1:] ) # remove scripts/ from the path
+sys.path = new_path
+
+from galaxy import eggs
+import pkg_resources
+pkg_resources.require("simplejson")
+import simplejson as json
+pkg_resources.require("drmaa")
+import drmaa
+
+DRMAA_jobTemplate_attributes = [ 'args', 'remoteCommand', 'outputPath', 'errorPath', 'nativeSpecification',
+ 'name','email','project' ]
+
+def load_job_template_from_file(jt, filename):
+ f = open(filename,'r')
+ data = json.load(f)
+ for attr in DRMAA_jobTemplate_attributes:
+ if attr in data:
+ setattr(jt, attr, data[attr])
+
+def valid_numeric_userid(userid):
+ try:
+ uid = int(userid)
+ except:
+ return False
+ try:
+ pw = pwd.getpwuid(uid)
+ except KeyError:
+ sys.stderr.write("error: User-ID (%d) is not valid.\n" % uid)
+ exit(1)
+ return True
+
+def get_user_id_by_name(username):
+ try:
+ pw = pwd.getpwnam(username)
+ except KeyError:
+ sys.stderr.write("error: User name (%s) is not valid.\n" % username)
+ exit(1)
+ return pw.pw_uid
+def validate_paramters():
+ if len(sys.argv)<3:
+ sys.stderr.write("usage: %s [USER-ID] [JSON-JOB-TEMPLATE-FILE]\n" % sys.argv[0])
+ exit(1)
+
+ userid = sys.argv[1]
+ json_filename = sys.argv[2]
+
+ if valid_numeric_userid(userid):
+ uid = int(userid)
+ else:
+ uid = get_user_id_by_name(userid)
+
+ if uid == 0:
+ sys.stderr.write("error: userid must not be 0 (root)\n")
+ exit(1)
+
+ if not os.path.exists(json_filename):
+ sys.stderr.write("error: JobTemplate file (%s) doesn't exist\n" % ( json_filename ) )
+ exit(1)
+
+ return uid, json_filename
+
+def set_user(uid):
+ try:
+ # Get user's default group and set it to current process to make sure file permissions are inherited correctly
+ # Solves issue with permission denied for JSON files
+ gid = pwd.getpwuid(uid).pw_gid
+ os.setgid(gid)
+ os.setuid(uid)
+ except OSError, e:
+ if e.errno == errno.EPERM:
+ sys.stderr.write("error: setuid(%d) failed: permission denied. Did you setup 'sudo' correctly for this script?\n" % uid )
+ exit(1)
+ else:
+ pass
+ if os.getuid()==0:
+ sys.stderr.write("error: UID is 0 (root) after changing user. This script should not be run as root. aborting.\n" )
+ exit(1)
+ if os.geteuid()==0:
+ sys.stderr.write("error: EUID is 0 (root) after changing user. This script should not be run as root. aborting.\n" )
+ exit(1)
+def main():
+ userid, json_filename = validate_paramters()
+ set_user(userid)
+ s = drmaa.Session()
+ s.initialize()
+ jt = s.createJobTemplate()
+ load_job_template_from_file(jt, json_filename)
+ # runJob will raise if there's a submittion error
+ jobId = s.runJob(jt)
+ s.deleteJobTemplate(jt)
+ s.exit()
+
+ # Print the Job-ID and exit. Galaxy will pick it up from there.
+ print jobId
+
+if __name__ == "__main__":
+ main()
+
diff -r 070513d25b63110ef6569a9b09101864009f2ba4 -r 1d0bb560bd3d584708972001afd054774e9e89c5 scripts/external_chown_script.py
--- /dev/null
+++ b/scripts/external_chown_script.py
@@ -0,0 +1,43 @@
+#!/usr/bin/env python
+import os
+import sys
+import errno
+import pwd
+#import drmaa
+new_path = [ os.path.join( os.getcwd(), "lib" ) ]
+new_path.extend( sys.path[1:] ) # remove scripts/ from the path
+sys.path = new_path
+
+from galaxy import eggs
+import pkg_resources
+pkg_resources.require("simplejson")
+import simplejson as json
+pkg_resources.require("drmaa")
+import drmaa
+
+
+
+def validate_paramters():
+ if len(sys.argv)<4:
+ sys.stderr.write("usage: %s path user_name gid\n" % sys.argv[0])
+ exit(1)
+
+ path = sys.argv[1]
+ galaxy_user_name = sys.argv[2]
+ gid = sys.argv[3]
+
+
+
+ return path, galaxy_user_name, gid
+
+def main():
+ path, galaxy_user_name, gid = validate_paramters()
+ os.system('chown %s %s' %(galaxy_user_name, path))
+ os.system('chgrp %s %s' %(gid, path))
+
+
+
+if __name__ == "__main__":
+ main()
+
+
diff -r 070513d25b63110ef6569a9b09101864009f2ba4 -r 1d0bb560bd3d584708972001afd054774e9e89c5 tools/data_source/upload.py
--- a/tools/data_source/upload.py
+++ b/tools/data_source/upload.py
@@ -165,6 +165,7 @@
dataset.path = uncompressed
else:
shutil.move( uncompressed, dataset.path )
+ os.chmod(dataset.path, 0644)
dataset.name = dataset.name.rstrip( '.gz' )
data_type = 'gzip'
if not data_type and bz2 is not None:
@@ -197,6 +198,7 @@
dataset.path = uncompressed
else:
shutil.move( uncompressed, dataset.path )
+ os.chmod(dataset.path, 0644)
dataset.name = dataset.name.rstrip( '.bz2' )
data_type = 'bz2'
if not data_type:
@@ -253,6 +255,7 @@
dataset.path = uncompressed
else:
shutil.move( uncompressed, dataset.path )
+ os.chmod(dataset.path, 0644)
dataset.name = uncompressed_name
data_type = 'zip'
if not data_type:
@@ -312,9 +315,18 @@
pass
else:
# This should not happen, but it's here just in case
- shutil.copy( dataset.path, output_path )
+ shutil.move( dataset.path, output_path )
+ try:
+ os.chmod(output_path,0644)
+ except:
+ pass
elif link_data_only == 'copy_files':
shutil.move( dataset.path, output_path )
+ try:
+ os.chmod(output_path,0644)
+ except:
+ pass
+
# Write the job info
stdout = stdout or 'uploaded %s file' % data_type
info = dict( type = 'dataset',
diff -r 070513d25b63110ef6569a9b09101864009f2ba4 -r 1d0bb560bd3d584708972001afd054774e9e89c5 tools/ngs_rna/cufflinks_wrapper.xml
--- a/tools/ngs_rna/cufflinks_wrapper.xml
+++ b/tools/ngs_rna/cufflinks_wrapper.xml
@@ -1,5 +1,4 @@
-<tool id="cufflinks" name="Cufflinks" version="0.0.5">
- <!-- Wrapper supports Cufflinks versions v1.0.0-v1.0.3 -->
+<tool id="cufflinks" name="Cufflinks" version="0.9.1"><description>transcript assembly and FPKM (RPKM) estimates for RNA-Seq data</description><requirements><requirement type="package">cufflinks</requirement>
@@ -15,10 +14,27 @@
## Include reference annotation?
#if $reference_annotation.use_ref == "Use reference annotation":
- -G $reference_annotation.reference_annotation_file
+ #if $reference_annotation.annotationSource.reference_annotation_file == "indexed":
+ -G "${ filter( lambda x: str( x[0] ) == str( $reference_annotation.annotationSource.indices ), $__app__.tool_data_tables[ 'gtf_index' ].get_fields() )[0][-1] }"
+ #else:
+ #if $reference_annotation.annotationSource.reference_annotation_file == "attribute":
+ -G "${ filter( lambda x: str( x[0] ) == str( $input.metadata.dbkey ), $__app__.tool_data_tables[ 'gtf_index' ].get_fields() )[0][-1] }"
+ #else:
+ -G "${reference_annotation.annotationSource.ownFile}"
+ #end if
+ #end if
#end if
+
#if $reference_annotation.use_ref == "Use reference annotation guide":
- -g $reference_annotation.reference_annotation_guide_file
+ #if $reference_annotation.annotationSource.reference_annotation_file == "indexed":
+ -g "${ filter( lambda x: str( x[0] ) == str( $reference_annotation.annotationSource.indices ), $__app__.tool_data_tables[ 'gtf_index' ].get_fields() )[0][-1] }"
+ #else:
+ #if $reference_annotation.annotationSource.reference_annotation_file == "attribute":
+ -g "${ filter( lambda x: str( x[0] ) == str( $input.metadata.dbkey ), $__app__.tool_data_tables[ 'gtf_index' ].get_fields() )[0][-1] }"
+ #else:
+ -g "${reference_annotation.annotationSource.ownFile}"
+ #end if
+ #end if
#end if
## Set paired-end parameters?
@@ -61,10 +77,44 @@
</param><when value="No"></when><when value="Use reference annotation">
- <param format="gff3,gtf" name="reference_annotation_file" type="data" label="Reference Annotation" help="Make sure your annotation file is in GTF format and that Galaxy knows that your file is GTF--not GFF."/>
- </when>
+ <conditional name="annotationSource">
+ <param name="reference_annotation_file" type="select" label="Please select a reference Aonnotation">
+ <option value="indexed">Use a built-in index</option>
+ <option value="history">Use one from the history</option>
+ <option value="attribute">Use input bam metadata.dbkey attribute</option>
+ </param>
+ <when value="indexed">
+ <param name="indices" type="select" label="Select genome for gtf annotation">
+ <options from_data_table="gtf_index">
+ <filter type="sort_by" column="3" />
+ <validator type="no_options" message="No indexes are available for the selected input dataset" />
+ </options>
+ </param>
+ </when>
+ <when value="history">
+ <param name="ownFile" type="data" format="gff3, gtf" label="Select a reference annotation file" />
+ </when>
+ </conditional>
+ </when><when value="Use reference annotation guide">
- <param format="gff3,gtf" name="reference_annotation_guide_file" type="data" label="Reference Annotation" help="Make sure your annotation file is in GTF format and that Galaxy knows that your file is GTF--not GFF."/>
+ <conditional name="annotationSource">
+ <param name="reference_annotation_file" type="select" label="Please select a reference Aonnotation">
+ <option value="indexed">Use a built-in index</option>
+ <option value="history">Use one from the history</option>
+ <option value="attribute">Use input bam metadata.dbkey attribute</option>
+ </param>
+ <when value="indexed">
+ <param name="indices" type="select" label="Select genome for gtf annotation">
+ <options from_data_table="gtf_index">
+ <filter type="sort_by" column="3" />
+ <validator type="no_options" message="No indexes are available for the selected input dataset" />
+ </options>
+ </param>
+ </when>
+ <when value="history">
+ <param name="ownFile" type="data" format="gff3, gtf" label="Select a reference annotation file" />
+ </when>
+ </conditional></when></conditional><conditional name="bias_correction">
diff -r 070513d25b63110ef6569a9b09101864009f2ba4 -r 1d0bb560bd3d584708972001afd054774e9e89c5 tools/ngs_rna/tophat_wrapper.xml
--- a/tools/ngs_rna/tophat_wrapper.xml
+++ b/tools/ngs_rna/tophat_wrapper.xml
@@ -1,7 +1,8 @@
-<tool id="tophat" name="Tophat for Illumina" version="1.5.0">
+<tool id="tophat" name="Tophat" version="1.2.1"><description>Find splice junctions using RNA-seq data</description>
- <version_command>tophat --version</version_command><requirements>
+ <requirement type="package">samtools</requirement>
+ <requirement type="package">bowtie</requirement><requirement type="package">tophat</requirement></requirements><command interpreter="python">
@@ -17,14 +18,18 @@
#if $refGenomeSource.genomeSource == "history":
--own-file=$refGenomeSource.ownFile
#else:
- --indexes-path="${ filter( lambda x: str( x[0] ) == str( $refGenomeSource.index ), $__app__.tool_data_tables[ 'tophat_indexes' ].get_fields() )[0][-1] }"
+ #if $refGenomeSource.genomeSource == "indexed":
+ --indexes-path="${ filter( lambda x: str( x[0] ) == str( $refGenomeSource.index ), $__app__.tool_data_tables[ 'tophat_indexes' ].get_fields() )[0][-1] }"
+ #else:
+ --indexes-path="${ filter( lambda x: str( x[0] ) == str( $singlePaired.input1.metadata.dbkey ), $__app__.tool_data_tables[ 'tophat_indexes' ].get_fields() )[0][-1] }"
+ #end if
#end if
## Are reads single-end or paired?
--single-paired=$singlePaired.sPaired
## First input file always required.
- --input1=$input1
+ --input1=$singlePaired.input1
## Set params based on whether reads are single-end or paired.
#if $singlePaired.sPaired == "single":
@@ -52,7 +57,15 @@
## Supplying junctions parameters.
#if $singlePaired.sParams.own_junctions.use_junctions == "Yes":
#if $singlePaired.sParams.own_junctions.gene_model_ann.use_annotations == "Yes":
- -G $singlePaired.sParams.own_junctions.gene_model_ann.gene_annotation_model
+ #if $singlePaired.sParams.own_junctions.gene_model_ann.annotationSource.reference_annotation_file == "indexed":
+ -G "${ filter( lambda x: str( x[0] ) == str( $refGenomeSource.index ), $__app__.tool_data_tables[ 'gtf_index' ].get_fields() )[0][-1] }"
+ #else:
+ #if $singlePaired.sParams.own_junctions.gene_model_ann.annotationSource.reference_annotation_file == "attribute":
+ -G "${ filter( lambda x: str( x[0] ) == str( $singlePaired.input1.metadata.dbkey ), $__app__.tool_data_tables[ 'gtf_index' ].get_fields() )[0][-1] }"
+ #else
+ -G "${singlePaired.sParams.own_junctions.gene_model_ann.annotationSource.owngtfFile}"
+ #end if
+ #end if
#end if
#if $singlePaired.sParams.own_junctions.raw_juncs.use_juncs == "Yes":
-j $singlePaired.sParams.own_junctions.raw_juncs.raw_juncs
@@ -111,7 +124,15 @@
## Supplying junctions parameters.
#if $singlePaired.pParams.own_junctions.use_junctions == "Yes":
#if $singlePaired.pParams.own_junctions.gene_model_ann.use_annotations == "Yes":
- -G $singlePaired.pParams.own_junctions.gene_model_ann.gene_annotation_model
+ #if $singlePaired.pParams.own_junctions.gene_model_ann.annotationSource.reference_annotation_file == "indexed":
+ -G "${ filter( lambda x: str( x[0] ) == str( $refGenomeSource.index ), $__app__.tool_data_tables[ 'gtf_index' ].get_fields() )[0][-1] }"
+ #else:
+ #if $singlePaired.pParams.own_junctions.gene_model_ann.annotationSource.reference_annotation_file == "attribute":
+ -G "${ filter( lambda x: str( x[0] ) == str( $singlePaired.input1.metadata.dbkey ), $__app__.tool_data_tables[ 'gtf_index' ].get_fields() )[0][-1] }"
+ #else
+ -G "${singlePaired.sParams.own_junctions.gene_model_ann.annotationSource.owngtfFile}"
+ #end if
+ #end if
#end if
#if $singlePaired.pParams.own_junctions.raw_juncs.use_juncs == "Yes":
-j $singlePaired.pParams.own_junctions.raw_juncs.raw_juncs
@@ -145,18 +166,15 @@
#end if
</command><inputs>
- <param format="fastqsanger" name="input1" type="data" label="RNA-Seq FASTQ file" help="Nucleotide-space: Must have Sanger-scaled quality values with ASCII offset 33" /><conditional name="refGenomeSource"><param name="genomeSource" type="select" label="Will you select a reference genome from your history or use a built-in index?" help="Built-ins were indexed using default options"><option value="indexed">Use a built-in index</option><option value="history">Use one from the history</option>
+ <option value="attribute">Use input fastq metadata.dbkey attribute</option></param><when value="indexed"><param name="index" type="select" label="Select a reference genome" help="If your genome of interest is not listed, contact the Galaxy team">
- <options from_data_table="tophat_indexes">
- <filter type="sort_by" column="2"/>
- <validator type="no_options" message="No indexes are available for the selected input dataset"/>
- </options>
+ <options from_data_table="tophat_indexes" /></param></when><when value="history">
@@ -169,6 +187,7 @@
<option value="paired">Paired-end</option></param><when value="single">
+ <param format="fastqsanger" name="input1" type="data" label="RNA-Seq FASTQ file" help="Must have Sanger-scaled quality values with ASCII offset 33"/><conditional name="sParams"><param name="sSettingsType" type="select" label="TopHat settings to use" help="You can use the default settings or set custom values for any of Tophat's parameters."><option value="preSet">Use Defaults</option>
@@ -218,7 +237,16 @@
</param><when value="No" /><when value="Yes">
- <param format="gtf" name="gene_annotation_model" type="data" label="Gene Model Annotations" help="TopHat will use the exon records in this file to build a set of known splice junctions for each gene, and will attempt to align reads to these junctions even if they would not normally be covered by the initial mapping."/>
+ <conditional name="annotationSource">
+ <param name="reference_annotation_file" type="select" label="Please select a reference Aonnotation">
+ <option value="indexed">Use a built-in index</option>
+ <option value="history">Use one from the history</option>
+ <option value="attribute">Use metadata.bkey attribute from input fastq file</option>
+ </param>
+ <when value="history">
+ <param name="owngtfFile" type="data" format="gff3, gtf" label="Select a reference annotation file" />
+ </when>
+ </conditional></when></conditional><conditional name="raw_juncs">
@@ -263,7 +291,7 @@
<param name="max_coverage_intron" type="integer" value="20000" label="Maximum intron length that may be found during coverage search" /></when><when value="No" />
- </conditional>
+ </conditional><param name="microexon_search" type="select" label="Use Microexon Search" help="With this option, the pipeline will attempt to find alignments incident to microexons. Works only for reads 50bp or longer."><option value="No">No</option><option value="Yes">Yes</option>
@@ -272,7 +300,8 @@
</conditional><!-- sParams --></when><!-- single --><when value="paired">
- <param format="fastqsanger" name="input2" type="data" label="RNA-Seq FASTQ file" help="Nucleotide-space: Must have Sanger-scaled quality values with ASCII offset 33" />
+ <param format="fastqsanger" name="input1" type="data" label="RNA-Seq FASTQ file" help="Must have Sanger-scaled quality values with ASCII offset 33"/>
+ <param format="fastqsanger" name="input2" type="data" label="RNA-Seq FASTQ file" help="Must have Sanger-scaled quality values with ASCII offset 33"/><param name="mate_inner_distance" type="integer" value="20" label="Mean Inner Distance between Mate Pairs" /><conditional name="pParams"><param name="pSettingsType" type="select" label="TopHat settings to use" help="For most mapping needs use Commonly used settings. If you want full control use Full parameter list">
@@ -323,7 +352,16 @@
</param><when value="No" /><when value="Yes">
- <param format="gtf" name="gene_annotation_model" type="data" label="Gene Model Annotations" help="TopHat will use the exon records in this file to build a set of known splice junctions for each gene, and will attempt to align reads to these junctions even if they would not normally be covered by the initial mapping."/>
+ <conditional name="annotationSource">
+ <param name="reference_annotation_file" type="select" label="Please select a reference Aonnotation">
+ <option value="indexed">Use a built-in index</option>
+ <option value="history">Use one from the history</option>
+ <option value="attribute">Use metadata.bkey attribute from input fastq files</option>
+ </param>
+ <when value="history">
+ <param name="owngtfFile" type="data" format="gff3, gtf" label="Select a reference annotation file" />
+ </when>
+ </conditional></when></conditional><conditional name="raw_juncs">
@@ -387,7 +425,7 @@
( singlePaired['sParams']['indel_search']['allow_indel_search'] == 'Yes' ) ) or
( ( 'pParams' in singlePaired ) and ( 'indel_search' in singlePaired['pParams'] ) and
( singlePaired['pParams']['indel_search']['allow_indel_search'] == 'Yes' ) )
- )
+ )
</filter><actions><conditional name="refGenomeSource.genomeSource">
@@ -475,49 +513,46 @@
</outputs><tests>
- <!-- Test base-space single-end reads with pre-built index and preset parameters -->
+ <!-- Test single-end reads with pre-built index and preset parameters --><test><!-- TopHat commands:
- tophat -o tmp_dir -p 1 tophat_in1 test-data/tophat_in2.fastqsanger
- Rename the files in tmp_dir appropriately
+ tophat -o tmp_dir -p 1 /afs/bx.psu.edu/depot/data/genome/test/tophat/tophat_in1 test-data/tophat_in2.fastqsanger
-->
- <param name="input1" ftype="fastqsanger" value="tophat_in2.fastqsanger" /><param name="genomeSource" value="indexed" /><param name="index" value="tophat_test" /><param name="sPaired" value="single" />
+ <param name="input1" ftype="fastqsanger" value="tophat_in2.fastqsanger" /><param name="sSettingsType" value="preSet" /><output name="junctions" file="tophat_out1j.bed" /><output name="accepted_hits" file="tophat_out1h.bam" compare="sim_size" /></test>
- <!-- Test using base-space test data: paired-end reads, index from history. -->
+ <!-- Test using test data: paired-end reads, index from history. --><test><!-- TopHat commands:
bowtie-build -f test-data/tophat_in1.fasta tophat_in1
tophat -o tmp_dir -p 1 -r 20 tophat_in1 test-data/tophat_in2.fastqsanger test-data/tophat_in3.fastqsanger
- Rename the files in tmp_dir appropriately
-->
- <param name="input1" ftype="fastqsanger" value="tophat_in2.fastqsanger" /><param name="genomeSource" value="history" /><param name="ownFile" ftype="fasta" value="tophat_in1.fasta" /><param name="sPaired" value="paired" />
+ <param name="input1" ftype="fastqsanger" value="tophat_in2.fastqsanger" /><param name="input2" ftype="fastqsanger" value="tophat_in3.fastqsanger" /><param name="mate_inner_distance" value="20" /><param name="pSettingsType" value="preSet" /><output name="junctions" file="tophat_out2j.bed" /><output name="accepted_hits" file="tophat_out2h.bam" compare="sim_size" /></test>
- <!-- Test base-space single-end reads with user-supplied reference fasta and full parameters -->
+ <!-- Test single-end reads with user-supplied reference fasta and full parameters --><test><!-- Tophat commands:
bowtie-build -f test-data/tophat_in1.fasta tophat_in1
tophat -o tmp_dir -p 1 -a 8 -m 0 -i 70 -I 500000 -F 0.15 -g 40 +allow-indels +coverage-search +min-coverage-intron 50 +max-coverage-intro 20000 +segment-mismatches 2 +segment-length 25 +closure-search +min-closure-exon 50 +min-closure-intron 50 +max-closure-intro 5000 +microexon-search tophat_in1 test-data/tophat_in2.fastqsanger
Replace the + with double-dash
- Rename the files in tmp_dir appropriately
-->
- <param name="input1" ftype="fastqsanger" value="tophat_in2.fastqsanger"/><param name="genomeSource" value="history"/><param name="ownFile" value="tophat_in1.fasta"/><param name="sPaired" value="single"/>
+ <param name="input1" ftype="fastqsanger" value="tophat_in2.fastqsanger"/><param name="sSettingsType" value="full"/><param name="library_type" value="FR Unstranded"/><param name="anchor_length" value="8"/>
@@ -550,17 +585,16 @@
<output name="junctions" file="tophat_out3j.bed" /><output name="accepted_hits" file="tophat_out3h.bam" compare="sim_size" /></test>
- <!-- Test base-space paired-end reads with user-supplied reference fasta and full parameters -->
+ <!-- Test paired-end reads with user-supplied reference fasta and full parameters --><test><!-- TopHat commands:
- tophat -o tmp_dir -r 20 -p 1 -a 8 -m 0 -i 70 -I 500000 -F 0.15 -g 40 +coverage-search +min-coverage-intron 50 +max-coverage-intro 20000 +segment-mismatches 2 +segment-length 25 +closure-search +min-closure-exon 50 +min-closure-intron 50 +max-closure-intron 5000 +microexon-search tophat_in1 test-data/tophat_in2.fastqsanger test-data/tophat_in3.fastqsanger
+ tophat -o tmp_dir -r 20 -p 1 -a 8 -m 0 -i 70 -I 500000 -F 0.15 -g 40 +coverage-search +min-coverage-intron 50 +max-coverage-intro 20000 +segment-mismatches 2 +segment-length 25 +closure-search +min-closure-exon 50 +min-closure-intron 50 +max-closure-intron 5000 +microexon-search /afs/bx.psu.edu/depot/data/genome/test/tophat/tophat_in1 test-data/tophat_in2.fastqsanger test-data/tophat_in3.fastqsanger
Replace the + with double-dash
- Rename the files in tmp_dir appropriately
-->
- <param name="input1" ftype="fastqsanger" value="tophat_in2.fastqsanger"/><param name="genomeSource" value="indexed"/><param name="index" value="tophat_test"/><param name="sPaired" value="paired"/>
+ <param name="input1" ftype="fastqsanger" value="tophat_in2.fastqsanger"/><param name="input2" ftype="fastqsanger" value="tophat_in3.fastqsanger"/><param name="mate_inner_distance" value="20"/><param name="pSettingsType" value="full"/>
@@ -628,9 +662,7 @@
.. _BED: http://genome.ucsc.edu/FAQ/FAQformat.html#format1
.. _BAM: http://samtools.sourceforge.net/
-
-Two other possible outputs, depending on the options you choose, are insertions and deletions, both of which are in BED format.
-
+
-------
**Tophat settings**
@@ -649,7 +681,7 @@
--mate-std-dev INT The standard deviation for the distribution on inner distances between mate pairs. The default is 20bp.
-a/--min-anchor-length INT The "anchor length". TopHat will report junctions spanned by reads with at least this many bases on each side of the junction. Note that individual spliced
alignments may span a junction with fewer than this many bases on one side. However, every junction involved in spliced alignments is supported by at least one
- read with this many bases on each side. This must be at least 3 and the default is 8.
+ read with this many bases on each side. This must be at least 3 and the default is 8.
-m/--splice-mismatches INT The maximum number of mismatches that may appear in the "anchor" region of a spliced alignment. The default is 0.
-i/--min-intron-length INT The minimum intron length. TopHat will ignore donor/acceptor pairs closer than this many bases apart. The default is 70.
-I/--max-intron-length INT The maximum intron length. When searching for junctions ab initio, TopHat will ignore donor/acceptor pairs farther than this many bases apart, except when such a pair is supported by a split segment alignment of a long read. The default is 500000.
diff -r 070513d25b63110ef6569a9b09101864009f2ba4 -r 1d0bb560bd3d584708972001afd054774e9e89c5 universe_wsgi.ini.sample
--- a/universe_wsgi.ini.sample
+++ b/universe_wsgi.ini.sample
@@ -446,6 +446,14 @@
# large servers.
#enable_tool_tags = False
+# Enable a feature when running workflows. When enabled, default datasets
+# are selected for "Set at Runtime" inputs from the history such that the
+# same input will not be selected twice, unless there are more inputs than
+# compatible datasets in the history.
+# When False, the most recently added compatible item in the history will
+# be used for each "Set at Runtime" input, independent of others in the Workflow
+#enable_unique_workflow_defaults = False
+
# Enable Galaxy's "Upload via FTP" interface. You'll need to install and
# configure an FTP server (we've used ProFTPd since it can use Galaxy's
# database for authentication) and set the following two options.
@@ -533,6 +541,30 @@
# currently available are 'pbs' and 'drmaa'.
#start_job_runners = None
+# Uncomment drmaa_external_runjob_script , drmaa_external_killjob_script, and external_chown_script pameters and have them point to the
+# absolute path for scripts/drmaa_external_runner.py and scripts/drmaa_external_killer.py.
+# The scripts directory is located in the top level galaxy directory. The parameters when
+# uncommented allow for submission to the drmaa queue with the user name of the user submitting
+# the job and not the galaxy user. In order for this to work the actual user must log into galaxy
+# and the galaxy authentication must be consistent with the authentication on the server in which the
+# drmaa queue is running (i.e. the username must have an account on the server and be allowed to
+# submit jobs to the queue). The galaxy user must also be given sudo permission to execute
+# scripts/drmaa_external_runner.py and scripts/drmaa_external_killer.py in /etc/sudoers
+# Example:
+# galaxy ALL = (root) NOPASSWD: SETENV: /opt/galaxy/scripts/drmaa_external_runner.py
+# galaxy ALL = (root) NOPASSWD: SETENV: /opt/galaxy/scripts/drmaa_external_killer.py
+# Also the
+# Defaults requiretty
+# in /etc/sudoers must be commented out
+#drmaa_external_runjob_script = /opt/galaxy/scripts/drmaa_external_runner.py
+#drmaa_external_killjob_script = /opt/galaxy/scripts/drmaa_external_killer.py
+#external_chown_script = /opt/galaxy/scripts/external_chown_script.py
+
+#important if running as actual user since enviromental variables are not passed
+#will supercede an other definition of TMPDIR if using drmaa
+#TMPDIR = /opt/galaxy/database/tmp
+
+
# The URL for the default runner to use when a tool doesn't explicitly define a
# runner below.
#default_cluster_job_runner = local:///
@@ -554,7 +586,9 @@
# run with the runner defined with default_cluster_job_runner.
[galaxy:tool_runners]
-
+binsort = drmaa://-cwd -V -pe threaded 4/
+bwa_wrapper = drmaa://-cwd -V -pe threaded 4/
+unified_genotyper = drmaa://-cwd -V -pe threaded 2/
biomart = local:///
encode_db1 = local:///
hbvar = local:///
https://bitbucket.org/galaxy/galaxy-central/changeset/28ab7dde0972/
changeset: 28ab7dde0972
user: ichorny
date: 2011-10-21 23:05:06
summary: merge with galaxy central
affected #: 27 files
diff -r 1d0bb560bd3d584708972001afd054774e9e89c5 -r 28ab7dde097298b7565a6238f0bbcade29a73ae9 lib/galaxy/util/__init__.py
--- a/lib/galaxy/util/__init__.py
+++ b/lib/galaxy/util/__init__.py
@@ -133,6 +133,8 @@
def restore_text(text):
"""Restores sanitized text"""
+ if not text:
+ return text
for key, value in mapped_chars.items():
text = text.replace(value, key)
return text
diff -r 1d0bb560bd3d584708972001afd054774e9e89c5 -r 28ab7dde097298b7565a6238f0bbcade29a73ae9 lib/galaxy/web/api/histories.py
--- a/lib/galaxy/web/api/histories.py
+++ b/lib/galaxy/web/api/histories.py
@@ -88,9 +88,9 @@
state = states.QUEUED
elif summary[states.OK] == num_sets:
state = states.OK
+ item['state_details'] = summary
item['contents_url'] = url_for( 'history_contents', history_id=history_id )
item['state'] = state
- item['state_details'] = summary
except Exception, e:
item = "Error in history API at showing history detail"
log.error(item + ": %s" % str(e))
diff -r 1d0bb560bd3d584708972001afd054774e9e89c5 -r 28ab7dde097298b7565a6238f0bbcade29a73ae9 lib/galaxy/web/api/history_contents.py
--- a/lib/galaxy/web/api/history_contents.py
+++ b/lib/galaxy/web/api/history_contents.py
@@ -14,7 +14,7 @@
log = logging.getLogger( __name__ )
-class HistoryContentsController( BaseAPIController, UsesHistoryDatasetAssociation, UsesHistory ):
+class HistoryContentsController( BaseAPIController, UsesHistoryDatasetAssociation, UsesHistory, UsesLibrary, UsesLibraryItems ):
@web.expose_api
def index( self, trans, history_id, **kwd ):
@@ -85,7 +85,7 @@
if from_ld_id:
try:
- ld = get_library_content_for_access( trans, from_ld_id )
+ ld = self.get_library_dataset( trans, from_ld_id, check_ownership=False, check_accessible=False )
assert type( ld ) is trans.app.model.LibraryDataset, "Library content id ( %s ) is not a dataset" % from_ld_id
except AssertionError, e:
trans.response.status = 400
diff -r 1d0bb560bd3d584708972001afd054774e9e89c5 -r 28ab7dde097298b7565a6238f0bbcade29a73ae9 lib/galaxy/web/api/library_contents.py
--- a/lib/galaxy/web/api/library_contents.py
+++ b/lib/galaxy/web/api/library_contents.py
@@ -75,9 +75,9 @@
"""
class_name, content_id = self.__decode_library_content_id( trans, id )
if class_name == 'LibraryFolder':
- content = self.get_library_folder( trans, content_id, check_ownership=False, check_accessibility=True )
+ content = self.get_library_folder( trans, content_id, check_ownership=False, check_accessible=True )
else:
- content = self.get_library_dataset( trans, content_id, check_ownership=False, check_accessibility=True )
+ content = self.get_library_dataset( trans, content_id, check_ownership=False, check_accessible=True )
return self.encode_all_ids( trans, content.get_api_value( view='element' ) )
@web.expose_api
@@ -100,9 +100,10 @@
return "Missing requred 'folder_id' parameter."
else:
folder_id = payload.pop( 'folder_id' )
+ class_name, folder_id = self.__decode_library_content_id( trans, folder_id )
try:
# security is checked in the downstream controller
- parent = self.get_library_folder( trans, folder_id, check_ownership=False, check_accessibility=False )
+ parent = self.get_library_folder( trans, folder_id, check_ownership=False, check_accessible=False )
except Exception, e:
return str( e )
# The rest of the security happens in the library_common controller.
@@ -128,6 +129,23 @@
url = url_for( 'library_content', library_id=library_id, id=encoded_id ) ) )
return rval
+ @web.expose_api
+ def update( self, trans, id, library_id, payload, **kwd ):
+ """
+ PUT /api/libraries/{encoded_library_id}/contents/{encoded_content_type_and_id}
+ Sets relationships among items
+ """
+ if 'converted_dataset_id' in payload:
+ converted_id = payload.pop( 'converted_dataset_id' )
+ content = self.get_library_dataset( trans, id, check_ownership=False, check_accessible=False )
+ content_conv = self.get_library_dataset( trans, converted_id, check_ownership=False, check_accessible=False )
+ assoc = trans.app.model.ImplicitlyConvertedDatasetAssociation( parent = content.library_dataset_dataset_association,
+ dataset = content_conv.library_dataset_dataset_association,
+ file_type = content_conv.library_dataset_dataset_association.extension,
+ metadata_safe = True )
+ trans.sa_session.add( assoc )
+ trans.sa_session.flush()
+
def __decode_library_content_id( self, trans, content_id ):
if ( len( content_id ) % 16 == 0 ):
return 'LibraryDataset', content_id
diff -r 1d0bb560bd3d584708972001afd054774e9e89c5 -r 28ab7dde097298b7565a6238f0bbcade29a73ae9 lib/galaxy/web/controllers/admin.py
--- a/lib/galaxy/web/controllers/admin.py
+++ b/lib/galaxy/web/controllers/admin.py
@@ -708,7 +708,7 @@
def browse_tool_shed( self, trans, **kwd ):
tool_shed_url = kwd[ 'tool_shed_url' ]
galaxy_url = trans.request.host
- url = '%s/repository/browse_downloadable_repositories?galaxy_url=%s&webapp=galaxy' % ( tool_shed_url, galaxy_url )
+ url = '%s/repository/browse_valid_repositories?galaxy_url=%s&webapp=galaxy' % ( tool_shed_url, galaxy_url )
return trans.response.send_redirect( url )
@web.expose
@web.require_admin
diff -r 1d0bb560bd3d584708972001afd054774e9e89c5 -r 28ab7dde097298b7565a6238f0bbcade29a73ae9 lib/galaxy/webapps/community/controllers/repository.py
--- a/lib/galaxy/webapps/community/controllers/repository.py
+++ b/lib/galaxy/webapps/community/controllers/repository.py
@@ -183,7 +183,7 @@
.outerjoin( model.RepositoryCategoryAssociation.table ) \
.outerjoin( model.Category.table )
-class DownloadableRepositoryListGrid( RepositoryListGrid ):
+class ValidRepositoryListGrid( RepositoryListGrid ):
class RevisionColumn( grids.GridColumn ):
def __init__( self, col_name ):
grids.GridColumn.__init__( self, col_name )
@@ -196,7 +196,7 @@
if len( select_field.options ) > 1:
return select_field.get_html()
return repository.revision
- title = "Downloadable repositories"
+ title = "Valid repositories"
columns = [
RepositoryListGrid.NameColumn( "Name",
key="name",
@@ -210,11 +210,6 @@
attach_popup=False,
key="User.username" )
]
- columns.append( grids.MulticolFilterColumn( "Search repository name, description",
- cols_to_filter=[ columns[0], columns[1] ],
- key="free-text-search",
- visible=False,
- filterable="standard" ) )
operations = []
def build_initial_query( self, trans, **kwd ):
return trans.sa_session.query( self.model_class ) \
@@ -237,7 +232,7 @@
return repository_metadata.repository.user.username
return 'no user'
# Grid definition
- title = "Matched repositories"
+ title = "Repositories with matching tools"
model_class = model.RepositoryMetadata
template='/webapps/community/repository/grid.mako'
default_sort_key = "Repository.name"
@@ -282,21 +277,19 @@
.filter( self.model_class.table.c.repository_id == 0 )
class InstallMatchedRepositoryListGrid( MatchedRepositoryListGrid ):
- # Grid definition
- title = "Repositories that contain tools matching search criteria"
columns = [ col for col in MatchedRepositoryListGrid.columns ]
# Override the NameColumn
columns[ 0 ] = MatchedRepositoryListGrid.NameColumn( "Name",
link=( lambda item: dict( operation="view_or_manage_repository",
id=item.id,
webapp="galaxy" ) ),
- attach_popup=True )
+ attach_popup=False )
class RepositoryController( BaseUIController, ItemRatings ):
install_matched_repository_list_grid = InstallMatchedRepositoryListGrid()
matched_repository_list_grid = MatchedRepositoryListGrid()
- downloadable_repository_list_grid = DownloadableRepositoryListGrid()
+ valid_repository_list_grid = ValidRepositoryListGrid()
repository_list_grid = RepositoryListGrid()
category_list_grid = CategoryListGrid()
@@ -340,7 +333,7 @@
# Render the list view
return self.category_list_grid( trans, **kwd )
@web.expose
- def browse_downloadable_repositories( self, trans, **kwd ):
+ def browse_valid_repositories( self, trans, **kwd ):
webapp = kwd.get( 'webapp', 'community' )
galaxy_url = kwd.get( 'galaxy_url', None )
if galaxy_url:
@@ -352,6 +345,7 @@
repository = get_repository( trans, repository_id )
return trans.response.send_redirect( web.url_for( controller='repository',
action='preview_tools_in_changeset',
+ webapp=webapp,
repository_id=repository_id,
changeset_revision=repository.tip ) )
# The changeset_revision_select_field in the RepositoryListGrid performs a refresh_on_change
@@ -371,16 +365,16 @@
webapp=webapp,
repository_id=trans.security.encode_id( repository.id ),
changeset_revision=v ) )
- url_args = dict( action='browse_downloadable_repositories',
+ url_args = dict( action='browse_valid_repositories',
operation='preview_tools_in_changeset',
webapp=webapp,
repository_id=repository_id )
- self.downloadable_repository_list_grid.operations = [ grids.GridOperation( "Preview and install",
- url_args=url_args,
- allow_multiple=False,
- async_compatible=False ) ]
+ self.valid_repository_list_grid.operations = [ grids.GridOperation( "Preview and install",
+ url_args=url_args,
+ allow_multiple=False,
+ async_compatible=False ) ]
# Render the list view
- return self.downloadable_repository_list_grid( trans, **kwd )
+ return self.valid_repository_list_grid( trans, **kwd )
@web.expose
def find_tools( self, trans, **kwd ):
params = util.Params( kwd )
@@ -391,38 +385,35 @@
if galaxy_url:
trans.set_cookie( galaxy_url, name='toolshedgalaxyurl' )
if 'operation' in kwd:
- operation = kwd[ 'operation' ].lower()
- is_admin = trans.user_is_admin()
- if operation == "view_or_manage_repository":
- # The received id is a RepositoryMetadata id, so we have to get the repository id.
- repository_metadata = get_repository_metadata_by_id( trans, kwd[ 'id' ] )
- repository_id = trans.security.encode_id( repository_metadata.repository.id )
- repository = get_repository( trans, repository_id )
- kwd[ 'id' ] = repository_id
- kwd[ 'changeset_revision' ] = repository_metadata.changeset_revision
- if webapp == 'community' and ( is_admin or repository.user == trans.user ):
- a = 'manage_repository'
- else:
- a = 'view_repository'
- return trans.response.send_redirect( web.url_for( controller='repository',
- action=a,
- **kwd ) )
- if operation == "install":
- repo_info_dict = {}
- galaxy_url = trans.get_cookie( name='toolshedgalaxyurl' )
- # TODO: support https in the following url.
- url = 'http://%s/admin/install_tool_shed_repository?tool_shed_url=%s&webapp=%s' % ( galaxy_url, trans.request.host, webapp )
- repository_metadata_ids = util.listify( kwd[ 'id' ] )
- for repository_metadata_id in repository_metadata_ids:
- repository_metadata = get_repository_metadata_by_id( trans, repository_metadata_id )
- repository = get_repository( trans, trans.security.encode_id( repository_metadata.repository_id ) )
- repository_id = trans.security.encode_id( repository.id )
- changeset_revision = repository_metadata.changeset_revision
- repository_clone_url = generate_clone_url( trans, repository_id )
- repo_info_dict[ repository.name ] = ( repository.description, repository_clone_url, changeset_revision )
- encoded_repo_info_dict = self.__encode( repo_info_dict )
- url += '&repo_info_dict=%s' % encoded_repo_info_dict
- return trans.response.send_redirect( url )
+ item_id = kwd.get( 'id', '' )
+ if item_id:
+ operation = kwd[ 'operation' ].lower()
+ is_admin = trans.user_is_admin()
+ if operation == "view_or_manage_repository":
+ # The received id is a RepositoryMetadata id, so we have to get the repository id.
+ repository_metadata = get_repository_metadata_by_id( trans, item_id )
+ repository_id = trans.security.encode_id( repository_metadata.repository.id )
+ repository = get_repository( trans, repository_id )
+ kwd[ 'id' ] = repository_id
+ kwd[ 'changeset_revision' ] = repository_metadata.changeset_revision
+ if webapp == 'community' and ( is_admin or repository.user == trans.user ):
+ a = 'manage_repository'
+ else:
+ a = 'view_repository'
+ return trans.response.send_redirect( web.url_for( controller='repository',
+ action=a,
+ **kwd ) )
+ if operation == "install":
+ galaxy_url = trans.get_cookie( name='toolshedgalaxyurl' )
+ encoded_repo_info_dict = self.__encode_repo_info_dict( trans, webapp, util.listify( item_id ) )
+ # TODO: support https in the following url.
+ url = 'http://%s/admin/install_tool_shed_repository?tool_shed_url=%s&webapp=%s&repo_info_dict=%s' % \
+ ( galaxy_url, trans.request.host, webapp, encoded_repo_info_dict )
+ return trans.response.send_redirect( url )
+ else:
+ # This can only occur when there is a multi-select grid with check boxes and an operation,
+ # and the user clicked the operation button without checking any of the check boxes.
+ return trans.show_error_message( "No items were selected." )
tool_ids = [ item.lower() for item in util.listify( kwd.get( 'tool_id', '' ) ) ]
tool_names = [ item.lower() for item in util.listify( kwd.get( 'tool_name', '' ) ) ]
tool_versions = [ item.lower() for item in util.listify( kwd.get( 'tool_version', '' ) ) ]
@@ -436,7 +427,12 @@
kwd[ 'match_tuples' ] = match_tuples
# Render the list view
if webapp == 'galaxy':
- # Our request originated from a Galaxy instance.
+ # Our initial request originated from a Galaxy instance.
+ global_actions = [ grids.GridAction( "Browse valid repositories",
+ dict( controller='repository', action='browse_valid_repositories', webapp=webapp ) ),
+ grids.GridAction( "Search for valid tools",
+ dict( controller='repository', action='find_tools', webapp=webapp ) ) ]
+ self.install_matched_repository_list_grid.global_actions = global_actions
install_url_args = dict( controller='repository', action='find_tools', webapp=webapp )
operations = [ grids.GridOperation( "Install", url_args=install_url_args, allow_multiple=True, async_compatible=False ) ]
self.install_matched_repository_list_grid.operations = operations
@@ -583,8 +579,21 @@
if self.__in_tool_dict( tool_dict, exact_matches_checked, tool_name=tool_name, tool_version=tool_version ):
match_tuples.append( ( repository_metadata.repository_id, repository_metadata.changeset_revision ) )
return match_tuples
- def __encode( self, repo_info_dict ):
- value = simplejson.dumps( repo_info_dict )
+ def __encode_repo_info_dict( self, trans, webapp, repository_metadata_ids ):
+ repo_info_dict = {}
+ for repository_metadata_id in repository_metadata_ids:
+ repository_metadata = get_repository_metadata_by_id( trans, repository_metadata_id )
+ repository = get_repository( trans, trans.security.encode_id( repository_metadata.repository_id ) )
+ repository_id = trans.security.encode_id( repository.id )
+ changeset_revision = repository_metadata.changeset_revision
+ repository_clone_url = generate_clone_url( trans, repository_id )
+ repo_info_dict[ repository.name ] = ( repository.description, repository_clone_url, changeset_revision )
+ return self.__encode( repo_info_dict )
+ def __encode( self, val ):
+ if isinstance( val, dict ):
+ value = simplejson.dumps( val )
+ else:
+ value = val
a = hmac_new( 'ToolShedAndGalaxyMustHaveThisSameKey', value )
b = binascii.hexlify( value )
return "%s:%s" % ( a, b )
@@ -620,14 +629,18 @@
params = util.Params( kwd )
message = util.restore_text( params.get( 'message', '' ) )
status = params.get( 'status', 'done' )
+ webapp = params.get( 'webapp', 'community' )
galaxy_url = trans.get_cookie( name='toolshedgalaxyurl' )
+ repository_clone_url = generate_clone_url( trans, repository_id )
repository = get_repository( trans, repository_id )
changeset_revision = util.restore_text( params.get( 'changeset_revision', repository.tip ) )
+ repo_info_dict = {}
+ repo_info_dict[ repository.name ] = ( repository.description, repository_clone_url, changeset_revision )
+ encoded_repo_info_dict = self.__encode( repo_info_dict )
# Redirect back to local Galaxy to perform install.
- repository_clone_url = generate_clone_url( trans, repository_id )
# TODO: support https in the following url.
- url = 'http://%s/admin/install_tool_shed_repository?tool_shed_url=%s&name=%s&description=%s&repository_clone_url=%s&changeset_revision=%s' % \
- ( galaxy_url, trans.request.host, repository.name, repository.description, repository_clone_url, changeset_revision )
+ url = 'http://%s/admin/install_tool_shed_repository?tool_shed_url=%s&repo_info_dict=%s' % \
+ ( galaxy_url, trans.request.host, encoded_repo_info_dict )
return trans.response.send_redirect( url )
@web.expose
def check_for_updates( self, trans, **kwd ):
diff -r 1d0bb560bd3d584708972001afd054774e9e89c5 -r 28ab7dde097298b7565a6238f0bbcade29a73ae9 templates/grid_base.mako
--- a/templates/grid_base.mako
+++ b/templates/grid_base.mako
@@ -777,6 +777,7 @@
show_item_checkboxes = True
%><form action="${url()}" method="post" onsubmit="return false;">
+ <input type="hidden" name="webapp" value="${webapp}"/><table id="grid-table" class="grid"><thead id="grid-table-header"><tr>
diff -r 1d0bb560bd3d584708972001afd054774e9e89c5 -r 28ab7dde097298b7565a6238f0bbcade29a73ae9 templates/webapps/community/repository/find_tools.mako
--- a/templates/webapps/community/repository/find_tools.mako
+++ b/templates/webapps/community/repository/find_tools.mako
@@ -10,6 +10,13 @@
%><%inherit file="${inherit(context)}"/>
+%if webapp == 'galaxy':
+ <br/><br/>
+ <ul class="manage-table-actions">
+ <li><a class="action-button" href="${h.url_for( controller='repository', action='browse_valid_repositories', webapp=webapp )}">Browse valid repositories</a></li>
+ </ul>
+%endif
+
%if message:
${render_msg( message, status )}
%endif
diff -r 1d0bb560bd3d584708972001afd054774e9e89c5 -r 28ab7dde097298b7565a6238f0bbcade29a73ae9 templates/webapps/community/repository/preview_tools_in_changeset.mako
--- a/templates/webapps/community/repository/preview_tools_in_changeset.mako
+++ b/templates/webapps/community/repository/preview_tools_in_changeset.mako
@@ -64,7 +64,12 @@
<br/><br/><ul class="manage-table-actions">
- <a class="action-button" href="${h.url_for( controller='repository', action='install_repository_revision', repository_id=trans.security.encode_id( repository.id ), webapp=webapp, changeset_revision=changeset_revision )}">Install to local Galaxy</a>
+ <li><a class="action-button" href="${h.url_for( controller='repository', action='install_repository_revision', repository_id=trans.security.encode_id( repository.id ), webapp=webapp, changeset_revision=changeset_revision )}">Install to local Galaxy</a></li>
+ <li><a class="action-button" id="repository-${repository.id}-popup" class="menubutton">Tool Shed Actions</a></li>
+ <div popupmenu="repository-${repository.id}-popup">
+ <a class="action-button" href="${h.url_for( controller='repository', action='browse_valid_repositories', webapp=webapp )}">Browse valid repositories</a>
+ <a class="action-button" href="${h.url_for( controller='repository', action='find_tools', webapp=webapp )}">Search for valid tools</a>
+ </div></ul>
%if message:
diff -r 1d0bb560bd3d584708972001afd054774e9e89c5 -r 28ab7dde097298b7565a6238f0bbcade29a73ae9 templates/webapps/community/repository/tool_form.mako
--- a/templates/webapps/community/repository/tool_form.mako
+++ b/templates/webapps/community/repository/tool_form.mako
@@ -111,7 +111,12 @@
<br/><br/><ul class="manage-table-actions">
%if webapp == 'galaxy':
- <a class="action-button" href="${h.url_for( controller='repository', action='install_repository_revision', repository_id=trans.security.encode_id( repository.id ), webapp=webapp, changeset_revision=changeset_revision )}">Install to local Galaxy</a>
+ <li><a class="action-button" href="${h.url_for( controller='repository', action='install_repository_revision', repository_id=trans.security.encode_id( repository.id ), webapp=webapp, changeset_revision=changeset_revision )}">Install to local Galaxy</a></li>
+ <li><a class="action-button" id="repository-${repository.id}-popup" class="menubutton">Tool Shed Actions</a></li>
+ <div popupmenu="repository-${repository.id}-popup">
+ <a class="action-button" href="${h.url_for( controller='repository', action='browse_valid_repositories', webapp=webapp )}">Browse valid repositories</a>
+ <a class="action-button" href="${h.url_for( controller='repository', action='find_tools', webapp=webapp )}">Search for valid tools</a>
+ </div>
%else:
%if is_new:
<a class="action-button" href="${h.url_for( controller='upload', action='upload', repository_id=trans.security.encode_id( repository.id ), webapp=webapp )}">Upload files to repository</a>
diff -r 1d0bb560bd3d584708972001afd054774e9e89c5 -r 28ab7dde097298b7565a6238f0bbcade29a73ae9 templates/webapps/community/repository/view_repository.mako
--- a/templates/webapps/community/repository/view_repository.mako
+++ b/templates/webapps/community/repository/view_repository.mako
@@ -94,7 +94,12 @@
</div>
%endif
%else:
- <a class="action-button" href="${h.url_for( controller='repository', action='install_repository_revision', repository_id=trans.security.encode_id( repository.id ), webapp=webapp, changeset_revision=changeset_revision )}">Install to local Galaxy</a>
+ <li><a class="action-button" href="${h.url_for( controller='repository', action='install_repository_revision', repository_id=trans.security.encode_id( repository.id ), webapp=webapp, changeset_revision=changeset_revision )}">Install to local Galaxy</a></li>
+ <li><a class="action-button" id="repository-${repository.id}-popup" class="menubutton">Tool Shed Actions</a></li>
+ <div popupmenu="repository-${repository.id}-popup">
+ <a class="action-button" href="${h.url_for( controller='repository', action='browse_valid_repositories', webapp=webapp )}">Browse valid repositories</a>
+ <a class="action-button" href="${h.url_for( controller='repository', action='find_tools', webapp=webapp )}">Search for valid tools</a>
+ </div>
%endif
</ul>
diff -r 1d0bb560bd3d584708972001afd054774e9e89c5 -r 28ab7dde097298b7565a6238f0bbcade29a73ae9 templates/webapps/community/repository/view_tool_metadata.mako
--- a/templates/webapps/community/repository/view_tool_metadata.mako
+++ b/templates/webapps/community/repository/view_tool_metadata.mako
@@ -34,7 +34,12 @@
<br/><br/><ul class="manage-table-actions">
%if webapp == 'galaxy':
- <a class="action-button" href="${h.url_for( controller='repository', action='install_repository_revision', repository_id=trans.security.encode_id( repository.id ), webapp=webapp, changeset_revision=changeset_revision )}">Install to local Galaxy</a>
+ <li><a class="action-button" href="${h.url_for( controller='repository', action='install_repository_revision', repository_id=trans.security.encode_id( repository.id ), webapp=webapp, changeset_revision=changeset_revision )}">Install to local Galaxy</a></li>
+ <li><a class="action-button" id="repository-${repository.id}-popup" class="menubutton">Tool Shed Actions</a></li>
+ <div popupmenu="repository-${repository.id}-popup">
+ <a class="action-button" href="${h.url_for( controller='repository', action='browse_valid_repositories', webapp=webapp )}">Browse valid repositories</a>
+ <a class="action-button" href="${h.url_for( controller='repository', action='find_tools', webapp=webapp )}">Search for valid tools</a>
+ </div>
%else:
%if is_new:
<a class="action-button" href="${h.url_for( controller='upload', action='upload', repository_id=trans.security.encode_id( repository.id ), webapp=webapp )}">Upload files to repository</a>
diff -r 1d0bb560bd3d584708972001afd054774e9e89c5 -r 28ab7dde097298b7565a6238f0bbcade29a73ae9 templates/webapps/galaxy/admin/tool_sheds.mako
--- a/templates/webapps/galaxy/admin/tool_sheds.mako
+++ b/templates/webapps/galaxy/admin/tool_sheds.mako
@@ -16,7 +16,7 @@
<div class="toolFormTitle">Accessible Galaxy tool sheds</div><div class="toolFormBody"><div class="form-row">
- <table cellspacing="0" cellpadding="0" border="0" width="100%" class="grid" id="library-grid">
+ <table class="grid"><% shed_id = 0 %>
%for name, url in trans.app.tool_shed_registry.tool_sheds.items():
<tr class="libraryTitle">
@@ -25,7 +25,7 @@
<a class="view-info" href="${h.url_for( controller='admin', action='browse_tool_shed', tool_shed_url=url )}">${name}</a></div><div popupmenu="dataset-${shed_id}-popup">
- <a class="action-button" href="${h.url_for( controller='admin', action='browse_tool_shed', tool_shed_url=url )}">Browse downloadable repositories</a>
+ <a class="action-button" href="${h.url_for( controller='admin', action='browse_tool_shed', tool_shed_url=url )}">Browse valid repositories</a><a class="action-button" href="${h.url_for( controller='admin', action='find_tools_in_tool_shed', tool_shed_url=url )}">Search for valid tools</a></div></td>
diff -r 1d0bb560bd3d584708972001afd054774e9e89c5 -r 28ab7dde097298b7565a6238f0bbcade29a73ae9 tools/filters/sff_extract.py
--- a/tools/filters/sff_extract.py
+++ b/tools/filters/sff_extract.py
@@ -27,7 +27,7 @@
__author__ = 'Jose Blanca and Bastien Chevreux'
__copyright__ = 'Copyright 2008, Jose Blanca, COMAV, and Bastien Chevreux'
__license__ = 'GPLv3 or later'
-__version__ = '0.2.8'
+__version__ = '0.2.10'
__email__ = 'jblanca(a)btc.upv.es'
__status__ = 'beta'
@@ -298,7 +298,8 @@
#we check that we're removing the asked tag
if tag is not None and tag != last_tag:
- raise RuntimeError("The given xml tag wasn't the last one in the file")
+ etxt=join('The given xml tag (',tag,') was not the last one in the file');
+ raise RuntimeError(etxt)
# while we are at it: also remove all white spaces in that line :-)
i -= 1
@@ -843,7 +844,7 @@
if len(boundaries) == 3:
# case: mask char on both sides of sequence
#print "bounds3"
- data['clip_adapter_left']=1+boundaries[0][1]
+ data['clip_adapter_left']=boundaries[0][1]
data['clip_adapter_right']=boundaries[2][0]
elif len(boundaries) == 2:
# case: mask char left or right of sequence
@@ -851,7 +852,7 @@
if maskedseq[0] == maskchar :
# case: mask char left
#print "left"
- data['clip_adapter_left']=1+boundaries[0][1]
+ data['clip_adapter_left']=boundaries[0][1]
else:
# case: mask char right
#print "right"
@@ -1192,7 +1193,11 @@
'''
left, right = return_merged_clips(data)
seq = data['bases']
- new_seq = ''.join((seq[:left-1].lower(), seq[left-1:right], seq[right:].lower()))
+ if left >= right:
+ new_seq = seq.lower()
+ else:
+ new_seq = ''.join((seq[:left-1].lower(), seq[left-1:right], seq[right:].lower()))
+
return new_seq
def clip_read(data):
@@ -1209,14 +1214,14 @@
-def tests_for_ssaha(linker_fname):
+def tests_for_ssaha():
'''Tests whether SSAHA2 can be successfully called.'''
try:
print "Testing whether SSAHA2 is installed and can be launched ... ",
sys.stdout.flush()
fh = open('/dev/null', 'w')
- retcode = subprocess.call(["ssaha2", "-v"], stdout = fh)
+ retcode = subprocess.call(["ssaha2"], stdout = fh)
fh.close()
print "ok."
except :
@@ -1247,6 +1252,8 @@
'''Launches SSAHA2 on the linker and query file, string SSAHA2 output
into the output filehandle'''
+ tests_for_ssaha()
+
try:
print "Searching linker sequences with SSAHA2 (this may take a while) ... ",
sys.stdout.flush()
diff -r 1d0bb560bd3d584708972001afd054774e9e89c5 -r 28ab7dde097298b7565a6238f0bbcade29a73ae9 tools/filters/sff_extractor.xml
--- a/tools/filters/sff_extractor.xml
+++ b/tools/filters/sff_extractor.xml
@@ -1,4 +1,4 @@
-<tool id="Sff_extractor" name="SFF converter" version="1.0.0">
+<tool id="Sff_extractor" name="SFF converter" version="1.0.1"><description></description><command interpreter="python">
#if str($fastq_output) == "fastq_false" #sff_extract.py $clip --seq_file=$out_file3 --qual_file=$out_file4 --xml_file=$out_file2 $input
diff -r 1d0bb560bd3d584708972001afd054774e9e89c5 -r 28ab7dde097298b7565a6238f0bbcade29a73ae9 tools/gatk/count_covariates.xml
--- a/tools/gatk/count_covariates.xml
+++ b/tools/gatk/count_covariates.xml
@@ -59,14 +59,16 @@
#end for
'
#end for
- #if str( $gatk_param_type.input_intervals ) != "None":
- -d "-L" "${gatk_param_type.input_intervals}" "${gatk_param_type.input_intervals.ext}" "input_intervals"
- #end if
- #if str( $gatk_param_type.input_exclude_intervals ) != "None":
- -d "-XL" "${gatk_param_type.input_exclude_intervals}" "${gatk_param_type.input_exclude_intervals.ext}" "input_intervals"
- #end if
+ #for $interval_count, $input_intervals in enumerate( $gatk_param_type.input_interval_repeat ):
+ -d "--intervals" "${input_intervals.input_intervals}" "${input_intervals.input_intervals.ext}" "input_intervals_${interval_count}"
+ #end for
+ #for $interval_count, $input_intervals in enumerate( $gatk_param_type.input_exclude_interval_repeat ):
+ -d "--excludeIntervals" "${input_intervals.input_exclude_intervals}" "${input_intervals.input_exclude_intervals.ext}" "input_exlude_intervals_${interval_count}"
+ #end for
+
-p '--BTI_merge_rule "${gatk_param_type.BTI_merge_rule}"'
+
-p '--downsampling_type "${gatk_param_type.downsampling_type.downsampling_type_selector}"'
#if str( $gatk_param_type.downsampling_type.downsampling_type_selector ) != "NONE":
-p '--${gatk_param_type.downsampling_type.downsample_to_type.downsample_to_type_selector} "${gatk_param_type.downsampling_type.downsample_to_type.downsample_to_value}"'
@@ -78,11 +80,18 @@
--defaultBaseQualities "${gatk_param_type.default_base_qualities}"
--validation_strictness "${gatk_param_type.validation_strictness}"
--interval_merging "${gatk_param_type.interval_merging}"
+ ${gatk_param_type.disable_experimental_low_memory_sharding}
+ ${gatk_param_type.non_deterministic_random_seed}
'
- #if str( $gatk_param_type.read_group_black_list ) != "None":
- -d "-read_group_black_list" "${gatk_param_type.read_group_black_list}" "txt" "input_read_group_black_list"
- #end if
+ #for $rg_black_list_count, $rg_black_list in enumerate( $gatk_param_type.read_group_black_list_repeat ):
+ #if $rg_black_list.read_group_black_list_type.read_group_black_list_type_selector == "file":
+ -d "--read_group_black_list" "${rg_black_list.read_group_black_list_type.read_group_black_list}" "txt" "input_read_group_black_list_${rg_black_list_count}"
+ #else
+ -p '--read_group_black_list "${rg_black_list.read_group_black_list_type.read_group_black_list}"'
+ #end if
+ #end for
#end if
+
#if str( $reference_source.reference_source_selector ) == "history":
-d "-R" "${reference_source.ref_file}" "${reference_source.ref_file.ext}" "gatk_input"
#end if
@@ -202,7 +211,7 @@
</when><when value="advanced"><repeat name="sample_metadata" title="Sample Metadata">
- <param name="sample_metadata_file" type="data" format="txt" label="Sample file(s) in JSON format" />
+ <param name="sample_metadata_file" type="data" format="txt" label="Sample file in JSON format" /></repeat><repeat name="read_filter" title="Read Filter"><conditional name="read_filter_type">
@@ -218,12 +227,18 @@
</when></conditional></repeat>
- <param name="input_intervals" type="data" format="picard_interval_list" optional="True" label="A list of genomic intervals over which to operate" />
- <param name="input_exclude_intervals" type="data" format="picard_interval_list" optional="True" label="A list of genomic intervals to exclude from processing" />
+ <repeat name="input_interval_repeat" title="Operate on Genomic intervals">
+ <param name="input_intervals" type="data" format="bed,gatk_interval,picard_interval_list" label="Genomic intervals" />
+ </repeat>
+ <repeat name="input_exclude_interval_repeat" title="Exclude Genomic intervals">
+ <param name="input_exclude_intervals" type="data" format="bed,gatk_interval,picard_interval_list" label="Genomic intervals" />
+ </repeat>
+
<param name="BTI_merge_rule" type="select" label="BTI merge rule"><option value="UNION" selected="True">UNION</option><option value="INTERSECTION">INTERSECTION</option></param>
+
<conditional name="downsampling_type"><param name="downsampling_type_selector" type="select" label="Type of reads downsampling to employ at a given locus" help="Downsampling Type"><option value="NONE" selected="True">NONE</option>
@@ -240,7 +255,7 @@
<option value="downsample_to_coverage">Downsample by Coverage</option></param><when value="downsample_to_fraction">
- <param name="downsample_to_value" type="float" label="Fraction [0.0-1.0] of reads to downsample to" value="0.1"/>
+ <param name="downsample_to_value" type="float" label="Fraction [0.0-1.0] of reads to downsample to" value="1" min="0" max="1"/></when><when value="downsample_to_coverage"><param name="downsample_to_value" type="integer" label="Coverage to downsample to at any given locus" value="0"/>
@@ -254,7 +269,7 @@
<option value="downsample_to_coverage">Downsample by Coverage</option></param><when value="downsample_to_fraction">
- <param name="downsample_to_value" type="float" label="Fraction [0.0-1.0] of reads to downsample to" value="0.1"/>
+ <param name="downsample_to_value" type="float" label="Fraction [0.0-1.0] of reads to downsample to" value="1" min="0" max="1"/></when><when value="downsample_to_coverage"><param name="downsample_to_value" type="integer" label="Coverage to downsample to at any given locus" value="0"/>
@@ -267,19 +282,38 @@
<option value="CALCULATE_AS_NECESSARY">CALCULATE_AS_NECESSARY</option><option value="RECALCULATE">RECALCULATE</option></param>
- <param name="baq_gap_open_penalty" type="integer" label="BAQ gap open penalty (Phred Scaled)" value="40" help="Default value is 40. 30 is perhaps better for whole genome call sets."/>
+ <param name="baq_gap_open_penalty" type="float" label="BAQ gap open penalty (Phred Scaled)" value="40" help="Default value is 40. 30 is perhaps better for whole genome call sets."/><param name="use_original_qualities" type="boolean" truevalue="--useOriginalQualities" falsevalue="" label="Use the original base quality scores from the OQ tag" /><param name="default_base_qualities" type="integer" label="Value to be used for all base quality scores, when some are missing" value="-1"/><param name="validation_strictness" type="select" label="How strict should we be with validation"><option value="STRICT" selected="True">STRICT</option><option value="LENIENT">LENIENT</option><option value="SILENT">SILENT</option>
+ <!-- <option value="DEFAULT_STRINGENCY">DEFAULT_STRINGENCY</option> listed in docs, but not valid value...--></param><param name="interval_merging" type="select" label="Interval merging rule"><option value="ALL" selected="True">ALL</option><option value="OVERLAPPING_ONLY">OVERLAPPING_ONLY</option></param>
- <param name="read_group_black_list" type="data" format="txt" optional="True" label="Read group black list" />
+
+ <repeat name="read_group_black_list_repeat" title="Read group black list">
+ <conditional name="read_group_black_list_type">
+ <param name="read_group_black_list_type_selector" type="select" label="Type of reads read group black list">
+ <option value="file" selected="True">Filters in file</option>
+ <option value="text">Specify filters as a string</option>
+ </param>
+ <when value="file">
+ <param name="read_group_black_list" type="data" format="txt" label="Read group black list file" />
+ </when>
+ <when value="text">
+ <param name="read_group_black_list" type="text" value="tag:string" label="Read group black list tag:string" />
+ </when>
+ </conditional>
+ </repeat>
+
+ <param name="disable_experimental_low_memory_sharding" type="boolean" truevalue="--disable_experimental_low_memory_sharding" falsevalue="" label="Disable experimental low-memory sharding functionality." checked="False"/>
+ <param name="non_deterministic_random_seed" type="boolean" truevalue="--nonDeterministicRandomSeed" falsevalue="" label="Makes the GATK behave non deterministically, that is, the random numbers generated will be different in every run" checked="False" />
+
</when></conditional>
diff -r 1d0bb560bd3d584708972001afd054774e9e89c5 -r 28ab7dde097298b7565a6238f0bbcade29a73ae9 tools/gatk/indel_realigner.xml
--- a/tools/gatk/indel_realigner.xml
+++ b/tools/gatk/indel_realigner.xml
@@ -165,7 +165,7 @@
</when><when value="advanced"><repeat name="sample_metadata" title="Sample Metadata">
- <param name="sample_metadata_file" type="data" format="txt" label="Sample file(s) in JSON format" />
+ <param name="sample_metadata_file" type="data" format="txt" label="Sample file in JSON format" /></repeat><repeat name="read_filter" title="Read Filter"><conditional name="read_filter_type">
@@ -181,12 +181,18 @@
</when></conditional></repeat>
- <param name="input_intervals" type="data" format="picard_interval_list" optional="True" label="A list of genomic intervals over which to operate" />
- <param name="input_exclude_intervals" type="data" format="picard_interval_list" optional="True" label="A list of genomic intervals to exclude from processing" />
+ <repeat name="input_interval_repeat" title="Operate on Genomic intervals">
+ <param name="input_intervals" type="data" format="bed,gatk_interval,picard_interval_list" label="Genomic intervals" />
+ </repeat>
+ <repeat name="input_exclude_interval_repeat" title="Exclude Genomic intervals">
+ <param name="input_exclude_intervals" type="data" format="bed,gatk_interval,picard_interval_list" label="Genomic intervals" />
+ </repeat>
+
<param name="BTI_merge_rule" type="select" label="BTI merge rule"><option value="UNION" selected="True">UNION</option><option value="INTERSECTION">INTERSECTION</option></param>
+
<conditional name="downsampling_type"><param name="downsampling_type_selector" type="select" label="Type of reads downsampling to employ at a given locus" help="Downsampling Type"><option value="NONE" selected="True">NONE</option>
@@ -203,7 +209,7 @@
<option value="downsample_to_coverage">Downsample by Coverage</option></param><when value="downsample_to_fraction">
- <param name="downsample_to_value" type="float" label="Fraction [0.0-1.0] of reads to downsample to" value="0.1"/>
+ <param name="downsample_to_value" type="float" label="Fraction [0.0-1.0] of reads to downsample to" value="1" min="0" max="1"/></when><when value="downsample_to_coverage"><param name="downsample_to_value" type="integer" label="Coverage to downsample to at any given locus" value="0"/>
@@ -217,7 +223,7 @@
<option value="downsample_to_coverage">Downsample by Coverage</option></param><when value="downsample_to_fraction">
- <param name="downsample_to_value" type="float" label="Fraction [0.0-1.0] of reads to downsample to" value="0.1"/>
+ <param name="downsample_to_value" type="float" label="Fraction [0.0-1.0] of reads to downsample to" value="1" min="0" max="1"/></when><when value="downsample_to_coverage"><param name="downsample_to_value" type="integer" label="Coverage to downsample to at any given locus" value="0"/>
@@ -230,19 +236,38 @@
<option value="CALCULATE_AS_NECESSARY">CALCULATE_AS_NECESSARY</option><option value="RECALCULATE">RECALCULATE</option></param>
- <param name="baq_gap_open_penalty" type="integer" label="BAQ gap open penalty (Phred Scaled)" value="40" help="Default value is 40. 30 is perhaps better for whole genome call sets."/>
+ <param name="baq_gap_open_penalty" type="float" label="BAQ gap open penalty (Phred Scaled)" value="40" help="Default value is 40. 30 is perhaps better for whole genome call sets."/><param name="use_original_qualities" type="boolean" truevalue="--useOriginalQualities" falsevalue="" label="Use the original base quality scores from the OQ tag" /><param name="default_base_qualities" type="integer" label="Value to be used for all base quality scores, when some are missing" value="-1"/><param name="validation_strictness" type="select" label="How strict should we be with validation"><option value="STRICT" selected="True">STRICT</option><option value="LENIENT">LENIENT</option><option value="SILENT">SILENT</option>
+ <!-- <option value="DEFAULT_STRINGENCY">DEFAULT_STRINGENCY</option> listed in docs, but not valid value...--></param><param name="interval_merging" type="select" label="Interval merging rule"><option value="ALL" selected="True">ALL</option><option value="OVERLAPPING_ONLY">OVERLAPPING_ONLY</option></param>
- <param name="read_group_black_list" type="data" format="txt" optional="True" label="Read group black list" />
+
+ <repeat name="read_group_black_list_repeat" title="Read group black list">
+ <conditional name="read_group_black_list_type">
+ <param name="read_group_black_list_type_selector" type="select" label="Type of reads read group black list">
+ <option value="file" selected="True">Filters in file</option>
+ <option value="text">Specify filters as a string</option>
+ </param>
+ <when value="file">
+ <param name="read_group_black_list" type="data" format="txt" label="Read group black list file" />
+ </when>
+ <when value="text">
+ <param name="read_group_black_list" type="text" value="tag:string" label="Read group black list tag:string" />
+ </when>
+ </conditional>
+ </repeat>
+
+ <param name="disable_experimental_low_memory_sharding" type="boolean" truevalue="--disable_experimental_low_memory_sharding" falsevalue="" label="Disable experimental low-memory sharding functionality." checked="False"/>
+ <param name="non_deterministic_random_seed" type="boolean" truevalue="--nonDeterministicRandomSeed" falsevalue="" label="Makes the GATK behave non deterministically, that is, the random numbers generated will be different in every run" checked="False" />
+
</when></conditional>
diff -r 1d0bb560bd3d584708972001afd054774e9e89c5 -r 28ab7dde097298b7565a6238f0bbcade29a73ae9 tools/gatk/realigner_target_creator.xml
--- a/tools/gatk/realigner_target_creator.xml
+++ b/tools/gatk/realigner_target_creator.xml
@@ -47,12 +47,13 @@
#end for
'
#end for
- #if str( $gatk_param_type.input_intervals ) != "None":
- -d "-L" "${gatk_param_type.input_intervals}" "${gatk_param_type.input_intervals.ext}" "input_intervals"
- #end if
- #if str( $gatk_param_type.input_exclude_intervals ) != "None":
- -d "-XL" "${gatk_param_type.input_exclude_intervals}" "${gatk_param_type.input_exclude_intervals.ext}" "input_intervals"
- #end if
+ #for $interval_count, $input_intervals in enumerate( $gatk_param_type.input_interval_repeat ):
+ -d "--intervals" "${input_intervals.input_intervals}" "${input_intervals.input_intervals.ext}" "input_intervals_${interval_count}"
+ #end for
+
+ #for $interval_count, $input_intervals in enumerate( $gatk_param_type.input_exclude_interval_repeat ):
+ -d "--excludeIntervals" "${input_intervals.input_exclude_intervals}" "${input_intervals.input_exclude_intervals.ext}" "input_exlude_intervals_${interval_count}"
+ #end for
-p '--BTI_merge_rule "${gatk_param_type.BTI_merge_rule}"'
@@ -67,11 +68,18 @@
--defaultBaseQualities "${gatk_param_type.default_base_qualities}"
--validation_strictness "${gatk_param_type.validation_strictness}"
--interval_merging "${gatk_param_type.interval_merging}"
+ ${gatk_param_type.disable_experimental_low_memory_sharding}
+ ${gatk_param_type.non_deterministic_random_seed}
'
- #if str( $gatk_param_type.read_group_black_list ) != "None":
- -d "-read_group_black_list" "${gatk_param_type.read_group_black_list}" "txt" "input_read_group_black_list"
- #end if
+ #for $rg_black_list_count, $rg_black_list in enumerate( $gatk_param_type.read_group_black_list_repeat ):
+ #if $rg_black_list.read_group_black_list_type.read_group_black_list_type_selector == "file":
+ -d "--read_group_black_list" "${rg_black_list.read_group_black_list_type.read_group_black_list}" "txt" "input_read_group_black_list_${rg_black_list_count}"
+ #else
+ -p '--read_group_black_list "${rg_black_list.read_group_black_list_type.read_group_black_list}"'
+ #end if
+ #end for
#end if
+
#if $reference_source.reference_source_selector == "history":
-d "-R" "${reference_source.ref_file}" "${reference_source.ref_file.ext}" "gatk_input"
#end if
@@ -151,7 +159,7 @@
</when><when value="advanced"><repeat name="sample_metadata" title="Sample Metadata">
- <param name="sample_metadata_file" type="data" format="txt" label="Sample file(s) in JSON format" />
+ <param name="sample_metadata_file" type="data" format="txt" label="Sample file in JSON format" /></repeat><repeat name="read_filter" title="Read Filter"><conditional name="read_filter_type">
@@ -167,8 +175,12 @@
</when></conditional></repeat>
- <param name="input_intervals" type="data" format="picard_interval_list" optional="True" label="A list of genomic intervals over which to operate" />
- <param name="input_exclude_intervals" type="data" format="picard_interval_list" optional="True" label="A list of genomic intervals to exclude from processing" />
+ <repeat name="input_interval_repeat" title="Operate on Genomic intervals">
+ <param name="input_intervals" type="data" format="bed,gatk_interval,picard_interval_list" label="Genomic intervals" />
+ </repeat>
+ <repeat name="input_exclude_interval_repeat" title="Exclude Genomic intervals">
+ <param name="input_exclude_intervals" type="data" format="bed,gatk_interval,picard_interval_list" label="Genomic intervals" />
+ </repeat><param name="BTI_merge_rule" type="select" label="BTI merge rule"><option value="UNION" selected="True">UNION</option>
@@ -191,7 +203,7 @@
<option value="downsample_to_coverage">Downsample by Coverage</option></param><when value="downsample_to_fraction">
- <param name="downsample_to_value" type="float" label="Fraction [0.0-1.0] of reads to downsample to" value="0.1"/>
+ <param name="downsample_to_value" type="float" label="Fraction [0.0-1.0] of reads to downsample to" value="1" min="0" max="1"/></when><when value="downsample_to_coverage"><param name="downsample_to_value" type="integer" label="Coverage to downsample to at any given locus" value="0"/>
@@ -205,7 +217,7 @@
<option value="downsample_to_coverage">Downsample by Coverage</option></param><when value="downsample_to_fraction">
- <param name="downsample_to_value" type="float" label="Fraction [0.0-1.0] of reads to downsample to" value="0.1"/>
+ <param name="downsample_to_value" type="float" label="Fraction [0.0-1.0] of reads to downsample to" value="1" min="0" max="1"/></when><when value="downsample_to_coverage"><param name="downsample_to_value" type="integer" label="Coverage to downsample to at any given locus" value="0"/>
@@ -218,19 +230,38 @@
<option value="CALCULATE_AS_NECESSARY">CALCULATE_AS_NECESSARY</option><option value="RECALCULATE">RECALCULATE</option></param>
- <param name="baq_gap_open_penalty" type="integer" label="BAQ gap open penalty (Phred Scaled)" value="40" help="Default value is 40. 30 is perhaps better for whole genome call sets."/>
+ <param name="baq_gap_open_penalty" type="float" label="BAQ gap open penalty (Phred Scaled)" value="40" help="Default value is 40. 30 is perhaps better for whole genome call sets."/><param name="use_original_qualities" type="boolean" truevalue="--useOriginalQualities" falsevalue="" label="Use the original base quality scores from the OQ tag" /><param name="default_base_qualities" type="integer" label="Value to be used for all base quality scores, when some are missing" value="-1"/><param name="validation_strictness" type="select" label="How strict should we be with validation"><option value="STRICT" selected="True">STRICT</option><option value="LENIENT">LENIENT</option><option value="SILENT">SILENT</option>
+ <!-- <option value="DEFAULT_STRINGENCY">DEFAULT_STRINGENCY</option> listed in docs, but not valid value...--></param><param name="interval_merging" type="select" label="Interval merging rule"><option value="ALL" selected="True">ALL</option><option value="OVERLAPPING_ONLY">OVERLAPPING_ONLY</option></param>
- <param name="read_group_black_list" type="data" format="txt" optional="True" label="Read group black list" />
+
+ <repeat name="read_group_black_list_repeat" title="Read group black list">
+ <conditional name="read_group_black_list_type">
+ <param name="read_group_black_list_type_selector" type="select" label="Type of reads read group black list">
+ <option value="file" selected="True">Filters in file</option>
+ <option value="text">Specify filters as a string</option>
+ </param>
+ <when value="file">
+ <param name="read_group_black_list" type="data" format="txt" label="Read group black list file" />
+ </when>
+ <when value="text">
+ <param name="read_group_black_list" type="text" value="tag:string" label="Read group black list tag:string" />
+ </when>
+ </conditional>
+ </repeat>
+
+ <param name="disable_experimental_low_memory_sharding" type="boolean" truevalue="--disable_experimental_low_memory_sharding" falsevalue="" label="Disable experimental low-memory sharding functionality." checked="False"/>
+ <param name="non_deterministic_random_seed" type="boolean" truevalue="--nonDeterministicRandomSeed" falsevalue="" label="Makes the GATK behave non deterministically, that is, the random numbers generated will be different in every run" checked="False" />
+
</when></conditional>
diff -r 1d0bb560bd3d584708972001afd054774e9e89c5 -r 28ab7dde097298b7565a6238f0bbcade29a73ae9 tools/gatk/table_recalibration.xml
--- a/tools/gatk/table_recalibration.xml
+++ b/tools/gatk/table_recalibration.xml
@@ -35,29 +35,16 @@
#end for
'
#end for
- #if str( $gatk_param_type.input_intervals ) != "None":
- -d "-L" "${gatk_param_type.input_intervals}" "${gatk_param_type.input_intervals.ext}" "input_intervals"
- #end if
- #if str( $gatk_param_type.input_exclude_intervals ) != "None":
- -d "-XL" "${gatk_param_type.input_exclude_intervals}" "${gatk_param_type.input_exclude_intervals.ext}" "input_intervals"
- #end if
- #set $rod_binding_names = dict()
- #for $rod_binding in $gatk_param_type.rod_bind:
- #if str( $rod_binding.rod_bind_type.rod_bind_type_selector ) == 'custom':
- #set $rod_bind_name = $rod_binding.rod_bind_type.custom_rod_name
- #else
- #set $rod_bind_name = $rod_binding.rod_bind_type.rod_bind_type_selector
- #end if
- #set $rod_binding_names[$rod_bind_name] = $rod_binding_names.get( $rod_bind_name, -1 ) + 1
- -d "-B:${rod_bind_name},%(file_type)s" "${rod_binding.rod_bind_type.input_rod}" "${rod_binding.rod_bind_type.input_rod.ext}" "input_${rod_bind_name}_${rod_binding_names[$rod_bind_name]}"
- #if str( $rod_binding.rod_bind_type.rodToIntervalTrackName ):
- -p '--rodToIntervalTrackName "${rod_bind_name}"'
- #end if
+ #for $interval_count, $input_intervals in enumerate( $gatk_param_type.input_interval_repeat ):
+ -d "--intervals" "${input_intervals.input_intervals}" "${input_intervals.input_intervals.ext}" "input_intervals_${interval_count}"
#end for
+
+ #for $interval_count, $input_intervals in enumerate( $gatk_param_type.input_exclude_interval_repeat ):
+ -d "--excludeIntervals" "${input_intervals.input_exclude_intervals}" "${input_intervals.input_exclude_intervals.ext}" "input_exlude_intervals_${interval_count}"
+ #end for
+
-p '--BTI_merge_rule "${gatk_param_type.BTI_merge_rule}"'
- #if str( $gatk_param_type.input_dbsnp_rod ) != "None":
- -d "-D" "${gatk_param_type.input_dbsnp_rod}" "${gatk_param_type.input_dbsnp_rod.ext}" "dbsnp_rod"
- #end if
+
-p '--downsampling_type "${gatk_param_type.downsampling_type.downsampling_type_selector}"'
#if str( $gatk_param_type.downsampling_type.downsampling_type_selector ) != "NONE":
-p '--${gatk_param_type.downsampling_type.downsample_to_type.downsample_to_type_selector} "${gatk_param_type.downsampling_type.downsample_to_type.downsample_to_value}"'
@@ -69,11 +56,18 @@
--defaultBaseQualities "${gatk_param_type.default_base_qualities}"
--validation_strictness "${gatk_param_type.validation_strictness}"
--interval_merging "${gatk_param_type.interval_merging}"
+ ${gatk_param_type.disable_experimental_low_memory_sharding}
+ ${gatk_param_type.non_deterministic_random_seed}
'
- #if str( $gatk_param_type.read_group_black_list ) != "None":
- -d "-read_group_black_list" "${gatk_param_type.read_group_black_list}" "txt" "input_read_group_black_list"
- #end if
+ #for $rg_black_list_count, $rg_black_list in enumerate( $gatk_param_type.read_group_black_list_repeat ):
+ #if $rg_black_list.read_group_black_list_type.read_group_black_list_type_selector == "file":
+ -d "--read_group_black_list" "${rg_black_list.read_group_black_list_type.read_group_black_list}" "txt" "input_read_group_black_list_${rg_black_list_count}"
+ #else
+ -p '--read_group_black_list "${rg_black_list.read_group_black_list_type.read_group_black_list}"'
+ #end if
+ #end for
#end if
+
#if str( $reference_source.reference_source_selector ) == "history":
-d "-R" "${reference_source.ref_file}" "${reference_source.ref_file.ext}" "gatk_input"
#end if
@@ -147,7 +141,7 @@
</when><when value="advanced"><repeat name="sample_metadata" title="Sample Metadata">
- <param name="sample_metadata_file" type="data" format="txt" label="Sample file(s) in JSON format" />
+ <param name="sample_metadata_file" type="data" format="txt" label="Sample file in JSON format" /></repeat><repeat name="read_filter" title="Read Filter"><conditional name="read_filter_type">
@@ -163,35 +157,18 @@
</when></conditional></repeat>
- <param name="input_intervals" type="data" format="picard_interval_list" optional="True" label="A list of genomic intervals over which to operate" />
- <param name="input_exclude_intervals" type="data" format="picard_interval_list" optional="True" label="A list of genomic intervals to exclude from processing" />
- <repeat name="rod_bind" title="Binding for reference-ordered data">
- <conditional name="rod_bind_type">
- <param name="rod_bind_type_selector" type="select" label="Binding Type">
- <option value="snps" selected="True">SNPs</option>
- <option value="indels">INDELs</option>
- <option value="custom">Custom</option>
- </param>
- <when value="snps">
- <param name="input_rod" type="data" format="vcf,gatk_dbsnp,bed" label="ROD file" />
- <param name="rodToIntervalTrackName" type="boolean" truevalue="--rodToIntervalTrackName" falsevalue="" label="Use ROD as interval List (-BTI, --rodToIntervalTrackName)" help="Only one ROD may have this option specified" />
- </when>
- <when value="indels">
- <param name="input_rod" type="data" format="vcf,gatk_dbsnp,bed" label="ROD file" />
- <param name="rodToIntervalTrackName" type="boolean" truevalue="--rodToIntervalTrackName" falsevalue="" label="Use ROD as interval List (-BTI, --rodToIntervalTrackName)" help="Only one ROD may have this option specified" />
- </when>
- <when value="custom">
- <param name="custom_rod_name" type="text" value="Unknown" label="ROD Name"/>
- <param name="input_rod" type="data" format="vcf,gatk_dbsnp,bed" label="ROD file" />
- <param name="rodToIntervalTrackName" type="boolean" truevalue="--rodToIntervalTrackName" falsevalue="" label="Use ROD as interval List (-BTI, --rodToIntervalTrackName)" help="Only one ROD may have this option specified" />
- </when>
- </conditional>
+ <repeat name="input_interval_repeat" title="Operate on Genomic intervals">
+ <param name="input_intervals" type="data" format="bed,gatk_interval,picard_interval_list" label="Genomic intervals" /></repeat>
+ <repeat name="input_exclude_interval_repeat" title="Exclude Genomic intervals">
+ <param name="input_exclude_intervals" type="data" format="bed,gatk_interval,picard_interval_list" label="Genomic intervals" />
+ </repeat>
+
<param name="BTI_merge_rule" type="select" label="BTI merge rule"><option value="UNION" selected="True">UNION</option><option value="INTERSECTION">INTERSECTION</option></param>
- <param name="input_dbsnp_rod" type="data" format="gatk_dbsnp" optional="True" label="dbSNP reference ordered data (ROD)" />
+
<conditional name="downsampling_type"><param name="downsampling_type_selector" type="select" label="Type of reads downsampling to employ at a given locus" help="Downsampling Type"><option value="NONE" selected="True">NONE</option>
@@ -208,7 +185,7 @@
<option value="downsample_to_coverage">Downsample by Coverage</option></param><when value="downsample_to_fraction">
- <param name="downsample_to_value" type="float" label="Fraction [0.0-1.0] of reads to downsample to" value="0.1"/>
+ <param name="downsample_to_value" type="float" label="Fraction [0.0-1.0] of reads to downsample to" value="1" min="0" max="1"/></when><when value="downsample_to_coverage"><param name="downsample_to_value" type="integer" label="Coverage to downsample to at any given locus" value="0"/>
@@ -222,7 +199,7 @@
<option value="downsample_to_coverage">Downsample by Coverage</option></param><when value="downsample_to_fraction">
- <param name="downsample_to_value" type="float" label="Fraction [0.0-1.0] of reads to downsample to" value="0.1"/>
+ <param name="downsample_to_value" type="float" label="Fraction [0.0-1.0] of reads to downsample to" value="1" min="0" max="1"/></when><when value="downsample_to_coverage"><param name="downsample_to_value" type="integer" label="Coverage to downsample to at any given locus" value="0"/>
@@ -235,19 +212,38 @@
<option value="CALCULATE_AS_NECESSARY">CALCULATE_AS_NECESSARY</option><option value="RECALCULATE">RECALCULATE</option></param>
- <param name="baq_gap_open_penalty" type="integer" label="BAQ gap open penalty (Phred Scaled)" value="40" help="Default value is 40. 30 is perhaps better for whole genome call sets."/>
+ <param name="baq_gap_open_penalty" type="float" label="BAQ gap open penalty (Phred Scaled)" value="40" help="Default value is 40. 30 is perhaps better for whole genome call sets."/><param name="use_original_qualities" type="boolean" truevalue="--useOriginalQualities" falsevalue="" label="Use the original base quality scores from the OQ tag" /><param name="default_base_qualities" type="integer" label="Value to be used for all base quality scores, when some are missing" value="-1"/><param name="validation_strictness" type="select" label="How strict should we be with validation"><option value="STRICT" selected="True">STRICT</option><option value="LENIENT">LENIENT</option><option value="SILENT">SILENT</option>
+ <!-- <option value="DEFAULT_STRINGENCY">DEFAULT_STRINGENCY</option> listed in docs, but not valid value...--></param><param name="interval_merging" type="select" label="Interval merging rule"><option value="ALL" selected="True">ALL</option><option value="OVERLAPPING_ONLY">OVERLAPPING_ONLY</option></param>
- <param name="read_group_black_list" type="data" format="txt" optional="True" label="Read group black list" />
+
+ <repeat name="read_group_black_list_repeat" title="Read group black list">
+ <conditional name="read_group_black_list_type">
+ <param name="read_group_black_list_type_selector" type="select" label="Type of reads read group black list">
+ <option value="file" selected="True">Filters in file</option>
+ <option value="text">Specify filters as a string</option>
+ </param>
+ <when value="file">
+ <param name="read_group_black_list" type="data" format="txt" label="Read group black list file" />
+ </when>
+ <when value="text">
+ <param name="read_group_black_list" type="text" value="tag:string" label="Read group black list tag:string" />
+ </when>
+ </conditional>
+ </repeat>
+
+ <param name="disable_experimental_low_memory_sharding" type="boolean" truevalue="--disable_experimental_low_memory_sharding" falsevalue="" label="Disable experimental low-memory sharding functionality." checked="False"/>
+ <param name="non_deterministic_random_seed" type="boolean" truevalue="--nonDeterministicRandomSeed" falsevalue="" label="Makes the GATK behave non deterministically, that is, the random numbers generated will be different in every run" checked="False" />
+
</when></conditional>
diff -r 1d0bb560bd3d584708972001afd054774e9e89c5 -r 28ab7dde097298b7565a6238f0bbcade29a73ae9 tools/gatk/unified_genotyper.xml
--- a/tools/gatk/unified_genotyper.xml
+++ b/tools/gatk/unified_genotyper.xml
@@ -56,12 +56,13 @@
#end for
'
#end for
- #if str( $gatk_param_type.input_intervals ) != "None":
- -d "-L" "${gatk_param_type.input_intervals}" "${gatk_param_type.input_intervals.ext}" "input_intervals"
- #end if
- #if str( $gatk_param_type.input_exclude_intervals ) != "None":
- -d "-XL" "${gatk_param_type.input_exclude_intervals}" "${gatk_param_type.input_exclude_intervals.ext}" "input_intervals"
- #end if
+ #for $interval_count, $input_intervals in enumerate( $gatk_param_type.input_interval_repeat ):
+ -d "--intervals" "${input_intervals.input_intervals}" "${input_intervals.input_intervals.ext}" "input_intervals_${interval_count}"
+ #end for
+
+ #for $interval_count, $input_intervals in enumerate( $gatk_param_type.input_exclude_interval_repeat ):
+ -d "--excludeIntervals" "${input_intervals.input_exclude_intervals}" "${input_intervals.input_exclude_intervals.ext}" "input_exlude_intervals_${interval_count}"
+ #end for
-p '--BTI_merge_rule "${gatk_param_type.BTI_merge_rule}"'
@@ -76,11 +77,18 @@
--defaultBaseQualities "${gatk_param_type.default_base_qualities}"
--validation_strictness "${gatk_param_type.validation_strictness}"
--interval_merging "${gatk_param_type.interval_merging}"
+ ${gatk_param_type.disable_experimental_low_memory_sharding}
+ ${gatk_param_type.non_deterministic_random_seed}
'
- #if str( $gatk_param_type.read_group_black_list ) != "None":
- -d "-read_group_black_list" "${gatk_param_type.read_group_black_list}" "txt" "input_read_group_black_list"
- #end if
+ #for $rg_black_list_count, $rg_black_list in enumerate( $gatk_param_type.read_group_black_list_repeat ):
+ #if $rg_black_list.read_group_black_list_type.read_group_black_list_type_selector == "file":
+ -d "--read_group_black_list" "${rg_black_list.read_group_black_list_type.read_group_black_list}" "txt" "input_read_group_black_list_${rg_black_list_count}"
+ #else
+ -p '--read_group_black_list "${rg_black_list.read_group_black_list_type.read_group_black_list}"'
+ #end if
+ #end for
#end if
+
#if $reference_source.reference_source_selector == "history":
-d "-R" "${reference_source.ref_file}" "${reference_source.ref_file.ext}" "gatk_input"
#end if
@@ -194,7 +202,7 @@
</when><when value="advanced"><repeat name="sample_metadata" title="Sample Metadata">
- <param name="sample_metadata_file" type="data" format="txt" label="Sample file(s) in JSON format" />
+ <param name="sample_metadata_file" type="data" format="txt" label="Sample file in JSON format" /></repeat><repeat name="read_filter" title="Read Filter"><conditional name="read_filter_type">
@@ -210,8 +218,12 @@
</when></conditional></repeat>
- <param name="input_intervals" type="data" format="picard_interval_list" optional="True" label="A list of genomic intervals over which to operate" />
- <param name="input_exclude_intervals" type="data" format="picard_interval_list" optional="True" label="A list of genomic intervals to exclude from processing" />
+ <repeat name="input_interval_repeat" title="Operate on Genomic intervals">
+ <param name="input_intervals" type="data" format="bed,gatk_interval,picard_interval_list" label="Genomic intervals" />
+ </repeat>
+ <repeat name="input_exclude_interval_repeat" title="Exclude Genomic intervals">
+ <param name="input_exclude_intervals" type="data" format="bed,gatk_interval,picard_interval_list" label="Genomic intervals" />
+ </repeat><param name="BTI_merge_rule" type="select" label="BTI merge rule"><option value="UNION" selected="True">UNION</option>
@@ -234,7 +246,7 @@
<option value="downsample_to_coverage">Downsample by Coverage</option></param><when value="downsample_to_fraction">
- <param name="downsample_to_value" type="float" label="Fraction [0.0-1.0] of reads to downsample to" value="0.1"/>
+ <param name="downsample_to_value" type="float" label="Fraction [0.0-1.0] of reads to downsample to" value="1" min="0" max="1"/></when><when value="downsample_to_coverage"><param name="downsample_to_value" type="integer" label="Coverage to downsample to at any given locus" value="0"/>
@@ -248,7 +260,7 @@
<option value="downsample_to_coverage">Downsample by Coverage</option></param><when value="downsample_to_fraction">
- <param name="downsample_to_value" type="float" label="Fraction [0.0-1.0] of reads to downsample to" value="0.1"/>
+ <param name="downsample_to_value" type="float" label="Fraction [0.0-1.0] of reads to downsample to" value="1" min="0" max="1"/></when><when value="downsample_to_coverage"><param name="downsample_to_value" type="integer" label="Coverage to downsample to at any given locus" value="0"/>
@@ -261,19 +273,38 @@
<option value="CALCULATE_AS_NECESSARY">CALCULATE_AS_NECESSARY</option><option value="RECALCULATE">RECALCULATE</option></param>
- <param name="baq_gap_open_penalty" type="integer" label="BAQ gap open penalty (Phred Scaled)" value="40" help="Default value is 40. 30 is perhaps better for whole genome call sets."/>
+ <param name="baq_gap_open_penalty" type="float" label="BAQ gap open penalty (Phred Scaled)" value="40" help="Default value is 40. 30 is perhaps better for whole genome call sets."/><param name="use_original_qualities" type="boolean" truevalue="--useOriginalQualities" falsevalue="" label="Use the original base quality scores from the OQ tag" /><param name="default_base_qualities" type="integer" label="Value to be used for all base quality scores, when some are missing" value="-1"/><param name="validation_strictness" type="select" label="How strict should we be with validation"><option value="STRICT" selected="True">STRICT</option><option value="LENIENT">LENIENT</option><option value="SILENT">SILENT</option>
+ <!-- <option value="DEFAULT_STRINGENCY">DEFAULT_STRINGENCY</option> listed in docs, but not valid value...--></param><param name="interval_merging" type="select" label="Interval merging rule"><option value="ALL" selected="True">ALL</option><option value="OVERLAPPING_ONLY">OVERLAPPING_ONLY</option></param>
- <param name="read_group_black_list" type="data" format="txt" optional="True" label="Read group black list" />
+
+ <repeat name="read_group_black_list_repeat" title="Read group black list">
+ <conditional name="read_group_black_list_type">
+ <param name="read_group_black_list_type_selector" type="select" label="Type of reads read group black list">
+ <option value="file" selected="True">Filters in file</option>
+ <option value="text">Specify filters as a string</option>
+ </param>
+ <when value="file">
+ <param name="read_group_black_list" type="data" format="txt" label="Read group black list file" />
+ </when>
+ <when value="text">
+ <param name="read_group_black_list" type="text" value="tag:string" label="Read group black list tag:string" />
+ </when>
+ </conditional>
+ </repeat>
+
+ <param name="disable_experimental_low_memory_sharding" type="boolean" truevalue="--disable_experimental_low_memory_sharding" falsevalue="" label="Disable experimental low-memory sharding functionality." checked="False"/>
+ <param name="non_deterministic_random_seed" type="boolean" truevalue="--nonDeterministicRandomSeed" falsevalue="" label="Makes the GATK behave non deterministically, that is, the random numbers generated will be different in every run" checked="False" />
+
</when></conditional>
diff -r 1d0bb560bd3d584708972001afd054774e9e89c5 -r 28ab7dde097298b7565a6238f0bbcade29a73ae9 tools/gatk/variant_annotator.xml
--- a/tools/gatk/variant_annotator.xml
+++ b/tools/gatk/variant_annotator.xml
@@ -89,14 +89,16 @@
#end for
'
#end for
- #if str( $gatk_param_type.input_intervals ) != "None":
- -d "-L" "${gatk_param_type.input_intervals}" "${gatk_param_type.input_intervals.ext}" "input_intervals"
- #end if
- #if str( $gatk_param_type.input_exclude_intervals ) != "None":
- -d "-XL" "${gatk_param_type.input_exclude_intervals}" "${gatk_param_type.input_exclude_intervals.ext}" "input_intervals"
- #end if
+ #for $interval_count, $input_intervals in enumerate( $gatk_param_type.input_interval_repeat ):
+ -d "--intervals" "${input_intervals.input_intervals}" "${input_intervals.input_intervals.ext}" "input_intervals_${interval_count}"
+ #end for
+ #for $interval_count, $input_intervals in enumerate( $gatk_param_type.input_exclude_interval_repeat ):
+ -d "--excludeIntervals" "${input_intervals.input_exclude_intervals}" "${input_intervals.input_exclude_intervals.ext}" "input_exlude_intervals_${interval_count}"
+ #end for
+
-p '--BTI_merge_rule "${gatk_param_type.BTI_merge_rule}"'
+
-p '--downsampling_type "${gatk_param_type.downsampling_type.downsampling_type_selector}"'
#if str( $gatk_param_type.downsampling_type.downsampling_type_selector ) != "NONE":
-p '--${gatk_param_type.downsampling_type.downsample_to_type.downsample_to_type_selector} "${gatk_param_type.downsampling_type.downsample_to_type.downsample_to_value}"'
@@ -108,10 +110,16 @@
--defaultBaseQualities "${gatk_param_type.default_base_qualities}"
--validation_strictness "${gatk_param_type.validation_strictness}"
--interval_merging "${gatk_param_type.interval_merging}"
+ ${gatk_param_type.disable_experimental_low_memory_sharding}
+ ${gatk_param_type.non_deterministic_random_seed}
'
- #if str( $gatk_param_type.read_group_black_list ) != "None":
- -d "-read_group_black_list" "${gatk_param_type.read_group_black_list}" "txt" "input_read_group_black_list"
- #end if
+ #for $rg_black_list_count, $rg_black_list in enumerate( $gatk_param_type.read_group_black_list_repeat ):
+ #if $rg_black_list.read_group_black_list_type.read_group_black_list_type_selector == "file":
+ -d "--read_group_black_list" "${rg_black_list.read_group_black_list_type.read_group_black_list}" "txt" "input_read_group_black_list_${rg_black_list_count}"
+ #else
+ -p '--read_group_black_list "${rg_black_list.read_group_black_list_type.read_group_black_list}"'
+ #end if
+ #end for
#end if
#if str( $reference_source.reference_source_selector ) == "history":
-d "-R" "${reference_source.ref_file}" "${reference_source.ref_file.ext}" "gatk_input"
@@ -252,28 +260,34 @@
</when><when value="advanced"><repeat name="sample_metadata" title="Sample Metadata">
- <param name="sample_metadata_file" type="data" format="txt" label="Sample file(s) in JSON format" />
+ <param name="sample_metadata_file" type="data" format="txt" label="Sample file in JSON format" /></repeat><repeat name="read_filter" title="Read Filter"><conditional name="read_filter_type">
- <param name="read_filter_type_selector" type="select" label="Read Filter Type">
- <option value="MaxReadLength" selected="True">MaxReadLength</option>
- <option value="ZeroMappingQualityRead">ZeroMappingQualityRead</option>
- </param>
- <when value="ZeroMappingQualityRead">
- <!-- no extra options -->
- </when>
- <when value="MaxReadLength">
- <param name="maxReadLength" type="integer" value="76" label="Max Read Length"/>
- </when>
+ <param name="read_filter_type_selector" type="select" label="Read Filter Type">
+ <option value="MaxReadLength" selected="True">MaxReadLength</option>
+ <option value="ZeroMappingQualityRead">ZeroMappingQualityRead</option>
+ </param>
+ <when value="ZeroMappingQualityRead">
+ <!-- no extra options -->
+ </when>
+ <when value="MaxReadLength">
+ <param name="maxReadLength" type="integer" value="76" label="Max Read Length"/>
+ </when></conditional></repeat>
- <param name="input_intervals" type="data" format="picard_interval_list" optional="True" label="A list of genomic intervals over which to operate" />
- <param name="input_exclude_intervals" type="data" format="picard_interval_list" optional="True" label="A list of genomic intervals to exclude from processing" />
+ <repeat name="input_interval_repeat" title="Operate on Genomic intervals">
+ <param name="input_intervals" type="data" format="bed,gatk_interval,picard_interval_list" label="Genomic intervals" />
+ </repeat>
+ <repeat name="input_exclude_interval_repeat" title="Exclude Genomic intervals">
+ <param name="input_exclude_intervals" type="data" format="bed,gatk_interval,picard_interval_list" label="Genomic intervals" />
+ </repeat>
+
<param name="BTI_merge_rule" type="select" label="BTI merge rule"><option value="UNION" selected="True">UNION</option><option value="INTERSECTION">INTERSECTION</option></param>
+
<conditional name="downsampling_type"><param name="downsampling_type_selector" type="select" label="Type of reads downsampling to employ at a given locus" help="Downsampling Type"><option value="NONE" selected="True">NONE</option>
@@ -281,55 +295,74 @@
<option value="BY_SAMPLE">BY_SAMPLE</option></param><when value="NONE">
- <!-- no more options here -->
- </when>
+ <!-- no more options here -->
+ </when><when value="ALL_READS">
- <conditional name="downsample_to_type">
- <param name="downsample_to_type_selector" type="select" label="Type of reads downsampling to employ at a given locus" help="Downsampling Type">
- <option value="downsample_to_fraction" selected="True">Downsample by Fraction</option>
- <option value="downsample_to_coverage">Downsample by Coverage</option>
- </param>
- <when value="downsample_to_fraction">
- <param name="downsample_to_value" type="float" label="Fraction [0.0-1.0] of reads to downsample to" value="0.1"/>
- </when>
- <when value="downsample_to_coverage">
- <param name="downsample_to_value" type="integer" label="Coverage to downsample to at any given locus" value="0"/>
- </when>
- </conditional>
- </when>
+ <conditional name="downsample_to_type">
+ <param name="downsample_to_type_selector" type="select" label="Type of reads downsampling to employ at a given locus" help="Downsampling Type">
+ <option value="downsample_to_fraction" selected="True">Downsample by Fraction</option>
+ <option value="downsample_to_coverage">Downsample by Coverage</option>
+ </param>
+ <when value="downsample_to_fraction">
+ <param name="downsample_to_value" type="float" label="Fraction [0.0-1.0] of reads to downsample to" value="1" min="0" max="1"/>
+ </when>
+ <when value="downsample_to_coverage">
+ <param name="downsample_to_value" type="integer" label="Coverage to downsample to at any given locus" value="0"/>
+ </when>
+ </conditional>
+ </when><when value="BY_SAMPLE">
- <conditional name="downsample_to_type">
- <param name="downsample_to_type_selector" type="select" label="Type of reads downsampling to employ at a given locus" help="Downsampling Type">
- <option value="downsample_to_fraction" selected="True">Downsample by Fraction</option>
- <option value="downsample_to_coverage">Downsample by Coverage</option>
- </param>
- <when value="downsample_to_fraction">
- <param name="downsample_to_value" type="float" label="Fraction [0.0-1.0] of reads to downsample to" value="0.1"/>
- </when>
- <when value="downsample_to_coverage">
- <param name="downsample_to_value" type="integer" label="Coverage to downsample to at any given locus" value="0"/>
- </when>
- </conditional>
- </when>
+ <conditional name="downsample_to_type">
+ <param name="downsample_to_type_selector" type="select" label="Type of reads downsampling to employ at a given locus" help="Downsampling Type">
+ <option value="downsample_to_fraction" selected="True">Downsample by Fraction</option>
+ <option value="downsample_to_coverage">Downsample by Coverage</option>
+ </param>
+ <when value="downsample_to_fraction">
+ <param name="downsample_to_value" type="float" label="Fraction [0.0-1.0] of reads to downsample to" value="1" min="0" max="1"/>
+ </when>
+ <when value="downsample_to_coverage">
+ <param name="downsample_to_value" type="integer" label="Coverage to downsample to at any given locus" value="0"/>
+ </when>
+ </conditional>
+ </when></conditional><param name="baq" type="select" label="Type of BAQ calculation to apply in the engine"><option value="OFF" selected="True">OFF</option><option value="CALCULATE_AS_NECESSARY">CALCULATE_AS_NECESSARY</option><option value="RECALCULATE">RECALCULATE</option></param>
- <param name="baq_gap_open_penalty" type="integer" label="BAQ gap open penalty (Phred Scaled)" value="40" help="Default value is 40. 30 is perhaps better for whole genome call sets."/>
+ <param name="baq_gap_open_penalty" type="float" label="BAQ gap open penalty (Phred Scaled)" value="40" help="Default value is 40. 30 is perhaps better for whole genome call sets."/><param name="use_original_qualities" type="boolean" truevalue="--useOriginalQualities" falsevalue="" label="Use the original base quality scores from the OQ tag" /><param name="default_base_qualities" type="integer" label="Value to be used for all base quality scores, when some are missing" value="-1"/><param name="validation_strictness" type="select" label="How strict should we be with validation"><option value="STRICT" selected="True">STRICT</option><option value="LENIENT">LENIENT</option><option value="SILENT">SILENT</option>
+ <!-- <option value="DEFAULT_STRINGENCY">DEFAULT_STRINGENCY</option> listed in docs, but not valid value...--></param><param name="interval_merging" type="select" label="Interval merging rule"><option value="ALL" selected="True">ALL</option><option value="OVERLAPPING_ONLY">OVERLAPPING_ONLY</option></param>
- <param name="read_group_black_list" type="data" format="txt" optional="True" label="Read group black list" />
+
+ <repeat name="read_group_black_list_repeat" title="Read group black list">
+ <conditional name="read_group_black_list_type">
+ <param name="read_group_black_list_type_selector" type="select" label="Type of reads read group black list">
+ <option value="file" selected="True">Filters in file</option>
+ <option value="text">Specify filters as a string</option>
+ </param>
+ <when value="file">
+ <param name="read_group_black_list" type="data" format="txt" label="Read group black list file" />
+ </when>
+ <when value="text">
+ <param name="read_group_black_list" type="text" value="tag:string" label="Read group black list tag:string" />
+ </when>
+ </conditional>
+ </repeat>
+
+ <param name="disable_experimental_low_memory_sharding" type="boolean" truevalue="--disable_experimental_low_memory_sharding" falsevalue="" label="Disable experimental low-memory sharding functionality." checked="False"/>
+ <param name="non_deterministic_random_seed" type="boolean" truevalue="--nonDeterministicRandomSeed" falsevalue="" label="Makes the GATK behave non deterministically, that is, the random numbers generated will be different in every run" checked="False" />
+
</when></conditional>
diff -r 1d0bb560bd3d584708972001afd054774e9e89c5 -r 28ab7dde097298b7565a6238f0bbcade29a73ae9 tools/gatk/variant_apply_recalibration.xml
--- a/tools/gatk/variant_apply_recalibration.xml
+++ b/tools/gatk/variant_apply_recalibration.xml
@@ -37,14 +37,16 @@
#end for
'
#end for
- #if str( $gatk_param_type.input_intervals ) != "None":
- -d "-L" "${gatk_param_type.input_intervals}" "${gatk_param_type.input_intervals.ext}" "input_intervals"
- #end if
- #if str( $gatk_param_type.input_exclude_intervals ) != "None":
- -d "-XL" "${gatk_param_type.input_exclude_intervals}" "${gatk_param_type.input_exclude_intervals.ext}" "input_intervals"
- #end if
+ #for $interval_count, $input_intervals in enumerate( $gatk_param_type.input_interval_repeat ):
+ -d "--intervals" "${input_intervals.input_intervals}" "${input_intervals.input_intervals.ext}" "input_intervals_${interval_count}"
+ #end for
+ #for $interval_count, $input_intervals in enumerate( $gatk_param_type.input_exclude_interval_repeat ):
+ -d "--excludeIntervals" "${input_intervals.input_exclude_intervals}" "${input_intervals.input_exclude_intervals.ext}" "input_exlude_intervals_${interval_count}"
+ #end for
+
-p '--BTI_merge_rule "${gatk_param_type.BTI_merge_rule}"'
+
-p '--downsampling_type "${gatk_param_type.downsampling_type.downsampling_type_selector}"'
#if str( $gatk_param_type.downsampling_type.downsampling_type_selector ) != "NONE":
-p '--${gatk_param_type.downsampling_type.downsample_to_type.downsample_to_type_selector} "${gatk_param_type.downsampling_type.downsample_to_type.downsample_to_value}"'
@@ -56,11 +58,18 @@
--defaultBaseQualities "${gatk_param_type.default_base_qualities}"
--validation_strictness "${gatk_param_type.validation_strictness}"
--interval_merging "${gatk_param_type.interval_merging}"
+ ${gatk_param_type.disable_experimental_low_memory_sharding}
+ ${gatk_param_type.non_deterministic_random_seed}
'
- #if str( $gatk_param_type.read_group_black_list ) != "None":
- -d "-read_group_black_list" "${gatk_param_type.read_group_black_list}" "txt" "input_read_group_black_list"
- #end if
+ #for $rg_black_list_count, $rg_black_list in enumerate( $gatk_param_type.read_group_black_list_repeat ):
+ #if $rg_black_list.read_group_black_list_type.read_group_black_list_type_selector == "file":
+ -d "--read_group_black_list" "${rg_black_list.read_group_black_list_type.read_group_black_list}" "txt" "input_read_group_black_list_${rg_black_list_count}"
+ #else
+ -p '--read_group_black_list "${rg_black_list.read_group_black_list_type.read_group_black_list}"'
+ #end if
+ #end for
#end if
+
#if str( $reference_source.reference_source_selector ) == "history":
-d "-R" "${reference_source.ref_file}" "${reference_source.ref_file.ext}" "gatk_input"
#end if
@@ -118,28 +127,34 @@
</when><when value="advanced"><repeat name="sample_metadata" title="Sample Metadata">
- <param name="sample_metadata_file" type="data" format="txt" label="Sample file(s) in JSON format" />
+ <param name="sample_metadata_file" type="data" format="txt" label="Sample file in JSON format" /></repeat><repeat name="read_filter" title="Read Filter"><conditional name="read_filter_type">
- <param name="read_filter_type_selector" type="select" label="Read Filter Type">
- <option value="MaxReadLength" selected="True">MaxReadLength</option>
- <option value="ZeroMappingQualityRead">ZeroMappingQualityRead</option>
- </param>
- <when value="ZeroMappingQualityRead">
- <!-- no extra options -->
- </when>
- <when value="MaxReadLength">
- <param name="maxReadLength" type="integer" value="76" label="Max Read Length"/>
- </when>
+ <param name="read_filter_type_selector" type="select" label="Read Filter Type">
+ <option value="MaxReadLength" selected="True">MaxReadLength</option>
+ <option value="ZeroMappingQualityRead">ZeroMappingQualityRead</option>
+ </param>
+ <when value="ZeroMappingQualityRead">
+ <!-- no extra options -->
+ </when>
+ <when value="MaxReadLength">
+ <param name="maxReadLength" type="integer" value="76" label="Max Read Length"/>
+ </when></conditional></repeat>
- <param name="input_intervals" type="data" format="picard_interval_list" optional="True" label="A list of genomic intervals over which to operate" />
- <param name="input_exclude_intervals" type="data" format="picard_interval_list" optional="True" label="A list of genomic intervals to exclude from processing" />
+ <repeat name="input_interval_repeat" title="Operate on Genomic intervals">
+ <param name="input_intervals" type="data" format="bed,gatk_interval,picard_interval_list" label="Genomic intervals" />
+ </repeat>
+ <repeat name="input_exclude_interval_repeat" title="Exclude Genomic intervals">
+ <param name="input_exclude_intervals" type="data" format="bed,gatk_interval,picard_interval_list" label="Genomic intervals" />
+ </repeat>
+
<param name="BTI_merge_rule" type="select" label="BTI merge rule"><option value="UNION" selected="True">UNION</option><option value="INTERSECTION">INTERSECTION</option></param>
+
<conditional name="downsampling_type"><param name="downsampling_type_selector" type="select" label="Type of reads downsampling to employ at a given locus" help="Downsampling Type"><option value="NONE" selected="True">NONE</option>
@@ -147,55 +162,74 @@
<option value="BY_SAMPLE">BY_SAMPLE</option></param><when value="NONE">
- <!-- no more options here -->
- </when>
+ <!-- no more options here -->
+ </when><when value="ALL_READS">
- <conditional name="downsample_to_type">
- <param name="downsample_to_type_selector" type="select" label="Type of reads downsampling to employ at a given locus" help="Downsampling Type">
- <option value="downsample_to_fraction" selected="True">Downsample by Fraction</option>
- <option value="downsample_to_coverage">Downsample by Coverage</option>
- </param>
- <when value="downsample_to_fraction">
- <param name="downsample_to_value" type="float" label="Fraction [0.0-1.0] of reads to downsample to" value="0.1"/>
- </when>
- <when value="downsample_to_coverage">
- <param name="downsample_to_value" type="integer" label="Coverage to downsample to at any given locus" value="0"/>
- </when>
- </conditional>
- </when>
+ <conditional name="downsample_to_type">
+ <param name="downsample_to_type_selector" type="select" label="Type of reads downsampling to employ at a given locus" help="Downsampling Type">
+ <option value="downsample_to_fraction" selected="True">Downsample by Fraction</option>
+ <option value="downsample_to_coverage">Downsample by Coverage</option>
+ </param>
+ <when value="downsample_to_fraction">
+ <param name="downsample_to_value" type="float" label="Fraction [0.0-1.0] of reads to downsample to" value="1" min="0" max="1"/>
+ </when>
+ <when value="downsample_to_coverage">
+ <param name="downsample_to_value" type="integer" label="Coverage to downsample to at any given locus" value="0"/>
+ </when>
+ </conditional>
+ </when><when value="BY_SAMPLE">
- <conditional name="downsample_to_type">
- <param name="downsample_to_type_selector" type="select" label="Type of reads downsampling to employ at a given locus" help="Downsampling Type">
- <option value="downsample_to_fraction" selected="True">Downsample by Fraction</option>
- <option value="downsample_to_coverage">Downsample by Coverage</option>
- </param>
- <when value="downsample_to_fraction">
- <param name="downsample_to_value" type="float" label="Fraction [0.0-1.0] of reads to downsample to" value="0.1"/>
- </when>
- <when value="downsample_to_coverage">
- <param name="downsample_to_value" type="integer" label="Coverage to downsample to at any given locus" value="0"/>
- </when>
- </conditional>
- </when>
+ <conditional name="downsample_to_type">
+ <param name="downsample_to_type_selector" type="select" label="Type of reads downsampling to employ at a given locus" help="Downsampling Type">
+ <option value="downsample_to_fraction" selected="True">Downsample by Fraction</option>
+ <option value="downsample_to_coverage">Downsample by Coverage</option>
+ </param>
+ <when value="downsample_to_fraction">
+ <param name="downsample_to_value" type="float" label="Fraction [0.0-1.0] of reads to downsample to" value="1" min="0" max="1"/>
+ </when>
+ <when value="downsample_to_coverage">
+ <param name="downsample_to_value" type="integer" label="Coverage to downsample to at any given locus" value="0"/>
+ </when>
+ </conditional>
+ </when></conditional><param name="baq" type="select" label="Type of BAQ calculation to apply in the engine"><option value="OFF" selected="True">OFF</option><option value="CALCULATE_AS_NECESSARY">CALCULATE_AS_NECESSARY</option><option value="RECALCULATE">RECALCULATE</option></param>
- <param name="baq_gap_open_penalty" type="integer" label="BAQ gap open penalty (Phred Scaled)" value="40" help="Default value is 40. 30 is perhaps better for whole genome call sets."/>
+ <param name="baq_gap_open_penalty" type="float" label="BAQ gap open penalty (Phred Scaled)" value="40" help="Default value is 40. 30 is perhaps better for whole genome call sets."/><param name="use_original_qualities" type="boolean" truevalue="--useOriginalQualities" falsevalue="" label="Use the original base quality scores from the OQ tag" /><param name="default_base_qualities" type="integer" label="Value to be used for all base quality scores, when some are missing" value="-1"/><param name="validation_strictness" type="select" label="How strict should we be with validation"><option value="STRICT" selected="True">STRICT</option><option value="LENIENT">LENIENT</option><option value="SILENT">SILENT</option>
+ <!-- <option value="DEFAULT_STRINGENCY">DEFAULT_STRINGENCY</option> listed in docs, but not valid value...--></param><param name="interval_merging" type="select" label="Interval merging rule"><option value="ALL" selected="True">ALL</option><option value="OVERLAPPING_ONLY">OVERLAPPING_ONLY</option></param>
- <param name="read_group_black_list" type="data" format="txt" optional="True" label="Read group black list" />
+
+ <repeat name="read_group_black_list_repeat" title="Read group black list">
+ <conditional name="read_group_black_list_type">
+ <param name="read_group_black_list_type_selector" type="select" label="Type of reads read group black list">
+ <option value="file" selected="True">Filters in file</option>
+ <option value="text">Specify filters as a string</option>
+ </param>
+ <when value="file">
+ <param name="read_group_black_list" type="data" format="txt" label="Read group black list file" />
+ </when>
+ <when value="text">
+ <param name="read_group_black_list" type="text" value="tag:string" label="Read group black list tag:string" />
+ </when>
+ </conditional>
+ </repeat>
+
+ <param name="disable_experimental_low_memory_sharding" type="boolean" truevalue="--disable_experimental_low_memory_sharding" falsevalue="" label="Disable experimental low-memory sharding functionality." checked="False"/>
+ <param name="non_deterministic_random_seed" type="boolean" truevalue="--nonDeterministicRandomSeed" falsevalue="" label="Makes the GATK behave non deterministically, that is, the random numbers generated will be different in every run" checked="False" />
+
</when></conditional>
diff -r 1d0bb560bd3d584708972001afd054774e9e89c5 -r 28ab7dde097298b7565a6238f0bbcade29a73ae9 tools/gatk/variant_combine.xml
--- a/tools/gatk/variant_combine.xml
+++ b/tools/gatk/variant_combine.xml
@@ -28,7 +28,6 @@
--rod_priority_list "${ ','.join( $priority_order ) }"
'
-
##start standard gatk options
#if $gatk_param_type.gatk_param_type_selector == "advanced":
#for $sample_metadata in $gatk_param_type.sample_metadata:
@@ -44,13 +43,16 @@
#end for
'
#end for
- #if str( $gatk_param_type.input_intervals ) != "None":
- -d "-L" "${gatk_param_type.input_intervals}" "${gatk_param_type.input_intervals.ext}" "input_intervals"
- #end if
- #if str( $gatk_param_type.input_exclude_intervals ) != "None":
- -d "-XL" "${gatk_param_type.input_exclude_intervals}" "${gatk_param_type.input_exclude_intervals.ext}" "input_intervals"
- #end if
+ #for $interval_count, $input_intervals in enumerate( $gatk_param_type.input_interval_repeat ):
+ -d "--intervals" "${input_intervals.input_intervals}" "${input_intervals.input_intervals.ext}" "input_intervals_${interval_count}"
+ #end for
+
+ #for $interval_count, $input_intervals in enumerate( $gatk_param_type.input_exclude_interval_repeat ):
+ -d "--excludeIntervals" "${input_intervals.input_exclude_intervals}" "${input_intervals.input_exclude_intervals.ext}" "input_exlude_intervals_${interval_count}"
+ #end for
+
-p '--BTI_merge_rule "${gatk_param_type.BTI_merge_rule}"'
+
-p '--downsampling_type "${gatk_param_type.downsampling_type.downsampling_type_selector}"'
#if str( $gatk_param_type.downsampling_type.downsampling_type_selector ) != "NONE":
-p '--${gatk_param_type.downsampling_type.downsample_to_type.downsample_to_type_selector} "${gatk_param_type.downsampling_type.downsample_to_type.downsample_to_value}"'
@@ -62,11 +64,18 @@
--defaultBaseQualities "${gatk_param_type.default_base_qualities}"
--validation_strictness "${gatk_param_type.validation_strictness}"
--interval_merging "${gatk_param_type.interval_merging}"
+ ${gatk_param_type.disable_experimental_low_memory_sharding}
+ ${gatk_param_type.non_deterministic_random_seed}
'
- #if str( $gatk_param_type.read_group_black_list ) != "None":
- -d "-read_group_black_list" "${gatk_param_type.read_group_black_list}" "txt" "input_read_group_black_list"
- #end if
+ #for $rg_black_list_count, $rg_black_list in enumerate( $gatk_param_type.read_group_black_list_repeat ):
+ #if $rg_black_list.read_group_black_list_type.read_group_black_list_type_selector == "file":
+ -d "--read_group_black_list" "${rg_black_list.read_group_black_list_type.read_group_black_list}" "txt" "input_read_group_black_list_${rg_black_list_count}"
+ #else
+ -p '--read_group_black_list "${rg_black_list.read_group_black_list_type.read_group_black_list}"'
+ #end if
+ #end for
#end if
+
#if $reference_source.reference_source_selector == "history":
-d "-R" "${reference_source.ref_file}" "${reference_source.ref_file.ext}" "gatk_input"
#end if
@@ -138,7 +147,7 @@
</when><when value="advanced"><repeat name="sample_metadata" title="Sample Metadata">
- <param name="sample_metadata_file" type="data" format="txt" label="Sample file(s) in JSON format" />
+ <param name="sample_metadata_file" type="data" format="txt" label="Sample file in JSON format" /></repeat><repeat name="read_filter" title="Read Filter"><conditional name="read_filter_type">
@@ -154,12 +163,18 @@
</when></conditional></repeat>
- <param name="input_intervals" type="data" format="picard_interval_list" optional="True" label="A list of genomic intervals over which to operate" />
- <param name="input_exclude_intervals" type="data" format="picard_interval_list" optional="True" label="A list of genomic intervals to exclude from processing" />
+ <repeat name="input_interval_repeat" title="Operate on Genomic intervals">
+ <param name="input_intervals" type="data" format="bed,gatk_interval,picard_interval_list" label="Genomic intervals" />
+ </repeat>
+ <repeat name="input_exclude_interval_repeat" title="Exclude Genomic intervals">
+ <param name="input_exclude_intervals" type="data" format="bed,gatk_interval,picard_interval_list" label="Genomic intervals" />
+ </repeat>
+
<param name="BTI_merge_rule" type="select" label="BTI merge rule"><option value="UNION" selected="True">UNION</option><option value="INTERSECTION">INTERSECTION</option></param>
+
<conditional name="downsampling_type"><param name="downsampling_type_selector" type="select" label="Type of reads downsampling to employ at a given locus" help="Downsampling Type"><option value="NONE" selected="True">NONE</option>
@@ -176,7 +191,7 @@
<option value="downsample_to_coverage">Downsample by Coverage</option></param><when value="downsample_to_fraction">
- <param name="downsample_to_value" type="float" label="Fraction [0.0-1.0] of reads to downsample to" value="0.1"/>
+ <param name="downsample_to_value" type="float" label="Fraction [0.0-1.0] of reads to downsample to" value="1" min="0" max="1"/></when><when value="downsample_to_coverage"><param name="downsample_to_value" type="integer" label="Coverage to downsample to at any given locus" value="0"/>
@@ -190,7 +205,7 @@
<option value="downsample_to_coverage">Downsample by Coverage</option></param><when value="downsample_to_fraction">
- <param name="downsample_to_value" type="float" label="Fraction [0.0-1.0] of reads to downsample to" value="0.1"/>
+ <param name="downsample_to_value" type="float" label="Fraction [0.0-1.0] of reads to downsample to" value="1" min="0" max="1"/></when><when value="downsample_to_coverage"><param name="downsample_to_value" type="integer" label="Coverage to downsample to at any given locus" value="0"/>
@@ -203,19 +218,38 @@
<option value="CALCULATE_AS_NECESSARY">CALCULATE_AS_NECESSARY</option><option value="RECALCULATE">RECALCULATE</option></param>
- <param name="baq_gap_open_penalty" type="integer" label="BAQ gap open penalty (Phred Scaled)" value="40" help="Default value is 40. 30 is perhaps better for whole genome call sets."/>
+ <param name="baq_gap_open_penalty" type="float" label="BAQ gap open penalty (Phred Scaled)" value="40" help="Default value is 40. 30 is perhaps better for whole genome call sets."/><param name="use_original_qualities" type="boolean" truevalue="--useOriginalQualities" falsevalue="" label="Use the original base quality scores from the OQ tag" /><param name="default_base_qualities" type="integer" label="Value to be used for all base quality scores, when some are missing" value="-1"/><param name="validation_strictness" type="select" label="How strict should we be with validation"><option value="STRICT" selected="True">STRICT</option><option value="LENIENT">LENIENT</option><option value="SILENT">SILENT</option>
+ <!-- <option value="DEFAULT_STRINGENCY">DEFAULT_STRINGENCY</option> listed in docs, but not valid value...--></param><param name="interval_merging" type="select" label="Interval merging rule"><option value="ALL" selected="True">ALL</option><option value="OVERLAPPING_ONLY">OVERLAPPING_ONLY</option></param>
- <param name="read_group_black_list" type="data" format="txt" optional="True" label="Read group black list" />
+
+ <repeat name="read_group_black_list_repeat" title="Read group black list">
+ <conditional name="read_group_black_list_type">
+ <param name="read_group_black_list_type_selector" type="select" label="Type of reads read group black list">
+ <option value="file" selected="True">Filters in file</option>
+ <option value="text">Specify filters as a string</option>
+ </param>
+ <when value="file">
+ <param name="read_group_black_list" type="data" format="txt" label="Read group black list file" />
+ </when>
+ <when value="text">
+ <param name="read_group_black_list" type="text" value="tag:string" label="Read group black list tag:string" />
+ </when>
+ </conditional>
+ </repeat>
+
+ <param name="disable_experimental_low_memory_sharding" type="boolean" truevalue="--disable_experimental_low_memory_sharding" falsevalue="" label="Disable experimental low-memory sharding functionality." checked="False"/>
+ <param name="non_deterministic_random_seed" type="boolean" truevalue="--nonDeterministicRandomSeed" falsevalue="" label="Makes the GATK behave non deterministically, that is, the random numbers generated will be different in every run" checked="False" />
+
</when></conditional>
diff -r 1d0bb560bd3d584708972001afd054774e9e89c5 -r 28ab7dde097298b7565a6238f0bbcade29a73ae9 tools/gatk/variant_eval.xml
--- a/tools/gatk/variant_eval.xml
+++ b/tools/gatk/variant_eval.xml
@@ -56,13 +56,16 @@
#end for
'
#end for
- #if str( $gatk_param_type.input_intervals ) != "None":
- -d "-L" "${gatk_param_type.input_intervals}" "${gatk_param_type.input_intervals.ext}" "input_intervals"
- #end if
- #if str( $gatk_param_type.input_exclude_intervals ) != "None":
- -d "-XL" "${gatk_param_type.input_exclude_intervals}" "${gatk_param_type.input_exclude_intervals.ext}" "input_intervals"
- #end if
+ #for $interval_count, $input_intervals in enumerate( $gatk_param_type.input_interval_repeat ):
+ -d "--intervals" "${input_intervals.input_intervals}" "${input_intervals.input_intervals.ext}" "input_intervals_${interval_count}"
+ #end for
+
+ #for $interval_count, $input_intervals in enumerate( $gatk_param_type.input_exclude_interval_repeat ):
+ -d "--excludeIntervals" "${input_intervals.input_exclude_intervals}" "${input_intervals.input_exclude_intervals.ext}" "input_exlude_intervals_${interval_count}"
+ #end for
+
-p '--BTI_merge_rule "${gatk_param_type.BTI_merge_rule}"'
+
-p '--downsampling_type "${gatk_param_type.downsampling_type.downsampling_type_selector}"'
#if str( $gatk_param_type.downsampling_type.downsampling_type_selector ) != "NONE":
-p '--${gatk_param_type.downsampling_type.downsample_to_type.downsample_to_type_selector} "${gatk_param_type.downsampling_type.downsample_to_type.downsample_to_value}"'
@@ -74,11 +77,18 @@
--defaultBaseQualities "${gatk_param_type.default_base_qualities}"
--validation_strictness "${gatk_param_type.validation_strictness}"
--interval_merging "${gatk_param_type.interval_merging}"
+ ${gatk_param_type.disable_experimental_low_memory_sharding}
+ ${gatk_param_type.non_deterministic_random_seed}
'
- #if str( $gatk_param_type.read_group_black_list ) != "None":
- -d "-read_group_black_list" "${gatk_param_type.read_group_black_list}" "txt" "input_read_group_black_list"
- #end if
+ #for $rg_black_list_count, $rg_black_list in enumerate( $gatk_param_type.read_group_black_list_repeat ):
+ #if $rg_black_list.read_group_black_list_type.read_group_black_list_type_selector == "file":
+ -d "--read_group_black_list" "${rg_black_list.read_group_black_list_type.read_group_black_list}" "txt" "input_read_group_black_list_${rg_black_list_count}"
+ #else
+ -p '--read_group_black_list "${rg_black_list.read_group_black_list_type.read_group_black_list}"'
+ #end if
+ #end for
#end if
+
#if $reference_source.reference_source_selector == "history":
-d "-R" "${reference_source.ref_file}" "${reference_source.ref_file.ext}" "gatk_input"
#end if
@@ -195,7 +205,7 @@
</when><when value="advanced"><repeat name="sample_metadata" title="Sample Metadata">
- <param name="sample_metadata_file" type="data" format="txt" label="Sample file(s) in JSON format" />
+ <param name="sample_metadata_file" type="data" format="txt" label="Sample file in JSON format" /></repeat><repeat name="read_filter" title="Read Filter"><conditional name="read_filter_type">
@@ -211,12 +221,18 @@
</when></conditional></repeat>
- <param name="input_intervals" type="data" format="picard_interval_list" optional="True" label="A list of genomic intervals over which to operate" />
- <param name="input_exclude_intervals" type="data" format="picard_interval_list" optional="True" label="A list of genomic intervals to exclude from processing" />
+ <repeat name="input_interval_repeat" title="Operate on Genomic intervals">
+ <param name="input_intervals" type="data" format="bed,gatk_interval,picard_interval_list" label="Genomic intervals" />
+ </repeat>
+ <repeat name="input_exclude_interval_repeat" title="Exclude Genomic intervals">
+ <param name="input_exclude_intervals" type="data" format="bed,gatk_interval,picard_interval_list" label="Genomic intervals" />
+ </repeat>
+
<param name="BTI_merge_rule" type="select" label="BTI merge rule"><option value="UNION" selected="True">UNION</option><option value="INTERSECTION">INTERSECTION</option></param>
+
<conditional name="downsampling_type"><param name="downsampling_type_selector" type="select" label="Type of reads downsampling to employ at a given locus" help="Downsampling Type"><option value="NONE" selected="True">NONE</option>
@@ -233,7 +249,7 @@
<option value="downsample_to_coverage">Downsample by Coverage</option></param><when value="downsample_to_fraction">
- <param name="downsample_to_value" type="float" label="Fraction [0.0-1.0] of reads to downsample to" value="0.1"/>
+ <param name="downsample_to_value" type="float" label="Fraction [0.0-1.0] of reads to downsample to" value="1" min="0" max="1"/></when><when value="downsample_to_coverage"><param name="downsample_to_value" type="integer" label="Coverage to downsample to at any given locus" value="0"/>
@@ -247,7 +263,7 @@
<option value="downsample_to_coverage">Downsample by Coverage</option></param><when value="downsample_to_fraction">
- <param name="downsample_to_value" type="float" label="Fraction [0.0-1.0] of reads to downsample to" value="0.1"/>
+ <param name="downsample_to_value" type="float" label="Fraction [0.0-1.0] of reads to downsample to" value="1" min="0" max="1"/></when><when value="downsample_to_coverage"><param name="downsample_to_value" type="integer" label="Coverage to downsample to at any given locus" value="0"/>
@@ -260,19 +276,38 @@
<option value="CALCULATE_AS_NECESSARY">CALCULATE_AS_NECESSARY</option><option value="RECALCULATE">RECALCULATE</option></param>
- <param name="baq_gap_open_penalty" type="integer" label="BAQ gap open penalty (Phred Scaled)" value="40" help="Default value is 40. 30 is perhaps better for whole genome call sets."/>
+ <param name="baq_gap_open_penalty" type="float" label="BAQ gap open penalty (Phred Scaled)" value="40" help="Default value is 40. 30 is perhaps better for whole genome call sets."/><param name="use_original_qualities" type="boolean" truevalue="--useOriginalQualities" falsevalue="" label="Use the original base quality scores from the OQ tag" /><param name="default_base_qualities" type="integer" label="Value to be used for all base quality scores, when some are missing" value="-1"/><param name="validation_strictness" type="select" label="How strict should we be with validation"><option value="STRICT" selected="True">STRICT</option><option value="LENIENT">LENIENT</option><option value="SILENT">SILENT</option>
+ <!-- <option value="DEFAULT_STRINGENCY">DEFAULT_STRINGENCY</option> listed in docs, but not valid value...--></param><param name="interval_merging" type="select" label="Interval merging rule"><option value="ALL" selected="True">ALL</option><option value="OVERLAPPING_ONLY">OVERLAPPING_ONLY</option></param>
- <param name="read_group_black_list" type="data" format="txt" optional="True" label="Read group black list" />
+
+ <repeat name="read_group_black_list_repeat" title="Read group black list">
+ <conditional name="read_group_black_list_type">
+ <param name="read_group_black_list_type_selector" type="select" label="Type of reads read group black list">
+ <option value="file" selected="True">Filters in file</option>
+ <option value="text">Specify filters as a string</option>
+ </param>
+ <when value="file">
+ <param name="read_group_black_list" type="data" format="txt" label="Read group black list file" />
+ </when>
+ <when value="text">
+ <param name="read_group_black_list" type="text" value="tag:string" label="Read group black list tag:string" />
+ </when>
+ </conditional>
+ </repeat>
+
+ <param name="disable_experimental_low_memory_sharding" type="boolean" truevalue="--disable_experimental_low_memory_sharding" falsevalue="" label="Disable experimental low-memory sharding functionality." checked="False"/>
+ <param name="non_deterministic_random_seed" type="boolean" truevalue="--nonDeterministicRandomSeed" falsevalue="" label="Makes the GATK behave non deterministically, that is, the random numbers generated will be different in every run" checked="False" />
+
</when></conditional>
diff -r 1d0bb560bd3d584708972001afd054774e9e89c5 -r 28ab7dde097298b7565a6238f0bbcade29a73ae9 tools/gatk/variant_filtration.xml
--- a/tools/gatk/variant_filtration.xml
+++ b/tools/gatk/variant_filtration.xml
@@ -50,14 +50,16 @@
#end for
'
#end for
- #if str( $gatk_param_type.input_intervals ) != "None":
- -d "-L" "${gatk_param_type.input_intervals}" "${gatk_param_type.input_intervals.ext}" "input_intervals"
- #end if
- #if str( $gatk_param_type.input_exclude_intervals ) != "None":
- -d "-XL" "${gatk_param_type.input_exclude_intervals}" "${gatk_param_type.input_exclude_intervals.ext}" "input_intervals"
- #end if
+ #for $interval_count, $input_intervals in enumerate( $gatk_param_type.input_interval_repeat ):
+ -d "--intervals" "${input_intervals.input_intervals}" "${input_intervals.input_intervals.ext}" "input_intervals_${interval_count}"
+ #end for
+ #for $interval_count, $input_intervals in enumerate( $gatk_param_type.input_exclude_interval_repeat ):
+ -d "--excludeIntervals" "${input_intervals.input_exclude_intervals}" "${input_intervals.input_exclude_intervals.ext}" "input_exlude_intervals_${interval_count}"
+ #end for
+
-p '--BTI_merge_rule "${gatk_param_type.BTI_merge_rule}"'
+
-p '--downsampling_type "${gatk_param_type.downsampling_type.downsampling_type_selector}"'
#if str( $gatk_param_type.downsampling_type.downsampling_type_selector ) != "NONE":
-p '--${gatk_param_type.downsampling_type.downsample_to_type.downsample_to_type_selector} "${gatk_param_type.downsampling_type.downsample_to_type.downsample_to_value}"'
@@ -69,11 +71,18 @@
--defaultBaseQualities "${gatk_param_type.default_base_qualities}"
--validation_strictness "${gatk_param_type.validation_strictness}"
--interval_merging "${gatk_param_type.interval_merging}"
+ ${gatk_param_type.disable_experimental_low_memory_sharding}
+ ${gatk_param_type.non_deterministic_random_seed}
'
- #if str( $gatk_param_type.read_group_black_list ) != "None":
- -d "-read_group_black_list" "${gatk_param_type.read_group_black_list}" "txt" "input_read_group_black_list"
- #end if
+ #for $rg_black_list_count, $rg_black_list in enumerate( $gatk_param_type.read_group_black_list_repeat ):
+ #if $rg_black_list.read_group_black_list_type.read_group_black_list_type_selector == "file":
+ -d "--read_group_black_list" "${rg_black_list.read_group_black_list_type.read_group_black_list}" "txt" "input_read_group_black_list_${rg_black_list_count}"
+ #else
+ -p '--read_group_black_list "${rg_black_list.read_group_black_list_type.read_group_black_list}"'
+ #end if
+ #end for
#end if
+
#if str( $reference_source.reference_source_selector ) == "history":
-d "-R" "${reference_source.ref_file}" "${reference_source.ref_file.ext}" "gatk_input"
#end if
@@ -152,7 +161,7 @@
</when><when value="advanced"><repeat name="sample_metadata" title="Sample Metadata">
- <param name="sample_metadata_file" type="data" format="txt" label="Sample file(s) in JSON format" />
+ <param name="sample_metadata_file" type="data" format="txt" label="Sample file in JSON format" /></repeat><repeat name="read_filter" title="Read Filter"><conditional name="read_filter_type">
@@ -168,12 +177,18 @@
</when></conditional></repeat>
- <param name="input_intervals" type="data" format="picard_interval_list" optional="True" label="A list of genomic intervals over which to operate" />
- <param name="input_exclude_intervals" type="data" format="picard_interval_list" optional="True" label="A list of genomic intervals to exclude from processing" />
+ <repeat name="input_interval_repeat" title="Operate on Genomic intervals">
+ <param name="input_intervals" type="data" format="bed,gatk_interval,picard_interval_list" label="Genomic intervals" />
+ </repeat>
+ <repeat name="input_exclude_interval_repeat" title="Exclude Genomic intervals">
+ <param name="input_exclude_intervals" type="data" format="bed,gatk_interval,picard_interval_list" label="Genomic intervals" />
+ </repeat>
+
<param name="BTI_merge_rule" type="select" label="BTI merge rule"><option value="UNION" selected="True">UNION</option><option value="INTERSECTION">INTERSECTION</option></param>
+
<conditional name="downsampling_type"><param name="downsampling_type_selector" type="select" label="Type of reads downsampling to employ at a given locus" help="Downsampling Type"><option value="NONE" selected="True">NONE</option>
@@ -190,7 +205,7 @@
<option value="downsample_to_coverage">Downsample by Coverage</option></param><when value="downsample_to_fraction">
- <param name="downsample_to_value" type="float" label="Fraction [0.0-1.0] of reads to downsample to" value="0.1"/>
+ <param name="downsample_to_value" type="float" label="Fraction [0.0-1.0] of reads to downsample to" value="1" min="0" max="1"/></when><when value="downsample_to_coverage"><param name="downsample_to_value" type="integer" label="Coverage to downsample to at any given locus" value="0"/>
@@ -204,7 +219,7 @@
<option value="downsample_to_coverage">Downsample by Coverage</option></param><when value="downsample_to_fraction">
- <param name="downsample_to_value" type="float" label="Fraction [0.0-1.0] of reads to downsample to" value="0.1"/>
+ <param name="downsample_to_value" type="float" label="Fraction [0.0-1.0] of reads to downsample to" value="1" min="0" max="1"/></when><when value="downsample_to_coverage"><param name="downsample_to_value" type="integer" label="Coverage to downsample to at any given locus" value="0"/>
@@ -217,19 +232,38 @@
<option value="CALCULATE_AS_NECESSARY">CALCULATE_AS_NECESSARY</option><option value="RECALCULATE">RECALCULATE</option></param>
- <param name="baq_gap_open_penalty" type="integer" label="BAQ gap open penalty (Phred Scaled)" value="40" help="Default value is 40. 30 is perhaps better for whole genome call sets."/>
+ <param name="baq_gap_open_penalty" type="float" label="BAQ gap open penalty (Phred Scaled)" value="40" help="Default value is 40. 30 is perhaps better for whole genome call sets."/><param name="use_original_qualities" type="boolean" truevalue="--useOriginalQualities" falsevalue="" label="Use the original base quality scores from the OQ tag" /><param name="default_base_qualities" type="integer" label="Value to be used for all base quality scores, when some are missing" value="-1"/><param name="validation_strictness" type="select" label="How strict should we be with validation"><option value="STRICT" selected="True">STRICT</option><option value="LENIENT">LENIENT</option><option value="SILENT">SILENT</option>
+ <!-- <option value="DEFAULT_STRINGENCY">DEFAULT_STRINGENCY</option> listed in docs, but not valid value...--></param><param name="interval_merging" type="select" label="Interval merging rule"><option value="ALL" selected="True">ALL</option><option value="OVERLAPPING_ONLY">OVERLAPPING_ONLY</option></param>
- <param name="read_group_black_list" type="data" format="txt" optional="True" label="Read group black list" />
+
+ <repeat name="read_group_black_list_repeat" title="Read group black list">
+ <conditional name="read_group_black_list_type">
+ <param name="read_group_black_list_type_selector" type="select" label="Type of reads read group black list">
+ <option value="file" selected="True">Filters in file</option>
+ <option value="text">Specify filters as a string</option>
+ </param>
+ <when value="file">
+ <param name="read_group_black_list" type="data" format="txt" label="Read group black list file" />
+ </when>
+ <when value="text">
+ <param name="read_group_black_list" type="text" value="tag:string" label="Read group black list tag:string" />
+ </when>
+ </conditional>
+ </repeat>
+
+ <param name="disable_experimental_low_memory_sharding" type="boolean" truevalue="--disable_experimental_low_memory_sharding" falsevalue="" label="Disable experimental low-memory sharding functionality." checked="False"/>
+ <param name="non_deterministic_random_seed" type="boolean" truevalue="--nonDeterministicRandomSeed" falsevalue="" label="Makes the GATK behave non deterministically, that is, the random numbers generated will be different in every run" checked="False" />
+
</when></conditional>
diff -r 1d0bb560bd3d584708972001afd054774e9e89c5 -r 28ab7dde097298b7565a6238f0bbcade29a73ae9 tools/gatk/variant_recalibrator.xml
--- a/tools/gatk/variant_recalibrator.xml
+++ b/tools/gatk/variant_recalibrator.xml
@@ -58,14 +58,16 @@
#end for
'
#end for
- #if str( $gatk_param_type.input_intervals ) != "None":
- -d "-L" "${gatk_param_type.input_intervals}" "${gatk_param_type.input_intervals.ext}" "input_intervals"
- #end if
- #if str( $gatk_param_type.input_exclude_intervals ) != "None":
- -d "-XL" "${gatk_param_type.input_exclude_intervals}" "${gatk_param_type.input_exclude_intervals.ext}" "input_intervals"
- #end if
+ #for $interval_count, $input_intervals in enumerate( $gatk_param_type.input_interval_repeat ):
+ -d "--intervals" "${input_intervals.input_intervals}" "${input_intervals.input_intervals.ext}" "input_intervals_${interval_count}"
+ #end for
+ #for $interval_count, $input_intervals in enumerate( $gatk_param_type.input_exclude_interval_repeat ):
+ -d "--excludeIntervals" "${input_intervals.input_exclude_intervals}" "${input_intervals.input_exclude_intervals.ext}" "input_exlude_intervals_${interval_count}"
+ #end for
+
-p '--BTI_merge_rule "${gatk_param_type.BTI_merge_rule}"'
+
-p '--downsampling_type "${gatk_param_type.downsampling_type.downsampling_type_selector}"'
#if str( $gatk_param_type.downsampling_type.downsampling_type_selector ) != "NONE":
-p '--${gatk_param_type.downsampling_type.downsample_to_type.downsample_to_type_selector} "${gatk_param_type.downsampling_type.downsample_to_type.downsample_to_value}"'
@@ -77,11 +79,18 @@
--defaultBaseQualities "${gatk_param_type.default_base_qualities}"
--validation_strictness "${gatk_param_type.validation_strictness}"
--interval_merging "${gatk_param_type.interval_merging}"
+ ${gatk_param_type.disable_experimental_low_memory_sharding}
+ ${gatk_param_type.non_deterministic_random_seed}
'
- #if str( $gatk_param_type.read_group_black_list ) != "None":
- -d "-read_group_black_list" "${gatk_param_type.read_group_black_list}" "txt" "input_read_group_black_list"
- #end if
+ #for $rg_black_list_count, $rg_black_list in enumerate( $gatk_param_type.read_group_black_list_repeat ):
+ #if $rg_black_list.read_group_black_list_type.read_group_black_list_type_selector == "file":
+ -d "--read_group_black_list" "${rg_black_list.read_group_black_list_type.read_group_black_list}" "txt" "input_read_group_black_list_${rg_black_list_count}"
+ #else
+ -p '--read_group_black_list "${rg_black_list.read_group_black_list_type.read_group_black_list}"'
+ #end if
+ #end for
#end if
+
#if str( $reference_source.reference_source_selector ) == "history":
-d "-R" "${reference_source.ref_file}" "${reference_source.ref_file.ext}" "gatk_input"
#end if
@@ -382,28 +391,34 @@
</when><when value="advanced"><repeat name="sample_metadata" title="Sample Metadata">
- <param name="sample_metadata_file" type="data" format="txt" label="Sample file(s) in JSON format" />
+ <param name="sample_metadata_file" type="data" format="txt" label="Sample file in JSON format" /></repeat><repeat name="read_filter" title="Read Filter"><conditional name="read_filter_type">
- <param name="read_filter_type_selector" type="select" label="Read Filter Type">
- <option value="MaxReadLength" selected="True">MaxReadLength</option>
- <option value="ZeroMappingQualityRead">ZeroMappingQualityRead</option>
- </param>
- <when value="ZeroMappingQualityRead">
- <!-- no extra options -->
- </when>
- <when value="MaxReadLength">
- <param name="maxReadLength" type="integer" value="76" label="Max Read Length"/>
- </when>
+ <param name="read_filter_type_selector" type="select" label="Read Filter Type">
+ <option value="MaxReadLength" selected="True">MaxReadLength</option>
+ <option value="ZeroMappingQualityRead">ZeroMappingQualityRead</option>
+ </param>
+ <when value="ZeroMappingQualityRead">
+ <!-- no extra options -->
+ </when>
+ <when value="MaxReadLength">
+ <param name="maxReadLength" type="integer" value="76" label="Max Read Length"/>
+ </when></conditional></repeat>
- <param name="input_intervals" type="data" format="picard_interval_list" optional="True" label="A list of genomic intervals over which to operate" />
- <param name="input_exclude_intervals" type="data" format="picard_interval_list" optional="True" label="A list of genomic intervals to exclude from processing" />
+ <repeat name="input_interval_repeat" title="Operate on Genomic intervals">
+ <param name="input_intervals" type="data" format="bed,gatk_interval,picard_interval_list" label="Genomic intervals" />
+ </repeat>
+ <repeat name="input_exclude_interval_repeat" title="Exclude Genomic intervals">
+ <param name="input_exclude_intervals" type="data" format="bed,gatk_interval,picard_interval_list" label="Genomic intervals" />
+ </repeat>
+
<param name="BTI_merge_rule" type="select" label="BTI merge rule"><option value="UNION" selected="True">UNION</option><option value="INTERSECTION">INTERSECTION</option></param>
+
<conditional name="downsampling_type"><param name="downsampling_type_selector" type="select" label="Type of reads downsampling to employ at a given locus" help="Downsampling Type"><option value="NONE" selected="True">NONE</option>
@@ -411,55 +426,74 @@
<option value="BY_SAMPLE">BY_SAMPLE</option></param><when value="NONE">
- <!-- no more options here -->
- </when>
+ <!-- no more options here -->
+ </when><when value="ALL_READS">
- <conditional name="downsample_to_type">
- <param name="downsample_to_type_selector" type="select" label="Type of reads downsampling to employ at a given locus" help="Downsampling Type">
- <option value="downsample_to_fraction" selected="True">Downsample by Fraction</option>
- <option value="downsample_to_coverage">Downsample by Coverage</option>
- </param>
- <when value="downsample_to_fraction">
- <param name="downsample_to_value" type="float" label="Fraction [0.0-1.0] of reads to downsample to" value="0.1"/>
- </when>
- <when value="downsample_to_coverage">
- <param name="downsample_to_value" type="integer" label="Coverage to downsample to at any given locus" value="0"/>
- </when>
- </conditional>
- </when>
+ <conditional name="downsample_to_type">
+ <param name="downsample_to_type_selector" type="select" label="Type of reads downsampling to employ at a given locus" help="Downsampling Type">
+ <option value="downsample_to_fraction" selected="True">Downsample by Fraction</option>
+ <option value="downsample_to_coverage">Downsample by Coverage</option>
+ </param>
+ <when value="downsample_to_fraction">
+ <param name="downsample_to_value" type="float" label="Fraction [0.0-1.0] of reads to downsample to" value="1" min="0" max="1"/>
+ </when>
+ <when value="downsample_to_coverage">
+ <param name="downsample_to_value" type="integer" label="Coverage to downsample to at any given locus" value="0"/>
+ </when>
+ </conditional>
+ </when><when value="BY_SAMPLE">
- <conditional name="downsample_to_type">
- <param name="downsample_to_type_selector" type="select" label="Type of reads downsampling to employ at a given locus" help="Downsampling Type">
- <option value="downsample_to_fraction" selected="True">Downsample by Fraction</option>
- <option value="downsample_to_coverage">Downsample by Coverage</option>
- </param>
- <when value="downsample_to_fraction">
- <param name="downsample_to_value" type="float" label="Fraction [0.0-1.0] of reads to downsample to" value="0.1"/>
- </when>
- <when value="downsample_to_coverage">
- <param name="downsample_to_value" type="integer" label="Coverage to downsample to at any given locus" value="0"/>
- </when>
- </conditional>
- </when>
+ <conditional name="downsample_to_type">
+ <param name="downsample_to_type_selector" type="select" label="Type of reads downsampling to employ at a given locus" help="Downsampling Type">
+ <option value="downsample_to_fraction" selected="True">Downsample by Fraction</option>
+ <option value="downsample_to_coverage">Downsample by Coverage</option>
+ </param>
+ <when value="downsample_to_fraction">
+ <param name="downsample_to_value" type="float" label="Fraction [0.0-1.0] of reads to downsample to" value="1" min="0" max="1"/>
+ </when>
+ <when value="downsample_to_coverage">
+ <param name="downsample_to_value" type="integer" label="Coverage to downsample to at any given locus" value="0"/>
+ </when>
+ </conditional>
+ </when></conditional><param name="baq" type="select" label="Type of BAQ calculation to apply in the engine"><option value="OFF" selected="True">OFF</option><option value="CALCULATE_AS_NECESSARY">CALCULATE_AS_NECESSARY</option><option value="RECALCULATE">RECALCULATE</option></param>
- <param name="baq_gap_open_penalty" type="integer" label="BAQ gap open penalty (Phred Scaled)" value="40" help="Default value is 40. 30 is perhaps better for whole genome call sets."/>
+ <param name="baq_gap_open_penalty" type="float" label="BAQ gap open penalty (Phred Scaled)" value="40" help="Default value is 40. 30 is perhaps better for whole genome call sets."/><param name="use_original_qualities" type="boolean" truevalue="--useOriginalQualities" falsevalue="" label="Use the original base quality scores from the OQ tag" /><param name="default_base_qualities" type="integer" label="Value to be used for all base quality scores, when some are missing" value="-1"/><param name="validation_strictness" type="select" label="How strict should we be with validation"><option value="STRICT" selected="True">STRICT</option><option value="LENIENT">LENIENT</option><option value="SILENT">SILENT</option>
+ <!-- <option value="DEFAULT_STRINGENCY">DEFAULT_STRINGENCY</option> listed in docs, but not valid value...--></param><param name="interval_merging" type="select" label="Interval merging rule"><option value="ALL" selected="True">ALL</option><option value="OVERLAPPING_ONLY">OVERLAPPING_ONLY</option></param>
- <param name="read_group_black_list" type="data" format="txt" optional="True" label="Read group black list" />
+
+ <repeat name="read_group_black_list_repeat" title="Read group black list">
+ <conditional name="read_group_black_list_type">
+ <param name="read_group_black_list_type_selector" type="select" label="Type of reads read group black list">
+ <option value="file" selected="True">Filters in file</option>
+ <option value="text">Specify filters as a string</option>
+ </param>
+ <when value="file">
+ <param name="read_group_black_list" type="data" format="txt" label="Read group black list file" />
+ </when>
+ <when value="text">
+ <param name="read_group_black_list" type="text" value="tag:string" label="Read group black list tag:string" />
+ </when>
+ </conditional>
+ </repeat>
+
+ <param name="disable_experimental_low_memory_sharding" type="boolean" truevalue="--disable_experimental_low_memory_sharding" falsevalue="" label="Disable experimental low-memory sharding functionality." checked="False"/>
+ <param name="non_deterministic_random_seed" type="boolean" truevalue="--nonDeterministicRandomSeed" falsevalue="" label="Makes the GATK behave non deterministically, that is, the random numbers generated will be different in every run" checked="False" />
+
</when></conditional>
diff -r 1d0bb560bd3d584708972001afd054774e9e89c5 -r 28ab7dde097298b7565a6238f0bbcade29a73ae9 tools/gatk/variants_validate.xml
--- a/tools/gatk/variants_validate.xml
+++ b/tools/gatk/variants_validate.xml
@@ -42,13 +42,16 @@
#end for
'
#end for
- #if str( $gatk_param_type.input_intervals ) != "None":
- -d "-L" "${gatk_param_type.input_intervals}" "${gatk_param_type.input_intervals.ext}" "input_intervals"
- #end if
- #if str( $gatk_param_type.input_exclude_intervals ) != "None":
- -d "-XL" "${gatk_param_type.input_exclude_intervals}" "${gatk_param_type.input_exclude_intervals.ext}" "input_intervals"
- #end if
+ #for $interval_count, $input_intervals in enumerate( $gatk_param_type.input_interval_repeat ):
+ -d "--intervals" "${input_intervals.input_intervals}" "${input_intervals.input_intervals.ext}" "input_intervals_${interval_count}"
+ #end for
+
+ #for $interval_count, $input_intervals in enumerate( $gatk_param_type.input_exclude_interval_repeat ):
+ -d "--excludeIntervals" "${input_intervals.input_exclude_intervals}" "${input_intervals.input_exclude_intervals.ext}" "input_exlude_intervals_${interval_count}"
+ #end for
+
-p '--BTI_merge_rule "${gatk_param_type.BTI_merge_rule}"'
+
-p '--downsampling_type "${gatk_param_type.downsampling_type.downsampling_type_selector}"'
#if str( $gatk_param_type.downsampling_type.downsampling_type_selector ) != "NONE":
-p '--${gatk_param_type.downsampling_type.downsample_to_type.downsample_to_type_selector} "${gatk_param_type.downsampling_type.downsample_to_type.downsample_to_value}"'
@@ -60,11 +63,18 @@
--defaultBaseQualities "${gatk_param_type.default_base_qualities}"
--validation_strictness "${gatk_param_type.validation_strictness}"
--interval_merging "${gatk_param_type.interval_merging}"
+ ${gatk_param_type.disable_experimental_low_memory_sharding}
+ ${gatk_param_type.non_deterministic_random_seed}
'
- #if str( $gatk_param_type.read_group_black_list ) != "None":
- -d "-read_group_black_list" "${gatk_param_type.read_group_black_list}" "txt" "input_read_group_black_list"
- #end if
+ #for $rg_black_list_count, $rg_black_list in enumerate( $gatk_param_type.read_group_black_list_repeat ):
+ #if $rg_black_list.read_group_black_list_type.read_group_black_list_type_selector == "file":
+ -d "--read_group_black_list" "${rg_black_list.read_group_black_list_type.read_group_black_list}" "txt" "input_read_group_black_list_${rg_black_list_count}"
+ #else
+ -p '--read_group_black_list "${rg_black_list.read_group_black_list_type.read_group_black_list}"'
+ #end if
+ #end for
#end if
+
#if $reference_source.reference_source_selector == "history":
-d "-R" "${reference_source.ref_file}" "${reference_source.ref_file.ext}" "gatk_input"
#end if
@@ -120,7 +130,7 @@
</when><when value="advanced"><repeat name="sample_metadata" title="Sample Metadata">
- <param name="sample_metadata_file" type="data" format="txt" label="Sample file(s) in JSON format" />
+ <param name="sample_metadata_file" type="data" format="txt" label="Sample file in JSON format" /></repeat><repeat name="read_filter" title="Read Filter"><conditional name="read_filter_type">
@@ -136,12 +146,18 @@
</when></conditional></repeat>
- <param name="input_intervals" type="data" format="picard_interval_list" optional="True" label="A list of genomic intervals over which to operate" />
- <param name="input_exclude_intervals" type="data" format="picard_interval_list" optional="True" label="A list of genomic intervals to exclude from processing" />
+ <repeat name="input_interval_repeat" title="Operate on Genomic intervals">
+ <param name="input_intervals" type="data" format="bed,gatk_interval,picard_interval_list" label="Genomic intervals" />
+ </repeat>
+ <repeat name="input_exclude_interval_repeat" title="Exclude Genomic intervals">
+ <param name="input_exclude_intervals" type="data" format="bed,gatk_interval,picard_interval_list" label="Genomic intervals" />
+ </repeat>
+
<param name="BTI_merge_rule" type="select" label="BTI merge rule"><option value="UNION" selected="True">UNION</option><option value="INTERSECTION">INTERSECTION</option></param>
+
<conditional name="downsampling_type"><param name="downsampling_type_selector" type="select" label="Type of reads downsampling to employ at a given locus" help="Downsampling Type"><option value="NONE" selected="True">NONE</option>
@@ -158,7 +174,7 @@
<option value="downsample_to_coverage">Downsample by Coverage</option></param><when value="downsample_to_fraction">
- <param name="downsample_to_value" type="float" label="Fraction [0.0-1.0] of reads to downsample to" value="0.1"/>
+ <param name="downsample_to_value" type="float" label="Fraction [0.0-1.0] of reads to downsample to" value="1" min="0" max="1"/></when><when value="downsample_to_coverage"><param name="downsample_to_value" type="integer" label="Coverage to downsample to at any given locus" value="0"/>
@@ -172,7 +188,7 @@
<option value="downsample_to_coverage">Downsample by Coverage</option></param><when value="downsample_to_fraction">
- <param name="downsample_to_value" type="float" label="Fraction [0.0-1.0] of reads to downsample to" value="0.1"/>
+ <param name="downsample_to_value" type="float" label="Fraction [0.0-1.0] of reads to downsample to" value="1" min="0" max="1"/></when><when value="downsample_to_coverage"><param name="downsample_to_value" type="integer" label="Coverage to downsample to at any given locus" value="0"/>
@@ -185,19 +201,38 @@
<option value="CALCULATE_AS_NECESSARY">CALCULATE_AS_NECESSARY</option><option value="RECALCULATE">RECALCULATE</option></param>
- <param name="baq_gap_open_penalty" type="integer" label="BAQ gap open penalty (Phred Scaled)" value="40" help="Default value is 40. 30 is perhaps better for whole genome call sets."/>
+ <param name="baq_gap_open_penalty" type="float" label="BAQ gap open penalty (Phred Scaled)" value="40" help="Default value is 40. 30 is perhaps better for whole genome call sets."/><param name="use_original_qualities" type="boolean" truevalue="--useOriginalQualities" falsevalue="" label="Use the original base quality scores from the OQ tag" /><param name="default_base_qualities" type="integer" label="Value to be used for all base quality scores, when some are missing" value="-1"/><param name="validation_strictness" type="select" label="How strict should we be with validation"><option value="STRICT" selected="True">STRICT</option><option value="LENIENT">LENIENT</option><option value="SILENT">SILENT</option>
+ <!-- <option value="DEFAULT_STRINGENCY">DEFAULT_STRINGENCY</option> listed in docs, but not valid value...--></param><param name="interval_merging" type="select" label="Interval merging rule"><option value="ALL" selected="True">ALL</option><option value="OVERLAPPING_ONLY">OVERLAPPING_ONLY</option></param>
- <param name="read_group_black_list" type="data" format="txt" optional="True" label="Read group black list" />
+
+ <repeat name="read_group_black_list_repeat" title="Read group black list">
+ <conditional name="read_group_black_list_type">
+ <param name="read_group_black_list_type_selector" type="select" label="Type of reads read group black list">
+ <option value="file" selected="True">Filters in file</option>
+ <option value="text">Specify filters as a string</option>
+ </param>
+ <when value="file">
+ <param name="read_group_black_list" type="data" format="txt" label="Read group black list file" />
+ </when>
+ <when value="text">
+ <param name="read_group_black_list" type="text" value="tag:string" label="Read group black list tag:string" />
+ </when>
+ </conditional>
+ </repeat>
+
+ <param name="disable_experimental_low_memory_sharding" type="boolean" truevalue="--disable_experimental_low_memory_sharding" falsevalue="" label="Disable experimental low-memory sharding functionality." checked="False"/>
+ <param name="non_deterministic_random_seed" type="boolean" truevalue="--nonDeterministicRandomSeed" falsevalue="" label="Makes the GATK behave non deterministically, that is, the random numbers generated will be different in every run" checked="False" />
+
</when></conditional>
https://bitbucket.org/galaxy/galaxy-central/changeset/603924d3abc3/
changeset: 603924d3abc3
user: ichorny
date: 2011-10-21 23:18:09
summary: added altered config.py
affected #: 1 file
diff -r 28ab7dde097298b7565a6238f0bbcade29a73ae9 -r 603924d3abc3057def82337b53178ad48a71b1d1 lib/galaxy/config.py
--- a/lib/galaxy/config.py
+++ b/lib/galaxy/config.py
@@ -104,6 +104,10 @@
self.pbs_dataset_server = kwargs.get('pbs_dataset_server', "" )
self.pbs_dataset_path = kwargs.get('pbs_dataset_path', "" )
self.pbs_stage_path = kwargs.get('pbs_stage_path', "" )
+ self.drmaa_external_runjob_script = kwargs.get('drmaa_external_runjob_script', None )
+ self.drmaa_external_killjob_script = kwargs.get('drmaa_external_killjob_script', None)
+ self.external_chown_script = kwargs.get('external_chown_script', None)
+ self.TMPDIR = kwargs.get('TMPDIR', None)
self.use_heartbeat = string_as_bool( kwargs.get( 'use_heartbeat', 'False' ) )
self.use_memdump = string_as_bool( kwargs.get( 'use_memdump', 'False' ) )
self.log_actions = string_as_bool( kwargs.get( 'log_actions', 'False' ) )
@@ -215,12 +219,21 @@
os.makedirs( path )
except Exception, e:
raise ConfigurationError( "Unable to create missing directory: %s\n%s" % ( path, e ) )
+ if self.drmaa_external_runjob_script:
+ os.chmod(self.new_file_path, 0777)
+ os.chmod(self.job_working_directory, 0777)
+ os.chmod(self.cluster_files_directory, 0777)
+ else:
+ os.chmod(self.new_file_path, 0755)
+ os.chmod(self.job_working_directory, 0755)
+ os.chmod(self.cluster_files_directory, 0755)
+
# Check that required files exist
for path in self.tool_configs:
if not os.path.isfile(path):
raise ConfigurationError("File not found: %s" % path )
if not os.path.isfile( self.datatypes_config ):
- raise ConfigurationError("File not found: %s" % path )
+ raise ConfigurationError("File not found: %s" % self.datatypes_config )
# Check for deprecated options.
for key in self.config_dict.keys():
if key in self.deprecated_options:
https://bitbucket.org/galaxy/galaxy-central/changeset/125d735c689e/
changeset: 125d735c689e
user: natefoo
date: 2011-10-25 17:14:04
summary: merge
affected #: 50 files
diff -r 603924d3abc3057def82337b53178ad48a71b1d1 -r 125d735c689ee60ad9bd9601c7a22738ba3523de README.txt
--- a/README.txt
+++ b/README.txt
@@ -7,7 +7,7 @@
HOW TO START
============
-Galaxy requires Python 2.4, 2.5 or 2.6. To check your python version, run:
+Galaxy requires Python 2.5, 2.6 or 2.7. To check your python version, run:
% python -V
Python 2.4.4
diff -r 603924d3abc3057def82337b53178ad48a71b1d1 -r 125d735c689ee60ad9bd9601c7a22738ba3523de lib/galaxy/web/controllers/tracks.py
--- a/lib/galaxy/web/controllers/tracks.py
+++ b/lib/galaxy/web/controllers/tracks.py
@@ -646,7 +646,7 @@
# TODO: unpack and validate bookmarks:
def unpack_bookmarks( bookmarks_json ):
- return
+ return bookmarks_json
# Unpack and validate view content.
view_content = unpack_collection( decoded_payload[ 'view' ] )
diff -r 603924d3abc3057def82337b53178ad48a71b1d1 -r 125d735c689ee60ad9bd9601c7a22738ba3523de static/images/fugue/application-dock-270-bw.png
Binary file static/images/fugue/application-dock-270-bw.png has changed
diff -r 603924d3abc3057def82337b53178ad48a71b1d1 -r 125d735c689ee60ad9bd9601c7a22738ba3523de static/images/fugue/application-dock-270.png
Binary file static/images/fugue/application-dock-270.png has changed
diff -r 603924d3abc3057def82337b53178ad48a71b1d1 -r 125d735c689ee60ad9bd9601c7a22738ba3523de static/images/fugue/block--plus-bw.png
Binary file static/images/fugue/block--plus-bw.png has changed
diff -r 603924d3abc3057def82337b53178ad48a71b1d1 -r 125d735c689ee60ad9bd9601c7a22738ba3523de static/images/fugue/block--plus.png
Binary file static/images/fugue/block--plus.png has changed
diff -r 603924d3abc3057def82337b53178ad48a71b1d1 -r 125d735c689ee60ad9bd9601c7a22738ba3523de static/images/fugue/bookmarks-bw.png
Binary file static/images/fugue/bookmarks-bw.png has changed
diff -r 603924d3abc3057def82337b53178ad48a71b1d1 -r 125d735c689ee60ad9bd9601c7a22738ba3523de static/images/fugue/bookmarks.png
Binary file static/images/fugue/bookmarks.png has changed
diff -r 603924d3abc3057def82337b53178ad48a71b1d1 -r 125d735c689ee60ad9bd9601c7a22738ba3523de static/images/fugue/cross-circle-bw.png
Binary file static/images/fugue/cross-circle-bw.png has changed
diff -r 603924d3abc3057def82337b53178ad48a71b1d1 -r 125d735c689ee60ad9bd9601c7a22738ba3523de static/images/fugue/cross-circle.png
Binary file static/images/fugue/cross-circle.png has changed
diff -r 603924d3abc3057def82337b53178ad48a71b1d1 -r 125d735c689ee60ad9bd9601c7a22738ba3523de static/images/fugue/cross-small-bw.png
Binary file static/images/fugue/cross-small-bw.png has changed
diff -r 603924d3abc3057def82337b53178ad48a71b1d1 -r 125d735c689ee60ad9bd9601c7a22738ba3523de static/images/fugue/disk--arrow-bw.png
Binary file static/images/fugue/disk--arrow-bw.png has changed
diff -r 603924d3abc3057def82337b53178ad48a71b1d1 -r 125d735c689ee60ad9bd9601c7a22738ba3523de static/images/fugue/disk--arrow.png
Binary file static/images/fugue/disk--arrow.png has changed
diff -r 603924d3abc3057def82337b53178ad48a71b1d1 -r 125d735c689ee60ad9bd9601c7a22738ba3523de static/images/fugue/gear-bw.png
Binary file static/images/fugue/gear-bw.png has changed
diff -r 603924d3abc3057def82337b53178ad48a71b1d1 -r 125d735c689ee60ad9bd9601c7a22738ba3523de static/images/fugue/gear.png
Binary file static/images/fugue/gear.png has changed
diff -r 603924d3abc3057def82337b53178ad48a71b1d1 -r 125d735c689ee60ad9bd9601c7a22738ba3523de static/images/fugue/plus-button-bw.png
Binary file static/images/fugue/plus-button-bw.png has changed
diff -r 603924d3abc3057def82337b53178ad48a71b1d1 -r 125d735c689ee60ad9bd9601c7a22738ba3523de static/images/fugue/plus-button.png
Binary file static/images/fugue/plus-button.png has changed
diff -r 603924d3abc3057def82337b53178ad48a71b1d1 -r 125d735c689ee60ad9bd9601c7a22738ba3523de static/images/fugue/toolbox-bw.png
Binary file static/images/fugue/toolbox-bw.png has changed
diff -r 603924d3abc3057def82337b53178ad48a71b1d1 -r 125d735c689ee60ad9bd9601c7a22738ba3523de static/images/fugue/toolbox.png
Binary file static/images/fugue/toolbox.png has changed
diff -r 603924d3abc3057def82337b53178ad48a71b1d1 -r 125d735c689ee60ad9bd9601c7a22738ba3523de static/images/fugue/ui-slider-050-bw.png
Binary file static/images/fugue/ui-slider-050-bw.png has changed
diff -r 603924d3abc3057def82337b53178ad48a71b1d1 -r 125d735c689ee60ad9bd9601c7a22738ba3523de static/images/fugue/ui-slider-050.png
Binary file static/images/fugue/ui-slider-050.png has changed
diff -r 603924d3abc3057def82337b53178ad48a71b1d1 -r 125d735c689ee60ad9bd9601c7a22738ba3523de static/june_2007_style/blue/trackster.css
--- a/static/june_2007_style/blue/trackster.css
+++ b/static/june_2007_style/blue/trackster.css
@@ -3,9 +3,30 @@
.content{font:10px verdana;}
.nav-controls{text-align:center;padding:1px 0;}
.nav-controls input{margin:0 5px;}
+.menu-button{padding: 0px 4px 0px 4px;}
#zoom-in,#zoom-out{display:inline-block;height:16px;width:16px;margin-bottom:-3px;cursor:pointer;}
#zoom-out{background:transparent url(../images/fugue/magnifier-zoom-out.png) center center no-repeat;}
#zoom-in{margin-left:10px;background:transparent url(../images/fugue/magnifier-zoom.png) center center no-repeat;}
+.overview-icon{background:transparent url(../images/fugue/application-dock-270-bw.png) no-repeat;}
+.overview-icon:hover{background:transparent url(../images/fugue/application-dock-270.png) no-repeat;}
+.settings-icon{background:transparent url(../images/fugue/gear-bw.png) no-repeat;}
+.settings-icon:hover{background:transparent url(../images/fugue/gear.png) no-repeat;}
+.tools-icon{background:transparent url(../images/fugue/toolbox-bw.png) no-repeat;}
+.tools-icon:hover{background:transparent url(../images/fugue/toolbox.png) no-repeat;}
+.filters-icon{background:transparent url(../images/fugue/ui-slider-050-bw.png) no-repeat;}
+.filters-icon:hover{background:transparent url(../images/fugue/ui-slider-050.png) no-repeat;}
+.remove-icon,.overview-close{background:transparent url(../images/fugue/cross-small-bw.png) no-repeat;}
+.remove-icon:hover,.overview-close:hover{background:transparent url(../images/fugue/cross-circle.png) no-repeat;}
+#close-icon{background:transparent url(../images/fugue/cross-circle-bw.png) no-repeat;margin-right:0px;}
+#close-icon:hover{background:transparent url(../images/fugue/cross-circle.png) no-repeat;}
+#add-tracks-icon{background:transparent url(../images/fugue/plus-button-bw.png) no-repeat;}
+#add-tracks-icon:hover{background:transparent url(../images/fugue/plus-button.png) no-repeat;}
+#add-group-icon{background:transparent url(../images/fugue/block--plus-bw.png) no-repeat;}
+#add-group-icon:hover{background:transparent url(../images/fugue/block--plus.png) no-repeat;}
+#bookmarks-icon{background:transparent url(../images/fugue/bookmarks-bw.png) no-repeat;}
+#bookmarks-icon:hover{background:transparent url(../images/fugue/bookmarks.png) no-repeat;}
+#save-icon{background:transparent url(../images/fugue/disk--arrow-bw.png) no-repeat;}
+#save-icon:hover{background:transparent url(../images/fugue/disk--arrow.png) no-repeat;}
.nav-input{font-size:12px;width:30em;z-index:1000;}
.location{display:inline-block;width:15em;margin:0 10px;}
.draghandle{margin-top:2px;cursor:move;float:left;background:transparent url(../images/visualization/draggable_horizontal.png) center center no-repeat;width:10px;height:12px;}
@@ -19,12 +40,13 @@
.viewport-canvas{width:100%;height:100px;}
.yaxislabel{color:#777;z-index:100;}
.line-track .track-content{border-top:1px solid #eee;border-bottom:1px solid #eee;}
-.group-handle{cursor:move;float:left;background:#eee url('/static/images/tracks/block.png');width:12px;height:12px;}
+.group-handle{cursor:move;float:left;background:#eee url('../images/tracks/block.png');width:12px;height:12px;}
.group{min-height:20px;border-top:2px solid #888;border-bottom:2px solid #888;}
.track{background:white;}
.track-header{text-align:left;padding:4px 0px;color:#666;}
.track-header .menubutton{margin-left:0px;}
-.track-content{text-align:center;border-top:1px solid #eee;border-bottom:2px solid #eee;background:#eee url('/static/images/tracks/diag_bg.gif');min-height:16px;}
+.track-content{text-align:center;border-top:1px solid #eee;border-bottom:2px solid #eee;background:#eee url('../images/tracks/diag_bg.gif');min-height:16px;}
+.track-name{float:left;margin-top:2px;height:16px;}
.label-track .track-content{background:white;}
.track-tile{background:white;}
.track-tile canvas{position:relative;z-index:100;}
diff -r 603924d3abc3057def82337b53178ad48a71b1d1 -r 125d735c689ee60ad9bd9601c7a22738ba3523de static/june_2007_style/trackster.css.tmpl
--- a/static/june_2007_style/trackster.css.tmpl
+++ b/static/june_2007_style/trackster.css.tmpl
@@ -130,7 +130,7 @@
.group-handle {
cursor: move;
float: left;
- background: #eee url('/static/images/tracks/block.png');
+ background: #eee url('../images/tracks/block.png');
width: 12px;
height: 12px;
}
@@ -159,10 +159,16 @@
text-align: center;
border-top: 1px solid #eee;
border-bottom: 2px solid #eee;
- background: #eee url('/static/images/tracks/diag_bg.gif');
+ background: #eee url('../images/tracks/diag_bg.gif');
min-height: 16px;
}
+.track-name {
+ float: left;
+ margin-top: 2px;
+ height: 16px;
+}
+
.label-track .track-content {
background: white;
}
@@ -288,6 +294,70 @@
font-weight: bold;
padding-top: 0.2em;
}
+.menu-button {
+ padding: 0px 4px 0px 4px;
+}
+.settings-icon {
+ background: transparent url(../images/fugue/gear-bw.png) no-repeat;
+}
+.settings-icon:hover {
+ background: transparent url(../images/fugue/gear.png) no-repeat;
+}
+.overview-icon {
+ background:transparent url(../images/fugue/application-dock-270-bw.png) no-repeat;
+}
+.overview-icon:hover {
+ background:transparent url(../images/fugue/application-dock-270.png) no-repeat;
+}
+
+.tools-icon {
+ background: transparent url(../images/fugue/toolbox-bw.png) no-repeat;
+}
+.tools-icon:hover {
+ background: transparent url(../images/fugue/toolbox.png) no-repeat;
+}
+.filters-icon {
+ background: transparent url(../images/fugue/ui-slider-050-bw.png) no-repeat;
+}
+.filters-icon:hover {
+ background: transparent url(../images/fugue/ui-slider-050.png) no-repeat;
+}
+.remove-icon, .overview-close {
+ background: transparent url(../images/fugue/cross-small-bw.png) no-repeat;
+}
+.remove-icon:hover, .overview-close:hover {
+ background: transparent url(../images/fugue/cross-circle.png) no-repeat;
+}
+#close-icon {
+ background: transparent url(../images/fugue/cross-circle-bw.png) no-repeat;margin-right:0px;
+}
+#close-icon:hover {
+ background: transparent url(../images/fugue/cross-circle.png) no-repeat;
+}
+#add-tracks-icon {
+ background: transparent url(../images/fugue/plus-button-bw.png) no-repeat;
+}
+#add-tracks-icon:hover {
+ background: transparent url(../images/fugue/plus-button.png) no-repeat;
+}
+#add-group-icon {
+ background: transparent url(../images/fugue/block--plus-bw.png) no-repeat;
+}
+#add-group-icon:hover {
+ background: transparent url(../images/fugue/block--plus.png) no-repeat;
+}
+#bookmarks-icon {
+ background: transparent url(../images/fugue/bookmarks-bw.png) no-repeat;
+}
+#bookmarks-icon:hover {
+ background: transparent url(../images/fugue/bookmarks.png) no-repeat;
+}
+#save-icon {
+ background: transparent url(../images/fugue/disk--arrow-bw.png) no-repeat;
+}
+#save-icon:hover {
+ background: transparent url(../images/fugue/disk--arrow.png) no-repeat;
+}
.child-track-icon {
background:url('../images/fugue/arrow-000-small-bw.png') no-repeat;
width: 30px;
@@ -317,7 +387,6 @@
.delete-icon-container {
float:right;
}
-
.icon {
display:inline-block;
width:16px;
diff -r 603924d3abc3057def82337b53178ad48a71b1d1 -r 125d735c689ee60ad9bd9601c7a22738ba3523de static/scripts/galaxy.base.js
--- a/static/scripts/galaxy.base.js
+++ b/static/scripts/galaxy.base.js
@@ -698,6 +698,8 @@
});
// Tooltips
if ( $.fn.tipsy ) {
+ // FIXME: tipsy gravity cannot be updated, so need classes that specify N/S gravity and
+ // initialize each separately.
$(".tooltip").tipsy( { gravity: 's' } );
}
// Make popup menus.
diff -r 603924d3abc3057def82337b53178ad48a71b1d1 -r 125d735c689ee60ad9bd9601c7a22738ba3523de static/scripts/packed/trackster.js
--- a/static/scripts/packed/trackster.js
+++ b/static/scripts/packed/trackster.js
@@ -1,1 +1,1 @@
-var class_module=function(b,a){var c=function(){var f=arguments[0];for(var e=1;e<arguments.length;e++){var d=arguments[e];for(key in d){f[key]=d[key]}}return f};a.extend=c};var requestAnimationFrame=(function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(b,a){window.setTimeout(b,1000/60)}})();var BEFORE=1001,CONTAINS=1002,OVERLAP_START=1003,OVERLAP_END=1004,CONTAINED_BY=1005,AFTER=1006;var compute_overlap=function(e,b){var g=e[0],f=e[1],d=b[0],c=b[1],a;if(g<d){if(f<d){a=BEFORE}else{if(f<=c){a=OVERLAP_START}else{a=CONTAINS}}}else{if(g>c){a=AFTER}else{if(f<=c){a=CONTAINED_BY}else{a=OVERLAP_END}}}return a};var is_overlap=function(c,b){var a=compute_overlap(c,b);return(a!==BEFORE&&a!==AFTER)};var trackster_module=function(f,Z){var q=f("class").extend,t=f("slotting"),N=f("painters");var ag=function(ah,ai){this.document=ah;this.default_font=ai!==undefined?ai:"9px Monaco, Lucida Console, monospace";this.dummy_canvas=this.new_canvas();this.dummy_context=this.dummy_canvas.getContext("2d");this.dummy_context.font=this.default_font;this.char_width_px=this.dummy_context.measureText("A").width;this.patterns={};this.load_pattern("right_strand","/visualization/strand_right.png");this.load_pattern("left_strand","/visualization/strand_left.png");this.load_pattern("right_strand_inv","/visualization/strand_right_inv.png");this.load_pattern("left_strand_inv","/visualization/strand_left_inv.png")};q(ag.prototype,{load_pattern:function(ah,al){var ai=this.patterns,aj=this.dummy_context,ak=new Image();ak.src=image_path+al;ak.onload=function(){ai[ah]=aj.createPattern(ak,"repeat")}},get_pattern:function(ah){return this.patterns[ah]},new_canvas:function(){var ah=this.document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(ah)}ah.manager=this;return ah}});var o={};var m=function(ah,ai){o[ah.attr("id")]=ai};var n=function(ah,aj,al,ak){al=".group";var ai={};o[ah.attr("id")]=ak;ah.bind("drag",{handle:"."+aj,relative:true},function(au,av){var at=$(this);var ay=$(this).parent(),ap=ay.children(),ar=o[$(this).attr("id")],ao,an,aw,am,aq;an=$(this).parents(al);if(an.length!==0){aw=an.position().top;am=aw+an.outerHeight();if(av.offsetY<aw){$(this).insertBefore(an);var ax=o[an.attr("id")];ax.remove_drawable(ar);ax.container.add_drawable_before(ar,ax);return}else{if(av.offsetY>am){$(this).insertAfter(an);var ax=o[an.attr("id")];ax.remove_drawable(ar);ax.container.add_drawable(ar);return}}}an=null;for(aq=0;aq<ap.length;aq++){ao=$(ap.get(aq));aw=ao.position().top;am=aw+ao.outerHeight();if(ao.is(al)&&this!==ao.get(0)&&av.offsetY>=aw&&av.offsetY<=am){if(av.offsetY-aw<am-av.offsetY){ao.find(".content-div").prepend(this)}else{ao.find(".content-div").append(this)}if(ar.container){ar.container.remove_drawable(ar)}o[ao.attr("id")].add_drawable(ar);return}}for(aq=0;aq<ap.length;aq++){if(av.offsetY<$(ap.get(aq)).position().top){break}}if(aq===ap.length){if(this!==ap.get(aq-1)){ay.append(this);o[ay.attr("id")].move_drawable(ar,aq)}}else{if(this!==ap.get(aq)){$(this).insertBefore(ap.get(aq));o[ay.attr("id")].move_drawable(ar,(av.deltaY>0?aq-1:aq))}}}).bind("dragstart",function(){ai["border-top"]=ah.css("border-top");ai["border-bottom"]=ah.css("border-bottom");$(this).css({"border-top":"1px solid blue","border-bottom":"1px solid blue"})}).bind("dragend",function(){$(this).css(ai)})};Z.moveable=n;var af=16,I=9,F=20,U=I+2,A=100,K=12000,S=200,D=5,w=10,M=5000,x=100,p="There was an error in indexing this dataset. ",L="A converter for this dataset is not installed. Please check your datatypes_conf.xml file.",G="No data for this chrom/contig.",u="Currently indexing... please wait",y="Tool cannot be rerun: ",a="Loading data...",aa="Ready for display",d=10,v=5,C=5;function ab(ai,ah){if(!ah){ah=0}var aj=Math.pow(10,ah);return Math.round(ai*aj)/aj}var c=function(ah){this.num_elements=ah;this.clear()};q(c.prototype,{get:function(ai){var ah=this.key_ary.indexOf(ai);if(ah!==-1){if(this.obj_cache[ai].stale){this.key_ary.splice(ah,1);delete this.obj_cache[ai]}else{this.move_key_to_end(ai,ah)}}return this.obj_cache[ai]},set:function(ai,aj){if(!this.obj_cache[ai]){if(this.key_ary.length>=this.num_elements){var ah=this.key_ary.shift();delete this.obj_cache[ah]}this.key_ary.push(ai)}this.obj_cache[ai]=aj;return aj},move_key_to_end:function(ai,ah){this.key_ary.splice(ah,1);this.key_ary.push(ai)},clear:function(){this.obj_cache={};this.key_ary=[]},size:function(){return this.key_ary.length}});var T=function(ai,ah,aj){c.call(this,ai);this.track=ah;this.subset=(aj!==undefined?aj:true)};q(T.prototype,c.prototype,{load_data:function(aq,al,ao,ai,an){var ap=this.track.view.chrom,ak={chrom:ap,low:aq,high:al,mode:ao,resolution:ai,dataset_id:this.track.dataset_id,hda_ldda:this.track.hda_ldda};$.extend(ak,an);if(this.track.filters_manager){var ar=[];var ah=this.track.filters_manager.filters;for(var am=0;am<ah.length;am++){ar[ar.length]=ah[am].name}ak.filter_cols=JSON.stringify(ar)}var aj=this;return $.getJSON(this.track.data_url,ak,function(at){aj.set_data(aq,al,ao,at)})},get_data:function(ah,al,am,ai,ak){var aj=this.get_data_from_cache(ah,al,am);if(aj){return aj}aj=this.load_data(ah,al,am,ai,ak);this.set_data(ah,al,am,aj);return aj},DEEP_DATA_REQ:"deep",BROAD_DATA_REQ:"breadth",get_more_data:function(ap,ak,ao,aj,an,al){var aq=this.get_data_from_cache(ap,ak,ao);if(!aq){console.log("ERROR: no current data for: ",this.track,ap,ak,ao,aj,an);return}aq.stale=true;var ai=ap;if(al===this.DEEP_DATA_REQ){$.extend(an,{start_val:aq.data.length+1})}else{if(al===this.BROAD_DATA_REQ){ai=(aq.max_high?aq.max_high:aq.data[aq.data.length-1][2])+1}}var ah=this,am=this.load_data(ai,ak,ao,aj,an);new_data_available=$.Deferred();this.set_data(ap,ak,ao,new_data_available);$.when(am).then(function(ar){if(ar.data){ar.data=aq.data.concat(ar.data);if(ar.max_low){ar.max_low=aq.max_low}if(ar.message){ar.message=ar.message.replace(/[0-9]+/,ar.data.length)}}ah.set_data(ap,ak,ao,ar);new_data_available.resolve(ar)});return new_data_available},get_data_from_cache:function(ah,ai,aj){return this.get(this.gen_key(ah,ai,aj))},set_data:function(ai,aj,ak,ah){return this.set(this.gen_key(ai,aj,ak),ah)},gen_key:function(ah,aj,ak){var ai=ah+"_"+aj+"_"+ak;return ai},split_key:function(ah){return ah.split("_")}});var J=function(ai,ah,aj){T.call(this,ai,ah,aj)};q(J.prototype,T.prototype,c.prototype,{load_data:function(aj,ah,al,am,ai,ak){if(ai>1){return}return T.prototype.load_data.call(this,aj,ah,al,am,ai,ak)}});var r=function(ak,ai,ah,aj,al){this.name=ak;this.view=ai;this.container=ah;this.drag_handle_class=al;this.config=new H({track:this,params:[{key:"name",label:"Name",type:"text",default_value:ak}],saved_values:aj,onchange:function(){this.track.set_name(this.track.config.values.name)}});this.prefs=this.config.values};q(r.prototype,{init:function(){},request_draw:function(){},_draw:function(){},to_json:function(){},make_name_popup_menu:function(){},set_name:function(ah){this.old_name=this.name;this.name=ah;this.name_div.text(this.name)},revert_name:function(){this.name=this.old_name;this.name_div.text(this.name)},remove:function(){this.container.remove_drawable(this);this.container_div.fadeOut("slow",function(){$(this).remove();view.update_intro_div();view.has_changes=true})}});var z=function(al,ak,ai,ah,aj,am){r.call(this,ak,ai,ah,aj,am);this.obj_type=al;this.drawables=[]};q(z.prototype,r.prototype,{init:function(){for(var ah=0;ah<this.drawables.length;ah++){this.drawables[ah].init()}},_draw:function(){for(var ah=0;ah<this.drawables.length;ah++){this.drawables[ah]._draw()}},to_json:function(){var ai=[];for(var ah=0;ah<this.drawables.length;ah++){ai.push(this.drawables[ah].to_json())}return{name:this.name,prefs:this.prefs,obj_type:this.obj_type,drawables:ai}},add_drawable:function(ah){this.drawables.push(ah);ah.container=this},add_drawable_before:function(aj,ah){var ai=this.drawables.indexOf(ah);if(ai!=-1){this.drawables.splice(ai,0,aj);return true}return false},remove_drawable:function(ai){var ah=this.drawables.indexOf(ai);if(ah!=-1){this.drawables.splice(ah,1);ai.container=null;return true}return false},move_drawable:function(ai,aj){var ah=this.drawables.indexOf(ai);if(ah!=-1){this.drawables.splice(ah,1);this.drawables.splice(aj,0,ai);return true}return false}});var R=function(ak,ai,ah,aj){z.call(this,"DrawableGroup",ak,ai,ah,aj,"group-handle");if(!R.id_counter){R.id_counter=0}var al=R.id_counter++;this.container_div=$("<div/>").addClass("group").attr("id","group_"+al).appendTo(this.container.content_div);this.header_div=$("<div/>").addClass("track-header").appendTo(this.container_div);this.header_div.append($("<div/>").addClass(this.drag_handle_class));this.name_div=$("<div/>").addClass("group-name menubutton popup").text(this.name).appendTo(this.header_div);this.content_div=$("<div/>").addClass("content-div").attr("id","group_"+al+"_content_div").appendTo(this.container_div);m(this.container_div,this);m(this.content_div,this);n(this.container_div,this.drag_handle_class,".group",this);this.make_name_popup_menu()};q(R.prototype,r.prototype,z.prototype,{make_name_popup_menu:function(){var ai=this;var ah={};ah["Edit configuration"]=function(){var al=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},aj=function(){ai.config.update_from_form($(".dialog-box"));hide_modal();$(window).unbind("keypress.check_enter_esc")},ak=function(am){if((am.keyCode||am.which)===27){al()}else{if((am.keyCode||am.which)===13){aj()}}};$(window).bind("keypress.check_enter_esc",ak);show_modal("Configure Group",ai.config.build_form(),{Cancel:al,OK:aj})};ah.Remove=function(){ai.remove()};make_popupmenu(ai.name_div,ah)}});var ae=function(ah,ak,aj,ai){z.call(this,"View");this.container=ah;this.chrom=null;this.vis_id=aj;this.dbkey=ai;this.title=ak;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.init();this.canvas_manager=new ag(ah.get(0).ownerDocument);this.reset()};q(ae.prototype,z.prototype,{init:function(){var aj=this.container,ah=this;this.top_container=$("<div/>").addClass("top-container").appendTo(aj);this.browser_content_div=$("<div/>").addClass("content").css("position","relative").appendTo(aj);this.bottom_container=$("<div/>").addClass("bottom-container").appendTo(aj);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;m(this.viewport_container,ah);this.intro_div=$("<div/>").addClass("intro");var ak=$("<div/>").text("Add Datasets to Visualization").addClass("action-button").appendTo(this.intro_div).click(function(){add_tracks()});this.nav_labeltrack=$("<div/>").addClass("nav-labeltrack").appendTo(this.bottom_container);this.nav_container=$("<div/>").addClass("nav-container").prependTo(this.top_container);this.nav=$("<div/>").addClass("nav").appendTo(this.nav_container);this.overview=$("<div/>").addClass("overview").appendTo(this.bottom_container);this.overview_viewport=$("<div/>").addClass("overview-viewport").appendTo(this.overview);this.overview_close=$("<a href='javascript:void(0);'>Close Overview</a>").addClass("overview-close").hide().appendTo(this.overview_viewport);this.overview_highlight=$("<div/>").addClass("overview-highlight").hide().appendTo(this.overview_viewport);this.overview_box_background=$("<div/>").addClass("overview-boxback").appendTo(this.overview_viewport);this.overview_box=$("<div/>").addClass("overview-box").appendTo(this.overview_viewport);this.default_overview_height=this.overview_box.height();this.nav_controls=$("<div/>").addClass("nav-controls").appendTo(this.nav);this.chrom_select=$("<select/>").attr({name:"chrom"}).css("width","15em").addClass("no-autocomplete").append("<option value=''>Loading</option>").appendTo(this.nav_controls);var ai=function(al){if(al.type==="focusout"||(al.keyCode||al.which)===13||(al.keyCode||al.which)===27){if((al.keyCode||al.which)!==27){ah.go_to($(this).val())}$(this).hide();$(this).val("");ah.location_span.show();ah.chrom_select.show()}};this.nav_input=$("<input/>").addClass("nav-input").hide().bind("keyup focusout",ai).appendTo(this.nav_controls);this.location_span=$("<span/>").addClass("location").appendTo(this.nav_controls);this.location_span.click(function(){ah.location_span.hide();ah.chrom_select.hide();ah.nav_input.val(ah.chrom+":"+ah.low+"-"+ah.high);ah.nav_input.css("display","inline-block");ah.nav_input.select();ah.nav_input.focus()});if(this.vis_id!==undefined){this.hidden_input=$("<input/>").attr("type","hidden").val(this.vis_id).appendTo(this.nav_controls)}this.zo_link=$("<a id='zoom-out' />").click(function(){ah.zoom_out();ah.request_redraw()}).appendTo(this.nav_controls);this.zi_link=$("<a id='zoom-in' />").click(function(){ah.zoom_in();ah.request_redraw()}).appendTo(this.nav_controls);this.load_chroms_deferred=this.load_chroms({low:0});this.chrom_select.bind("change",function(){ah.change_chrom(ah.chrom_select.val())});this.browser_content_div.click(function(al){$(this).find("input").trigger("blur")});this.browser_content_div.bind("dblclick",function(al){ah.zoom_in(al.pageX,this.viewport_container)});this.overview_box.bind("dragstart",function(al,am){this.current_x=am.offsetX}).bind("drag",function(al,an){var ao=an.offsetX-this.current_x;this.current_x=an.offsetX;var am=Math.round(ao/ah.viewport_container.width()*(ah.max_high-ah.max_low));ah.move_delta(-am)});this.overview_close.click(function(){ah.reset_overview()});this.viewport_container.bind("draginit",function(al,am){if(al.clientX>ah.viewport_container.width()-16){return false}}).bind("dragstart",function(al,am){am.original_low=ah.low;am.current_height=al.clientY;am.current_x=am.offsetX}).bind("drag",function(an,ap){var al=$(this);var aq=ap.offsetX-ap.current_x;var am=al.scrollTop()-(an.clientY-ap.current_height);al.scrollTop(am);ap.current_height=an.clientY;ap.current_x=ap.offsetX;var ao=Math.round(aq/ah.viewport_container.width()*(ah.high-ah.low));ah.move_delta(ao)}).bind("mousewheel",function(an,ap,am,al){if(am){var ao=Math.round(-am/ah.viewport_container.width()*(ah.high-ah.low));ah.move_delta(ao)}});this.top_labeltrack.bind("dragstart",function(al,am){return $("<div />").css({height:ah.browser_content_div.height()+ah.top_labeltrack.height()+ah.nav_labeltrack.height()+1,top:"0px",position:"absolute","background-color":"#ccf",opacity:0.5,"z-index":1000}).appendTo($(this))}).bind("drag",function(ap,aq){$(aq.proxy).css({left:Math.min(ap.pageX,aq.startX),width:Math.abs(ap.pageX-aq.startX)});var am=Math.min(ap.pageX,aq.startX)-ah.container.offset().left,al=Math.max(ap.pageX,aq.startX)-ah.container.offset().left,ao=(ah.high-ah.low),an=ah.viewport_container.width();ah.update_location(Math.round(am/an*ao)+ah.low,Math.round(al/an*ao)+ah.low)}).bind("dragend",function(aq,ar){var am=Math.min(aq.pageX,ar.startX),al=Math.max(aq.pageX,ar.startX),ao=(ah.high-ah.low),an=ah.viewport_container.width(),ap=ah.low;ah.low=Math.round(am/an*ao)+ap;ah.high=Math.round(al/an*ao)+ap;$(ar.proxy).remove();ah.request_redraw()});this.add_label_track(new ad(this,{content_div:this.top_labeltrack}));this.add_label_track(new ad(this,{content_div:this.nav_labeltrack}));$(window).bind("resize",function(){ah.resize_window()});$(document).bind("redraw",function(){ah.redraw()});this.reset();$(window).trigger("resize");this.update_intro_div()},update_intro_div:function(){if(this.num_tracks===0){this.intro_div.appendTo(this.viewport_container)}else{this.intro_div.remove()}},update_location:function(ah,ai){this.location_span.text(commatize(ah)+" - "+commatize(ai));this.nav_input.val(this.chrom+":"+commatize(ah)+"-"+commatize(ai))},load_chroms:function(aj){aj.num=x;$.extend(aj,(this.vis_id!==undefined?{vis_id:this.vis_id}:{dbkey:this.dbkey}));var ah=this,ai=$.Deferred();$.ajax({url:chrom_url,data:aj,dataType:"json",success:function(al){if(al.chrom_info.length===0){alert("Invalid chromosome: "+aj.chrom);return}if(al.reference){ah.add_label_track(new B(ah))}ah.chrom_data=al.chrom_info;var ao='<option value="">Select Chrom/Contig</option>';for(var an=0,ak=ah.chrom_data.length;an<ak;an++){var am=ah.chrom_data[an].chrom;ao+='<option value="'+am+'">'+am+"</option>"}if(al.prev_chroms){ao+='<option value="previous">Previous '+x+"</option>"}if(al.next_chroms){ao+='<option value="next">Next '+x+"</option>"}ah.chrom_select.html(ao);ah.chrom_start_index=al.start_index;ai.resolve(al)},error:function(){alert("Could not load chroms for this dbkey:",ah.dbkey)}});return ai},change_chrom:function(am,ai,ao){if(!am||am==="None"){return}var aj=this;if(am==="previous"){aj.load_chroms({low:this.chrom_start_index-x});return}if(am==="next"){aj.load_chroms({low:this.chrom_start_index+x});return}var an=$.grep(aj.chrom_data,function(ap,aq){return ap.chrom===am})[0];if(an===undefined){aj.load_chroms({chrom:am},function(){aj.change_chrom(am,ai,ao)});return}else{if(am!==aj.chrom){aj.chrom=am;aj.chrom_select.val(aj.chrom);aj.max_high=an.len-1;aj.reset();aj.request_redraw(true);for(var al=0,ah=aj.drawables.length;al<ah;al++){var ak=aj.drawables[al];if(ak.init){ak.init()}}}if(ai!==undefined&&ao!==undefined){aj.low=Math.max(ai,0);aj.high=Math.min(ao,aj.max_high)}aj.reset_overview();aj.request_redraw()}},go_to:function(al){var ap=this,ah,ak,ai=al.split(":"),an=ai[0],ao=ai[1];if(ao!==undefined){try{var am=ao.split("-");ah=parseInt(am[0].replace(/,/g,""),10);ak=parseInt(am[1].replace(/,/g,""),10)}catch(aj){return false}}ap.change_chrom(an,ah,ak)},move_fraction:function(aj){var ah=this;var ai=ah.high-ah.low;this.move_delta(aj*ai)},move_delta:function(aj){var ah=this;var ai=ah.high-ah.low;if(ah.low-aj<ah.max_low){ah.low=ah.max_low;ah.high=ah.max_low+ai}else{if(ah.high-aj>ah.max_high){ah.high=ah.max_high;ah.low=ah.max_high-ai}else{ah.high-=aj;ah.low-=aj}}ah.request_redraw()},add_drawable:function(ah){z.prototype.add_drawable.call(this,ah);ah.init();this.has_changes=true;this.update_intro_div()},add_label_track:function(ah){ah.view=this;ah.init();this.label_tracks.push(ah)},remove_drawable:function(aj,ai){z.prototype.remove_drawable.call(this,aj);if(ai){var ah=this;aj.container_div.fadeOut("slow",function(){$(this).remove();ah.update_intro_div()});this.has_changes=true}},reset:function(){this.low=this.max_low;this.high=this.max_high;this.viewport_container.find(".yaxislabel").remove()},request_redraw:function(ap,ah,ao,ai){var an=this,al=(ai?[ai]:an.drawables),aj;var ai;for(var am=0;am<al.length;am++){ai=al[am];aj=-1;for(var ak=0;ak<an.tracks_to_be_redrawn.length;ak++){if(an.tracks_to_be_redrawn[ak][0]===ai){aj=ak;break}}if(aj<0){an.tracks_to_be_redrawn.push([ai,ah,ao])}else{an.tracks_to_be_redrawn[am][1]=ah;an.tracks_to_be_redrawn[am][2]=ao}}requestAnimationFrame(function(){an._redraw(ap)})},_redraw:function(ar){var ao=this.low,ak=this.high;if(ao<this.max_low){ao=this.max_low}if(ak>this.max_high){ak=this.max_high}var aq=this.high-this.low;if(this.high!==0&&aq<this.min_separation){ak=ao+this.min_separation}this.low=Math.floor(ao);this.high=Math.ceil(ak);this.resolution=Math.pow(D,Math.ceil(Math.log((this.high-this.low)/S)/Math.log(D)));this.zoom_res=Math.pow(w,Math.max(0,Math.ceil(Math.log(this.resolution,w)/Math.log(w))));var ah=(this.low/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var an=((this.high-this.low)/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var at=13;this.overview_box.css({left:ah,width:Math.max(at,an)}).show();if(an<at){this.overview_box.css("left",ah-(at-an)/2)}if(this.overview_highlight){this.overview_highlight.css({left:ah,width:an})}this.update_location(this.low,this.high);if(!ar){var aj,ai,ap;for(var al=0,am=this.tracks_to_be_redrawn.length;al<am;al++){aj=this.tracks_to_be_redrawn[al][0];ai=this.tracks_to_be_redrawn[al][1];ap=this.tracks_to_be_redrawn[al][2];if(aj){aj._draw(ai,ap)}}this.tracks_to_be_redrawn=[];for(al=0,am=this.label_tracks.length;al<am;al++){this.label_tracks[al]._draw()}}},zoom_in:function(ai,aj){if(this.max_high===0||this.high-this.low<this.min_separation){return}var ak=this.high-this.low,al=ak/2+this.low,ah=(ak/this.zoom_factor)/2;if(ai){al=ai/this.viewport_container.width()*(this.high-this.low)+this.low}this.low=Math.round(al-ah);this.high=Math.round(al+ah);this.request_redraw()},zoom_out:function(){if(this.max_high===0){return}var ai=this.high-this.low,aj=ai/2+this.low,ah=(ai*this.zoom_factor)/2;this.low=Math.round(aj-ah);this.high=Math.round(aj+ah);this.request_redraw()},resize_window:function(){this.viewport_container.height(this.container.height()-this.top_container.height()-this.bottom_container.height());this.nav_container.width(this.container.width());this.request_redraw()},set_overview:function(ah){$.when(ah.get_overview_tile()).then(function(ai){view.overview_viewport.find(".track-tile").remove();view.overview_close.show();view.overview_viewport.append(ai.canvas);view.overview_highlight.show().height(ai.canvas.height());view.overview_viewport.height(ai.canvas.height()+view.overview_box.outerHeight());view.resize_window();if(view.overview_track){view.overview_track.set_is_overview(false)}view.overview_track=ah;ah.set_is_overview(true)});view.has_changes=true},reset_overview:function(){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();if(view.overview_track){view.overview_track.set_is_overview(false)}view.overview_track=null}});var s=function(aj,an){this.track=aj;this.name=an.name;this.params=[];var av=an.params;for(var ak=0;ak<av.length;ak++){var ap=av[ak],ai=ap.name,au=ap.label,al=unescape(ap.html),aw=ap.value,ar=ap.type;if(ar==="number"){this.params[this.params.length]=new g(ai,au,al,aw,ap.min,ap.max)}else{if(ar=="select"){this.params[this.params.length]=new P(ai,au,al,aw)}else{console.log("WARNING: unrecognized tool parameter type:",ai,ar)}}}this.parent_div=$("<div/>").addClass("dynamic-tool").hide();this.parent_div.bind("drag",function(ay){ay.stopPropagation()}).click(function(ay){ay.stopPropagation()}).bind("dblclick",function(ay){ay.stopPropagation()});var at=$("<div class='tool-name'>").appendTo(this.parent_div).text(this.name);var aq=this.params;var ao=this;$.each(this.params,function(az,aC){var aB=$("<div>").addClass("param-row").appendTo(ao.parent_div);var ay=$("<div>").addClass("param-label").text(aC.label).appendTo(aB);var aA=$("<div/>").addClass("slider").html(aC.html).appendTo(aB);aA.find(":input").val(aC.value);$("<div style='clear: both;'/>").appendTo(aB)});this.parent_div.find("input").click(function(){$(this).select()});var ax=$("<div>").addClass("param-row").appendTo(this.parent_div);var am=$("<input type='submit'>").attr("value","Run on complete dataset").appendTo(ax);var ah=$("<input type='submit'>").attr("value","Run on visible region").css("margin-left","3em").appendTo(ax);var ao=this;ah.click(function(){ao.run_on_region()});am.click(function(){ao.run_on_dataset()})};q(s.prototype,{get_param_values_dict:function(){var ah={};this.parent_div.find(":input").each(function(){var ai=$(this).attr("name"),aj=$(this).val();ah[ai]=JSON.stringify(aj)});return ah},get_param_values:function(){var ai=[];var ah={};this.parent_div.find(":input").each(function(){var aj=$(this).attr("name"),ak=$(this).val();if(aj){ai[ai.length]=ak}});return ai},run_on_dataset:function(){var ah=this;ah.run({dataset_id:this.track.original_dataset_id,tool_id:ah.name},null,function(ai){show_modal(ah.name+" is Running",ah.name+" is running on the complete dataset. Tool outputs are in dataset's history.",{Close:hide_modal})})},run_on_region:function(){var ai={dataset_id:this.track.original_dataset_id,chrom:this.track.view.chrom,low:this.track.view.low,high:this.track.view.high,tool_id:this.name},al=this.track,aj=ai.tool_id+al.tool_region_and_parameters_str(ai.chrom,ai.low,ai.high),ah,am;if(al.container===view){var ak=new R(this.name,this.track.view,this.track.container);al.container.add_drawable(ak);al.container.remove_drawable(al);ak.add_drawable(al);al.container_div.appendTo(ak.content_div);ah=ak}else{ah=al.container}if(al instanceof e){am=new W(aj,view,ah,"hda");am.change_mode(al.mode);ah.add_drawable(am)}am.content_div.text("Starting job.");this.run(ai,am,function(an){am.dataset_id=an.dataset_id;am.content_div.text("Running job.");am.init()})},run:function(ai,aj,ak){$.extend(ai,this.get_param_values_dict());var ah=function(){$.getJSON(rerun_tool_url,ai,function(al){if(al==="no converter"){aj.container_div.addClass("error");aj.content_div.text(L)}else{if(al.error){aj.container_div.addClass("error");aj.content_div.text(y+al.message)}else{if(al==="pending"){aj.container_div.addClass("pending");aj.content_div.text("Converting input data so that it can be used quickly with tool.");setTimeout(ah,2000)}else{ak(al)}}}})};ah()}});var P=function(ai,ah,aj,ak){this.name=ai;this.label=ah;this.html=aj;this.value=ak};var g=function(aj,ai,al,am,ak,ah){P.call(this,aj,ai,al,am);this.min=ak;this.max=ah};var h=function(ai,ah,aj,ak){this.name=ai;this.index=ah;this.tool_id=aj;this.tool_exp_name=ak};var X=function(ai,ah,aj,ak){h.call(this,ai,ah,aj,ak);this.low=-Number.MAX_VALUE;this.high=Number.MAX_VALUE;this.min=Number.MAX_VALUE;this.max=-Number.MAX_VALUE;this.container=null;this.slider=null;this.slider_label=null};q(X.prototype,{applies_to:function(ah){if(ah.length>this.index){return true}return false},keep:function(ah){if(!this.applies_to(ah)){return true}var ai=ah[this.index];return(isNaN(ai)||(ai>=this.low&&ai<=this.high))},update_attrs:function(ai){var ah=false;if(!this.applies_to(ai)){return ah}if(ai[this.index]<this.min){this.min=Math.floor(ai[this.index]);ah=true}if(ai[this.index]>this.max){this.max=Math.ceil(ai[this.index]);ah=true}return ah},update_ui_elt:function(){if(this.min!=this.max){this.container.show()}else{this.container.hide()}var aj=function(am,ak){var al=ak-am;return(al<=2?0.01:1)};var ai=this.slider.slider("option","min"),ah=this.slider.slider("option","max");if(this.min<ai||this.max>ah){this.slider.slider("option","min",this.min);this.slider.slider("option","max",this.max);this.slider.slider("option","step",aj(this.min,this.max));this.slider.slider("option","values",[this.min,this.max])}}});var ac=function(at,aA){this.track=at;this.filters=[];for(var av=0;av<aA.length;av++){var aw=aA[av],aB=aw.name,ah=aw.type,aj=aw.index,az=aw.tool_id,ay=aw.tool_exp_name;if(ah==="int"||ah==="float"){this.filters[av]=new X(aB,aj,az,ay)}else{console.log("ERROR: unsupported filter: ",aB,ah)}}var ak=function(aC,aD,aE){aC.click(function(){var aF=aD.text();max=parseFloat(aE.slider("option","max")),input_size=(max<=1?4:max<=1000000?max.toString().length:6),multi_value=false;if(aE.slider("option","values")){input_size=2*input_size+1;multi_value=true}aD.text("");$("<input type='text'/>").attr("size",input_size).attr("maxlength",input_size).attr("value",aF).appendTo(aD).focus().select().click(function(aG){aG.stopPropagation()}).blur(function(){$(this).remove();aD.text(aF)}).keyup(function(aK){if(aK.keyCode===27){$(this).trigger("blur")}else{if(aK.keyCode===13){var aI=aE.slider("option","min"),aG=aE.slider("option","max"),aJ=function(aL){return(isNaN(aL)||aL>aG||aL<aI)},aH=$(this).val();if(!multi_value){aH=parseFloat(aH);if(aJ(aH)){alert("Parameter value must be in the range ["+aI+"-"+aG+"]");return $(this)}}else{aH=aH.split("-");aH=[parseFloat(aH[0]),parseFloat(aH[1])];if(aJ(aH[0])||aJ(aH[1])){alert("Parameter value must be in the range ["+aI+"-"+aG+"]");return $(this)}}aE.slider((multi_value?"values":"value"),aH)}}})})};this.parent_div=$("<div/>").addClass("filters").hide();this.parent_div.bind("drag",function(aC){aC.stopPropagation()}).click(function(aC){aC.stopPropagation()}).bind("dblclick",function(aC){aC.stopPropagation()}).bind("keydown",function(aC){aC.stopPropagation()});var ax=$("<div/>").addClass("sliders").appendTo(this.parent_div);var ap=this;$.each(this.filters,function(aF,aH){aH.container=$("<div/>").addClass("filter-row slider-row").appendTo(ax);var aG=$("<div/>").addClass("elt-label").appendTo(aH.container);var aE=$("<span/>").addClass("slider-name").text(aH.name+" ").appendTo(aG);var aD=$("<span/>");var aJ=$("<span/>").addClass("slider-value").appendTo(aG).append("[").append(aD).append("]");var aC=$("<div/>").addClass("slider").appendTo(aH.container);aH.control_element=$("<div/>").attr("id",aH.name+"-filter-control").appendTo(aC);var aI=[0,0];aH.control_element.slider({range:true,min:Number.MAX_VALUE,max:-Number.MIN_VALUE,values:[0,0],slide:function(aL,aM){var aK=aM.values;aD.text(aK[0]+"-"+aK[1]);aH.low=aK[0];aH.high=aK[1];ap.track.request_draw(true,true)},change:function(aK,aL){aH.control_element.slider("option","slide").call(aH.control_element,aK,aL)}});aH.slider=aH.control_element;aH.slider_label=aD;ak(aJ,aD,aH.control_element);$("<div style='clear: both;'/>").appendTo(aH.container)});if(this.filters.length!==0){var am=$("<div/>").addClass("param-row").appendTo(ax);var ao=$("<input type='submit'/>").attr("value","Run on complete dataset").appendTo(am);var ai=this;ao.click(function(){ai.run_on_dataset()})}var ar=$("<div/>").addClass("display-controls").appendTo(this.parent_div),au,an,aq,al={Transparency:function(aC){ap.alpha_filter=aC},Height:function(aC){ap.height_filter=aC}};$.each(al,function(aE,aD){au=$("<div/>").addClass("filter-row").appendTo(ar),an=$("<span/>").addClass("elt-label").text(aE+":").appendTo(au),aq=$("<select/>").attr("name",aE+"_dropdown").css("float","right").appendTo(au);$("<option/>").attr("value",-1).text("== None ==").appendTo(aq);for(var aC=0;aC<ap.filters.length;aC++){$("<option/>").attr("value",aC).text(ap.filters[aC].name).appendTo(aq)}aq.change(function(){$(this).children("option:selected").each(function(){var aF=parseInt($(this).val());al[aE]((aF>=0?ap.filters[aF]:null));ap.track.request_draw(true,true)})});$("<div style='clear: both;'/>").appendTo(au)});$("<div style='clear: both;'/>").appendTo(this.parent_div)};q(ac.prototype,{reset_filters:function(){for(var ah=0;ah<this.filters.length;ah++){filter=this.filters[ah];filter.slider.slider("option","values",[filter.min,filter.max])}this.alpha_filter=null;this.height_filter=null},run_on_dataset:function(){var ap=function(au,ar,at){if(!(ar in au)){au[ar]=at}return au[ar]};var aj={},ah,ai,ak;for(var al=0;al<this.filters.length;al++){ah=this.filters[al];if(ah.tool_id){if(ah.min!=ah.low){ai=ap(aj,ah.tool_id,[]);ai[ai.length]=ah.tool_exp_name+" >= "+ah.low}if(ah.max!=ah.high){ai=ap(aj,ah.tool_id,[]);ai[ai.length]=ah.tool_exp_name+" <= "+ah.high}}}var an=[];for(var aq in aj){an[an.length]=[aq,aj[aq]]}var ao=an.length;(function am(ay,av){var at=av[0],au=at[0],ax=at[1],aw="("+ax.join(") and (")+")",ar={cond:aw,input:ay,target_dataset_id:ay,tool_id:au},av=av.slice(1);$.getJSON(run_tool_url,ar,function(az){if(az.error){show_modal("Filter Dataset","Error running tool "+au,{Close:hide_modal})}else{if(av.length===0){show_modal("Filtering Dataset","Filter(s) are running on the complete dataset. Outputs are in dataset's history.",{Close:hide_modal})}else{am(az.dataset_id,av)}}})})(this.track.dataset_id,an)}});var E=function(ah,ai){N.Scaler.call(this,ai);this.filter=ah};E.prototype.gen_val=function(ah){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(ah[this.filter.index])-this.filter.low)/(this.filter.high-this.filter.low))};var H=function(ah){this.track=ah.track;this.params=ah.params;this.values={};this.restore_values((ah.saved_values?ah.saved_values:{}));this.onchange=ah.onchange};q(H.prototype,{restore_values:function(ah){var ai=this;$.each(this.params,function(aj,ak){if(ah[ak.key]!==undefined){ai.values[ak.key]=ah[ak.key]}else{ai.values[ak.key]=ak.default_value}})},build_form:function(){var ai=this;var ah=$("<div />");$.each(this.params,function(am,ak){if(!ak.hidden){var aj="param_"+am;var ao=ai.values[ak.key];var ar=$("<div class='form-row' />").appendTo(ah);ar.append($("<label />").attr("for",aj).text(ak.label+":"));if(ak.type==="bool"){ar.append($('<input type="checkbox" />').attr("id",aj).attr("name",aj).attr("checked",ao))}else{if(ak.type==="text"){ar.append($('<input type="text"/>').attr("id",aj).val(ao).click(function(){$(this).select()}))}else{if(ak.type==="color"){var an=$("<input />").attr("id",aj).attr("name",aj).val(ao);var ap=$("<div class='tipsy tipsy-north' style='position: absolute;' />").hide();var al=$("<div style='background-color: black; padding: 10px;'></div>").appendTo(ap);var aq=$("<div/>").appendTo(al).farbtastic({width:100,height:100,callback:an,color:ao});$("<div />").append(an).append(ap).appendTo(ar).bind("click",function(at){ap.css({left:$(this).position().left+($(an).width()/2)-60,top:$(this).position().top+$(this.height)}).show();$(document).bind("click.color-picker",function(){ap.hide();$(document).unbind("click.color-picker")});at.stopPropagation()})}else{ar.append($("<input />").attr("id",aj).attr("name",aj).val(ao))}}}}});return ah},update_from_form:function(ah){var aj=this;var ai=false;$.each(this.params,function(ak,am){if(!am.hidden){var an="param_"+ak;var al=ah.find("#"+an).val();if(am.type==="float"){al=parseFloat(al)}else{if(am.type==="int"){al=parseInt(al)}else{if(am.type==="bool"){al=ah.find("#"+an).is(":checked")}}}if(al!==aj.values[am.key]){aj.values[am.key]=al;ai=true}}});if(ai){this.onchange()}}});var b=function(ah,ak,aj,ai,al){this.track=ah;this.index=ak;this.low=ak*S*aj;this.high=(ak+1)*S*aj;this.resolution=aj;this.canvas=$("<div class='track-tile'/>").append(ai);this.data=al;this.stale=false};b.prototype.predisplay_actions=function(){};var l=function(ah,ak,aj,ai,al,am){b.call(this,ah,ak,aj,ai,al);this.max_val=am};q(l.prototype,b.prototype);var Q=function(ah,al,ak,aj,an,ao,am,ai){b.call(this,ah,al,ak,aj,an);this.mode=ao;this.message=am;this.feature_mapper=ai};q(Q.prototype,b.prototype);Q.prototype.predisplay_actions=function(){var ai=this,ah={};if(ai.mode!=="Pack"){return}$(this.canvas).mousemove(function(au){var ao=$(this).offset(),at=au.pageX-ao.left,ar=au.pageY-ao.top,ay=ai.feature_mapper.get_feature_data(at,ar),ap=(ay?ay[0]:null);$(this).siblings(".feature-popup").each(function(){if(!ap||$(this).attr("id")!==ap.toString()){$(this).remove()}});if(ay){var ak=ah[ap];if(!ak){var ap=ay[0],av={name:ay[3],start:ay[1],end:ay[2],strand:ay[4]},an=ai.track.filters_manager.filters,am;for(var aq=0;aq<an.length;aq++){am=an[aq];av[am.name]=ay[am.index]}var ak=$("<div/>").attr("id",ap).addClass("feature-popup"),ax,aw,az=$("<table/>").appendTo(ak),aA;for(ax in av){aw=av[ax];aA=$("<tr/>").appendTo(az);$("<th/>").appendTo(aA).text(ax);$("<td/>").attr("align","left").appendTo(aA).text(typeof(aw)=="number"?ab(aw,2):aw)}ah[ap]=ak}ak.appendTo($(ai.canvas).parent());var al=at+parseInt(ai.canvas.css("left"))+7,aj=ar+parseInt(ai.canvas.css("top"))+7;ak.css("left",al+"px").css("top",aj+"px")}else{if(!au.isPropagationStopped()){au.stopPropagation();$(this).siblings().each(function(){$(this).trigger(au)})}}}).mouseleave(function(){$(this).siblings(".feature-popup").remove()})};var j=function(ak,ai,ah,aj,al,am){r.call(this,ak,ai,ah,{},"draghandle");this.data_url=(al?al:default_data_url);this.data_url_extra_params={};this.data_query_wait=(am?am:M);this.dataset_check_url=converted_datasets_state_url;if(!j.id_counter){j.id_counter=0}this.container_div=$("<div />").addClass("track").attr("id","track_"+j.id_counter++).css("position","relative");if(!this.hidden){this.header_div=$("<div class='track-header' />").appendTo(this.container_div);if(this.view.editor){this.drag_div=$("<div/>").addClass(this.drag_handle_class).appendTo(this.header_div)}this.name_div=$("<div class='menubutton popup' />").appendTo(this.header_div);this.name_div.text(this.name);this.name_div.attr("id",this.name.replace(/\s+/g,"-").replace(/[^a-zA-Z0-9\-]/g,"").toLowerCase())}this.content_div=$("<div class='track-content'>").appendTo(this.container_div);this.container.content_div.append(this.container_div)};q(j.prototype,r.prototype,{get_type:function(){if(this instanceof ad){return"LabelTrack"}else{if(this instanceof B){return"ReferenceTrack"}else{if(this instanceof k){return"LineTrack"}else{if(this instanceof Y){return"ReadTrack"}else{if(this instanceof W){return"ToolDataFeatureTrack"}else{if(this instanceof V){return"VcfTrack"}else{if(this instanceof e){return"FeatureTrack"}}}}}}}return""},init:function(){var ah=this;ah.enabled=false;ah.tile_cache.clear();ah.data_manager.clear();ah.initial_canvas=undefined;ah.content_div.css("height","auto");ah.container_div.removeClass("nodata error pending");if(!ah.dataset_id){return}$.getJSON(converted_datasets_state_url,{hda_ldda:ah.hda_ldda,dataset_id:ah.dataset_id,chrom:ah.view.chrom},function(ai){if(!ai||ai==="error"||ai.kind==="error"){ah.container_div.addClass("error");ah.content_div.text(p);if(ai.message){var aj=$(" <a href='javascript:void(0);'></a>").text("View error").click(function(){show_modal("Trackster Error","<pre>"+ai.message+"</pre>",{Close:hide_modal})});ah.content_div.append(aj)}}else{if(ai==="no converter"){ah.container_div.addClass("error");ah.content_div.text(L)}else{if(ai==="no data"||(ai.data!==undefined&&(ai.data===null||ai.data.length===0))){ah.container_div.addClass("nodata");ah.content_div.text(G)}else{if(ai==="pending"){ah.container_div.addClass("pending");ah.content_div.text(u);setTimeout(function(){ah.init()},ah.data_query_wait)}else{if(ai.status==="data"){if(ai.valid_chroms){ah.valid_chroms=ai.valid_chroms;ah.make_name_popup_menu()}ah.content_div.text(aa);if(ah.view.chrom){ah.content_div.text("");ah.content_div.css("height",ah.height_px+"px");ah.enabled=true;$.when(ah.predraw_init()).done(function(){ah.container_div.removeClass("nodata error pending");ah.request_draw()})}}}}}}})},predraw_init:function(){},});var O=function(ao,am){var ai=this,ap=ai.view;n(ai.container_div,ai.drag_handle_class,".group",ai);this.filters_manager=new ac(this,(ao!==undefined?ao:{}));this.filters_available=false;this.filters_visible=false;this.tool=(am!==undefined&&obj_length(am)>0?new s(this,am):undefined);this.is_overview=false;if(ai.hidden){return}if(this.filters_manager){this.filters_div=this.filters_manager.parent_div;this.header_div.after(this.filters_div)}if(this.tool){this.dynamic_tool_div=this.tool.parent_div;this.header_div.after(this.dynamic_tool_div)}if(ai.display_modes!==undefined){if(ai.mode_div===undefined){ai.mode_div=$("<div class='right-float menubutton popup' />").appendTo(ai.header_div);var aj=(ai.config&&ai.config.values.mode?ai.config.values.mode:ai.display_modes[0]);ai.mode=aj;ai.mode_div.text(aj);var ah={};for(var ak=0,an=ai.display_modes.length;ak<an;ak++){var al=ai.display_modes[ak];ah[al]=function(aq){return function(){ai.change_mode(aq)}}(al)}make_popupmenu(ai.mode_div,ah)}else{ai.mode_div.hide()}}this.make_name_popup_menu()};q(O.prototype,r.prototype,j.prototype,{to_json: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,}},change_mode:function(ai){var ah=this;ah.mode_div.text(ai);ah.mode=ai;ah.config.values.mode=ai;ah.tile_cache.clear();ah.request_draw();return ah},make_name_popup_menu:function(){var ai=this;var ah={};ah[(this.is_overview?"Hide overview":"Set as overview")]=function(){if(ai.is_overview){ai.view.reset_overview()}else{ai.view.set_overview(ai)}};ah["Edit configuration"]=function(){var am=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},ak=function(){ai.config.update_from_form($(".dialog-box"));hide_modal();$(window).unbind("keypress.check_enter_esc")},al=function(an){if((an.keyCode||an.which)===27){am()}else{if((an.keyCode||an.which)===13){ak()}}};$(window).bind("keypress.check_enter_esc",al);show_modal("Configure Track",ai.config.build_form(),{Cancel:am,OK:ak})};if(ai.filters_available>0){var aj=(ai.filters_div.is(":visible")?"Hide filters":"Show filters");ah[aj]=function(){ai.filters_visible=(ai.filters_div.is(":visible"));if(ai.filters_visible){ai.filters_manager.reset_filters()}ai.filters_div.toggle();ai.make_name_popup_menu()}}if(ai.tool){var aj=(ai.dynamic_tool_div.is(":visible")?"Hide tool":"Show tool");ah[aj]=function(){if(!ai.dynamic_tool_div.is(":visible")){ai.set_name(ai.name+ai.tool_region_and_parameters_str())}else{menu_option_text="Show dynamic tool";ai.revert_name()}ai.dynamic_tool_div.toggle();ai.make_name_popup_menu()}}ah.Remove=function(){ai.remove()};make_popupmenu(ai.name_div,ah)},set_is_overview:function(ah){this.is_overview=ah;this.make_name_popup_menu()},get_overview_tile:function(){var ah=this;view=ah.view,resolution=Math.pow(D,Math.ceil(Math.log((view.max_high-view.max_low)/S)/Math.log(D))),view_width=view.container.width(),w_scale=view_width/(view.max_high-view.max_low),overview_tile=$.Deferred();$.when(ah.data_manager.get_data(view.max_low,view.max_high,"Auto",resolution,ah.data_url_extra_params)).then(function(ai){var ak=ah._gen_tile_cache_key(view_width,w_scale,0),am=ah.tile_cache.get(ak);if(!am){am=ah.draw_tile(ai,"Auto",resolution,0,w_scale);ah.tile_cache.set(ak,am)}var ap=$(am.canvas.find("canvas")),al=ap.clone(),ao=ap.get(0).getContext("2d"),aj=al.get(0).getContext("2d"),an=ao.getImageData(0,0,ao.canvas.width,ao.canvas.height);aj.putImageData(an,-ah.left_offset,(am.data.dataset_type==="summary_tree"?U:0));new_tile=new b(ah,-1,resolution,al);overview_tile.resolve(new_tile)});return overview_tile},_gen_tile_cache_key:function(ai,aj,ah){return ai+"_"+aj+"_"+ah},request_draw:function(ai,ah){this.view.request_redraw(false,ai,ah,this)},_draw:function(aj,ar){if(!this.enabled){return}if(!(this instanceof B)&&(!this.dataset_id)){return}var aq=this.view.low,an=this.view.high,ao=an-aq,ak=this.view.container.width(),av=ak/ao,am=this.view.resolution,au=$("<div style='position: relative;'></div>");if(!ar){this.content_div.children().remove()}this.content_div.append(au);this.max_height=0;var ai=Math.floor(aq/am/S);var ap=true;var at=[];var ah=0;while((ai*S*am)<an){tile=this.draw_helper(aj,ak,ai,am,au,av);if(tile){at.push(tile)}else{ap=false}ai+=1;ah++}var al=this;if(ap){al.postdraw_actions(at,ak,av,ar)}},postdraw_actions:function(al,am,an,ah){var aj=this;var ak=false;for(var ai=0;ai<al.length;ai++){if(al[ai].message){ak=true;break}}if(ak){for(var ai=0;ai<al.length;ai++){tile=al[ai];if(!tile.message){tile.canvas.css("padding-top",F)}}}},draw_helper:function(ai,aj,ak,an,au,ay,av,ao){var al=this,at=this._gen_tile_cache_key(aj,ay,ak),ap=ak*S*an,ax=ap+S*an;var aq=(ai?undefined:al.tile_cache.get(at));if(aq){al.show_tile(aq,au,ay);return aq}var ar=function(az){return("isResolved" in az)};var am=true;var ah=al.data_manager.get_data(ap,ax,al.mode,an,al.data_url_extra_params);if(ar(ah)){am=false}var aw;if(view.reference_track&&ay>view.canvas_manager.char_width_px){aw=view.reference_track.data_manager.get_data(ap,ax,al.mode,an,view.reference_track.data_url_extra_params);if(ar(aw)){am=false}}if(am){q(ah,ao);var aq=al.draw_tile(ah,al.mode,an,ak,ay,aw);if(aq!==undefined){al.tile_cache.set(at,aq);al.show_tile(aq,au,ay)}return aq}$.when(ah,aw).then(function(){view.request_redraw()});return null},show_tile:function(ao,aq,ar){var aj=this,ai=ao.canvas,an=ai;if(ao.message){var at=$("<div/>"),ap=$("<div/>").addClass("tile-message").text(ao.message).css({height:F-1,width:ao.canvas.width}).appendTo(at),al=$("<a href='javascript:void(0);'/>").addClass("icon more-down").appendTo(ap),ah=$("<a href='javascript:void(0);'/>").addClass("icon more-across").appendTo(ap);at.append(ai);an=at;al.click(function(){ao.stale=true;aj.data_manager.get_more_data(ao.low,ao.high,aj.mode,ao.resolution,{},aj.data_manager.DEEP_DATA_REQ);aj.request_draw()}).dblclick(function(au){au.stopPropagation()});ah.click(function(){ao.stale=true;aj.data_manager.get_more_data(ao.low,ao.high,aj.mode,ao.resolution,{},aj.data_manager.BROAD_DATA_REQ);aj.request_draw()}).dblclick(function(au){au.stopPropagation()})}ao.predisplay_actions();var am=this.view.high-this.view.low,ak=(ao.low-this.view.low)*ar;if(this.left_offset){ak-=this.left_offset}an.css({position:"absolute",top:0,left:ak,height:""});aq.append(an);aj.max_height=Math.max(aj.max_height,an.height());aj.content_div.css("height",aj.max_height+"px");aq.children().css("height",aj.max_height+"px")},_get_tile_bounds:function(ah,ai){var ak=ah*S*ai,al=S*ai,aj=(ak+al<=this.view.max_high?ak+al:this.view.max_high);return[ak,aj]},tool_region_and_parameters_str:function(aj,ah,ak){var ai=this,al=(aj!==undefined&&ah!==undefined&&ak!==undefined?aj+":"+ah+"-"+ak:"all");return" - region=["+al+"], parameters=["+ai.tool.get_param_values().join(", ")+"]"}});var ad=function(ai,ah){this.hidden=true;j.call(this,"label",ai,ah,{});this.container_div.addClass("label-track")};q(ad.prototype,j.prototype,{init:function(){this.enabled=true},_draw:function(){var aj=this.view,ak=aj.high-aj.low,an=Math.floor(Math.pow(10,Math.floor(Math.log(ak)/Math.log(10)))),ah=Math.floor(aj.low/an)*an,al=this.view.container.width(),ai=$("<div style='position: relative; height: 1.3em;'></div>");while(ah<aj.high){var am=(ah-aj.low)/ak*al;ai.append($("<div class='label'>"+commatize(ah)+"</div>").css({position:"absolute",left:am-1}));ah+=an}this.content_div.children(":first").remove();this.content_div.append(ai)}});var B=function(ah){this.hidden=true;j.call(this,"reference",ah,{content_div:ah.top_labeltrack},{});O.call(this);ah.reference_track=this;this.left_offset=200;this.height_px=12;this.container_div.addClass("reference-track");this.content_div.css("background","none");this.content_div.css("min-height","0px");this.content_div.css("border","none");this.data_url=reference_url;this.data_url_extra_params={dbkey:ah.dbkey};this.data_manager=new J(C,this,false);this.tile_cache=new c(v)};q(B.prototype,r.prototype,O.prototype,{init:function(){this.enabled=true},draw_tile:function(ar,an,am,ai,at){var al=this,aj=S*am;if(at>this.view.canvas_manager.char_width_px){if(ar===null){al.content_div.css("height","0px");return}var ak=this.view.canvas_manager.new_canvas();var aq=ak.getContext("2d");ak.width=Math.ceil(aj*at+al.left_offset);ak.height=al.height_px;aq.font=aq.canvas.manager.default_font;aq.textAlign="center";ar=ar.data;for(var ao=0,ap=ar.length;ao<ap;ao++){var ah=Math.round(ao*at);aq.fillText(ar[ao],ah+al.left_offset,10)}return new b(al,ai,am,ak,ar)}this.content_div.css("height","0px")}});var k=function(am,ak,aj,an,ah,al){var ai=this;this.display_modes=["Histogram","Line","Filled","Intensity"];this.mode="Histogram";j.call(this,am,ak,aj,al);O.call(this);this.min_height_px=16;this.max_height_px=400;this.height_px=80;this.hda_ldda=an;this.dataset_id=ah;this.original_dataset_id=ah;this.data_manager=new T(C,this);this.tile_cache=new c(v);this.left_offset=0;this.config=new H({track:this,params:[{key:"name",label:"Name",type:"text",default_value:am},{key:"color",label:"Color",type:"color",default_value:"black"},{key:"min_value",label:"Min Value",type:"float",default_value:undefined},{key:"max_value",label:"Max Value",type:"float",default_value:undefined},{key:"mode",type:"string",default_value:this.mode,hidden:true},{key:"height",type:"int",default_value:this.height_px,hidden:true}],saved_values:al,onchange:function(){ai.set_name(ai.prefs.name);ai.vertical_range=ai.prefs.max_value-ai.prefs.min_value;$("#linetrack_"+ai.dataset_id+"_minval").text(ai.prefs.min_value);$("#linetrack_"+ai.dataset_id+"_maxval").text(ai.prefs.max_value);ai.tile_cache.clear();ai.request_draw()}});this.prefs=this.config.values;this.height_px=this.config.values.height;this.vertical_range=this.config.values.max_value-this.config.values.min_value;this.add_resize_handle()};q(k.prototype,r.prototype,O.prototype,{add_resize_handle:function(){var ah=this;var ak=false;var aj=false;var ai=$("<div class='track-resize'>");$(ah.container_div).hover(function(){ak=true;ai.show()},function(){ak=false;if(!aj){ai.hide()}});ai.hide().bind("dragstart",function(al,am){aj=true;am.original_height=$(ah.content_div).height()}).bind("drag",function(am,an){var al=Math.min(Math.max(an.original_height+an.deltaY,ah.min_height_px),ah.max_height_px);$(ah.content_div).css("height",al);ah.height_px=al;ah.request_draw(true)}).bind("dragend",function(al,am){ah.tile_cache.clear();aj=false;if(!ak){ai.hide()}ah.config.values.height=ah.height_px}).appendTo(ah.container_div)},predraw_init:function(){var ah=this;ah.vertical_range=undefined;return $.getJSON(ah.data_url,{stats:true,chrom:ah.view.chrom,low:null,high:null,hda_ldda:ah.hda_ldda,dataset_id:ah.dataset_id},function(ai){ah.container_div.addClass("line-track");var ak=ai.data;if(isNaN(parseFloat(ah.prefs.min_value))||isNaN(parseFloat(ah.prefs.max_value))){ah.prefs.min_value=ak.min;ah.prefs.max_value=ak.max;$("#track_"+ah.dataset_id+"_minval").val(ah.prefs.min_value);$("#track_"+ah.dataset_id+"_maxval").val(ah.prefs.max_value)}ah.vertical_range=ah.prefs.max_value-ah.prefs.min_value;ah.total_frequency=ak.total_frequency;ah.container_div.find(".yaxislabel").remove();var al=$("<div />").addClass("yaxislabel").attr("id","linetrack_"+ah.dataset_id+"_minval").text(ab(ah.prefs.min_value,3));var aj=$("<div />").addClass("yaxislabel").attr("id","linetrack_"+ah.dataset_id+"_maxval").text(ab(ah.prefs.max_value,3));aj.css({position:"absolute",top:"24px",left:"10px"});aj.prependTo(ah.container_div);al.css({position:"absolute",bottom:"2px",left:"10px"});al.prependTo(ah.container_div)})},draw_tile:function(au,am,al,aj,at){if(this.vertical_range===undefined){return}var ah=this._get_tile_bounds(aj,al),an=ah[0],ar=ah[1],ai=Math.ceil((ar-an)*at),ap=this.height_px;var ak=this.view.canvas_manager.new_canvas();ak.width=ai,ak.height=ap;var aq=ak.getContext("2d");var ao=new N.LinePainter(au.data,an,ar,this.prefs,am);ao.draw(aq,ai,ap);return new b(this.track,aj,al,ak,au.data)}});var e=function(ah,an,ai,am,ap,ao,ak,al){var aj=this;this.display_modes=["Auto","Histogram","Dense","Squish","Pack"];j.call(this,ah,an,ai,ao);O.call(this,ak,al);this.config=new H({track:this,params:[{key:"name",label:"Name",type:"text",default_value:ah},{key:"block_color",label:"Block color",type:"color",default_value:"#444"},{key:"label_color",label:"Label color",type:"color",default_value:"black"},{key:"show_counts",label:"Show summary counts",type:"bool",default_value:true},{key:"mode",type:"string",default_value:this.mode,hidden:true},],saved_values:ao,onchange:function(){aj.set_name(aj.prefs.name);aj.tile_cache.clear();aj.request_draw()}});this.prefs=this.config.values;this.height_px=0;this.container_div.addClass("feature-track");this.hda_ldda=am;this.dataset_id=ap;this.original_dataset_id=ap;this.show_labels_scale=0.001;this.showing_details=false;this.summary_draw_height=30;this.inc_slots={};this.start_end_dct={};this.tile_cache=new c(d);this.data_manager=new T(20,this);this.left_offset=200;this.painter=N.LinkedFeaturePainter};q(e.prototype,r.prototype,O.prototype,{postdraw_actions:function(ax,ah,ay,aw){O.prototype.postdraw_actions.call(this,ax,aw);var ak=this;if(aw){var am=ak.content_div.children();var an=false;for(var al=am.length-1,ar=0;al>=ar;al--){var aj=$(am[al]);if(an){aj.remove()}else{if(aj.children().length!==0){an=true}}}}if(ak.mode=="Histogram"){var aq=-1;for(var al=0;al<ax.length;al++){var av=ax[al].max_val;if(av>aq){aq=av}}for(var al=0;al<ax.length;al++){var au=ax[al];if(au.max_val!==aq){au.canvas.remove();ak.draw_helper(true,ah,au.index,au.resolution,au.canvas.parent(),ay,[],{max:aq})}}}if(ak.filters_manager){var ai=ak.filters_manager.filters;for(var ap=0;ap<ai.length;ap++){ai[ap].update_ui_elt()}var ao=false,at;for(var al=0;al<ax.length;al++){if(ax[al].data.length){at=ax[al].data[0];for(var ap=0;ap<ai.length;ap++){if(ai[ap].applies_to(at)){ao=true;break}}}}if(ak.filters_available!==ao){ak.filters_available=ao;if(!ak.filters_available){ak.filters_div.hide()}ak.make_name_popup_menu()}}},update_auto_mode:function(ah){if(this.mode=="Auto"){if(ah=="no_detail"){ah="feature spans"}else{if(ah=="summary_tree"){ah="coverage histogram"}}this.mode_div.text("Auto ("+ah+")")}},incremental_slots:function(al,ai,ak){var aj=this.view.canvas_manager.dummy_context,ah=this.inc_slots[al];if(!ah||(ah.mode!==ak)){ah=new (t.FeatureSlotter)(al,ak==="Pack",A,function(am){return aj.measureText(am)});ah.mode=ak;this.inc_slots[al]=ah}return ah.slot_features(ai)},get_summary_tree_data:function(al,ao,aj,ax){if(ax>aj-ao){ax=aj-ao}var at=Math.floor((aj-ao)/ax),aw=[],ak=0;var am=0,an=0,ar,av=0,ap=[],au,aq;var ai=function(aA,az,aB,ay){aA[0]=az+aB*ay;aA[1]=az+(aB+1)*ay};while(av<ax&&am!==al.length){var ah=false;for(;av<ax&&!ah;av++){ai(ap,ao,av,at);for(an=am;an<al.length;an++){ar=al[an].slice(1,3);if(is_overlap(ar,ap)){ah=true;break}}if(ah){break}}data_start_index=an;aw[aw.length]=au=[ap[0],0];for(;an<al.length;an++){ar=al[an].slice(1,3);if(is_overlap(ar,ap)){au[1]++}else{break}}if(au[1]>ak){ak=au[1]}av++}return{max:ak,delta:at,data:aw}},draw_tile:function(aw,az,aD,aH,ar,ak){var aA=this,am=aA._get_tile_bounds(aH,aD),aK=am[0],ai=am[1],ay=ai-aK,aB=Math.ceil(ay*ar),aQ=25,al=this.left_offset,ax,an;if(az==="Auto"){if(aw.dataset_type==="summary_tree"){az=aw.dataset_type}else{if(aw.extra_info==="no_detail"){az="no_detail"}else{var aP=aw.data;if(this.view.high-this.view.low>K){az="Squish"}else{az="Pack"}}}this.update_auto_mode(az)}if(az==="summary_tree"||az==="Histogram"){an=this.summary_draw_height;this.container_div.find(".yaxislabel").remove();var ah=$("<div />").addClass("yaxislabel");ah.text(aw.max);ah.css({position:"absolute",top:"24px",left:"10px",color:this.prefs.label_color});ah.prependTo(this.container_div);var aj=this.view.canvas_manager.new_canvas();aj.width=aB+al;aj.height=an+U;if(aw.dataset_type!="summary_tree"){var at=this.get_summary_tree_data(aw.data,aK,ai,200);if(aw.max){at.max=aw.max}aw=at}var aM=new N.SummaryTreePainter(aw,aK,ai,this.prefs);var aC=aj.getContext("2d");aC.translate(al,U);aM.draw(aC,aB,an);return new l(aA,aH,aD,aj,aw.data,aw.max)}var ax,ap=1;if(az==="no_detail"||az==="Squish"||az==="Pack"){ap=this.incremental_slots(ar,aw.data,az);ax=this.inc_slots[ar].slots}var aq=[];if(aw.data){var au=this.filters_manager.filters;for(var aE=0,aG=aw.data.length;aE<aG;aE++){var ao=aw.data[aE];var aF=false;var av;for(var aJ=0,aO=au.length;aJ<aO;aJ++){av=au[aJ];av.update_attrs(ao);if(!av.keep(ao)){aF=true;break}}if(!aF){aq.push(ao)}}}var aN=(this.filters_manager.alpha_filter?new E(this.filters_manager.alpha_filter):null);var aL=(this.filters_manager.height_filter?new E(this.filters_manager.height_filter):null);var aM=new (this.painter)(aq,aK,ai,this.prefs,az,aN,aL,ak);var an=Math.max(af,aM.get_required_height(ap));var aj=this.view.canvas_manager.new_canvas();var aI=null;aj.width=aB+al;aj.height=an;var aC=aj.getContext("2d");aC.fillStyle=this.prefs.block_color;aC.font=aC.canvas.manager.default_font;aC.textAlign="right";this.container_div.find(".yaxislabel").remove();if(aw.data){aC.translate(al,0);aI=aM.draw(aC,aB,an,ax);aI.translation=-al}return new Q(aA,aH,aD,aj,aw.data,az,aw.message,aI)}});var V=function(al,aj,ai,an,ah,ak,am){e.call(this,al,aj,ai,an,ah,ak,am);this.painter=N.VariantPainter};q(V.prototype,r.prototype,O.prototype,e.prototype);var Y=function(al,aj,ai,an,ah,ak,am){e.call(this,al,aj,ai,an,ah,ak,am);this.config=new H({track:this,params:[{key:"name",label:"Name",type:"text",default_value:al},{key:"block_color",label:"Block color",type:"color",default_value:"#444"},{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:"mode",type:"string",default_value:this.mode,hidden:true},],saved_values:ak,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=N.ReadPainter;this.make_name_popup_menu()};q(Y.prototype,r.prototype,O.prototype,e.prototype);var W=function(al,aj,ai,an,ah,ak,am){e.call(this,al,aj,ai,an,ah,ak,am,{});this.data_url=raw_data_url;this.data_query_wait=1000;this.dataset_check_url=dataset_state_url};q(W.prototype,r.prototype,O.prototype,e.prototype,{predraw_init:function(){var ai=this;var ah=function(){if(ai.data_manager.size()===0){setTimeout(ah,300)}else{ai.data_url=default_data_url;ai.data_query_wait=M;ai.dataset_state_url=converted_datasets_state_url;$.getJSON(ai.dataset_state_url,{dataset_id:ai.dataset_id,hda_ldda:ai.hda_ldda},function(aj){})}};ah()}});Z.View=ae;Z.DrawableGroup=R;Z.LineTrack=k;Z.FeatureTrack=e;Z.ReadTrack=Y};var slotting_module=function(c,b){var e=c("class").extend;var d=2,a=5;b.FeatureSlotter=function(j,h,f,g){this.slots={};this.start_end_dct={};this.w_scale=j;this.include_label=h;this.max_rows=f;this.measureText=g};e(b.FeatureSlotter.prototype,{slot_features:function(m){var p=this.w_scale,s=this.slots,h=this.start_end_dct,y=[],A=[],n=0,z=this.max_rows;for(var w=0,x=m.length;w<x;w++){var l=m[w],o=l[0];if(s[o]!==undefined){n=Math.max(n,s[o]);A.push(s[o])}else{y.push(w)}}var q=function(G,H){for(var F=0;F<=z;F++){var D=false,I=h[F];if(I!==undefined){for(var C=0,E=I.length;C<E;C++){var B=I[C];if(H>B[0]&&G<B[1]){D=true;break}}}if(!D){return F}}return -1};for(var w=0,x=y.length;w<x;w++){var l=m[y[w]],o=l[0],u=l[1],f=l[2],r=l[3],g=Math.floor(u*p),k=Math.ceil(f*p),v=this.measureText(r).width,j;if(r!==undefined&&this.include_label){v+=(d+a);if(g-v>=0){g-=v;j="left"}else{k+=v;j="right"}}var t=q(g,k);if(t>=0){if(h[t]===undefined){h[t]=[]}h[t].push([g,k]);s[o]=t;n=Math.max(n,t)}else{}}return n+1}})};var painters_module=function(k,y){var v=k("class").extend;var q=function(J,B,H,A,G,E){if(E===undefined){E=4}var D=A-B;var C=G-H;var F=Math.floor(Math.sqrt(D*D+C*C)/E);var K=D/F;var I=C/F;var z;for(z=0;z<F;z++,B+=K,H+=I){if(z%2!==0){continue}J.fillRect(B,H,E,1)}};var r=function(B,A,z,E){var D=A-E/2,C=A+E/2,F=z-Math.sqrt(E*3/2);B.beginPath();B.moveTo(D,F);B.lineTo(C,F);B.lineTo(A,z);B.lineTo(D,F);B.strokeStyle=this.fillStyle;B.fill();B.stroke();B.closePath()};var e=function(z){this.default_val=(z?z:1)};e.prototype.gen_val=function(z){return this.default_val};var n=function(B,D,z,A,C){this.data=B;this.view_start=D;this.view_end=z;this.prefs=v({},this.default_prefs,A);this.mode=C};n.prototype.default_prefs={};var w=function(B,D,z,A,C){n.call(this,B,D,z,A,C)};w.prototype.default_prefs={show_counts:false};w.prototype.draw=function(M,z,L){var E=this.view_start,O=this.view_end-this.view_start,N=z/O;var J=this.data.data,I=this.data.delta,G=this.data.max,B=L;delta_x_px=Math.ceil(I*N);M.save();for(var C=0,D=J.length;C<D;C++){var H=Math.floor((J[C][0]-E)*N);var F=J[C][1];if(!F){continue}var K=F/G*L;if(F!==0&&K<1){K=1}M.fillStyle=this.prefs.block_color;M.fillRect(H,B-K,delta_x_px,K);var A=4;if(this.prefs.show_counts&&(M.measureText(F).width+A)<delta_x_px){M.fillStyle=this.prefs.label_color;M.textAlign="center";M.fillText(F,H+(delta_x_px/2),10)}}M.restore()};var c=function(z,D,F,G,B){n.call(this,z,D,F,G,B);if(this.prefs.min_value===undefined){var H=Infinity;for(var A=0,C=this.data.length;A<C;A++){H=Math.min(H,this.data[A][1])}this.prefs.min_value=H}if(this.prefs.max_value===undefined){var E=-Infinity;for(var A=0,C=this.data.length;A<C;A++){E=Math.max(E,this.data[A][1])}this.prefs.max_value=E}};c.prototype.default_prefs={min_value:undefined,max_value:undefined,mode:"Histogram",color:"#000",overflow_color:"#F66"};c.prototype.draw=function(N,M,K){var F=false,H=this.prefs.min_value,D=this.prefs.max_value,J=D-H,z=K,A=this.view_start,L=this.view_end-this.view_start,B=M/L,I=this.mode,T=this.data;N.save();var U=Math.round(K+H/J*K);if(I!=="Intensity"){N.fillStyle="#aaa";N.fillRect(0,U,M,1)}N.beginPath();var R,E,C;if(T.length>1){C=Math.ceil((T[1][0]-T[0][0])*B)}else{C=10}for(var O=0,P=T.length;O<P;O++){N.fillStyle=this.prefs.color;R=Math.round((T[O][0]-A)*B);E=T[O][1];var Q=false,G=false;if(E===null){if(F&&I==="Filled"){N.lineTo(R,z)}F=false;continue}if(E<H){G=true;E=H}else{if(E>D){Q=true;E=D}}if(I==="Histogram"){E=Math.round(E/J*z);N.fillRect(R,U,C,-E)}else{if(I==="Intensity"){E=255-Math.floor((E-H)/J*255);N.fillStyle="rgb("+E+","+E+","+E+")";N.fillRect(R,0,C,z)}else{E=Math.round(z-(E-H)/J*z);if(F){N.lineTo(R,E)}else{F=true;if(I==="Filled"){N.moveTo(R,z);N.lineTo(R,E)}else{N.moveTo(R,E)}}}}N.fillStyle=this.prefs.overflow_color;if(Q||G){var S;if(I==="Histogram"||I==="Intensity"){S=C}else{R-=2;S=4}if(Q){N.fillRect(R,0,S,3)}if(G){N.fillRect(R,z-3,S,3)}}N.fillStyle=this.prefs.color}if(I==="Filled"){if(F){N.lineTo(R,U);N.lineTo(0,U)}N.fill()}else{N.stroke()}N.restore()};var o=function(z){this.feature_positions={};this.slot_height=z;this.translation=0};o.prototype.map_feature_data=function(A,C,z,B){if(!this.feature_positions[C]){this.feature_positions[C]=[]}this.feature_positions[C].push({data:A,x_start:z,x_end:B})};o.prototype.get_feature_data=function(z,D){var C=Math.floor(D/this.slot_height),B;if(!this.feature_positions[C]){return null}z+=this.translation;for(var A=0;A<this.feature_positions[C].length;A++){B=this.feature_positions[C][A];if(z>=B.x_start&&z<=B.x_end){return B.data}}};var p=function(B,E,z,A,D,F,C){n.call(this,B,E,z,A,D);this.alpha_scaler=(F?F:new e());this.height_scaler=(C?C:new e())};p.prototype.default_prefs={block_color:"#FFF",connector_color:"#FFF"};v(p.prototype,{get_required_height:function(A){var z=y_scale=this.get_row_height(),B=this.mode;if(B==="no_detail"||B==="Squish"||B==="Pack"){z=A*y_scale}return z+Math.max(Math.round(y_scale/2),5)},draw:function(L,J,H,G){var R=this.data,E=this.view_start,N=this.view_end;L.save();L.fillStyle=this.prefs.block_color;L.textAlign="right";var I=this.view_end-this.view_start,F=J/I,M=this.get_row_height(),Q=new o(M),C;for(var O=0,P=R.length;O<P;O++){var B=R[O],D=B[0],K=B[1],z=B[2],A=(G&&G[D]!==undefined?G[D]:null);if((K<N&&z>E)&&(this.mode=="Dense"||A!==null)){C=this.draw_element(L,this.mode,B,A,E,N,F,M,J);Q.map_feature_data(B,A,C[0],C[1])}}L.restore();return Q},draw_element:function(F,B,H,D,C,E,G,A,z){console.log("WARNING: Unimplemented function.");return[0,0]}});var d=10,j=3,m=5,x=10,g=1,t=3,f=3,a=9,l=2,h="#ccc";var s=function(B,E,z,A,D,F,C){p.call(this,B,E,z,A,D,F,C)};v(s.prototype,p.prototype,{get_row_height:function(){var A=this.mode,z;if(A==="Dense"){z=d}else{if(A==="no_detail"){z=j}else{if(A==="Squish"){z=m}else{z=x}}}return z},draw_element:function(N,E,W,I,P,ah,al,an,z){var T=W[0],aj=W[1],ab=W[2],R=W[3],ac=Math.floor(Math.max(0,(aj-P)*al)),O=Math.ceil(Math.min(z,Math.max(0,(ab-P)*al))),aa=ac,am=O,Z=(E==="Dense"?0:(0+I))*an,M,af,S=null,ap=null,C=this.prefs.block_color,ae=this.prefs.label_color;N.globalAlpha=this.alpha_scaler.gen_val(W);if(E=="Dense"){I=1}if(E==="no_detail"){N.fillStyle=C;N.fillRect(ac,Z+5,O-ac,g)}else{var L=W[4],Y=W[5],ad=W[6],D=W[7];if(Y&&ad){S=Math.floor(Math.max(0,(Y-P)*al));ap=Math.ceil(Math.min(z,Math.max(0,(ad-P)*al)))}var ak,U;if(E==="Squish"||E==="Dense"){ak=1;U=f}else{ak=5;U=a}if(!D){if(W.strand){if(W.strand==="+"){N.fillStyle=N.canvas.manager.get_pattern("right_strand_inv")}else{if(W.strand==="-"){N.fillStyle=N.canvas.manager.get_pattern("left_strand_inv")}}}else{N.fillStyle=C}N.fillRect(ac,Z,O-ac,U)}else{var K,V;if(E==="Squish"||E==="Dense"){N.fillStyle=h;K=Z+Math.floor(f/2)+1;V=1}else{if(L){var K=Z;var V=U;if(L==="+"){N.fillStyle=N.canvas.manager.get_pattern("right_strand")}else{if(L==="-"){N.fillStyle=N.canvas.manager.get_pattern("left_strand")}}}else{N.fillStyle=h;K+=(f/2)+1;V=1}}N.fillRect(ac,K,O-ac,V);var F;for(var ai=0,B=D.length;ai<B;ai++){var G=D[ai],A=Math.floor(Math.max(0,(G[0]-P)*al)),X=Math.ceil(Math.min(z,Math.max((G[1]-P)*al)));if(A>X){continue}N.fillStyle=C;N.fillRect(A,Z+(U-ak)/2+1,X-A,ak);if(S!==undefined&&ad>Y&&!(A>ap||X<S)){var ag=Math.max(A,S),J=Math.min(X,ap);N.fillRect(ag,Z+1,J-ag,U);if(D.length==1&&E=="Pack"){if(L==="+"){N.fillStyle=N.canvas.manager.get_pattern("right_strand_inv")}else{if(L==="-"){N.fillStyle=N.canvas.manager.get_pattern("left_strand_inv")}}if(ag+14<J){ag+=2;J-=2}N.fillRect(ag,Z+1,J-ag,U)}}}if(E==="Pack"){N.globalAlpha=1;N.fillStyle="white";var H=this.height_scaler.gen_val(W),Q=Math.ceil(U*H),ao=Math.round((U-Q)/2);if(H!==1){N.fillRect(ac,K+1,O-ac,ao);N.fillRect(ac,K+U-ao+1,O-ac,ao)}}}N.globalAlpha=1;if(E==="Pack"&&aj>P){N.fillStyle=ae;if(P===0&&ac-N.measureText(R).width<0){N.textAlign="left";N.fillText(R,O+l,Z+8);am+=N.measureText(R).width+l}else{N.textAlign="right";N.fillText(R,ac-l,Z+8);aa-=N.measureText(R).width+l}}}N.globalAlpha=1;return[aa,am]}});var b=function(B,E,z,A,D,F,C){p.call(this,B,E,z,A,D,F,C)};v(b.prototype,p.prototype,{draw_element:function(S,N,H,D,V,B,K,T,Q){var H=data[i],J=H[0],R=H[1],C=H[2],M=H[3],F=Math.floor(Math.max(0,(R-V)*K)),I=Math.ceil(Math.min(Q,Math.max(0,(C-V)*K))),E=(N==="Dense"?0:(0+D))*T,z,W,A=null,L=null;if(no_label){S.fillStyle=block_color;S.fillRect(F+left_offset,E+5,I-F,1)}else{var U=H[4],P=H[5],G=H[6];z=9;W=1;S.fillRect(F+left_offset,E,I-F,z);if(N!=="Dense"&&M!==undefined&&R>V){S.fillStyle=label_color;if(V===0&&F-S.measureText(M).width<0){S.textAlign="left";S.fillText(M,I+2+left_offset,E+8)}else{S.textAlign="right";S.fillText(M,F-2+left_offset,E+8)}S.fillStyle=block_color}var O=U+" / "+P;if(R>V&&S.measureText(O).width<(I-F)){S.fillStyle="white";S.textAlign="center";S.fillText(O,left_offset+F+(I-F)/2,E+8);S.fillStyle=block_color}}return[F,I]}});var u=function(C,F,z,B,E,G,D,A){p.call(this,C,F,z,B,E,G,D);this.ref_seq=A};u.prototype.default_prefs=v({},p.prototype.default_prefs,{show_insertions:false});v(u.prototype,p.prototype,{get_row_height:function(){var z,A=this.mode;if(A==="Dense"){z=d}else{if(A==="Squish"){z=m}else{z=x;if(this.prefs.show_insertions){z*=2}}}return z},draw_read:function(V,Q,M,aa,B,U,J,G,F){V.textAlign="center";var T=this,A=[aa,B],P=0,W=0,S=0;ref_seq=this.ref_seq.data,char_width_px=V.canvas.manager.char_width_px;var af=[];if((Q==="Pack"||this.mode==="Auto")&&G!==undefined&&M>char_width_px){S=Math.round(M/2)}if(!J){J=[[0,G.length]]}for(var N=0,Y=J.length;N<Y;N++){var K=J[N],C="MIDNSHP=X"[K[0]],O=K[1];if(C==="H"||C==="S"){P-=O}var H=U+P,ae=Math.floor(Math.max(0,(H-aa)*M)),I=Math.floor(Math.max(0,(H+O-aa)*M));if(ae===I){I+=1}switch(C){case"H":break;case"S":case"M":case"=":if(is_overlap([H,H+O],A)){var R=G.slice(W,W+O);if(S>0){V.fillStyle=this.prefs.block_color;V.fillRect(ae-S,F+1,I-ae,9);V.fillStyle=h;for(var ac=0,z=R.length;ac<z;ac++){if(this.prefs.show_differences&&ref_seq){var L=ref_seq[H-aa+ac];if(!L||L.toLowerCase()===R[ac].toLowerCase()){continue}}if(H+ac>=aa&&H+ac<=B){var ad=Math.floor(Math.max(0,(H+ac-aa)*M));V.fillText(R[ac],ad,F+9)}}}else{V.fillStyle=this.prefs.block_color;V.fillRect(ae,F+4,I-ae,f)}}W+=O;P+=O;break;case"N":V.fillStyle=h;V.fillRect(ae-S,F+5,I-ae,1);P+=O;break;case"D":V.fillStyle="red";V.fillRect(ae-S,F+4,I-ae,3);P+=O;break;case"P":break;case"I":var Z=ae-S;if(is_overlap([H,H+O],A)){var R=G.slice(W,W+O);if(this.prefs.show_insertions){var E=ae-(I-ae)/2;if((Q==="Pack"||this.mode==="Auto")&&G!==undefined&&M>char_width_px){V.fillStyle="yellow";V.fillRect(E-S,F-9,I-ae,9);af[af.length]={type:"triangle",data:[Z,F+4,5]};V.fillStyle=h;switch(seq_tile_overlap){case (OVERLAP_START):R=R.slice(aa-H);break;case (OVERLAP_END):R=R.slice(0,H-B);break;case (CONTAINED_BY):break;case (CONTAINS):R=R.slice(aa-H,H-B);break}for(var ac=0,z=R.length;ac<z;ac++){var ad=Math.floor(Math.max(0,(H+ac-aa)*M));V.fillText(R[ac],ad-(I-ae)/2,F)}}else{V.fillStyle="yellow";V.fillRect(E,F+(this.mode!=="Dense"?2:5),I-ae,(Q!=="Dense"?f:t))}}else{if((Q==="Pack"||this.mode==="Auto")&&G!==undefined&&M>char_width_px){af[af.length]={type:"text",data:[R.length,Z,F+9]}}else{}}}W+=O;break;case"X":W+=O;break}}V.fillStyle="yellow";var ab,D,ag;for(var X=0;X<af.length;X++){ab=af[X];D=ab.type;ag=ab.data;if(D==="text"){V.save();V.font="bold "+V.font;V.fillText(ag[0],ag[1],ag[2]);V.restore()}else{if(D=="triangle"){r(V,ag[0],ag[1],ag[2])}}}},draw_element:function(S,N,F,C,V,A,J,T,Q){var I=F[0],R=F[1],B=F[2],K=F[3],E=Math.floor(Math.max(0,(R-V)*J)),G=Math.ceil(Math.min(Q,Math.max(0,(B-V)*J))),D=(N==="Dense"?0:(0+C))*T,W=this.prefs.block_color,H=this.prefs.label_color,P=0;if((N==="Pack"||this.mode==="Auto")&&J>S.canvas.manager.char_width_px){var P=Math.round(J/2)}S.fillStyle=W;if(F[5] instanceof Array){var O=Math.floor(Math.max(0,(F[4][0]-V)*J)),M=Math.ceil(Math.min(Q,Math.max(0,(F[4][1]-V)*J))),L=Math.floor(Math.max(0,(F[5][0]-V)*J)),z=Math.ceil(Math.min(Q,Math.max(0,(F[5][1]-V)*J)));if(F[4][1]>=V&&F[4][0]<=A&&F[4][2]){this.draw_read(S,N,J,V,A,F[4][0],F[4][2],F[4][3],D)}if(F[5][1]>=V&&F[5][0]<=A&&F[5][2]){this.draw_read(S,N,J,V,A,F[5][0],F[5][2],F[5][3],D)}if(L>M){S.fillStyle=h;q(S,M-P,D+5,L-P,D+5)}}else{S.fillStyle=W;this.draw_read(S,N,J,V,A,R,F[4],F[5],D)}if(N==="Pack"&&R>V){S.fillStyle=this.prefs.label_color;var U=1;if(U===0&&E-S.measureText(K).width<0){S.textAlign="left";S.fillText(K,G+l-P,D+8)}else{S.textAlign="right";S.fillText(K,E-l-P,D+8)}S.fillStyle=W}return[0,0]}});y.Scaler=e;y.SummaryTreePainter=w;y.LinePainter=c;y.LinkedFeaturePainter=s;y.ReadPainter=u;y.VariantPainter=b};(function(d){var c={};var b=function(e){return c[e]};var a=function(f,g){var e={};g(b,e);c[f]=e};a("class",class_module);a("slotting",slotting_module);a("painters",painters_module);a("trackster",trackster_module);for(key in c.trackster){d[key]=c.trackster[key]}})(window);
\ No newline at end of file
+var class_module=function(b,a){var c=function(){var f=arguments[0];for(var e=1;e<arguments.length;e++){var d=arguments[e];for(key in d){f[key]=d[key]}}return f};a.extend=c};var requestAnimationFrame=(function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(b,a){window.setTimeout(b,1000/60)}})();var BEFORE=1001,CONTAINS=1002,OVERLAP_START=1003,OVERLAP_END=1004,CONTAINED_BY=1005,AFTER=1006;var compute_overlap=function(e,b){var g=e[0],f=e[1],d=b[0],c=b[1],a;if(g<d){if(f<d){a=BEFORE}else{if(f<=c){a=OVERLAP_START}else{a=CONTAINS}}}else{if(g>c){a=AFTER}else{if(f<=c){a=CONTAINED_BY}else{a=OVERLAP_END}}}return a};var is_overlap=function(c,b){var a=compute_overlap(c,b);return(a!==BEFORE&&a!==AFTER)};var get_random_color=function(a){if(!a){a="#ffffff"}if(typeof(a)==="string"){a=[a]}for(var j=0;j<a.length;j++){a[j]=parseInt(a[j].slice(1),16)}var m=function(u,t,s){return((u*299)+(t*587)+(s*114))/1000};var e=function(v,u,w,s,r,t){return(Math.max(v,s)-Math.min(v,s))+(Math.max(u,r)-Math.min(u,r))+(Math.max(w,t)-Math.min(w,t))};var g,n,f,k,p,h,q,c,d,b,o,l=false;do{g=Math.random()*16777215;n=g|16711680;f=g|65280;k=g|255;d=m(n,f,k);l=true;for(var j=0;j<a.length;j++){p=a[j];h=p|16711680;q=p|65280;c=p|255;b=m(h,q,c);o=e(n,f,k,h,q,c);if((Math.abs(d-b)<125)||(o<500)){l=false;break}}}while(!l);return"#"+(16777216+g).toString(16).substr(1,6)};var trackster_module=function(f,Z){var q=f("class").extend,t=f("slotting"),N=f("painters");var ag=function(ah,ai){this.document=ah;this.default_font=ai!==undefined?ai:"9px Monaco, Lucida Console, monospace";this.dummy_canvas=this.new_canvas();this.dummy_context=this.dummy_canvas.getContext("2d");this.dummy_context.font=this.default_font;this.char_width_px=this.dummy_context.measureText("A").width;this.patterns={};this.load_pattern("right_strand","/visualization/strand_right.png");this.load_pattern("left_strand","/visualization/strand_left.png");this.load_pattern("right_strand_inv","/visualization/strand_right_inv.png");this.load_pattern("left_strand_inv","/visualization/strand_left_inv.png")};q(ag.prototype,{load_pattern:function(ah,al){var ai=this.patterns,aj=this.dummy_context,ak=new Image();ak.src=image_path+al;ak.onload=function(){ai[ah]=aj.createPattern(ak,"repeat")}},get_pattern:function(ah){return this.patterns[ah]},new_canvas:function(){var ah=this.document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(ah)}ah.manager=this;return ah}});var o={};var m=function(ah,ai){o[ah.attr("id")]=ai};var n=function(ah,aj,al,ak){al=".group";var ai={};o[ah.attr("id")]=ak;ah.bind("drag",{handle:"."+aj,relative:true},function(au,av){var at=$(this);var ay=$(this).parent(),ap=ay.children(),ar=o[$(this).attr("id")],ao,an,aw,am,aq;an=$(this).parents(al);if(an.length!==0){aw=an.position().top;am=aw+an.outerHeight();if(av.offsetY<aw){$(this).insertBefore(an);var ax=o[an.attr("id")];ax.remove_drawable(ar);ax.container.add_drawable_before(ar,ax);return}else{if(av.offsetY>am){$(this).insertAfter(an);var ax=o[an.attr("id")];ax.remove_drawable(ar);ax.container.add_drawable(ar);return}}}an=null;for(aq=0;aq<ap.length;aq++){ao=$(ap.get(aq));aw=ao.position().top;am=aw+ao.outerHeight();if(ao.is(al)&&this!==ao.get(0)&&av.offsetY>=aw&&av.offsetY<=am){if(av.offsetY-aw<am-av.offsetY){ao.find(".content-div").prepend(this)}else{ao.find(".content-div").append(this)}if(ar.container){ar.container.remove_drawable(ar)}o[ao.attr("id")].add_drawable(ar);return}}for(aq=0;aq<ap.length;aq++){if(av.offsetY<$(ap.get(aq)).position().top){break}}if(aq===ap.length){if(this!==ap.get(aq-1)){ay.append(this);o[ay.attr("id")].move_drawable(ar,aq)}}else{if(this!==ap.get(aq)){$(this).insertBefore(ap.get(aq));o[ay.attr("id")].move_drawable(ar,(av.deltaY>0?aq-1:aq))}}}).bind("dragstart",function(){ai["border-top"]=ah.css("border-top");ai["border-bottom"]=ah.css("border-bottom");$(this).css({"border-top":"1px solid blue","border-bottom":"1px solid blue"})}).bind("dragend",function(){$(this).css(ai)})};Z.moveable=n;var af=16,I=9,F=20,U=I+2,A=100,K=12000,S=200,D=5,w=10,M=5000,x=100,p="There was an error in indexing this dataset. ",L="A converter for this dataset is not installed. Please check your datatypes_conf.xml file.",G="No data for this chrom/contig.",u="Currently indexing... please wait",y="Tool cannot be rerun: ",a="Loading data...",aa="Ready for display",d=10,v=5,C=5;function ab(ai,ah){if(!ah){ah=0}var aj=Math.pow(10,ah);return Math.round(ai*aj)/aj}var c=function(ah){this.num_elements=ah;this.clear()};q(c.prototype,{get:function(ai){var ah=this.key_ary.indexOf(ai);if(ah!==-1){if(this.obj_cache[ai].stale){this.key_ary.splice(ah,1);delete this.obj_cache[ai]}else{this.move_key_to_end(ai,ah)}}return this.obj_cache[ai]},set:function(ai,aj){if(!this.obj_cache[ai]){if(this.key_ary.length>=this.num_elements){var ah=this.key_ary.shift();delete this.obj_cache[ah]}this.key_ary.push(ai)}this.obj_cache[ai]=aj;return aj},move_key_to_end:function(ai,ah){this.key_ary.splice(ah,1);this.key_ary.push(ai)},clear:function(){this.obj_cache={};this.key_ary=[]},size:function(){return this.key_ary.length}});var T=function(ai,ah,aj){c.call(this,ai);this.track=ah;this.subset=(aj!==undefined?aj:true)};q(T.prototype,c.prototype,{load_data:function(aq,al,ao,ai,an){var ap=this.track.view.chrom,ak={chrom:ap,low:aq,high:al,mode:ao,resolution:ai,dataset_id:this.track.dataset_id,hda_ldda:this.track.hda_ldda};$.extend(ak,an);if(this.track.filters_manager){var ar=[];var ah=this.track.filters_manager.filters;for(var am=0;am<ah.length;am++){ar[ar.length]=ah[am].name}ak.filter_cols=JSON.stringify(ar)}var aj=this;return $.getJSON(this.track.data_url,ak,function(at){aj.set_data(aq,al,ao,at)})},get_data:function(ah,al,am,ai,ak){var aj=this.get_data_from_cache(ah,al,am);if(aj){return aj}aj=this.load_data(ah,al,am,ai,ak);this.set_data(ah,al,am,aj);return aj},DEEP_DATA_REQ:"deep",BROAD_DATA_REQ:"breadth",get_more_data:function(ap,ak,ao,aj,an,al){var aq=this.get_data_from_cache(ap,ak,ao);if(!aq){console.log("ERROR: no current data for: ",this.track,ap,ak,ao,aj,an);return}aq.stale=true;var ai=ap;if(al===this.DEEP_DATA_REQ){$.extend(an,{start_val:aq.data.length+1})}else{if(al===this.BROAD_DATA_REQ){ai=(aq.max_high?aq.max_high:aq.data[aq.data.length-1][2])+1}}var ah=this,am=this.load_data(ai,ak,ao,aj,an);new_data_available=$.Deferred();this.set_data(ap,ak,ao,new_data_available);$.when(am).then(function(ar){if(ar.data){ar.data=aq.data.concat(ar.data);if(ar.max_low){ar.max_low=aq.max_low}if(ar.message){ar.message=ar.message.replace(/[0-9]+/,ar.data.length)}}ah.set_data(ap,ak,ao,ar);new_data_available.resolve(ar)});return new_data_available},get_data_from_cache:function(ah,ai,aj){return this.get(this.gen_key(ah,ai,aj))},set_data:function(ai,aj,ak,ah){return this.set(this.gen_key(ai,aj,ak),ah)},gen_key:function(ah,aj,ak){var ai=ah+"_"+aj+"_"+ak;return ai},split_key:function(ah){return ah.split("_")}});var J=function(ai,ah,aj){T.call(this,ai,ah,aj)};q(J.prototype,T.prototype,c.prototype,{load_data:function(ah,ak,al,ai,aj){if(ai>1){return{data:null}}return T.prototype.load_data.call(this,ah,ak,al,ai,aj)}});var r=function(ak,ai,ah,aj,al){this.name=ak;this.view=ai;this.container=ah;this.config=new H({track:this,params:[{key:"name",label:"Name",type:"text",default_value:ak}],saved_values:aj,onchange:function(){this.track.set_name(this.track.config.values.name)}});this.prefs=this.config.values;this.drag_handle_class=al;this.is_overview=false};q(r.prototype,{init:function(){},request_draw:function(){},_draw:function(){},to_json:function(){},update_track_icons:function(){},set_name:function(ah){this.old_name=this.name;this.name=ah;this.name_div.text(this.name)},revert_name:function(){this.name=this.old_name;this.name_div.text(this.name)},remove:function(){this.container.remove_drawable(this);this.container_div.fadeOut("slow",function(){$(this).remove();view.update_intro_div();view.has_changes=true})}});var z=function(al,ak,ai,ah,aj,am){r.call(this,ak,ai,ah,aj,am);this.obj_type=al;this.drawables=[]};q(z.prototype,r.prototype,{init:function(){for(var ah=0;ah<this.drawables.length;ah++){this.drawables[ah].init()}},_draw:function(){for(var ah=0;ah<this.drawables.length;ah++){this.drawables[ah]._draw()}},to_json:function(){var ai=[];for(var ah=0;ah<this.drawables.length;ah++){ai.push(this.drawables[ah].to_json())}return{name:this.name,prefs:this.prefs,obj_type:this.obj_type,drawables:ai}},add_drawable:function(ah){this.drawables.push(ah);ah.container=this},add_drawable_before:function(aj,ah){var ai=this.drawables.indexOf(ah);if(ai!=-1){this.drawables.splice(ai,0,aj);return true}return false},remove_drawable:function(ai){var ah=this.drawables.indexOf(ai);if(ah!=-1){this.drawables.splice(ah,1);ai.container=null;return true}return false},move_drawable:function(ai,aj){var ah=this.drawables.indexOf(ai);if(ah!=-1){this.drawables.splice(ah,1);this.drawables.splice(aj,0,ai);return true}return false}});var R=function(ak,ai,ah,aj){z.call(this,"DrawableGroup",ak,ai,ah,aj,"group-handle");if(!R.id_counter){R.id_counter=0}var al=R.id_counter++;this.container_div=$("<div/>").addClass("group").attr("id","group_"+al).appendTo(this.container.content_div);this.header_div=$("<div/>").addClass("track-header").appendTo(this.container_div);this.header_div.append($("<div/>").addClass(this.drag_handle_class));this.name_div=$("<div/>").addClass("group-name menubutton popup").text(this.name).appendTo(this.header_div);this.content_div=$("<div/>").addClass("content-div").attr("id","group_"+al+"_content_div").appendTo(this.container_div);m(this.container_div,this);m(this.content_div,this);n(this.container_div,this.drag_handle_class,".group",this);this.update_track_icons()};q(R.prototype,r.prototype,z.prototype,{update_track_icons:function(){var ai=this;var ah={};ah["Edit configuration"]=function(){var al=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},aj=function(){ai.config.update_from_form($(".dialog-box"));hide_modal();$(window).unbind("keypress.check_enter_esc")},ak=function(am){if((am.keyCode||am.which)===27){al()}else{if((am.keyCode||am.which)===13){aj()}}};$(window).bind("keypress.check_enter_esc",ak);show_modal("Configure Group",ai.config.build_form(),{Cancel:al,OK:aj})};ah.Remove=function(){ai.remove()};make_popupmenu(ai.name_div,ah)}});var ae=function(ah,ak,aj,ai){z.call(this,"View");this.container=ah;this.chrom=null;this.vis_id=aj;this.dbkey=ai;this.title=ak;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.init();this.canvas_manager=new ag(ah.get(0).ownerDocument);this.reset()};q(ae.prototype,z.prototype,{init:function(){var aj=this.container,ah=this;this.top_container=$("<div/>").addClass("top-container").appendTo(aj);this.browser_content_div=$("<div/>").addClass("content").css("position","relative").appendTo(aj);this.bottom_container=$("<div/>").addClass("bottom-container").appendTo(aj);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;m(this.viewport_container,ah);this.intro_div=$("<div/>").addClass("intro");var ak=$("<div/>").text("Add Datasets to Visualization").addClass("action-button").appendTo(this.intro_div).click(function(){add_tracks()});this.nav_labeltrack=$("<div/>").addClass("nav-labeltrack").appendTo(this.bottom_container);this.nav_container=$("<div/>").addClass("nav-container").prependTo(this.top_container);this.nav=$("<div/>").addClass("nav").appendTo(this.nav_container);this.overview=$("<div/>").addClass("overview").appendTo(this.bottom_container);this.overview_viewport=$("<div/>").addClass("overview-viewport").appendTo(this.overview);this.overview_close=$("<a/>").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").addClass("no-autocomplete").append("<option value=''>Loading</option>").appendTo(this.nav_controls);var ai=function(al){if(al.type==="focusout"||(al.keyCode||al.which)===13||(al.keyCode||al.which)===27){if((al.keyCode||al.which)!==27){ah.go_to($(this).val())}$(this).hide();$(this).val("");ah.location_span.show();ah.chrom_select.show()}};this.nav_input=$("<input/>").addClass("nav-input").hide().bind("keyup focusout",ai).appendTo(this.nav_controls);this.location_span=$("<span/>").addClass("location").appendTo(this.nav_controls);this.location_span.click(function(){ah.location_span.hide();ah.chrom_select.hide();ah.nav_input.val(ah.chrom+":"+ah.low+"-"+ah.high);ah.nav_input.css("display","inline-block");ah.nav_input.select();ah.nav_input.focus()});if(this.vis_id!==undefined){this.hidden_input=$("<input/>").attr("type","hidden").val(this.vis_id).appendTo(this.nav_controls)}this.zo_link=$("<a id='zoom-out' />").click(function(){ah.zoom_out();ah.request_redraw()}).appendTo(this.nav_controls);this.zi_link=$("<a id='zoom-in' />").click(function(){ah.zoom_in();ah.request_redraw()}).appendTo(this.nav_controls);this.load_chroms_deferred=this.load_chroms({low:0});this.chrom_select.bind("change",function(){ah.change_chrom(ah.chrom_select.val())});this.browser_content_div.click(function(al){$(this).find("input").trigger("blur")});this.browser_content_div.bind("dblclick",function(al){ah.zoom_in(al.pageX,this.viewport_container)});this.overview_box.bind("dragstart",function(al,am){this.current_x=am.offsetX}).bind("drag",function(al,an){var ao=an.offsetX-this.current_x;this.current_x=an.offsetX;var am=Math.round(ao/ah.viewport_container.width()*(ah.max_high-ah.max_low));ah.move_delta(-am)});this.overview_close.click(function(){ah.reset_overview()});this.viewport_container.bind("draginit",function(al,am){if(al.clientX>ah.viewport_container.width()-16){return false}}).bind("dragstart",function(al,am){am.original_low=ah.low;am.current_height=al.clientY;am.current_x=am.offsetX}).bind("drag",function(an,ap){var al=$(this);var aq=ap.offsetX-ap.current_x;var am=al.scrollTop()-(an.clientY-ap.current_height);al.scrollTop(am);ap.current_height=an.clientY;ap.current_x=ap.offsetX;var ao=Math.round(aq/ah.viewport_container.width()*(ah.high-ah.low));ah.move_delta(ao)}).bind("mousewheel",function(an,ap,am,al){if(am){var ao=Math.round(-am/ah.viewport_container.width()*(ah.high-ah.low));ah.move_delta(ao)}});this.top_labeltrack.bind("dragstart",function(al,am){return $("<div />").css({height:ah.browser_content_div.height()+ah.top_labeltrack.height()+ah.nav_labeltrack.height()+1,top:"0px",position:"absolute","background-color":"#ccf",opacity:0.5,"z-index":1000}).appendTo($(this))}).bind("drag",function(ap,aq){$(aq.proxy).css({left:Math.min(ap.pageX,aq.startX),width:Math.abs(ap.pageX-aq.startX)});var am=Math.min(ap.pageX,aq.startX)-ah.container.offset().left,al=Math.max(ap.pageX,aq.startX)-ah.container.offset().left,ao=(ah.high-ah.low),an=ah.viewport_container.width();ah.update_location(Math.round(am/an*ao)+ah.low,Math.round(al/an*ao)+ah.low)}).bind("dragend",function(aq,ar){var am=Math.min(aq.pageX,ar.startX),al=Math.max(aq.pageX,ar.startX),ao=(ah.high-ah.low),an=ah.viewport_container.width(),ap=ah.low;ah.low=Math.round(am/an*ao)+ap;ah.high=Math.round(al/an*ao)+ap;$(ar.proxy).remove();ah.request_redraw()});this.add_label_track(new ad(this,{content_div:this.top_labeltrack}));this.add_label_track(new ad(this,{content_div:this.nav_labeltrack}));$(window).bind("resize",function(){ah.resize_window()});$(document).bind("redraw",function(){ah.redraw()});this.reset();$(window).trigger("resize");this.update_intro_div()},update_intro_div:function(){if(this.num_tracks===0){this.intro_div.appendTo(this.viewport_container)}else{this.intro_div.remove()}},update_location:function(ah,ai){this.location_span.text(commatize(ah)+" - "+commatize(ai));this.nav_input.val(this.chrom+":"+commatize(ah)+"-"+commatize(ai))},load_chroms:function(aj){aj.num=x;$.extend(aj,(this.vis_id!==undefined?{vis_id:this.vis_id}:{dbkey:this.dbkey}));var ah=this,ai=$.Deferred();$.ajax({url:chrom_url,data:aj,dataType:"json",success:function(al){if(al.chrom_info.length===0){alert("Invalid chromosome: "+aj.chrom);return}if(al.reference){ah.add_label_track(new B(ah))}ah.chrom_data=al.chrom_info;var ao='<option value="">Select Chrom/Contig</option>';for(var an=0,ak=ah.chrom_data.length;an<ak;an++){var am=ah.chrom_data[an].chrom;ao+='<option value="'+am+'">'+am+"</option>"}if(al.prev_chroms){ao+='<option value="previous">Previous '+x+"</option>"}if(al.next_chroms){ao+='<option value="next">Next '+x+"</option>"}ah.chrom_select.html(ao);ah.chrom_start_index=al.start_index;ai.resolve(al)},error:function(){alert("Could not load chroms for this dbkey:",ah.dbkey)}});return ai},change_chrom:function(am,ai,ao){if(!am||am==="None"){return}var aj=this;if(am==="previous"){aj.load_chroms({low:this.chrom_start_index-x});return}if(am==="next"){aj.load_chroms({low:this.chrom_start_index+x});return}var an=$.grep(aj.chrom_data,function(ap,aq){return ap.chrom===am})[0];if(an===undefined){aj.load_chroms({chrom:am},function(){aj.change_chrom(am,ai,ao)});return}else{if(am!==aj.chrom){aj.chrom=am;aj.chrom_select.val(aj.chrom);aj.max_high=an.len-1;aj.reset();aj.request_redraw(true);for(var al=0,ah=aj.drawables.length;al<ah;al++){var ak=aj.drawables[al];if(ak.init){ak.init()}}}if(ai!==undefined&&ao!==undefined){aj.low=Math.max(ai,0);aj.high=Math.min(ao,aj.max_high)}aj.reset_overview();aj.request_redraw()}},go_to:function(al){var ap=this,ah,ak,ai=al.split(":"),an=ai[0],ao=ai[1];if(ao!==undefined){try{var am=ao.split("-");ah=parseInt(am[0].replace(/,/g,""),10);ak=parseInt(am[1].replace(/,/g,""),10)}catch(aj){return false}}ap.change_chrom(an,ah,ak)},move_fraction:function(aj){var ah=this;var ai=ah.high-ah.low;this.move_delta(aj*ai)},move_delta:function(aj){var ah=this;var ai=ah.high-ah.low;if(ah.low-aj<ah.max_low){ah.low=ah.max_low;ah.high=ah.max_low+ai}else{if(ah.high-aj>ah.max_high){ah.high=ah.max_high;ah.low=ah.max_high-ai}else{ah.high-=aj;ah.low-=aj}}ah.request_redraw()},add_drawable:function(ah){z.prototype.add_drawable.call(this,ah);ah.init();this.has_changes=true;this.update_intro_div()},add_label_track:function(ah){ah.view=this;ah.init();this.label_tracks.push(ah)},remove_drawable:function(aj,ai){z.prototype.remove_drawable.call(this,aj);if(ai){var ah=this;aj.container_div.fadeOut("slow",function(){$(this).remove();ah.update_intro_div()});this.has_changes=true}},reset:function(){this.low=this.max_low;this.high=this.max_high;this.viewport_container.find(".yaxislabel").remove()},request_redraw:function(ap,ah,ao,ai){var an=this,al=(ai?[ai]:an.drawables),aj;var ai;for(var am=0;am<al.length;am++){ai=al[am];aj=-1;for(var ak=0;ak<an.tracks_to_be_redrawn.length;ak++){if(an.tracks_to_be_redrawn[ak][0]===ai){aj=ak;break}}if(aj<0){an.tracks_to_be_redrawn.push([ai,ah,ao])}else{an.tracks_to_be_redrawn[am][1]=ah;an.tracks_to_be_redrawn[am][2]=ao}}requestAnimationFrame(function(){an._redraw(ap)})},_redraw:function(ar){var ao=this.low,ak=this.high;if(ao<this.max_low){ao=this.max_low}if(ak>this.max_high){ak=this.max_high}var aq=this.high-this.low;if(this.high!==0&&aq<this.min_separation){ak=ao+this.min_separation}this.low=Math.floor(ao);this.high=Math.ceil(ak);this.resolution=Math.pow(D,Math.ceil(Math.log((this.high-this.low)/S)/Math.log(D)));this.zoom_res=Math.pow(w,Math.max(0,Math.ceil(Math.log(this.resolution,w)/Math.log(w))));var ah=(this.low/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var an=((this.high-this.low)/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var at=13;this.overview_box.css({left:ah,width:Math.max(at,an)}).show();if(an<at){this.overview_box.css("left",ah-(at-an)/2)}if(this.overview_highlight){this.overview_highlight.css({left:ah,width:an})}this.update_location(this.low,this.high);if(!ar){var aj,ai,ap;for(var al=0,am=this.tracks_to_be_redrawn.length;al<am;al++){aj=this.tracks_to_be_redrawn[al][0];ai=this.tracks_to_be_redrawn[al][1];ap=this.tracks_to_be_redrawn[al][2];if(aj){aj._draw(ai,ap)}}this.tracks_to_be_redrawn=[];for(al=0,am=this.label_tracks.length;al<am;al++){this.label_tracks[al]._draw()}}},zoom_in:function(ai,aj){if(this.max_high===0||this.high-this.low<this.min_separation){return}var ak=this.high-this.low,al=ak/2+this.low,ah=(ak/this.zoom_factor)/2;if(ai){al=ai/this.viewport_container.width()*(this.high-this.low)+this.low}this.low=Math.round(al-ah);this.high=Math.round(al+ah);this.request_redraw()},zoom_out:function(){if(this.max_high===0){return}var ai=this.high-this.low,aj=ai/2+this.low,ah=(ai*this.zoom_factor)/2;this.low=Math.round(aj-ah);this.high=Math.round(aj+ah);this.request_redraw()},resize_window:function(){this.viewport_container.height(this.container.height()-this.top_container.height()-this.bottom_container.height());this.nav_container.width(this.container.width());this.request_redraw()},set_overview:function(aj){if(this.overview_drawable){if(this.overview_drawable.dataset_id===aj.dataset_id){return}this.overview_viewport.find(".track").remove()}var ai=aj.copy({content_div:this.overview_viewport}),ah=this;ai.header_div.hide();ai.is_overview=true;ah.overview_drawable=ai;this.overview_drawable.postdraw_actions=function(){ah.overview_highlight.show().height(ah.overview_drawable.content_div.height());ah.overview_viewport.height(ah.overview_drawable.content_div.height()+ah.overview_box.outerHeight());ah.overview_close.show();ah.resize_window()};this.overview_drawable.init();ah.has_changes=true},reset_overview:function(){$(".tipsy").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(aj,an){this.track=aj;this.name=an.name;this.params=[];var av=an.params;for(var ak=0;ak<av.length;ak++){var ap=av[ak],ai=ap.name,au=ap.label,al=unescape(ap.html),aw=ap.value,ar=ap.type;if(ar==="number"){this.params[this.params.length]=new g(ai,au,al,aw,ap.min,ap.max)}else{if(ar=="select"){this.params[this.params.length]=new P(ai,au,al,aw)}else{console.log("WARNING: unrecognized tool parameter type:",ai,ar)}}}this.parent_div=$("<div/>").addClass("dynamic-tool").hide();this.parent_div.bind("drag",function(ay){ay.stopPropagation()}).click(function(ay){ay.stopPropagation()}).bind("dblclick",function(ay){ay.stopPropagation()});var at=$("<div class='tool-name'>").appendTo(this.parent_div).text(this.name);var aq=this.params;var ao=this;$.each(this.params,function(az,aC){var aB=$("<div>").addClass("param-row").appendTo(ao.parent_div);var ay=$("<div>").addClass("param-label").text(aC.label).appendTo(aB);var aA=$("<div/>").addClass("slider").html(aC.html).appendTo(aB);aA.find(":input").val(aC.value);$("<div style='clear: both;'/>").appendTo(aB)});this.parent_div.find("input").click(function(){$(this).select()});var ax=$("<div>").addClass("param-row").appendTo(this.parent_div);var am=$("<input type='submit'>").attr("value","Run on complete dataset").appendTo(ax);var ah=$("<input type='submit'>").attr("value","Run on visible region").css("margin-left","3em").appendTo(ax);var ao=this;ah.click(function(){ao.run_on_region()});am.click(function(){ao.run_on_dataset()})};q(s.prototype,{get_param_values_dict:function(){var ah={};this.parent_div.find(":input").each(function(){var ai=$(this).attr("name"),aj=$(this).val();ah[ai]=JSON.stringify(aj)});return ah},get_param_values:function(){var ai=[];var ah={};this.parent_div.find(":input").each(function(){var aj=$(this).attr("name"),ak=$(this).val();if(aj){ai[ai.length]=ak}});return ai},run_on_dataset:function(){var ah=this;ah.run({dataset_id:this.track.original_dataset_id,tool_id:ah.name},null,function(ai){show_modal(ah.name+" is Running",ah.name+" is running on the complete dataset. Tool outputs are in dataset's history.",{Close:hide_modal})})},run_on_region:function(){var ai={dataset_id:this.track.original_dataset_id,chrom:this.track.view.chrom,low:this.track.view.low,high:this.track.view.high,tool_id:this.name},al=this.track,aj=ai.tool_id+al.tool_region_and_parameters_str(ai.chrom,ai.low,ai.high),ah,am;if(al.container===view){var ak=new R(this.name,this.track.view,this.track.container);al.container.add_drawable(ak);al.container.remove_drawable(al);ak.add_drawable(al);al.container_div.appendTo(ak.content_div);ah=ak}else{ah=al.container}if(al instanceof e){am=new W(aj,view,ah,"hda");am.change_mode(al.mode);ah.add_drawable(am)}am.content_div.text("Starting job.");this.run(ai,am,function(an){am.dataset_id=an.dataset_id;am.content_div.text("Running job.");am.init()})},run:function(ai,aj,ak){$.extend(ai,this.get_param_values_dict());var ah=function(){$.getJSON(rerun_tool_url,ai,function(al){if(al==="no converter"){aj.container_div.addClass("error");aj.content_div.text(L)}else{if(al.error){aj.container_div.addClass("error");aj.content_div.text(y+al.message)}else{if(al==="pending"){aj.container_div.addClass("pending");aj.content_div.text("Converting input data so that it can be used quickly with tool.");setTimeout(ah,2000)}else{ak(al)}}}})};ah()}});var P=function(ai,ah,aj,ak){this.name=ai;this.label=ah;this.html=aj;this.value=ak};var g=function(aj,ai,al,am,ak,ah){P.call(this,aj,ai,al,am);this.min=ak;this.max=ah};var h=function(ai,ah,aj,ak){this.name=ai;this.index=ah;this.tool_id=aj;this.tool_exp_name=ak};var X=function(ai,ah,aj,ak){h.call(this,ai,ah,aj,ak);this.low=-Number.MAX_VALUE;this.high=Number.MAX_VALUE;this.min=Number.MAX_VALUE;this.max=-Number.MAX_VALUE;this.container=null;this.slider=null;this.slider_label=null};q(X.prototype,{applies_to:function(ah){if(ah.length>this.index){return true}return false},keep:function(ah){if(!this.applies_to(ah)){return true}var ai=ah[this.index];return(isNaN(ai)||(ai>=this.low&&ai<=this.high))},update_attrs:function(ai){var ah=false;if(!this.applies_to(ai)){return ah}if(ai[this.index]<this.min){this.min=Math.floor(ai[this.index]);ah=true}if(ai[this.index]>this.max){this.max=Math.ceil(ai[this.index]);ah=true}return ah},update_ui_elt:function(){if(this.min!=this.max){this.container.show()}else{this.container.hide()}var aj=function(am,ak){var al=ak-am;return(al<=2?0.01:1)};var ai=this.slider.slider("option","min"),ah=this.slider.slider("option","max");if(this.min<ai||this.max>ah){this.slider.slider("option","min",this.min);this.slider.slider("option","max",this.max);this.slider.slider("option","step",aj(this.min,this.max));this.slider.slider("option","values",[this.min,this.max])}}});var ac=function(at,aA){this.track=at;this.filters=[];for(var av=0;av<aA.length;av++){var aw=aA[av],aB=aw.name,ah=aw.type,aj=aw.index,az=aw.tool_id,ay=aw.tool_exp_name;if(ah==="int"||ah==="float"){this.filters[av]=new X(aB,aj,az,ay)}else{console.log("ERROR: unsupported filter: ",aB,ah)}}var ak=function(aC,aD,aE){aC.click(function(){var aF=aD.text();max=parseFloat(aE.slider("option","max")),input_size=(max<=1?4:max<=1000000?max.toString().length:6),multi_value=false;if(aE.slider("option","values")){input_size=2*input_size+1;multi_value=true}aD.text("");$("<input type='text'/>").attr("size",input_size).attr("maxlength",input_size).attr("value",aF).appendTo(aD).focus().select().click(function(aG){aG.stopPropagation()}).blur(function(){$(this).remove();aD.text(aF)}).keyup(function(aK){if(aK.keyCode===27){$(this).trigger("blur")}else{if(aK.keyCode===13){var aI=aE.slider("option","min"),aG=aE.slider("option","max"),aJ=function(aL){return(isNaN(aL)||aL>aG||aL<aI)},aH=$(this).val();if(!multi_value){aH=parseFloat(aH);if(aJ(aH)){alert("Parameter value must be in the range ["+aI+"-"+aG+"]");return $(this)}}else{aH=aH.split("-");aH=[parseFloat(aH[0]),parseFloat(aH[1])];if(aJ(aH[0])||aJ(aH[1])){alert("Parameter value must be in the range ["+aI+"-"+aG+"]");return $(this)}}aE.slider((multi_value?"values":"value"),aH)}}})})};this.parent_div=$("<div/>").addClass("filters").hide();this.parent_div.bind("drag",function(aC){aC.stopPropagation()}).click(function(aC){aC.stopPropagation()}).bind("dblclick",function(aC){aC.stopPropagation()}).bind("keydown",function(aC){aC.stopPropagation()});var ax=$("<div/>").addClass("sliders").appendTo(this.parent_div);var ap=this;$.each(this.filters,function(aF,aH){aH.container=$("<div/>").addClass("filter-row slider-row").appendTo(ax);var aG=$("<div/>").addClass("elt-label").appendTo(aH.container);var aE=$("<span/>").addClass("slider-name").text(aH.name+" ").appendTo(aG);var aD=$("<span/>");var aJ=$("<span/>").addClass("slider-value").appendTo(aG).append("[").append(aD).append("]");var aC=$("<div/>").addClass("slider").appendTo(aH.container);aH.control_element=$("<div/>").attr("id",aH.name+"-filter-control").appendTo(aC);var aI=[0,0];aH.control_element.slider({range:true,min:Number.MAX_VALUE,max:-Number.MIN_VALUE,values:[0,0],slide:function(aL,aM){var aK=aM.values;aD.text(aK[0]+"-"+aK[1]);aH.low=aK[0];aH.high=aK[1];ap.track.request_draw(true,true)},change:function(aK,aL){aH.control_element.slider("option","slide").call(aH.control_element,aK,aL)}});aH.slider=aH.control_element;aH.slider_label=aD;ak(aJ,aD,aH.control_element);$("<div style='clear: both;'/>").appendTo(aH.container)});if(this.filters.length!==0){var am=$("<div/>").addClass("param-row").appendTo(ax);var ao=$("<input type='submit'/>").attr("value","Run on complete dataset").appendTo(am);var ai=this;ao.click(function(){ai.run_on_dataset()})}var ar=$("<div/>").addClass("display-controls").appendTo(this.parent_div),au,an,aq,al={Transparency:function(aC){ap.alpha_filter=aC},Height:function(aC){ap.height_filter=aC}};$.each(al,function(aE,aD){au=$("<div/>").addClass("filter-row").appendTo(ar),an=$("<span/>").addClass("elt-label").text(aE+":").appendTo(au),aq=$("<select/>").attr("name",aE+"_dropdown").css("float","right").appendTo(au);$("<option/>").attr("value",-1).text("== None ==").appendTo(aq);for(var aC=0;aC<ap.filters.length;aC++){$("<option/>").attr("value",aC).text(ap.filters[aC].name).appendTo(aq)}aq.change(function(){$(this).children("option:selected").each(function(){var aF=parseInt($(this).val());al[aE]((aF>=0?ap.filters[aF]:null));ap.track.request_draw(true,true)})});$("<div style='clear: both;'/>").appendTo(au)});$("<div style='clear: both;'/>").appendTo(this.parent_div)};q(ac.prototype,{reset_filters:function(){for(var ah=0;ah<this.filters.length;ah++){filter=this.filters[ah];filter.slider.slider("option","values",[filter.min,filter.max])}this.alpha_filter=null;this.height_filter=null},run_on_dataset:function(){var ap=function(au,ar,at){if(!(ar in au)){au[ar]=at}return au[ar]};var aj={},ah,ai,ak;for(var al=0;al<this.filters.length;al++){ah=this.filters[al];if(ah.tool_id){if(ah.min!=ah.low){ai=ap(aj,ah.tool_id,[]);ai[ai.length]=ah.tool_exp_name+" >= "+ah.low}if(ah.max!=ah.high){ai=ap(aj,ah.tool_id,[]);ai[ai.length]=ah.tool_exp_name+" <= "+ah.high}}}var an=[];for(var aq in aj){an[an.length]=[aq,aj[aq]]}var ao=an.length;(function am(ay,av){var at=av[0],au=at[0],ax=at[1],aw="("+ax.join(") and (")+")",ar={cond:aw,input:ay,target_dataset_id:ay,tool_id:au},av=av.slice(1);$.getJSON(run_tool_url,ar,function(az){if(az.error){show_modal("Filter Dataset","Error running tool "+au,{Close:hide_modal})}else{if(av.length===0){show_modal("Filtering Dataset","Filter(s) are running on the complete dataset. Outputs are in dataset's history.",{Close:hide_modal})}else{am(az.dataset_id,av)}}})})(this.track.dataset_id,an)}});var E=function(ah,ai){N.Scaler.call(this,ai);this.filter=ah};E.prototype.gen_val=function(ah){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(ah[this.filter.index])-this.filter.low)/(this.filter.high-this.filter.low))};var H=function(ah){this.track=ah.track;this.params=ah.params;this.values={};this.restore_values((ah.saved_values?ah.saved_values:{}));this.onchange=ah.onchange};q(H.prototype,{restore_values:function(ah){var ai=this;$.each(this.params,function(aj,ak){if(ah[ak.key]!==undefined){ai.values[ak.key]=ah[ak.key]}else{ai.values[ak.key]=ak.default_value}})},build_form:function(){var ai=this;var ah=$("<div />");$.each(this.params,function(am,ak){if(!ak.hidden){var aj="param_"+am;var ao=ai.values[ak.key];var ar=$("<div class='form-row' />").appendTo(ah);ar.append($("<label />").attr("for",aj).text(ak.label+":"));if(ak.type==="bool"){ar.append($('<input type="checkbox" />').attr("id",aj).attr("name",aj).attr("checked",ao))}else{if(ak.type==="text"){ar.append($('<input type="text"/>').attr("id",aj).val(ao).click(function(){$(this).select()}))}else{if(ak.type==="color"){var an=$("<input />").attr("id",aj).attr("name",aj).val(ao);var ap=$("<div class='tipsy tipsy-north' style='position: absolute;' />").hide();var al=$("<div style='background-color: black; padding: 10px;'></div>").appendTo(ap);var aq=$("<div/>").appendTo(al).farbtastic({width:100,height:100,callback:an,color:ao});$("<div />").append(an).append(ap).appendTo(ar).bind("click",function(at){ap.css({left:$(this).position().left+($(an).width()/2)-60,top:$(this).position().top+$(this.height)}).show();$(document).bind("click.color-picker",function(){ap.hide();$(document).unbind("click.color-picker")});at.stopPropagation()})}else{ar.append($("<input />").attr("id",aj).attr("name",aj).val(ao))}}}}});return ah},update_from_form:function(ah){var aj=this;var ai=false;$.each(this.params,function(ak,am){if(!am.hidden){var an="param_"+ak;var al=ah.find("#"+an).val();if(am.type==="float"){al=parseFloat(al)}else{if(am.type==="int"){al=parseInt(al)}else{if(am.type==="bool"){al=ah.find("#"+an).is(":checked")}}}if(al!==aj.values[am.key]){aj.values[am.key]=al;ai=true}}});if(ai){this.onchange()}}});var b=function(ah,ak,aj,ai,al){this.track=ah;this.index=ak;this.low=ak*S*aj;this.high=(ak+1)*S*aj;this.resolution=aj;this.canvas=$("<div class='track-tile'/>").append(ai);this.data=al;this.stale=false};b.prototype.predisplay_actions=function(){};var l=function(ah,ak,aj,ai,al,am){b.call(this,ah,ak,aj,ai,al);this.max_val=am};q(l.prototype,b.prototype);var Q=function(ah,al,ak,aj,an,ao,am,ai){b.call(this,ah,al,ak,aj,an);this.mode=ao;this.message=am;this.feature_mapper=ai};q(Q.prototype,b.prototype);Q.prototype.predisplay_actions=function(){var ai=this,ah={};if(ai.mode!=="Pack"){return}$(this.canvas).mousemove(function(au){var ao=$(this).offset(),at=au.pageX-ao.left,ar=au.pageY-ao.top,ay=ai.feature_mapper.get_feature_data(at,ar),ap=(ay?ay[0]:null);$(this).siblings(".feature-popup").each(function(){if(!ap||$(this).attr("id")!==ap.toString()){$(this).remove()}});if(ay){var ak=ah[ap];if(!ak){var ap=ay[0],av={name:ay[3],start:ay[1],end:ay[2],strand:ay[4]},an=ai.track.filters_manager.filters,am;for(var aq=0;aq<an.length;aq++){am=an[aq];av[am.name]=ay[am.index]}var ak=$("<div/>").attr("id",ap).addClass("feature-popup"),ax,aw,az=$("<table/>").appendTo(ak),aA;for(ax in av){aw=av[ax];aA=$("<tr/>").appendTo(az);$("<th/>").appendTo(aA).text(ax);$("<td/>").attr("align","left").appendTo(aA).text(typeof(aw)=="number"?ab(aw,2):aw)}ah[ap]=ak}ak.appendTo($(ai.canvas).parent());var al=at+parseInt(ai.canvas.css("left"))+7,aj=ar+parseInt(ai.canvas.css("top"))+7;ak.css("left",al+"px").css("top",aj+"px")}else{if(!au.isPropagationStopped()){au.stopPropagation();$(this).siblings().each(function(){$(this).trigger(au)})}}}).mouseleave(function(){$(this).siblings(".feature-popup").remove()})};var j=function(ak,at,al,ao,au,aj,ai){r.call(this,ak,at,al,{},"draghandle");this.data_url=(aj?aj:default_data_url);this.data_url_extra_params={};this.data_query_wait=(ai?ai:M);this.dataset_check_url=converted_datasets_state_url;if(!j.id_counter){j.id_counter=0}this.id=j.id_counter++;this.container_div=$("<div />").addClass("track").attr("id","track_"+this.id).css("position","relative");if(ao){this.header_div=$("<div class='track-header' />").appendTo(this.container_div);if(this.view.editor){this.drag_div=$("<div/>").addClass(this.drag_handle_class).appendTo(this.header_div)}this.name_div=$("<div/>").addClass("track-name").appendTo(this.header_div).text(this.name).attr("id",this.name.replace(/\s+/g,"-").replace(/[^a-zA-Z0-9\-]/g,"").toLowerCase());this.icons_div=$("<div/>").css("float","left").appendTo(this.header_div).hide();this.settings_icon=$("<a/>").attr("href","javascript:void(0);").attr("title","Edit settings").addClass("icon-button settings-icon").tipsy({gravity:"s"}).appendTo(this.icons_div);this.overview_icon=$("<a/>").attr("href","javascript:void(0);").attr("title","Set as overview").addClass("icon-button overview-icon").tipsy({gravity:"s"}).appendTo(this.icons_div);this.filters_icon=$("<a/>").attr("href","javascript:void(0);").attr("title","Filters").addClass("icon-button filters-icon").tipsy({gravity:"s"}).appendTo(this.icons_div).hide();this.tools_icon=$("<a/>").attr("href","javascript:void(0);").attr("title","Tools").addClass("icon-button tools-icon").tipsy({gravity:"s"}).appendTo(this.icons_div).hide();this.remove_icon=$("<a/>").attr("href","javascript:void(0);").attr("title","Remove").addClass("icon-button remove-icon").tipsy({gravity:"s"}).appendTo(this.icons_div);var am=this;this.header_div.dblclick(function(av){av.stopPropagation()});this.settings_icon.click(function(){var ax=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},av=function(){am.config.update_from_form($(".dialog-box"));hide_modal();$(window).unbind("keypress.check_enter_esc")},aw=function(ay){if((ay.keyCode||ay.which)===27){ax()}else{if((ay.keyCode||ay.which)===13){av()}}};$(window).bind("keypress.check_enter_esc",aw);show_modal("Configure Track",am.config.build_form(),{Cancel:ax,OK:av})});this.overview_icon.click(function(){am.view.set_overview(am)});this.filters_icon.click(function(){am.filters_div.toggle();am.filters_manager.reset_filters()});this.tools_icon.click(function(){am.dynamic_tool_div.toggle();if(am.dynamic_tool_div.is(":visible")){am.set_name(am.name+am.tool_region_and_parameters_str())}else{am.revert_name()}$(".tipsy").remove()});this.remove_icon.click(function(){$(".tipsy").remove();am.remove()});if(am.display_modes!==undefined){if(am.mode_div===undefined){am.mode_div=$("<div class='right-float menubutton popup' />").appendTo(am.header_div);var an=(am.config&&am.config.values.mode?am.config.values.mode:am.display_modes[0]);am.mode=an;am.mode_div.text(an);var ah={};for(var ap=0,ar=am.display_modes.length;ap<ar;ap++){var aq=am.display_modes[ap];ah[aq]=function(av){return function(){am.change_mode(av)}}(aq)}make_popupmenu(am.mode_div,ah)}else{am.mode_div.hide()}this.header_div.append($("<div/>").css("clear","both"));this.container_div.hover(function(){am.icons_div.show()},function(){am.icons_div.hide()})}}this.content_div=$("<div class='track-content'>").appendTo(this.container_div);this.container.content_div.append(this.container_div)};q(j.prototype,r.prototype,{get_type:function(){if(this instanceof ad){return"LabelTrack"}else{if(this instanceof B){return"ReferenceTrack"}else{if(this instanceof k){return"LineTrack"}else{if(this instanceof Y){return"ReadTrack"}else{if(this instanceof W){return"ToolDataFeatureTrack"}else{if(this instanceof V){return"VcfTrack"}else{if(this instanceof e){return"FeatureTrack"}}}}}}}return""},init:function(){var ah=this;ah.enabled=false;ah.tile_cache.clear();ah.data_manager.clear();ah.initial_canvas=undefined;ah.content_div.css("height","auto");ah.container_div.removeClass("nodata error pending");if(!ah.dataset_id){return}$.getJSON(converted_datasets_state_url,{hda_ldda:ah.hda_ldda,dataset_id:ah.dataset_id,chrom:ah.view.chrom},function(ai){if(!ai||ai==="error"||ai.kind==="error"){ah.container_div.addClass("error");ah.content_div.text(p);if(ai.message){var aj=$(" <a href='javascript:void(0);'></a>").text("View error").click(function(){show_modal("Trackster Error","<pre>"+ai.message+"</pre>",{Close:hide_modal})});ah.content_div.append(aj)}}else{if(ai==="no converter"){ah.container_div.addClass("error");ah.content_div.text(L)}else{if(ai==="no data"||(ai.data!==undefined&&(ai.data===null||ai.data.length===0))){ah.container_div.addClass("nodata");ah.content_div.text(G)}else{if(ai==="pending"){ah.container_div.addClass("pending");ah.content_div.text(u);setTimeout(function(){ah.init()},ah.data_query_wait)}else{if(ai.status==="data"){if(ai.valid_chroms){ah.valid_chroms=ai.valid_chroms;ah.update_track_icons()}ah.content_div.text(aa);if(ah.view.chrom){ah.content_div.text("");ah.content_div.css("height",ah.height_px+"px");ah.enabled=true;$.when(ah.predraw_init()).done(function(){ah.container_div.removeClass("nodata error pending");ah.request_draw()})}}}}}}});this.update_track_icons()},predraw_init:function(){}});var O=function(ak,aj){var ai=this,ah=ai.view;n(ai.container_div,ai.drag_handle_class,".group",ai);this.filters_manager=new ac(this,(ak!==undefined?ak:{}));this.filters_available=false;this.filters_visible=false;this.tool=(aj!==undefined&&obj_length(aj)>0?new s(this,aj):undefined);if(this.header_div){if(this.filters_manager){this.filters_div=this.filters_manager.parent_div;this.header_div.after(this.filters_div)}if(this.tool){this.dynamic_tool_div=this.tool.parent_div;this.header_div.after(this.dynamic_tool_div)}}};q(O.prototype,r.prototype,j.prototype,{copy:function(ah){return new this.constructor(this.name,this.view,ah,this.hda_ldda,this.dataset_id,this.prefs,this.filters,this.tool)},to_json: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,}},change_mode:function(ai){var ah=this;ah.mode_div.text(ai);ah.mode=ai;ah.config.values.mode=ai;ah.tile_cache.clear();ah.request_draw();return ah},update_track_icons:function(){var ah=this;if(ah.filters_available>0){ah.filters_icon.show()}else{ah.filters_icon.hide()}if(ah.tool){ah.tools_icon.show()}else{ah.tools_icon.hide()}},_gen_tile_cache_key:function(ai,aj,ah){return ai+"_"+aj+"_"+ah},request_draw:function(ai,ah){this.view.request_redraw(false,ai,ah,this)},_draw:function(aj,ar){if(!this.enabled){return}if(!(this instanceof B)&&(!this.dataset_id)){return}var aq=this.view.low,an=this.view.high,ao=an-aq,ak=this.view.container.width(),av=ak/ao,am=this.view.resolution,au=$("<div style='position: relative;'></div>");if(this.is_overview){aq=this.view.max_low;an=this.view.max_high;am=Math.pow(D,Math.ceil(Math.log((view.max_high-view.max_low)/S)/Math.log(D)));av=ak/(view.max_high-view.max_low)}if(!ar){this.content_div.children().remove()}this.content_div.append(au);this.max_height=0;var ai=Math.floor(aq/am/S);var ap=true;var at=[];var ah=0;while((ai*S*am)<an){tile=this.draw_helper(aj,ak,ai,am,au,av);if(tile){at.push(tile)}else{ap=false}ai+=1;ah++}var al=this;if(ap){al.postdraw_actions(at,ak,av,ar)}},postdraw_actions:function(al,am,an,ah){var aj=this;var ak=false;for(var ai=0;ai<al.length;ai++){if(al[ai].message){ak=true;break}}if(ak){for(var ai=0;ai<al.length;ai++){tile=al[ai];if(!tile.message){tile.canvas.css("padding-top",F)}}}},draw_helper:function(ai,aj,ak,an,au,ay,av,ao){var al=this,at=this._gen_tile_cache_key(aj,ay,ak),ap=ak*S*an,ax=ap+S*an;var aq=(ai?undefined:al.tile_cache.get(at));if(aq){al.show_tile(aq,au,ay);return aq}var ar=function(az){return("isResolved" in az)};var am=true;var ah=al.data_manager.get_data(ap,ax,al.mode,an,al.data_url_extra_params);if(ar(ah)){am=false}var aw;if(view.reference_track&&ay>view.canvas_manager.char_width_px){aw=view.reference_track.data_manager.get_data(ap,ax,al.mode,an,view.reference_track.data_url_extra_params);if(ar(aw)){am=false}}if(am){q(ah,ao);var aq=al.draw_tile(ah,al.mode,an,ak,ay,aw);if(aq!==undefined){al.tile_cache.set(at,aq);al.show_tile(aq,au,ay)}return aq}$.when(ah,aw).then(function(){view.request_redraw(false,false,false,al)});return null},show_tile:function(an,ap,aq){var aj=this,ai=an.canvas,am=ai;if(an.message){var ar=$("<div/>"),ao=$("<div/>").addClass("tile-message").text(an.message).css({height:F-1,width:an.canvas.width}).appendTo(ar),al=$("<a href='javascript:void(0);'/>").addClass("icon more-down").appendTo(ao),ah=$("<a href='javascript:void(0);'/>").addClass("icon more-across").appendTo(ao);ar.append(ai);am=ar;al.click(function(){an.stale=true;aj.data_manager.get_more_data(an.low,an.high,aj.mode,an.resolution,{},aj.data_manager.DEEP_DATA_REQ);aj.request_draw()}).dblclick(function(at){at.stopPropagation()});ah.click(function(){an.stale=true;aj.data_manager.get_more_data(an.low,an.high,aj.mode,an.resolution,{},aj.data_manager.BROAD_DATA_REQ);aj.request_draw()}).dblclick(function(at){at.stopPropagation()})}an.predisplay_actions();var ak=(an.low-(this.is_overview?this.view.max_low:this.view.low))*aq;if(this.left_offset){ak-=this.left_offset}am.css({position:"absolute",top:0,left:ak,height:""});ap.append(am);aj.max_height=Math.max(aj.max_height,am.height());aj.content_div.css("height",aj.max_height+"px");ap.children().css("height",aj.max_height+"px")},_get_tile_bounds:function(ah,ai){var ak=ah*S*ai,al=S*ai,aj=(ak+al<=this.view.max_high?ak+al:this.view.max_high);return[ak,aj]},tool_region_and_parameters_str:function(aj,ah,ak){var ai=this,al=(aj!==undefined&&ah!==undefined&&ak!==undefined?aj+":"+ah+"-"+ak:"all");return" - region=["+al+"], parameters=["+ai.tool.get_param_values().join(", ")+"]"}});var ad=function(ai,ah){j.call(this,"label",ai,ah,false,{});this.container_div.addClass("label-track")};q(ad.prototype,j.prototype,{init:function(){this.enabled=true},_draw:function(){var aj=this.view,ak=aj.high-aj.low,an=Math.floor(Math.pow(10,Math.floor(Math.log(ak)/Math.log(10)))),ah=Math.floor(aj.low/an)*an,al=this.view.container.width(),ai=$("<div style='position: relative; height: 1.3em;'></div>");while(ah<aj.high){var am=(ah-aj.low)/ak*al;ai.append($("<div class='label'>"+commatize(ah)+"</div>").css({position:"absolute",left:am-1}));ah+=an}this.content_div.children(":first").remove();this.content_div.append(ai)}});var B=function(ah){j.call(this,"reference",ah,{content_div:ah.top_labeltrack},false,{});O.call(this);ah.reference_track=this;this.left_offset=200;this.height_px=12;this.container_div.addClass("reference-track");this.content_div.css("background","none");this.content_div.css("min-height","0px");this.content_div.css("border","none");this.data_url=reference_url;this.data_url_extra_params={dbkey:ah.dbkey};this.data_manager=new J(C,this,false);this.tile_cache=new c(v)};q(B.prototype,r.prototype,O.prototype,{init:function(){this.enabled=true},draw_tile:function(ar,an,am,ai,at){var al=this,aj=S*am;if(at>this.view.canvas_manager.char_width_px){if(ar.data===null){al.content_div.css("height","0px");return}var ak=this.view.canvas_manager.new_canvas();var aq=ak.getContext("2d");ak.width=Math.ceil(aj*at+al.left_offset);ak.height=al.height_px;aq.font=aq.canvas.manager.default_font;aq.textAlign="center";ar=ar.data;for(var ao=0,ap=ar.length;ao<ap;ao++){var ah=Math.round(ao*at);aq.fillText(ar[ao],ah+al.left_offset,10)}return new b(al,ai,am,ak,ar)}this.content_div.css("height","0px")}});var k=function(am,ak,aj,an,ah,al){var ai=this;this.display_modes=["Histogram","Line","Filled","Intensity"];this.mode="Histogram";j.call(this,am,ak,aj,al);O.call(this);this.min_height_px=16;this.max_height_px=400;this.height_px=80;this.hda_ldda=an;this.dataset_id=ah;this.original_dataset_id=ah;this.data_manager=new T(C,this);this.tile_cache=new c(v);this.left_offset=0;this.config=new H({track:this,params:[{key:"name",label:"Name",type:"text",default_value:am},{key:"color",label:"Color",type:"color",default_value: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:this.height_px,hidden:true}],saved_values:al,onchange:function(){ai.set_name(ai.prefs.name);ai.vertical_range=ai.prefs.max_value-ai.prefs.min_value;$("#linetrack_"+ai.dataset_id+"_minval").text(ai.prefs.min_value);$("#linetrack_"+ai.dataset_id+"_maxval").text(ai.prefs.max_value);ai.tile_cache.clear();ai.request_draw()}});this.prefs=this.config.values;this.height_px=this.config.values.height;this.vertical_range=this.config.values.max_value-this.config.values.min_value;this.add_resize_handle()};q(k.prototype,r.prototype,O.prototype,{add_resize_handle:function(){var ah=this;var ak=false;var aj=false;var ai=$("<div class='track-resize'>");$(ah.container_div).hover(function(){ak=true;ai.show()},function(){ak=false;if(!aj){ai.hide()}});ai.hide().bind("dragstart",function(al,am){aj=true;am.original_height=$(ah.content_div).height()}).bind("drag",function(am,an){var al=Math.min(Math.max(an.original_height+an.deltaY,ah.min_height_px),ah.max_height_px);$(ah.content_div).css("height",al);ah.height_px=al;ah.request_draw(true)}).bind("dragend",function(al,am){ah.tile_cache.clear();aj=false;if(!ak){ai.hide()}ah.config.values.height=ah.height_px}).appendTo(ah.container_div)},predraw_init:function(){var ah=this;ah.vertical_range=undefined;return $.getJSON(ah.data_url,{stats:true,chrom:ah.view.chrom,low:null,high:null,hda_ldda:ah.hda_ldda,dataset_id:ah.dataset_id},function(ai){ah.container_div.addClass("line-track");var ak=ai.data;if(isNaN(parseFloat(ah.prefs.min_value))||isNaN(parseFloat(ah.prefs.max_value))){ah.prefs.min_value=ak.min;ah.prefs.max_value=ak.max;$("#track_"+ah.dataset_id+"_minval").val(ah.prefs.min_value);$("#track_"+ah.dataset_id+"_maxval").val(ah.prefs.max_value)}ah.vertical_range=ah.prefs.max_value-ah.prefs.min_value;ah.total_frequency=ak.total_frequency;ah.container_div.find(".yaxislabel").remove();var al=$("<div />").addClass("yaxislabel").attr("id","linetrack_"+ah.dataset_id+"_minval").text(ab(ah.prefs.min_value,3));var aj=$("<div />").addClass("yaxislabel").attr("id","linetrack_"+ah.dataset_id+"_maxval").text(ab(ah.prefs.max_value,3));aj.css({position:"absolute",top:"24px",left:"10px"});aj.prependTo(ah.container_div);al.css({position:"absolute",bottom:"2px",left:"10px"});al.prependTo(ah.container_div)})},draw_tile:function(au,am,al,aj,at){if(this.vertical_range===undefined){return}var ah=this._get_tile_bounds(aj,al),an=ah[0],ar=ah[1],ai=Math.ceil((ar-an)*at),ap=this.height_px;var ak=this.view.canvas_manager.new_canvas();ak.width=ai,ak.height=ap;var aq=ak.getContext("2d");var ao=new N.LinePainter(au.data,an,ar,this.prefs,am);ao.draw(aq,ai,ap);return new b(this.track,aj,al,ak,au.data)}});var e=function(ah,an,ai,am,ap,ao,ak,al){var aj=this;this.display_modes=["Auto","Histogram","Dense","Squish","Pack"];j.call(this,ah,an,ai,true,ao);O.call(this,ak,al);this.config=new H({track:this,params:[{key:"name",label:"Name",type:"text",default_value:ah},{key:"block_color",label:"Block color",type:"color",default_value:get_random_color()},{key:"label_color",label:"Label color",type:"color",default_value:"black"},{key:"show_counts",label:"Show summary counts",type:"bool",default_value:true},{key:"mode",type:"string",default_value:this.mode,hidden:true},],saved_values:ao,onchange:function(){aj.set_name(aj.prefs.name);aj.tile_cache.clear();aj.request_draw()}});this.prefs=this.config.values;this.height_px=0;this.container_div.addClass("feature-track");this.hda_ldda=am;this.dataset_id=ap;this.original_dataset_id=ap;this.show_labels_scale=0.001;this.showing_details=false;this.summary_draw_height=30;this.inc_slots={};this.start_end_dct={};this.tile_cache=new c(d);this.data_manager=new T(20,this);this.left_offset=200;this.painter=N.LinkedFeaturePainter};q(e.prototype,r.prototype,O.prototype,{postdraw_actions:function(ax,ah,ay,aw){O.prototype.postdraw_actions.call(this,ax,aw);var ak=this;if(aw){var am=ak.content_div.children();var an=false;for(var al=am.length-1,ar=0;al>=ar;al--){var aj=$(am[al]);if(an){aj.remove()}else{if(aj.children().length!==0){an=true}}}}if(ak.mode=="Histogram"){var aq=-1;for(var al=0;al<ax.length;al++){var av=ax[al].max_val;if(av>aq){aq=av}}for(var al=0;al<ax.length;al++){var au=ax[al];if(au.max_val!==aq){au.canvas.remove();ak.draw_helper(true,ah,au.index,au.resolution,au.canvas.parent(),ay,[],{max:aq})}}}if(ak.filters_manager){var ai=ak.filters_manager.filters;for(var ap=0;ap<ai.length;ap++){ai[ap].update_ui_elt()}var ao=false,at;for(var al=0;al<ax.length;al++){if(ax[al].data.length){at=ax[al].data[0];for(var ap=0;ap<ai.length;ap++){if(ai[ap].applies_to(at)){ao=true;break}}}}if(ak.filters_available!==ao){ak.filters_available=ao;if(!ak.filters_available){ak.filters_div.hide()}ak.update_track_icons()}}},update_auto_mode:function(ah){if(this.mode=="Auto"){if(ah=="no_detail"){ah="feature spans"}else{if(ah=="summary_tree"){ah="coverage histogram"}}this.mode_div.text("Auto ("+ah+")")}},incremental_slots:function(al,ai,ak){var aj=this.view.canvas_manager.dummy_context,ah=this.inc_slots[al];if(!ah||(ah.mode!==ak)){ah=new (t.FeatureSlotter)(al,ak==="Pack",A,function(am){return aj.measureText(am)});ah.mode=ak;this.inc_slots[al]=ah}return ah.slot_features(ai)},get_summary_tree_data:function(al,ao,aj,ax){if(ax>aj-ao){ax=aj-ao}var at=Math.floor((aj-ao)/ax),aw=[],ak=0;var am=0,an=0,ar,av=0,ap=[],au,aq;var ai=function(aA,az,aB,ay){aA[0]=az+aB*ay;aA[1]=az+(aB+1)*ay};while(av<ax&&am!==al.length){var ah=false;for(;av<ax&&!ah;av++){ai(ap,ao,av,at);for(an=am;an<al.length;an++){ar=al[an].slice(1,3);if(is_overlap(ar,ap)){ah=true;break}}if(ah){break}}data_start_index=an;aw[aw.length]=au=[ap[0],0];for(;an<al.length;an++){ar=al[an].slice(1,3);if(is_overlap(ar,ap)){au[1]++}else{break}}if(au[1]>ak){ak=au[1]}av++}return{max:ak,delta:at,data:aw}},draw_tile:function(aw,az,aD,aH,ar,ak){var aA=this,am=aA._get_tile_bounds(aH,aD),aK=am[0],ai=am[1],ay=ai-aK,aB=Math.ceil(ay*ar),aQ=25,al=this.left_offset,ax,an;if(az==="Auto"){if(aw.dataset_type==="summary_tree"){az=aw.dataset_type}else{if(aw.extra_info==="no_detail"||aA.is_overview){az="no_detail"}else{var aP=aw.data;if(this.view.high-this.view.low>K){az="Squish"}else{az="Pack"}}}this.update_auto_mode(az)}if(az==="summary_tree"||az==="Histogram"){an=this.summary_draw_height;this.container_div.find(".yaxislabel").remove();var ah=$("<div />").addClass("yaxislabel");ah.text(aw.max);ah.css({position:"absolute",top:"24px",left:"10px",color:this.prefs.label_color});ah.prependTo(this.container_div);var aj=this.view.canvas_manager.new_canvas();aj.width=aB+al;aj.height=an+U;if(aw.dataset_type!="summary_tree"){var at=this.get_summary_tree_data(aw.data,aK,ai,200);if(aw.max){at.max=aw.max}aw=at}var aM=new N.SummaryTreePainter(aw,aK,ai,this.prefs);var aC=aj.getContext("2d");aC.translate(al,U);aM.draw(aC,aB,an);return new l(aA,aH,aD,aj,aw.data,aw.max)}var ax,ap=1;if(az==="no_detail"||az==="Squish"||az==="Pack"){ap=this.incremental_slots(ar,aw.data,az);ax=this.inc_slots[ar].slots}var aq=[];if(aw.data){var au=this.filters_manager.filters;for(var aE=0,aG=aw.data.length;aE<aG;aE++){var ao=aw.data[aE];var aF=false;var av;for(var aJ=0,aO=au.length;aJ<aO;aJ++){av=au[aJ];av.update_attrs(ao);if(!av.keep(ao)){aF=true;break}}if(!aF){aq.push(ao)}}}var aN=(this.filters_manager.alpha_filter?new E(this.filters_manager.alpha_filter):null);var aL=(this.filters_manager.height_filter?new E(this.filters_manager.height_filter):null);var aM=new (this.painter)(aq,aK,ai,this.prefs,az,aN,aL,ak);var an=Math.max(af,aM.get_required_height(ap));var aj=this.view.canvas_manager.new_canvas();var aI=null;aj.width=aB+al;aj.height=an;var aC=aj.getContext("2d");aC.fillStyle=this.prefs.block_color;aC.font=aC.canvas.manager.default_font;aC.textAlign="right";this.container_div.find(".yaxislabel").remove();if(aw.data){aC.translate(al,0);aI=aM.draw(aC,aB,an,ax);aI.translation=-al}return new Q(aA,aH,aD,aj,aw.data,az,aw.message,aI)}});var V=function(al,aj,ai,an,ah,ak,am){e.call(this,al,aj,ai,an,ah,ak,am);this.painter=N.VariantPainter};q(V.prototype,r.prototype,O.prototype,e.prototype);var Y=function(al,aj,ai,an,ah,ak,am){e.call(this,al,aj,ai,an,ah,ak,am);this.config=new H({track:this,params:[{key:"name",label:"Name",type:"text",default_value:al},{key:"block_color",label:"Block color",type:"color",default_value: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_differences",label:"Show differences only",type:"bool",default_value:true},{key:"show_counts",label:"Show summary counts",type:"bool",default_value:true},{key:"mode",type:"string",default_value:this.mode,hidden:true},],saved_values:ak,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=N.ReadPainter;this.update_track_icons()};q(Y.prototype,r.prototype,O.prototype,e.prototype);var W=function(al,aj,ai,an,ah,ak,am){e.call(this,al,aj,ai,an,ah,ak,am,{});this.data_url=raw_data_url;this.data_query_wait=1000;this.dataset_check_url=dataset_state_url};q(W.prototype,r.prototype,O.prototype,e.prototype,{predraw_init:function(){var ai=this;var ah=function(){if(ai.data_manager.size()===0){setTimeout(ah,300)}else{ai.data_url=default_data_url;ai.data_query_wait=M;ai.dataset_state_url=converted_datasets_state_url;$.getJSON(ai.dataset_state_url,{dataset_id:ai.dataset_id,hda_ldda:ai.hda_ldda},function(aj){})}};ah()}});Z.View=ae;Z.DrawableGroup=R;Z.LineTrack=k;Z.FeatureTrack=e;Z.ReadTrack=Y};var slotting_module=function(c,b){var e=c("class").extend;var d=2,a=5;b.FeatureSlotter=function(j,h,f,g){this.slots={};this.start_end_dct={};this.w_scale=j;this.include_label=h;this.max_rows=f;this.measureText=g};e(b.FeatureSlotter.prototype,{slot_features:function(m){var p=this.w_scale,s=this.slots,h=this.start_end_dct,y=[],A=[],n=0,z=this.max_rows;for(var w=0,x=m.length;w<x;w++){var l=m[w],o=l[0];if(s[o]!==undefined){n=Math.max(n,s[o]);A.push(s[o])}else{y.push(w)}}var q=function(G,H){for(var F=0;F<=z;F++){var D=false,I=h[F];if(I!==undefined){for(var C=0,E=I.length;C<E;C++){var B=I[C];if(H>B[0]&&G<B[1]){D=true;break}}}if(!D){return F}}return -1};for(var w=0,x=y.length;w<x;w++){var l=m[y[w]],o=l[0],u=l[1],f=l[2],r=l[3],g=Math.floor(u*p),k=Math.ceil(f*p),v=this.measureText(r).width,j;if(r!==undefined&&this.include_label){v+=(d+a);if(g-v>=0){g-=v;j="left"}else{k+=v;j="right"}}var t=q(g,k);if(t>=0){if(h[t]===undefined){h[t]=[]}h[t].push([g,k]);s[o]=t;n=Math.max(n,t)}else{}}return n+1}})};var painters_module=function(k,y){var v=k("class").extend;var q=function(J,B,H,A,G,E){if(E===undefined){E=4}var D=A-B;var C=G-H;var F=Math.floor(Math.sqrt(D*D+C*C)/E);var K=D/F;var I=C/F;var z;for(z=0;z<F;z++,B+=K,H+=I){if(z%2!==0){continue}J.fillRect(B,H,E,1)}};var r=function(B,A,z,E){var D=A-E/2,C=A+E/2,F=z-Math.sqrt(E*3/2);B.beginPath();B.moveTo(D,F);B.lineTo(C,F);B.lineTo(A,z);B.lineTo(D,F);B.strokeStyle=this.fillStyle;B.fill();B.stroke();B.closePath()};var e=function(z){this.default_val=(z?z:1)};e.prototype.gen_val=function(z){return this.default_val};var n=function(B,D,z,A,C){this.data=B;this.view_start=D;this.view_end=z;this.prefs=v({},this.default_prefs,A);this.mode=C};n.prototype.default_prefs={};var w=function(B,D,z,A,C){n.call(this,B,D,z,A,C)};w.prototype.default_prefs={show_counts:false};w.prototype.draw=function(M,z,L){var E=this.view_start,O=this.view_end-this.view_start,N=z/O;var J=this.data.data,I=this.data.delta,G=this.data.max,B=L;delta_x_px=Math.ceil(I*N);M.save();for(var C=0,D=J.length;C<D;C++){var H=Math.floor((J[C][0]-E)*N);var F=J[C][1];if(!F){continue}var K=F/G*L;if(F!==0&&K<1){K=1}M.fillStyle=this.prefs.block_color;M.fillRect(H,B-K,delta_x_px,K);var A=4;if(this.prefs.show_counts&&(M.measureText(F).width+A)<delta_x_px){M.fillStyle=this.prefs.label_color;M.textAlign="center";M.fillText(F,H+(delta_x_px/2),10)}}M.restore()};var c=function(z,D,F,G,B){n.call(this,z,D,F,G,B);if(this.prefs.min_value===undefined){var H=Infinity;for(var A=0,C=this.data.length;A<C;A++){H=Math.min(H,this.data[A][1])}this.prefs.min_value=H}if(this.prefs.max_value===undefined){var E=-Infinity;for(var A=0,C=this.data.length;A<C;A++){E=Math.max(E,this.data[A][1])}this.prefs.max_value=E}};c.prototype.default_prefs={min_value:undefined,max_value:undefined,mode:"Histogram",color:"#000",overflow_color:"#F66"};c.prototype.draw=function(N,M,K){var F=false,H=this.prefs.min_value,D=this.prefs.max_value,J=D-H,z=K,A=this.view_start,L=this.view_end-this.view_start,B=M/L,I=this.mode,T=this.data;N.save();var U=Math.round(K+H/J*K);if(I!=="Intensity"){N.fillStyle="#aaa";N.fillRect(0,U,M,1)}N.beginPath();var R,E,C;if(T.length>1){C=Math.ceil((T[1][0]-T[0][0])*B)}else{C=10}for(var O=0,P=T.length;O<P;O++){N.fillStyle=this.prefs.color;R=Math.round((T[O][0]-A)*B);E=T[O][1];var Q=false,G=false;if(E===null){if(F&&I==="Filled"){N.lineTo(R,z)}F=false;continue}if(E<H){G=true;E=H}else{if(E>D){Q=true;E=D}}if(I==="Histogram"){E=Math.round(E/J*z);N.fillRect(R,U,C,-E)}else{if(I==="Intensity"){E=255-Math.floor((E-H)/J*255);N.fillStyle="rgb("+E+","+E+","+E+")";N.fillRect(R,0,C,z)}else{E=Math.round(z-(E-H)/J*z);if(F){N.lineTo(R,E)}else{F=true;if(I==="Filled"){N.moveTo(R,z);N.lineTo(R,E)}else{N.moveTo(R,E)}}}}N.fillStyle=this.prefs.overflow_color;if(Q||G){var S;if(I==="Histogram"||I==="Intensity"){S=C}else{R-=2;S=4}if(Q){N.fillRect(R,0,S,3)}if(G){N.fillRect(R,z-3,S,3)}}N.fillStyle=this.prefs.color}if(I==="Filled"){if(F){N.lineTo(R,U);N.lineTo(0,U)}N.fill()}else{N.stroke()}N.restore()};var o=function(z){this.feature_positions={};this.slot_height=z;this.translation=0};o.prototype.map_feature_data=function(A,C,z,B){if(!this.feature_positions[C]){this.feature_positions[C]=[]}this.feature_positions[C].push({data:A,x_start:z,x_end:B})};o.prototype.get_feature_data=function(z,D){var C=Math.floor(D/this.slot_height),B;if(!this.feature_positions[C]){return null}z+=this.translation;for(var A=0;A<this.feature_positions[C].length;A++){B=this.feature_positions[C][A];if(z>=B.x_start&&z<=B.x_end){return B.data}}};var p=function(B,E,z,A,D,F,C){n.call(this,B,E,z,A,D);this.alpha_scaler=(F?F:new e());this.height_scaler=(C?C:new e())};p.prototype.default_prefs={block_color:"#FFF",connector_color:"#FFF"};v(p.prototype,{get_required_height:function(A){var z=y_scale=this.get_row_height(),B=this.mode;if(B==="no_detail"||B==="Squish"||B==="Pack"){z=A*y_scale}return z+Math.max(Math.round(y_scale/2),5)},draw:function(L,J,H,G){var R=this.data,E=this.view_start,N=this.view_end;L.save();L.fillStyle=this.prefs.block_color;L.textAlign="right";var I=this.view_end-this.view_start,F=J/I,M=this.get_row_height(),Q=new o(M),C;for(var O=0,P=R.length;O<P;O++){var B=R[O],D=B[0],K=B[1],z=B[2],A=(G&&G[D]!==undefined?G[D]:null);if((K<N&&z>E)&&(this.mode=="Dense"||A!==null)){C=this.draw_element(L,this.mode,B,A,E,N,F,M,J);Q.map_feature_data(B,A,C[0],C[1])}}L.restore();return Q},draw_element:function(F,B,H,D,C,E,G,A,z){console.log("WARNING: Unimplemented function.");return[0,0]}});var d=10,j=3,m=5,x=10,g=1,t=3,f=3,a=9,l=2,h="#ccc";var s=function(B,E,z,A,D,F,C){p.call(this,B,E,z,A,D,F,C)};v(s.prototype,p.prototype,{get_row_height:function(){var A=this.mode,z;if(A==="Dense"){z=d}else{if(A==="no_detail"){z=j}else{if(A==="Squish"){z=m}else{z=x}}}return z},draw_element:function(N,E,W,I,P,ah,al,an,z){var T=W[0],aj=W[1],ab=W[2],R=W[3],ac=Math.floor(Math.max(0,(aj-P)*al)),O=Math.ceil(Math.min(z,Math.max(0,(ab-P)*al))),aa=ac,am=O,Z=(E==="Dense"?0:(0+I))*an,M,af,S=null,ap=null,C=this.prefs.block_color,ae=this.prefs.label_color;N.globalAlpha=this.alpha_scaler.gen_val(W);if(E=="Dense"){I=1}if(E==="no_detail"){N.fillStyle=C;N.fillRect(ac,Z+5,O-ac,g)}else{var L=W[4],Y=W[5],ad=W[6],D=W[7];if(Y&&ad){S=Math.floor(Math.max(0,(Y-P)*al));ap=Math.ceil(Math.min(z,Math.max(0,(ad-P)*al)))}var ak,U;if(E==="Squish"||E==="Dense"){ak=1;U=f}else{ak=5;U=a}if(!D){if(W.strand){if(W.strand==="+"){N.fillStyle=N.canvas.manager.get_pattern("right_strand_inv")}else{if(W.strand==="-"){N.fillStyle=N.canvas.manager.get_pattern("left_strand_inv")}}}else{N.fillStyle=C}N.fillRect(ac,Z,O-ac,U)}else{var K,V;if(E==="Squish"||E==="Dense"){N.fillStyle=h;K=Z+Math.floor(f/2)+1;V=1}else{if(L){var K=Z;var V=U;if(L==="+"){N.fillStyle=N.canvas.manager.get_pattern("right_strand")}else{if(L==="-"){N.fillStyle=N.canvas.manager.get_pattern("left_strand")}}}else{N.fillStyle=h;K+=(f/2)+1;V=1}}N.fillRect(ac,K,O-ac,V);var F;for(var ai=0,B=D.length;ai<B;ai++){var G=D[ai],A=Math.floor(Math.max(0,(G[0]-P)*al)),X=Math.ceil(Math.min(z,Math.max((G[1]-P)*al)));if(A>X){continue}N.fillStyle=C;N.fillRect(A,Z+(U-ak)/2+1,X-A,ak);if(S!==undefined&&ad>Y&&!(A>ap||X<S)){var ag=Math.max(A,S),J=Math.min(X,ap);N.fillRect(ag,Z+1,J-ag,U);if(D.length==1&&E=="Pack"){if(L==="+"){N.fillStyle=N.canvas.manager.get_pattern("right_strand_inv")}else{if(L==="-"){N.fillStyle=N.canvas.manager.get_pattern("left_strand_inv")}}if(ag+14<J){ag+=2;J-=2}N.fillRect(ag,Z+1,J-ag,U)}}}if(E==="Pack"){N.globalAlpha=1;N.fillStyle="white";var H=this.height_scaler.gen_val(W),Q=Math.ceil(U*H),ao=Math.round((U-Q)/2);if(H!==1){N.fillRect(ac,K+1,O-ac,ao);N.fillRect(ac,K+U-ao+1,O-ac,ao)}}}N.globalAlpha=1;if(E==="Pack"&&aj>P){N.fillStyle=ae;if(P===0&&ac-N.measureText(R).width<0){N.textAlign="left";N.fillText(R,O+l,Z+8);am+=N.measureText(R).width+l}else{N.textAlign="right";N.fillText(R,ac-l,Z+8);aa-=N.measureText(R).width+l}}}N.globalAlpha=1;return[aa,am]}});var b=function(B,E,z,A,D,F,C){p.call(this,B,E,z,A,D,F,C)};v(b.prototype,p.prototype,{draw_element:function(S,N,H,D,V,B,K,T,Q){var H=data[i],J=H[0],R=H[1],C=H[2],M=H[3],F=Math.floor(Math.max(0,(R-V)*K)),I=Math.ceil(Math.min(Q,Math.max(0,(C-V)*K))),E=(N==="Dense"?0:(0+D))*T,z,W,A=null,L=null;if(no_label){S.fillStyle=block_color;S.fillRect(F+left_offset,E+5,I-F,1)}else{var U=H[4],P=H[5],G=H[6];z=9;W=1;S.fillRect(F+left_offset,E,I-F,z);if(N!=="Dense"&&M!==undefined&&R>V){S.fillStyle=label_color;if(V===0&&F-S.measureText(M).width<0){S.textAlign="left";S.fillText(M,I+2+left_offset,E+8)}else{S.textAlign="right";S.fillText(M,F-2+left_offset,E+8)}S.fillStyle=block_color}var O=U+" / "+P;if(R>V&&S.measureText(O).width<(I-F)){S.fillStyle="white";S.textAlign="center";S.fillText(O,left_offset+F+(I-F)/2,E+8);S.fillStyle=block_color}}return[F,I]}});var u=function(C,F,z,B,E,G,D,A){p.call(this,C,F,z,B,E,G,D);this.ref_seq=(A?A.data:null)};u.prototype.default_prefs=v({},p.prototype.default_prefs,{show_insertions:false});v(u.prototype,p.prototype,{get_row_height:function(){var z,A=this.mode;if(A==="Dense"){z=d}else{if(A==="Squish"){z=m}else{z=x;if(this.prefs.show_insertions){z*=2}}}return z},draw_read:function(W,R,N,ab,C,V,K,H,G){W.textAlign="center";var U=this,B=[ab,C],Q=0,X=0,T=0,z=W.canvas.manager.char_width_px;var ag=[];if((R==="Pack"||this.mode==="Auto")&&H!==undefined&&N>z){T=Math.round(N/2)}if(!K){K=[[0,H.length]]}for(var O=0,Z=K.length;O<Z;O++){var L=K[O],D="MIDNSHP=X"[L[0]],P=L[1];if(D==="H"||D==="S"){Q-=P}var I=V+Q,af=Math.floor(Math.max(0,(I-ab)*N)),J=Math.floor(Math.max(0,(I+P-ab)*N));if(af===J){J+=1}switch(D){case"H":break;case"S":case"M":case"=":if(is_overlap([I,I+P],B)){var S=H.slice(X,X+P);if(T>0){W.fillStyle=this.prefs.block_color;W.fillRect(af-T,G+1,J-af,9);W.fillStyle=h;for(var ad=0,A=S.length;ad<A;ad++){if(this.prefs.show_differences&&this.ref_seq){var M=this.ref_seq[I-ab+ad];if(!M||M.toLowerCase()===S[ad].toLowerCase()){continue}}if(I+ad>=ab&&I+ad<=C){var ae=Math.floor(Math.max(0,(I+ad-ab)*N));W.fillText(S[ad],ae,G+9)}}}else{W.fillStyle=this.prefs.block_color;W.fillRect(af,G+4,J-af,f)}}X+=P;Q+=P;break;case"N":W.fillStyle=h;W.fillRect(af-T,G+5,J-af,1);Q+=P;break;case"D":W.fillStyle="red";W.fillRect(af-T,G+4,J-af,3);Q+=P;break;case"P":break;case"I":var aa=af-T;if(is_overlap([I,I+P],B)){var S=H.slice(X,X+P);if(this.prefs.show_insertions){var F=af-(J-af)/2;if((R==="Pack"||this.mode==="Auto")&&H!==undefined&&N>z){W.fillStyle="yellow";W.fillRect(F-T,G-9,J-af,9);ag[ag.length]={type:"triangle",data:[aa,G+4,5]};W.fillStyle=h;switch(seq_tile_overlap){case (OVERLAP_START):S=S.slice(ab-I);break;case (OVERLAP_END):S=S.slice(0,I-C);break;case (CONTAINED_BY):break;case (CONTAINS):S=S.slice(ab-I,I-C);break}for(var ad=0,A=S.length;ad<A;ad++){var ae=Math.floor(Math.max(0,(I+ad-ab)*N));W.fillText(S[ad],ae-(J-af)/2,G)}}else{W.fillStyle="yellow";W.fillRect(F,G+(this.mode!=="Dense"?2:5),J-af,(R!=="Dense"?f:t))}}else{if((R==="Pack"||this.mode==="Auto")&&H!==undefined&&N>z){ag[ag.length]={type:"text",data:[S.length,aa,G+9]}}else{}}}X+=P;break;case"X":X+=P;break}}W.fillStyle="yellow";var ac,E,ah;for(var Y=0;Y<ag.length;Y++){ac=ag[Y];E=ac.type;ah=ac.data;if(E==="text"){W.save();W.font="bold "+W.font;W.fillText(ah[0],ah[1],ah[2]);W.restore()}else{if(E=="triangle"){r(W,ah[0],ah[1],ah[2])}}}},draw_element:function(S,N,F,C,V,A,J,T,Q){var I=F[0],R=F[1],B=F[2],K=F[3],E=Math.floor(Math.max(0,(R-V)*J)),G=Math.ceil(Math.min(Q,Math.max(0,(B-V)*J))),D=(N==="Dense"?0:(0+C))*T,W=this.prefs.block_color,H=this.prefs.label_color,P=0;if((N==="Pack"||this.mode==="Auto")&&J>S.canvas.manager.char_width_px){var P=Math.round(J/2)}S.fillStyle=W;if(F[5] instanceof Array){var O=Math.floor(Math.max(0,(F[4][0]-V)*J)),M=Math.ceil(Math.min(Q,Math.max(0,(F[4][1]-V)*J))),L=Math.floor(Math.max(0,(F[5][0]-V)*J)),z=Math.ceil(Math.min(Q,Math.max(0,(F[5][1]-V)*J)));if(F[4][1]>=V&&F[4][0]<=A&&F[4][2]){this.draw_read(S,N,J,V,A,F[4][0],F[4][2],F[4][3],D)}if(F[5][1]>=V&&F[5][0]<=A&&F[5][2]){this.draw_read(S,N,J,V,A,F[5][0],F[5][2],F[5][3],D)}if(L>M){S.fillStyle=h;q(S,M-P,D+5,L-P,D+5)}}else{S.fillStyle=W;this.draw_read(S,N,J,V,A,R,F[4],F[5],D)}if(N==="Pack"&&R>V){S.fillStyle=this.prefs.label_color;var U=1;if(U===0&&E-S.measureText(K).width<0){S.textAlign="left";S.fillText(K,G+l-P,D+8)}else{S.textAlign="right";S.fillText(K,E-l-P,D+8)}S.fillStyle=W}return[0,0]}});y.Scaler=e;y.SummaryTreePainter=w;y.LinePainter=c;y.LinkedFeaturePainter=s;y.ReadPainter=u;y.VariantPainter=b};(function(d){var c={};var b=function(e){return c[e]};var a=function(f,g){var e={};g(b,e);c[f]=e};a("class",class_module);a("slotting",slotting_module);a("painters",painters_module);a("trackster",trackster_module);for(key in c.trackster){d[key]=c.trackster[key]}})(window);
\ No newline at end of file
diff -r 603924d3abc3057def82337b53178ad48a71b1d1 -r 125d735c689ee60ad9bd9601c7a22738ba3523de static/scripts/packed/trackster_ui.js
--- a/static/scripts/packed/trackster_ui.js
+++ b/static/scripts/packed/trackster_ui.js
@@ -1,1 +1,1 @@
-var add_bookmark=function(b,a){var g=$("#bookmarks-container"),d=$("<div/>").addClass("bookmark").appendTo(g),c=$("<div/>").addClass("delete-icon-container").appendTo(d).click(function(){d.slideUp("fast");d.remove();view.has_changes=true;return false}),e=$("<a href=''/>").addClass("icon-button delete").appendTo(c),f=$("<div/>").addClass("position").appendTo(d),h=$("<a href=''/>").text(b).appendTo(f).click(function(){view.go_to(b);return false});annotation_div=get_editable_text_elt(a,true).addClass("annotation").appendTo(d);view.has_changes=true;return d};var addable_objects={LineTrack:LineTrack,FeatureTrack:FeatureTrack,ReadTrack:ReadTrack,DrawableGroup:DrawableGroup};var track_from_dict=function(c,b){var a=new addable_objects[c.track_type](c.name,view,b,c.hda_ldda,c.dataset_id,c.prefs,c.filters,c.tool);if(c.mode){a.change_mode(c.mode)}return a};var drawable_collection_from_dict=function(f,a){var e=new addable_objects[f.obj_type](f.name,view,a,f.prefs,view.viewport_container,view);for(var d=0;d<f.drawables.length;d++){var b=f.drawables[d],c;if(b.track_type){c=track_from_dict(b,e)}else{c=drawable_collection_from_dict(b)}e.add_drawable(c);e.content_div.append(c.container_div)}return e};var drawable_from_dict=function(b,a){return(b.track_type?track_from_dict(b,a):drawable_collection_from_dict(b,a))};var create_visualization=function(b,e,g,c,a,d,f){view=new View(b,e,g,c);view.editor=true;$.when(view.load_chroms_deferred).then(function(){if(a){var k=a.chrom,p=a.start,h=a.end,m=a.overview;if(k&&(p!==undefined)&&h){view.change_chrom(k,p,h)}}if(d){var o;for(var j=0;j<d.length;j++){o=d[j];view.add_drawable(drawable_from_dict(o,view))}}var n;for(var j=0;j<view.drawables.length;j++){if(view.drawables[j].name==m){view.set_overview(view.drawables[j]);break}}if(f){var l;for(var j=0;j<f.length;j++){l=f[j];add_bookmark(l.position,l.annotation)}}view.has_changes=false});return view};var init_keyboard_nav=function(a){$(document).keydown(function(b){if($(b.srcElement).is(":input")){return}switch(b.which){case 37:a.move_fraction(0.25);break;case 38:var c=Math.round(a.viewport_container.height()/15);a.viewport_container.scrollTo("-="+c+"px");break;case 39:a.move_fraction(-0.25);break;case 40:var c=Math.round(a.viewport_container.height()/15);a.viewport_container.scrollTo("+="+c+"px");break}})};
\ No newline at end of file
+var add_bookmark=function(b,a){var g=$("#bookmarks-container"),d=$("<div/>").addClass("bookmark").appendTo(g),c=$("<div/>").addClass("delete-icon-container").appendTo(d).click(function(){d.slideUp("fast");d.remove();view.has_changes=true;return false}),e=$("<a href=''/>").addClass("icon-button delete").appendTo(c),f=$("<div/>").addClass("position").appendTo(d),h=$("<a href=''/>").text(b).appendTo(f).click(function(){view.go_to(b);return false});annotation_div=get_editable_text_elt(a,true).addClass("annotation").appendTo(d);view.has_changes=true;return d};var addable_objects={LineTrack:LineTrack,FeatureTrack:FeatureTrack,ReadTrack:ReadTrack,DrawableGroup:DrawableGroup};var track_from_dict=function(c,b){var a=new addable_objects[c.track_type](c.name,view,b,c.hda_ldda,c.dataset_id,c.prefs,c.filters,c.tool);if(c.mode){a.change_mode(c.mode)}return a};var drawable_collection_from_dict=function(f,a){var e=new addable_objects[f.obj_type](f.name,view,a,f.prefs,view.viewport_container,view);for(var d=0;d<f.drawables.length;d++){var b=f.drawables[d],c;if(b.track_type){c=track_from_dict(b,e)}else{c=drawable_collection_from_dict(b)}e.add_drawable(c);e.content_div.append(c.container_div)}return e};var drawable_from_dict=function(b,a){return(b.track_type?track_from_dict(b,a):drawable_collection_from_dict(b,a))};var create_visualization=function(b,e,g,c,a,d,f){view=new View(b,e,g,c);view.editor=true;$.when(view.load_chroms_deferred).then(function(){if(a){var k=a.chrom,p=a.start,h=a.end,m=a.overview;if(k&&(p!==undefined)&&h){view.change_chrom(k,p,h)}}if(d){var o;for(var j=0;j<d.length;j++){o=d[j];view.add_drawable(drawable_from_dict(o,view))}}var n;for(var j=0;j<view.drawables.length;j++){if(view.drawables[j].name===m){view.set_overview(view.drawables[j]);break}}if(f){var l;for(var j=0;j<f.length;j++){l=f[j];add_bookmark(l.position,l.annotation)}}view.has_changes=false});return view};var init_keyboard_nav=function(a){$(document).keydown(function(b){if($(b.srcElement).is(":input")){return}switch(b.which){case 37:a.move_fraction(0.25);break;case 38:var c=Math.round(a.viewport_container.height()/15);a.viewport_container.scrollTo("-="+c+"px");break;case 39:a.move_fraction(-0.25);break;case 40:var c=Math.round(a.viewport_container.height()/15);a.viewport_container.scrollTo("+="+c+"px");break}})};
\ No newline at end of file
diff -r 603924d3abc3057def82337b53178ad48a71b1d1 -r 125d735c689ee60ad9bd9601c7a22738ba3523de static/scripts/trackster.js
--- a/static/scripts/trackster.js
+++ b/static/scripts/trackster.js
@@ -37,7 +37,6 @@
};
})();
-
/**
* Compute the type of overlap between two regions. They are assumed to be on the same chrom/contig.
* The overlap is computed relative to the second region; hence, OVERLAP_START indicates that the first
@@ -74,6 +73,7 @@
return overlap;
};
+
/**
* Returns true if regions overlap.
*/
@@ -82,6 +82,74 @@
return (overlap !== BEFORE && overlap !== AFTER);
};
+/**
+ * Returns a random color in hexadecimal format that is sufficiently different from a single color
+ * or set of colors.
+ * @param colors a color or list of colors in the format '#RRGGBB'
+ */
+var get_random_color = function(colors) {
+ // Default for colors is white.
+ if (!colors) { colors = "#ffffff" };
+
+ // If needed, create list of colors.
+ if ( typeof(colors) === "string" ) {
+ colors = [ colors ];
+ }
+
+ // Convert colors to numbers.
+ for (var i = 0; i < colors.length; i++) {
+ colors[i] = parseInt( colors[i].slice(1), 16 );
+ }
+
+ // -- Perceived brightness and difference formulas are from
+ // -- http://www.w3.org/WAI/ER/WD-AERT/#color-contrast
+
+ // Compute perceived color brightness (based on RGB-YIQ transformation):
+ var brightness = function(r, g, b) {
+ return ( (r * 299) + (g * 587) + (b * 114) ) / 1000;
+ };
+
+ // Compute color difference:
+ var difference = function(r1, g1, b1, r2, g2, b2) {
+ return ( Math.max(r1, r2) - Math.min(r1, r2) ) +
+ ( Math.max(g1, g2) - Math.min(g1, g2) ) +
+ ( Math.max(b1, b2) - Math.min(b1, b2) );
+ };
+
+ // Create new random color.
+ var new_color, nr, ng, nb,
+ other_color, or, og, ob,
+ n_brightness, o_brightness,
+ diff, ok = false;
+ do {
+ // New color is never white b/c random in [0,1)
+ new_color = Math.random() * 0xffffff;
+ nr = new_color | 0xff0000;
+ ng = new_color | 0x00ff00;
+ nb = new_color | 0x0000ff;
+ n_brightness = brightness(nr, ng, nb);
+ ok = true;
+ for (var i = 0; i < colors.length; i++) {
+ other_color = colors[i];
+ or = other_color | 0xff0000;
+ og = other_color | 0x00ff00;
+ ob = other_color | 0x0000ff;
+ o_brightness = brightness(or, og, ob);
+ diff = difference(nr, ng, nb, or, og, ob);
+ // Thresholds for brightness difference and color difference
+ // are from W3C link above.
+ if ( ( Math.abs(n_brightness - o_brightness) < 125 ) ||
+ ( diff < 500 ) ) {
+ ok = false;
+ break;
+ }
+ }
+ } while (!ok);
+
+ // Add 0x1000000 to left pad number with 0s.
+ return '#' + ( 0x1000000 + new_color ).toString(16).substr(1,6);
+};
+
// Encapsulate -- anything to be availabe outside this block is added to exports
var trackster_module = function(require, exports) {
@@ -463,7 +531,7 @@
// data is ready, it then replaces itself with the actual data
entry = this.load_data(low, high, mode, resolution, extra_params);
this.set_data(low, high, mode, entry);
- return entry
+ return entry;
},
/** "Deep" data request; used as a parameter for DataManager.get_more_data() */
DEEP_DATA_REQ: "deep",
@@ -589,7 +657,6 @@
this.name = name;
this.view = view;
this.container = container;
- this.drag_handle_class = drag_handle_class;
this.config = new DrawableConfig({
track: this,
params: [
@@ -601,6 +668,8 @@
}
});
this.prefs = this.config.values;
+ this.drag_handle_class = drag_handle_class;
+ this.is_overview = false;
};
extend(Drawable.prototype, {
@@ -608,7 +677,7 @@
request_draw: function() {},
_draw: function() {},
to_json: function() {},
- make_name_popup_menu: function() {},
+ update_track_icons: function() {},
/**
* Set drawable name.
*/
@@ -750,14 +819,14 @@
is_container(this.content_div, this);
moveable(this.container_div, this.drag_handle_class, ".group", this);
- this.make_name_popup_menu();
+ this.update_track_icons();
};
extend(DrawableGroup.prototype, Drawable.prototype, DrawableCollection.prototype, {
/**
* Make popup menu for group.
*/
- make_name_popup_menu: function() {
+ update_track_icons: function() {
var group = this;
var group_dropdown = {};
@@ -852,7 +921,7 @@
// Overview (scrollbar and overview plot) at bottom
this.overview = $("<div/>").addClass("overview").appendTo(this.bottom_container);
this.overview_viewport = $("<div/>").addClass("overview-viewport").appendTo(this.overview);
- this.overview_close = $("<a href='javascript:void(0);'>Close Overview</a>").addClass("overview-close").hide().appendTo(this.overview_viewport);
+ this.overview_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);
@@ -1195,13 +1264,14 @@
/**
* Request that view redraw some or all tracks. If a track is not specificied, redraw all tracks.
*/
+ // FIXME: change method call so that track is first and additional parameters are optional.
request_redraw: function(nodraw, force, clear_after, track) {
var
view = this,
- // Either redrawing a single track or all view's tracks.
+ // Either redrawing a single drawable or all view's drawables.
track_list = (track ? [track] : view.drawables),
track_index;
-
+
// Add/update tracks in track list to redraw list.
var track;
for (var i = 0; i < track_list.length; i++) {
@@ -1318,42 +1388,44 @@
this.nav_container.width( this.container.width() );
this.request_redraw();
},
- /** Show a track in the overview. */
- set_overview: function(track) {
- // Get data and draw tile.
- $.when(track.get_overview_tile()).then(function(tile) {
- // Update UI.
- view.overview_viewport.find(".track-tile").remove();
+ /** Show a Drawable in the overview. */
+ set_overview: function(drawable) {
+ if (this.overview_drawable) {
+ // If drawable to be set as overview is already in overview, do nothing.
+ // Otherwise, remove overview.
+ if (this.overview_drawable.dataset_id === drawable.dataset_id) {
+ return;
+ }
+ this.overview_viewport.find(".track").remove();
+ }
+
+ // Set new overview.
+ var
+ overview_drawable = drawable.copy( { content_div: this.overview_viewport } ),
+ view = this;
+ overview_drawable.header_div.hide();
+ overview_drawable.is_overview = true;
+ view.overview_drawable = overview_drawable;
+ this.overview_drawable.postdraw_actions = function() {
+ view.overview_highlight.show().height(view.overview_drawable.content_div.height());
+ view.overview_viewport.height(view.overview_drawable.content_div.height() + view.overview_box.outerHeight());
view.overview_close.show();
- view.overview_viewport.append(tile.canvas);
- view.overview_highlight.show().height(tile.canvas.height());
- view.overview_viewport.height(tile.canvas.height() + view.overview_box.outerHeight());
view.resize_window();
-
- // Update view, track states.
- if (view.overview_track) {
- view.overview_track.set_is_overview(false);
- }
- view.overview_track = track;
- track.set_is_overview(true);
- });
+ };
+ this.overview_drawable.init();
view.has_changes = true;
},
/** Close and reset overview. */
reset_overview: function() {
// Update UI.
+ $(".tipsy").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();
-
- // Update view, track states.
- if (view.overview_track) {
- view.overview_track.set_is_overview(false);
- }
- view.overview_track = null;
+ view.overview_drawable = null;
}
});
@@ -2243,7 +2315,7 @@
* -------> ToolDataFeatureTrack
* -------> VcfTrack
*/
-var Track = function(name, view, container, prefs, data_url, data_query_wait) {
+var Track = function(name, view, container, show_header, prefs, data_url, data_query_wait) {
// For now, track's container is always view.
Drawable.call(this, name, view, container, {}, "draghandle");
@@ -2254,18 +2326,128 @@
this.data_url_extra_params = {}
this.data_query_wait = (data_query_wait ? data_query_wait : DEFAULT_DATA_QUERY_WAIT);
this.dataset_check_url = converted_datasets_state_url;
+
+ if (!Track.id_counter) { Track.id_counter = 0; }
+ this.id = Track.id_counter++;
//
// Create HTML element structure for track.
//
- if (!Track.id_counter) { Track.id_counter = 0; }
- this.container_div = $("<div />").addClass('track').attr("id", "track_" + Track.id_counter++).css("position", "relative");
- if (!this.hidden) {
+ this.container_div = $("<div />").addClass('track').attr("id", "track_" + this.id).css("position", "relative");
+
+ // Create and initialize track header and icons.
+ if (show_header) {
this.header_div = $("<div class='track-header' />").appendTo(this.container_div);
if (this.view.editor) { this.drag_div = $("<div/>").addClass(this.drag_handle_class).appendTo(this.header_div); }
- this.name_div = $("<div class='menubutton popup' />").appendTo(this.header_div);
- this.name_div.text(this.name);
- this.name_div.attr( "id", this.name.replace(/\s+/g,'-').replace(/[^a-zA-Z0-9\-]/g,'').toLowerCase() );
+ this.name_div = $("<div/>").addClass("track-name").appendTo(this.header_div).text(this.name)
+ .attr( "id", this.name.replace(/\s+/g,'-').replace(/[^a-zA-Z0-9\-]/g,'').toLowerCase() );
+ this.icons_div = $("<div/>").css("float", "left").appendTo(this.header_div).hide();
+
+ // Track icons.
+ this.settings_icon = $("<a/>").attr("href", "javascript:void(0);").attr("title", "Edit settings")
+ .addClass("icon-button settings-icon").tipsy( {gravity: 's'} )
+ .appendTo(this.icons_div);
+ this.overview_icon = $("<a/>").attr("href", "javascript:void(0);").attr("title", "Set as overview")
+ .addClass("icon-button overview-icon").tipsy( {gravity: 's'} )
+ .appendTo(this.icons_div);
+ this.filters_icon = $("<a/>").attr("href", "javascript:void(0);").attr("title", "Filters")
+ .addClass("icon-button filters-icon").tipsy( {gravity: 's'} )
+ .appendTo(this.icons_div).hide();
+ this.tools_icon = $("<a/>").attr("href", "javascript:void(0);").attr("title", "Tools")
+ .addClass("icon-button tools-icon").tipsy( {gravity: 's'} )
+ .appendTo(this.icons_div).hide();
+ this.remove_icon = $("<a/>").attr("href", "javascript:void(0);").attr("title", "Remove")
+ .addClass("icon-button remove-icon").tipsy( {gravity: 's'} )
+ .appendTo(this.icons_div);
+ var track = this;
+
+ // Suppress double clicks in header so that they do not impact viz.
+ this.header_div.dblclick( function(e) { e.stopPropagation(); } );
+
+ // Clicking on settings icon opens track config.
+ this.settings_icon.click( function() {
+ var cancel_fn = function() { hide_modal(); $(window).unbind("keypress.check_enter_esc"); },
+ ok_fn = function() {
+ track.config.update_from_form( $(".dialog-box") );
+ hide_modal();
+ $(window).unbind("keypress.check_enter_esc");
+ },
+ check_enter_esc = function(e) {
+ if ((e.keyCode || e.which) === 27) { // Escape key
+ cancel_fn();
+ } else if ((e.keyCode || e.which) === 13) { // Enter key
+ ok_fn();
+ }
+ };
+
+ $(window).bind("keypress.check_enter_esc", check_enter_esc);
+ show_modal("Configure Track", track.config.build_form(), {
+ "Cancel": cancel_fn,
+ "OK": ok_fn
+ });
+ });
+
+ this.overview_icon.click( function() {
+ track.view.set_overview(track);
+ });
+
+ this.filters_icon.click( function() {
+ // TODO: update tipsy text.
+ track.filters_div.toggle();
+ track.filters_manager.reset_filters();
+ });
+
+ this.tools_icon.click( function() {
+ // TODO: update tipsy text.
+
+ track.dynamic_tool_div.toggle();
+
+ // Update track name.
+ if (track.dynamic_tool_div.is(":visible")) {
+ track.set_name(track.name + track.tool_region_and_parameters_str());
+ }
+ else {
+ track.revert_name();
+ }
+ // HACK: name change modifies icon placement, which leaves tooltip incorrectly placed.
+ $(".tipsy").remove();
+ });
+
+ // Clicking on remove icon removes track.
+ this.remove_icon.click( function() {
+ // Tipsy for remove icon must be deleted when track is deleted.
+ $(".tipsy").remove();
+ track.remove();
+ });
+
+ // Set up behavior for modes popup.
+ if (track.display_modes !== undefined) {
+ if (track.mode_div === undefined) {
+ track.mode_div = $("<div class='right-float menubutton popup' />").appendTo(track.header_div);
+ var init_mode = (track.config && track.config.values['mode'] ?
+ track.config.values['mode'] : track.display_modes[0]);
+ track.mode = init_mode;
+ track.mode_div.text(init_mode);
+
+ var mode_mapping = {};
+ for (var i = 0, len = track.display_modes.length; i < len; i++) {
+ var mode = track.display_modes[i];
+ mode_mapping[mode] = function(mode) {
+ return function() { track.change_mode(mode); };
+ }(mode);
+ }
+ make_popupmenu(track.mode_div, mode_mapping);
+ } else {
+ track.mode_div.hide();
+ }
+
+ this.header_div.append( $("<div/>").css("clear", "both") );
+
+ // Set up config icon.
+
+ // Show icons when users is hovering over track.
+ this.container_div.hover( function() { track.icons_div.show(); }, function() { track.icons_div.hide(); } );
+ }
}
//
@@ -2352,7 +2534,7 @@
} else if (result['status'] === "data") {
if (result['valid_chroms']) {
track.valid_chroms = result['valid_chroms'];
- track.make_name_popup_menu();
+ track.update_track_icons();
}
track.content_div.text(DATA_OK);
if (track.view.chrom) {
@@ -2367,14 +2549,18 @@
}
}
});
+
+ this.update_track_icons();
},
/**
* Additional initialization required before drawing track for the first time.
*/
- predraw_init: function() {},
+ predraw_init: function() {}
});
-var TiledTrack = function(filters_list, tool_dict) {
+var TiledTrack = function(name, view, container, show_header, prefs, filters_list, tool_dict, data_url, data_query_wait) {
+ Track.call(this, name, view, container, show_header, prefs, data_url, data_query_wait);
+
var track = this,
view = track.view;
@@ -2387,54 +2573,33 @@
this.filters_available = false;
this.filters_visible = false;
this.tool = (tool_dict !== undefined && obj_length(tool_dict) > 0 ? new Tool(this, tool_dict) : undefined);
- this.is_overview = false;
- if (track.hidden) { return; }
+ if (this.header_div) {
+ //
+ // Create filters div.
+ //
+ if (this.filters_manager) {
+ this.filters_div = this.filters_manager.parent_div
+ this.header_div.after(this.filters_div);
+ }
- //
- // Create filters div.
- //
- if (this.filters_manager) {
- this.filters_div = this.filters_manager.parent_div
- this.header_div.after(this.filters_div);
- }
-
- //
- // Create dynamic tool div.
- //
- if (this.tool) {
- this.dynamic_tool_div = this.tool.parent_div;
- this.header_div.after(this.dynamic_tool_div);
- }
-
- //
- // Create modes control.
- //
- if (track.display_modes !== undefined) {
- if (track.mode_div === undefined) {
- track.mode_div = $("<div class='right-float menubutton popup' />").appendTo(track.header_div);
- var init_mode = (track.config && track.config.values['mode'] ?
- track.config.values['mode'] : track.display_modes[0]);
- track.mode = init_mode;
- track.mode_div.text(init_mode);
-
- var mode_mapping = {};
- for (var i = 0, len = track.display_modes.length; i < len; i++) {
- var mode = track.display_modes[i];
- mode_mapping[mode] = function(mode) {
- return function() { track.change_mode(mode); };
- }(mode);
- }
- make_popupmenu(track.mode_div, mode_mapping);
- } else {
- track.mode_div.hide();
+ //
+ // Create dynamic tool div.
+ //
+ if (this.tool) {
+ this.dynamic_tool_div = this.tool.parent_div;
+ this.header_div.after(this.dynamic_tool_div);
}
}
-
- this.make_name_popup_menu();
};
extend(TiledTrack.prototype, Drawable.prototype, Track.prototype, {
/**
+ * Returns a copy of the track.
+ */
+ copy: function(container) {
+ return new this.constructor(this.name, this.view, container, this.hda_ldda, this.dataset_id, this.prefs, this.filters, this.tool);
+ },
+ /**
* Convert track to JSON object.
*/
to_json: function() {
@@ -2461,87 +2626,31 @@
return track;
},
/**
- * Make popup menu for track name.
+ * Update track's buttons.
*/
- make_name_popup_menu: function() {
+ update_track_icons: function() {
var track = this;
- var track_dropdown = {};
-
//
- // Make track overview option.
- //
- track_dropdown[(this.is_overview ? "Hide overview" : "Set as overview")] = function() {
- if (track.is_overview) {
- track.view.reset_overview();
- }
- else {
- track.view.set_overview(track);
- }
- };
-
- //
- // Edit config option.
- //
- track_dropdown["Edit configuration"] = function() {
- var cancel_fn = function() { hide_modal(); $(window).unbind("keypress.check_enter_esc"); },
- ok_fn = function() {
- track.config.update_from_form( $(".dialog-box") );
- hide_modal();
- $(window).unbind("keypress.check_enter_esc");
- },
- check_enter_esc = function(e) {
- if ((e.keyCode || e.which) === 27) { // Escape key
- cancel_fn();
- } else if ((e.keyCode || e.which) === 13) { // Enter key
- ok_fn();
- }
- };
-
- $(window).bind("keypress.check_enter_esc", check_enter_esc);
- show_modal("Configure Track", track.config.build_form(), {
- "Cancel": cancel_fn,
- "OK": ok_fn
- });
- };
-
- //
- // Show/hide filters option.
+ // Show/hide filter icon.
//
if (track.filters_available > 0) {
- // Show/hide filters menu item.
- var text = (track.filters_div.is(":visible") ? "Hide filters" : "Show filters");
- track_dropdown[text] = function() {
- // Toggle filtering div, reset filters, and remake menu.
- track.filters_visible = (track.filters_div.is(":visible"));
- if (track.filters_visible) {
- track.filters_manager.reset_filters();
- }
- track.filters_div.toggle();
- track.make_name_popup_menu();
- };
+ track.filters_icon.show();
+ }
+ else {
+ track.filters_icon.hide();
}
//
- // Show/hide tool option.
+ // Show/hide tool icon.
//
if (track.tool) {
- // Show/hide dynamic tool menu item.
- var text = (track.dynamic_tool_div.is(":visible") ? "Hide tool" : "Show tool");
- track_dropdown[text] = function() {
- // Set track name, toggle tool div, and remake menu.
- if (!track.dynamic_tool_div.is(":visible")) {
- track.set_name(track.name + track.tool_region_and_parameters_str());
- }
- else {
- menu_option_text = "Show dynamic tool";
- track.revert_name();
- }
- track.dynamic_tool_div.toggle();
- track.make_name_popup_menu();
- };
+ track.tools_icon.show();
}
-
+ else {
+ track.tools_icon.hide();
+ }
+
//
// List chrom/contigs with data option.
//
@@ -2552,61 +2661,6 @@
};
}
*/
-
- //
- // Remove option.
- //
- track_dropdown.Remove = function() {
- track.remove();
- };
-
- make_popupmenu(track.name_div, track_dropdown);
- },
- /**
- * Set track's overview status.
- */
- set_is_overview: function(is_overview) {
- this.is_overview = is_overview;
- this.make_name_popup_menu();
- },
- /**
- * Returns a jQuery Deferred object that resolves to a Tile with track's overview.
- * TODO: this should be the approach used when drawing any tile so that tile drawing is not blocking.
- */
- get_overview_tile: function() {
- var
- track = this;
- view = track.view,
- resolution = Math.pow(RESOLUTION, Math.ceil( Math.log( (view.max_high - view.max_low) / DENSITY ) / Math.log(RESOLUTION) )),
- view_width = view.container.width(),
- // w_scale units are pixels per base.
- w_scale = view_width / (view.max_high - view.max_low),
- overview_tile = $.Deferred();
- $.when(track.data_manager.get_data(view.max_low, view.max_high, "Auto", resolution, track.data_url_extra_params)).then(function(overview_data) {
- var
- key = track._gen_tile_cache_key(view_width, w_scale, 0),
- tile = track.tile_cache.get(key);
-
- // Draw tile if necessary.
- if (!tile) {
- tile = track.draw_tile(overview_data, "Auto", resolution, 0, w_scale);
- track.tile_cache.set(key, tile);
- }
-
- // Always copy tile because it may need to be used in viz.
- var
- src_canvas = $(tile.canvas.find("canvas")),
- new_canvas = src_canvas.clone(),
- src_ctx = src_canvas.get(0).getContext("2d"),
- tgt_ctx = new_canvas.get(0).getContext("2d"),
- data = src_ctx.getImageData(0, 0, src_ctx.canvas.width, src_ctx.canvas.height);
- // Need to undo offsets when placing image data.
- tgt_ctx.putImageData(data, -track.left_offset, (tile.data.dataset_type === "summary_tree" ? SUMMARY_TREE_TOP_PADDING : 0));
- new_tile = new Tile(track, -1, resolution, new_canvas);
- overview_tile.resolve(new_tile);
- });
-
- return overview_tile;
},
/**
* Generate a key for the tile cache.
@@ -2641,6 +2695,14 @@
w_scale = width / range,
resolution = this.view.resolution,
parent_element = $("<div style='position: relative;'></div>");
+
+ // For overview, adjust high, low, resolution, and w_scale.
+ if (this.is_overview) {
+ low = this.view.max_low;
+ high = this.view.max_high;
+ resolution = Math.pow(RESOLUTION, Math.ceil( Math.log( (view.max_high - view.max_low) / DENSITY ) / Math.log(RESOLUTION) ));
+ w_scale = width / (view.max_high - view.max_low);
+ }
if (!clear_after) { this.content_div.children().remove(); }
this.content_div.append( parent_element );
@@ -2751,7 +2813,7 @@
// Can't draw now, so trigger another redraw when the data is ready
$.when( tile_data, seq_data ).then( function() {
- view.request_redraw();
+ view.request_redraw(false, false, false, track);
});
// Indicate to caller that this tile could not be drawn
@@ -2811,8 +2873,7 @@
tile.predisplay_actions();
// Position tile element, recalculate left position at display time
- var range = this.view.high - this.view.low,
- left = (tile.low - this.view.low) * w_scale;
+ var left = ( tile.low - (this.is_overview? this.view.max_low : this.view.low) ) * w_scale;
if (this.left_offset) {
left -= this.left_offset;
}
@@ -2849,8 +2910,7 @@
});
var LabelTrack = function (view, container) {
- this.hidden = true;
- Track.call(this, "label", view, container, {} );
+ Track.call(this, "label", view, container, false, {} );
this.container_div.addClass( "label-track" );
};
extend(LabelTrack.prototype, Track.prototype, {
@@ -2880,9 +2940,7 @@
});
var ReferenceTrack = function (view) {
- this.hidden = true;
- Track.call(this, "reference", view, { content_div: view.top_labeltrack }, {});
- TiledTrack.call(this);
+ TiledTrack.call(this, "reference", view, { content_div: view.top_labeltrack }, false, {});
view.reference_track = this;
this.left_offset = 200;
@@ -2909,7 +2967,7 @@
tile_length = DENSITY * resolution;
if (w_scale > this.view.canvas_manager.char_width_px) {
- if (seq === null) {
+ if (seq.data === null) {
track.content_div.css("height", "0px");
return;
}
@@ -2934,8 +2992,7 @@
var track = this;
this.display_modes = ["Histogram", "Line", "Filled", "Intensity"];
this.mode = "Histogram";
- Track.call( this, name, view, container, prefs );
- TiledTrack.call( this );
+ TiledTrack.call( this, name, view, container, true, prefs );
this.min_height_px = 16;
this.max_height_px = 400;
@@ -2952,7 +3009,7 @@
track: this,
params: [
{ key: 'name', label: 'Name', type: 'text', default_value: name },
- { key: 'color', label: 'Color', type: 'color', default_value: 'black' },
+ { key: 'color', label: 'Color', type: 'color', default_value: 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 },
@@ -3080,18 +3137,15 @@
//
// Initialization.
- //
-
- // FIXME: cleaner init needed; should just be able to call TiledTrack()
- Track.call(this, name, view, container, prefs);
- TiledTrack.call(this, filters, tool);
+ //
+ TiledTrack.call(this, name, view, container, true, prefs, filters, tool);
// Define and restore track configuration.
this.config = new DrawableConfig( {
track: this,
params: [
{ key: 'name', label: 'Name', type: 'text', default_value: name },
- { key: 'block_color', label: 'Block color', type: 'color', default_value: '#444' },
+ { key: 'block_color', label: 'Block color', type: 'color', default_value: get_random_color() },
{ key: 'label_color', label: 'Label color', type: 'color', default_value: 'black' },
{ key: 'show_counts', label: 'Show summary counts', type: 'bool', default_value: true },
{ key: 'mode', type: 'string', default_value: this.mode, hidden: true },
@@ -3203,7 +3257,7 @@
if (!track.filters_available) {
track.filters_div.hide();
}
- track.make_name_popup_menu();
+ track.update_track_icons();
}
}
},
@@ -3345,9 +3399,12 @@
if (mode === "Auto") {
if (result.dataset_type === "summary_tree") {
mode = result.dataset_type;
- } else if (result.extra_info === "no_detail") {
+ }
+ // HACK: use no_detail mode track is in overview to prevent overview from being too large.
+ else if (result.extra_info === "no_detail" || track.is_overview) {
mode = "no_detail";
- } else {
+ }
+ else {
// Choose b/t Squish and Pack.
// Proxy measures for using Squish:
// (a) error message re: limiting number of features shown;
@@ -3478,7 +3535,7 @@
track: this,
params: [
{ key: 'name', label: 'Name', type: 'text', default_value: name },
- { key: 'block_color', label: 'Block color', type: 'color', default_value: '#444' },
+ { key: 'block_color', label: 'Block color', type: 'color', default_value: 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_differences', label: 'Show differences only', type: 'bool', default_value: true },
@@ -3495,7 +3552,7 @@
this.prefs = this.config.values;
this.painter = painters.ReadPainter;
- this.make_name_popup_menu();
+ this.update_track_icons();
};
extend(ReadTrack.prototype, Drawable.prototype, TiledTrack.prototype, FeatureTrack.prototype);
diff -r 603924d3abc3057def82337b53178ad48a71b1d1 -r 125d735c689ee60ad9bd9601c7a22738ba3523de static/scripts/trackster_ui.js
--- a/static/scripts/trackster_ui.js
+++ b/static/scripts/trackster_ui.js
@@ -114,7 +114,7 @@
// Set overview.
var overview_track;
for (var i = 0; i < view.drawables.length; i++) {
- if (view.drawables[i].name == overview_track_name) {
+ if (view.drawables[i].name === overview_track_name) {
view.set_overview(view.drawables[i]);
break;
}
diff -r 603924d3abc3057def82337b53178ad48a71b1d1 -r 125d735c689ee60ad9bd9601c7a22738ba3523de templates/tracks/browser.mako
--- a/templates/tracks/browser.mako
+++ b/templates/tracks/browser.mako
@@ -42,10 +42,9 @@
<script type='text/javascript' src="${h.url_for('/static/scripts/excanvas.js')}"></script><![endif]-->
-${h.js( "galaxy.base", "galaxy.panels", "json2", "jquery", "jstorage", "jquery.event.drag", "jquery.mousewheel", "jquery.autocomplete", "trackster", "trackster_ui", "jquery.ui.sortable.slider", "jquery.scrollTo", "farbtastic" )}
+${h.js( "galaxy.base", "galaxy.panels", "json2", "jquery", "jstorage", "jquery.event.drag", "jquery.mousewheel", "jquery.autocomplete", "trackster", "trackster_ui", "jquery.ui.sortable.slider", "jquery.scrollTo", "farbtastic", "jquery.tipsy" )}
<script type="text/javascript">
-
//
// Place URLs here so that url_for can be used to generate them.
//
@@ -113,6 +112,9 @@
};
$(function() {
+ // Manual tipsy config because default gravity is S and cannot be changed.
+ $(".menu-button").tipsy( {gravity: 'n'} );
+
// Hide bookmarks by default right now.
parent.force_right_panel("hide");
@@ -172,59 +174,62 @@
%endif
//
- // Make actions menu.
+ // Initialize icons.
//
- $("#viz-actions-button").css( "position", "relative" );
- make_popupmenu( $("#viz-actions-button"), {
- "Add Tracks": add_tracks,
- "Add Group": function() {
- var group = new DrawableGroup("New Group", view, view);
- view.add_drawable(group);
- },
- "Save": function() {
- // Show saving dialog box
- show_modal("Saving...", "<img src='${h.url_for('/static/images/yui/rel_interstitial_loading.gif')}'/>");
-
- // Save bookmarks.
- var bookmarks = [];
- $(".bookmark").each(function() {
- bookmarks[bookmarks.length] = {
- position: $(this).children(".position").text(),
- annotation: $(this).children(".annotation").text()
- };
- });
-
- var overview_track_name = (view.overview_track ? view.overview_track.name : null);
- var payload = {
- 'view': view.to_json(),
- 'viewport': { 'chrom': view.chrom, 'start': view.low , 'end': view.high, 'overview': overview_track_name },
- 'bookmarks': bookmarks
- };
-
- $.ajax({
- url: "${h.url_for( action='save' )}",
- type: "POST",
- data: {
- 'vis_id': view.vis_id,
- 'vis_title': view.title,
- 'dbkey': view.dbkey,
- 'payload': JSON.stringify(payload)
- },
- success: function(vis_id) {
- view.vis_id = vis_id;
- view.has_changes = false;
- hide_modal();
- },
- error: function() { alert("Could not save visualization"); }
- });
- },
- "Bookmarks": function() {
- // HACK -- use style to determine if panel is hidden and hide/show accordingly.
- parent.force_right_panel(($("div#right").css("right") == "0px" ? "hide" : "show"));
- },
- "Close": function() { window.location = "${h.url_for( controller='visualization', action='list' )}"; }
+ $("#add-tracks-icon").click( function() { add_tracks(); } );
+
+ $("#add-group-icon").click( function() {
+ view.add_drawable( new DrawableGroup("New Group", view, view) );
});
+ $("#save-icon").click( function() {
+ // Show saving dialog box
+ show_modal("Saving...", "<img src='${h.url_for('/static/images/yui/rel_interstitial_loading.gif')}'/>");
+
+ // Save bookmarks.
+ var bookmarks = [];
+ $(".bookmark").each(function() {
+ bookmarks[bookmarks.length] = {
+ position: $(this).children(".position").text(),
+ annotation: $(this).children(".annotation").text()
+ };
+ });
+
+ // FIXME: give unique IDs to Drawables and save overview as ID.
+ var overview_track_name = (view.overview_drawable ? view.overview_drawable.name : null);
+ var payload = {
+ 'view': view.to_json(),
+ 'viewport': { 'chrom': view.chrom, 'start': view.low , 'end': view.high, 'overview': overview_track_name },
+ 'bookmarks': bookmarks
+ };
+
+ $.ajax({
+ url: "${h.url_for( action='save' )}",
+ type: "POST",
+ data: {
+ 'vis_id': view.vis_id,
+ 'vis_title': view.title,
+ 'dbkey': view.dbkey,
+ 'payload': JSON.stringify(payload)
+ },
+ success: function(vis_id) {
+ view.vis_id = vis_id;
+ view.has_changes = false;
+ hide_modal();
+ },
+ error: function() { alert("Could not save visualization"); }
+ });
+ });
+
+ $("#bookmarks-icon").click( function() {
+ // HACK -- use style to determine if panel is hidden and hide/show accordingly.
+ parent.force_right_panel(($("div#right").css("right") == "0px" ? "hide" : "show"));
+ });
+
+ $("#close-icon").click( function() {
+ window.location = "${h.url_for( controller='visualization', action='list' )}";
+ });
+
$("#add-bookmark-button").click(function() {
// Add new bookmark.
var position = view.chrom + ":" + view.low + "-" + view.high,
@@ -245,9 +250,14 @@
<div class="unified-panel-header-inner"><div style="float:left;" id="title"></div><div style="float: right">
- <a id="viz-actions-button" class='panel-header-button popup' href="javascript:void(0)" target="galaxy_main">${_('Actions')}</a>
+ <a id="add-tracks-icon" class='icon-button menu-button' href="javascript:void(0);" title="Add tracks"></a>
+ <a id="add-group-icon" class='icon-button menu-button' href="javascript:void(0);" title="Add new group"></a>
+ <a id="bookmarks-icon" class='icon-button menu-button' href="javascript:void(0);" title="Bookmarks"></a>
+ <a id="save-icon" class='icon-button menu-button' href="javascript:void(0);" title="Save"></a>
+ <a id="close-icon" class='icon-button menu-button' href="javascript:void(0);" title="Close"></a></div></div>
+ <div style="clear: both"></div></div><div id="browser-container" class="unified-panel-body"></div>
diff -r 603924d3abc3057def82337b53178ad48a71b1d1 -r 125d735c689ee60ad9bd9601c7a22738ba3523de test-data/picard_fastq_to_sam_out1.bam
Binary file test-data/picard_fastq_to_sam_out1.bam has changed
diff -r 603924d3abc3057def82337b53178ad48a71b1d1 -r 125d735c689ee60ad9bd9601c7a22738ba3523de test-data/picard_fastq_to_sam_out2.bam
Binary file test-data/picard_fastq_to_sam_out2.bam has changed
diff -r 603924d3abc3057def82337b53178ad48a71b1d1 -r 125d735c689ee60ad9bd9601c7a22738ba3523de tool_conf.xml.sample
--- a/tool_conf.xml.sample
+++ b/tool_conf.xml.sample
@@ -295,6 +295,9 @@
<tool file="fastx_toolkit/fastx_trimmer.xml" /></section><section name="NGS: Picard (beta)" id="picard_beta">
+ <label text="Conversion" id="picard_conversion"/>
+ <tool file="picard/picard_FastqToSam.xml" />
+ <tool file="picard/picard_SamToFastq.xml" /><label text="QC/Metrics for sam/bam" id="qcsambam"/><tool file="picard/picard_BamIndexStats.xml" />
@@ -390,7 +393,6 @@
<label text="Filtration" id="gatk_filtration" /><tool file="gatk/variant_filtration.xml" />
- <tool file="gatk/variant_filtration.xml" /><label text="Variant Quality Score Recalibration" id="gatk_variant_quality_score_recalibration" /><tool file="gatk/variant_recalibrator.xml" />
diff -r 603924d3abc3057def82337b53178ad48a71b1d1 -r 125d735c689ee60ad9bd9601c7a22738ba3523de tools/fastq/fastq_paired_end_deinterlacer.py
--- a/tools/fastq/fastq_paired_end_deinterlacer.py
+++ b/tools/fastq/fastq_paired_end_deinterlacer.py
@@ -21,12 +21,14 @@
i = None
skip_count = 0
found = {}
- for i, mate1 in enumerate( fastqReader( open( input_filename, 'rb' ), format = type ) ):
+ for i, read in enumerate( fastqReader( open( input_filename, 'rb' ), format = type ) ):
- if mate1.identifier in found:
- del found[mate1.identifier]
+ if read.identifier in found:
+ del found[read.identifier]
continue
+ mate1 = input.get( read.identifier )
+
mate2 = input.get( joiner.get_paired_identifier( mate1 ) )
if mate2:
diff -r 603924d3abc3057def82337b53178ad48a71b1d1 -r 125d735c689ee60ad9bd9601c7a22738ba3523de tools/gatk/variant_apply_recalibration.xml
--- a/tools/gatk/variant_apply_recalibration.xml
+++ b/tools/gatk/variant_apply_recalibration.xml
@@ -102,9 +102,9 @@
<param name="input_recal" type="data" format="gatk_recal" label="Variant Recalibration file" /><param name="input_tranches" type="data" format="gatk_tranche" label="Variant Tranches file" /><param name="ref_file" type="select" label="Using reference genome">
- <!-- <options from_data_table="picard_indexes">
- <filter type="data_meta" key="dbkey" ref="variants[0].input_variants" column="dbkey"/>
- </options> -->
+ <options from_data_table="picard_indexes">
+ <!-- <filter type="data_meta" key="dbkey" ref="variants[0].input_variants" column="dbkey"/> -->
+ </options></param></when><when value="history"><!-- FIX ME!!!! -->
diff -r 603924d3abc3057def82337b53178ad48a71b1d1 -r 125d735c689ee60ad9bd9601c7a22738ba3523de tools/gatk/variant_eval.xml
--- a/tools/gatk/variant_eval.xml
+++ b/tools/gatk/variant_eval.xml
@@ -159,9 +159,9 @@
<param name="input_variant" type="data" format="vcf" label="Input variant file" /></repeat><param name="ref_file" type="select" label="Using reference genome">
- <!--<options from_data_table="picard_indexes">
- <filter type="data_meta" key="dbkey" ref="input_variant" column="dbkey"/>
- </options>-->
+ <options from_data_table="picard_indexes">
+ <!-- <filter type="data_meta" key="dbkey" ref="input_variant" column="dbkey"/> -->
+ </options></param></when><when value="history"><!-- FIX ME!!!! -->
diff -r 603924d3abc3057def82337b53178ad48a71b1d1 -r 125d735c689ee60ad9bd9601c7a22738ba3523de tools/gatk/variant_recalibrator.xml
--- a/tools/gatk/variant_recalibrator.xml
+++ b/tools/gatk/variant_recalibrator.xml
@@ -152,9 +152,9 @@
<param name="input_variants" type="data" format="vcf" label="Variant file to recalibrate" /></repeat><param name="ref_file" type="select" label="Using reference genome">
- <!-- <options from_data_table="picard_indexes">
- <filter type="data_meta" key="dbkey" ref="variants[0].input_variants" column="dbkey"/>
- </options> -->
+ <options from_data_table="picard_indexes">
+ <!-- <filter type="data_meta" key="dbkey" ref="variants[0].input_variants" column="dbkey"/> -->
+ </options></param></when><when value="history"><!-- FIX ME!!!! -->
diff -r 603924d3abc3057def82337b53178ad48a71b1d1 -r 125d735c689ee60ad9bd9601c7a22738ba3523de tools/picard/picard_AddOrReplaceReadGroups.xml
--- a/tools/picard/picard_AddOrReplaceReadGroups.xml
+++ b/tools/picard/picard_AddOrReplaceReadGroups.xml
@@ -1,4 +1,4 @@
-<tool name="Add or Replace Groups" id="picard_ARRG" version="0.2.0">
+<tool name="Add or Replace Groups" id="picard_ARRG" version="0.2.1"><requirements><requirement type="package">picard</requirement></requirements><command interpreter="python">
picard_wrapper.py
@@ -15,7 +15,7 @@
#end if
--output-format=$outputFormat
--output=$outFile
- -j "${GALAXY_DATA_INDEX_DIR}/shared/jars/AddOrReplaceReadGroups.jar"
+ -j "${GALAXY_DATA_INDEX_DIR}/shared/jars/picard/AddOrReplaceReadGroups.jar"
</command><inputs><param format="bam,sam" name="inputFile" type="data" label="SAM/BAM dataset to add or replace read groups in"
diff -r 603924d3abc3057def82337b53178ad48a71b1d1 -r 125d735c689ee60ad9bd9601c7a22738ba3523de tools/picard/picard_BamIndexStats.xml
--- a/tools/picard/picard_BamIndexStats.xml
+++ b/tools/picard/picard_BamIndexStats.xml
@@ -1,4 +1,4 @@
-<tool name="BAM Index Statistics" id="picard_BamIndexStats" version="0.2.0">
+<tool name="BAM Index Statistics" id="picard_BamIndexStats" version="0.2.1"><requirements><requirement type="package">picard</requirement></requirements><command interpreter="python">
picard_wrapper.py
@@ -6,7 +6,7 @@
--bai-file "$input_file.metadata.bam_index"
-t "$htmlfile"
-d "$htmlfile.files_path"
- -j "${GALAXY_DATA_INDEX_DIR}/shared/jars/BamIndexStats.jar"
+ -j "${GALAXY_DATA_INDEX_DIR}/shared/jars/picard/BamIndexStats.jar"
</command><inputs><param format="bam" name="input_file" type="data" label="BAM dataset to generate statistics for"
diff -r 603924d3abc3057def82337b53178ad48a71b1d1 -r 125d735c689ee60ad9bd9601c7a22738ba3523de tools/picard/picard_FastqToSam.xml
--- /dev/null
+++ b/tools/picard/picard_FastqToSam.xml
@@ -0,0 +1,144 @@
+<tool id="picard_FastqToSam" name="FASTQ to BAM" version="0.0.1">
+ <description>creates an unaligned BAM file</description>
+ <requirements><requirement type="package">picard</requirement></requirements>
+ <command>java -XX:DefaultMaxRAMFraction=1 -XX:+UseParallelGC
+ -jar "${GALAXY_DATA_INDEX_DIR}/shared/jars/picard/FastqToSam.jar"
+ FASTQ="${input_fastq1}"
+ #if str( $input_fastq2) != "None":
+ FASTQ2="${input_fastq2}"
+ #end if
+ QUALITY_FORMAT="${ dict( fastqsanger='Standard', fastqcssanger='Standard', fastqillumina='Illumina', fastqsolexa='Solexa' )[ $input_fastq1.ext ] }" ##Solexa, Illumina, Standard
+ OUTPUT="${output_bam}"
+ READ_GROUP_NAME="${read_group_name}"
+ SAMPLE_NAME="${sample_name}"
+ #if $param_type.param_type_selector == "advanced":
+ #if str( $param_type.library_name ) != "":
+ LIBRARY_NAME="${param_type.library_name}"
+ #end if
+ #if str( $param_type.platform_unit ) != "":
+ PLATFORM_UNIT="${param_type.platform_unit}"
+ #end if
+ #if str( $param_type.platform ) != "":
+ PLATFORM="${param_type.platform}"
+ #end if
+ #if str( $param_type.sequencing_center ) != "":
+ SEQUENCING_CENTER="${param_type.sequencing_center}"
+ #end if
+ #if str( $param_type.predicted_insert_size ) != "":
+ PREDICTED_INSERT_SIZE="${param_type.predicted_insert_size}"
+ #end if
+ #if str( $param_type.description.value ) != "":
+ DESCRIPTION="${param_type.description}"
+ #end if
+ #if str( $param_type.run_date ) != "":
+ RUN_DATE="${param_type.run_date}"
+ #end if
+ #if str( $param_type.min_q ) != "":
+ MIN_Q="${param_type.min_q}"
+ #end if
+ #if str( $param_type.min_q ) != "":
+ MAX_Q="${param_type.max_q}"
+ #end if
+ SORT_ORDER="${param_type.sort_order}"
+ #else:
+ SORT_ORDER=coordinate ##unsorted, queryname, coordinate; always use coordinate
+ #end if
+ 2>&1
+ || echo "Error running Picard FastqToSAM" >&2
+ </command>
+ <inputs>
+ <param name="input_fastq1" type="data" format="fastqsanger,fastqillumina,fastqsolexa,fastqcssanger" label="FASTQ file" /><!-- confirm that fastqcssanger also works -->
+ <param name="input_fastq2" type="data" format="fastqsanger,fastqillumina,fastqsolexa,fastqcssanger" optional="True" label="Second FASTQ of paired end data" help="Only needed when using paired end data." >
+ <options options_filter_attribute="ext" from_parameter="tool.app.datatypes_registry.datatypes_by_extension" transform_lines="obj.keys()">
+ <column name="name" index="0"/>
+ <column name="value" index="0"/>
+ <filter type="param_value" ref="input_fastq1" ref_attribute="ext" column="0"/>
+ </options>
+ </param>
+ <param name="read_group_name" type="text" value="A" label="Read Group Name" />
+ <param name="sample_name" type="text" value="unknown sample" label="Sample Name" />
+ <conditional name="param_type">
+ <param name="param_type_selector" type="select" label="Basic or Advanced options">
+ <option value="basic" selected="True">Basic</option>
+ <option value="advanced">Advanced</option>
+ </param>
+ <when value="basic">
+ <!-- Do nothing here -->
+ </when>
+ <when value="advanced">
+ <param name="library_name" type="text" value="" label="Library Name" />
+ <param name="platform_unit" type="text" value="" label="Platform Unit" />
+ <param name="platform" type="text" value="" label="Platform" />
+ <param name="sequencing_center" type="text" value="" label="Sequencing Center" />
+ <param name="predicted_insert_size" type="integer" value="" optional="True" label="Predicted Insert Size" />
+ <param name="description" type="text" value="" label="Description" />
+ <param name="run_date" type="text" value="" label="Run Date" />
+ <param name="min_q" type="integer" optional="True" value="0" label="Min Q" />
+ <param name="max_q" type="integer" optional="True" value="93" label="Max Q" />
+ <param name="sort_order" type="select" label="Sort order">
+ <option value="coordinate" selected="True">coordinate</option>
+ <option value="queryname">queryname</option>
+ <option value="unsorted">unsorted</option>
+ </param>
+ </when>
+ </conditional>
+ </inputs>
+ <outputs>
+ <data format="bam" name="output_bam" />
+ </outputs>
+ <tests>
+ <test>
+ <param name="input_fastq1" value="bwa_wrapper_in2.fastqsanger" ftype="fastqsanger" />
+ <param name="input_fastq2" />
+ <param name="read_group_name" value="A" />
+ <param name="sample_name" value="unknown sample" />
+ <param name="param_type_selector" value="basic" />
+ <output name="output_bam" file="picard_fastq_to_sam_out1.bam" ftype="bam"/>
+ </test>
+ <test>
+ <param name="input_fastq1" value="bwa_wrapper_in2.fastqsanger" ftype="fastqsanger" />
+ <param name="input_fastq2" value="bwa_wrapper_in3.fastqsanger" ftype="fastqsanger" />
+ <param name="read_group_name" value="A" />
+ <param name="sample_name" value="unknown sample" />
+ <param name="param_type_selector" value="basic" />
+ <output name="output_bam" file="picard_fastq_to_sam_out2.bam" ftype="bam"/>
+ </test>
+ </tests>
+ <help>
+**What it does**
+
+Picard: FastqToSam converts FASTQ files to unaligned BAM files.
+
+------
+
+Please cite the website "http://picard.sourceforge.net".
+
+------
+
+
+**Input formats**
+
+FastqToSam accepts FASTQ input files. If using paired-end data, you should select two FASTQ files.
+
+------
+
+**Outputs**
+
+The output is in BAM format, see http://samtools.sourceforge.net for more details.
+
+-------
+
+**FastqToSam settings**
+
+This is list of FastqToSam options::
+
+ READ_GROUP_NAME=String Read group name Default value: A. This option can be set to 'null' to clear the default value.
+ SAMPLE_NAME=String Sample name to insert into the read group header Required.
+ LIBRARY_NAME=String The library name to place into the LB attribute in the read group header Default value: null.
+ PLATFORM_UNIT=String The platform unit (often run_barcode.lane) to insert into the read group header Default value: null.
+ PLATFORM=String The platform type (e.g. illumina, solid) to insert into the read group header Default value: null.
+ SEQUENCING_CENTER=String The sequencing center from which the data originated Default value: null.
+ PREDICTED_INSERT_SIZE=Integer Predicted median insert size, to insert into the read group header Default value: null.
+ DESCRIPTION=String Inserted into the read group header Default value: null.
+ </help>
+</tool>
diff -r 603924d3abc3057def82337b53178ad48a71b1d1 -r 125d735c689ee60ad9bd9601c7a22738ba3523de tools/picard/picard_MarkDuplicates.xml
--- a/tools/picard/picard_MarkDuplicates.xml
+++ b/tools/picard/picard_MarkDuplicates.xml
@@ -1,4 +1,4 @@
-<tool name="Mark Duplicates" id="picard_MarkDuplicates" version="0.01">
+<tool name="Mark Duplicates" id="picard_MarkDuplicates" version="0.01.1"><command interpreter="python">
picard_wrapper.py
--input="$input_file"
@@ -20,7 +20,7 @@
--output-sam=$outFileBamMarked
#end if
#end if
- -j "${GALAXY_DATA_INDEX_DIR}/shared/jars/"
+ -j "${GALAXY_DATA_INDEX_DIR}/shared/jars/picard/"
--picard-cmd="MarkDuplicates"
</command><inputs>
diff -r 603924d3abc3057def82337b53178ad48a71b1d1 -r 125d735c689ee60ad9bd9601c7a22738ba3523de tools/picard/picard_ReorderSam.xml
--- a/tools/picard/picard_ReorderSam.xml
+++ b/tools/picard/picard_ReorderSam.xml
@@ -1,4 +1,4 @@
-<tool name="Reorder SAM/BAM" id="picard_ReorderSam" version="0.3.0">
+<tool name="Reorder SAM/BAM" id="picard_ReorderSam" version="0.3.1"><requirements><requirement type="package">picard</requirement></requirements><command interpreter="python">
picard_wrapper.py
@@ -15,7 +15,7 @@
--allow-contig-len-discord=$allowContigLenDiscord
--output-format=$outputFormat
--output=$outFile
- -j "${GALAXY_DATA_INDEX_DIR}/shared/jars/ReorderSam.jar"
+ -j "${GALAXY_DATA_INDEX_DIR}/shared/jars/picard/ReorderSam.jar"
</command><inputs><param format="bam,sam" name="inputFile" type="data" label="SAM/BAM dataset to be reordered"
diff -r 603924d3abc3057def82337b53178ad48a71b1d1 -r 125d735c689ee60ad9bd9601c7a22738ba3523de tools/picard/picard_ReplaceSamHeader.xml
--- a/tools/picard/picard_ReplaceSamHeader.xml
+++ b/tools/picard/picard_ReplaceSamHeader.xml
@@ -1,4 +1,4 @@
-<tool name="Replace SAM/BAM Header" id="picard_ReplaceSamHeader" version="0.2.0">
+<tool name="Replace SAM/BAM Header" id="picard_ReplaceSamHeader" version="0.2.1"><requirements><requirement type="package">picard</requirement></requirements><command interpreter="python">
picard_wrapper.py
@@ -6,7 +6,7 @@
-o $outFile
--header-file $headerFile
--output-format $outputFormat
- -j "${GALAXY_DATA_INDEX_DIR}/shared/jars/ReplaceSamHeader.jar"
+ -j "${GALAXY_DATA_INDEX_DIR}/shared/jars/picard/ReplaceSamHeader.jar"
--tmpdir "${__new_file_path__}"
</command><inputs>
diff -r 603924d3abc3057def82337b53178ad48a71b1d1 -r 125d735c689ee60ad9bd9601c7a22738ba3523de tools/picard/picard_SamToFastq.xml
--- /dev/null
+++ b/tools/picard/picard_SamToFastq.xml
@@ -0,0 +1,157 @@
+<tool id="picard_SamToFastq" name="SAM to FASTQ" version="0.0.1">
+ <description>creates a FASTQ file</description>
+ <requirements><requirement type="package">picard</requirement></requirements>
+ <command>java -XX:DefaultMaxRAMFraction=1 -XX:+UseParallelGC
+ -jar "${GALAXY_DATA_INDEX_DIR}/shared/jars/picard/SamToFastq.jar"
+ INPUT="${input_sam}"
+ RE_REVERSE=${re_reverse}
+ INCLUDE_NON_PF_READS=${include_non_pf_reads}
+ #if str( $clipping_attribute ):
+ CLIPPING_ATTRIBUTE="${clipping_attribute}"
+ #end if
+ #if str( $clipping_action ):
+ CLIPPING_ACTION="${clipping_action}"
+ #end if
+ #if str( $read1_trim ):
+ READ1_TRIM="${read1_trim}"
+ #end if
+ #if str( $read1_max_bases_to_write ):
+ READ1_MAX_BASES_TO_WRITE="${read1_max_bases_to_write}"
+ #end if
+ INCLUDE_NON_PRIMARY_ALIGNMENTS=${include_non_primary_alignments}
+
+ #if str( $output_per_read_group_selector ) == 'per_sam_file':
+ ##OUTPUT_PER_RG=false
+ FASTQ="${output_fastq1}"
+
+ #if str( $single_paired_end_type.single_paired_end_type_selector ) == 'paired':
+ SECOND_END_FASTQ="${output_fastq2}"
+ #if str( $single_paired_end_type.read2_trim ):
+ READ2_TRIM="${single_paired_end_type.read2_trim}"
+ #end if
+ #if str( $single_paired_end_type.read2_max_bases_to_write ):
+ READ2_MAX_BASES_TO_WRITE="${single_paired_end_type.read2_max_bases_to_write}"
+ #end if
+ #end if
+ #else:
+ #raise Exception( 'Per Read Group not yet supported.' )
+ OUTPUT_PER_RG=true
+ OUTPUT_DIR="./picard_sam_to_fastq_tmp_dir/"
+ #end if
+ 2>&1
+ || echo "Error running SamToFastq" >&2
+ </command>
+ <inputs>
+ <param name="input_sam" type="data" format="sam" label="SAM file" />
+ <param name="read1_trim" type="integer" value="" optional="True" label="The number of bases to trim from the beginning of read 1." />
+ <param name="read1_max_bases_to_write" type="integer" optional="True" value="" label="The maximum number of bases to write from read 1 after trimming." />
+ <param name="output_per_read_group_selector" type="select" label="Output per read group">
+ <option value="per_sam_file" selected="True">Per SAM file</option>
+ <!-- <option value="per_read_group">Per Read Group</option> -->
+ <validator type="expression" message="Per Read Group selection is not yet implemented">value == 'per_sam_file'</validator>
+ </param>
+ <conditional name="single_paired_end_type">
+ <param name="single_paired_end_type_selector" type="select" label="Single or Paired end">
+ <option value="single" selected="True">Single</option>
+ <option value="paired">Paired end</option>
+ </param>
+ <when value="single">
+ <!-- nothing yet -->
+ </when>
+ <when value="paired">
+ <param name="read2_trim" type="integer" value="" optional="True" label="The number of bases to trim from the beginning of read 2." />
+ <param name="read2_max_bases_to_write" type="integer" optional="True" value="" label="The maximum number of bases to write from read 2 after trimming." />
+ </when>
+ </conditional>
+ <param name="re_reverse" type="boolean" truevalue="true" falsevalue="false" checked="True" label="Re-reverse bases and qualities of reads on negative strand"/>
+ <param name="include_non_pf_reads" type="boolean" truevalue="true" falsevalue="false" checked="False" label="Include non-PF reads from the SAM file into the output FASTQ files."/>
+ <param name="clipping_attribute" type="text" value="" label="The attribute that stores the position at which the SAM record should be clipped" help="Leave blank for null" />
+ <param name="clipping_action" type="text" value="" label="The action that should be taken with clipped reads" help="'X' means the reads and qualities should be trimmed at the clipped position; 'N' means the bases should be changed to Ns in the clipped region; and any integer means that the base qualities should be set to that value in the clipped region. Leave blank for null" />
+ <param name="include_non_primary_alignments" type="boolean" truevalue="true" falsevalue="false" checked="False" label="If true, include non-primary alignments in the output." help="Support of non-primary alignments in SamToFastq is not comprehensive, so there may be exceptions if this is set to true and there are paired reads with non-primary alignments."/>
+
+ </inputs>
+ <outputs>
+ <data format="fastqsanger" name="output_fastq1" label="${tool.name} on ${on_string}: FASTQ 1" />
+ <data format="fastqsanger" name="output_fastq2" label="${tool.name} on ${on_string}: FASTQ 2" >
+ <filter>single_paired_end_type['single_paired_end_type_selector'] == 'paired'</filter>
+ </data>
+ </outputs>
+ <tests>
+ <test>
+ <param name="input_sam" value="bfast_out1.sam" ftype="sam" />
+ <param name="output_per_read_group_selector" value="per_sam_file" />
+ <param name="single_paired_end_type_selector" value="single" />
+ <param name="read1_trim" value="" />
+ <param name="read1_max_bases_to_write" value="" />
+ <param name="re_reverse" value="True" />
+ <param name="include_non_pf_reads" value="False" />
+ <param name="clipping_action" value="" />
+ <param name="clipping_attribute" value="" />
+ <param name="include_non_primary_alignments" value="False" />
+ <output name="output_fastq1" file="random_phiX_1.fastqsanger"/>
+ </test>
+ <test>
+ <param name="input_sam" value="bwa_wrapper_out3.sam" ftype="sam" />
+ <param name="output_per_read_group_selector" value="per_sam_file" />
+ <param name="single_paired_end_type_selector" value="paired" />
+ <param name="read1_trim" value="" />
+ <param name="read1_max_bases_to_write" value="" />
+ <param name="read2_trim" value="" />
+ <param name="read2_max_bases_to_write" value="" />
+ <param name="re_reverse" value="True" />
+ <param name="include_non_pf_reads" value="False" />
+ <param name="clipping_action" value="" />
+ <param name="clipping_attribute" value="" />
+ <param name="include_non_primary_alignments" value="False" />
+ <output name="output_fastq1" file="bwa_wrapper_in2.fastqsanger" lines_diff="64"/><!-- 16 unaligned fastq blocks not present in original sam file -->
+ <output name="output_fastq2" file="bwa_wrapper_in3.fastqsanger" lines_diff="64"/><!-- 16 unaligned fastq blocks not present in original sam file -->
+ </test>
+ </tests>
+ <help>
+**What it does**
+
+Picard: SamToFastq converts SAM files to FASTQ files.
+
+Extracts read sequences and qualities from the input SAM/BAM file and writes them into the output file in Sanger fastq format. In the RC mode (default is True), if the read is aligned and the alignment is to the reverse strand on the genome, the read's sequence from input SAM file will be reverse-complemented prior to writing it to fastq in order restore correctly the original read sequence as it was generated by the sequencer.
+
+------
+
+Please cite the website "http://picard.sourceforge.net".
+
+------
+
+
+**Input formats**
+
+FastqToSam accepts SAM input files, see http://samtools.sourceforge.net for more details.
+
+------
+
+**Outputs**
+
+The output is in FASTQ format. If using Paired end data, 2 fastq files are created.
+
+-------
+
+**FastqToSam settings**
+
+This is list of SamToFastq options::
+
+ INPUT=File Input SAM/BAM file to extract reads from Required.
+ FASTQ=File Output fastq file (single-end fastq or, if paired, first end of the pair fastq). Required. Cannot be used in conjuction with option(s) OUTPUT_PER_RG (OPRG)
+ SECOND_END_FASTQ=File Output fastq file (if paired, second end of the pair fastq). Default value: null. Cannot be used in conjuction with option(s) OUTPUT_PER_RG (OPRG)
+ OUTPUT_PER_RG=Boolean Output a fastq file per read group (two fastq files per read group if the group is paired). Default value: false. This option can be set to 'null' to clear the default value. Possible values: {true, false} Cannot be used in conjuction with option(s) SECOND_END_FASTQ (F2) FASTQ (F)
+ OUTPUT_DIR=File Directory in which to output the fastq file(s). Used only when OUTPUT_PER_RG is true. Default value: null.
+ RE_REVERSE=Boolean Re-reverse bases and qualities of reads with negative strand flag set before writing them to fastq Default value: true. This option can be set to 'null' to clear the default value. Possible values: {true, false}
+ INCLUDE_NON_PF_READS=Boolean Include non-PF reads from the SAM file into the output FASTQ files. Default value: false. This option can be set to 'null' to clear the default value. Possible values: {true, false}
+ CLIPPING_ATTRIBUTE=String The attribute that stores the position at which the SAM record should be clipped Default value: null.
+ CLIPPING_ACTION=String The action that should be taken with clipped reads: 'X' means the reads and qualities should be trimmed at the clipped position; 'N' means the bases should be changed to Ns in the clipped region; and any integer means that the base qualities should be set to that value in the clipped region. Default value: null.
+ READ1_TRIM=Integer The number of bases to trim from the beginning of read 1. Default value: 0. This option can be set to 'null' to clear the default value.
+ READ1_MAX_BASES_TO_WRITE=Integer The maximum number of bases to write from read 1 after trimming. If there are fewer than this many bases left after trimming, all will be written. If this value is null then all bases left after trimming will be written. Default value: null.
+ READ2_TRIM=Integer The number of bases to trim from the beginning of read 2. Default value: 0. This option can be set to 'null' to clear the default value.
+ READ2_MAX_BASES_TO_WRITE=Integer The maximum number of bases to write from read 2 after trimming. If there are fewer than this many bases left after trimming, all will be written. If this value is null then all bases left after trimming will be written. Default value: null.
+ INCLUDE_NON_PRIMARY_ALIGNMENTS=Boolean If true, include non-primary alignments in the output. Support of non-primary alignments in SamToFastq is not comprehensive, so there may be exceptions if this is set to true and there are paired reads with non-primary alignments. Default value: false. This option can be set to 'null' to clear the default value. Possible values: {true, false}
+
+
+ </help>
+</tool>
diff -r 603924d3abc3057def82337b53178ad48a71b1d1 -r 125d735c689ee60ad9bd9601c7a22738ba3523de tools/picard/rgPicardASMetrics.xml
--- a/tools/picard/rgPicardASMetrics.xml
+++ b/tools/picard/rgPicardASMetrics.xml
@@ -1,8 +1,8 @@
-<tool name="SAM/BAM Alignment Summary Metrics" id="PicardASMetrics" version="0.03">
+<tool name="SAM/BAM Alignment Summary Metrics" id="PicardASMetrics" version="0.03.1"><command interpreter="python">
picard_wrapper.py -i "$input_file" -d "$html_file.files_path" -t "$html_file"
--assumesorted "$sorted" -b "$bisulphite" --adaptors "$adaptors" --maxinsert "$maxinsert" -n "$out_prefix"
- -j ${GALAXY_DATA_INDEX_DIR}/shared/jars/CollectAlignmentSummaryMetrics.jar
+ -j ${GALAXY_DATA_INDEX_DIR}/shared/jars/picard/CollectAlignmentSummaryMetrics.jar
#if $genomeSource.refGenomeSource == "history":
--ref-file "$genomeSource.ownFile"
#else
diff -r 603924d3abc3057def82337b53178ad48a71b1d1 -r 125d735c689ee60ad9bd9601c7a22738ba3523de tools/picard/rgPicardFixMate.xml
--- a/tools/picard/rgPicardFixMate.xml
+++ b/tools/picard/rgPicardFixMate.xml
@@ -1,8 +1,8 @@
-<tool name="Paired Read Mate Fixer" id="rgPicFixMate" version="0.2.0">
+<tool name="Paired Read Mate Fixer" id="rgPicFixMate" version="0.2.1"><description>for paired data</description><command interpreter="python">
picard_wrapper.py -i "$input_file" -o "$out_file" --tmpdir "${__new_file_path__}" -n "$out_prefix"
- --output-format "$outputFormat" -j "${GALAXY_DATA_INDEX_DIR}/shared/jars/FixMateInformation.jar" --sortorder "$sortOrder"
+ --output-format "$outputFormat" -j "${GALAXY_DATA_INDEX_DIR}/shared/jars/picard/FixMateInformation.jar" --sortorder "$sortOrder"
</command><requirements><requirement type="package">picard</requirement></requirements><inputs>
diff -r 603924d3abc3057def82337b53178ad48a71b1d1 -r 125d735c689ee60ad9bd9601c7a22738ba3523de tools/picard/rgPicardGCBiasMetrics.xml
--- a/tools/picard/rgPicardGCBiasMetrics.xml
+++ b/tools/picard/rgPicardGCBiasMetrics.xml
@@ -1,8 +1,8 @@
-<tool name="SAM/BAM GC Bias Metrics" id="PicardGCBiasMetrics" version="0.02">
+<tool name="SAM/BAM GC Bias Metrics" id="PicardGCBiasMetrics" version="0.02.1"><command interpreter="python">
picard_wrapper.py -i "$input_file" -d "$html_file.files_path" -t "$html_file"
--windowsize "$windowsize" --mingenomefrac "$mingenomefrac" -n "$out_prefix" --tmpdir "${__new_file_path__}"
- -j ${GALAXY_DATA_INDEX_DIR}/shared/jars/CollectGcBiasMetrics.jar
+ -j ${GALAXY_DATA_INDEX_DIR}/shared/jars/picard/CollectGcBiasMetrics.jar
#if $genomeSource.refGenomeSource == "history":
--ref-file "$genomeSource.ownFile"
#else:
diff -r 603924d3abc3057def82337b53178ad48a71b1d1 -r 125d735c689ee60ad9bd9601c7a22738ba3523de tools/picard/rgPicardHsMetrics.xml
--- a/tools/picard/rgPicardHsMetrics.xml
+++ b/tools/picard/rgPicardHsMetrics.xml
@@ -1,10 +1,10 @@
-<tool name="SAM/BAM Hybrid Selection Metrics" id="PicardHsMetrics" version="0.02">
+<tool name="SAM/BAM Hybrid Selection Metrics" id="PicardHsMetrics" version="0.02.1"><description>for targeted resequencing data</description><command interpreter="python">
picard_wrapper.py -i "$input_file" -d "$html_file.files_path" -t "$html_file" --datatype "$input_file.ext"
--baitbed "$bait_bed" --targetbed "$target_bed" -n "$out_prefix" --tmpdir "${__new_file_path__}"
- -j "${GALAXY_DATA_INDEX_DIR}/shared/jars/CalculateHsMetrics.jar"
+ -j "${GALAXY_DATA_INDEX_DIR}/shared/jars/picard/CalculateHsMetrics.jar"
</command><requirements><requirement type="package">picard</requirement></requirements>
diff -r 603924d3abc3057def82337b53178ad48a71b1d1 -r 125d735c689ee60ad9bd9601c7a22738ba3523de tools/picard/rgPicardInsertSize.xml
--- a/tools/picard/rgPicardInsertSize.xml
+++ b/tools/picard/rgPicardInsertSize.xml
@@ -1,10 +1,10 @@
-<tool name="Insertion size metrics" id="PicardInsertSize" version="0.3.0">
+<tool name="Insertion size metrics" id="PicardInsertSize" version="0.3.1"><description>for PAIRED data</description><requirements><requirement type="package">picard</requirement></requirements><command interpreter="python">
picard_wrapper.py -i "$input_file" -n "$out_prefix" --tmpdir "${__new_file_path__}" --taillimit "$tailLimit"
--histwidth "$histWidth" --minpct "$minPct"
- -j "${GALAXY_DATA_INDEX_DIR}/shared/jars/CollectInsertSizeMetrics.jar" -d "$html_file.files_path" -t "$html_file"
+ -j "${GALAXY_DATA_INDEX_DIR}/shared/jars/picard/CollectInsertSizeMetrics.jar" -d "$html_file.files_path" -t "$html_file"
</command><inputs><param format="bam,sam" name="input_file" type="data" label="SAM/BAM dataset to generate statistics for"
diff -r 603924d3abc3057def82337b53178ad48a71b1d1 -r 125d735c689ee60ad9bd9601c7a22738ba3523de tools/picard/rgPicardLibComplexity.xml
--- a/tools/picard/rgPicardLibComplexity.xml
+++ b/tools/picard/rgPicardLibComplexity.xml
@@ -1,8 +1,8 @@
-<tool name="Estimate Library Complexity" id="rgEstLibComp" version="0.01">
+<tool name="Estimate Library Complexity" id="rgEstLibComp" version="0.01.1"><command interpreter="python">
picard_wrapper.py -i "$input_file" -n "$out_prefix" --tmpdir "${__new_file_path__}" --minid "$minIDbases"
--maxdiff "$maxDiff" --minmeanq "$minMeanQ" --readregex "$readRegex" --optdupdist "$optDupeDist"
- -j "${GALAXY_DATA_INDEX_DIR}/shared/jars/EstimateLibraryComplexity.jar" -d "$html_file.files_path" -t "$html_file"
+ -j "${GALAXY_DATA_INDEX_DIR}/shared/jars/picard/EstimateLibraryComplexity.jar" -d "$html_file.files_path" -t "$html_file"
</command><inputs><param format="bam,sam" name="input_file" type="data" label="SAM/BAM dataset"
diff -r 603924d3abc3057def82337b53178ad48a71b1d1 -r 125d735c689ee60ad9bd9601c7a22738ba3523de tools/picard/rgPicardMarkDups.xml
--- a/tools/picard/rgPicardMarkDups.xml
+++ b/tools/picard/rgPicardMarkDups.xml
@@ -1,8 +1,8 @@
-<tool name="Mark Duplicate reads" id="rgPicardMarkDups" version="0.01">
+<tool name="Mark Duplicate reads" id="rgPicardMarkDups" version="0.01.1"><command interpreter="python">
picard_wrapper.py -i "$input_file" -n "$out_prefix" --tmpdir "${__new_file_path__}" -o "$out_file"
--remdups "$remDups" --assumesorted "$assumeSorted" --readregex "$readRegex" --optdupdist "$optDupeDist"
- -j "${GALAXY_DATA_INDEX_DIR}/shared/jars/MarkDuplicates.jar" -d "$html_file.files_path" -t "$html_file" -e "$input_file.ext"
+ -j "${GALAXY_DATA_INDEX_DIR}/shared/jars/picard/MarkDuplicates.jar" -d "$html_file.files_path" -t "$html_file" -e "$input_file.ext"
</command><requirements><requirement type="package">picard</requirement></requirements><inputs>
https://bitbucket.org/galaxy/galaxy-central/changeset/ab8fb6d1f56d/
changeset: ab8fb6d1f56d
user: natefoo
date: 2011-10-27 19:51:28
summary: merge
affected #: 37 files
diff -r 125d735c689ee60ad9bd9601c7a22738ba3523de -r ab8fb6d1f56d6677ccd9dbfa137acf6efbc4d245 lib/galaxy/web/base/controller.py
--- a/lib/galaxy/web/base/controller.py
+++ b/lib/galaxy/web/base/controller.py
@@ -1,10 +1,11 @@
"""
Contains functionality needed in every web interface
"""
-import os, time, logging, re, string, sys, glob, shutil, tempfile, subprocess
+import os, time, logging, re, string, sys, glob, shutil, tempfile, subprocess, binascii
from datetime import date, datetime, timedelta
from time import strftime
from galaxy import config, tools, web, util
+from galaxy.util.hash_util import *
from galaxy.web import error, form, url_for
from galaxy.model.orm import *
from galaxy.workflow.modules import *
@@ -2484,3 +2485,32 @@
message = "The required file named tool_data_table_conf.xml does not exist in the Galaxy install directory."
error = True
return error, message
+def tool_shed_encode( val ):
+ if isinstance( val, dict ):
+ value = simplejson.dumps( val )
+ else:
+ value = val
+ a = hmac_new( 'ToolShedAndGalaxyMustHaveThisSameKey', value )
+ b = binascii.hexlify( value )
+ return "%s:%s" % ( a, b )
+def tool_shed_decode( value ):
+ # Extract and verify hash
+ a, b = value.split( ":" )
+ value = binascii.unhexlify( b )
+ test = hmac_new( 'ToolShedAndGalaxyMustHaveThisSameKey', value )
+ assert a == test
+ # Restore from string
+ values = None
+ try:
+ values = simplejson.loads( value )
+ except Exception, e:
+ log.debug( "Decoding json value from tool shed threw exception: %s" % str( e ) )
+ if values is not None:
+ try:
+ return json_fix( values )
+ except Exception, e:
+ log.debug( "Fixing decoded json value from tool shed threw exception: %s" % str( e ) )
+ fixed_values = values
+ if values is None:
+ values = value
+ return values
diff -r 125d735c689ee60ad9bd9601c7a22738ba3523de -r ab8fb6d1f56d6677ccd9dbfa137acf6efbc4d245 lib/galaxy/web/controllers/admin.py
--- a/lib/galaxy/web/controllers/admin.py
+++ b/lib/galaxy/web/controllers/admin.py
@@ -4,8 +4,7 @@
from galaxy.web.framework.helpers import time_ago, iff, grids
from galaxy.tools.search import ToolBoxSearch
from galaxy.tools import json_fix
-from galaxy.util.hash_util import *
-import simplejson, binascii, logging
+import logging
log = logging.getLogger( __name__ )
from galaxy.actions.admin import AdminActions
@@ -705,6 +704,13 @@
return trans.response.send_redirect( url )
@web.expose
@web.require_admin
+ def find_workflows_in_tool_shed( self, trans, **kwd ):
+ tool_shed_url = kwd[ 'tool_shed_url' ]
+ galaxy_url = trans.request.host
+ url = '%s/repository/find_workflows?galaxy_url=%s&webapp=galaxy' % ( tool_shed_url, galaxy_url )
+ return trans.response.send_redirect( url )
+ @web.expose
+ @web.require_admin
def browse_tool_shed( self, trans, **kwd ):
tool_shed_url = kwd[ 'tool_shed_url' ]
galaxy_url = trans.request.host
@@ -736,7 +742,7 @@
section_key = 'section_%s' % kwd[ 'tool_panel_section' ]
tool_section = trans.app.toolbox.tool_panel[ section_key ]
# Decode the encoded repo_info_dict param value.
- repo_info_dict = self.__decode( repo_info_dict )
+ repo_info_dict = tool_shed_decode( repo_info_dict )
# Clone the repository to the configured location.
current_working_dir = os.getcwd()
for name, repo_info_tuple in repo_info_dict.items():
@@ -1157,15 +1163,6 @@
section_str += ' </tool>\n'
section_str += ' </section>\n'
return section_str
- def __decode( self, value ):
- # Extract and verify hash
- a, b = value.split( ":" )
- value = binascii.unhexlify( b )
- test = hmac_new( 'ToolShedAndGalaxyMustHaveThisSameKey', value )
- assert a == test
- # Restore from string
- values = json_fix( simplejson.loads( value ) )
- return values
## ---- Utility methods -------------------------------------------------------
diff -r 125d735c689ee60ad9bd9601c7a22738ba3523de -r ab8fb6d1f56d6677ccd9dbfa137acf6efbc4d245 lib/galaxy/web/controllers/tracks.py
--- a/lib/galaxy/web/controllers/tracks.py
+++ b/lib/galaxy/web/controllers/tracks.py
@@ -663,7 +663,8 @@
vis.latest_revision = vis_rev
session.add( vis_rev )
session.flush()
- return trans.security.encode_id(vis.id)
+ encoded_id = trans.security.encode_id(vis.id)
+ return { "id": encoded_id, "url": url_for( action='browser', id=encoded_id ) }
@web.expose
@web.require_login( "see all available libraries" )
diff -r 125d735c689ee60ad9bd9601c7a22738ba3523de -r ab8fb6d1f56d6677ccd9dbfa137acf6efbc4d245 lib/galaxy/web/controllers/workflow.py
--- a/lib/galaxy/web/controllers/workflow.py
+++ b/lib/galaxy/web/controllers/workflow.py
@@ -4,7 +4,7 @@
pkg_resources.require( "simplejson" )
pkg_resources.require( "SVGFig" )
import simplejson
-import base64, httplib, urllib2, sgmllib, svgfig
+import base64, httplib, urllib2, sgmllib, svgfig, urllib, urllib2
import math
from galaxy.web.framework.helpers import time_ago, grids
from galaxy.tools.parameters import *
@@ -1092,13 +1092,35 @@
trans.response.headers["Content-Disposition"] = "attachment; filename=Galaxy-Workflow-%s.ga" % ( sname )
trans.response.set_content_type( 'application/galaxy-archive' )
return stored_dict
-
@web.expose
def import_workflow( self, trans, **kwd ):
+ """
+ Import a workflow by reading an url, uploading a file, or receiving the textual
+ representation of a workflow.
+ """
url = kwd.get( 'url', '' )
+ workflow_text = kwd.get( 'workflow_text', '' )
+ webapp = kwd.get( 'webapp', 'galaxy' )
message = kwd.get( 'message', '' )
status = kwd.get( 'status', 'done' )
- if kwd.get( 'import_button', False ):
+ import_button = kwd.get( 'import_button', False )
+ tool_shed_url = kwd.get( 'tool_shed_url', '' )
+ repository_metadata_id = kwd.get( 'repository_metadata_id', '' )
+ # The workflow_name parameter is in the request only if the import originated
+ # from a Galaxy tool shed, in which case the value was encoded.
+ workflow_name = kwd.get( 'workflow_name', '' )
+ if workflow_name:
+ workflow_name = tool_shed_decode( workflow_name )
+ if tool_shed_url and not import_button:
+ # Use urllib (send another request to the tool shed) to retrieve the workflow.
+ workflow_url = 'http://%s/workflow/import_workflow?repository_metadata_id=%s&workflow_name=%s&webapp=%s&open_for_url=true' % \
+ ( tool_shed_url, repository_metadata_id, tool_shed_encode( workflow_name ), webapp )
+ response = urllib2.urlopen( workflow_url )
+ workflow_text = response.read()
+ response.close()
+ workflow_text = workflow_text
+ import_button = True
+ if import_button:
workflow_data = None
if url:
# Load workflow from external URL
@@ -1108,6 +1130,8 @@
except Exception, e:
message = "Failed to open URL: <b>%s</b><br>Exception: %s" % ( url, str( e ) )
status = 'error'
+ elif workflow_text:
+ workflow_data = workflow_text
else:
# Load workflow from browsed file.
file_data = kwd.get( 'file_data', '' )
@@ -1175,6 +1199,13 @@
else:
# TODO: Figure out what to do here...
pass
+ if tool_shed_url:
+ # We've received the textual representation of a workflow from a Galaxy tool shed.
+ message = "This workflow has been successfully imported into your local Galaxy instance."
+ # TODO: support https in the following url.
+ url = 'http://%s/workflow/view_workflow?repository_metadata_id=%s&workflow_name=%s&webapp=%s&message=%s' % \
+ ( tool_shed_url, repository_metadata_id, tool_shed_encode( workflow_name ), webapp, message )
+ return trans.response.send_redirect( url )
return self.list( trans )
return trans.fill_template( "workflow/import.mako",
url=url,
diff -r 125d735c689ee60ad9bd9601c7a22738ba3523de -r ab8fb6d1f56d6677ccd9dbfa137acf6efbc4d245 lib/galaxy/webapps/community/app.py
--- a/lib/galaxy/webapps/community/app.py
+++ b/lib/galaxy/webapps/community/app.py
@@ -35,6 +35,8 @@
self.tag_handler = CommunityTagHandler()
# Tool data tables
self.tool_data_tables = galaxy.tools.data.ToolDataTableManager( self.config.tool_data_table_config_path )
+ # The tool shed has no toolbox, but this attribute is still required.
+ self.toolbox = None
# Load security policy
self.security_agent = self.model.security_agent
self.quota_agent = galaxy.quota.NoQuotaAgent( self.model )
diff -r 125d735c689ee60ad9bd9601c7a22738ba3523de -r ab8fb6d1f56d6677ccd9dbfa137acf6efbc4d245 lib/galaxy/webapps/community/controllers/admin.py
--- a/lib/galaxy/webapps/community/controllers/admin.py
+++ b/lib/galaxy/webapps/community/controllers/admin.py
@@ -332,13 +332,13 @@
if 'tools' in metadata:
metadata_str += '<b>Tools:</b><br/>'
for tool_metadata_dict in metadata[ 'tools' ]:
- metadata_str += '%s <b>%s</b><br/>' % \
- ( tool_metadata_dict[ 'id' ], tool_metadata_dict[ 'version' ] )
+ metadata_str += '%s <b>%s</b><br/>' % ( tool_metadata_dict[ 'id' ],
+ tool_metadata_dict[ 'version' ] )
if 'workflows' in metadata:
metadata_str += '<b>Workflows:</b><br/>'
for workflow_metadata_dict in metadata[ 'workflows' ]:
- metadata_str += '%s <b>%s</b><br/>' % \
- ( workflow_metadata_dict[ 'name' ], workflow_metadata_dict[ 'format-version' ] )
+ metadata_str += '%s <b>%s</b><br/>' % ( workflow_metadata_dict[ 'name' ],
+ workflow_metadata_dict[ 'format-version' ] )
return metadata_str
class MaliciousColumn( grids.BooleanColumn ):
def get_value( self, trans, grid, repository_metadata ):
diff -r 125d735c689ee60ad9bd9601c7a22738ba3523de -r ab8fb6d1f56d6677ccd9dbfa137acf6efbc4d245 lib/galaxy/webapps/community/controllers/common.py
--- a/lib/galaxy/webapps/community/controllers/common.py
+++ b/lib/galaxy/webapps/community/controllers/common.py
@@ -1,8 +1,9 @@
-import os, string, socket, logging
+import os, string, socket, logging, simplejson, binascii
from time import strftime
from datetime import *
from galaxy.tools import *
from galaxy.util.json import from_json_string, to_json_string
+from galaxy.util.hash_util import *
from galaxy.web.base.controller import *
from galaxy.webapps.community import model
from galaxy.model.orm import *
@@ -126,23 +127,18 @@
def generate_workflow_metadata( trans, id, changeset_revision, exported_workflow_dict, metadata_dict ):
"""
Update the received metadata_dict with changes that have been applied
- to the received exported_workflow_dict. Store everything except the
- workflow steps in the database.
+ to the received exported_workflow_dict. Store everything in the database.
"""
- workflow_dict = { 'a_galaxy_workflow' : exported_workflow_dict[ 'a_galaxy_workflow' ],
- 'name' :exported_workflow_dict[ 'name' ],
- 'annotation' : exported_workflow_dict[ 'annotation' ],
- 'format-version' : exported_workflow_dict[ 'format-version' ] }
if 'workflows' in metadata_dict:
- metadata_dict[ 'workflows' ].append( workflow_dict )
+ metadata_dict[ 'workflows' ].append( exported_workflow_dict )
else:
- metadata_dict[ 'workflows' ] = [ workflow_dict ]
+ metadata_dict[ 'workflows' ] = [ exported_workflow_dict ]
return metadata_dict
def new_workflow_metadata_required( trans, id, metadata_dict ):
"""
- TODO: Currently everything about an exported workflow except the name is hard-coded, so
- there's no real way to differentiate versions of exported workflows. If this changes at
- some future time, this method should be enhanced accordingly...
+ Currently everything about an exported workflow except the name is hard-coded, so there's
+ no real way to differentiate versions of exported workflows. If this changes at some future
+ time, this method should be enhanced accordingly.
"""
if 'workflows' in metadata_dict:
repository_metadata = get_latest_repository_metadata( trans, id )
@@ -425,18 +421,20 @@
trans.sa_session.add( repository_metadata )
trans.sa_session.flush()
else:
- message = "Change set revision '%s' includes no tools or exported workflows for which metadata can be set." % str( changeset_revision )
+ message = "Revision '%s' includes no tools or exported workflows for which metadata can be defined " % str( changeset_revision )
+ message += "so this revision cannot be automatically installed into a local Galaxy instance."
status = "error"
else:
# change_set is None
- message = "Repository does not include change set revision '%s'." % str( changeset_revision )
+ message = "This repository does not include revision '%s'." % str( changeset_revision )
status = 'error'
if invalid_files:
if metadata_dict:
- message = "Metadata was defined for some items in change set revision '%s'. " % str( changeset_revision )
+ message = "Metadata was defined for some items in revision '%s'. " % str( changeset_revision )
message += "Correct the following problems if necessary and reset metadata.<br/>"
else:
- message = "Metadata cannot be defined for change set revision '%s'. Correct the following problems and reset metadata.<br/>" % str( changeset_revision )
+ message = "Metadata cannot be defined for revision '%s' so this revision cannot be automatically " % str( changeset_revision )
+ message += "installed into a local Galaxy instance. Correct the following problems and reset metadata.<br/>"
for itc_tup in invalid_files:
tool_file, exception_msg = itc_tup
if exception_msg.find( 'No such file or directory' ) >= 0:
@@ -619,3 +617,24 @@
selected = selected_value and option_tup[1] == selected_value
select_field.add_option( option_tup[0], option_tup[1], selected=selected )
return select_field
+def encode( val ):
+ if isinstance( val, dict ):
+ value = simplejson.dumps( val )
+ else:
+ value = val
+ a = hmac_new( 'ToolShedAndGalaxyMustHaveThisSameKey', value )
+ b = binascii.hexlify( value )
+ return "%s:%s" % ( a, b )
+def decode( value ):
+ # Extract and verify hash
+ a, b = value.split( ":" )
+ value = binascii.unhexlify( b )
+ test = hmac_new( 'ToolShedAndGalaxyMustHaveThisSameKey', value )
+ assert a == test
+ # Restore from string
+ try:
+ values = json_fix( simplejson.loads( value ) )
+ except Exception, e:
+ # We do not have a json string
+ values = value
+ return values
diff -r 125d735c689ee60ad9bd9601c7a22738ba3523de -r ab8fb6d1f56d6677ccd9dbfa137acf6efbc4d245 lib/galaxy/webapps/community/controllers/repository.py
--- a/lib/galaxy/webapps/community/controllers/repository.py
+++ b/lib/galaxy/webapps/community/controllers/repository.py
@@ -9,7 +9,6 @@
from galaxy.webapps.community.model import directory_hash_id
from galaxy.web.framework.helpers import time_ago, iff, grids
from galaxy.util.json import from_json_string, to_json_string
-from galaxy.util.hash_util import *
from galaxy.model.orm import *
from common import *
from mercurial import hg, ui, patch, commands
@@ -232,7 +231,7 @@
return repository_metadata.repository.user.username
return 'no user'
# Grid definition
- title = "Repositories with matching tools"
+ title = "Matching repositories"
model_class = model.RepositoryMetadata
template='/webapps/community/repository/grid.mako'
default_sort_key = "Repository.name"
@@ -376,6 +375,83 @@
# Render the list view
return self.valid_repository_list_grid( trans, **kwd )
@web.expose
+ def find_workflows( self, trans, **kwd ):
+ params = util.Params( kwd )
+ message = util.restore_text( params.get( 'message', '' ) )
+ status = params.get( 'status', 'done' )
+ webapp = params.get( 'webapp', 'community' )
+ galaxy_url = kwd.get( 'galaxy_url', None )
+ if galaxy_url:
+ trans.set_cookie( galaxy_url, name='toolshedgalaxyurl' )
+ if 'operation' in kwd:
+ item_id = kwd.get( 'id', '' )
+ if item_id:
+ operation = kwd[ 'operation' ].lower()
+ is_admin = trans.user_is_admin()
+ if operation == "view_or_manage_repository":
+ # The received id is a RepositoryMetadata id, so we have to get the repository id.
+ repository_metadata = get_repository_metadata_by_id( trans, item_id )
+ repository_id = trans.security.encode_id( repository_metadata.repository.id )
+ repository = get_repository( trans, repository_id )
+ kwd[ 'id' ] = repository_id
+ kwd[ 'changeset_revision' ] = repository_metadata.changeset_revision
+ if webapp == 'community' and ( is_admin or repository.user == trans.user ):
+ a = 'manage_repository'
+ else:
+ a = 'view_repository'
+ return trans.response.send_redirect( web.url_for( controller='repository',
+ action=a,
+ **kwd ) )
+ if operation == "install":
+ galaxy_url = trans.get_cookie( name='toolshedgalaxyurl' )
+ encoded_repo_info_dict = self.__encode_repo_info_dict( trans, webapp, util.listify( item_id ) )
+ # TODO: support https in the following url.
+ url = 'http://%s/admin/install_tool_shed_repository?tool_shed_url=%s&webapp=%s&repo_info_dict=%s' % \
+ ( galaxy_url, trans.request.host, webapp, encoded_repo_info_dict )
+ return trans.response.send_redirect( url )
+ else:
+ # This can only occur when there is a multi-select grid with check boxes and an operation,
+ # and the user clicked the operation button without checking any of the check boxes.
+ return trans.show_error_message( "No items were selected." )
+ workflow_names = [ item.lower() for item in util.listify( kwd.get( 'workflow_name', '' ) ) ]
+ exact_matches = params.get( 'exact_matches', '' )
+ exact_matches_checked = CheckboxField.is_checked( exact_matches )
+ match_tuples = []
+ ok = True
+ if workflow_names:
+ ok, match_tuples = self.__search_repository_metadata( trans, exact_matches_checked, workflow_names=workflow_names )
+ if ok:
+ kwd[ 'match_tuples' ] = match_tuples
+ # Render the list view
+ if webapp == 'galaxy':
+ # Our initial request originated from a Galaxy instance.
+ global_actions = [ grids.GridAction( "Browse valid repositories",
+ dict( controller='repository', action='browse_valid_repositories', webapp=webapp ) ),
+ grids.GridAction( "Search for valid tools",
+ dict( controller='repository', action='find_tools', webapp=webapp ) ),
+ grids.GridAction( "Search for workflows",
+ dict( controller='repository', action='find_workflows', webapp=webapp ) ) ]
+ self.install_matched_repository_list_grid.global_actions = global_actions
+ install_url_args = dict( controller='repository', action='find_workflows', webapp=webapp )
+ operations = [ grids.GridOperation( "Install", url_args=install_url_args, allow_multiple=True, async_compatible=False ) ]
+ self.install_matched_repository_list_grid.operations = operations
+ return self.install_matched_repository_list_grid( trans, **kwd )
+ else:
+ kwd[ 'message' ] = "workflow name: <b>%s</b><br/>exact matches only: <b>%s</b>" % \
+ ( self.__stringify( workflow_names ), str( exact_matches_checked ) )
+ self.matched_repository_list_grid.title = "Repositories with matching workflows"
+ return self.matched_repository_list_grid( trans, **kwd )
+ else:
+ message = "No search performed - each field must contain the same number of comma-separated items."
+ status = "error"
+ exact_matches_check_box = CheckboxField( 'exact_matches', checked=exact_matches_checked )
+ return trans.fill_template( '/webapps/community/repository/find_workflows.mako',
+ webapp=webapp,
+ workflow_name=self.__stringify( workflow_names ),
+ exact_matches_check_box=exact_matches_check_box,
+ message=message,
+ status=status )
+ @web.expose
def find_tools( self, trans, **kwd ):
params = util.Params( kwd )
message = util.restore_text( params.get( 'message', '' ) )
@@ -422,7 +498,7 @@
match_tuples = []
ok = True
if tool_ids or tool_names or tool_versions:
- ok, match_tuples = self.__search_repository_metadata( trans, tool_ids, tool_names, tool_versions, exact_matches_checked )
+ ok, match_tuples = self.__search_repository_metadata( trans, exact_matches_checked, tool_ids=tool_ids, tool_names=tool_names, tool_versions=tool_versions )
if ok:
kwd[ 'match_tuples' ] = match_tuples
# Render the list view
@@ -431,7 +507,9 @@
global_actions = [ grids.GridAction( "Browse valid repositories",
dict( controller='repository', action='browse_valid_repositories', webapp=webapp ) ),
grids.GridAction( "Search for valid tools",
- dict( controller='repository', action='find_tools', webapp=webapp ) ) ]
+ dict( controller='repository', action='find_tools', webapp=webapp ) ),
+ grids.GridAction( "Search for workflows",
+ dict( controller='repository', action='find_workflows', webapp=webapp ) ) ]
self.install_matched_repository_list_grid.global_actions = global_actions
install_url_args = dict( controller='repository', action='find_tools', webapp=webapp )
operations = [ grids.GridOperation( "Install", url_args=install_url_args, allow_multiple=True, async_compatible=False ) ]
@@ -440,6 +518,7 @@
else:
kwd[ 'message' ] = "tool id: <b>%s</b><br/>tool name: <b>%s</b><br/>tool version: <b>%s</b><br/>exact matches only: <b>%s</b>" % \
( self.__stringify( tool_ids ), self.__stringify( tool_names ), self.__stringify( tool_versions ), str( exact_matches_checked ) )
+ self.matched_repository_list_grid.title = "Repositories with matching tools"
return self.matched_repository_list_grid( trans, **kwd )
else:
message = "No search performed - each field must contain the same number of comma-separated items."
@@ -453,59 +532,76 @@
exact_matches_check_box=exact_matches_check_box,
message=message,
status=status )
- def __search_repository_metadata( self, trans, tool_ids, tool_names, tool_versions, exact_matches_checked ):
+ def __search_repository_metadata( self, trans, exact_matches_checked, tool_ids='', tool_names='', tool_versions='', workflow_names='' ):
match_tuples = []
ok = True
for repository_metadata in trans.sa_session.query( model.RepositoryMetadata ):
metadata = repository_metadata.metadata
- tools = metadata[ 'tools' ]
- for tool_dict in tools:
- if tool_ids and not tool_names and not tool_versions:
- for tool_id in tool_ids:
- if self.__in_tool_dict( tool_dict, exact_matches_checked, tool_id=tool_id ):
+ if tool_ids or tool_names or tool_versions:
+ if 'tools' in metadata:
+ tools = metadata[ 'tools' ]
+ else:
+ tools = []
+ for tool_dict in tools:
+ if tool_ids and not tool_names and not tool_versions:
+ for tool_id in tool_ids:
+ if self.__in_tool_dict( tool_dict, exact_matches_checked, tool_id=tool_id ):
+ match_tuples.append( ( repository_metadata.repository_id, repository_metadata.changeset_revision ) )
+ elif tool_names and not tool_ids and not tool_versions:
+ for tool_name in tool_names:
+ if self.__in_tool_dict( tool_dict, exact_matches_checked, tool_name=tool_name ):
+ match_tuples.append( ( repository_metadata.repository_id, repository_metadata.changeset_revision ) )
+ elif tool_versions and not tool_ids and not tool_names:
+ for tool_version in tool_versions:
+ if self.__in_tool_dict( tool_dict, exact_matches_checked, tool_version=tool_version ):
+ match_tuples.append( ( repository_metadata.repository_id, repository_metadata.changeset_revision ) )
+ elif tool_ids and tool_names and not tool_versions:
+ if len( tool_ids ) == len( tool_names ):
+ match_tuples = self.__search_ids_names( tool_dict, exact_matches_checked, match_tuples, repository_metadata, tool_ids, tool_names )
+ elif len( tool_ids ) == 1 or len( tool_names ) == 1:
+ tool_ids, tool_names = self.__make_same_length( tool_ids, tool_names )
+ match_tuples = self.__search_ids_names( tool_dict, exact_matches_checked, match_tuples, repository_metadata, tool_ids, tool_names )
+ else:
+ ok = False
+ elif tool_ids and tool_versions and not tool_names:
+ if len( tool_ids ) == len( tool_versions ):
+ match_tuples = self.__search_ids_versions( tool_dict, exact_matches_checked, match_tuples, repository_metadata, tool_ids, tool_versions )
+ elif len( tool_ids ) == 1 or len( tool_versions ) == 1:
+ tool_ids, tool_versions = self.__make_same_length( tool_ids, tool_versions )
+ match_tuples = self.__search_ids_versions( tool_dict, exact_matches_checked, match_tuples, repository_metadata, tool_ids, tool_versions )
+ else:
+ ok = False
+ elif tool_versions and tool_names and not tool_ids:
+ if len( tool_versions ) == len( tool_names ):
+ match_tuples = self.__search_names_versions( tool_dict, exact_matches_checked, match_tuples, repository_metadata, tool_names, tool_versions )
+ elif len( tool_versions ) == 1 or len( tool_names ) == 1:
+ tool_versions, tool_names = self.__make_same_length( tool_versions, tool_names )
+ match_tuples = self.__search_names_versions( tool_dict, exact_matches_checked, match_tuples, repository_metadata, tool_names, tool_versions )
+ else:
+ ok = False
+ elif tool_versions and tool_names and tool_ids:
+ if len( tool_versions ) == len( tool_names ) and len( tool_names ) == len( tool_ids ):
+ for i, tool_version in enumerate( tool_versions ):
+ tool_name = tool_names[ i ]
+ tool_id = tool_ids[ i ]
+ if self.__in_tool_dict( tool_dict, exact_matches_checked, tool_id=tool_id, tool_name=tool_name, tool_version=tool_version ):
+ match_tuples.append( ( repository_metadata.repository_id, repository_metadata.changeset_revision ) )
+ else:
+ ok = False
+ if workflow_names:
+ if 'workflows' in metadata:
+ workflows = metadata[ 'workflows' ]
+ else:
+ workflows = []
+ for workflow_dict in workflows:
+ for workflow_name in workflow_names:
+ if self.__in_workflow_dict( workflow_dict, exact_matches_checked, workflow_name=workflow_name ):
match_tuples.append( ( repository_metadata.repository_id, repository_metadata.changeset_revision ) )
- elif tool_names and not tool_ids and not tool_versions:
- for tool_name in tool_names:
- if self.__in_tool_dict( tool_dict, exact_matches_checked, tool_name=tool_name ):
- match_tuples.append( ( repository_metadata.repository_id, repository_metadata.changeset_revision ) )
- elif tool_versions and not tool_ids and not tool_names:
- for tool_version in tool_versions:
- if self.__in_tool_dict( tool_dict, exact_matches_checked, tool_version=tool_version ):
- match_tuples.append( ( repository_metadata.repository_id, repository_metadata.changeset_revision ) )
- elif tool_ids and tool_names and not tool_versions:
- if len( tool_ids ) == len( tool_names ):
- match_tuples = self.__search_ids_names( tool_dict, exact_matches_checked, match_tuples, repository_metadata, tool_ids, tool_names )
- elif len( tool_ids ) == 1 or len( tool_names ) == 1:
- tool_ids, tool_names = self.__make_same_length( tool_ids, tool_names )
- match_tuples = self.__search_ids_names( tool_dict, exact_matches_checked, match_tuples, repository_metadata, tool_ids, tool_names )
- else:
- ok = False
- elif tool_ids and tool_versions and not tool_names:
- if len( tool_ids ) == len( tool_versions ):
- match_tuples = self.__search_ids_versions( tool_dict, exact_matches_checked, match_tuples, repository_metadata, tool_ids, tool_versions )
- elif len( tool_ids ) == 1 or len( tool_versions ) == 1:
- tool_ids, tool_versions = self.__make_same_length( tool_ids, tool_versions )
- match_tuples = self.__search_ids_versions( tool_dict, exact_matches_checked, match_tuples, repository_metadata, tool_ids, tool_versions )
- else:
- ok = False
- elif tool_versions and tool_names and not tool_ids:
- if len( tool_versions ) == len( tool_names ):
- match_tuples = self.__search_names_versions( tool_dict, exact_matches_checked, match_tuples, repository_metadata, tool_names, tool_versions )
- elif len( tool_versions ) == 1 or len( tool_names ) == 1:
- tool_versions, tool_names = self.__make_same_length( tool_versions, tool_names )
- match_tuples = self.__search_names_versions( tool_dict, exact_matches_checked, match_tuples, repository_metadata, tool_names, tool_versions )
- else:
- ok = False
- elif tool_versions and tool_names and tool_ids:
- if len( tool_versions ) == len( tool_names ) and len( tool_names ) == len( tool_ids ):
- for i, tool_version in enumerate( tool_versions ):
- tool_name = tool_names[ i ]
- tool_id = tool_ids[ i ]
- if self.__in_tool_dict( tool_dict, exact_matches_checked, tool_id=tool_id, tool_name=tool_name, tool_version=tool_version ):
- match_tuples.append( ( repository_metadata.repository_id, repository_metadata.changeset_revision ) )
- else:
- ok = False
return ok, match_tuples
+ def __in_workflow_dict( self, workflow_dict, exact_matches_checked, workflow_name=None ):
+ workflow_dict_workflow_name = workflow_dict[ 'name' ].lower()
+ return ( workflow_name == workflow_dict_workflow_name ) or \
+ ( not exact_matches_checked and workflow_dict_workflow_name.find( workflow_name ) >= 0 )
def __in_tool_dict( self, tool_dict, exact_matches_checked, tool_id=None, tool_name=None, tool_version=None ):
found = False
if tool_id and not tool_name and not tool_version:
@@ -588,15 +684,7 @@
changeset_revision = repository_metadata.changeset_revision
repository_clone_url = generate_clone_url( trans, repository_id )
repo_info_dict[ repository.name ] = ( repository.description, repository_clone_url, changeset_revision )
- return self.__encode( repo_info_dict )
- def __encode( self, val ):
- if isinstance( val, dict ):
- value = simplejson.dumps( val )
- else:
- value = val
- a = hmac_new( 'ToolShedAndGalaxyMustHaveThisSameKey', value )
- b = binascii.hexlify( value )
- return "%s:%s" % ( a, b )
+ return encode( repo_info_dict )
@web.expose
def preview_tools_in_changeset( self, trans, repository_id, **kwd ):
params = util.Params( kwd )
@@ -607,8 +695,10 @@
changeset_revision = util.restore_text( params.get( 'changeset_revision', repository.tip ) )
repository_metadata = get_repository_metadata_by_changeset_revision( trans, repository_id, changeset_revision )
if repository_metadata:
+ repository_metadata_id = trans.security.encode_id( repository_metadata.id ),
metadata = repository_metadata.metadata
else:
+ repository_metadata_id = None
metadata = None
revision_label = get_revision_label( trans, repository, changeset_revision )
changeset_revision_select_field = build_changeset_revision_select_field( trans,
@@ -617,6 +707,7 @@
add_id_to_name=False )
return trans.fill_template( '/webapps/community/repository/preview_tools_in_changeset.mako',
repository=repository,
+ repository_metadata_id=repository_metadata_id,
changeset_revision=changeset_revision,
revision_label=revision_label,
changeset_revision_select_field=changeset_revision_select_field,
@@ -636,7 +727,7 @@
changeset_revision = util.restore_text( params.get( 'changeset_revision', repository.tip ) )
repo_info_dict = {}
repo_info_dict[ repository.name ] = ( repository.description, repository_clone_url, changeset_revision )
- encoded_repo_info_dict = self.__encode( repo_info_dict )
+ encoded_repo_info_dict = encode( repo_info_dict )
# Redirect back to local Galaxy to perform install.
# TODO: support https in the following url.
url = 'http://%s/admin/install_tool_shed_repository?tool_shed_url=%s&repo_info_dict=%s' % \
@@ -1159,8 +1250,10 @@
revision_label = get_revision_label( trans, repository, changeset_revision )
repository_metadata = get_repository_metadata_by_changeset_revision( trans, id, changeset_revision )
if repository_metadata:
+ repository_metadata_id = trans.security.encode_id( repository_metadata.id ),
metadata = repository_metadata.metadata
else:
+ repository_metadata_id = None
metadata = None
is_malicious = change_set_is_malicious( trans, id, repository.tip )
if is_malicious:
@@ -1172,6 +1265,7 @@
return trans.fill_template( '/webapps/community/repository/view_repository.mako',
repo=repo,
repository=repository,
+ repository_metadata_id=repository_metadata_id,
metadata=metadata,
avg_rating=avg_rating,
display_reviews=display_reviews,
@@ -1299,9 +1393,11 @@
revision_label = get_revision_label( trans, repository, changeset_revision )
repository_metadata = get_repository_metadata_by_changeset_revision( trans, id, changeset_revision )
if repository_metadata:
+ repository_metadata_id = trans.security.encode_id( repository_metadata.id )
metadata = repository_metadata.metadata
is_malicious = repository_metadata.malicious
else:
+ repository_metadata_id = None
metadata = None
is_malicious = False
if is_malicious:
@@ -1321,6 +1417,7 @@
allow_push_select_field=allow_push_select_field,
repo=repo,
repository=repository,
+ repository_metadata_id=repository_metadata_id,
changeset_revision=changeset_revision,
changeset_revision_select_field=changeset_revision_select_field,
revision_label=revision_label,
diff -r 125d735c689ee60ad9bd9601c7a22738ba3523de -r ab8fb6d1f56d6677ccd9dbfa137acf6efbc4d245 lib/galaxy/webapps/community/controllers/workflow.py
--- /dev/null
+++ b/lib/galaxy/webapps/community/controllers/workflow.py
@@ -0,0 +1,395 @@
+import pkg_resources
+pkg_resources.require( "simplejson" )
+pkg_resources.require( "SVGFig" )
+import os, logging, ConfigParser, tempfile, shutil, svgfig
+from galaxy.webapps.community import model
+from galaxy.web.framework.helpers import time_ago, iff, grids
+from galaxy.util.json import from_json_string, to_json_string
+from galaxy.workflow.modules import InputDataModule, ToolModule, WorkflowModuleFactory
+from galaxy.tools import DefaultToolState
+from galaxy.web.controllers.workflow import attach_ordered_steps
+from galaxy.model.orm import *
+from common import *
+
+class RepoInputDataModule( InputDataModule ):
+
+ type = "data_input"
+ name = "Input dataset"
+
+ @classmethod
+ def new( Class, trans, tools_metadata=None, tool_id=None ):
+ module = Class( trans )
+ module.state = dict( name="Input Dataset" )
+ return module
+ @classmethod
+ def from_dict( Class, trans, d, tools_metadata=None, secure=True ):
+ module = Class( trans )
+ state = from_json_string( d[ "tool_state" ] )
+ module.state = dict( name=state.get( "name", "Input Dataset" ) )
+ return module
+ @classmethod
+ def from_workflow_step( Class, trans, tools_metadata, step ):
+ module = Class( trans )
+ module.state = dict( name="Input Dataset" )
+ if step.tool_inputs and "name" in step.tool_inputs:
+ module.state[ 'name' ] = step.tool_inputs[ 'name' ]
+ return module
+
+class RepoToolModule( ToolModule ):
+
+ type = "tool"
+
+ def __init__( self, trans, tools_metadata, tool_id ):
+ self.trans = trans
+ self.tools_metadata = tools_metadata
+ self.tool_id = tool_id
+ self.tool = None
+ for tool_dict in tools_metadata:
+ if self.tool_id in [ tool_dict[ 'id' ], tool_dict[ 'guid' ] ]:
+ self.tool = load_tool( trans, os.path.abspath( tool_dict[ 'tool_config' ] ) )
+ self.post_job_actions = {}
+ self.workflow_outputs = []
+ self.state = None
+ self.errors = None
+ @classmethod
+ def new( Class, trans, tools_metadata, tool_id=None ):
+ module = Class( trans, tools_metadata, tool_id )
+ module.state = module.tool.new_state( trans, all_pages=True )
+ return module
+ @classmethod
+ def from_dict( Class, trans, d, tools_metadata, secure=True ):
+ tool_id = d[ 'tool_id' ]
+ module = Class( trans, tools_metadata, tool_id )
+ module.state = DefaultToolState()
+ if module.tool is not None:
+ module.state.decode( d[ "tool_state" ], module.tool, module.trans.app, secure=secure )
+ module.errors = d.get( "tool_errors", None )
+ return module
+ @classmethod
+ def from_workflow_step( Class, trans, tools_metadata, step ):
+ module = Class( trans, tools_metadata, step.tool_id )
+ module.state = DefaultToolState()
+ if module.tool:
+ module.state.inputs = module.tool.params_from_strings( step.tool_inputs, trans.app, ignore_errors=True )
+ else:
+ module.state.inputs = {}
+ module.errors = step.tool_errors
+ return module
+ def get_data_inputs( self ):
+ data_inputs = []
+ def callback( input, value, prefixed_name, prefixed_label ):
+ if isinstance( input, DataToolParameter ):
+ data_inputs.append( dict( name=prefixed_name,
+ label=prefixed_label,
+ extensions=input.extensions ) )
+ if self.tool:
+ visit_input_values( self.tool.inputs, self.state.inputs, callback )
+ return data_inputs
+ def get_data_outputs( self ):
+ data_outputs = []
+ if self.tool:
+ data_inputs = None
+ for name, tool_output in self.tool.outputs.iteritems():
+ if tool_output.format_source != None:
+ # Default to special name "input" which remove restrictions on connections
+ formats = [ 'input' ]
+ if data_inputs == None:
+ data_inputs = self.get_data_inputs()
+ # Find the input parameter referenced by format_source
+ for di in data_inputs:
+ # Input names come prefixed with conditional and repeat names separated by '|',
+ # so remove prefixes when comparing with format_source.
+ if di[ 'name' ] != None and di[ 'name' ].split( '|' )[ -1 ] == tool_output.format_source:
+ formats = di[ 'extensions' ]
+ else:
+ formats = [ tool_output.format ]
+ for change_elem in tool_output.change_format:
+ for when_elem in change_elem.findall( 'when' ):
+ format = when_elem.get( 'format', None )
+ if format and format not in formats:
+ formats.append( format )
+ data_outputs.append( dict( name=name, extensions=formats ) )
+ return data_outputs
+
+class RepoWorkflowModuleFactory( WorkflowModuleFactory ):
+ def __init__( self, module_types ):
+ self.module_types = module_types
+ def new( self, trans, type, tools_metadata=None, tool_id=None ):
+ """Return module for type and (optional) tool_id intialized with new / default state."""
+ assert type in self.module_types
+ return self.module_types[type].new( trans, tool_id )
+ def from_dict( self, trans, d, **kwargs ):
+ """Return module initialized from the data in dictionary `d`."""
+ type = d[ 'type' ]
+ assert type in self.module_types
+ return self.module_types[ type ].from_dict( trans, d, **kwargs )
+ def from_workflow_step( self, trans, tools_metadata, step ):
+ """Return module initialized from the WorkflowStep object `step`."""
+ type = step.type
+ return self.module_types[ type ].from_workflow_step( trans, tools_metadata, step )
+
+module_factory = RepoWorkflowModuleFactory( dict( data_input=RepoInputDataModule, tool=RepoToolModule ) )
+
+class WorkflowController( BaseUIController ):
+ @web.expose
+ def view_workflow( self, trans, **kwd ):
+ repository_metadata_id = kwd.get( 'repository_metadata_id', '' )
+ workflow_name = kwd.get( 'workflow_name', '' )
+ if workflow_name:
+ workflow_name = decode( workflow_name )
+ webapp = kwd.get( 'webapp', 'community' )
+ message = kwd.get( 'message', '' )
+ status = kwd.get( 'status', 'done' )
+ repository_metadata = get_repository_metadata_by_id( trans, repository_metadata_id )
+ repository = get_repository( trans, trans.security.encode_id( repository_metadata.repository_id ) )
+ return trans.fill_template( "/webapps/community/repository/view_workflow.mako",
+ repository=repository,
+ changeset_revision=repository_metadata.changeset_revision,
+ repository_metadata_id=repository_metadata_id,
+ workflow_name=workflow_name,
+ webapp=webapp,
+ message=message,
+ status=status )
+ @web.expose
+ def generate_workflow_image( self, trans, repository_metadata_id, workflow_name, webapp='community' ):
+ repository_metadata = get_repository_metadata_by_id( trans, repository_metadata_id )
+ metadata = repository_metadata.metadata
+ workflow_name = decode( workflow_name )
+ for workflow_dict in metadata[ 'workflows' ]:
+ if workflow_dict[ 'name' ] == workflow_name:
+ break
+ if 'tools' in metadata:
+ tools_metadata = metadata[ 'tools' ]
+ else:
+ tools_metadata = []
+ workflow, missing_tool_tups = self.__workflow_from_dict( trans, workflow_dict, tools_metadata )
+ data = []
+ canvas = svgfig.canvas( style="stroke:black; fill:none; stroke-width:1px; stroke-linejoin:round; text-anchor:left" )
+ text = svgfig.SVG( "g" )
+ connectors = svgfig.SVG( "g" )
+ boxes = svgfig.SVG( "g" )
+ svgfig.Text.defaults[ "font-size" ] = "10px"
+ in_pos = {}
+ out_pos = {}
+ margin = 5
+ # Spacing between input/outputs.
+ line_px = 16
+ # Store px width for boxes of each step.
+ widths = {}
+ max_width, max_x, max_y = 0, 0, 0
+ for step in workflow.steps:
+ step.upgrade_messages = {}
+ module = module_factory.from_workflow_step( trans, tools_metadata, step )
+ tool_errors = module.type == 'tool' and not module.tool
+ module_data_inputs = self.__get_data_inputs( step, module )
+ module_data_outputs = self.__get_data_outputs( step, module, workflow.steps )
+ step_dict = {
+ 'id' : step.order_index,
+ 'data_inputs' : module_data_inputs,
+ 'data_outputs' : module_data_outputs,
+ 'position' : step.position,
+ 'tool_errors' : tool_errors
+ }
+ input_conn_dict = {}
+ for conn in step.input_connections:
+ input_conn_dict[ conn.input_name ] = dict( id=conn.output_step.order_index, output_name=conn.output_name )
+ step_dict[ 'input_connections' ] = input_conn_dict
+ data.append( step_dict )
+ x, y = step.position[ 'left' ], step.position[ 'top' ]
+ count = 0
+ module_name = self.__get_name( module, missing_tool_tups )
+ max_len = len( module_name ) * 1.5
+ text.append( svgfig.Text( x, y + 20, module_name, **{ "font-size": "14px" } ).SVG() )
+ y += 45
+ for di in module_data_inputs:
+ cur_y = y + count * line_px
+ if step.order_index not in in_pos:
+ in_pos[ step.order_index ] = {}
+ in_pos[ step.order_index ][ di[ 'name' ] ] = ( x, cur_y )
+ text.append( svgfig.Text( x, cur_y, di[ 'label' ] ).SVG() )
+ count += 1
+ max_len = max( max_len, len( di[ 'label' ] ) )
+ if len( module.get_data_inputs() ) > 0:
+ y += 15
+ for do in module_data_outputs:
+ cur_y = y + count * line_px
+ if step.order_index not in out_pos:
+ out_pos[ step.order_index ] = {}
+ out_pos[ step.order_index ][ do[ 'name' ] ] = ( x, cur_y )
+ text.append( svgfig.Text( x, cur_y, do[ 'name' ] ).SVG() )
+ count += 1
+ max_len = max( max_len, len( do['name' ] ) )
+ widths[ step.order_index ] = max_len * 5.5
+ max_x = max( max_x, step.position[ 'left' ] )
+ max_y = max( max_y, step.position[ 'top' ] )
+ max_width = max( max_width, widths[ step.order_index ] )
+ for step_dict in data:
+ tool_unavailable = step_dict[ 'tool_errors' ]
+ width = widths[ step_dict[ 'id' ] ]
+ x, y = step_dict[ 'position' ][ 'left' ], step_dict[ 'position' ][ 'top' ]
+ if tool_unavailable:
+ fill = "#EBBCB2"
+ else:
+ fill = "#EBD9B2"
+ boxes.append( svgfig.Rect( x - margin, y, x + width - margin, y + 30, fill=fill ).SVG() )
+ box_height = ( len( step_dict[ 'data_inputs' ] ) + len( step_dict[ 'data_outputs' ] ) ) * line_px + margin
+ # Draw separator line.
+ if len( step_dict[ 'data_inputs' ] ) > 0:
+ box_height += 15
+ sep_y = y + len( step_dict[ 'data_inputs' ] ) * line_px + 40
+ text.append( svgfig.Line( x - margin, sep_y, x + width - margin, sep_y ).SVG() )
+ # Define an input/output box.
+ boxes.append( svgfig.Rect( x - margin, y + 30, x + width - margin, y + 30 + box_height, fill="#ffffff" ).SVG() )
+ for conn, output_dict in step_dict[ 'input_connections' ].iteritems():
+ in_coords = in_pos[ step_dict[ 'id' ] ][ conn ]
+ out_conn_pos = out_pos[ output_dict[ 'id' ] ][ output_dict[ 'output_name' ] ]
+ adjusted = ( out_conn_pos[ 0 ] + widths[ output_dict[ 'id' ] ], out_conn_pos[ 1 ] )
+ text.append( svgfig.SVG( "circle",
+ cx=out_conn_pos[ 0 ] + widths[ output_dict[ 'id' ] ] - margin,
+ cy=out_conn_pos[ 1 ] - margin,
+ r = 5,
+ fill="#ffffff" ) )
+ connectors.append( svgfig.Line( adjusted[ 0 ],
+ adjusted[ 1 ] - margin,
+ in_coords[ 0 ] - 10,
+ in_coords[ 1 ],
+ arrow_end = "true" ).SVG() )
+ canvas.append( connectors )
+ canvas.append( boxes )
+ canvas.append( text )
+ width, height = ( max_x + max_width + 50 ), max_y + 300
+ canvas[ 'width' ] = "%s px" % width
+ canvas[ 'height' ] = "%s px" % height
+ canvas[ 'viewBox' ] = "0 0 %s %s" % ( width, height )
+ trans.response.set_content_type( "image/svg+xml" )
+ return canvas.standalone_xml()
+ def __get_name( self, module, missing_tool_tups ):
+ module_name = module.get_name()
+ if module.type == 'tool' and module_name == 'unavailable':
+ for missing_tool_tup in missing_tool_tups:
+ missing_tool_id, missing_tool_name, missing_tool_version = missing_tool_tup
+ if missing_tool_id == module.tool_id:
+ module_name = '%s' % missing_tool_name
+ return module_name
+ def __get_data_inputs( self, step, module ):
+ if module.type == 'tool':
+ if module.tool:
+ return module.get_data_inputs()
+ else:
+ data_inputs = []
+ for wfsc in step.input_connections:
+ data_inputs_dict = {}
+ data_inputs_dict[ 'extensions' ] = [ '' ]
+ data_inputs_dict[ 'name' ] = wfsc.input_name
+ data_inputs_dict[ 'label' ] = 'Unknown'
+ data_inputs.append( data_inputs_dict )
+ return data_inputs
+ return module.get_data_inputs()
+ def __get_data_outputs( self, step, module, steps ):
+ if module.type == 'tool':
+ if module.tool:
+ return module.get_data_outputs()
+ else:
+ data_outputs = []
+ data_outputs_dict = {}
+ data_outputs_dict[ 'extensions' ] = [ 'input' ]
+ found = False
+ for workflow_step in steps:
+ for wfsc in workflow_step.input_connections:
+ if step.name == wfsc.output_step.name:
+ data_outputs_dict[ 'name' ] = wfsc.output_name
+ found = True
+ break
+ if found:
+ break
+ if not found:
+ # We're at the last step of the workflow.
+ data_outputs_dict[ 'name' ] = 'output'
+ data_outputs.append( data_outputs_dict )
+ return data_outputs
+ return module.get_data_outputs()
+ def __workflow_from_dict( self, trans, data, tools_metadata ):
+ """Creates and returns workflow object from a dictionary."""
+ trans.workflow_building_mode = True
+ workflow = model.Workflow()
+ workflow.name = data[ 'name' ]
+ workflow.has_errors = False
+ steps = []
+ # Keep ids for each step that we need to use to make connections.
+ steps_by_external_id = {}
+ # Keep track of tools required by the workflow that are not available in
+ # the tool shed repository. Each tuple in the list of missing_tool_tups
+ # will be ( tool_id, tool_name, tool_version ).
+ missing_tool_tups = []
+ # First pass to build step objects and populate basic values
+ for key, step_dict in data[ 'steps' ].iteritems():
+ # Create the model class for the step
+ step = model.WorkflowStep()
+ step.name = step_dict[ 'name' ]
+ step.position = step_dict[ 'position' ]
+ module = module_factory.from_dict( trans, step_dict, tools_metadata=tools_metadata, secure=False )
+ if module.type == 'tool' and module.tool is None:
+ # A required tool is not available in the current repository.
+ step.tool_errors = 'unavailable'
+ missing_tool_tup = ( step_dict[ 'tool_id' ], step_dict[ 'name' ], step_dict[ 'tool_version' ] )
+ if missing_tool_tup not in missing_tool_tups:
+ missing_tool_tups.append( missing_tool_tup )
+ module.save_to_step( step )
+ if step.tool_errors:
+ workflow.has_errors = True
+ # Stick this in the step temporarily.
+ step.temp_input_connections = step_dict[ 'input_connections' ]
+ # Unpack and add post-job actions.
+ post_job_actions = step_dict.get( 'post_job_actions', {} )
+ for name, pja_dict in post_job_actions.items():
+ pja = PostJobAction( pja_dict[ 'action_type' ],
+ step, pja_dict[ 'output_name' ],
+ pja_dict[ 'action_arguments' ] )
+ steps.append( step )
+ steps_by_external_id[ step_dict[ 'id' ] ] = step
+ # Second pass to deal with connections between steps.
+ for step in steps:
+ # Input connections.
+ for input_name, conn_dict in step.temp_input_connections.iteritems():
+ if conn_dict:
+ output_step = steps_by_external_id[ conn_dict[ 'id' ] ]
+ conn = model.WorkflowStepConnection()
+ conn.input_step = step
+ conn.input_name = input_name
+ conn.output_step = output_step
+ conn.output_name = conn_dict[ 'output_name' ]
+ step.input_connections.append( conn )
+ del step.temp_input_connections
+ # Order the steps if possible.
+ attach_ordered_steps( workflow, steps )
+ return workflow, missing_tool_tups
+ @web.expose
+ def import_workflow( self, trans, **kwd ):
+ repository_metadata_id = kwd.get( 'repository_metadata_id', '' )
+ workflow_name = kwd.get( 'workflow_name', '' )
+ if workflow_name:
+ workflow_name = decode( workflow_name )
+ webapp = kwd.get( 'webapp', 'community' )
+ message = kwd.get( 'message', '' )
+ status = kwd.get( 'status', 'done' )
+ repository_metadata = get_repository_metadata_by_id( trans, repository_metadata_id )
+ workflows = repository_metadata.metadata[ 'workflows' ]
+ workflow_data = None
+ for workflow_data in workflows:
+ if workflow_data[ 'name' ] == workflow_name:
+ break
+ if workflow_data:
+ if kwd.get( 'open_for_url', False ):
+ tmp_fd, tmp_fname = tempfile.mkstemp()
+ to_file = open( tmp_fname, 'wb' )
+ to_file.write( to_json_string( workflow_data ) )
+ return open( tmp_fname )
+ galaxy_url = trans.get_cookie( name='toolshedgalaxyurl' )
+ # TODO: support https in the following url.
+ url = 'http://%s/workflow/import_workflow?tool_shed_url=%s&repository_metadata_id=%s&workflow_name=%s&webapp=%s' % \
+ ( galaxy_url, trans.request.host, repository_metadata_id, encode( workflow_name ), webapp )
+ return trans.response.send_redirect( url )
+ return trans.response.send_redirect( web.url_for( controller='workflow',
+ action='view_workflow',
+ message=message,
+ status=status ) )
diff -r 125d735c689ee60ad9bd9601c7a22738ba3523de -r ab8fb6d1f56d6677ccd9dbfa137acf6efbc4d245 lib/galaxy/webapps/community/model/__init__.py
--- a/lib/galaxy/webapps/community/model/__init__.py
+++ b/lib/galaxy/webapps/community/model/__init__.py
@@ -204,6 +204,34 @@
self.value = None
self.user_value = None
+class Workflow( object ):
+ def __init__( self ):
+ self.user = None
+ self.name = None
+ self.has_cycles = None
+ self.has_errors = None
+ self.steps = []
+
+class WorkflowStep( object ):
+ def __init__( self ):
+ self.id = None
+ self.type = None
+ self.name = None
+ self.tool_id = None
+ self.tool_inputs = None
+ self.tool_errors = None
+ self.position = None
+ self.input_connections = []
+ #self.output_connections = []
+ self.config = None
+
+class WorkflowStepConnection( object ):
+ def __init__( self ):
+ self.output_step = None
+ self.output_name = None
+ self.input_step = None
+ self.input_name = None
+
## ---- Utility methods -------------------------------------------------------
def sort_by_attr( seq, attr ):
"""
diff -r 125d735c689ee60ad9bd9601c7a22738ba3523de -r ab8fb6d1f56d6677ccd9dbfa137acf6efbc4d245 lib/galaxy/workflow/modules.py
--- a/lib/galaxy/workflow/modules.py
+++ b/lib/galaxy/workflow/modules.py
@@ -205,14 +205,14 @@
def from_workflow_step( Class, trans, step ):
tool_id = step.tool_id
install_tool_id = None
- if tool_id not in trans.app.toolbox.tools_by_id:
+ if trans.app.toolbox and tool_id not in trans.app.toolbox.tools_by_id:
# The id value of tools installed from a Galaxy tool shed is a guid, but
# these tool's old_id attribute should contain what we're looking for.
for available_tool_id, available_tool in trans.app.toolbox.tools_by_id.items():
if tool_id == available_tool.old_id:
install_tool_id = available_tool_id
break
- if tool_id in trans.app.toolbox.tools_by_id or install_tool_id:
+ if ( trans.app.toolbox and tool_id in trans.app.toolbox.tools_by_id ) or install_tool_id:
module = Class( trans, tool_id )
module.state = DefaultToolState()
module.state.inputs = module.tool.params_from_strings( step.tool_inputs, trans.app, ignore_errors=True )
@@ -247,7 +247,9 @@
action_arguments = None
n_p = PostJobAction(v['action_type'], step, output_name, action_arguments)
def get_name( self ):
- return self.tool.name
+ if self.tool:
+ return self.tool.name
+ return 'unavailable'
def get_tool_id( self ):
return self.tool_id
def get_tool_version( self ):
diff -r 125d735c689ee60ad9bd9601c7a22738ba3523de -r ab8fb6d1f56d6677ccd9dbfa137acf6efbc4d245 static/scripts/trackster.js
--- a/static/scripts/trackster.js
+++ b/static/scripts/trackster.js
@@ -1189,6 +1189,10 @@
}
},
go_to: function(str) {
+ // Preprocess str to remove spaces and commas.
+ str = str.replace(/ |,/g, "");
+
+ // Go to new location.
var view = this,
new_low,
new_high,
@@ -1199,8 +1203,8 @@
if (pos !== undefined) {
try {
var pos_split = pos.split("-");
- new_low = parseInt(pos_split[0].replace(/,/g, ""), 10);
- new_high = parseInt(pos_split[1].replace(/,/g, ""), 10);
+ new_low = parseInt(pos_split[0], 10);
+ new_high = parseInt(pos_split[1], 10);
} catch (e) {
return false;
}
diff -r 125d735c689ee60ad9bd9601c7a22738ba3523de -r ab8fb6d1f56d6677ccd9dbfa137acf6efbc4d245 templates/grid_base.mako
--- a/templates/grid_base.mako
+++ b/templates/grid_base.mako
@@ -744,7 +744,7 @@
%if grid.global_actions:
<ul class="manage-table-actions">
- %if len( grid.global_actions ) < 4:
+ %if len( grid.global_actions ) < 3:
%for action in grid.global_actions:
<li><a class="action-button" href="${h.url_for( **action.url_args )}">${action.label}</a></li>
%endfor
diff -r 125d735c689ee60ad9bd9601c7a22738ba3523de -r ab8fb6d1f56d6677ccd9dbfa137acf6efbc4d245 templates/root/history_common.mako
--- a/templates/root/history_common.mako
+++ b/templates/root/history_common.mako
@@ -96,7 +96,7 @@
display_url = h.url_for( controller='dataset', action='display', dataset_id=dataset_id, preview=True, filename='' )
%>
%if data.purged:
- <span class="icon-button display_disabled tooltip" title="Cannoy display datasets removed from disk"></span>
+ <span class="icon-button display_disabled tooltip" title="Cannot display datasets removed from disk"></span>
%else:
<a class="icon-button display tooltip" title="Display data in browser" href="${display_url}"
%if for_editing:
@@ -150,6 +150,9 @@
%endif
</div>
%elif data_state == "error":
+ %if not data.purged:
+ <div>${data.get_size( nice_size=True )}</div>
+ %endif
<div>
An error occurred running this job: <i>${data.display_info().strip()}</i></div>
diff -r 125d735c689ee60ad9bd9601c7a22738ba3523de -r ab8fb6d1f56d6677ccd9dbfa137acf6efbc4d245 templates/tracks/browser.mako
--- a/templates/tracks/browser.mako
+++ b/templates/tracks/browser.mako
@@ -212,10 +212,14 @@
'dbkey': view.dbkey,
'payload': JSON.stringify(payload)
},
- success: function(vis_id) {
- view.vis_id = vis_id;
+ dataType: "json",
+ success: function(vis_info) {
+ hide_modal();
+ view.vis_id = vis_info.vis_id;
view.has_changes = false;
- hide_modal();
+
+ // Needed to set URL when first saving a visualization.
+ window.history.pushState({}, "", vis_info.url);
},
error: function() { alert("Could not save visualization"); }
});
diff -r 125d735c689ee60ad9bd9601c7a22738ba3523de -r ab8fb6d1f56d6677ccd9dbfa137acf6efbc4d245 templates/webapps/community/index.mako
--- a/templates/webapps/community/index.mako
+++ b/templates/webapps/community/index.mako
@@ -44,6 +44,20 @@
<div class="page-container" style="padding: 10px;"><div class="toolMenu"><div class="toolSectionList">
+ %if repository_metadata:
+ <div class="toolSectionPad"></div>
+ <div class="toolSectionTitle">
+ Search
+ </div>
+ <div class="toolSectionBody">
+ <div class="toolTitle">
+ <a target="galaxy_main" href="${h.url_for( controller='repository', action='find_tools', webapp='community' )}">Search for valid tools</a>
+ </div>
+ <div class="toolTitle">
+ <a target="galaxy_main" href="${h.url_for( controller='repository', action='find_workflows', webapp='community' )}">Search for workflows</a>
+ </div>
+ </div>
+ %endif
<div class="toolSectionPad"></div><div class="toolSectionTitle">
Repositories
@@ -61,11 +75,6 @@
<a target="galaxy_main" href="${h.url_for( controller='repository', action='browse_repositories', operation='my_repositories', webapp='community' )}">Browse my repositories</a></div>
%endif
- %if repository_metadata:
- <div class="toolTitle">
- <a target="galaxy_main" href="${h.url_for( controller='repository', action='find_tools', webapp='community' )}">Search for valid tools</a>
- </div>
- %endif
</div></div><div class="toolSectionBody">
diff -r 125d735c689ee60ad9bd9601c7a22738ba3523de -r ab8fb6d1f56d6677ccd9dbfa137acf6efbc4d245 templates/webapps/community/repository/common.mako
--- a/templates/webapps/community/repository/common.mako
+++ b/templates/webapps/community/repository/common.mako
@@ -83,7 +83,8 @@
hg clone <a href="${clone_str}">${clone_str}</a></%def>
-<%def name="render_repository_tools_and_workflows( metadata, can_set_metadata=False, webapp='community' )">
+<%def name="render_repository_tools_and_workflows( repository_metadata_id, metadata, can_set_metadata=False, webapp='community' )">
+ <% from galaxy.webapps.community.controllers.common import encode, decode %>
%if metadata or can_set_metadata:
<p/><div class="toolForm">
@@ -160,14 +161,34 @@
<table class="grid"><tr><td><b>name</b></td>
+ <td><b>steps</b></td><td><b>format-version</b></td><td><b>annotation</b></td></tr>
%for workflow_dict in workflow_dicts:
+ <%
+ workflow_name = workflow_dict[ 'name' ]
+ if 'steps' in workflow_dict:
+ ## Initially steps were not stored in the metadata record.
+ steps = workflow_dict[ 'steps' ]
+ else:
+ steps = []
+ format_version = workflow_dict[ 'format-version' ]
+ annotation = workflow_dict[ 'annotation' ]
+ %><tr>
- <td>${workflow_dict[ 'name' ]}</td>
- <td>${workflow_dict[ 'format-version' ]}</td>
- <td>${workflow_dict[ 'annotation' ]}</td>
+ <td>
+ <a href="${h.url_for( controller='workflow', action='view_workflow', repository_metadata_id=repository_metadata_id, workflow_name=encode( workflow_name ), webapp=webapp )}">${workflow_name}</a>
+ </td>
+ <td>
+ %if 'steps' in workflow_dict:
+ ${len( steps )}
+ %else:
+ unknown
+ %endif
+ </td>
+ <td>${format_version}</td>
+ <td>${annotation}</td></tr>
%endfor
</table>
diff -r 125d735c689ee60ad9bd9601c7a22738ba3523de -r ab8fb6d1f56d6677ccd9dbfa137acf6efbc4d245 templates/webapps/community/repository/find_tools.mako
--- a/templates/webapps/community/repository/find_tools.mako
+++ b/templates/webapps/community/repository/find_tools.mako
@@ -14,6 +14,7 @@
<br/><br/><ul class="manage-table-actions"><li><a class="action-button" href="${h.url_for( controller='repository', action='browse_valid_repositories', webapp=webapp )}">Browse valid repositories</a></li>
+ <li><a class="action-button" href="${h.url_for( controller='repository', action='find_workflows', webapp=webapp )}">Search for workflows</a></li></ul>
%endif
diff -r 125d735c689ee60ad9bd9601c7a22738ba3523de -r ab8fb6d1f56d6677ccd9dbfa137acf6efbc4d245 templates/webapps/community/repository/find_workflows.mako
--- /dev/null
+++ b/templates/webapps/community/repository/find_workflows.mako
@@ -0,0 +1,53 @@
+<%inherit file="/base.mako"/>
+<%namespace file="/message.mako" import="render_msg" />
+
+<%!
+ def inherit(context):
+ if context.get('use_panels'):
+ return '/webapps/community/base_panels.mako'
+ else:
+ return '/base.mako'
+%>
+<%inherit file="${inherit(context)}"/>
+
+%if webapp == 'galaxy':
+ <br/><br/>
+ <ul class="manage-table-actions">
+ <li><a class="action-button" href="${h.url_for( controller='repository', action='browse_valid_repositories', webapp=webapp )}">Browse valid repositories</a></li>
+ <a class="action-button" href="${h.url_for( controller='repository', action='find_tools', webapp=webapp )}">Search for valid tools</a>
+ </ul>
+%endif
+
+%if message:
+ ${render_msg( message, status )}
+%endif
+
+<div class="toolForm">
+ <div class="toolFormTitle">Search repositories for workflows</div>
+ <div class="toolFormBody">
+ <div class="form-row">
+ Enter a workflow name to find repositories that contain workflows matching the search criteria.<br/><br/>
+ Comma-separated strings may be entered to expand search criteria.
+ </div>
+ <div style="clear: both"></div>
+ <form name="find_workflows" id="find_workflows" action="${h.url_for( controller='repository', action='find_workflows', webapp=webapp )}" method="post" >
+ <div style="clear: both"></div>
+ <div class="form-row">
+ <label>Workflow name:</label>
+ <input name="workflow_name" type="textfield" value="${workflow_name}" size="40"/>
+ </div>
+ <div style="clear: both"></div>
+ <div class="form-row">
+ <label>Exact matches only:</label>
+ ${exact_matches_check_box.get_html()}
+ <div class="toolParamHelp" style="clear: both;">
+ Check the box to match text exactly (text case doesn't matter as all strings are forced to lower case).
+ </div>
+ </div>
+ <div style="clear: both"></div>
+ <div class="form-row">
+ <input type="submit" value="Search repositories"/>
+ </div>
+ </form>
+ </div>
+</div>
diff -r 125d735c689ee60ad9bd9601c7a22738ba3523de -r ab8fb6d1f56d6677ccd9dbfa137acf6efbc4d245 templates/webapps/community/repository/manage_repository.mako
--- a/templates/webapps/community/repository/manage_repository.mako
+++ b/templates/webapps/community/repository/manage_repository.mako
@@ -184,7 +184,7 @@
</form></div></div>
-${render_repository_tools_and_workflows( metadata, can_set_metadata=True )}
+${render_repository_tools_and_workflows( repository_metadata_id, metadata, can_set_metadata=True )}
<p/><div class="toolForm"><div class="toolFormTitle">Manage categories</div>
diff -r 125d735c689ee60ad9bd9601c7a22738ba3523de -r ab8fb6d1f56d6677ccd9dbfa137acf6efbc4d245 templates/webapps/community/repository/preview_tools_in_changeset.mako
--- a/templates/webapps/community/repository/preview_tools_in_changeset.mako
+++ b/templates/webapps/community/repository/preview_tools_in_changeset.mako
@@ -69,6 +69,7 @@
<div popupmenu="repository-${repository.id}-popup"><a class="action-button" href="${h.url_for( controller='repository', action='browse_valid_repositories', webapp=webapp )}">Browse valid repositories</a><a class="action-button" href="${h.url_for( controller='repository', action='find_tools', webapp=webapp )}">Search for valid tools</a>
+ <a class="action-button" href="${h.url_for( controller='repository', action='find_workflows', webapp=webapp )}">Search for workflows</a></div></ul>
@@ -103,4 +104,4 @@
</div></div><p/>
-${render_repository_tools_and_workflows( metadata, webapp=webapp )}
+${render_repository_tools_and_workflows( repository_metadata_id, metadata, webapp=webapp )}
diff -r 125d735c689ee60ad9bd9601c7a22738ba3523de -r ab8fb6d1f56d6677ccd9dbfa137acf6efbc4d245 templates/webapps/community/repository/tool_form.mako
--- a/templates/webapps/community/repository/tool_form.mako
+++ b/templates/webapps/community/repository/tool_form.mako
@@ -116,6 +116,7 @@
<div popupmenu="repository-${repository.id}-popup"><a class="action-button" href="${h.url_for( controller='repository', action='browse_valid_repositories', webapp=webapp )}">Browse valid repositories</a><a class="action-button" href="${h.url_for( controller='repository', action='find_tools', webapp=webapp )}">Search for valid tools</a>
+ <a class="action-button" href="${h.url_for( controller='repository', action='find_workflows', webapp=webapp )}">Search for workflows</a></div>
%else:
%if is_new:
diff -r 125d735c689ee60ad9bd9601c7a22738ba3523de -r ab8fb6d1f56d6677ccd9dbfa137acf6efbc4d245 templates/webapps/community/repository/view_repository.mako
--- a/templates/webapps/community/repository/view_repository.mako
+++ b/templates/webapps/community/repository/view_repository.mako
@@ -99,6 +99,7 @@
<div popupmenu="repository-${repository.id}-popup"><a class="action-button" href="${h.url_for( controller='repository', action='browse_valid_repositories', webapp=webapp )}">Browse valid repositories</a><a class="action-button" href="${h.url_for( controller='repository', action='find_tools', webapp=webapp )}">Search for valid tools</a>
+ <a class="action-button" href="${h.url_for( controller='repository', action='find_workflows', webapp=webapp )}">Search for workflows</a></div>
%endif
</ul>
@@ -185,7 +186,7 @@
%endif
</div></div>
-${render_repository_tools_and_workflows( metadata, webapp=webapp )}
+${render_repository_tools_and_workflows( repository_metadata_id, metadata, webapp=webapp )}
%if repository.categories:
<p/><div class="toolForm">
diff -r 125d735c689ee60ad9bd9601c7a22738ba3523de -r ab8fb6d1f56d6677ccd9dbfa137acf6efbc4d245 templates/webapps/community/repository/view_tool_metadata.mako
--- a/templates/webapps/community/repository/view_tool_metadata.mako
+++ b/templates/webapps/community/repository/view_tool_metadata.mako
@@ -39,6 +39,7 @@
<div popupmenu="repository-${repository.id}-popup"><a class="action-button" href="${h.url_for( controller='repository', action='browse_valid_repositories', webapp=webapp )}">Browse valid repositories</a><a class="action-button" href="${h.url_for( controller='repository', action='find_tools', webapp=webapp )}">Search for valid tools</a>
+ <a class="action-button" href="${h.url_for( controller='repository', action='find_workflows', webapp=webapp )}">Search for workflows</a></div>
%else:
%if is_new:
diff -r 125d735c689ee60ad9bd9601c7a22738ba3523de -r ab8fb6d1f56d6677ccd9dbfa137acf6efbc4d245 templates/webapps/community/repository/view_workflow.mako
--- /dev/null
+++ b/templates/webapps/community/repository/view_workflow.mako
@@ -0,0 +1,105 @@
+<%inherit file="/base.mako"/>
+<%namespace file="/message.mako" import="render_msg" />
+<%namespace file="/webapps/community/common/common.mako" import="*" />
+<%namespace file="/webapps/community/repository/common.mako" import="*" />
+
+<%
+ from galaxy.web.framework.helpers import time_ago
+ from galaxy.webapps.community.controllers.common import encode
+
+ in_tool_shed = webapp == 'community'
+ is_admin = trans.user_is_admin()
+ is_new = repository.is_new
+ can_manage = is_admin or trans.user == repository.user
+ can_contact_owner = in_tool_shed and trans.user and trans.user != repository.user
+ can_push = in_tool_shed and trans.app.security_agent.can_push( trans.user, repository )
+ can_upload = can_push
+ can_download = in_tool_shed and not is_new and ( not is_malicious or can_push )
+ can_browse_contents = in_tool_shed and not is_new
+ can_set_metadata = in_tool_shed and not is_new
+ can_rate = in_tool_shed and not is_new and trans.user and repository.user != trans.user
+ can_view_change_log = in_tool_shed and not is_new
+ if can_push:
+ browse_label = 'Browse or delete repository files'
+ else:
+ browse_label = 'Browse repository files'
+%>
+
+<%!
+ def inherit(context):
+ if context.get('use_panels'):
+ return '/webapps/community/base_panels.mako'
+ else:
+ return '/base.mako'
+%>
+<%inherit file="${inherit(context)}"/>
+
+<%def name="render_workflow( repository_metadata_id, workflow_name, webapp )">
+ <% center_url = h.url_for( controller='workflow', action='generate_workflow_image', repository_metadata_id=repository_metadata_id, workflow_name=encode( workflow_name ), webapp=webapp ) %>
+ <iframe name="galaxy_main" id="galaxy_main" frameborder="0" style="position: absolute; width: 100%; height: 100%;" src="${center_url}"></iframe>
+</%def>
+
+<br/><br/>
+<ul class="manage-table-actions">
+ %if in_tool_shed:
+ %if is_new and can_upload:
+ <a class="action-button" href="${h.url_for( controller='upload', action='upload', repository_id=trans.security.encode_id( repository.id ), webapp='community' )}">Upload files to repository</a>
+ %else:
+ <li><a class="action-button" id="repository-${repository.id}-popup" class="menubutton">Repository Actions</a></li>
+ <div popupmenu="repository-${repository.id}-popup">
+ %if can_upload:
+ <a class="action-button" href="${h.url_for( controller='upload', action='upload', repository_id=trans.security.encode_id( repository.id ), webapp='community' )}">Upload files to repository</a>
+ %endif
+ %if can_manage:
+ <a class="action-button" href="${h.url_for( controller='repository', action='manage_repository', id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip )}">Manage repository</a>
+ %else:
+ <a class="action-button" href="${h.url_for( controller='repository', action='view_repository', id=trans.app.security.encode_id( repository.id ), changeset_revision=repository.tip, webapp='community' )}">View repository</a>
+ %endif
+ %if can_view_change_log:
+ <a class="action-button" href="${h.url_for( controller='repository', action='view_changelog', id=trans.app.security.encode_id( repository.id ), webapp='community' )}">View change log</a>
+ %endif
+ %if can_rate:
+ <a class="action-button" href="${h.url_for( controller='repository', action='rate_repository', id=trans.app.security.encode_id( repository.id ) )}">Rate repository</a>
+ %endif
+ %if can_browse_contents:
+ <a class="action-button" href="${h.url_for( controller='repository', action='browse_repository', id=trans.app.security.encode_id( repository.id ), webapp='community' )}">${browse_label}</a>
+ %endif
+ %if can_contact_owner:
+ <a class="action-button" href="${h.url_for( controller='repository', action='contact_owner', id=trans.security.encode_id( repository.id ), webapp='community' )}">Contact repository owner</a>
+ %endif
+ %if can_download:
+ <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision, file_type='gz' )}">Download as a .tar.gz file</a>
+ <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision, file_type='bz2' )}">Download as a .tar.bz2 file</a>
+ <a class="action-button" href="${h.url_for( controller='repository', action='download', repository_id=trans.app.security.encode_id( repository.id ), changeset_revision=changeset_revision, file_type='zip' )}">Download as a zip file</a>
+ %endif
+ </div>
+ %endif
+ %else:
+ <li><a class="action-button" id="repository-${repository.id}-popup" class="menubutton">Repository Actions</a></li>
+ <div popupmenu="repository-${repository.id}-popup">
+ <li><a class="action-button" href="${h.url_for( controller='workflow', action='import_workflow', repository_metadata_id=repository_metadata_id, workflow_name=encode( workflow_name ), webapp=webapp )}">Import workflow to local Galaxy</a></li>
+ <li><a class="action-button" href="${h.url_for( controller='repository', action='install_repository_revision', repository_id=trans.security.encode_id( repository.id ), webapp=webapp, changeset_revision=changeset_revision )}">Install repository to local Galaxy</a></li>
+ </div>
+ <li><a class="action-button" id="toolshed-${repository.id}-popup" class="menubutton">Tool Shed Actions</a></li>
+ <div popupmenu="toolshed-${repository.id}-popup">
+ <a class="action-button" href="${h.url_for( controller='repository', action='browse_valid_repositories', webapp=webapp )}">Browse valid repositories</a>
+ <a class="action-button" href="${h.url_for( controller='repository', action='find_tools', webapp=webapp )}">Search for valid tools</a>
+ <a class="action-button" href="${h.url_for( controller='repository', action='find_workflows', webapp=webapp )}">Search for workflows</a>
+ </div>
+ %endif
+</ul>
+
+%if message:
+ ${render_msg( message, status )}
+%endif
+
+<div class="toolFormTitle">${workflow_name}</div>
+<div class="form-row">
+ <b>Boxes are red when tools are not available in this repository</b>
+ <div class="toolParamHelp" style="clear: both;">
+ (this page displays SVG graphics)
+ </div>
+</div>
+<br clear="left"/>
+
+${render_workflow( repository_metadata_id, workflow_name, webapp )}
diff -r 125d735c689ee60ad9bd9601c7a22738ba3523de -r ab8fb6d1f56d6677ccd9dbfa137acf6efbc4d245 templates/webapps/galaxy/admin/index.mako
--- a/templates/webapps/galaxy/admin/index.mako
+++ b/templates/webapps/galaxy/admin/index.mako
@@ -73,7 +73,7 @@
<div class="toolSectionTitle">Tool sheds</div><div class="toolSectionBody"><div class="toolSectionBg">
- <div class="toolTitle"><a href="${h.url_for( controller='admin', action='browse_tool_sheds' )}" target="galaxy_main">Browse tool sheds</a></div>
+ <div class="toolTitle"><a href="${h.url_for( controller='admin', action='browse_tool_sheds' )}" target="galaxy_main">Search and browse tool sheds</a></div></div></div>
%endif
diff -r 125d735c689ee60ad9bd9601c7a22738ba3523de -r ab8fb6d1f56d6677ccd9dbfa137acf6efbc4d245 templates/webapps/galaxy/admin/tool_sheds.mako
--- a/templates/webapps/galaxy/admin/tool_sheds.mako
+++ b/templates/webapps/galaxy/admin/tool_sheds.mako
@@ -27,6 +27,7 @@
<div popupmenu="dataset-${shed_id}-popup"><a class="action-button" href="${h.url_for( controller='admin', action='browse_tool_shed', tool_shed_url=url )}">Browse valid repositories</a><a class="action-button" href="${h.url_for( controller='admin', action='find_tools_in_tool_shed', tool_shed_url=url )}">Search for valid tools</a>
+ <a class="action-button" href="${h.url_for( controller='admin', action='find_workflows_in_tool_shed', tool_shed_url=url )}">Search for workflows</a></div></td></tr>
diff -r 125d735c689ee60ad9bd9601c7a22738ba3523de -r ab8fb6d1f56d6677ccd9dbfa137acf6efbc4d245 templates/workflow/display.mako
--- a/templates/workflow/display.mako
+++ b/templates/workflow/display.mako
@@ -1,7 +1,7 @@
<%inherit file="/display_base.mako"/><%namespace file="/display_common.mako" import="render_message" />
-<%!
+<%
from galaxy.tools.parameters import DataToolParameter, RuntimeValue
from galaxy.web import form_builder
%>
@@ -82,7 +82,17 @@
%for i, step in enumerate( steps ):
<tr><td>
%if step.type == 'tool' or step.type is None:
- <% tool = app.toolbox.tools_by_id[step.tool_id] %>
+ <%
+ try:
+ tool = trans.app.toolbox.tools_by_id[ step.tool_id ]
+ except KeyError, e:
+ # The id value of tools installed from a Galaxy tool shed is a guid, but
+ # these tool's old_id attribute should contain what we're looking for.
+ for available_tool_id, available_tool in trans.app.toolbox.tools_by_id.items():
+ if step.tool_id == available_tool.old_id:
+ tool = available_tool
+ break
+ %><div class="toolForm"><div class="toolFormTitle">Step ${int(step.order_index)+1}: ${tool.name}</div><div class="toolFormBody">
diff -r 125d735c689ee60ad9bd9601c7a22738ba3523de -r ab8fb6d1f56d6677ccd9dbfa137acf6efbc4d245 templates/workflow/run.mako
--- a/templates/workflow/run.mako
+++ b/templates/workflow/run.mako
@@ -363,7 +363,17 @@
%endif
%for i, step in enumerate( steps ):
%if step.type == 'tool' or step.type is None:
- <% tool = app.toolbox.tools_by_id[step.tool_id] %>
+ <%
+ try:
+ tool = trans.app.toolbox.tools_by_id[ step.tool_id ]
+ except KeyError, e:
+ # The id value of tools installed from a Galaxy tool shed is a guid, but
+ # these tool's old_id attribute should contain what we're looking for.
+ for available_tool_id, available_tool in trans.app.toolbox.tools_by_id.items():
+ if step.tool_id == available_tool.old_id:
+ tool = available_tool
+ break
+ %><input type="hidden" name="${step.id}|tool_state" value="${step.state.encode( tool, app )}"><div class="toolForm"><div class="toolFormTitle">
diff -r 125d735c689ee60ad9bd9601c7a22738ba3523de -r ab8fb6d1f56d6677ccd9dbfa137acf6efbc4d245 tools/gatk/count_covariates.xml
--- a/tools/gatk/count_covariates.xml
+++ b/tools/gatk/count_covariates.xml
@@ -138,6 +138,7 @@
<when value="cached"><param name="input_bam" type="data" format="bam" label="BAM file"><validator type="unspecified_build" />
+ <validator type="metadata" check="bam_index" message="Metadata missing, click the pencil icon in the history item and use the auto-detect feature to correct this issue."/><validator type="dataset_metadata_in_file" filename="picard_index.loc" metadata_name="dbkey" metadata_column="1" message="Sequences are not currently available for the specified build." /><!-- fixme!!! this needs to be a select --></param><param name="ref_file" type="select" label="Using reference genome">
@@ -147,7 +148,9 @@
</param></when><when value="history"><!-- FIX ME!!!! -->
- <param name="input_bam" type="data" format="bam" label="BAM file" />
+ <param name="input_bam" type="data" format="bam" label="BAM file" >
+ <validator type="metadata" check="bam_index" message="Metadata missing, click the pencil icon in the history item and use the auto-detect feature to correct this issue."/>
+ </param><param name="ref_file" type="data" format="fasta" label="Using reference file" /></when></conditional>
diff -r 125d735c689ee60ad9bd9601c7a22738ba3523de -r ab8fb6d1f56d6677ccd9dbfa137acf6efbc4d245 tools/gatk/indel_realigner.xml
--- a/tools/gatk/indel_realigner.xml
+++ b/tools/gatk/indel_realigner.xml
@@ -107,6 +107,7 @@
<when value="cached"><param name="input_bam" type="data" format="bam" label="BAM file"><validator type="unspecified_build" />
+ <validator type="metadata" check="bam_index" message="Metadata missing, click the pencil icon in the history item and use the auto-detect feature to correct this issue."/><validator type="dataset_metadata_in_data_table" table_name="picard_indexes" metadata_name="dbkey" metadata_column="dbkey" message="Sequences are not currently available for the specified build." /><!-- fixme!!! this needs to be a select --></param><param name="ref_file" type="select" label="Using reference genome">
@@ -116,7 +117,9 @@
</param></when><when value="history"><!-- FIX ME!!!! -->
- <param name="input_bam" type="data" format="bam" label="BAM file" />
+ <param name="input_bam" type="data" format="bam" label="BAM file" >
+ <validator type="metadata" check="bam_index" message="Metadata missing, click the pencil icon in the history item and use the auto-detect feature to correct this issue."/>
+ </param><param name="ref_file" type="data" format="fasta" label="Using reference file"><options><filter type="data_meta" key="dbkey" ref="input_bam" /><!-- FIX ME!!!! -->
diff -r 125d735c689ee60ad9bd9601c7a22738ba3523de -r ab8fb6d1f56d6677ccd9dbfa137acf6efbc4d245 tools/gatk/realigner_target_creator.xml
--- a/tools/gatk/realigner_target_creator.xml
+++ b/tools/gatk/realigner_target_creator.xml
@@ -103,6 +103,7 @@
<when value="cached"><param name="input_bam" type="data" format="bam" label="BAM file"><validator type="unspecified_build" />
+ <validator type="metadata" check="bam_index" message="Metadata missing, click the pencil icon in the history item and use the auto-detect feature to correct this issue."/><validator type="dataset_metadata_in_data_table" table_name="picard_indexes" metadata_name="dbkey" metadata_column="dbkey" message="Sequences are not currently available for the specified build." /><!-- fixme!!! this needs to be a select --></param><param name="ref_file" type="select" label="Using reference genome">
@@ -112,7 +113,9 @@
</param></when><when value="history">
- <param name="input_bam" type="data" format="bam" label="BAM file" />
+ <param name="input_bam" type="data" format="bam" label="BAM file" >
+ <validator type="metadata" check="bam_index" message="Metadata missing, click the pencil icon in the history item and use the auto-detect feature to correct this issue."/>
+ </param><param name="ref_file" type="data" format="fasta" label="Using reference file"><options><filter type="data_meta" key="dbkey" ref="input_bam" /><!-- FIX ME!!!! -->
diff -r 125d735c689ee60ad9bd9601c7a22738ba3523de -r ab8fb6d1f56d6677ccd9dbfa137acf6efbc4d245 tools/gatk/table_recalibration.xml
--- a/tools/gatk/table_recalibration.xml
+++ b/tools/gatk/table_recalibration.xml
@@ -117,6 +117,7 @@
<when value="cached"><param name="input_bam" type="data" format="bam" label="BAM file"><validator type="unspecified_build" />
+ <validator type="metadata" check="bam_index" message="Metadata missing, click the pencil icon in the history item and use the auto-detect feature to correct this issue."/><validator type="dataset_metadata_in_data_table" table_name="picard_indexes" metadata_name="dbkey" metadata_column="dbkey" message="Sequences are not currently available for the specified build." /><!-- fixme!!! this needs to be a select --></param><param name="ref_file" type="select" label="Using reference genome">
@@ -126,7 +127,9 @@
</param></when><when value="history"><!-- FIX ME!!!! -->
- <param name="input_bam" type="data" format="bam" label="BAM file" />
+ <param name="input_bam" type="data" format="bam" label="BAM file" >
+ <validator type="metadata" check="bam_index" message="Metadata missing, click the pencil icon in the history item and use the auto-detect feature to correct this issue."/>
+ </param><param name="ref_file" type="data" format="fasta" label="Using reference file" /></when></conditional>
diff -r 125d735c689ee60ad9bd9601c7a22738ba3523de -r ab8fb6d1f56d6677ccd9dbfa137acf6efbc4d245 tools/gatk/unified_genotyper.xml
--- a/tools/gatk/unified_genotyper.xml
+++ b/tools/gatk/unified_genotyper.xml
@@ -7,8 +7,6 @@
--max_jvm_heap_fraction "1"
--stdout "${output_log}"
#for $i, $input_bam in enumerate( $reference_source.input_bams ):
- ${dir( $input_bam.input_bam )}
- ${dir( $input_bam.input_bam.dataset )}
-d "-I" "${input_bam.input_bam}" "${input_bam.input_bam.ext}" "gatk_input_${i}"
-d "" "${input_bam.input_bam.metadata.bam_index}" "bam_index" "gatk_input_${i}" ##hardcode galaxy ext type as bam_index
#end for
@@ -137,6 +135,7 @@
<repeat name="input_bams" title="Sample BAM file" min="1"><param name="input_bam" type="data" format="bam" label="BAM file"><validator type="unspecified_build" />
+ <validator type="metadata" check="bam_index" message="Metadata missing, click the pencil icon in the history item and use the auto-detect feature to correct this issue."/><validator type="dataset_metadata_in_data_table" table_name="picard_indexes" metadata_name="dbkey" metadata_column="dbkey" message="Sequences are not currently available for the specified build." /><!-- fixme!!! this needs to be a select --></param></repeat>
@@ -148,7 +147,9 @@
</when><when value="history"><!-- FIX ME!!!! --><repeat name="input_bams" title="Sample BAM file" min="1">
- <param name="input_bam" type="data" format="bam" label="BAM file" />
+ <param name="input_bam" type="data" format="bam" label="BAM file" >
+ <validator type="metadata" check="bam_index" message="Metadata missing, click the pencil icon in the history item and use the auto-detect feature to correct this issue."/>
+ </param></repeat><param name="ref_file" type="data" format="fasta" label="Using reference file" /></when>
diff -r 125d735c689ee60ad9bd9601c7a22738ba3523de -r ab8fb6d1f56d6677ccd9dbfa137acf6efbc4d245 tools/gatk/variant_annotator.xml
--- a/tools/gatk/variant_annotator.xml
+++ b/tools/gatk/variant_annotator.xml
@@ -145,6 +145,7 @@
<param name="input_variant_bti" type="boolean" truevalue="-BTI variant" falsevalue="" label="Increase efficiency for small variant files." /><param name="input_bam" type="data" format="bam" label="BAM file" optional="True" help="Not needed for all annotations." ><validator type="unspecified_build" />
+ <validator type="metadata" check="bam_index" message="Metadata missing, click the pencil icon in the history item and use the auto-detect feature to correct this issue."/><validator type="dataset_metadata_in_data_table" table_name="picard_indexes" metadata_name="dbkey" metadata_column="dbkey" message="Sequences are not currently available for the specified build." /><!-- fixme!!! this needs to be a select --></param><param name="ref_file" type="select" label="Using reference genome">
@@ -156,7 +157,9 @@
<when value="history"><!-- FIX ME!!!! --><param name="input_variant" type="data" format="vcf" label="Variant file to annotate" /><param name="input_variant_bti" type="boolean" truevalue="-BTI variant" falsevalue="" label="Increase efficiency for small variant files." />
- <param name="input_bam" type="data" format="bam" label="BAM file" optional="True" />
+ <param name="input_bam" type="data" format="bam" label="BAM file" optional="True" >
+ <validator type="metadata" check="bam_index" message="Metadata missing, click the pencil icon in the history item and use the auto-detect feature to correct this issue."/>
+ </param><param name="ref_file" type="data" format="fasta" label="Using reference file" /></when></conditional>
diff -r 125d735c689ee60ad9bd9601c7a22738ba3523de -r ab8fb6d1f56d6677ccd9dbfa137acf6efbc4d245 tools/picard/picard_SamToFastq.xml
--- a/tools/picard/picard_SamToFastq.xml
+++ b/tools/picard/picard_SamToFastq.xml
@@ -42,11 +42,11 @@
|| echo "Error running SamToFastq" >&2
</command><inputs>
- <param name="input_sam" type="data" format="sam" label="SAM file" />
+ <param name="input_sam" type="data" format="sam,bam" label="BAM/SAM file" /><param name="read1_trim" type="integer" value="" optional="True" label="The number of bases to trim from the beginning of read 1." /><param name="read1_max_bases_to_write" type="integer" optional="True" value="" label="The maximum number of bases to write from read 1 after trimming." /><param name="output_per_read_group_selector" type="select" label="Output per read group">
- <option value="per_sam_file" selected="True">Per SAM file</option>
+ <option value="per_sam_file" selected="True">Per BAM/SAM file</option><!-- <option value="per_read_group">Per Read Group</option> --><validator type="expression" message="Per Read Group selection is not yet implemented">value == 'per_sam_file'</validator></param>
diff -r 125d735c689ee60ad9bd9601c7a22738ba3523de -r ab8fb6d1f56d6677ccd9dbfa137acf6efbc4d245 tools/samtools/sam_merge.xml
--- a/tools/samtools/sam_merge.xml
+++ b/tools/samtools/sam_merge.xml
@@ -4,11 +4,12 @@
<requirement type="package">picard</requirement></requirements><command>
-java -Xmx2G -jar ${GALAXY_DATA_INDEX_DIR}/shared/jars/MergeSamFiles.jar MSD=$mergeSD VALIDATION_STRINGENCY=LENIENT O=$output1 I=$input1 I=$input2
+java -Xmx2G -jar ${GALAXY_DATA_INDEX_DIR}/shared/jars/picard/MergeSamFiles.jar MSD=$mergeSD VALIDATION_STRINGENCY=LENIENT O=$output1 I=$input1 I=$input2
#for $i in $inputs
I=${i.input}
#end for
2> $outlog
+ || echo "Error running Picard MergeSamFiles" >&2
</command><inputs><param name="title" label="Name for the output merged bam file" type="text" default="Merged.bam"
@@ -16,10 +17,10 @@
<param name="mergeSD" value="true" type="boolean" label="Merge all component bam file headers into the merged bam file"
truevalue="true" falsevalue="false" checked="yes"
help="Control the MERGE_SEQUENCE_DICTIONARIES flag for Picard MergeSamFiles. Default (true) correctly propagates read groups and other important metadata" />
- <param name="input1" label="First file" type="data" format="bam" />
- <param name="input2" label="with file" type="data" format="bam" help="Need to add more files? Use controls below." />
+ <param name="input1" label="First file" type="data" format="bam,sam" />
+ <param name="input2" label="with file" type="data" format="bam,sam" help="Need to add more files? Use controls below." /><repeat name="inputs" title="Input Files">
- <param name="input" label="Add file" type="data" format="bam" />
+ <param name="input" label="Add file" type="data" format="bam,sam" /></repeat></inputs><outputs>
@@ -36,7 +37,7 @@
<param name="input1" value="sam_merge_in1.bam" ftype="bam" /><param name="input2" value="sam_merge_in2.bam" ftype="bam" /><output name="output1" file="sam_merge_out1.bam" ftype="bam" />
- <output name="outlog" file="sam_merge_out1.log" ftype="txt" lines_diff="10"/>
+ <output name="outlog" file="sam_merge_out1.log" ftype="txt" lines_diff="11"/></test><test><param name="title" value="test2" />
@@ -45,7 +46,7 @@
<param name="input2" value="sam_merge_in2.bam" ftype="bam" /><param name="input" value="sam_merge_in3.bam" ftype="bam" /><output name="output1" file="sam_merge_out2.bam" ftype="bam" />
- <output name="outlog" file="sam_merge_out2.log" ftype="txt" lines_diff="10"/>
+ <output name="outlog" file="sam_merge_out2.log" ftype="txt" lines_diff="11"/></test></tests><help>
https://bitbucket.org/galaxy/galaxy-central/changeset/89893520cb6d/
changeset: 89893520cb6d
user: natefoo
date: 2011-10-27 20:04:57
summary: Fixes for stuff lost in a merge somewhere.
affected #: 1 file
diff -r ab8fb6d1f56d6677ccd9dbfa137acf6efbc4d245 -r 89893520cb6d18d1371d2dbf816a83b1d7ae2631 lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -107,6 +107,14 @@
try:
path = elem.get( "file" )
tool = self.load_tool( os.path.join( tool_path, path ), guid=guid )
+ if guid is not None:
+ # Tool was installed from a Galaxy tool shed.
+ tool.tool_shed = elem.find( "tool_shed" ).text
+ tool.repository_name = elem.find( "repository_name" ).text
+ tool.repository_owner = elem.find( "repository_owner" ).text
+ tool.changeset_revision = elem.find( "changeset_revision" ).text
+ tool.old_id = elem.find( "id" ).text
+ tool.version = elem.find( "version" ).text
if self.app.config.get_bool( 'enable_tool_tags', False ):
tag_names = elem.get( "tags", "" ).split( "," )
for tag_name in tag_names:
@@ -367,9 +375,7 @@
# legacy basic mode - provide compatible defaults
self.attributes['split_size'] = 20
self.attributes['split_mode'] = 'number_of_parts'
-
-
-
+
class Tool:
"""
Represents a computational tool that can be executed through Galaxy.
@@ -390,6 +396,13 @@
# easily ensure that parameter dependencies like index files or
# tool_data_table_conf.xml entries exist.
self.input_params = []
+ # Attributes of tools installed from Galaxy tool sheds.
+ self.tool_shed = None
+ self.repository_name = None
+ self.repository_owner = None
+ self.changeset_revision = None
+ self.old_id = None
+ self.version = None
# Parse XML element containing configuration
self.parse( root, guid=guid )
self.external_runJob_script = app.config.drmaa_external_runjob_script
@@ -411,14 +424,15 @@
raise Exception, "Missing tool 'name'"
# Get the UNIQUE id for the tool
# TODO: can this be generated automatically?
- if guid is not None:
+ if guid is None:
+ self.id = root.get( "id" )
+ self.version = root.get( "version" )
+ else:
self.id = guid
- else:
- self.id = root.get( "id" )
if not self.id:
- raise Exception, "Missing tool 'id'"
+ raise Exception, "Missing tool 'id'"
self.version = root.get( "version" )
- if not self.version:
+ if not self.version:
# For backward compatibility, some tools may not have versions yet.
self.version = "1.0.0"
# Support multi-byte tools
@@ -806,6 +820,7 @@
group = Repeat()
group.name = elem.get( "name" )
group.title = elem.get( "title" )
+ group.help = elem.get( "help", None )
group.inputs = self.parse_input_elem( elem, enctypes, context )
group.default = int( elem.get( "default", 0 ) )
group.min = int( elem.get( "min", 0 ) )
@@ -1571,7 +1586,7 @@
name = conversion_name, config_info = self.app.config )
# Wrap actual input dataset
input_values[ input.name ] = \
- DatasetFilenameWrapper( input_values[ input.name ],
+ DatasetFilenameWrapper( input_values[ input.name ],
datatypes_registry = self.app.datatypes_registry,
tool = self,
name = input.name, config_info = self.app.config )
https://bitbucket.org/galaxy/galaxy-central/changeset/638d994c4cc7/
changeset: 638d994c4cc7
user: natefoo
date: 2011-10-27 20:14:27
summary: Revert changes to cufflinks/tophat, these can be integrated in a seperate commit.
affected #: 2 files
diff -r 89893520cb6d18d1371d2dbf816a83b1d7ae2631 -r 638d994c4cc7783248357b3cf7403b00924d0016 tools/ngs_rna/cufflinks_wrapper.xml
--- a/tools/ngs_rna/cufflinks_wrapper.xml
+++ b/tools/ngs_rna/cufflinks_wrapper.xml
@@ -1,4 +1,5 @@
-<tool id="cufflinks" name="Cufflinks" version="0.9.1">
+<tool id="cufflinks" name="Cufflinks" version="0.0.5">
+ <!-- Wrapper supports Cufflinks versions v1.0.0-v1.0.3 --><description>transcript assembly and FPKM (RPKM) estimates for RNA-Seq data</description><requirements><requirement type="package">cufflinks</requirement>
@@ -14,27 +15,10 @@
## Include reference annotation?
#if $reference_annotation.use_ref == "Use reference annotation":
- #if $reference_annotation.annotationSource.reference_annotation_file == "indexed":
- -G "${ filter( lambda x: str( x[0] ) == str( $reference_annotation.annotationSource.indices ), $__app__.tool_data_tables[ 'gtf_index' ].get_fields() )[0][-1] }"
- #else:
- #if $reference_annotation.annotationSource.reference_annotation_file == "attribute":
- -G "${ filter( lambda x: str( x[0] ) == str( $input.metadata.dbkey ), $__app__.tool_data_tables[ 'gtf_index' ].get_fields() )[0][-1] }"
- #else:
- -G "${reference_annotation.annotationSource.ownFile}"
- #end if
- #end if
+ -G $reference_annotation.reference_annotation_file
#end if
-
#if $reference_annotation.use_ref == "Use reference annotation guide":
- #if $reference_annotation.annotationSource.reference_annotation_file == "indexed":
- -g "${ filter( lambda x: str( x[0] ) == str( $reference_annotation.annotationSource.indices ), $__app__.tool_data_tables[ 'gtf_index' ].get_fields() )[0][-1] }"
- #else:
- #if $reference_annotation.annotationSource.reference_annotation_file == "attribute":
- -g "${ filter( lambda x: str( x[0] ) == str( $input.metadata.dbkey ), $__app__.tool_data_tables[ 'gtf_index' ].get_fields() )[0][-1] }"
- #else:
- -g "${reference_annotation.annotationSource.ownFile}"
- #end if
- #end if
+ -g $reference_annotation.reference_annotation_guide_file
#end if
## Set paired-end parameters?
@@ -77,44 +61,10 @@
</param><when value="No"></when><when value="Use reference annotation">
- <conditional name="annotationSource">
- <param name="reference_annotation_file" type="select" label="Please select a reference Aonnotation">
- <option value="indexed">Use a built-in index</option>
- <option value="history">Use one from the history</option>
- <option value="attribute">Use input bam metadata.dbkey attribute</option>
- </param>
- <when value="indexed">
- <param name="indices" type="select" label="Select genome for gtf annotation">
- <options from_data_table="gtf_index">
- <filter type="sort_by" column="3" />
- <validator type="no_options" message="No indexes are available for the selected input dataset" />
- </options>
- </param>
- </when>
- <when value="history">
- <param name="ownFile" type="data" format="gff3, gtf" label="Select a reference annotation file" />
- </when>
- </conditional>
- </when>
+ <param format="gff3,gtf" name="reference_annotation_file" type="data" label="Reference Annotation" help="Make sure your annotation file is in GTF format and that Galaxy knows that your file is GTF--not GFF."/>
+ </when><when value="Use reference annotation guide">
- <conditional name="annotationSource">
- <param name="reference_annotation_file" type="select" label="Please select a reference Aonnotation">
- <option value="indexed">Use a built-in index</option>
- <option value="history">Use one from the history</option>
- <option value="attribute">Use input bam metadata.dbkey attribute</option>
- </param>
- <when value="indexed">
- <param name="indices" type="select" label="Select genome for gtf annotation">
- <options from_data_table="gtf_index">
- <filter type="sort_by" column="3" />
- <validator type="no_options" message="No indexes are available for the selected input dataset" />
- </options>
- </param>
- </when>
- <when value="history">
- <param name="ownFile" type="data" format="gff3, gtf" label="Select a reference annotation file" />
- </when>
- </conditional>
+ <param format="gff3,gtf" name="reference_annotation_guide_file" type="data" label="Reference Annotation" help="Make sure your annotation file is in GTF format and that Galaxy knows that your file is GTF--not GFF."/></when></conditional><conditional name="bias_correction">
diff -r 89893520cb6d18d1371d2dbf816a83b1d7ae2631 -r 638d994c4cc7783248357b3cf7403b00924d0016 tools/ngs_rna/tophat_wrapper.xml
--- a/tools/ngs_rna/tophat_wrapper.xml
+++ b/tools/ngs_rna/tophat_wrapper.xml
@@ -1,8 +1,7 @@
-<tool id="tophat" name="Tophat" version="1.2.1">
+<tool id="tophat" name="Tophat for Illumina" version="1.5.0"><description>Find splice junctions using RNA-seq data</description>
+ <version_command>tophat --version</version_command><requirements>
- <requirement type="package">samtools</requirement>
- <requirement type="package">bowtie</requirement><requirement type="package">tophat</requirement></requirements><command interpreter="python">
@@ -18,18 +17,14 @@
#if $refGenomeSource.genomeSource == "history":
--own-file=$refGenomeSource.ownFile
#else:
- #if $refGenomeSource.genomeSource == "indexed":
- --indexes-path="${ filter( lambda x: str( x[0] ) == str( $refGenomeSource.index ), $__app__.tool_data_tables[ 'tophat_indexes' ].get_fields() )[0][-1] }"
- #else:
- --indexes-path="${ filter( lambda x: str( x[0] ) == str( $singlePaired.input1.metadata.dbkey ), $__app__.tool_data_tables[ 'tophat_indexes' ].get_fields() )[0][-1] }"
- #end if
+ --indexes-path="${ filter( lambda x: str( x[0] ) == str( $refGenomeSource.index ), $__app__.tool_data_tables[ 'tophat_indexes' ].get_fields() )[0][-1] }"
#end if
## Are reads single-end or paired?
--single-paired=$singlePaired.sPaired
## First input file always required.
- --input1=$singlePaired.input1
+ --input1=$input1
## Set params based on whether reads are single-end or paired.
#if $singlePaired.sPaired == "single":
@@ -57,15 +52,7 @@
## Supplying junctions parameters.
#if $singlePaired.sParams.own_junctions.use_junctions == "Yes":
#if $singlePaired.sParams.own_junctions.gene_model_ann.use_annotations == "Yes":
- #if $singlePaired.sParams.own_junctions.gene_model_ann.annotationSource.reference_annotation_file == "indexed":
- -G "${ filter( lambda x: str( x[0] ) == str( $refGenomeSource.index ), $__app__.tool_data_tables[ 'gtf_index' ].get_fields() )[0][-1] }"
- #else:
- #if $singlePaired.sParams.own_junctions.gene_model_ann.annotationSource.reference_annotation_file == "attribute":
- -G "${ filter( lambda x: str( x[0] ) == str( $singlePaired.input1.metadata.dbkey ), $__app__.tool_data_tables[ 'gtf_index' ].get_fields() )[0][-1] }"
- #else
- -G "${singlePaired.sParams.own_junctions.gene_model_ann.annotationSource.owngtfFile}"
- #end if
- #end if
+ -G $singlePaired.sParams.own_junctions.gene_model_ann.gene_annotation_model
#end if
#if $singlePaired.sParams.own_junctions.raw_juncs.use_juncs == "Yes":
-j $singlePaired.sParams.own_junctions.raw_juncs.raw_juncs
@@ -124,15 +111,7 @@
## Supplying junctions parameters.
#if $singlePaired.pParams.own_junctions.use_junctions == "Yes":
#if $singlePaired.pParams.own_junctions.gene_model_ann.use_annotations == "Yes":
- #if $singlePaired.pParams.own_junctions.gene_model_ann.annotationSource.reference_annotation_file == "indexed":
- -G "${ filter( lambda x: str( x[0] ) == str( $refGenomeSource.index ), $__app__.tool_data_tables[ 'gtf_index' ].get_fields() )[0][-1] }"
- #else:
- #if $singlePaired.pParams.own_junctions.gene_model_ann.annotationSource.reference_annotation_file == "attribute":
- -G "${ filter( lambda x: str( x[0] ) == str( $singlePaired.input1.metadata.dbkey ), $__app__.tool_data_tables[ 'gtf_index' ].get_fields() )[0][-1] }"
- #else
- -G "${singlePaired.sParams.own_junctions.gene_model_ann.annotationSource.owngtfFile}"
- #end if
- #end if
+ -G $singlePaired.pParams.own_junctions.gene_model_ann.gene_annotation_model
#end if
#if $singlePaired.pParams.own_junctions.raw_juncs.use_juncs == "Yes":
-j $singlePaired.pParams.own_junctions.raw_juncs.raw_juncs
@@ -166,15 +145,18 @@
#end if
</command><inputs>
+ <param format="fastqsanger" name="input1" type="data" label="RNA-Seq FASTQ file" help="Nucleotide-space: Must have Sanger-scaled quality values with ASCII offset 33" /><conditional name="refGenomeSource"><param name="genomeSource" type="select" label="Will you select a reference genome from your history or use a built-in index?" help="Built-ins were indexed using default options"><option value="indexed">Use a built-in index</option><option value="history">Use one from the history</option>
- <option value="attribute">Use input fastq metadata.dbkey attribute</option></param><when value="indexed"><param name="index" type="select" label="Select a reference genome" help="If your genome of interest is not listed, contact the Galaxy team">
- <options from_data_table="tophat_indexes" />
+ <options from_data_table="tophat_indexes">
+ <filter type="sort_by" column="2"/>
+ <validator type="no_options" message="No indexes are available for the selected input dataset"/>
+ </options></param></when><when value="history">
@@ -187,7 +169,6 @@
<option value="paired">Paired-end</option></param><when value="single">
- <param format="fastqsanger" name="input1" type="data" label="RNA-Seq FASTQ file" help="Must have Sanger-scaled quality values with ASCII offset 33"/><conditional name="sParams"><param name="sSettingsType" type="select" label="TopHat settings to use" help="You can use the default settings or set custom values for any of Tophat's parameters."><option value="preSet">Use Defaults</option>
@@ -237,16 +218,7 @@
</param><when value="No" /><when value="Yes">
- <conditional name="annotationSource">
- <param name="reference_annotation_file" type="select" label="Please select a reference Aonnotation">
- <option value="indexed">Use a built-in index</option>
- <option value="history">Use one from the history</option>
- <option value="attribute">Use metadata.bkey attribute from input fastq file</option>
- </param>
- <when value="history">
- <param name="owngtfFile" type="data" format="gff3, gtf" label="Select a reference annotation file" />
- </when>
- </conditional>
+ <param format="gtf" name="gene_annotation_model" type="data" label="Gene Model Annotations" help="TopHat will use the exon records in this file to build a set of known splice junctions for each gene, and will attempt to align reads to these junctions even if they would not normally be covered by the initial mapping."/></when></conditional><conditional name="raw_juncs">
@@ -291,7 +263,7 @@
<param name="max_coverage_intron" type="integer" value="20000" label="Maximum intron length that may be found during coverage search" /></when><when value="No" />
- </conditional>
+ </conditional><param name="microexon_search" type="select" label="Use Microexon Search" help="With this option, the pipeline will attempt to find alignments incident to microexons. Works only for reads 50bp or longer."><option value="No">No</option><option value="Yes">Yes</option>
@@ -300,8 +272,7 @@
</conditional><!-- sParams --></when><!-- single --><when value="paired">
- <param format="fastqsanger" name="input1" type="data" label="RNA-Seq FASTQ file" help="Must have Sanger-scaled quality values with ASCII offset 33"/>
- <param format="fastqsanger" name="input2" type="data" label="RNA-Seq FASTQ file" help="Must have Sanger-scaled quality values with ASCII offset 33"/>
+ <param format="fastqsanger" name="input2" type="data" label="RNA-Seq FASTQ file" help="Nucleotide-space: Must have Sanger-scaled quality values with ASCII offset 33" /><param name="mate_inner_distance" type="integer" value="20" label="Mean Inner Distance between Mate Pairs" /><conditional name="pParams"><param name="pSettingsType" type="select" label="TopHat settings to use" help="For most mapping needs use Commonly used settings. If you want full control use Full parameter list">
@@ -352,16 +323,7 @@
</param><when value="No" /><when value="Yes">
- <conditional name="annotationSource">
- <param name="reference_annotation_file" type="select" label="Please select a reference Aonnotation">
- <option value="indexed">Use a built-in index</option>
- <option value="history">Use one from the history</option>
- <option value="attribute">Use metadata.bkey attribute from input fastq files</option>
- </param>
- <when value="history">
- <param name="owngtfFile" type="data" format="gff3, gtf" label="Select a reference annotation file" />
- </when>
- </conditional>
+ <param format="gtf" name="gene_annotation_model" type="data" label="Gene Model Annotations" help="TopHat will use the exon records in this file to build a set of known splice junctions for each gene, and will attempt to align reads to these junctions even if they would not normally be covered by the initial mapping."/></when></conditional><conditional name="raw_juncs">
@@ -425,7 +387,7 @@
( singlePaired['sParams']['indel_search']['allow_indel_search'] == 'Yes' ) ) or
( ( 'pParams' in singlePaired ) and ( 'indel_search' in singlePaired['pParams'] ) and
( singlePaired['pParams']['indel_search']['allow_indel_search'] == 'Yes' ) )
- )
+ )
</filter><actions><conditional name="refGenomeSource.genomeSource">
@@ -513,46 +475,49 @@
</outputs><tests>
- <!-- Test single-end reads with pre-built index and preset parameters -->
+ <!-- Test base-space single-end reads with pre-built index and preset parameters --><test><!-- TopHat commands:
- tophat -o tmp_dir -p 1 /afs/bx.psu.edu/depot/data/genome/test/tophat/tophat_in1 test-data/tophat_in2.fastqsanger
+ tophat -o tmp_dir -p 1 tophat_in1 test-data/tophat_in2.fastqsanger
+ Rename the files in tmp_dir appropriately
-->
+ <param name="input1" ftype="fastqsanger" value="tophat_in2.fastqsanger" /><param name="genomeSource" value="indexed" /><param name="index" value="tophat_test" /><param name="sPaired" value="single" />
- <param name="input1" ftype="fastqsanger" value="tophat_in2.fastqsanger" /><param name="sSettingsType" value="preSet" /><output name="junctions" file="tophat_out1j.bed" /><output name="accepted_hits" file="tophat_out1h.bam" compare="sim_size" /></test>
- <!-- Test using test data: paired-end reads, index from history. -->
+ <!-- Test using base-space test data: paired-end reads, index from history. --><test><!-- TopHat commands:
bowtie-build -f test-data/tophat_in1.fasta tophat_in1
tophat -o tmp_dir -p 1 -r 20 tophat_in1 test-data/tophat_in2.fastqsanger test-data/tophat_in3.fastqsanger
+ Rename the files in tmp_dir appropriately
-->
+ <param name="input1" ftype="fastqsanger" value="tophat_in2.fastqsanger" /><param name="genomeSource" value="history" /><param name="ownFile" ftype="fasta" value="tophat_in1.fasta" /><param name="sPaired" value="paired" />
- <param name="input1" ftype="fastqsanger" value="tophat_in2.fastqsanger" /><param name="input2" ftype="fastqsanger" value="tophat_in3.fastqsanger" /><param name="mate_inner_distance" value="20" /><param name="pSettingsType" value="preSet" /><output name="junctions" file="tophat_out2j.bed" /><output name="accepted_hits" file="tophat_out2h.bam" compare="sim_size" /></test>
- <!-- Test single-end reads with user-supplied reference fasta and full parameters -->
+ <!-- Test base-space single-end reads with user-supplied reference fasta and full parameters --><test><!-- Tophat commands:
bowtie-build -f test-data/tophat_in1.fasta tophat_in1
tophat -o tmp_dir -p 1 -a 8 -m 0 -i 70 -I 500000 -F 0.15 -g 40 +allow-indels +coverage-search +min-coverage-intron 50 +max-coverage-intro 20000 +segment-mismatches 2 +segment-length 25 +closure-search +min-closure-exon 50 +min-closure-intron 50 +max-closure-intro 5000 +microexon-search tophat_in1 test-data/tophat_in2.fastqsanger
Replace the + with double-dash
+ Rename the files in tmp_dir appropriately
-->
+ <param name="input1" ftype="fastqsanger" value="tophat_in2.fastqsanger"/><param name="genomeSource" value="history"/><param name="ownFile" value="tophat_in1.fasta"/><param name="sPaired" value="single"/>
- <param name="input1" ftype="fastqsanger" value="tophat_in2.fastqsanger"/><param name="sSettingsType" value="full"/><param name="library_type" value="FR Unstranded"/><param name="anchor_length" value="8"/>
@@ -585,16 +550,17 @@
<output name="junctions" file="tophat_out3j.bed" /><output name="accepted_hits" file="tophat_out3h.bam" compare="sim_size" /></test>
- <!-- Test paired-end reads with user-supplied reference fasta and full parameters -->
+ <!-- Test base-space paired-end reads with user-supplied reference fasta and full parameters --><test><!-- TopHat commands:
- tophat -o tmp_dir -r 20 -p 1 -a 8 -m 0 -i 70 -I 500000 -F 0.15 -g 40 +coverage-search +min-coverage-intron 50 +max-coverage-intro 20000 +segment-mismatches 2 +segment-length 25 +closure-search +min-closure-exon 50 +min-closure-intron 50 +max-closure-intron 5000 +microexon-search /afs/bx.psu.edu/depot/data/genome/test/tophat/tophat_in1 test-data/tophat_in2.fastqsanger test-data/tophat_in3.fastqsanger
+ tophat -o tmp_dir -r 20 -p 1 -a 8 -m 0 -i 70 -I 500000 -F 0.15 -g 40 +coverage-search +min-coverage-intron 50 +max-coverage-intro 20000 +segment-mismatches 2 +segment-length 25 +closure-search +min-closure-exon 50 +min-closure-intron 50 +max-closure-intron 5000 +microexon-search tophat_in1 test-data/tophat_in2.fastqsanger test-data/tophat_in3.fastqsanger
Replace the + with double-dash
+ Rename the files in tmp_dir appropriately
-->
+ <param name="input1" ftype="fastqsanger" value="tophat_in2.fastqsanger"/><param name="genomeSource" value="indexed"/><param name="index" value="tophat_test"/><param name="sPaired" value="paired"/>
- <param name="input1" ftype="fastqsanger" value="tophat_in2.fastqsanger"/><param name="input2" ftype="fastqsanger" value="tophat_in3.fastqsanger"/><param name="mate_inner_distance" value="20"/><param name="pSettingsType" value="full"/>
@@ -662,7 +628,9 @@
.. _BED: http://genome.ucsc.edu/FAQ/FAQformat.html#format1
.. _BAM: http://samtools.sourceforge.net/
-
+
+Two other possible outputs, depending on the options you choose, are insertions and deletions, both of which are in BED format.
+
-------
**Tophat settings**
@@ -681,7 +649,7 @@
--mate-std-dev INT The standard deviation for the distribution on inner distances between mate pairs. The default is 20bp.
-a/--min-anchor-length INT The "anchor length". TopHat will report junctions spanned by reads with at least this many bases on each side of the junction. Note that individual spliced
alignments may span a junction with fewer than this many bases on one side. However, every junction involved in spliced alignments is supported by at least one
- read with this many bases on each side. This must be at least 3 and the default is 8.
+ read with this many bases on each side. This must be at least 3 and the default is 8.
-m/--splice-mismatches INT The maximum number of mismatches that may appear in the "anchor" region of a spliced alignment. The default is 0.
-i/--min-intron-length INT The minimum intron length. TopHat will ignore donor/acceptor pairs closer than this many bases apart. The default is 70.
-I/--max-intron-length INT The maximum intron length. When searching for junctions ab initio, TopHat will ignore donor/acceptor pairs farther than this many bases apart, except when such a pair is supported by a split segment alignment of a long read. The default is 500000.
https://bitbucket.org/galaxy/galaxy-central/changeset/3f0872314937/
changeset: 3f0872314937
user: natefoo
date: 2011-10-27 22:36:46
summary: A couple more fixes.
affected #: 4 files
diff -r 638d994c4cc7783248357b3cf7403b00924d0016 -r 3f08723149377d3f10b53909f97f90edd4babf6e lib/galaxy/jobs/__init__.py
--- a/lib/galaxy/jobs/__init__.py
+++ b/lib/galaxy/jobs/__init__.py
@@ -778,7 +778,7 @@
jeha_false_path = None
if self.app.config.outputs_to_working_directory:
self.output_paths = []
- output_dataset_paths = {}
+ self.output_dataset_paths = {}
for name, data in [ ( da.name, da.dataset.dataset ) for da in job.output_datasets + job.output_library_datasets ]:
false_path = os.path.abspath( os.path.join( self.working_directory, "galaxy_dataset_%d.dat" % data.id ) )
dsp = DatasetPath( data.id, data.file_name, false_path )
@@ -908,7 +908,7 @@
else:
self.prepare_input_files_cmds = None
self.status = task.states.NEW
-
+
def get_job( self ):
if self.job_id:
return self.sa_session.query( model.Job ).get( self.job_id )
diff -r 638d994c4cc7783248357b3cf7403b00924d0016 -r 3f08723149377d3f10b53909f97f90edd4babf6e lib/galaxy/model/__init__.py
--- a/lib/galaxy/model/__init__.py
+++ b/lib/galaxy/model/__init__.py
@@ -649,7 +649,7 @@
permitted_actions = get_permitted_actions( filter='DATASET' )
file_path = "/tmp/"
engine = None
- def __init__( self, id=None, state=None, external_filename=None, extra_files_path=None, file_size=None, purgable=True):
+ def __init__( self, id=None, state=None, external_filename=None, extra_files_path=None, file_size=None, purgable=True ):
self.id = id
self.state = state
self.deleted = False
diff -r 638d994c4cc7783248357b3cf7403b00924d0016 -r 3f08723149377d3f10b53909f97f90edd4babf6e lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -819,7 +819,7 @@
if elem.tag == "repeat":
group = Repeat()
group.name = elem.get( "name" )
- group.title = elem.get( "title" )
+ group.title = elem.get( "title" )
group.help = elem.get( "help", None )
group.inputs = self.parse_input_elem( elem, enctypes, context )
group.default = int( elem.get( "default", 0 ) )
diff -r 638d994c4cc7783248357b3cf7403b00924d0016 -r 3f08723149377d3f10b53909f97f90edd4babf6e universe_wsgi.ini.sample
--- a/universe_wsgi.ini.sample
+++ b/universe_wsgi.ini.sample
@@ -586,9 +586,6 @@
# run with the runner defined with default_cluster_job_runner.
[galaxy:tool_runners]
-binsort = drmaa://-cwd -V -pe threaded 4/
-bwa_wrapper = drmaa://-cwd -V -pe threaded 4/
-unified_genotyper = drmaa://-cwd -V -pe threaded 2/
biomart = local:///
encode_db1 = local:///
hbvar = local:///
https://bitbucket.org/galaxy/galaxy-central/changeset/0dbc8f529441/
changeset: 0dbc8f529441
user: natefoo
date: 2011-10-31 21:15:00
summary: Some fixes to actual user code to negate the need for world-writable directories and write external metadata and job stdout/stderr to the job working directory.
affected #: 6 files
diff -r 3f08723149377d3f10b53909f97f90edd4babf6e -r 0dbc8f529441cb79585c520a062ea01940714814 lib/galaxy/config.py
--- a/lib/galaxy/config.py
+++ b/lib/galaxy/config.py
@@ -81,6 +81,7 @@
self.job_working_directory = resolve_path( kwargs.get( "job_working_directory", "database/job_working_directory" ), self.root )
self.outputs_to_working_directory = string_as_bool( kwargs.get( 'outputs_to_working_directory', False ) )
self.output_size_limit = int( kwargs.get( 'output_size_limit', 0 ) )
+ self.retry_job_output_collection = int( kwargs.get( 'retry_job_output_collection', 0 ) )
self.job_walltime = kwargs.get( 'job_walltime', None )
self.admin_users = kwargs.get( "admin_users", "" )
self.mailing_join_addr = kwargs.get('mailing_join_addr',"galaxy-user-join(a)bx.psu.edu")
@@ -219,14 +220,6 @@
os.makedirs( path )
except Exception, e:
raise ConfigurationError( "Unable to create missing directory: %s\n%s" % ( path, e ) )
- if self.drmaa_external_runjob_script:
- os.chmod(self.new_file_path, 0777)
- os.chmod(self.job_working_directory, 0777)
- os.chmod(self.cluster_files_directory, 0777)
- else:
- os.chmod(self.new_file_path, 0755)
- os.chmod(self.job_working_directory, 0755)
- os.chmod(self.cluster_files_directory, 0755)
# Check that required files exist
for path in self.tool_configs:
diff -r 3f08723149377d3f10b53909f97f90edd4babf6e -r 0dbc8f529441cb79585c520a062ea01940714814 lib/galaxy/jobs/__init__.py
--- a/lib/galaxy/jobs/__init__.py
+++ b/lib/galaxy/jobs/__init__.py
@@ -332,6 +332,9 @@
# Wrapper holding the info required to restore and clean up from files used for setting metadata externally
self.external_output_metadata = metadata.JobExternalOutputMetadataWrapper( job )
+ self.__user_system_pwent = None
+ self.__galaxy_system_pwent = None
+
def get_job_runner( self ):
return self.tool.job_runner
@@ -360,15 +363,15 @@
config files.
"""
self.sa_session.expunge_all() #this prevents the metadata reverting that has been seen in conjunction with the PBS job runner
+
if not os.path.exists( self.working_directory ):
os.mkdir( self.working_directory )
- if self.app.config.drmaa_external_runjob_script:
- os.chmod(self.working_directory , 0777)
# Restore parameters from the database
job = self.get_job()
if job.user is None and job.galaxy_session is None:
raise Exception( 'Job %s has no user and no session.' % job.id )
+
incoming = dict( [ ( p.name, p.value ) for p in job.parameters ] )
incoming = self.tool.params_from_strings( incoming, self.app )
# Do any validation that could not be done at job creation
@@ -526,6 +529,21 @@
# default post job setup
self.sa_session.expunge_all()
job = self.get_job()
+
+ if self.app.config.drmaa_external_runjob_script and job.user is not None:
+ try:
+ # FIXME: hardcoded path
+ cmd = [ '/usr/bin/sudo', '-E', self.app.config.external_chown_script, self.working_directory, self.galaxy_system_pwent[0], str( self.galaxy_system_pwent[3] ) ]
+ log.debug( '(%s) Changing ownership of working directory with: %s' % ( job.id, ' '.join( cmd ) ) )
+ p = subprocess.Popen( cmd, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE )
+ stdout, stderr = p.communicate()
+ assert p.returncode == 0
+ except:
+ # TODO: log stdout/stderr
+ log.exception( '(%s) Failed to change ownership of %s, failing' % ( job.id, self.working_directory ) )
+ self.fail( job.info )
+ return
+
# if the job was deleted, don't finish it
if job.state == job.states.DELETED:
self.cleanup()
@@ -698,16 +716,6 @@
# fix permissions
for path in [ dp.real_path for dp in self.get_output_fnames() ]:
- #change the ownership of the files in file_path directory back to galaxy user
- if self.app.config.drmaa_external_runjob_script and self.app.config.external_chown_script:
- galaxy_user_name = pwd.getpwuid(os.getuid())[0]
- galaxy_group_id = str(pwd.getpwuid(os.getuid())[3])
- p = subprocess.Popen([ '/usr/bin/sudo', '-E', self.app.config.external_chown_script, path,galaxy_user_name,galaxy_group_id], shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- (stdoutdata, stderrdata) = p.communicate()
- exitcode = p.returncode
- if exitcode != 0:
- ## There was an error in the child process
- raise RuntimeError("External_chown_script failed (exit code %s) with error %s" % (str(exitcode), stderrdata))
util.umask_fix_perms( path, self.app.config.umask, 0666, self.app.config.gid )
self.sa_session.flush()
log.debug( 'job %d ended' % self.job_id )
@@ -718,10 +726,10 @@
try:
for fname in self.extra_filenames:
os.remove( fname )
+ if self.app.config.set_metadata_externally:
+ self.external_output_metadata.cleanup_external_metadata( self.sa_session )
if self.working_directory is not None and os.path.isdir( self.working_directory ):
shutil.rmtree( self.working_directory )
- if self.app.config.set_metadata_externally:
- self.external_output_metadata.cleanup_external_metadata( self.sa_session )
galaxy.tools.imp_exp.JobExportHistoryArchiveWrapper( self.job_id ).cleanup_after_job( self.sa_session )
galaxy.tools.imp_exp.JobImportHistoryArchiveWrapper( self.job_id ).cleanup_after_job( self.sa_session )
except:
@@ -892,6 +900,33 @@
else:
return 'anonymous@unknown'
+ def change_ownership_for_run( self ):
+ job = self.get_job()
+ if self.app.config.external_chown_script and job.user is not None:
+ try:
+ # FIXME: hardcoded path
+ cmd = [ '/usr/bin/sudo', '-E', self.app.config.external_chown_script, self.working_directory, self.user_system_pwent[0], str( self.user_system_pwent[3] ) ]
+ log.debug( '(%s) Changing ownership of working directory with: %s' % ( job.id, ' '.join( cmd ) ) )
+ p = subprocess.Popen( cmd, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE )
+ stdout, stderr = p.communicate()
+ assert p.returncode == 0
+ except:
+ log.exception( '(%s) Failed to change ownership of %s, making world-writable instead' % ( job.id, self.working_directory ) )
+ os.chmod( self.working_directory, 0777 )
+
+ @property
+ def user_system_pwent( self ):
+ if self.__user_system_pwent is None:
+ job = self.get_job()
+ self.__user_system_pwent = pwd.getpwnam( job.user.email.split('@')[0] )
+ return self.__user_system_pwent
+
+ @property
+ def galaxy_system_pwent( self ):
+ if self.__galaxy_system_pwent is None:
+ self.__galaxy_system_pwent = pwd.getpwuid(os.getuid())
+ return self.__galaxy_system_pwent
+
class TaskWrapper(JobWrapper):
"""
Extension of JobWrapper intended for running tasks.
diff -r 3f08723149377d3f10b53909f97f90edd4babf6e -r 0dbc8f529441cb79585c520a062ea01940714814 lib/galaxy/jobs/runners/__init__.py
--- a/lib/galaxy/jobs/runners/__init__.py
+++ b/lib/galaxy/jobs/runners/__init__.py
@@ -31,7 +31,7 @@
commands += "; cd %s; " % os.path.abspath( os.getcwd() )
commands += job_wrapper.setup_external_metadata(
exec_dir = os.path.abspath( os.getcwd() ),
- tmp_dir = self.app.config.new_file_path,
+ tmp_dir = job_wrapper.working_directory,
dataset_files_path = self.app.model.Dataset.file_path,
output_fnames = job_wrapper.get_output_fnames(),
set_extension = False,
diff -r 3f08723149377d3f10b53909f97f90edd4babf6e -r 0dbc8f529441cb79585c520a062ea01940714814 lib/galaxy/jobs/runners/drmaa.py
--- a/lib/galaxy/jobs/runners/drmaa.py
+++ b/lib/galaxy/jobs/runners/drmaa.py
@@ -53,8 +53,6 @@
cd %s
%s
%s
-%s
-%s
"""
def __lineno__():
"""Returns the current line number in our program."""
@@ -168,8 +166,8 @@
job_wrapper.change_state( model.Job.states.QUEUED )
# define job attributes
- ofile = "%s/%s.o" % (self.app.config.cluster_files_directory, job_wrapper.get_id_tag())
- efile = "%s/%s.e" % (self.app.config.cluster_files_directory, job_wrapper.get_id_tag())
+ ofile = "%s.drmout" % os.path.join(os.getcwd(), job_wrapper.working_directory, job_wrapper.get_id_tag())
+ efile = "%s.drmerr" % os.path.join(os.getcwd(), job_wrapper.working_directory, job_wrapper.get_id_tag())
jt = self.ds.createJobTemplate()
jt.remoteCommand = "%s/database/pbs/galaxy_%s.sh" % (os.getcwd(), job_wrapper.get_id_tag())
jt.outputPath = ":%s" % ofile
@@ -191,12 +189,7 @@
else:
export_tmp = ''
- if self.external_runJob_script == None:
- script = drm_template % (job_wrapper.galaxy_lib_dir, export_path, os.path.abspath( job_wrapper.working_directory ),export_tmp, command_line,'','')
- else:
- touchcmd = 'touch ' + os.path.abspath( job_wrapper.working_directory ) + '/just_in_cases.txt'
- chmodcmd = 'chmod -Rf a+rwx ' + os.path.abspath( job_wrapper.working_directory ) + '/*'
- script = drm_template % (job_wrapper.galaxy_lib_dir, export_path, os.path.abspath( job_wrapper.working_directory ), export_tmp, command_line, touchcmd,chmodcmd)
+ script = drm_template % ( job_wrapper.galaxy_lib_dir, export_path, os.path.abspath( job_wrapper.working_directory ), export_tmp, command_line )
fh = file( jt.remoteCommand, "w" )
fh.write( script )
@@ -219,9 +212,10 @@
if self.external_runJob_script is None:
job_id = self.ds.runJob(jt)
else:
- userid = self.get_qsub_user(job_wrapper)
+ job_wrapper.change_ownership_for_run()
+ log.debug( '(%s) submitting with credentials: %s [uid: %s]' % ( galaxy_id_tag, job_wrapper.user_system_pwent[0], job_wrapper.user_system_pwent[2] ) )
filename = self.store_jobtemplate(job_wrapper, jt)
- job_id = self.external_runjob(filename, userid)
+ job_id = self.external_runjob(filename, job_wrapper.user_system_pwent[2]).strip()
log.info("(%s) queued as %s" % ( galaxy_id_tag, job_id ) )
# store runner information for tracking if Galaxy restarts
@@ -315,23 +309,23 @@
efile = drm_job_state.efile
job_file = drm_job_state.job_file
# collect the output
- # JED - HACK to wait for the files to appear
+ # wait for the files to appear
which_try = 0
- while which_try < 60:
+ while which_try < (self.app.config.retry_job_output_collection + 1):
try:
ofh = file(ofile, "r")
efh = file(efile, "r")
stdout = ofh.read( 32768 )
stderr = efh.read( 32768 )
- which_try = 60
+ which_try = (self.app.config.retry_job_output_collection + 1)
except:
- if which_try == 60:
+ if which_try == self.app.config.retry_job_output_collection:
stdout = ''
stderr = 'Job output not returned from cluster'
- log.debug(stderr)
+ log.debug( stderr )
else:
- which_try += 1
time.sleep(1)
+ which_try += 1
try:
drm_job_state.job_wrapper.finish( stdout, stderr )
@@ -389,9 +383,9 @@
def recover( self, job, job_wrapper ):
"""Recovers jobs stuck in the queued/running state when Galaxy started"""
drm_job_state = DRMAAJobState()
- drm_job_state.ofile = "%s/database/pbs/%s.o" % (os.getcwd(), job.id)
- drm_job_state.efile = "%s/database/pbs/%s.e" % (os.getcwd(), job.id)
- drm_job_state.job_file = "%s/database/pbs/galaxy_%s.sh" % (os.getcwd(), job.id)
+ drm_job_state.ofile = "%s.drmout" % os.path.join(os.getcwd(), job_wrapper.working_directory, job_wrapper.get_id_tag())
+ drm_job_state.efile = "%s.drmerr" % os.path.join(os.getcwd(), job_wrapper.working_directory, job_wrapper.get_id_tag())
+ drm_job_state.job_file = "%s/galaxy_%s.sh" % (self.app.config.cluster_files_directory, job.id)
drm_job_state.job_id = str( job.job_runner_external_id )
drm_job_state.runner_url = job_wrapper.get_job_runner()
job_wrapper.command_line = job.command_line
@@ -407,30 +401,22 @@
drm_job_state.running = False
self.monitor_queue.put( drm_job_state )
- def get_qsub_user(self, job_wrapper):
- """ Returns the UserID (or Username) that should be used to execute the job. """
- #TODO:
- #add some logic to decide on an SGE user for the given job.
- job_user_name = job_wrapper.user.split('@')
- self.job_user_uid = getpwnam(job_user_name[0])
- log.debug (" (%s) is the uid being passed to the DRM queu\n" % ( self.job_user_uid[2]) )
- return self.job_user_uid[2]
-
def store_jobtemplate(self, job_wrapper, jt):
""" Stores the content of a DRMAA JobTemplate object in a file as a JSON string.
Path is hard-coded, but it's no worse than other path in this module.
Uses Galaxy's JobID, so file is expected to be unique."""
- filename = "%s/database/pbs/%s.jt_json" % (os.getcwd(), job_wrapper.get_id_tag())
+ filename = "%s/%s.jt_json" % (self.app.config.cluster_files_directory, job_wrapper.get_id_tag())
data = {}
for attr in DRMAA_jobTemplate_attributes:
try:
data[attr] = getattr(jt, attr)
except:
pass
- s = json.dumps(data);
+ s = json.dumps(data)
f = open(filename,'w')
f.write(s)
f.close()
+ log.debug( '(%s) Job script for external submission is: %s' % ( job_wrapper.job_id, filename ) )
return filename
def external_runjob(self, jobtemplate_filename, username):
diff -r 3f08723149377d3f10b53909f97f90edd4babf6e -r 0dbc8f529441cb79585c520a062ea01940714814 scripts/external_chown_script.py
--- a/scripts/external_chown_script.py
+++ b/scripts/external_chown_script.py
@@ -15,8 +15,6 @@
pkg_resources.require("drmaa")
import drmaa
-
-
def validate_paramters():
if len(sys.argv)<4:
sys.stderr.write("usage: %s path user_name gid\n" % sys.argv[0])
@@ -26,16 +24,12 @@
galaxy_user_name = sys.argv[2]
gid = sys.argv[3]
-
-
return path, galaxy_user_name, gid
def main():
path, galaxy_user_name, gid = validate_paramters()
- os.system('chown %s %s' %(galaxy_user_name, path))
- os.system('chgrp %s %s' %(gid, path))
-
-
+ os.system('chown -Rh %s %s' %(galaxy_user_name, path))
+ os.system('chgrp -Rh %s %s' %(gid, path))
if __name__ == "__main__":
main()
diff -r 3f08723149377d3f10b53909f97f90edd4babf6e -r 0dbc8f529441cb79585c520a062ea01940714814 universe_wsgi.ini.sample
--- a/universe_wsgi.ini.sample
+++ b/universe_wsgi.ini.sample
@@ -519,6 +519,13 @@
# Galaxy server after the job completes.
#outputs_to_working_directory = False
+# If your network filesystem's caching prevents the Galaxy server from seeing
+# the job's stdout and stderr files when it completes, you can retry reading
+# these files. The job runner will retry the number of times specified below,
+# waiting 1 second between tries. For NFS, you may want to try the -noac mount
+# option (Linux) or -actimeo=0 (Solaris).
+#retry_job_output_collection = 0
+
# Number of concurrent jobs to run (local job runner)
#local_job_queue_workers = 5
@@ -556,9 +563,9 @@
# Also the
# Defaults requiretty
# in /etc/sudoers must be commented out
-#drmaa_external_runjob_script = /opt/galaxy/scripts/drmaa_external_runner.py
-#drmaa_external_killjob_script = /opt/galaxy/scripts/drmaa_external_killer.py
-#external_chown_script = /opt/galaxy/scripts/external_chown_script.py
+#drmaa_external_runjob_script = scripts/drmaa_external_runner.py
+#drmaa_external_killjob_script = scripts/drmaa_external_killer.py
+#external_chown_script = scripts/external_chown_script.py
#important if running as actual user since enviromental variables are not passed
#will supercede an other definition of TMPDIR if using drmaa
https://bitbucket.org/galaxy/galaxy-central/changeset/ce2673f8f212/
changeset: ce2673f8f212
user: natefoo
date: 2011-11-02 14:18:47
summary: Run as user: Don't overwrite stdout/stderr on finish.
affected #: 1 file
diff -r 0dbc8f529441cb79585c520a062ea01940714814 -r ce2673f8f2122c4d2cf455f35b9bdc42b540a373 lib/galaxy/jobs/__init__.py
--- a/lib/galaxy/jobs/__init__.py
+++ b/lib/galaxy/jobs/__init__.py
@@ -536,7 +536,7 @@
cmd = [ '/usr/bin/sudo', '-E', self.app.config.external_chown_script, self.working_directory, self.galaxy_system_pwent[0], str( self.galaxy_system_pwent[3] ) ]
log.debug( '(%s) Changing ownership of working directory with: %s' % ( job.id, ' '.join( cmd ) ) )
p = subprocess.Popen( cmd, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE )
- stdout, stderr = p.communicate()
+ p.wait()
assert p.returncode == 0
except:
# TODO: log stdout/stderr
https://bitbucket.org/galaxy/galaxy-central/changeset/574db4e4ea45/
changeset: 574db4e4ea45
user: natefoo
date: 2011-11-02 15:49:17
summary: Fix a merge error in model/__init__.py
affected #: 1 file
diff -r ce2673f8f2122c4d2cf455f35b9bdc42b540a373 -r 574db4e4ea45c90d02c89110879ace47085a1ac4 lib/galaxy/model/__init__.py
--- a/lib/galaxy/model/__init__.py
+++ b/lib/galaxy/model/__init__.py
@@ -480,23 +480,6 @@
rval = galaxy.datatypes.data.nice_size( rval )
return rval
- def get_api_value( self, view='collection', value_mapper = None ):
- if value_mapper is None:
- value_mapper = {}
- rval = {}
- try:
- visible_keys = self.__getattribute__( 'api_' + view + '_visible_keys' )
- except AttributeError:
- raise Exception( 'Unknown API view: %s' % view )
- for key in visible_keys:
- try:
- rval[key] = self.__getattribute__( key )
- if key in value_mapper:
- rval[key] = value_mapper.get( key )( rval[key] )
- except AttributeError:
- rval[key] = None
- return rval
-
class HistoryUserShareAssociation( object ):
def __init__( self ):
self.history = None
@@ -1149,28 +1132,6 @@
return hda_name
def get_access_roles( self, trans ):
return self.dataset.get_access_roles( trans )
- def get_api_value( self, view='collection' ):
- # Since this class is a proxy to rather complex attributes we want to
- # display in other objects, we can't use the simpler method used by
- # other model classes.
- hda = self
- rval = dict( name = hda.name,
- extension = hda.extension,
- deleted = hda.deleted,
- visible = hda.visible,
- state = hda.state,
- file_size = int( hda.get_size() ),
- genome_build = hda.dbkey,
- misc_info = hda.info,
- misc_blurb = hda.blurb )
- for name, spec in hda.metadata.spec.items():
- val = hda.metadata.get( name )
- if isinstance( val, MetadataFile ):
- val = val.file_name
- elif isinstance( val, list ):
- val = ', '.join( [str(v) for v in val] )
- rval['metadata_' + name] = val
- return rval
def quota_amount( self, user ):
"""
If the user has multiple instances of this dataset, it will not affect their disk usage statistic.
https://bitbucket.org/galaxy/galaxy-central/changeset/9ec467c9268d/
changeset: 9ec467c9268d
user: natefoo
date: 2011-11-02 17:08:40
summary: Run as user: Removed a few more chmods that shouldn't be necessary with everything happening in the job working directory.
affected #: 4 files
diff -r 574db4e4ea45c90d02c89110879ace47085a1ac4 -r 9ec467c9268d58d995b81cec3499804d572d5430 lib/galaxy/jobs/runners/drmaa.py
--- a/lib/galaxy/jobs/runners/drmaa.py
+++ b/lib/galaxy/jobs/runners/drmaa.py
@@ -365,20 +365,17 @@
def stop_job( self, job ):
"""Attempts to delete a job from the DRM queue"""
- if self.external_killJob_script is None:
- try:
- self.ds.control( job.job_runner_external_id, drmaa.JobControlAction.TERMINATE )
- log.debug( "(%s/%s) Removed from DRM queue at user's request" % ( job.id, job.job_runner_external_id ) )
- except drmaa.InvalidJobException:
- log.debug( "(%s/%s) User killed running job, but it was already dead" % ( job.id, job.job_runner_external_id ) )
- except Exception, e:
- log.debug( "(%s/%s) User killed running job, but error encountered removing from DRM queue: %s" % ( job.id, job.job_runner_external_id, e ) )
- else:
- try:
- subprocess.Popen(['/usr/bin/sudo','-E', self.external_killJob_script, str(job.job_runner_external_id), str(self.job_user_uid[2])],shell=False)
- log.debug( "(%s/%s) Removed from DRM queue at user's request" % ( job.id, job.job_runner_external_id ) )
- except Exception, e:
- log.debug( "(%s/%s) User killed running job, but error encountered removing from DRM queue: %s" % ( job.id, job.job_runner_external_id, e ) )
+ try:
+ if self.external_killJob_script is None:
+ self.ds.control( job.job_runner_external_id, drmaa.JobControlAction.TERMINATE )
+ else:
+ # FIXME: hardcoded path
+ subprocess.Popen( [ '/usr/bin/sudo', '-E', self.external_killJob_script, str( job.job_runner_external_id ), str( self.job_user_uid[2] ) ], shell=False )
+ log.debug( "(%s/%s) Removed from DRM queue at user's request" % ( job.id, job.job_runner_external_id ) )
+ except drmaa.InvalidJobException:
+ log.debug( "(%s/%s) User killed running job, but it was already dead" % ( job.id, job.job_runner_external_id ) )
+ except Exception, e:
+ log.debug( "(%s/%s) User killed running job, but error encountered removing from DRM queue: %s" % ( job.id, job.job_runner_external_id, e ) )
def recover( self, job, job_wrapper ):
"""Recovers jobs stuck in the queued/running state when Galaxy started"""
diff -r 574db4e4ea45c90d02c89110879ace47085a1ac4 -r 9ec467c9268d58d995b81cec3499804d572d5430 lib/galaxy/model/__init__.py
--- a/lib/galaxy/model/__init__.py
+++ b/lib/galaxy/model/__init__.py
@@ -653,7 +653,6 @@
# Create directory if it does not exist
if not os.path.exists( dir ):
os.makedirs( dir )
- os.chmod(dir, 0777)
# Return filename inside hashed directory
return os.path.abspath( os.path.join( dir, "dataset_%d.dat" % self.id ) )
else:
@@ -1795,8 +1794,6 @@
# File Exists is okay, otherwise reraise
if e.errno != errno.EEXIST:
raise
-
- os.chmod(path, 0777)
# Return filename inside hashed directory
return os.path.abspath( os.path.join( path, "metadata_%d.dat" % self.id ) )
diff -r 574db4e4ea45c90d02c89110879ace47085a1ac4 -r 9ec467c9268d58d995b81cec3499804d572d5430 lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -1707,10 +1707,10 @@
fd, config_filename = tempfile.mkstemp( dir=directory )
os.close( fd )
f = open( config_filename, "wt" )
- os.chmod(config_filename, 0777)
f.write( fill_template( template_text, context=param_dict ) )
f.close()
- os.chmod(config_filename, 0777)
+ # For running jobs as the actual user, ensure the config file is globally readable
+ os.chmod( config_filename, 0644 )
param_dict[name] = config_filename
config_filenames.append( config_filename )
return config_filenames
@@ -1843,25 +1843,23 @@
"""
for name, hda in output.items():
temp_file_path = os.path.join( job_working_directory, "dataset_%s_files" % ( hda.dataset.id ) )
- #try:
- if os.path.exists(temp_file_path) and len( os.listdir( temp_file_path ) ) > 0:
- store_file_path = os.path.join(
- os.path.join( self.app.config.file_path, *directory_hash_id( hda.dataset.id ) ),
+ try:
+ if len( os.listdir( temp_file_path ) ) > 0:
+ store_file_path = os.path.join(
+ os.path.join( self.app.config.file_path, *directory_hash_id( hda.dataset.id ) ),
"dataset_%d_files" % hda.dataset.id )
- os.mkdir(store_file_path)
- os.system('mv %s/* %s/' %(temp_file_path ,store_file_path))
- # Fix permissions
- if self.external_runJob_script == None:
+ shutil.move( temp_file_path, store_file_path )
+ # Fix permissions
for basedir, dirs, files in os.walk( store_file_path ):
util.umask_fix_perms( basedir, self.app.config.umask, 0777, self.app.config.gid )
for file in files:
path = os.path.join( basedir, file )
# Ignore symlinks
if os.path.islink( path ):
- continue
+ continue
util.umask_fix_perms( path, self.app.config.umask, 0666, self.app.config.gid )
- #except:
- #continue
+ except:
+ continue
def collect_child_datasets( self, output):
"""
diff -r 574db4e4ea45c90d02c89110879ace47085a1ac4 -r 9ec467c9268d58d995b81cec3499804d572d5430 lib/galaxy/tools/actions/__init__.py
--- a/lib/galaxy/tools/actions/__init__.py
+++ b/lib/galaxy/tools/actions/__init__.py
@@ -282,12 +282,9 @@
trans.sa_session.flush()
trans.app.security_agent.set_all_dataset_permissions( data.dataset, output_permissions )
# Create an empty file immediately
- self.external_runJob_script = trans.app.config.drmaa_external_runjob_script
- if self.external_runJob_script == None:
- open( data.file_name, "w" ).close()
- # Fix permissions
- util.umask_fix_perms( data.file_name, trans.app.config.umask, 0666)
- log.debug('.DAT file name = %s\n' %(data.file_name))
+ open( data.file_name, "w" ).close()
+ # Fix permissions
+ util.umask_fix_perms( data.file_name, trans.app.config.umask, 0666)
# This may not be neccesary with the new parent/child associations
data.designation = name
# Copy metadata from one of the inputs if requested.
https://bitbucket.org/galaxy/galaxy-central/changeset/f701f2805fff/
changeset: f701f2805fff
user: natefoo
date: 2011-11-04 00:03:55
summary: Fix for splitting with outputs_to_working_directory = True, also rename a dict and method in jobs to refer to hda instead of dataset to avoid (my own) confusion.
affected #: 4 files
diff -r 9ec467c9268d58d995b81cec3499804d572d5430 -r f701f2805fff88e6ad94d40b00dd8dc72f0ef48f lib/galaxy/jobs/__init__.py
--- a/lib/galaxy/jobs/__init__.py
+++ b/lib/galaxy/jobs/__init__.py
@@ -327,7 +327,7 @@
self.working_directory = \
os.path.join( self.app.config.job_working_directory, str( self.job_id ) )
self.output_paths = None
- self.output_dataset_paths = None
+ self.output_hdas_and_paths = None
self.tool_provided_job_metadata = None
# Wrapper holding the info required to restore and clean up from files used for setting metadata externally
self.external_output_metadata = metadata.JobExternalOutputMetadataWrapper( job )
@@ -764,10 +764,10 @@
self.compute_outputs()
return self.output_paths
- def get_output_datasets_and_fnames( self ):
- if self.output_dataset_paths is None:
+ def get_output_hdas_and_fnames( self ):
+ if self.output_hdas_and_paths is None:
self.compute_outputs()
- return self.output_dataset_paths
+ return self.output_hdas_and_paths
def compute_outputs( self ) :
class DatasetPath( object ):
@@ -786,18 +786,18 @@
jeha_false_path = None
if self.app.config.outputs_to_working_directory:
self.output_paths = []
- self.output_dataset_paths = {}
- for name, data in [ ( da.name, da.dataset.dataset ) for da in job.output_datasets + job.output_library_datasets ]:
- false_path = os.path.abspath( os.path.join( self.working_directory, "galaxy_dataset_%d.dat" % data.id ) )
- dsp = DatasetPath( data.id, data.file_name, false_path )
+ self.output_hdas_and_paths = {}
+ for name, hda in [ ( da.name, da.dataset ) for da in job.output_datasets + job.output_library_datasets ]:
+ false_path = os.path.abspath( os.path.join( self.working_directory, "galaxy_dataset_%d.dat" % hda.dataset.id ) )
+ dsp = DatasetPath( hda.dataset.id, hda.dataset.file_name, false_path )
self.output_paths.append( dsp )
- self.output_dataset_paths[name] = data, dsp
+ self.output_hdas_and_paths[name] = hda, dsp
if jeha:
jeha_false_path = os.path.abspath( os.path.join( self.working_directory, "galaxy_dataset_%d.dat" % jeha.dataset.id ) )
else:
- results = [ (da.name, da.dataset, DatasetPath( da.dataset.dataset.id, da.dataset.file_name )) for da in job.output_datasets + job.output_library_datasets ]
+ results = [ ( da.name, da.dataset, DatasetPath( da.dataset.dataset.id, da.dataset.file_name ) ) for da in job.output_datasets + job.output_library_datasets ]
self.output_paths = [t[2] for t in results]
- self.output_dataset_paths = dict([(t[0], t[1:]) for t in results])
+ self.output_hdas_and_paths = dict([(t[0], t[1:]) for t in results])
if jeha:
dsp = DatasetPath( jeha.dataset.id, jeha.dataset.file_name, jeha_false_path )
self.output_paths.append( dsp )
diff -r 9ec467c9268d58d995b81cec3499804d572d5430 -r f701f2805fff88e6ad94d40b00dd8dc72f0ef48f lib/galaxy/jobs/splitters/basic.py
--- a/lib/galaxy/jobs/splitters/basic.py
+++ b/lib/galaxy/jobs/splitters/basic.py
@@ -6,7 +6,7 @@
def set_basic_defaults(job_wrapper):
parent_job = job_wrapper.get_job()
job_wrapper.tool.parallelism.attributes['split_inputs'] = parent_job.input_datasets[0].name
- job_wrapper.tool.parallelism.attributes['merge_outputs'] = job_wrapper.get_output_datasets_and_fnames().keys()[0]
+ job_wrapper.tool.parallelism.attributes['merge_outputs'] = job_wrapper.get_output_hdas_and_fnames().keys()[0]
def do_split (job_wrapper):
if len(job_wrapper.get_input_fnames()) > 1 or len(job_wrapper.get_output_fnames()) > 1:
diff -r 9ec467c9268d58d995b81cec3499804d572d5430 -r f701f2805fff88e6ad94d40b00dd8dc72f0ef48f lib/galaxy/jobs/splitters/multi.py
--- a/lib/galaxy/jobs/splitters/multi.py
+++ b/lib/galaxy/jobs/splitters/multi.py
@@ -33,7 +33,6 @@
subdir_index[0] = subdir_index[0] + 1
if not os.path.exists(dir):
os.makedirs(dir)
- os.chmod(dir,0777)
task_dirs.append(dir)
return dir
@@ -118,7 +117,7 @@
working_directory = job_wrapper.working_directory
task_dirs = [os.path.join(working_directory, x) for x in os.listdir(working_directory) if x.startswith('task_')]
# TODO: Output datasets can be very complex. This doesn't handle metadata files
- outputs = job_wrapper.get_output_datasets_and_fnames()
+ outputs = job_wrapper.get_output_hdas_and_fnames()
pickone_done = []
task_dirs = [os.path.join(working_directory, x) for x in os.listdir(working_directory) if x.startswith('task_')]
for output in outputs:
@@ -143,6 +142,7 @@
raise Exception(log_error)
except Exception, e:
stdout = 'Error merging files';
+ log.exception( stdout )
stderr = str(e)
https://bitbucket.org/galaxy/galaxy-central/changeset/89ade2dfb20a/
changeset: 89ade2dfb20a
user: ichorny
date: 2011-11-04 18:47:40
summary: Fix for killing jobs using external jobKillin script
affected #: 1 file
diff -r f701f2805fff88e6ad94d40b00dd8dc72f0ef48f -r 89ade2dfb20a1167305df832c6d5eaabf671c2a0 lib/galaxy/jobs/runners/drmaa.py
--- a/lib/galaxy/jobs/runners/drmaa.py
+++ b/lib/galaxy/jobs/runners/drmaa.py
@@ -113,6 +113,7 @@
self.external_runJob_script = app.config.drmaa_external_runjob_script
self.external_killJob_script = app.config.drmaa_external_killjob_script
self.TMPDIR = app.config.TMPDIR
+ self.userid = []
def get_native_spec( self, url ):
"""Get any native DRM arguments specified by the site configuration"""
@@ -215,6 +216,7 @@
job_wrapper.change_ownership_for_run()
log.debug( '(%s) submitting with credentials: %s [uid: %s]' % ( galaxy_id_tag, job_wrapper.user_system_pwent[0], job_wrapper.user_system_pwent[2] ) )
filename = self.store_jobtemplate(job_wrapper, jt)
+ self.userid = job_wrapper.user_system_pwent[2]
job_id = self.external_runjob(filename, job_wrapper.user_system_pwent[2]).strip()
log.info("(%s) queued as %s" % ( galaxy_id_tag, job_id ) )
@@ -370,7 +372,7 @@
self.ds.control( job.job_runner_external_id, drmaa.JobControlAction.TERMINATE )
else:
# FIXME: hardcoded path
- subprocess.Popen( [ '/usr/bin/sudo', '-E', self.external_killJob_script, str( job.job_runner_external_id ), str( self.job_user_uid[2] ) ], shell=False )
+ subprocess.Popen( [ '/usr/bin/sudo', '-E', self.external_killJob_script, str( job.job_runner_external_id ), str( self.userid ) ], shell=False )
log.debug( "(%s/%s) Removed from DRM queue at user's request" % ( job.id, job.job_runner_external_id ) )
except drmaa.InvalidJobException:
log.debug( "(%s/%s) User killed running job, but it was already dead" % ( job.id, job.job_runner_external_id ) )
https://bitbucket.org/galaxy/galaxy-central/changeset/42c8a6cfaa5b/
changeset: 42c8a6cfaa5b
user: ichorny
date: 2011-11-05 00:59:30
summary: made a change to sniff.py to copyfile instead of move. Move fails when running as actual user
affected #: 1 file
diff -r 89ade2dfb20a1167305df832c6d5eaabf671c2a0 -r 42c8a6cfaa5b76204e978eedfd17647b05531b13 lib/galaxy/datatypes/sniff.py
--- a/lib/galaxy/datatypes/sniff.py
+++ b/lib/galaxy/datatypes/sniff.py
@@ -95,7 +95,7 @@
fp.write( "%s\n" % line.rstrip( "\r\n" ) )
fp.close()
if in_place:
- shutil.move( temp_name, fname )
+ shutil.copyfile( temp_name, fname )
# Return number of lines in file.
return ( i + 1, None )
else:
https://bitbucket.org/galaxy/galaxy-central/changeset/f05722e66a8a/
changeset: f05722e66a8a
user: natefoo
date: 2011-11-07 20:17:43
summary: merge.
affected #: 64 files
diff -r 42c8a6cfaa5b76204e978eedfd17647b05531b13 -r f05722e66a8a42e75f01a29b723ed50525e77e55 lib/galaxy/config.py
--- a/lib/galaxy/config.py
+++ b/lib/galaxy/config.py
@@ -71,6 +71,7 @@
self.allow_user_creation = string_as_bool( kwargs.get( "allow_user_creation", "True" ) )
self.allow_user_deletion = string_as_bool( kwargs.get( "allow_user_deletion", "False" ) )
self.allow_user_dataset_purge = string_as_bool( kwargs.get( "allow_user_dataset_purge", "False" ) )
+ self.allow_user_impersonation = string_as_bool( kwargs.get( "allow_user_impersonation", "False" ) )
self.new_user_dataset_access_role_default_private = string_as_bool( kwargs.get( "new_user_dataset_access_role_default_private", "False" ) )
self.template_path = resolve_path( kwargs.get( "template_path", "templates" ), self.root )
self.template_cache = resolve_path( kwargs.get( "template_cache_path", "database/compiled_templates" ), self.root )
diff -r 42c8a6cfaa5b76204e978eedfd17647b05531b13 -r f05722e66a8a42e75f01a29b723ed50525e77e55 lib/galaxy/datatypes/data.py
--- a/lib/galaxy/datatypes/data.py
+++ b/lib/galaxy/datatypes/data.py
@@ -462,15 +462,16 @@
dataset.peek = 'file does not exist'
dataset.blurb = 'file purged from disk'
- def split( input_files, subdir_generator_function, split_params):
+ def split( cls, input_datasets, subdir_generator_function, split_params):
"""
Split the input files by line.
"""
if split_params is None:
return
- if len(input_files) > 1:
+ if len(input_datasets) > 1:
raise Exception("Text file splitting does not support multiple files")
+ input_files = [ds.file_name for ds in input_datasets]
lines_per_file = None
chunk_size = None
@@ -534,7 +535,7 @@
part_file.close()
raise
f.close()
- split = staticmethod(split)
+ split = classmethod(split)
class LineCount( Text ):
"""
diff -r 42c8a6cfaa5b76204e978eedfd17647b05531b13 -r f05722e66a8a42e75f01a29b723ed50525e77e55 lib/galaxy/datatypes/display_applications/parameters.py
--- a/lib/galaxy/datatypes/display_applications/parameters.py
+++ b/lib/galaxy/datatypes/display_applications/parameters.py
@@ -94,13 +94,11 @@
if target_ext and not converted_dataset:
if isinstance( data, DisplayDataValueWrapper ):
data = data.value
- assoc = trans.app.model.ImplicitlyConvertedDatasetAssociation( parent = data, file_type = target_ext, metadata_safe = False )
new_data = data.datatype.convert_dataset( trans, data, target_ext, return_output = True, visible = False ).values()[0]
new_data.hid = data.hid
new_data.name = data.name
trans.sa_session.add( new_data )
- trans.sa_session.flush()
- assoc.dataset = new_data
+ assoc = trans.app.model.ImplicitlyConvertedDatasetAssociation( parent = data, file_type = target_ext, dataset = new_data, metadata_safe = False )
trans.sa_session.add( assoc )
trans.sa_session.flush()
elif converted_dataset and converted_dataset.state == converted_dataset.states.ERROR:
diff -r 42c8a6cfaa5b76204e978eedfd17647b05531b13 -r f05722e66a8a42e75f01a29b723ed50525e77e55 lib/galaxy/datatypes/genetics.py
--- a/lib/galaxy/datatypes/genetics.py
+++ b/lib/galaxy/datatypes/genetics.py
@@ -192,27 +192,9 @@
Tabular.__init__( self, **kwd )
self.column_names = []
- def make_html_table( self, dataset, skipchars=[] ):
- """
- Create HTML table, used for displaying peek
- """
- out = ['<table cellspacing="0" cellpadding="3">']
- comments = []
- try:
- # Generate column header
- out.append( '<tr>' )
- for i, name in enumerate( self.column_names ):
- out.append( '<th>%s.%s</th>' % ( str( i+1 ), name ) )
- if dataset.metadata.columns - len( self.column_names ) > 0:
- for i in range( len( self.column_names ), dataset.metadata.columns ):
- out.append( '<th>%s</th>' % str( i+1 ) )
- out.append( '</tr>' )
- out.append( self.make_html_peek_rows( dataset, skipchars=skipchars ) )
- out.append( '</table>' )
- out = "".join( out )
- except Exception, exc:
- out = "Can't create peek %s" % exc
- return out
+ def display_peek( self, dataset ):
+ """Returns formated html of peek"""
+ return Tabular.make_html_table( self, dataset, column_names=self.column_names )
def get_mime(self):
"""Returns the mime type of the datatype"""
diff -r 42c8a6cfaa5b76204e978eedfd17647b05531b13 -r f05722e66a8a42e75f01a29b723ed50525e77e55 lib/galaxy/datatypes/interval.py
--- a/lib/galaxy/datatypes/interval.py
+++ b/lib/galaxy/datatypes/interval.py
@@ -219,33 +219,9 @@
os.write(fd, '%s\n' % '\t'.join(tmp) )
os.close(fd)
return open(temp_name)
- def make_html_table( self, dataset, skipchars=[] ):
- """Create HTML table, used for displaying peek"""
- out = ['<table cellspacing="0" cellpadding="3">']
- comments = []
- try:
- # Generate column header
- out.append('<tr>')
- for i in range( 1, dataset.metadata.columns+1 ):
- if i == dataset.metadata.chromCol:
- out.append( '<th>%s.Chrom</th>' % i )
- elif i == dataset.metadata.startCol:
- out.append( '<th>%s.Start</th>' % i )
- elif i == dataset.metadata.endCol:
- out.append( '<th>%s.End</th>' % i )
- elif dataset.metadata.strandCol and i == dataset.metadata.strandCol:
- out.append( '<th>%s.Strand</th>' % i )
- elif dataset.metadata.nameCol and i == dataset.metadata.nameCol:
- out.append( '<th>%s.Name</th>' % i )
- else:
- out.append( '<th>%s</th>' % i )
- out.append('</tr>')
- out.append( self.make_html_peek_rows( dataset, skipchars=skipchars ) )
- out.append( '</table>' )
- out = "".join( out )
- except Exception, exc:
- out = "Can't create peek %s" % str( exc )
- return out
+ def display_peek( self, dataset ):
+ """Returns formated html of peek"""
+ return Tabular.make_html_table( self, dataset, column_parameter_alias={'chromCol':'Chrom', 'startCol':'Start', 'endCol':'End', 'strandCol':'Strand', 'nameCol':'Name'} )
def ucsc_links( self, dataset, type, app, base_url ):
"""
Generate links to UCSC genome browser sites based on the dbkey
@@ -617,21 +593,9 @@
except:
pass
Tabular.set_meta( self, dataset, overwrite = overwrite, skip = i )
- def make_html_table( self, dataset, skipchars=[] ):
- """Create HTML table, used for displaying peek"""
- out = ['<table cellspacing="0" cellpadding="3">']
- comments = []
- try:
- # Generate column header
- out.append( '<tr>' )
- for i, name in enumerate( self.column_names ):
- out.append( '<th>%s.%s</th>' % ( str( i+1 ), name ) )
- out.append( self.make_html_peek_rows( dataset, skipchars=skipchars ) )
- out.append( '</table>' )
- out = "".join( out )
- except Exception, exc:
- out = "Can't create peek %s" % exc
- return out
+ def display_peek( self, dataset ):
+ """Returns formated html of peek"""
+ return Tabular.make_html_table( self, dataset, column_names=self.column_names )
def get_estimated_display_viewport( self, dataset ):
"""
Return a chrom, start, stop tuple for viewing a file. There are slight differences between gff 2 and gff 3
@@ -1081,7 +1045,8 @@
link = self._get_remote_call_url( redirect_url, site_name, dataset, type, app, base_url )
ret_val.append( ( site_name, link ) )
return ret_val
- def make_html_table( self, dataset ):
+ def display_peek( self, dataset ):
+ """Returns formated html of peek"""
return Tabular.make_html_table( self, dataset, skipchars=['track', '#'] )
def set_meta( self, dataset, overwrite = True, **kwd ):
max_data_lines = None
diff -r 42c8a6cfaa5b76204e978eedfd17647b05531b13 -r f05722e66a8a42e75f01a29b723ed50525e77e55 lib/galaxy/datatypes/tabular.py
--- a/lib/galaxy/datatypes/tabular.py
+++ b/lib/galaxy/datatypes/tabular.py
@@ -164,64 +164,69 @@
dataset.metadata.comment_lines = comment_lines
dataset.metadata.column_types = column_types
dataset.metadata.columns = len( column_types )
- def make_html_table( self, dataset, skipchars=[] ):
+ def make_html_table( self, dataset, **kwargs ):
"""Create HTML table, used for displaying peek"""
out = ['<table cellspacing="0" cellpadding="3">']
try:
- out.append( '<tr>' )
- # Generate column header
- for i in range( 1, dataset.metadata.columns+1 ):
- out.append( '<th>%s</th>' % str( i ) )
- out.append( '</tr>' )
- out.append( self.make_html_peek_rows( dataset, skipchars=skipchars ) )
+ out.append( self.make_html_peek_header( dataset, **kwargs ) )
+ out.append( self.make_html_peek_rows( dataset, **kwargs ) )
out.append( '</table>' )
out = "".join( out )
except Exception, exc:
out = "Can't create peek %s" % str( exc )
return out
- def make_html_peek_rows( self, dataset, skipchars=[] ):
- out = [""]
- comments = []
- if not dataset.peek:
- dataset.set_peek()
- data = dataset.peek
- lines = data.splitlines()
- for line in lines:
- line = line.rstrip( '\r\n' )
- if not line:
- continue
- comment = False
- for skipchar in skipchars:
- if line.startswith( skipchar ):
- comments.append( line )
- comment = True
- break
- if comment:
- continue
- elems = line.split( '\t' )
- if len( elems ) != dataset.metadata.columns:
- # We may have an invalid comment line or invalid data
- comments.append( line )
- comment = True
- continue
- while len( comments ) > 0: # Keep comments
- try:
- out.append( '<tr><td colspan="100%">' )
- except:
- out.append( '<tr><td>' )
- out.append( '%s</td></tr>' % escape( comments.pop(0) ) )
+ def make_html_peek_header( self, dataset, skipchars=[], column_names=[], column_number_format='%s', column_parameter_alias={}, **kwargs ):
+ out = []
+ try:
+ column_headers = [None] * dataset.metadata.columns
+
+ # fill in empty headers with data from column_names
+ for i in range( min( dataset.metadata.columns, len( column_names ) ) ):
+ if column_headers[i] is None and column_names[i] is not None:
+ column_headers[i] = column_names[i]
+
+ # fill in empty headers from ColumnParameters set in the metadata
+ for name, spec in dataset.metadata.spec.items():
+ if isinstance( spec.param, metadata.ColumnParameter ):
+ try:
+ i = int( getattr( dataset.metadata, name ) ) - 1
+ except:
+ i = -1
+ if 0 <= i < dataset.metadata.columns and column_headers[i] is None:
+ column_headers[i] = column_parameter_alias.get(name, name)
+
out.append( '<tr>' )
- for elem in elems: # valid data
- elem = escape( elem )
- out.append( '<td>%s</td>' % elem )
+ for i, header in enumerate( column_headers ):
+ out.append( '<th>' )
+ if header is None:
+ out.append( column_number_format % str( i + 1 ) )
+ else:
+ out.append( '%s.%s' % ( str( i + 1 ), escape( header ) ) )
+ out.append( '</th>' )
out.append( '</tr>' )
- # Peek may consist only of comments
- while len( comments ) > 0:
- try:
- out.append( '<tr><td colspan="100%">' )
- except:
- out.append( '<tr><td>' )
- out.append( '%s</td></tr>' % escape( comments.pop(0) ) )
+ except Exception, exc:
+ raise Exception, "Can't create peek header %s" % str( exc )
+ return "".join( out )
+ def make_html_peek_rows( self, dataset, skipchars=[], **kwargs ):
+ out = []
+ try:
+ if not dataset.peek:
+ dataset.set_peek()
+ for line in dataset.peek.splitlines():
+ if line.startswith( tuple( skipchars ) ):
+ out.append( '<tr><td colspan="100%%">%s</td></tr>' % escape( line ) )
+ elif line:
+ elems = line.split( '\t' )
+ # we may have an invalid comment line or invalid data
+ if len( elems ) != dataset.metadata.columns:
+ out.append( '<tr><td colspan="100%%">%s</td></tr>' % escape( line ) )
+ else:
+ out.append( '<tr>' )
+ for elem in elems:
+ out.append( '<td>%s</td>' % escape( elem ) )
+ out.append( '</tr>' )
+ except Exception, exc:
+ raise Exception, "Can't create peek rows %s" % str( exc )
return "".join( out )
def set_peek( self, dataset, line_count=None, is_multi_byte=False):
super(Tabular, self).set_peek( dataset, line_count=line_count, is_multi_byte=is_multi_byte)
@@ -252,26 +257,9 @@
'Superorder', 'Order', 'Suborder', 'Superfamily', 'Family', 'Subfamily',
'Tribe', 'Subtribe', 'Genus', 'Subgenus', 'Species', 'Subspecies'
]
- def make_html_table( self, dataset, skipchars=[] ):
- """Create HTML table, used for displaying peek"""
- out = ['<table cellspacing="0" cellpadding="3">']
- comments = []
- try:
- # Generate column header
- out.append( '<tr>' )
- for i, name in enumerate( self.column_names ):
- out.append( '<th>%s.%s</th>' % ( str( i+1 ), name ) )
- # This data type requires at least 24 columns in the data
- if dataset.metadata.columns - len( self.column_names ) > 0:
- for i in range( len( self.column_names ), dataset.metadata.columns ):
- out.append( '<th>%s</th>' % str( i+1 ) )
- out.append( '</tr>' )
- out.append( self.make_html_peek_rows( dataset, skipchars=skipchars ) )
- out.append( '</table>' )
- out = "".join( out )
- except Exception, exc:
- out = "Can't create peek %s" % exc
- return out
+ def display_peek( self, dataset ):
+ """Returns formated html of peek"""
+ return Tabular.make_html_table( self, dataset, column_names=self.column_names )
class Sam( Tabular ):
file_ext = 'sam'
@@ -281,25 +269,10 @@
self.column_names = ['QNAME', 'FLAG', 'RNAME', 'POS', 'MAPQ', 'CIGAR',
'MRNM', 'MPOS', 'ISIZE', 'SEQ', 'QUAL', 'OPT'
]
- def make_html_table( self, dataset, skipchars=[] ):
- """Create HTML table, used for displaying peek"""
- out = ['<table cellspacing="0" cellpadding="3">']
- try:
- # Generate column header
- out.append( '<tr>' )
- for i, name in enumerate( self.column_names ):
- out.append( '<th>%s.%s</th>' % ( str( i+1 ), name ) )
- # This data type requires at least 11 columns in the data
- if dataset.metadata.columns - len( self.column_names ) > 0:
- for i in range( len( self.column_names ), dataset.metadata.columns ):
- out.append( '<th>%s</th>' % str( i+1 ) )
- out.append( '</tr>' )
- out.append( self.make_html_peek_rows( dataset, skipchars=skipchars ) )
- out.append( '</table>' )
- out = "".join( out )
- except Exception, exc:
- out = "Can't create peek %s" % exc
- return out
+ def display_peek( self, dataset ):
+ """Returns formated html of peek"""
+ return Tabular.make_html_table( self, dataset, column_names=self.column_names )
+
def sniff( self, filename ):
"""
Determines whether the file is in SAM format
@@ -393,29 +366,9 @@
def init_meta( self, dataset, copy_from=None ):
Tabular.init_meta( self, dataset, copy_from=copy_from )
- def make_html_table( self, dataset, skipchars=[] ):
- """Create HTML table, used for displaying peek"""
- out = ['<table cellspacing="0" cellpadding="3">']
- comments = []
- try:
- # Generate column header
- out.append('<tr>')
- for i in range( 1, dataset.metadata.columns+1 ):
- if i == dataset.metadata.chromCol:
- out.append( '<th>%s.Chrom</th>' % i )
- elif i == dataset.metadata.startCol:
- out.append( '<th>%s.Start</th>' % i )
- elif i == dataset.metadata.baseCol:
- out.append( '<th>%s.Base</th>' % i )
- else:
- out.append( '<th>%s</th>' % i )
- out.append('</tr>')
- out.append( self.make_html_peek_rows( dataset, skipchars=skipchars ) )
- out.append( '</table>' )
- out = "".join( out )
- except Exception, exc:
- out = "Can't create peek %s" % str( exc )
- return out
+ def display_peek( self, dataset ):
+ """Returns formated html of peek"""
+ return Tabular.make_html_table( self, dataset, column_parameter_alias={'chromCol':'Chrom', 'startCol':'Start', 'baseCol':'Base'} )
def repair_methods( self, dataset ):
"""Return options for removing errors along with a description"""
@@ -481,21 +434,9 @@
def sniff( self, filename ):
headers = get_headers( filename, '\n', count=1 )
return headers[0][0].startswith("##fileformat=VCF")
+ def display_peek( self, dataset ):
+ """Returns formated html of peek"""
+ return Tabular.make_html_table( self, dataset, column_names=self.column_names )
- def make_html_table( self, dataset, skipchars=[] ):
- """Create HTML table, used for displaying peek"""
- out = ['<table cellspacing="0" cellpadding="3">']
- try:
- # Generate column header
- out.append( '<tr>' )
- for i, name in enumerate( self.column_names ):
- out.append( '<th>%s.%s</th>' % ( str( i+1 ), name ) )
- out.append( self.make_html_peek_rows( dataset, skipchars=skipchars ) )
- out.append( '</table>' )
- out = "".join( out )
- except Exception, exc:
- out = "Can't create peek %s" % exc
- return out
-
def get_track_type( self ):
- return "FeatureTrack", {"data": "tabix", "index": "summary_tree"}
+ return "VcfTrack", {"data": "tabix", "index": "summary_tree"}
diff -r 42c8a6cfaa5b76204e978eedfd17647b05531b13 -r f05722e66a8a42e75f01a29b723ed50525e77e55 lib/galaxy/tools/actions/__init__.py
--- a/lib/galaxy/tools/actions/__init__.py
+++ b/lib/galaxy/tools/actions/__init__.py
@@ -43,13 +43,11 @@
data = converted_dataset
else:
#run converter here
- assoc = trans.app.model.ImplicitlyConvertedDatasetAssociation( parent = data, file_type = target_ext, metadata_safe = False )
new_data = data.datatype.convert_dataset( trans, data, target_ext, return_output = True, visible = False ).values()[0]
new_data.hid = data.hid
new_data.name = data.name
trans.sa_session.add( new_data )
- trans.sa_session.flush()
- assoc.dataset = new_data
+ assoc = trans.app.model.ImplicitlyConvertedDatasetAssociation( parent = data, file_type = target_ext, dataset = new_data, metadata_safe = False )
trans.sa_session.add( assoc )
trans.sa_session.flush()
data = new_data
diff -r 42c8a6cfaa5b76204e978eedfd17647b05531b13 -r f05722e66a8a42e75f01a29b723ed50525e77e55 lib/galaxy/visualization/tracks/data_providers.py
--- a/lib/galaxy/visualization/tracks/data_providers.py
+++ b/lib/galaxy/visualization/tracks/data_providers.py
@@ -135,10 +135,137 @@
{ 'name' : attrs[ 'name' ], 'type' : column_types[viz_col_index], \
'index' : attrs[ 'index' ] } )
return filters
+
+#
+# -- Base mixins and providers --
+#
+
+class FilterableMixin:
+ def get_filters( self ):
+ """ Returns a dataset's filters. """
+
+ # is_ functions taken from Tabular.set_meta
+ def is_int( column_text ):
+ try:
+ int( column_text )
+ return True
+ except:
+ return False
+ def is_float( column_text ):
+ try:
+ float( column_text )
+ return True
+ except:
+ if column_text.strip().lower() == 'na':
+ return True #na is special cased to be a float
+ return False
+
+ #
+ # Get filters.
+ # TODOs:
+ # (a) might be useful to move this into each datatype's set_meta method;
+ # (b) could look at first N lines to ensure GTF attribute types are consistent.
+ #
+ filters = []
+ # HACK: first 8 fields are for drawing, so start filter column index at 9.
+ filter_col = 8
+ if isinstance( self.original_dataset.datatype, Gff ):
+ # Can filter by score and GTF attributes.
+ filters = [ { 'name': 'Score',
+ 'type': 'int',
+ 'index': filter_col,
+ 'tool_id': 'Filter1',
+ 'tool_exp_name': 'c6' } ]
+ filter_col += 1
+ if isinstance( self.original_dataset.datatype, Gtf ):
+ # Create filters based on dataset metadata.
+ for name, a_type in self.original_dataset.metadata.attribute_types.items():
+ if a_type in [ 'int', 'float' ]:
+ filters.append(
+ { 'name': name,
+ 'type': a_type,
+ 'index': filter_col,
+ 'tool_id': 'gff_filter_by_attribute',
+ 'tool_exp_name': name } )
+ filter_col += 1
+
+ '''
+ # Old code: use first line in dataset to find attributes.
+ for i, line in enumerate( open(self.original_dataset.file_name) ):
+ if not line.startswith('#'):
+ # Look at first line for attributes and types.
+ attributes = parse_gff_attributes( line.split('\t')[8] )
+ for attr, value in attributes.items():
+ # Get attribute type.
+ if is_int( value ):
+ attr_type = 'int'
+ elif is_float( value ):
+ attr_type = 'float'
+ else:
+ attr_type = 'str'
+ # Add to filters.
+ if attr_type is not 'str':
+ filters.append( { 'name': attr, 'type': attr_type, 'index': filter_col } )
+ filter_col += 1
+ break
+ '''
+ elif isinstance( self.original_dataset.datatype, Bed ):
+ # Can filter by score column only.
+ filters = [ { 'name': 'Score',
+ 'type': 'int',
+ 'index': filter_col,
+ 'tool_id': 'Filter1',
+ 'tool_exp_name': 'c5'
+ } ]
+
+ return filters
+
+
+class TabixDataProvider( FilterableMixin, TracksDataProvider ):
+ """
+ Tabix index data provider for the Galaxy track browser.
+ """
+
+ col_name_data_attr_mapping = { 4 : { 'index': 4 , 'name' : 'Score' } }
+
+ def get_iterator( self, chrom, start, end ):
+ start, end = int(start), int(end)
+ if end >= (2<<29):
+ end = (2<<29 - 1) # Tabix-enforced maximum
+
+ bgzip_fname = self.dependencies['bgzip'].file_name
+
+ # if os.path.getsize(self.converted_dataset.file_name) == 0:
+ # return { 'kind': messages.ERROR, 'message': "Tabix converted size was 0, meaning the input file had invalid values." }
+ tabix = ctabix.Tabixfile(bgzip_fname, index_filename=self.converted_dataset.file_name)
+
+ # If chrom is not found in indexes, try removing the first three
+ # characters (e.g. 'chr') and see if that works. This enables the
+ # provider to handle chrome names defined as chrXXX and as XXX.
+ chrom = str(chrom)
+ if chrom not in tabix.contigs and chrom.startswith("chr") and (chrom[3:] in tabix.contigs):
+ chrom = chrom[3:]
+
+ return tabix.fetch(reference=chrom, start=start, end=end)
+
+ def get_data( self, chrom, start, end, start_val=0, max_vals=None, **kwargs ):
+ iterator = self.get_iterator( chrom, start, end )
+ return self.process_data( iterator, start_val, max_vals, **kwargs )
+
+ def write_data_to_file( self, chrom, start, end, filename ):
+ iterator = self.get_iterator( chrom, start, end )
+ out = open( filename, "w" )
+ for line in iterator:
+ out.write( "%s\n" % line )
+ out.close()
+
+#
+# -- BED data providers --
+#
class BedDataProvider( TracksDataProvider ):
"""
- Abstract class that processes BED data from text format to payload format.
+ Abstract class that processes BED data from native format to payload format.
Payload format: [ uid (offset), start, end, name, strand, thick_start, thick_end, blocks ]
"""
@@ -220,7 +347,168 @@
for line in iterator:
out.write( "%s\n" % line )
out.close()
-
+
+class BedTabixDataProvider( TabixDataProvider, BedDataProvider ):
+ """
+ Provides data from a BED file indexed via tabix.
+ """
+ pass
+
+class RawBedDataProvider( BedDataProvider ):
+ """
+ Provide data from BED file.
+
+ NOTE: this data provider does not use indices, and hence will be very slow
+ for large datasets.
+ """
+
+ def get_iterator( self, chrom, start, end ):
+ def line_filter_iter():
+ for line in open( self.original_dataset.file_name ):
+ feature = line.split()
+ feature_chrom = feature[0]
+ feature_start = int( feature[1] )
+ feature_end = int( feature[2] )
+ if feature_chrom != chrom or feature_start > int( end ) or feature_end < int( start ):
+ continue
+ yield line
+ return line_filter_iter()
+
+#
+# -- VCF data providers --
+#
+
+class VcfDataProvider( TracksDataProvider ):
+ """
+ Abstract class that processes VCF data from native format to payload format.
+
+ Payload format: TODO
+ """
+
+ col_name_data_attr_mapping = { 'Qual' : { 'index': 6 , 'name' : 'Qual' } }
+
+
+ def get_iterator( self, chrom, start, end ):
+ raise "Unimplemented Method"
+
+ def get_data( self, chrom, start, end, start_val=0, max_vals=None, **kwargs ):
+ iterator = self.get_iterator( chrom, start, end )
+ return self.process_data( iterator, start_val, max_vals, **kwargs )
+
+ def process_data( self, iterator, start_val=0, max_vals=None, **kwargs ):
+ """
+ Returns a dict with the following attributes:
+ data - a list of variants with the format
+ [<guid>, <start>, <end>, <name>, cigar, seq]
+
+ message - error/informative message
+ """
+ rval = []
+ message = None
+
+ def get_mapping( ref, alt ):
+ """
+ Returns ( offset, new_seq, cigar ) tuple that defines mapping of
+ alt to ref. Cigar format is an array of [ op_index, length ] pairs
+ where op_index is the 0-based index into the string "MIDNSHP=X"
+ """
+
+ cig_ops = "MIDNSHP=X"
+
+ ref_len = len( ref )
+ alt_len = len( alt )
+
+ # Substitutions?
+ if ref_len == alt_len:
+ return 0, alt, [ [ cig_ops.find( "M" ), ref_len ] ]
+
+ # Deletions?
+ alt_in_ref_index = ref.find( alt )
+ if alt_in_ref_index != -1:
+ return alt_in_ref_index, ref[ alt_in_ref_index + 1: ], [ [ cig_ops.find( "D" ), ref_len - alt_len ] ]
+
+ # Insertions?
+ ref_in_alt_index = alt.find( ref )
+ if ref_in_alt_index != -1:
+ return ref_in_alt_index, alt[ ref_in_alt_index + 1: ], [ [ cig_ops.find( "I" ), alt_len - ref_len ] ]
+
+ # Pack data.
+ for count, line in enumerate( iterator ):
+ if count < start_val:
+ continue
+ if max_vals and count-start_val >= max_vals:
+ message = ERROR_MAX_VALS % ( max_vals, "features" )
+ break
+
+ feature = line.split()
+ start = int( feature[1] ) - 1
+ ref = feature[3]
+ alts = feature[4]
+
+ # HACK? alts == '.' --> monomorphism.
+ if alts == '.':
+ alts = ref
+
+ # Pack variants.
+ for alt in alts.split(","):
+ offset, new_seq, cigar = get_mapping( ref, alt )
+ start += offset
+ end = start + len( new_seq )
+
+ # Pack line.
+ payload = [ hash( line ),
+ start,
+ end,
+ # ID:
+ feature[2],
+ cigar,
+ # TODO? VCF does not have strand, so default to positive.
+ "+",
+ new_seq,
+ float( feature[5] ) ]
+ rval.append(payload)
+
+ return { 'data': rval, 'message': message }
+
+ def write_data_to_file( self, chrom, start, end, filename ):
+ iterator = self.get_iterator( chrom, start, end )
+ out = open( filename, "w" )
+ for line in iterator:
+ out.write( "%s\n" % line )
+ out.close()
+
+class VcfTabixDataProvider( TabixDataProvider, VcfDataProvider ):
+ """
+ Provides data from a VCF file indexed via tabix.
+ """
+ pass
+
+class RawVcfDataProvider( VcfDataProvider ):
+ """
+ Provide data from VCF file.
+
+ NOTE: this data provider does not use indices, and hence will be very slow
+ for large datasets.
+ """
+
+ def get_iterator( self, chrom, 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 > int( end ) or variant_end < int( start ):
+ continue
+ yield line
+ return line_filter_iter()
+
class SummaryTreeDataProvider( TracksDataProvider ):
"""
Summary tree data provider for the Galaxy track browser.
@@ -323,11 +611,11 @@
data - a list of reads with the format
[<guid>, <start>, <end>, <name>, <read_1>, <read_2>]
where <read_1> has the format
- [<start>, <end>, <cigar>, ?<read_seq>?]
+ [<start>, <end>, <cigar>, <strand>, ?<read_seq>?]
and <read_2> has the format
- [<start>, <end>, <cigar>, ?<read_seq>?]
+ [<start>, <end>, <cigar>, <strand>, ?<read_seq>?]
For single-end reads, read has format:
- [<guid>, <start>, <end>, <name>, cigar, seq]
+ [<guid>, <start>, <end>, <name>, <cigar>, <strand>, <seq>]
NOTE: read end and sequence data are not valid for reads outside of
requested region and should not be used.
@@ -355,17 +643,34 @@
else:
return None
+ # Decode strand from read flag.
+ def decode_strand( read_flag, mask ):
+ strand_flag = ( read_flag & mask == 0 )
+ if strand_flag:
+ return "+"
+ else:
+ return "-"
+
# Encode reads as list of lists.
results = []
paired_pending = {}
+ unmapped = 0
for count, read in enumerate( data ):
if count < start_val:
continue
- if count-start_val >= max_vals:
+ if ( count - start_val - unmapped ) >= max_vals:
message = ERROR_MAX_VALS % ( max_vals, "reads" )
break
+
+ # If not mapped, skip read.
+ is_mapped = ( read.flag & 0x0004 == 0 )
+ if not is_mapped:
+ unmapped += 1
+ continue
+
qname = read.qname
seq = read.seq
+ strand = decode_strand( read.flag, 0x0010 )
if read.cigar is not None:
read_len = sum( [cig[1] for cig in read.cigar] ) # Use cigar to determine length
else:
@@ -378,14 +683,15 @@
pair['start'],
read.pos + read_len,
qname,
- [ pair['start'], pair['end'], pair['cigar'], pair['seq'] ],
- [ read.pos, read.pos + read_len, read.cigar, seq ]
+ [ pair['start'], pair['end'], pair['cigar'], pair['strand'], pair['seq'] ],
+ [ read.pos, read.pos + read_len, read.cigar, strand, seq ]
] )
del paired_pending[qname]
else:
- paired_pending[qname] = { 'start': read.pos, 'end': read.pos + read_len, 'seq': seq, 'mate_start': read.mpos, 'rlen': read_len, 'cigar': read.cigar }
+ paired_pending[qname] = { 'start': read.pos, 'end': read.pos + read_len, 'seq': seq, 'mate_start': read.mpos,
+ 'rlen': read_len, 'strand': strand, 'cigar': read.cigar }
else:
- results.append( [ "%i_%s" % ( read.pos, qname ), read.pos, read.pos + read_len, qname, read.cigar, read.seq] )
+ results.append( [ "%i_%s" % ( read.pos, qname ), read.pos, read.pos + read_len, qname, read.cigar, strand, read.seq] )
# Take care of reads whose mates are out of range.
# TODO: count paired reads when adhering to max_vals?
@@ -397,14 +703,14 @@
# Make read_1 start=end so that length is 0 b/c we don't know
# read length.
r1 = [ read['mate_start'], read['mate_start'] ]
- r2 = [ read['start'], read['end'], read['cigar'], read['seq'] ]
+ r2 = [ read['start'], read['end'], read['cigar'], read['strand'], read['seq'] ]
else:
# Mate is after read.
read_start = read['start']
# Make read_2 start=end so that length is 0 b/c we don't know
# read length. Hence, end of read is start of read_2.
read_end = read['mate_start']
- r1 = [ read['start'], read['end'], read['cigar'], read['seq'] ]
+ r1 = [ read['start'], read['end'], read['cigar'], read['strand'], read['seq'] ]
r2 = [ read['mate_start'], read['mate_start'] ]
results.append( [ "%i_%s" % ( read_start, qname ), read_start, read_end, qname, r1, r2 ] )
@@ -485,118 +791,7 @@
else:
f = open( self.original_dataset.file_name )
return f, BigWigFile(file=f)
-
-class FilterableMixin:
- def get_filters( self ):
- """ Returns a dataset's filters. """
-
- # is_ functions taken from Tabular.set_meta
- def is_int( column_text ):
- try:
- int( column_text )
- return True
- except:
- return False
- def is_float( column_text ):
- try:
- float( column_text )
- return True
- except:
- if column_text.strip().lower() == 'na':
- return True #na is special cased to be a float
- return False
-
- #
- # Get filters.
- # TODOs:
- # (a) might be useful to move this into each datatype's set_meta method;
- # (b) could look at first N lines to ensure GTF attribute types are consistent.
- #
- filters = []
- # HACK: first 8 fields are for drawing, so start filter column index at 9.
- filter_col = 8
- if isinstance( self.original_dataset.datatype, Gff ):
- # Can filter by score and GTF attributes.
- filters = [ { 'name': 'Score',
- 'type': 'int',
- 'index': filter_col,
- 'tool_id': 'Filter1',
- 'tool_exp_name': 'c6' } ]
- filter_col += 1
- if isinstance( self.original_dataset.datatype, Gtf ):
- # Create filters based on dataset metadata.
- for name, a_type in self.original_dataset.metadata.attribute_types.items():
- if a_type in [ 'int', 'float' ]:
- filters.append(
- { 'name': name,
- 'type': a_type,
- 'index': filter_col,
- 'tool_id': 'gff_filter_by_attribute',
- 'tool_exp_name': name } )
- filter_col += 1
-
- '''
- # Old code: use first line in dataset to find attributes.
- for i, line in enumerate( open(self.original_dataset.file_name) ):
- if not line.startswith('#'):
- # Look at first line for attributes and types.
- attributes = parse_gff_attributes( line.split('\t')[8] )
- for attr, value in attributes.items():
- # Get attribute type.
- if is_int( value ):
- attr_type = 'int'
- elif is_float( value ):
- attr_type = 'float'
- else:
- attr_type = 'str'
- # Add to filters.
- if attr_type is not 'str':
- filters.append( { 'name': attr, 'type': attr_type, 'index': filter_col } )
- filter_col += 1
- break
- '''
- elif isinstance( self.original_dataset.datatype, Bed ):
- # Can filter by score column only.
- filters = [ { 'name': 'Score',
- 'type': 'int',
- 'index': filter_col,
- 'tool_id': 'Filter1',
- 'tool_exp_name': 'c5'
- } ]
-
- return filters
-
-class TabixDataProvider( FilterableMixin, TracksDataProvider ):
- """
- Tabix index data provider for the Galaxy track browser.
- """
-
- col_name_data_attr_mapping = { 4 : { 'index': 4 , 'name' : 'Score' } }
-
- def get_iterator( self, chrom, start, end ):
- start, end = int(start), int(end)
- if end >= (2<<29):
- end = (2<<29 - 1) # Tabix-enforced maximum
-
- bgzip_fname = self.dependencies['bgzip'].file_name
-
- # if os.path.getsize(self.converted_dataset.file_name) == 0:
- # return { 'kind': messages.ERROR, 'message': "Tabix converted size was 0, meaning the input file had invalid values." }
- tabix = ctabix.Tabixfile(bgzip_fname, index_filename=self.converted_dataset.file_name)
-
- # If chrom is not found in indexes, try removing the first three
- # characters (e.g. 'chr') and see if that works. This enables the
- # provider to handle chrome names defined as chrXXX and as XXX.
- chrom = str(chrom)
- if chrom not in tabix.contigs and chrom.startswith("chr") and (chrom[3:] in tabix.contigs):
- chrom = chrom[3:]
-
- return tabix.fetch(reference=chrom, start=start, end=end)
-
- def get_data( self, chrom, start, end, start_val=0, max_vals=None, **kwargs ):
- iterator = self.get_iterator( chrom, start, end )
- return self.process_data( iterator, start_val, max_vals, **kwargs )
-
+
class IntervalIndexDataProvider( FilterableMixin, TracksDataProvider ):
"""
Interval index files used only for GFF files.
@@ -658,41 +853,6 @@
results.append( payload )
return { 'data': results, 'message': message }
-
-class VcfDataProvider( TabixDataProvider ):
- """
- VCF data provider for the Galaxy track browser.
-
- Payload format:
- [ uid (offset), start, end, ID, reference base(s), alternate base(s), quality score ]
- """
-
- col_name_data_attr_mapping = { 'Qual' : { 'index': 6 , 'name' : 'Qual' } }
-
- def process_data( self, iterator, start_val=0, max_vals=sys.maxint, **kwargs ):
- rval = []
- message = None
-
- for count, line in enumerate( iterator ):
- if count < start_val:
- continue
- if count-start_val >= max_vals:
- message = ERROR_MAX_VALS % ( "max_vals", "features" )
- break
-
- feature = line.split()
- payload = [ hash(line), int(feature[1])-1, int(feature[1]),
- # ID:
- feature[2],
- # reference base(s):
- feature[3],
- # alternative base(s)
- feature[4],
- # phred quality score
- float( feature[5] )]
- rval.append(payload)
-
- return { 'data': rval, 'message': message }
class GFFDataProvider( TracksDataProvider ):
"""
@@ -724,40 +884,16 @@
offset += feature.raw_size
return { 'data': results, 'message': message }
-
-class BedTabixDataProvider( TabixDataProvider, BedDataProvider ):
- """
- Provides data from a BED file indexed via tabix.
- """
- pass
-
-class RawBedDataProvider( BedDataProvider ):
- """
- Provide data from BED file.
-
- NOTE: this data provider does not use indices, and hence will be very slow
- for large datasets.
- """
-
- def get_iterator( self, chrom, start, end ):
- def line_filter_iter():
- for line in open( self.original_dataset.file_name ):
- feature = line.split()
- feature_chrom, feature_start, feature_end = feature[ 0:3 ]
- if feature_chrom != chrom or feature_start > end or feature_end < start:
- continue
- yield line
- return line_filter_iter()
-
+
#
-# Helper methods.
+# -- Helper methods. --
#
# Mapping from dataset type name to a class that can fetch data from a file of that
# type. First key is converted dataset type; if result is another dict, second key
# is original dataset type. TODO: This needs to be more flexible.
dataset_type_name_to_data_provider = {
- "tabix": { Vcf: VcfDataProvider, Bed: BedTabixDataProvider, "default" : TabixDataProvider },
+ "tabix": { Vcf: VcfTabixDataProvider, Bed: BedTabixDataProvider, "default" : TabixDataProvider },
"interval_index": IntervalIndexDataProvider,
"bai": BamDataProvider,
"summary_tree": SummaryTreeDataProvider,
diff -r 42c8a6cfaa5b76204e978eedfd17647b05531b13 -r f05722e66a8a42e75f01a29b723ed50525e77e55 lib/galaxy/web/controllers/admin.py
--- a/lib/galaxy/web/controllers/admin.py
+++ b/lib/galaxy/web/controllers/admin.py
@@ -410,7 +410,8 @@
columns = [
NameColumn( "Name",
key="name",
- attach_popup=True ),
+ link=( lambda item: dict( operation="manage_repository", id=item.id, webapp="galaxy" ) ),
+ attach_popup=False ),
DescriptionColumn( "Description" ),
OwnerColumn( "Owner" ),
RevisionColumn( "Revision" ),
@@ -426,17 +427,14 @@
key="free-text-search",
visible=False,
filterable="standard" ) )
- operations = [ grids.GridOperation( "Get updates",
- allow_multiple=False,
- condition=( lambda item: not item.deleted ),
- async_compatible=False ) ]
standard_filters = []
default_filter = dict( deleted="False" )
num_rows_per_page = 50
preserve_state = False
use_paging = True
def build_initial_query( self, trans, **kwd ):
- return trans.sa_session.query( self.model_class )
+ return trans.sa_session.query( self.model_class ) \
+ .filter( self.model_class.table.c.deleted == False )
class AdminGalaxy( BaseUIController, Admin, AdminActions, UsesQuota, QuotaParamParser ):
@@ -678,11 +676,88 @@
return quota, params
@web.expose
@web.require_admin
- def browse_repositories( self, trans, **kwd ):
+ def browse_tool_shed_repository( self, trans, **kwd ):
+ params = util.Params( kwd )
+ message = util.restore_text( params.get( 'message', '' ) )
+ status = params.get( 'status', 'done' )
+ repository = get_repository( trans, kwd[ 'id' ] )
+ relative_install_dir = self.__get_relative_install_dir( trans, repository )
+ repo_files_dir = os.path.abspath( os.path.join( relative_install_dir, repository.name ) )
+ tool_dicts = []
+ workflow_dicts = []
+ for root, dirs, files in os.walk( repo_files_dir ):
+ if not root.find( '.hg' ) >= 0 and not root.find( 'hgrc' ) >= 0:
+ if '.hg' in dirs:
+ # Don't visit .hg directories.
+ dirs.remove( '.hg' )
+ if 'hgrc' in files:
+ # Don't include hgrc files.
+ files.remove( 'hgrc' )
+ for name in files:
+ # Find all tool configs.
+ if name.endswith( '.xml' ):
+ try:
+ full_path = os.path.abspath( os.path.join( root, name ) )
+ tool = trans.app.toolbox.load_tool( full_path )
+ if tool is not None:
+ tool_config = os.path.join( root, name )
+ # Handle tool.requirements.
+ tool_requirements = []
+ for tr in tool.requirements:
+ name=tr.name
+ type=tr.type
+ if type == 'fabfile':
+ version = None
+ fabfile = tr.fabfile
+ method = tr.method
+ else:
+ version = tr.version
+ fabfile = None
+ method = None
+ requirement_dict = dict( name=name,
+ type=type,
+ version=version,
+ fabfile=fabfile,
+ method=method )
+ tool_requirements.append( requirement_dict )
+ tool_dict = dict( id=tool.id,
+ old_id=tool.old_id,
+ name=tool.name,
+ version=tool.version,
+ description=tool.description,
+ requirements=tool_requirements,
+ tool_config=tool_config )
+ tool_dicts.append( tool_dict )
+ except Exception, e:
+ # The file is not a Galaxy tool config.
+ pass
+ # Find all exported workflows
+ elif name.endswith( '.ga' ):
+ try:
+ full_path = os.path.abspath( os.path.join( root, name ) )
+ # Convert workflow data from json
+ fp = open( full_path, 'rb' )
+ workflow_text = fp.read()
+ fp.close()
+ workflow_dict = from_json_string( workflow_text )
+ if workflow_dict[ 'a_galaxy_workflow' ] == 'true':
+ workflow_dicts.append( dict( full_path=full_path, workflow_dict=workflow_dict ) )
+ except Exception, e:
+ # The file is not a Galaxy workflow.
+ pass
+ return trans.fill_template( '/admin/tool_shed_repository/browse_repository.mako',
+ repository=repository,
+ tool_dicts=tool_dicts,
+ workflow_dicts=workflow_dicts,
+ message=message,
+ status=status )
+ @web.expose
+ @web.require_admin
+ def browse_tool_shed_repositories( self, trans, **kwd ):
if 'operation' in kwd:
- operation = kwd.pop('operation').lower()
- if operation == "get updates":
- return self.check_for_updates( trans, **kwd )
+ operation = kwd.pop( 'operation' ).lower()
+ if operation == "manage_repository":
+ return self.manage_tool_shed_repository( trans, **kwd )
# Render the list view
return self.repository_list_grid( trans, **kwd )
@web.expose
@@ -725,7 +800,7 @@
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 '
message += '<b><toolbox></b> tag is <b><toolbox tool_path="../shed_tools"></b>).<p/>See the '
message += '<a href="http://wiki.g2.bx.psu.edu/Tool%20Shed#Automatic_installation_of_Galaxy_tool…" '
- message += 'target=_blank">Automatic installation of Galaxy tool shed repository tools into a local Galaxy instance</a> section of the '
+ message += 'target="_blank">Automatic installation of Galaxy tool shed repository tools into a local Galaxy instance</a> section of the '
message += '<a href="http://wiki.g2.bx.psu.edu/Tool%20Shed" target="_blank">Galaxy tool shed wiki</a> for all of the details.'
return trans.show_error_message( message )
message = kwd.get( 'message', '' )
@@ -766,12 +841,9 @@
os.chdir( current_working_dir )
tmp_stderr.close()
if returncode == 0:
- # Add a new record to the tool_shed_repository table.
- tool_shed_repository = self.__create_tool_shed_repository( trans,
- name,
- description,
- changeset_revision,
- repository_clone_url )
+ # Add a new record to the tool_shed_repository table if one doesn't
+ # already exist. If one exists but is marked deleted, undelete it.
+ self.__create_or_undelete_tool_shed_repository( trans, name, description, changeset_revision, repository_clone_url )
# Update the cloned repository to changeset_revision.
repo_files_dir = os.path.join( clone_dir, name )
log.debug( 'Updating cloned repository to revision "%s"...' % changeset_revision )
@@ -853,10 +925,35 @@
status=status )
@web.expose
@web.require_admin
+ def manage_tool_shed_repository( self, trans, **kwd ):
+ params = util.Params( kwd )
+ message = util.restore_text( params.get( 'message', '' ) )
+ status = params.get( 'status', 'done' )
+ repository_id = params.get( 'id', None )
+ repository = get_repository( trans, repository_id )
+ description = util.restore_text( params.get( 'description', repository.description ) )
+ if params.get( 'edit_repository_button', False ):
+ if description != repository.description:
+ repository.description = description
+ trans.sa_session.add( repository )
+ trans.sa_session.flush()
+ message = "The repository information has been updated."
+ relative_install_dir = self.__get_relative_install_dir( trans, repository )
+ if relative_install_dir:
+ repo_files_dir = os.path.abspath( os.path.join( relative_install_dir, repository.name ) )
+ else:
+ repo_files_dir = 'unknown'
+ return trans.fill_template( '/admin/tool_shed_repository/manage_repository.mako',
+ repository=repository,
+ description=description,
+ repo_files_dir=repo_files_dir,
+ message=message,
+ status=status )
+ @web.expose
+ @web.require_admin
def check_for_updates( self, trans, **kwd ):
params = util.Params( kwd )
- repository_id = params.get( 'id', None )
- repository = get_repository( trans, repository_id )
+ repository = get_repository( trans, kwd[ 'id' ] )
galaxy_url = trans.request.host
# Send a request to the relevant tool shed to see if there are any updates.
# TODO: support https in the following url.
@@ -875,26 +972,16 @@
owner = params.get( 'owner', None )
changeset_revision = params.get( 'changeset_revision', None )
latest_changeset_revision = params.get( 'latest_changeset_revision', None )
+ repository = get_repository_by_shed_name_owner_changeset_revision( trans, tool_shed_url, name, owner, changeset_revision )
if changeset_revision and latest_changeset_revision:
if changeset_revision == latest_changeset_revision:
message = "The cloned tool shed repository named '%s' is current (there are no updates available)." % name
else:
- repository = get_repository_by_name_owner_changeset_revision( trans, name, owner, changeset_revision )
current_working_dir = os.getcwd()
- # Get the directory where the repository is cloned.
- cleaned_tool_shed_url = self.__clean_tool_shed_url( tool_shed_url )
- partial_cloned_dir = '%s/repos/%s/%s/%s' % ( cleaned_tool_shed_url, owner, name, changeset_revision )
- # Get the relative tool installation paths from each of the shed tool configs.
- shed_tool_confs = trans.app.toolbox.shed_tool_confs
- relative_cloned_dir = None
- # The shed_tool_confs dictionary contains shed_conf_filename : tool_path pairs.
- for shed_conf_filename, tool_path in shed_tool_confs.items():
- relative_cloned_dir = os.path.join( tool_path, partial_cloned_dir )
- if os.path.isdir( relative_cloned_dir ):
- break
- if relative_cloned_dir:
+ relative_install_dir = self.__get_relative_install_dir( trans, repository )
+ if relative_install_dir:
# Update the cloned repository to changeset_revision.
- repo_files_dir = os.path.join( relative_cloned_dir, name )
+ repo_files_dir = os.path.join( relative_install_dir, name )
log.debug( "Updating cloned repository named '%s' from revision '%s' to revision '%s'..." % \
( name, changeset_revision, latest_changeset_revision ) )
cmd = 'hg pull'
@@ -938,9 +1025,44 @@
message = "The latest changeset revision could not be retrieved for the repository named '%s'." % name
status = 'error'
return trans.response.send_redirect( web.url_for( controller='admin',
- action='browse_repositories',
+ action='manage_tool_shed_repository',
+ id=trans.security.encode_id( repository.id ),
message=message,
status=status ) )
+ @web.expose
+ @web.require_admin
+ def impersonate( self, trans, email=None, **kwd ):
+ if not trans.app.config.allow_user_impersonation:
+ return trans.show_error_message( "User impersonation is not enabled in this instance of Galaxy." )
+ message = ''
+ status = 'done'
+ emails = None
+ if email is not None:
+ user = trans.sa_session.query( trans.app.model.User ).filter_by( email=email ).first()
+ if user:
+ trans.set_user( user )
+ message = 'You are now logged in as %s, <a target="_top" href="%s">return to the home page</a>' % ( email, url_for( controller='root' ) )
+ emails = []
+ else:
+ message = 'Invalid user selected'
+ status = 'error'
+ if emails is None:
+ emails = [ u.email for u in trans.sa_session.query( trans.app.model.User ).enable_eagerloads( False ).all() ]
+ return trans.fill_template( 'admin/impersonate.mako', emails=emails, message=message, status=status )
+
+ def __get_relative_install_dir( self, trans, repository ):
+ # Get the directory where the repository is install.
+ tool_shed = self.__clean_tool_shed_url( repository.tool_shed )
+ partial_install_dir = '%s/repos/%s/%s/%s' % ( tool_shed, repository.owner, repository.name, repository.changeset_revision )
+ # Get the relative tool installation paths from each of the shed tool configs.
+ shed_tool_confs = trans.app.toolbox.shed_tool_confs
+ relative_install_dir = None
+ # The shed_tool_confs dictionary contains { shed_conf_filename : tool_path } pairs.
+ for shed_conf_filename, tool_path in shed_tool_confs.items():
+ relative_install_dir = os.path.join( tool_path, partial_install_dir )
+ if os.path.isdir( relative_install_dir ):
+ break
+ return relative_install_dir
def __handle_missing_data_table_entry( self, trans, tool_path, sample_files, repository_tools_tups ):
# Inspect each tool to see if any have input parameters that are dynamically
# generated select lists that require entries in the tool_data_table_conf.xml file.
@@ -1055,17 +1177,26 @@
# We have an invalid .xml file, so not a tool config.
log.debug( "Ignoring invalid tool config (%s). Error: %s" % ( str( relative_path ), str( e ) ) )
return sample_files, repository_tools_tups
- def __create_tool_shed_repository( self, trans, name, description, changeset_revision, repository_clone_url ):
+ def __create_or_undelete_tool_shed_repository( self, trans, name, description, changeset_revision, repository_clone_url ):
tmp_url = self.__clean_repository_clone_url( repository_clone_url )
tool_shed = tmp_url.split( 'repos' )[ 0 ].rstrip( '/' )
owner = self.__get_repository_owner( tmp_url )
- tool_shed_repository = trans.model.ToolShedRepository( tool_shed=tool_shed,
- name=name,
- description=description,
- owner=owner,
- changeset_revision=changeset_revision )
- trans.sa_session.add( tool_shed_repository )
- trans.sa_session.flush()
+ flush_needed = False
+ tool_shed_repository = get_repository_by_shed_name_owner_changeset_revision( trans, tool_shed, name, owner, changeset_revision )
+ if tool_shed_repository:
+ if tool_shed_repository.deleted:
+ tool_shed_repository.deleted = False
+ flush_needed = True
+ else:
+ tool_shed_repository = trans.model.ToolShedRepository( tool_shed=tool_shed,
+ name=name,
+ description=description,
+ owner=owner,
+ changeset_revision=changeset_revision )
+ flush_needed = True
+ if flush_needed:
+ trans.sa_session.add( tool_shed_repository )
+ trans.sa_session.flush()
def __add_shed_tool_conf_entry( self, trans, shed_tool_conf, new_tool_section ):
# Add an entry in the shed_tool_conf file. An entry looks something like:
# <section name="Filter and Sort" id="filter">
@@ -1194,3 +1325,11 @@
trans.model.ToolShedRepository.table.c.owner == owner,
trans.model.ToolShedRepository.table.c.changeset_revision == changeset_revision ) ) \
.first()
+def get_repository_by_shed_name_owner_changeset_revision( trans, tool_shed, name, owner, changeset_revision ):
+ return trans.sa_session.query( trans.model.ToolShedRepository ) \
+ .filter( and_( trans.model.ToolShedRepository.table.c.tool_shed == tool_shed,
+ trans.model.ToolShedRepository.table.c.name == name,
+ trans.model.ToolShedRepository.table.c.owner == owner,
+ trans.model.ToolShedRepository.table.c.changeset_revision == changeset_revision ) ) \
+ .first()
+
diff -r 42c8a6cfaa5b76204e978eedfd17647b05531b13 -r f05722e66a8a42e75f01a29b723ed50525e77e55 lib/galaxy/web/controllers/tracks.py
--- a/lib/galaxy/web/controllers/tracks.py
+++ b/lib/galaxy/web/controllers/tracks.py
@@ -465,10 +465,14 @@
data = GFFDataProvider( original_dataset=dataset ).get_data( chrom, low, high, **kwargs )
data[ 'dataset_type' ] = 'interval_index'
data[ 'extra_info' ] = None
- if isinstance( dataset.datatype, Bed ):
+ elif isinstance( dataset.datatype, Bed ):
data = RawBedDataProvider( original_dataset=dataset ).get_data( chrom, low, high, **kwargs )
data[ 'dataset_type' ] = 'interval_index'
data[ 'extra_info' ] = None
+ elif isinstance( dataset.datatype, Vcf ):
+ data = RawVcfDataProvider( original_dataset=dataset ).get_data( chrom, low, high, **kwargs )
+ data[ 'dataset_type' ] = 'tabix'
+ data[ 'extra_info' ] = None
return data
@web.json
@@ -586,7 +590,7 @@
data_provider = data_provider_class( converted_dataset=converted_dataset, original_dataset=dataset, dependencies=deps )
# Get and return data from data_provider.
- result = data_provider.get_data( chrom, low, high, int(start_val), int(max_vals), **kwargs )
+ result = data_provider.get_data( chrom, low, high, int( start_val ), int( max_vals ), **kwargs )
result.update( { 'dataset_type': tracks_dataset_type, 'extra_info': extra_info } )
return result
@@ -840,6 +844,43 @@
# Set input datasets for tool. If running on region, extract and use subset
# when possible.
#
+
+ def set_param_value( param_dict, param_name, param_value ):
+ """
+ Set new parameter value in a parameter dictionary.
+ """
+
+ # Recursive function to set param value.
+ def set_value( param_dict, group_name, group_index, param_name, param_value ):
+ if group_name in param_dict:
+ param_dict[ group_name ][ group_index ][ param_name ] = param_value
+ return True
+ elif param_name in param_dict:
+ param_dict[ param_name ] = param_value
+ return True
+ else:
+ # Recursive search.
+ return_val = False
+ for name, value in param_dict.items():
+ if isinstance( value, dict ):
+ return_val = set_value( value, group_name, group_index, param_name, param_value)
+ if return_val:
+ return return_val
+ return False
+
+ # Parse parameter name if necessary.
+ if param_name.find( "|" ) == -1:
+ # Non-grouping parameter.
+ group_name = group_index = None
+ else:
+ # Grouping parameter.
+ group, param_name = param_name.split( "|" )
+ index = group.rfind( "_" )
+ group_name = group[ :index ]
+ group_index = int( group[ index + 1: ] )
+
+ return set_value( param_dict, group_name, group_index, param_name, param_value )
+
for jida in original_job.input_datasets:
input_dataset = jida.dataset
if input_dataset is None: #optional dataset and dataset wasn't selected
@@ -875,10 +916,20 @@
new_dataset.set_size()
new_dataset.info = "Data subset for trackster"
new_dataset.set_dataset_state( trans.app.model.Dataset.states.OK )
+
+ # Set metadata.
+ if trans.app.config.set_metadata_externally:
+ trans.app.datatypes_registry.set_external_metadata_tool.tool_action.execute( trans.app.datatypes_registry.set_external_metadata_tool, trans, incoming = { 'input1':new_dataset } )
+ else:
+ message = 'Attributes updated'
+ new_dataset.set_meta()
+ new_dataset.datatype.after_setting_metadata( new_dataset )
+
trans.sa_session.flush()
-
+
# Add dataset to tool's parameters.
- tool_params[ jida.name ] = new_dataset
+ if not set_param_value( tool_params, jida.name, new_dataset ):
+ return to_json_string( { "error" : True, "message" : "error setting parameter %s" % jida.name } )
#
# Execute tool and handle outputs.
diff -r 42c8a6cfaa5b76204e978eedfd17647b05531b13 -r f05722e66a8a42e75f01a29b723ed50525e77e55 lib/galaxy/web/controllers/workflow.py
--- a/lib/galaxy/web/controllers/workflow.py
+++ b/lib/galaxy/web/controllers/workflow.py
@@ -1095,8 +1095,8 @@
@web.expose
def import_workflow( self, trans, **kwd ):
"""
- Import a workflow by reading an url, uploading a file, or receiving the textual
- representation of a workflow.
+ Import a workflow by reading an url, uploading a file, opening and reading the contents
+ of a local file, or receiving the textual representation of a workflow via http.
"""
url = kwd.get( 'url', '' )
workflow_text = kwd.get( 'workflow_text', '' )
@@ -1104,6 +1104,8 @@
message = kwd.get( 'message', '' )
status = kwd.get( 'status', 'done' )
import_button = kwd.get( 'import_button', False )
+ # The following parameters will have values only if the workflow
+ # id being imported from a Galaxy tool shed repository.
tool_shed_url = kwd.get( 'tool_shed_url', '' )
repository_metadata_id = kwd.get( 'repository_metadata_id', '' )
# The workflow_name parameter is in the request only if the import originated
@@ -1111,6 +1113,15 @@
workflow_name = kwd.get( 'workflow_name', '' )
if workflow_name:
workflow_name = tool_shed_decode( workflow_name )
+ # The following parameters will have a value only if the import originated
+ # from a tool shed repository installed locally.
+ local_file = kwd.get( 'local_file', '' )
+ repository_id = kwd.get( 'repository_id', '' )
+ if local_file and not import_button:
+ workflow_file = open( local_file, 'rb' )
+ workflow_text = workflow_file.read()
+ workflow_file.close()
+ 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 = 'http://%s/workflow/import_workflow?repository_metadata_id=%s&workflow_name=%s&webapp=%s&open_for_url=true' % \
@@ -1118,7 +1129,6 @@
response = urllib2.urlopen( workflow_url )
workflow_text = response.read()
response.close()
- workflow_text = workflow_text
import_button = True
if import_button:
workflow_data = None
@@ -1131,6 +1141,7 @@
message = "Failed to open URL: <b>%s</b><br>Exception: %s" % ( url, str( e ) )
status = 'error'
elif workflow_text:
+ # This case occurs when the workflow_text was sent via http from the tool shed.
workflow_data = workflow_text
else:
# Load workflow from browsed file.
@@ -1170,7 +1181,7 @@
message += "Imported, but this workflow contains cycles. "
status = "error"
else:
- message += "Workflow '%s' imported successfully. " % workflow.name
+ message += "Workflow <b>%s</b> imported successfully. " % workflow.name
if missing_tool_tups:
if trans.user_is_admin():
# A required tool is not available in the local Galaxy instance.
@@ -1182,30 +1193,49 @@
# the Galaxy panels displayed whenever in Galaxy.
message += "The workflow requires the following tools that are not available in this Galaxy instance."
message += "You can likely install the required tools from one of the Galaxy tool sheds listed below.<br/><br/>"
- for tool_shed_name, tool_shed_url in trans.app.tool_shed_registry.tool_sheds.items():
- if tool_shed_url.endswith( '/' ):
- tool_shed_url = tool_shed_url.rstrip( '/' )
- url = '%s/repository/find_tools?galaxy_url=%s&webapp=galaxy' % ( tool_shed_url, trans.request.host )
+ for shed_name, shed_url in trans.app.tool_shed_registry.tool_sheds.items():
+ if shed_url.endswith( '/' ):
+ shed_url = shed_url.rstrip( '/' )
+ url = '%s/repository/find_tools?galaxy_url=%s&webapp=%s' % ( shed_url, trans.request.host, webapp )
for missing_tool_tup in missing_tool_tups:
missing_tool_id = missing_tool_tup[0]
url += '&tool_id=%s' % missing_tool_id
- message += '<a href="%s">%s</a><br/>' % ( url, tool_shed_name )
+ message += '<a href="%s">%s</a><br/>' % ( url, shed_name )
status = 'error'
- return trans.response.send_redirect( web.url_for( controller='admin',
- action='index',
- webapp='galaxy',
- message=message,
- status=status ) )
+ if local_file or tool_shed_url:
+ # Another Galaxy panels Hack: The request did not originate from the Galaxy
+ # workflow view, so we don't need to render the Galaxy panels.
+ return trans.response.send_redirect( web.url_for( controller='admin',
+ action='center',
+ webapp='galaxy',
+ message=message,
+ status=status ) )
+ else:
+ # Another Galaxy panels hack: The request originated from the Galaxy
+ # workflow view, so we need to render the Galaxy panels.
+ return trans.response.send_redirect( web.url_for( controller='admin',
+ action='index',
+ webapp='galaxy',
+ message=message,
+ status=status ) )
else:
# TODO: Figure out what to do here...
pass
if tool_shed_url:
# We've received the textual representation of a workflow from a Galaxy tool shed.
- message = "This workflow has been successfully imported into your local Galaxy instance."
+ message = "Workflow <b>%s</b> imported successfully." % workflow.name
# TODO: support https in the following url.
url = 'http://%s/workflow/view_workflow?repository_metadata_id=%s&workflow_name=%s&webapp=%s&message=%s' % \
( tool_shed_url, repository_metadata_id, tool_shed_encode( workflow_name ), webapp, message )
return trans.response.send_redirect( url )
+ elif local_file:
+ # The workflow was read from a file included with an installed tool shed repository.
+ message = "Workflow <b>%s</b> imported successfully." % workflow.name
+ return trans.response.send_redirect( web.url_for( controller='admin',
+ action='browse_tool_shed_repository',
+ id=repository_id,
+ message=message,
+ status=status ) )
return self.list( trans )
return trans.fill_template( "workflow/import.mako",
url=url,
@@ -1277,7 +1307,16 @@
for job_id in job_ids:
assert job_id in jobs_by_id, "Attempt to create workflow with job not connected to current history"
job = jobs_by_id[ job_id ]
- tool = trans.app.toolbox.tools_by_id[ job.tool_id ]
+ try:
+ tool = trans.app.toolbox.tools_by_id[ job.tool_id ]
+ except KeyError, e:
+ # Handle the case where the workflow requires a tool not available in the local Galaxy instance.
+ # The id value of tools installed from a Galaxy tool shed is a guid, but these tool's old_id
+ # attribute should contain what we're looking for.
+ for available_tool_id, available_tool in trans.app.toolbox.tools_by_id.items():
+ if job.tool_id == available_tool.old_id:
+ tool = available_tool
+ break
param_values = job.get_param_values( trans.app )
associations = cleanup_param_values( tool.inputs, param_values )
# Doing it this way breaks dynamic parameters, backed out temporarily.
@@ -1444,7 +1483,16 @@
# Execute module
job = None
if step.type == 'tool' or step.type is None:
- tool = trans.app.toolbox.tools_by_id[ step.tool_id ]
+ try:
+ tool = trans.app.toolbox.tools_by_id[ step.tool_id ]
+ except KeyError, e:
+ # Handle the case where the workflow requires a tool not available in the local Galaxy instance.
+ # The id value of tools installed from a Galaxy tool shed is a guid, but these tool's old_id
+ # attribute should contain what we're looking for.
+ for available_tool_id, available_tool in trans.app.toolbox.tools_by_id.items():
+ if step.tool_id == available_tool.old_id:
+ tool = available_tool
+ break
input_values = step.state.inputs
# Connect up
def callback( input, value, prefixed_name, prefixed_label ):
@@ -1480,10 +1528,10 @@
trans.sa_session.add( workflow_invocation )
invocations.append({'outputs': outputs,
'new_history': new_history})
- trans.sa_session.flush()
- return trans.fill_template( "workflow/run_complete.mako",
- workflow=stored,
- invocations=invocations )
+ trans.sa_session.flush()
+ return trans.fill_template( "workflow/run_complete.mako",
+ workflow=stored,
+ invocations=invocations )
else:
# Prepare each step
missing_tools = []
diff -r 42c8a6cfaa5b76204e978eedfd17647b05531b13 -r f05722e66a8a42e75f01a29b723ed50525e77e55 lib/galaxy/webapps/community/controllers/common.py
--- a/lib/galaxy/webapps/community/controllers/common.py
+++ b/lib/galaxy/webapps/community/controllers/common.py
@@ -361,8 +361,9 @@
workflow_text = fp.read()
fp.close()
exported_workflow_dict = from_json_string( workflow_text )
- # Update the list of metadata dictionaries for workflows in metadata_dict.
- metadata_dict = generate_workflow_metadata( trans, id, changeset_revision, exported_workflow_dict, metadata_dict )
+ if exported_workflow_dict[ 'a_galaxy_workflow' ] == 'true':
+ # Update the list of metadata dictionaries for workflows in metadata_dict.
+ metadata_dict = generate_workflow_metadata( trans, id, changeset_revision, exported_workflow_dict, metadata_dict )
except Exception, e:
invalid_files.append( ( name, str( e ) ) )
else:
diff -r 42c8a6cfaa5b76204e978eedfd17647b05531b13 -r f05722e66a8a42e75f01a29b723ed50525e77e55 lib/galaxy/webapps/community/controllers/workflow.py
--- a/lib/galaxy/webapps/community/controllers/workflow.py
+++ b/lib/galaxy/webapps/community/controllers/workflow.py
@@ -339,12 +339,6 @@
workflow.has_errors = True
# Stick this in the step temporarily.
step.temp_input_connections = step_dict[ 'input_connections' ]
- # Unpack and add post-job actions.
- post_job_actions = step_dict.get( 'post_job_actions', {} )
- for name, pja_dict in post_job_actions.items():
- pja = PostJobAction( pja_dict[ 'action_type' ],
- step, pja_dict[ 'output_name' ],
- pja_dict[ 'action_arguments' ] )
steps.append( step )
steps_by_external_id[ step_dict[ 'id' ] ] = step
# Second pass to deal with connections between steps.
diff -r 42c8a6cfaa5b76204e978eedfd17647b05531b13 -r f05722e66a8a42e75f01a29b723ed50525e77e55 static/scripts/jquery.scrollTo.js
--- a/static/scripts/jquery.scrollTo.js
+++ /dev/null
@@ -1,215 +0,0 @@
-/**
- * jQuery.ScrollTo
- * Copyright (c) 2007-2009 Ariel Flesler - aflesler(at)gmail(dot)com | http://flesler.blogspot.com
- * Dual licensed under MIT and GPL.
- * Date: 5/25/2009
- *
- * @projectDescription Easy element scrolling using jQuery.
- * http://flesler.blogspot.com/2007/10/jqueryscrollto.html
- * Works with jQuery +1.2.6. Tested on FF 2/3, IE 6/7/8, Opera 9.5/6, Safari 3, Chrome 1 on WinXP.
- *
- * @author Ariel Flesler
- * @version 1.4.2
- *
- * @id jQuery.scrollTo
- * @id jQuery.fn.scrollTo
- * @param {String, Number, DOMElement, jQuery, Object} target Where to scroll the matched elements.
- * The different options for target are:
- * - A number position (will be applied to all axes).
- * - A string position ('44', '100px', '+=90', etc ) will be applied to all axes
- * - A jQuery/DOM element ( logically, child of the element to scroll )
- * - A string selector, that will be relative to the element to scroll ( 'li:eq(2)', etc )
- * - A hash { top:x, left:y }, x and y can be any kind of number/string like above.
-* - A percentage of the container's dimension/s, for example: 50% to go to the middle.
- * - The string 'max' for go-to-end.
- * @param {Number} duration The OVERALL length of the animation, this argument can be the settings object instead.
- * @param {Object,Function} settings Optional set of settings or the onAfter callback.
- * @option {String} axis Which axis must be scrolled, use 'x', 'y', 'xy' or 'yx'.
- * @option {Number} duration The OVERALL length of the animation.
- * @option {String} easing The easing method for the animation.
- * @option {Boolean} margin If true, the margin of the target element will be deducted from the final position.
- * @option {Object, Number} offset Add/deduct from the end position. One number for both axes or { top:x, left:y }.
- * @option {Object, Number} over Add/deduct the height/width multiplied by 'over', can be { top:x, left:y } when using both axes.
- * @option {Boolean} queue If true, and both axis are given, the 2nd axis will only be animated after the first one ends.
- * @option {Function} onAfter Function to be called after the scrolling ends.
- * @option {Function} onAfterFirst If queuing is activated, this function will be called after the first scrolling ends.
- * @return {jQuery} Returns the same jQuery object, for chaining.
- *
- * @desc Scroll to a fixed position
- * @example $('div').scrollTo( 340 );
- *
- * @desc Scroll relatively to the actual position
- * @example $('div').scrollTo( '+=340px', { axis:'y' } );
- *
- * @dec Scroll using a selector (relative to the scrolled element)
- * @example $('div').scrollTo( 'p.paragraph:eq(2)', 500, { easing:'swing', queue:true, axis:'xy' } );
- *
- * @ Scroll to a DOM element (same for jQuery object)
- * @example var second_child = document.getElementById('container').firstChild.nextSibling;
- * $('#container').scrollTo( second_child, { duration:500, axis:'x', onAfter:function(){
- * alert('scrolled!!');
- * }});
- *
- * @desc Scroll on both axes, to different values
- * @example $('div').scrollTo( { top: 300, left:'+=200' }, { axis:'xy', offset:-20 } );
- */
-;(function( $ ){
-
- var $scrollTo = $.scrollTo = function( target, duration, settings ){
- $(window).scrollTo( target, duration, settings );
- };
-
- $scrollTo.defaults = {
- axis:'xy',
- duration: parseFloat($.fn.jquery) >= 1.3 ? 0 : 1
- };
-
- // Returns the element that needs to be animated to scroll the window.
- // Kept for backwards compatibility (specially for localScroll & serialScroll)
- $scrollTo.window = function( scope ){
- return $(window)._scrollable();
- };
-
- // Hack, hack, hack :)
- // Returns the real elements to scroll (supports window/iframes, documents and regular nodes)
- $.fn._scrollable = function(){
- return this.map(function(){
- var elem = this,
- isWin = !elem.nodeName || $.inArray( elem.nodeName.toLowerCase(), ['iframe','#document','html','body'] ) != -1;
-
- if( !isWin )
- return elem;
-
- var doc = (elem.contentWindow || elem).document || elem.ownerDocument || elem;
-
- return $.browser.safari || doc.compatMode == 'BackCompat' ?
- doc.body :
- doc.documentElement;
- });
- };
-
- $.fn.scrollTo = function( target, duration, settings ){
- if( typeof duration == 'object' ){
- settings = duration;
- duration = 0;
- }
- if( typeof settings == 'function' )
- settings = { onAfter:settings };
-
- if( target == 'max' )
- target = 9e9;
-
- settings = $.extend( {}, $scrollTo.defaults, settings );
- // Speed is still recognized for backwards compatibility
- duration = duration || settings.speed || settings.duration;
- // Make sure the settings are given right
- settings.queue = settings.queue && settings.axis.length > 1;
-
- if( settings.queue )
- // Let's keep the overall duration
- duration /= 2;
- settings.offset = both( settings.offset );
- settings.over = both( settings.over );
-
- return this._scrollable().each(function(){
- var elem = this,
- $elem = $(elem),
- targ = target, toff, attr = {},
- win = $elem.is('html,body');
-
- switch( typeof targ ){
- // A number will pass the regex
- case 'number':
- case 'string':
- if( /^([+-]=)?\d+(\.\d+)?(px|%)?$/.test(targ) ){
- targ = both( targ );
- // We are done
- break;
- }
- // Relative selector, no break!
- targ = $(targ,this);
- case 'object':
- // DOMElement / jQuery
- if( targ.is || targ.style )
- // Get the real position of the target
- toff = (targ = $(targ)).offset();
- }
- $.each( settings.axis.split(''), function( i, axis ){
- var Pos = axis == 'x' ? 'Left' : 'Top',
- pos = Pos.toLowerCase(),
- key = 'scroll' + Pos,
- old = elem[key],
- max = $scrollTo.max(elem, axis);
-
- if( toff ){// jQuery / DOMElement
- attr[key] = toff[pos] + ( win ? 0 : old - $elem.offset()[pos] );
-
- // If it's a dom element, reduce the margin
- if( settings.margin ){
- attr[key] -= parseInt(targ.css('margin'+Pos)) || 0;
- attr[key] -= parseInt(targ.css('border'+Pos+'Width')) || 0;
- }
-
- attr[key] += settings.offset[pos] || 0;
-
- if( settings.over[pos] )
- // Scroll to a fraction of its width/height
- attr[key] += targ[axis=='x'?'width':'height']() * settings.over[pos];
- }else{
- var val = targ[pos];
- // Handle percentage values
- attr[key] = val.slice && val.slice(-1) == '%' ?
- parseFloat(val) / 100 * max
- : val;
- }
-
- // Number or 'number'
- if( /^\d+$/.test(attr[key]) )
- // Check the limits
- attr[key] = attr[key] <= 0 ? 0 : Math.min( attr[key], max );
-
- // Queueing axes
- if( !i && settings.queue ){
- // Don't waste time animating, if there's no need.
- if( old != attr[key] )
- // Intermediate animation
- animate( settings.onAfterFirst );
- // Don't animate this axis again in the next iteration.
- delete attr[key];
- }
- });
-
- animate( settings.onAfter );
-
- function animate( callback ){
- $elem.animate( attr, duration, settings.easing, callback && function(){
- callback.call(this, target, settings);
- });
- };
-
- }).end();
- };
-
- // Max scrolling position, works on quirks mode
- // It only fails (not too badly) on IE, quirks mode.
- $scrollTo.max = function( elem, axis ){
- var Dim = axis == 'x' ? 'Width' : 'Height',
- scroll = 'scroll'+Dim;
-
- if( !$(elem).is('html,body') )
- return elem[scroll] - $(elem)[Dim.toLowerCase()]();
-
- var size = 'client' + Dim,
- html = elem.ownerDocument.documentElement,
- body = elem.ownerDocument.body;
-
- return Math.max( html[scroll], body[scroll] )
- - Math.min( html[size] , body[size] );
-
- };
-
- function both( val ){
- return typeof val == 'object' ? val : { top:val, left:val };
- };
-
-})( jQuery );
\ No newline at end of file
diff -r 42c8a6cfaa5b76204e978eedfd17647b05531b13 -r f05722e66a8a42e75f01a29b723ed50525e77e55 static/scripts/packed/jquery.scrollTo.js
--- a/static/scripts/packed/jquery.scrollTo.js
+++ /dev/null
@@ -1,1 +0,0 @@
-(function(c){var a=c.scrollTo=function(f,e,d){c(window).scrollTo(f,e,d)};a.defaults={axis:"xy",duration:parseFloat(c.fn.jquery)>=1.3?0:1};a.window=function(d){return c(window)._scrollable()};c.fn._scrollable=function(){return this.map(function(){var e=this,d=!e.nodeName||c.inArray(e.nodeName.toLowerCase(),["iframe","#document","html","body"])!=-1;if(!d){return e}var f=(e.contentWindow||e).document||e.ownerDocument||e;return c.browser.safari||f.compatMode=="BackCompat"?f.body:f.documentElement})};c.fn.scrollTo=function(f,e,d){if(typeof e=="object"){d=e;e=0}if(typeof d=="function"){d={onAfter:d}}if(f=="max"){f=9000000000}d=c.extend({},a.defaults,d);e=e||d.speed||d.duration;d.queue=d.queue&&d.axis.length>1;if(d.queue){e/=2}d.offset=b(d.offset);d.over=b(d.over);return this._scrollable().each(function(){var l=this,j=c(l),k=f,i,g={},m=j.is("html,body");switch(typeof k){case"number":case"string":if(/^([+-]=)?\d+(\.\d+)?(px|%)?$/.test(k)){k=b(k);break}k=c(k,this);case"object":if(k.is||k.style){i=(k=c(k)).offset()}}c.each(d.axis.split(""),function(q,r){var s=r=="x"?"Left":"Top",u=s.toLowerCase(),p="scroll"+s,o=l[p],n=a.max(l,r);if(i){g[p]=i[u]+(m?0:o-j.offset()[u]);if(d.margin){g[p]-=parseInt(k.css("margin"+s))||0;g[p]-=parseInt(k.css("border"+s+"Width"))||0}g[p]+=d.offset[u]||0;if(d.over[u]){g[p]+=k[r=="x"?"width":"height"]()*d.over[u]}}else{var t=k[u];g[p]=t.slice&&t.slice(-1)=="%"?parseFloat(t)/100*n:t}if(/^\d+$/.test(g[p])){g[p]=g[p]<=0?0:Math.min(g[p],n)}if(!q&&d.queue){if(o!=g[p]){h(d.onAfterFirst)}delete g[p]}});h(d.onAfter);function h(n){j.animate(g,e,d.easing,n&&function(){n.call(this,f,d)})}}).end()};a.max=function(j,i){var h=i=="x"?"Width":"Height",e="scroll"+h;if(!c(j).is("html,body")){return j[e]-c(j)[h.toLowerCase()]()}var g="client"+h,f=j.ownerDocument.documentElement,d=j.ownerDocument.body;return Math.max(f[e],d[e])-Math.min(f[g],d[g])};function b(d){return typeof d=="object"?d:{top:d,left:d}}})(jQuery);
\ No newline at end of file
diff -r 42c8a6cfaa5b76204e978eedfd17647b05531b13 -r f05722e66a8a42e75f01a29b723ed50525e77e55 static/scripts/packed/trackster.js
--- a/static/scripts/packed/trackster.js
+++ b/static/scripts/packed/trackster.js
@@ -1,1 +1,1 @@
-var class_module=function(b,a){var c=function(){var f=arguments[0];for(var e=1;e<arguments.length;e++){var d=arguments[e];for(key in d){f[key]=d[key]}}return f};a.extend=c};var requestAnimationFrame=(function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(b,a){window.setTimeout(b,1000/60)}})();var BEFORE=1001,CONTAINS=1002,OVERLAP_START=1003,OVERLAP_END=1004,CONTAINED_BY=1005,AFTER=1006;var compute_overlap=function(e,b){var g=e[0],f=e[1],d=b[0],c=b[1],a;if(g<d){if(f<d){a=BEFORE}else{if(f<=c){a=OVERLAP_START}else{a=CONTAINS}}}else{if(g>c){a=AFTER}else{if(f<=c){a=CONTAINED_BY}else{a=OVERLAP_END}}}return a};var is_overlap=function(c,b){var a=compute_overlap(c,b);return(a!==BEFORE&&a!==AFTER)};var get_random_color=function(a){if(!a){a="#ffffff"}if(typeof(a)==="string"){a=[a]}for(var j=0;j<a.length;j++){a[j]=parseInt(a[j].slice(1),16)}var m=function(u,t,s){return((u*299)+(t*587)+(s*114))/1000};var e=function(v,u,w,s,r,t){return(Math.max(v,s)-Math.min(v,s))+(Math.max(u,r)-Math.min(u,r))+(Math.max(w,t)-Math.min(w,t))};var g,n,f,k,p,h,q,c,d,b,o,l=false;do{g=Math.random()*16777215;n=g|16711680;f=g|65280;k=g|255;d=m(n,f,k);l=true;for(var j=0;j<a.length;j++){p=a[j];h=p|16711680;q=p|65280;c=p|255;b=m(h,q,c);o=e(n,f,k,h,q,c);if((Math.abs(d-b)<125)||(o<500)){l=false;break}}}while(!l);return"#"+(16777216+g).toString(16).substr(1,6)};var trackster_module=function(f,Z){var q=f("class").extend,t=f("slotting"),N=f("painters");var ag=function(ah,ai){this.document=ah;this.default_font=ai!==undefined?ai:"9px Monaco, Lucida Console, monospace";this.dummy_canvas=this.new_canvas();this.dummy_context=this.dummy_canvas.getContext("2d");this.dummy_context.font=this.default_font;this.char_width_px=this.dummy_context.measureText("A").width;this.patterns={};this.load_pattern("right_strand","/visualization/strand_right.png");this.load_pattern("left_strand","/visualization/strand_left.png");this.load_pattern("right_strand_inv","/visualization/strand_right_inv.png");this.load_pattern("left_strand_inv","/visualization/strand_left_inv.png")};q(ag.prototype,{load_pattern:function(ah,al){var ai=this.patterns,aj=this.dummy_context,ak=new Image();ak.src=image_path+al;ak.onload=function(){ai[ah]=aj.createPattern(ak,"repeat")}},get_pattern:function(ah){return this.patterns[ah]},new_canvas:function(){var ah=this.document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(ah)}ah.manager=this;return ah}});var o={};var m=function(ah,ai){o[ah.attr("id")]=ai};var n=function(ah,aj,al,ak){al=".group";var ai={};o[ah.attr("id")]=ak;ah.bind("drag",{handle:"."+aj,relative:true},function(au,av){var at=$(this);var ay=$(this).parent(),ap=ay.children(),ar=o[$(this).attr("id")],ao,an,aw,am,aq;an=$(this).parents(al);if(an.length!==0){aw=an.position().top;am=aw+an.outerHeight();if(av.offsetY<aw){$(this).insertBefore(an);var ax=o[an.attr("id")];ax.remove_drawable(ar);ax.container.add_drawable_before(ar,ax);return}else{if(av.offsetY>am){$(this).insertAfter(an);var ax=o[an.attr("id")];ax.remove_drawable(ar);ax.container.add_drawable(ar);return}}}an=null;for(aq=0;aq<ap.length;aq++){ao=$(ap.get(aq));aw=ao.position().top;am=aw+ao.outerHeight();if(ao.is(al)&&this!==ao.get(0)&&av.offsetY>=aw&&av.offsetY<=am){if(av.offsetY-aw<am-av.offsetY){ao.find(".content-div").prepend(this)}else{ao.find(".content-div").append(this)}if(ar.container){ar.container.remove_drawable(ar)}o[ao.attr("id")].add_drawable(ar);return}}for(aq=0;aq<ap.length;aq++){if(av.offsetY<$(ap.get(aq)).position().top){break}}if(aq===ap.length){if(this!==ap.get(aq-1)){ay.append(this);o[ay.attr("id")].move_drawable(ar,aq)}}else{if(this!==ap.get(aq)){$(this).insertBefore(ap.get(aq));o[ay.attr("id")].move_drawable(ar,(av.deltaY>0?aq-1:aq))}}}).bind("dragstart",function(){ai["border-top"]=ah.css("border-top");ai["border-bottom"]=ah.css("border-bottom");$(this).css({"border-top":"1px solid blue","border-bottom":"1px solid blue"})}).bind("dragend",function(){$(this).css(ai)})};Z.moveable=n;var af=16,I=9,F=20,U=I+2,A=100,K=12000,S=200,D=5,w=10,M=5000,x=100,p="There was an error in indexing this dataset. ",L="A converter for this dataset is not installed. Please check your datatypes_conf.xml file.",G="No data for this chrom/contig.",u="Currently indexing... please wait",y="Tool cannot be rerun: ",a="Loading data...",aa="Ready for display",d=10,v=5,C=5;function ab(ai,ah){if(!ah){ah=0}var aj=Math.pow(10,ah);return Math.round(ai*aj)/aj}var c=function(ah){this.num_elements=ah;this.clear()};q(c.prototype,{get:function(ai){var ah=this.key_ary.indexOf(ai);if(ah!==-1){if(this.obj_cache[ai].stale){this.key_ary.splice(ah,1);delete this.obj_cache[ai]}else{this.move_key_to_end(ai,ah)}}return this.obj_cache[ai]},set:function(ai,aj){if(!this.obj_cache[ai]){if(this.key_ary.length>=this.num_elements){var ah=this.key_ary.shift();delete this.obj_cache[ah]}this.key_ary.push(ai)}this.obj_cache[ai]=aj;return aj},move_key_to_end:function(ai,ah){this.key_ary.splice(ah,1);this.key_ary.push(ai)},clear:function(){this.obj_cache={};this.key_ary=[]},size:function(){return this.key_ary.length}});var T=function(ai,ah,aj){c.call(this,ai);this.track=ah;this.subset=(aj!==undefined?aj:true)};q(T.prototype,c.prototype,{load_data:function(aq,al,ao,ai,an){var ap=this.track.view.chrom,ak={chrom:ap,low:aq,high:al,mode:ao,resolution:ai,dataset_id:this.track.dataset_id,hda_ldda:this.track.hda_ldda};$.extend(ak,an);if(this.track.filters_manager){var ar=[];var ah=this.track.filters_manager.filters;for(var am=0;am<ah.length;am++){ar[ar.length]=ah[am].name}ak.filter_cols=JSON.stringify(ar)}var aj=this;return $.getJSON(this.track.data_url,ak,function(at){aj.set_data(aq,al,ao,at)})},get_data:function(ah,al,am,ai,ak){var aj=this.get_data_from_cache(ah,al,am);if(aj){return aj}aj=this.load_data(ah,al,am,ai,ak);this.set_data(ah,al,am,aj);return aj},DEEP_DATA_REQ:"deep",BROAD_DATA_REQ:"breadth",get_more_data:function(ap,ak,ao,aj,an,al){var aq=this.get_data_from_cache(ap,ak,ao);if(!aq){console.log("ERROR: no current data for: ",this.track,ap,ak,ao,aj,an);return}aq.stale=true;var ai=ap;if(al===this.DEEP_DATA_REQ){$.extend(an,{start_val:aq.data.length+1})}else{if(al===this.BROAD_DATA_REQ){ai=(aq.max_high?aq.max_high:aq.data[aq.data.length-1][2])+1}}var ah=this,am=this.load_data(ai,ak,ao,aj,an);new_data_available=$.Deferred();this.set_data(ap,ak,ao,new_data_available);$.when(am).then(function(ar){if(ar.data){ar.data=aq.data.concat(ar.data);if(ar.max_low){ar.max_low=aq.max_low}if(ar.message){ar.message=ar.message.replace(/[0-9]+/,ar.data.length)}}ah.set_data(ap,ak,ao,ar);new_data_available.resolve(ar)});return new_data_available},get_data_from_cache:function(ah,ai,aj){return this.get(this.gen_key(ah,ai,aj))},set_data:function(ai,aj,ak,ah){return this.set(this.gen_key(ai,aj,ak),ah)},gen_key:function(ah,aj,ak){var ai=ah+"_"+aj+"_"+ak;return ai},split_key:function(ah){return ah.split("_")}});var J=function(ai,ah,aj){T.call(this,ai,ah,aj)};q(J.prototype,T.prototype,c.prototype,{load_data:function(ah,ak,al,ai,aj){if(ai>1){return{data:null}}return T.prototype.load_data.call(this,ah,ak,al,ai,aj)}});var r=function(ak,ai,ah,aj,al){this.name=ak;this.view=ai;this.container=ah;this.config=new H({track:this,params:[{key:"name",label:"Name",type:"text",default_value:ak}],saved_values:aj,onchange:function(){this.track.set_name(this.track.config.values.name)}});this.prefs=this.config.values;this.drag_handle_class=al;this.is_overview=false};q(r.prototype,{init:function(){},request_draw:function(){},_draw:function(){},to_json:function(){},update_track_icons:function(){},set_name:function(ah){this.old_name=this.name;this.name=ah;this.name_div.text(this.name)},revert_name:function(){this.name=this.old_name;this.name_div.text(this.name)},remove:function(){this.container.remove_drawable(this);this.container_div.fadeOut("slow",function(){$(this).remove();view.update_intro_div();view.has_changes=true})}});var z=function(al,ak,ai,ah,aj,am){r.call(this,ak,ai,ah,aj,am);this.obj_type=al;this.drawables=[]};q(z.prototype,r.prototype,{init:function(){for(var ah=0;ah<this.drawables.length;ah++){this.drawables[ah].init()}},_draw:function(){for(var ah=0;ah<this.drawables.length;ah++){this.drawables[ah]._draw()}},to_json:function(){var ai=[];for(var ah=0;ah<this.drawables.length;ah++){ai.push(this.drawables[ah].to_json())}return{name:this.name,prefs:this.prefs,obj_type:this.obj_type,drawables:ai}},add_drawable:function(ah){this.drawables.push(ah);ah.container=this},add_drawable_before:function(aj,ah){var ai=this.drawables.indexOf(ah);if(ai!=-1){this.drawables.splice(ai,0,aj);return true}return false},remove_drawable:function(ai){var ah=this.drawables.indexOf(ai);if(ah!=-1){this.drawables.splice(ah,1);ai.container=null;return true}return false},move_drawable:function(ai,aj){var ah=this.drawables.indexOf(ai);if(ah!=-1){this.drawables.splice(ah,1);this.drawables.splice(aj,0,ai);return true}return false}});var R=function(ak,ai,ah,aj){z.call(this,"DrawableGroup",ak,ai,ah,aj,"group-handle");if(!R.id_counter){R.id_counter=0}var al=R.id_counter++;this.container_div=$("<div/>").addClass("group").attr("id","group_"+al).appendTo(this.container.content_div);this.header_div=$("<div/>").addClass("track-header").appendTo(this.container_div);this.header_div.append($("<div/>").addClass(this.drag_handle_class));this.name_div=$("<div/>").addClass("group-name menubutton popup").text(this.name).appendTo(this.header_div);this.content_div=$("<div/>").addClass("content-div").attr("id","group_"+al+"_content_div").appendTo(this.container_div);m(this.container_div,this);m(this.content_div,this);n(this.container_div,this.drag_handle_class,".group",this);this.update_track_icons()};q(R.prototype,r.prototype,z.prototype,{update_track_icons:function(){var ai=this;var ah={};ah["Edit configuration"]=function(){var al=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},aj=function(){ai.config.update_from_form($(".dialog-box"));hide_modal();$(window).unbind("keypress.check_enter_esc")},ak=function(am){if((am.keyCode||am.which)===27){al()}else{if((am.keyCode||am.which)===13){aj()}}};$(window).bind("keypress.check_enter_esc",ak);show_modal("Configure Group",ai.config.build_form(),{Cancel:al,OK:aj})};ah.Remove=function(){ai.remove()};make_popupmenu(ai.name_div,ah)}});var ae=function(ah,ak,aj,ai){z.call(this,"View");this.container=ah;this.chrom=null;this.vis_id=aj;this.dbkey=ai;this.title=ak;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.init();this.canvas_manager=new ag(ah.get(0).ownerDocument);this.reset()};q(ae.prototype,z.prototype,{init:function(){var aj=this.container,ah=this;this.top_container=$("<div/>").addClass("top-container").appendTo(aj);this.browser_content_div=$("<div/>").addClass("content").css("position","relative").appendTo(aj);this.bottom_container=$("<div/>").addClass("bottom-container").appendTo(aj);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;m(this.viewport_container,ah);this.intro_div=$("<div/>").addClass("intro");var ak=$("<div/>").text("Add Datasets to Visualization").addClass("action-button").appendTo(this.intro_div).click(function(){add_tracks()});this.nav_labeltrack=$("<div/>").addClass("nav-labeltrack").appendTo(this.bottom_container);this.nav_container=$("<div/>").addClass("nav-container").prependTo(this.top_container);this.nav=$("<div/>").addClass("nav").appendTo(this.nav_container);this.overview=$("<div/>").addClass("overview").appendTo(this.bottom_container);this.overview_viewport=$("<div/>").addClass("overview-viewport").appendTo(this.overview);this.overview_close=$("<a/>").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").addClass("no-autocomplete").append("<option value=''>Loading</option>").appendTo(this.nav_controls);var ai=function(al){if(al.type==="focusout"||(al.keyCode||al.which)===13||(al.keyCode||al.which)===27){if((al.keyCode||al.which)!==27){ah.go_to($(this).val())}$(this).hide();$(this).val("");ah.location_span.show();ah.chrom_select.show()}};this.nav_input=$("<input/>").addClass("nav-input").hide().bind("keyup focusout",ai).appendTo(this.nav_controls);this.location_span=$("<span/>").addClass("location").appendTo(this.nav_controls);this.location_span.click(function(){ah.location_span.hide();ah.chrom_select.hide();ah.nav_input.val(ah.chrom+":"+ah.low+"-"+ah.high);ah.nav_input.css("display","inline-block");ah.nav_input.select();ah.nav_input.focus()});if(this.vis_id!==undefined){this.hidden_input=$("<input/>").attr("type","hidden").val(this.vis_id).appendTo(this.nav_controls)}this.zo_link=$("<a id='zoom-out' />").click(function(){ah.zoom_out();ah.request_redraw()}).appendTo(this.nav_controls);this.zi_link=$("<a id='zoom-in' />").click(function(){ah.zoom_in();ah.request_redraw()}).appendTo(this.nav_controls);this.load_chroms_deferred=this.load_chroms({low:0});this.chrom_select.bind("change",function(){ah.change_chrom(ah.chrom_select.val())});this.browser_content_div.click(function(al){$(this).find("input").trigger("blur")});this.browser_content_div.bind("dblclick",function(al){ah.zoom_in(al.pageX,this.viewport_container)});this.overview_box.bind("dragstart",function(al,am){this.current_x=am.offsetX}).bind("drag",function(al,an){var ao=an.offsetX-this.current_x;this.current_x=an.offsetX;var am=Math.round(ao/ah.viewport_container.width()*(ah.max_high-ah.max_low));ah.move_delta(-am)});this.overview_close.click(function(){ah.reset_overview()});this.viewport_container.bind("draginit",function(al,am){if(al.clientX>ah.viewport_container.width()-16){return false}}).bind("dragstart",function(al,am){am.original_low=ah.low;am.current_height=al.clientY;am.current_x=am.offsetX}).bind("drag",function(an,ap){var al=$(this);var aq=ap.offsetX-ap.current_x;var am=al.scrollTop()-(an.clientY-ap.current_height);al.scrollTop(am);ap.current_height=an.clientY;ap.current_x=ap.offsetX;var ao=Math.round(aq/ah.viewport_container.width()*(ah.high-ah.low));ah.move_delta(ao)}).bind("mousewheel",function(an,ap,am,al){if(am){var ao=Math.round(-am/ah.viewport_container.width()*(ah.high-ah.low));ah.move_delta(ao)}});this.top_labeltrack.bind("dragstart",function(al,am){return $("<div />").css({height:ah.browser_content_div.height()+ah.top_labeltrack.height()+ah.nav_labeltrack.height()+1,top:"0px",position:"absolute","background-color":"#ccf",opacity:0.5,"z-index":1000}).appendTo($(this))}).bind("drag",function(ap,aq){$(aq.proxy).css({left:Math.min(ap.pageX,aq.startX),width:Math.abs(ap.pageX-aq.startX)});var am=Math.min(ap.pageX,aq.startX)-ah.container.offset().left,al=Math.max(ap.pageX,aq.startX)-ah.container.offset().left,ao=(ah.high-ah.low),an=ah.viewport_container.width();ah.update_location(Math.round(am/an*ao)+ah.low,Math.round(al/an*ao)+ah.low)}).bind("dragend",function(aq,ar){var am=Math.min(aq.pageX,ar.startX),al=Math.max(aq.pageX,ar.startX),ao=(ah.high-ah.low),an=ah.viewport_container.width(),ap=ah.low;ah.low=Math.round(am/an*ao)+ap;ah.high=Math.round(al/an*ao)+ap;$(ar.proxy).remove();ah.request_redraw()});this.add_label_track(new ad(this,{content_div:this.top_labeltrack}));this.add_label_track(new ad(this,{content_div:this.nav_labeltrack}));$(window).bind("resize",function(){ah.resize_window()});$(document).bind("redraw",function(){ah.redraw()});this.reset();$(window).trigger("resize");this.update_intro_div()},update_intro_div:function(){if(this.num_tracks===0){this.intro_div.appendTo(this.viewport_container)}else{this.intro_div.remove()}},update_location:function(ah,ai){this.location_span.text(commatize(ah)+" - "+commatize(ai));this.nav_input.val(this.chrom+":"+commatize(ah)+"-"+commatize(ai))},load_chroms:function(aj){aj.num=x;$.extend(aj,(this.vis_id!==undefined?{vis_id:this.vis_id}:{dbkey:this.dbkey}));var ah=this,ai=$.Deferred();$.ajax({url:chrom_url,data:aj,dataType:"json",success:function(al){if(al.chrom_info.length===0){alert("Invalid chromosome: "+aj.chrom);return}if(al.reference){ah.add_label_track(new B(ah))}ah.chrom_data=al.chrom_info;var ao='<option value="">Select Chrom/Contig</option>';for(var an=0,ak=ah.chrom_data.length;an<ak;an++){var am=ah.chrom_data[an].chrom;ao+='<option value="'+am+'">'+am+"</option>"}if(al.prev_chroms){ao+='<option value="previous">Previous '+x+"</option>"}if(al.next_chroms){ao+='<option value="next">Next '+x+"</option>"}ah.chrom_select.html(ao);ah.chrom_start_index=al.start_index;ai.resolve(al)},error:function(){alert("Could not load chroms for this dbkey:",ah.dbkey)}});return ai},change_chrom:function(am,ai,ao){if(!am||am==="None"){return}var aj=this;if(am==="previous"){aj.load_chroms({low:this.chrom_start_index-x});return}if(am==="next"){aj.load_chroms({low:this.chrom_start_index+x});return}var an=$.grep(aj.chrom_data,function(ap,aq){return ap.chrom===am})[0];if(an===undefined){aj.load_chroms({chrom:am},function(){aj.change_chrom(am,ai,ao)});return}else{if(am!==aj.chrom){aj.chrom=am;aj.chrom_select.val(aj.chrom);aj.max_high=an.len-1;aj.reset();aj.request_redraw(true);for(var al=0,ah=aj.drawables.length;al<ah;al++){var ak=aj.drawables[al];if(ak.init){ak.init()}}}if(ai!==undefined&&ao!==undefined){aj.low=Math.max(ai,0);aj.high=Math.min(ao,aj.max_high)}aj.reset_overview();aj.request_redraw()}},go_to:function(al){var ap=this,ah,ak,ai=al.split(":"),an=ai[0],ao=ai[1];if(ao!==undefined){try{var am=ao.split("-");ah=parseInt(am[0].replace(/,/g,""),10);ak=parseInt(am[1].replace(/,/g,""),10)}catch(aj){return false}}ap.change_chrom(an,ah,ak)},move_fraction:function(aj){var ah=this;var ai=ah.high-ah.low;this.move_delta(aj*ai)},move_delta:function(aj){var ah=this;var ai=ah.high-ah.low;if(ah.low-aj<ah.max_low){ah.low=ah.max_low;ah.high=ah.max_low+ai}else{if(ah.high-aj>ah.max_high){ah.high=ah.max_high;ah.low=ah.max_high-ai}else{ah.high-=aj;ah.low-=aj}}ah.request_redraw()},add_drawable:function(ah){z.prototype.add_drawable.call(this,ah);ah.init();this.has_changes=true;this.update_intro_div()},add_label_track:function(ah){ah.view=this;ah.init();this.label_tracks.push(ah)},remove_drawable:function(aj,ai){z.prototype.remove_drawable.call(this,aj);if(ai){var ah=this;aj.container_div.fadeOut("slow",function(){$(this).remove();ah.update_intro_div()});this.has_changes=true}},reset:function(){this.low=this.max_low;this.high=this.max_high;this.viewport_container.find(".yaxislabel").remove()},request_redraw:function(ap,ah,ao,ai){var an=this,al=(ai?[ai]:an.drawables),aj;var ai;for(var am=0;am<al.length;am++){ai=al[am];aj=-1;for(var ak=0;ak<an.tracks_to_be_redrawn.length;ak++){if(an.tracks_to_be_redrawn[ak][0]===ai){aj=ak;break}}if(aj<0){an.tracks_to_be_redrawn.push([ai,ah,ao])}else{an.tracks_to_be_redrawn[am][1]=ah;an.tracks_to_be_redrawn[am][2]=ao}}requestAnimationFrame(function(){an._redraw(ap)})},_redraw:function(ar){var ao=this.low,ak=this.high;if(ao<this.max_low){ao=this.max_low}if(ak>this.max_high){ak=this.max_high}var aq=this.high-this.low;if(this.high!==0&&aq<this.min_separation){ak=ao+this.min_separation}this.low=Math.floor(ao);this.high=Math.ceil(ak);this.resolution=Math.pow(D,Math.ceil(Math.log((this.high-this.low)/S)/Math.log(D)));this.zoom_res=Math.pow(w,Math.max(0,Math.ceil(Math.log(this.resolution,w)/Math.log(w))));var ah=(this.low/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var an=((this.high-this.low)/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var at=13;this.overview_box.css({left:ah,width:Math.max(at,an)}).show();if(an<at){this.overview_box.css("left",ah-(at-an)/2)}if(this.overview_highlight){this.overview_highlight.css({left:ah,width:an})}this.update_location(this.low,this.high);if(!ar){var aj,ai,ap;for(var al=0,am=this.tracks_to_be_redrawn.length;al<am;al++){aj=this.tracks_to_be_redrawn[al][0];ai=this.tracks_to_be_redrawn[al][1];ap=this.tracks_to_be_redrawn[al][2];if(aj){aj._draw(ai,ap)}}this.tracks_to_be_redrawn=[];for(al=0,am=this.label_tracks.length;al<am;al++){this.label_tracks[al]._draw()}}},zoom_in:function(ai,aj){if(this.max_high===0||this.high-this.low<this.min_separation){return}var ak=this.high-this.low,al=ak/2+this.low,ah=(ak/this.zoom_factor)/2;if(ai){al=ai/this.viewport_container.width()*(this.high-this.low)+this.low}this.low=Math.round(al-ah);this.high=Math.round(al+ah);this.request_redraw()},zoom_out:function(){if(this.max_high===0){return}var ai=this.high-this.low,aj=ai/2+this.low,ah=(ai*this.zoom_factor)/2;this.low=Math.round(aj-ah);this.high=Math.round(aj+ah);this.request_redraw()},resize_window:function(){this.viewport_container.height(this.container.height()-this.top_container.height()-this.bottom_container.height());this.nav_container.width(this.container.width());this.request_redraw()},set_overview:function(aj){if(this.overview_drawable){if(this.overview_drawable.dataset_id===aj.dataset_id){return}this.overview_viewport.find(".track").remove()}var ai=aj.copy({content_div:this.overview_viewport}),ah=this;ai.header_div.hide();ai.is_overview=true;ah.overview_drawable=ai;this.overview_drawable.postdraw_actions=function(){ah.overview_highlight.show().height(ah.overview_drawable.content_div.height());ah.overview_viewport.height(ah.overview_drawable.content_div.height()+ah.overview_box.outerHeight());ah.overview_close.show();ah.resize_window()};this.overview_drawable.init();ah.has_changes=true},reset_overview:function(){$(".tipsy").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(aj,an){this.track=aj;this.name=an.name;this.params=[];var av=an.params;for(var ak=0;ak<av.length;ak++){var ap=av[ak],ai=ap.name,au=ap.label,al=unescape(ap.html),aw=ap.value,ar=ap.type;if(ar==="number"){this.params[this.params.length]=new g(ai,au,al,aw,ap.min,ap.max)}else{if(ar=="select"){this.params[this.params.length]=new P(ai,au,al,aw)}else{console.log("WARNING: unrecognized tool parameter type:",ai,ar)}}}this.parent_div=$("<div/>").addClass("dynamic-tool").hide();this.parent_div.bind("drag",function(ay){ay.stopPropagation()}).click(function(ay){ay.stopPropagation()}).bind("dblclick",function(ay){ay.stopPropagation()});var at=$("<div class='tool-name'>").appendTo(this.parent_div).text(this.name);var aq=this.params;var ao=this;$.each(this.params,function(az,aC){var aB=$("<div>").addClass("param-row").appendTo(ao.parent_div);var ay=$("<div>").addClass("param-label").text(aC.label).appendTo(aB);var aA=$("<div/>").addClass("slider").html(aC.html).appendTo(aB);aA.find(":input").val(aC.value);$("<div style='clear: both;'/>").appendTo(aB)});this.parent_div.find("input").click(function(){$(this).select()});var ax=$("<div>").addClass("param-row").appendTo(this.parent_div);var am=$("<input type='submit'>").attr("value","Run on complete dataset").appendTo(ax);var ah=$("<input type='submit'>").attr("value","Run on visible region").css("margin-left","3em").appendTo(ax);var ao=this;ah.click(function(){ao.run_on_region()});am.click(function(){ao.run_on_dataset()})};q(s.prototype,{get_param_values_dict:function(){var ah={};this.parent_div.find(":input").each(function(){var ai=$(this).attr("name"),aj=$(this).val();ah[ai]=JSON.stringify(aj)});return ah},get_param_values:function(){var ai=[];var ah={};this.parent_div.find(":input").each(function(){var aj=$(this).attr("name"),ak=$(this).val();if(aj){ai[ai.length]=ak}});return ai},run_on_dataset:function(){var ah=this;ah.run({dataset_id:this.track.original_dataset_id,tool_id:ah.name},null,function(ai){show_modal(ah.name+" is Running",ah.name+" is running on the complete dataset. Tool outputs are in dataset's history.",{Close:hide_modal})})},run_on_region:function(){var ai={dataset_id:this.track.original_dataset_id,chrom:this.track.view.chrom,low:this.track.view.low,high:this.track.view.high,tool_id:this.name},al=this.track,aj=ai.tool_id+al.tool_region_and_parameters_str(ai.chrom,ai.low,ai.high),ah,am;if(al.container===view){var ak=new R(this.name,this.track.view,this.track.container);al.container.add_drawable(ak);al.container.remove_drawable(al);ak.add_drawable(al);al.container_div.appendTo(ak.content_div);ah=ak}else{ah=al.container}if(al instanceof e){am=new W(aj,view,ah,"hda");am.change_mode(al.mode);ah.add_drawable(am)}am.content_div.text("Starting job.");this.run(ai,am,function(an){am.dataset_id=an.dataset_id;am.content_div.text("Running job.");am.init()})},run:function(ai,aj,ak){$.extend(ai,this.get_param_values_dict());var ah=function(){$.getJSON(rerun_tool_url,ai,function(al){if(al==="no converter"){aj.container_div.addClass("error");aj.content_div.text(L)}else{if(al.error){aj.container_div.addClass("error");aj.content_div.text(y+al.message)}else{if(al==="pending"){aj.container_div.addClass("pending");aj.content_div.text("Converting input data so that it can be used quickly with tool.");setTimeout(ah,2000)}else{ak(al)}}}})};ah()}});var P=function(ai,ah,aj,ak){this.name=ai;this.label=ah;this.html=aj;this.value=ak};var g=function(aj,ai,al,am,ak,ah){P.call(this,aj,ai,al,am);this.min=ak;this.max=ah};var h=function(ai,ah,aj,ak){this.name=ai;this.index=ah;this.tool_id=aj;this.tool_exp_name=ak};var X=function(ai,ah,aj,ak){h.call(this,ai,ah,aj,ak);this.low=-Number.MAX_VALUE;this.high=Number.MAX_VALUE;this.min=Number.MAX_VALUE;this.max=-Number.MAX_VALUE;this.container=null;this.slider=null;this.slider_label=null};q(X.prototype,{applies_to:function(ah){if(ah.length>this.index){return true}return false},keep:function(ah){if(!this.applies_to(ah)){return true}var ai=ah[this.index];return(isNaN(ai)||(ai>=this.low&&ai<=this.high))},update_attrs:function(ai){var ah=false;if(!this.applies_to(ai)){return ah}if(ai[this.index]<this.min){this.min=Math.floor(ai[this.index]);ah=true}if(ai[this.index]>this.max){this.max=Math.ceil(ai[this.index]);ah=true}return ah},update_ui_elt:function(){if(this.min!=this.max){this.container.show()}else{this.container.hide()}var aj=function(am,ak){var al=ak-am;return(al<=2?0.01:1)};var ai=this.slider.slider("option","min"),ah=this.slider.slider("option","max");if(this.min<ai||this.max>ah){this.slider.slider("option","min",this.min);this.slider.slider("option","max",this.max);this.slider.slider("option","step",aj(this.min,this.max));this.slider.slider("option","values",[this.min,this.max])}}});var ac=function(at,aA){this.track=at;this.filters=[];for(var av=0;av<aA.length;av++){var aw=aA[av],aB=aw.name,ah=aw.type,aj=aw.index,az=aw.tool_id,ay=aw.tool_exp_name;if(ah==="int"||ah==="float"){this.filters[av]=new X(aB,aj,az,ay)}else{console.log("ERROR: unsupported filter: ",aB,ah)}}var ak=function(aC,aD,aE){aC.click(function(){var aF=aD.text();max=parseFloat(aE.slider("option","max")),input_size=(max<=1?4:max<=1000000?max.toString().length:6),multi_value=false;if(aE.slider("option","values")){input_size=2*input_size+1;multi_value=true}aD.text("");$("<input type='text'/>").attr("size",input_size).attr("maxlength",input_size).attr("value",aF).appendTo(aD).focus().select().click(function(aG){aG.stopPropagation()}).blur(function(){$(this).remove();aD.text(aF)}).keyup(function(aK){if(aK.keyCode===27){$(this).trigger("blur")}else{if(aK.keyCode===13){var aI=aE.slider("option","min"),aG=aE.slider("option","max"),aJ=function(aL){return(isNaN(aL)||aL>aG||aL<aI)},aH=$(this).val();if(!multi_value){aH=parseFloat(aH);if(aJ(aH)){alert("Parameter value must be in the range ["+aI+"-"+aG+"]");return $(this)}}else{aH=aH.split("-");aH=[parseFloat(aH[0]),parseFloat(aH[1])];if(aJ(aH[0])||aJ(aH[1])){alert("Parameter value must be in the range ["+aI+"-"+aG+"]");return $(this)}}aE.slider((multi_value?"values":"value"),aH)}}})})};this.parent_div=$("<div/>").addClass("filters").hide();this.parent_div.bind("drag",function(aC){aC.stopPropagation()}).click(function(aC){aC.stopPropagation()}).bind("dblclick",function(aC){aC.stopPropagation()}).bind("keydown",function(aC){aC.stopPropagation()});var ax=$("<div/>").addClass("sliders").appendTo(this.parent_div);var ap=this;$.each(this.filters,function(aF,aH){aH.container=$("<div/>").addClass("filter-row slider-row").appendTo(ax);var aG=$("<div/>").addClass("elt-label").appendTo(aH.container);var aE=$("<span/>").addClass("slider-name").text(aH.name+" ").appendTo(aG);var aD=$("<span/>");var aJ=$("<span/>").addClass("slider-value").appendTo(aG).append("[").append(aD).append("]");var aC=$("<div/>").addClass("slider").appendTo(aH.container);aH.control_element=$("<div/>").attr("id",aH.name+"-filter-control").appendTo(aC);var aI=[0,0];aH.control_element.slider({range:true,min:Number.MAX_VALUE,max:-Number.MIN_VALUE,values:[0,0],slide:function(aL,aM){var aK=aM.values;aD.text(aK[0]+"-"+aK[1]);aH.low=aK[0];aH.high=aK[1];ap.track.request_draw(true,true)},change:function(aK,aL){aH.control_element.slider("option","slide").call(aH.control_element,aK,aL)}});aH.slider=aH.control_element;aH.slider_label=aD;ak(aJ,aD,aH.control_element);$("<div style='clear: both;'/>").appendTo(aH.container)});if(this.filters.length!==0){var am=$("<div/>").addClass("param-row").appendTo(ax);var ao=$("<input type='submit'/>").attr("value","Run on complete dataset").appendTo(am);var ai=this;ao.click(function(){ai.run_on_dataset()})}var ar=$("<div/>").addClass("display-controls").appendTo(this.parent_div),au,an,aq,al={Transparency:function(aC){ap.alpha_filter=aC},Height:function(aC){ap.height_filter=aC}};$.each(al,function(aE,aD){au=$("<div/>").addClass("filter-row").appendTo(ar),an=$("<span/>").addClass("elt-label").text(aE+":").appendTo(au),aq=$("<select/>").attr("name",aE+"_dropdown").css("float","right").appendTo(au);$("<option/>").attr("value",-1).text("== None ==").appendTo(aq);for(var aC=0;aC<ap.filters.length;aC++){$("<option/>").attr("value",aC).text(ap.filters[aC].name).appendTo(aq)}aq.change(function(){$(this).children("option:selected").each(function(){var aF=parseInt($(this).val());al[aE]((aF>=0?ap.filters[aF]:null));ap.track.request_draw(true,true)})});$("<div style='clear: both;'/>").appendTo(au)});$("<div style='clear: both;'/>").appendTo(this.parent_div)};q(ac.prototype,{reset_filters:function(){for(var ah=0;ah<this.filters.length;ah++){filter=this.filters[ah];filter.slider.slider("option","values",[filter.min,filter.max])}this.alpha_filter=null;this.height_filter=null},run_on_dataset:function(){var ap=function(au,ar,at){if(!(ar in au)){au[ar]=at}return au[ar]};var aj={},ah,ai,ak;for(var al=0;al<this.filters.length;al++){ah=this.filters[al];if(ah.tool_id){if(ah.min!=ah.low){ai=ap(aj,ah.tool_id,[]);ai[ai.length]=ah.tool_exp_name+" >= "+ah.low}if(ah.max!=ah.high){ai=ap(aj,ah.tool_id,[]);ai[ai.length]=ah.tool_exp_name+" <= "+ah.high}}}var an=[];for(var aq in aj){an[an.length]=[aq,aj[aq]]}var ao=an.length;(function am(ay,av){var at=av[0],au=at[0],ax=at[1],aw="("+ax.join(") and (")+")",ar={cond:aw,input:ay,target_dataset_id:ay,tool_id:au},av=av.slice(1);$.getJSON(run_tool_url,ar,function(az){if(az.error){show_modal("Filter Dataset","Error running tool "+au,{Close:hide_modal})}else{if(av.length===0){show_modal("Filtering Dataset","Filter(s) are running on the complete dataset. Outputs are in dataset's history.",{Close:hide_modal})}else{am(az.dataset_id,av)}}})})(this.track.dataset_id,an)}});var E=function(ah,ai){N.Scaler.call(this,ai);this.filter=ah};E.prototype.gen_val=function(ah){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(ah[this.filter.index])-this.filter.low)/(this.filter.high-this.filter.low))};var H=function(ah){this.track=ah.track;this.params=ah.params;this.values={};this.restore_values((ah.saved_values?ah.saved_values:{}));this.onchange=ah.onchange};q(H.prototype,{restore_values:function(ah){var ai=this;$.each(this.params,function(aj,ak){if(ah[ak.key]!==undefined){ai.values[ak.key]=ah[ak.key]}else{ai.values[ak.key]=ak.default_value}})},build_form:function(){var ai=this;var ah=$("<div />");$.each(this.params,function(am,ak){if(!ak.hidden){var aj="param_"+am;var ao=ai.values[ak.key];var ar=$("<div class='form-row' />").appendTo(ah);ar.append($("<label />").attr("for",aj).text(ak.label+":"));if(ak.type==="bool"){ar.append($('<input type="checkbox" />').attr("id",aj).attr("name",aj).attr("checked",ao))}else{if(ak.type==="text"){ar.append($('<input type="text"/>').attr("id",aj).val(ao).click(function(){$(this).select()}))}else{if(ak.type==="color"){var an=$("<input />").attr("id",aj).attr("name",aj).val(ao);var ap=$("<div class='tipsy tipsy-north' style='position: absolute;' />").hide();var al=$("<div style='background-color: black; padding: 10px;'></div>").appendTo(ap);var aq=$("<div/>").appendTo(al).farbtastic({width:100,height:100,callback:an,color:ao});$("<div />").append(an).append(ap).appendTo(ar).bind("click",function(at){ap.css({left:$(this).position().left+($(an).width()/2)-60,top:$(this).position().top+$(this.height)}).show();$(document).bind("click.color-picker",function(){ap.hide();$(document).unbind("click.color-picker")});at.stopPropagation()})}else{ar.append($("<input />").attr("id",aj).attr("name",aj).val(ao))}}}}});return ah},update_from_form:function(ah){var aj=this;var ai=false;$.each(this.params,function(ak,am){if(!am.hidden){var an="param_"+ak;var al=ah.find("#"+an).val();if(am.type==="float"){al=parseFloat(al)}else{if(am.type==="int"){al=parseInt(al)}else{if(am.type==="bool"){al=ah.find("#"+an).is(":checked")}}}if(al!==aj.values[am.key]){aj.values[am.key]=al;ai=true}}});if(ai){this.onchange()}}});var b=function(ah,ak,aj,ai,al){this.track=ah;this.index=ak;this.low=ak*S*aj;this.high=(ak+1)*S*aj;this.resolution=aj;this.canvas=$("<div class='track-tile'/>").append(ai);this.data=al;this.stale=false};b.prototype.predisplay_actions=function(){};var l=function(ah,ak,aj,ai,al,am){b.call(this,ah,ak,aj,ai,al);this.max_val=am};q(l.prototype,b.prototype);var Q=function(ah,al,ak,aj,an,ao,am,ai){b.call(this,ah,al,ak,aj,an);this.mode=ao;this.message=am;this.feature_mapper=ai};q(Q.prototype,b.prototype);Q.prototype.predisplay_actions=function(){var ai=this,ah={};if(ai.mode!=="Pack"){return}$(this.canvas).mousemove(function(au){var ao=$(this).offset(),at=au.pageX-ao.left,ar=au.pageY-ao.top,ay=ai.feature_mapper.get_feature_data(at,ar),ap=(ay?ay[0]:null);$(this).siblings(".feature-popup").each(function(){if(!ap||$(this).attr("id")!==ap.toString()){$(this).remove()}});if(ay){var ak=ah[ap];if(!ak){var ap=ay[0],av={name:ay[3],start:ay[1],end:ay[2],strand:ay[4]},an=ai.track.filters_manager.filters,am;for(var aq=0;aq<an.length;aq++){am=an[aq];av[am.name]=ay[am.index]}var ak=$("<div/>").attr("id",ap).addClass("feature-popup"),ax,aw,az=$("<table/>").appendTo(ak),aA;for(ax in av){aw=av[ax];aA=$("<tr/>").appendTo(az);$("<th/>").appendTo(aA).text(ax);$("<td/>").attr("align","left").appendTo(aA).text(typeof(aw)=="number"?ab(aw,2):aw)}ah[ap]=ak}ak.appendTo($(ai.canvas).parent());var al=at+parseInt(ai.canvas.css("left"))+7,aj=ar+parseInt(ai.canvas.css("top"))+7;ak.css("left",al+"px").css("top",aj+"px")}else{if(!au.isPropagationStopped()){au.stopPropagation();$(this).siblings().each(function(){$(this).trigger(au)})}}}).mouseleave(function(){$(this).siblings(".feature-popup").remove()})};var j=function(ak,at,al,ao,au,aj,ai){r.call(this,ak,at,al,{},"draghandle");this.data_url=(aj?aj:default_data_url);this.data_url_extra_params={};this.data_query_wait=(ai?ai:M);this.dataset_check_url=converted_datasets_state_url;if(!j.id_counter){j.id_counter=0}this.id=j.id_counter++;this.container_div=$("<div />").addClass("track").attr("id","track_"+this.id).css("position","relative");if(ao){this.header_div=$("<div class='track-header' />").appendTo(this.container_div);if(this.view.editor){this.drag_div=$("<div/>").addClass(this.drag_handle_class).appendTo(this.header_div)}this.name_div=$("<div/>").addClass("track-name").appendTo(this.header_div).text(this.name).attr("id",this.name.replace(/\s+/g,"-").replace(/[^a-zA-Z0-9\-]/g,"").toLowerCase());this.icons_div=$("<div/>").css("float","left").appendTo(this.header_div).hide();this.settings_icon=$("<a/>").attr("href","javascript:void(0);").attr("title","Edit settings").addClass("icon-button settings-icon").tipsy({gravity:"s"}).appendTo(this.icons_div);this.overview_icon=$("<a/>").attr("href","javascript:void(0);").attr("title","Set as overview").addClass("icon-button overview-icon").tipsy({gravity:"s"}).appendTo(this.icons_div);this.filters_icon=$("<a/>").attr("href","javascript:void(0);").attr("title","Filters").addClass("icon-button filters-icon").tipsy({gravity:"s"}).appendTo(this.icons_div).hide();this.tools_icon=$("<a/>").attr("href","javascript:void(0);").attr("title","Tools").addClass("icon-button tools-icon").tipsy({gravity:"s"}).appendTo(this.icons_div).hide();this.remove_icon=$("<a/>").attr("href","javascript:void(0);").attr("title","Remove").addClass("icon-button remove-icon").tipsy({gravity:"s"}).appendTo(this.icons_div);var am=this;this.header_div.dblclick(function(av){av.stopPropagation()});this.settings_icon.click(function(){var ax=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},av=function(){am.config.update_from_form($(".dialog-box"));hide_modal();$(window).unbind("keypress.check_enter_esc")},aw=function(ay){if((ay.keyCode||ay.which)===27){ax()}else{if((ay.keyCode||ay.which)===13){av()}}};$(window).bind("keypress.check_enter_esc",aw);show_modal("Configure Track",am.config.build_form(),{Cancel:ax,OK:av})});this.overview_icon.click(function(){am.view.set_overview(am)});this.filters_icon.click(function(){am.filters_div.toggle();am.filters_manager.reset_filters()});this.tools_icon.click(function(){am.dynamic_tool_div.toggle();if(am.dynamic_tool_div.is(":visible")){am.set_name(am.name+am.tool_region_and_parameters_str())}else{am.revert_name()}$(".tipsy").remove()});this.remove_icon.click(function(){$(".tipsy").remove();am.remove()});if(am.display_modes!==undefined){if(am.mode_div===undefined){am.mode_div=$("<div class='right-float menubutton popup' />").appendTo(am.header_div);var an=(am.config&&am.config.values.mode?am.config.values.mode:am.display_modes[0]);am.mode=an;am.mode_div.text(an);var ah={};for(var ap=0,ar=am.display_modes.length;ap<ar;ap++){var aq=am.display_modes[ap];ah[aq]=function(av){return function(){am.change_mode(av)}}(aq)}make_popupmenu(am.mode_div,ah)}else{am.mode_div.hide()}this.header_div.append($("<div/>").css("clear","both"));this.container_div.hover(function(){am.icons_div.show()},function(){am.icons_div.hide()})}}this.content_div=$("<div class='track-content'>").appendTo(this.container_div);this.container.content_div.append(this.container_div)};q(j.prototype,r.prototype,{get_type:function(){if(this instanceof ad){return"LabelTrack"}else{if(this instanceof B){return"ReferenceTrack"}else{if(this instanceof k){return"LineTrack"}else{if(this instanceof Y){return"ReadTrack"}else{if(this instanceof W){return"ToolDataFeatureTrack"}else{if(this instanceof V){return"VcfTrack"}else{if(this instanceof e){return"FeatureTrack"}}}}}}}return""},init:function(){var ah=this;ah.enabled=false;ah.tile_cache.clear();ah.data_manager.clear();ah.initial_canvas=undefined;ah.content_div.css("height","auto");ah.container_div.removeClass("nodata error pending");if(!ah.dataset_id){return}$.getJSON(converted_datasets_state_url,{hda_ldda:ah.hda_ldda,dataset_id:ah.dataset_id,chrom:ah.view.chrom},function(ai){if(!ai||ai==="error"||ai.kind==="error"){ah.container_div.addClass("error");ah.content_div.text(p);if(ai.message){var aj=$(" <a href='javascript:void(0);'></a>").text("View error").click(function(){show_modal("Trackster Error","<pre>"+ai.message+"</pre>",{Close:hide_modal})});ah.content_div.append(aj)}}else{if(ai==="no converter"){ah.container_div.addClass("error");ah.content_div.text(L)}else{if(ai==="no data"||(ai.data!==undefined&&(ai.data===null||ai.data.length===0))){ah.container_div.addClass("nodata");ah.content_div.text(G)}else{if(ai==="pending"){ah.container_div.addClass("pending");ah.content_div.text(u);setTimeout(function(){ah.init()},ah.data_query_wait)}else{if(ai.status==="data"){if(ai.valid_chroms){ah.valid_chroms=ai.valid_chroms;ah.update_track_icons()}ah.content_div.text(aa);if(ah.view.chrom){ah.content_div.text("");ah.content_div.css("height",ah.height_px+"px");ah.enabled=true;$.when(ah.predraw_init()).done(function(){ah.container_div.removeClass("nodata error pending");ah.request_draw()})}}}}}}});this.update_track_icons()},predraw_init:function(){}});var O=function(ak,aj){var ai=this,ah=ai.view;n(ai.container_div,ai.drag_handle_class,".group",ai);this.filters_manager=new ac(this,(ak!==undefined?ak:{}));this.filters_available=false;this.filters_visible=false;this.tool=(aj!==undefined&&obj_length(aj)>0?new s(this,aj):undefined);if(this.header_div){if(this.filters_manager){this.filters_div=this.filters_manager.parent_div;this.header_div.after(this.filters_div)}if(this.tool){this.dynamic_tool_div=this.tool.parent_div;this.header_div.after(this.dynamic_tool_div)}}};q(O.prototype,r.prototype,j.prototype,{copy:function(ah){return new this.constructor(this.name,this.view,ah,this.hda_ldda,this.dataset_id,this.prefs,this.filters,this.tool)},to_json: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,}},change_mode:function(ai){var ah=this;ah.mode_div.text(ai);ah.mode=ai;ah.config.values.mode=ai;ah.tile_cache.clear();ah.request_draw();return ah},update_track_icons:function(){var ah=this;if(ah.filters_available>0){ah.filters_icon.show()}else{ah.filters_icon.hide()}if(ah.tool){ah.tools_icon.show()}else{ah.tools_icon.hide()}},_gen_tile_cache_key:function(ai,aj,ah){return ai+"_"+aj+"_"+ah},request_draw:function(ai,ah){this.view.request_redraw(false,ai,ah,this)},_draw:function(aj,ar){if(!this.enabled){return}if(!(this instanceof B)&&(!this.dataset_id)){return}var aq=this.view.low,an=this.view.high,ao=an-aq,ak=this.view.container.width(),av=ak/ao,am=this.view.resolution,au=$("<div style='position: relative;'></div>");if(this.is_overview){aq=this.view.max_low;an=this.view.max_high;am=Math.pow(D,Math.ceil(Math.log((view.max_high-view.max_low)/S)/Math.log(D)));av=ak/(view.max_high-view.max_low)}if(!ar){this.content_div.children().remove()}this.content_div.append(au);this.max_height=0;var ai=Math.floor(aq/am/S);var ap=true;var at=[];var ah=0;while((ai*S*am)<an){tile=this.draw_helper(aj,ak,ai,am,au,av);if(tile){at.push(tile)}else{ap=false}ai+=1;ah++}var al=this;if(ap){al.postdraw_actions(at,ak,av,ar)}},postdraw_actions:function(al,am,an,ah){var aj=this;var ak=false;for(var ai=0;ai<al.length;ai++){if(al[ai].message){ak=true;break}}if(ak){for(var ai=0;ai<al.length;ai++){tile=al[ai];if(!tile.message){tile.canvas.css("padding-top",F)}}}},draw_helper:function(ai,aj,ak,an,au,ay,av,ao){var al=this,at=this._gen_tile_cache_key(aj,ay,ak),ap=ak*S*an,ax=ap+S*an;var aq=(ai?undefined:al.tile_cache.get(at));if(aq){al.show_tile(aq,au,ay);return aq}var ar=function(az){return("isResolved" in az)};var am=true;var ah=al.data_manager.get_data(ap,ax,al.mode,an,al.data_url_extra_params);if(ar(ah)){am=false}var aw;if(view.reference_track&&ay>view.canvas_manager.char_width_px){aw=view.reference_track.data_manager.get_data(ap,ax,al.mode,an,view.reference_track.data_url_extra_params);if(ar(aw)){am=false}}if(am){q(ah,ao);var aq=al.draw_tile(ah,al.mode,an,ak,ay,aw);if(aq!==undefined){al.tile_cache.set(at,aq);al.show_tile(aq,au,ay)}return aq}$.when(ah,aw).then(function(){view.request_redraw(false,false,false,al)});return null},show_tile:function(an,ap,aq){var aj=this,ai=an.canvas,am=ai;if(an.message){var ar=$("<div/>"),ao=$("<div/>").addClass("tile-message").text(an.message).css({height:F-1,width:an.canvas.width}).appendTo(ar),al=$("<a href='javascript:void(0);'/>").addClass("icon more-down").appendTo(ao),ah=$("<a href='javascript:void(0);'/>").addClass("icon more-across").appendTo(ao);ar.append(ai);am=ar;al.click(function(){an.stale=true;aj.data_manager.get_more_data(an.low,an.high,aj.mode,an.resolution,{},aj.data_manager.DEEP_DATA_REQ);aj.request_draw()}).dblclick(function(at){at.stopPropagation()});ah.click(function(){an.stale=true;aj.data_manager.get_more_data(an.low,an.high,aj.mode,an.resolution,{},aj.data_manager.BROAD_DATA_REQ);aj.request_draw()}).dblclick(function(at){at.stopPropagation()})}an.predisplay_actions();var ak=(an.low-(this.is_overview?this.view.max_low:this.view.low))*aq;if(this.left_offset){ak-=this.left_offset}am.css({position:"absolute",top:0,left:ak,height:""});ap.append(am);aj.max_height=Math.max(aj.max_height,am.height());aj.content_div.css("height",aj.max_height+"px");ap.children().css("height",aj.max_height+"px")},_get_tile_bounds:function(ah,ai){var ak=ah*S*ai,al=S*ai,aj=(ak+al<=this.view.max_high?ak+al:this.view.max_high);return[ak,aj]},tool_region_and_parameters_str:function(aj,ah,ak){var ai=this,al=(aj!==undefined&&ah!==undefined&&ak!==undefined?aj+":"+ah+"-"+ak:"all");return" - region=["+al+"], parameters=["+ai.tool.get_param_values().join(", ")+"]"}});var ad=function(ai,ah){j.call(this,"label",ai,ah,false,{});this.container_div.addClass("label-track")};q(ad.prototype,j.prototype,{init:function(){this.enabled=true},_draw:function(){var aj=this.view,ak=aj.high-aj.low,an=Math.floor(Math.pow(10,Math.floor(Math.log(ak)/Math.log(10)))),ah=Math.floor(aj.low/an)*an,al=this.view.container.width(),ai=$("<div style='position: relative; height: 1.3em;'></div>");while(ah<aj.high){var am=(ah-aj.low)/ak*al;ai.append($("<div class='label'>"+commatize(ah)+"</div>").css({position:"absolute",left:am-1}));ah+=an}this.content_div.children(":first").remove();this.content_div.append(ai)}});var B=function(ah){j.call(this,"reference",ah,{content_div:ah.top_labeltrack},false,{});O.call(this);ah.reference_track=this;this.left_offset=200;this.height_px=12;this.container_div.addClass("reference-track");this.content_div.css("background","none");this.content_div.css("min-height","0px");this.content_div.css("border","none");this.data_url=reference_url;this.data_url_extra_params={dbkey:ah.dbkey};this.data_manager=new J(C,this,false);this.tile_cache=new c(v)};q(B.prototype,r.prototype,O.prototype,{init:function(){this.enabled=true},draw_tile:function(ar,an,am,ai,at){var al=this,aj=S*am;if(at>this.view.canvas_manager.char_width_px){if(ar.data===null){al.content_div.css("height","0px");return}var ak=this.view.canvas_manager.new_canvas();var aq=ak.getContext("2d");ak.width=Math.ceil(aj*at+al.left_offset);ak.height=al.height_px;aq.font=aq.canvas.manager.default_font;aq.textAlign="center";ar=ar.data;for(var ao=0,ap=ar.length;ao<ap;ao++){var ah=Math.round(ao*at);aq.fillText(ar[ao],ah+al.left_offset,10)}return new b(al,ai,am,ak,ar)}this.content_div.css("height","0px")}});var k=function(am,ak,aj,an,ah,al){var ai=this;this.display_modes=["Histogram","Line","Filled","Intensity"];this.mode="Histogram";j.call(this,am,ak,aj,al);O.call(this);this.min_height_px=16;this.max_height_px=400;this.height_px=80;this.hda_ldda=an;this.dataset_id=ah;this.original_dataset_id=ah;this.data_manager=new T(C,this);this.tile_cache=new c(v);this.left_offset=0;this.config=new H({track:this,params:[{key:"name",label:"Name",type:"text",default_value:am},{key:"color",label:"Color",type:"color",default_value: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:this.height_px,hidden:true}],saved_values:al,onchange:function(){ai.set_name(ai.prefs.name);ai.vertical_range=ai.prefs.max_value-ai.prefs.min_value;$("#linetrack_"+ai.dataset_id+"_minval").text(ai.prefs.min_value);$("#linetrack_"+ai.dataset_id+"_maxval").text(ai.prefs.max_value);ai.tile_cache.clear();ai.request_draw()}});this.prefs=this.config.values;this.height_px=this.config.values.height;this.vertical_range=this.config.values.max_value-this.config.values.min_value;this.add_resize_handle()};q(k.prototype,r.prototype,O.prototype,{add_resize_handle:function(){var ah=this;var ak=false;var aj=false;var ai=$("<div class='track-resize'>");$(ah.container_div).hover(function(){ak=true;ai.show()},function(){ak=false;if(!aj){ai.hide()}});ai.hide().bind("dragstart",function(al,am){aj=true;am.original_height=$(ah.content_div).height()}).bind("drag",function(am,an){var al=Math.min(Math.max(an.original_height+an.deltaY,ah.min_height_px),ah.max_height_px);$(ah.content_div).css("height",al);ah.height_px=al;ah.request_draw(true)}).bind("dragend",function(al,am){ah.tile_cache.clear();aj=false;if(!ak){ai.hide()}ah.config.values.height=ah.height_px}).appendTo(ah.container_div)},predraw_init:function(){var ah=this;ah.vertical_range=undefined;return $.getJSON(ah.data_url,{stats:true,chrom:ah.view.chrom,low:null,high:null,hda_ldda:ah.hda_ldda,dataset_id:ah.dataset_id},function(ai){ah.container_div.addClass("line-track");var ak=ai.data;if(isNaN(parseFloat(ah.prefs.min_value))||isNaN(parseFloat(ah.prefs.max_value))){ah.prefs.min_value=ak.min;ah.prefs.max_value=ak.max;$("#track_"+ah.dataset_id+"_minval").val(ah.prefs.min_value);$("#track_"+ah.dataset_id+"_maxval").val(ah.prefs.max_value)}ah.vertical_range=ah.prefs.max_value-ah.prefs.min_value;ah.total_frequency=ak.total_frequency;ah.container_div.find(".yaxislabel").remove();var al=$("<div />").addClass("yaxislabel").attr("id","linetrack_"+ah.dataset_id+"_minval").text(ab(ah.prefs.min_value,3));var aj=$("<div />").addClass("yaxislabel").attr("id","linetrack_"+ah.dataset_id+"_maxval").text(ab(ah.prefs.max_value,3));aj.css({position:"absolute",top:"24px",left:"10px"});aj.prependTo(ah.container_div);al.css({position:"absolute",bottom:"2px",left:"10px"});al.prependTo(ah.container_div)})},draw_tile:function(au,am,al,aj,at){if(this.vertical_range===undefined){return}var ah=this._get_tile_bounds(aj,al),an=ah[0],ar=ah[1],ai=Math.ceil((ar-an)*at),ap=this.height_px;var ak=this.view.canvas_manager.new_canvas();ak.width=ai,ak.height=ap;var aq=ak.getContext("2d");var ao=new N.LinePainter(au.data,an,ar,this.prefs,am);ao.draw(aq,ai,ap);return new b(this.track,aj,al,ak,au.data)}});var e=function(ah,an,ai,am,ap,ao,ak,al){var aj=this;this.display_modes=["Auto","Histogram","Dense","Squish","Pack"];j.call(this,ah,an,ai,true,ao);O.call(this,ak,al);this.config=new H({track:this,params:[{key:"name",label:"Name",type:"text",default_value:ah},{key:"block_color",label:"Block color",type:"color",default_value:get_random_color()},{key:"label_color",label:"Label color",type:"color",default_value:"black"},{key:"show_counts",label:"Show summary counts",type:"bool",default_value:true},{key:"mode",type:"string",default_value:this.mode,hidden:true},],saved_values:ao,onchange:function(){aj.set_name(aj.prefs.name);aj.tile_cache.clear();aj.request_draw()}});this.prefs=this.config.values;this.height_px=0;this.container_div.addClass("feature-track");this.hda_ldda=am;this.dataset_id=ap;this.original_dataset_id=ap;this.show_labels_scale=0.001;this.showing_details=false;this.summary_draw_height=30;this.inc_slots={};this.start_end_dct={};this.tile_cache=new c(d);this.data_manager=new T(20,this);this.left_offset=200;this.painter=N.LinkedFeaturePainter};q(e.prototype,r.prototype,O.prototype,{postdraw_actions:function(ax,ah,ay,aw){O.prototype.postdraw_actions.call(this,ax,aw);var ak=this;if(aw){var am=ak.content_div.children();var an=false;for(var al=am.length-1,ar=0;al>=ar;al--){var aj=$(am[al]);if(an){aj.remove()}else{if(aj.children().length!==0){an=true}}}}if(ak.mode=="Histogram"){var aq=-1;for(var al=0;al<ax.length;al++){var av=ax[al].max_val;if(av>aq){aq=av}}for(var al=0;al<ax.length;al++){var au=ax[al];if(au.max_val!==aq){au.canvas.remove();ak.draw_helper(true,ah,au.index,au.resolution,au.canvas.parent(),ay,[],{max:aq})}}}if(ak.filters_manager){var ai=ak.filters_manager.filters;for(var ap=0;ap<ai.length;ap++){ai[ap].update_ui_elt()}var ao=false,at;for(var al=0;al<ax.length;al++){if(ax[al].data.length){at=ax[al].data[0];for(var ap=0;ap<ai.length;ap++){if(ai[ap].applies_to(at)){ao=true;break}}}}if(ak.filters_available!==ao){ak.filters_available=ao;if(!ak.filters_available){ak.filters_div.hide()}ak.update_track_icons()}}},update_auto_mode:function(ah){if(this.mode=="Auto"){if(ah=="no_detail"){ah="feature spans"}else{if(ah=="summary_tree"){ah="coverage histogram"}}this.mode_div.text("Auto ("+ah+")")}},incremental_slots:function(al,ai,ak){var aj=this.view.canvas_manager.dummy_context,ah=this.inc_slots[al];if(!ah||(ah.mode!==ak)){ah=new (t.FeatureSlotter)(al,ak==="Pack",A,function(am){return aj.measureText(am)});ah.mode=ak;this.inc_slots[al]=ah}return ah.slot_features(ai)},get_summary_tree_data:function(al,ao,aj,ax){if(ax>aj-ao){ax=aj-ao}var at=Math.floor((aj-ao)/ax),aw=[],ak=0;var am=0,an=0,ar,av=0,ap=[],au,aq;var ai=function(aA,az,aB,ay){aA[0]=az+aB*ay;aA[1]=az+(aB+1)*ay};while(av<ax&&am!==al.length){var ah=false;for(;av<ax&&!ah;av++){ai(ap,ao,av,at);for(an=am;an<al.length;an++){ar=al[an].slice(1,3);if(is_overlap(ar,ap)){ah=true;break}}if(ah){break}}data_start_index=an;aw[aw.length]=au=[ap[0],0];for(;an<al.length;an++){ar=al[an].slice(1,3);if(is_overlap(ar,ap)){au[1]++}else{break}}if(au[1]>ak){ak=au[1]}av++}return{max:ak,delta:at,data:aw}},draw_tile:function(aw,az,aD,aH,ar,ak){var aA=this,am=aA._get_tile_bounds(aH,aD),aK=am[0],ai=am[1],ay=ai-aK,aB=Math.ceil(ay*ar),aQ=25,al=this.left_offset,ax,an;if(az==="Auto"){if(aw.dataset_type==="summary_tree"){az=aw.dataset_type}else{if(aw.extra_info==="no_detail"||aA.is_overview){az="no_detail"}else{var aP=aw.data;if(this.view.high-this.view.low>K){az="Squish"}else{az="Pack"}}}this.update_auto_mode(az)}if(az==="summary_tree"||az==="Histogram"){an=this.summary_draw_height;this.container_div.find(".yaxislabel").remove();var ah=$("<div />").addClass("yaxislabel");ah.text(aw.max);ah.css({position:"absolute",top:"24px",left:"10px",color:this.prefs.label_color});ah.prependTo(this.container_div);var aj=this.view.canvas_manager.new_canvas();aj.width=aB+al;aj.height=an+U;if(aw.dataset_type!="summary_tree"){var at=this.get_summary_tree_data(aw.data,aK,ai,200);if(aw.max){at.max=aw.max}aw=at}var aM=new N.SummaryTreePainter(aw,aK,ai,this.prefs);var aC=aj.getContext("2d");aC.translate(al,U);aM.draw(aC,aB,an);return new l(aA,aH,aD,aj,aw.data,aw.max)}var ax,ap=1;if(az==="no_detail"||az==="Squish"||az==="Pack"){ap=this.incremental_slots(ar,aw.data,az);ax=this.inc_slots[ar].slots}var aq=[];if(aw.data){var au=this.filters_manager.filters;for(var aE=0,aG=aw.data.length;aE<aG;aE++){var ao=aw.data[aE];var aF=false;var av;for(var aJ=0,aO=au.length;aJ<aO;aJ++){av=au[aJ];av.update_attrs(ao);if(!av.keep(ao)){aF=true;break}}if(!aF){aq.push(ao)}}}var aN=(this.filters_manager.alpha_filter?new E(this.filters_manager.alpha_filter):null);var aL=(this.filters_manager.height_filter?new E(this.filters_manager.height_filter):null);var aM=new (this.painter)(aq,aK,ai,this.prefs,az,aN,aL,ak);var an=Math.max(af,aM.get_required_height(ap));var aj=this.view.canvas_manager.new_canvas();var aI=null;aj.width=aB+al;aj.height=an;var aC=aj.getContext("2d");aC.fillStyle=this.prefs.block_color;aC.font=aC.canvas.manager.default_font;aC.textAlign="right";this.container_div.find(".yaxislabel").remove();if(aw.data){aC.translate(al,0);aI=aM.draw(aC,aB,an,ax);aI.translation=-al}return new Q(aA,aH,aD,aj,aw.data,az,aw.message,aI)}});var V=function(al,aj,ai,an,ah,ak,am){e.call(this,al,aj,ai,an,ah,ak,am);this.painter=N.VariantPainter};q(V.prototype,r.prototype,O.prototype,e.prototype);var Y=function(al,aj,ai,an,ah,ak,am){e.call(this,al,aj,ai,an,ah,ak,am);this.config=new H({track:this,params:[{key:"name",label:"Name",type:"text",default_value:al},{key:"block_color",label:"Block color",type:"color",default_value: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_differences",label:"Show differences only",type:"bool",default_value:true},{key:"show_counts",label:"Show summary counts",type:"bool",default_value:true},{key:"mode",type:"string",default_value:this.mode,hidden:true},],saved_values:ak,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=N.ReadPainter;this.update_track_icons()};q(Y.prototype,r.prototype,O.prototype,e.prototype);var W=function(al,aj,ai,an,ah,ak,am){e.call(this,al,aj,ai,an,ah,ak,am,{});this.data_url=raw_data_url;this.data_query_wait=1000;this.dataset_check_url=dataset_state_url};q(W.prototype,r.prototype,O.prototype,e.prototype,{predraw_init:function(){var ai=this;var ah=function(){if(ai.data_manager.size()===0){setTimeout(ah,300)}else{ai.data_url=default_data_url;ai.data_query_wait=M;ai.dataset_state_url=converted_datasets_state_url;$.getJSON(ai.dataset_state_url,{dataset_id:ai.dataset_id,hda_ldda:ai.hda_ldda},function(aj){})}};ah()}});Z.View=ae;Z.DrawableGroup=R;Z.LineTrack=k;Z.FeatureTrack=e;Z.ReadTrack=Y};var slotting_module=function(c,b){var e=c("class").extend;var d=2,a=5;b.FeatureSlotter=function(j,h,f,g){this.slots={};this.start_end_dct={};this.w_scale=j;this.include_label=h;this.max_rows=f;this.measureText=g};e(b.FeatureSlotter.prototype,{slot_features:function(m){var p=this.w_scale,s=this.slots,h=this.start_end_dct,y=[],A=[],n=0,z=this.max_rows;for(var w=0,x=m.length;w<x;w++){var l=m[w],o=l[0];if(s[o]!==undefined){n=Math.max(n,s[o]);A.push(s[o])}else{y.push(w)}}var q=function(G,H){for(var F=0;F<=z;F++){var D=false,I=h[F];if(I!==undefined){for(var C=0,E=I.length;C<E;C++){var B=I[C];if(H>B[0]&&G<B[1]){D=true;break}}}if(!D){return F}}return -1};for(var w=0,x=y.length;w<x;w++){var l=m[y[w]],o=l[0],u=l[1],f=l[2],r=l[3],g=Math.floor(u*p),k=Math.ceil(f*p),v=this.measureText(r).width,j;if(r!==undefined&&this.include_label){v+=(d+a);if(g-v>=0){g-=v;j="left"}else{k+=v;j="right"}}var t=q(g,k);if(t>=0){if(h[t]===undefined){h[t]=[]}h[t].push([g,k]);s[o]=t;n=Math.max(n,t)}else{}}return n+1}})};var painters_module=function(k,y){var v=k("class").extend;var q=function(J,B,H,A,G,E){if(E===undefined){E=4}var D=A-B;var C=G-H;var F=Math.floor(Math.sqrt(D*D+C*C)/E);var K=D/F;var I=C/F;var z;for(z=0;z<F;z++,B+=K,H+=I){if(z%2!==0){continue}J.fillRect(B,H,E,1)}};var r=function(B,A,z,E){var D=A-E/2,C=A+E/2,F=z-Math.sqrt(E*3/2);B.beginPath();B.moveTo(D,F);B.lineTo(C,F);B.lineTo(A,z);B.lineTo(D,F);B.strokeStyle=this.fillStyle;B.fill();B.stroke();B.closePath()};var e=function(z){this.default_val=(z?z:1)};e.prototype.gen_val=function(z){return this.default_val};var n=function(B,D,z,A,C){this.data=B;this.view_start=D;this.view_end=z;this.prefs=v({},this.default_prefs,A);this.mode=C};n.prototype.default_prefs={};var w=function(B,D,z,A,C){n.call(this,B,D,z,A,C)};w.prototype.default_prefs={show_counts:false};w.prototype.draw=function(M,z,L){var E=this.view_start,O=this.view_end-this.view_start,N=z/O;var J=this.data.data,I=this.data.delta,G=this.data.max,B=L;delta_x_px=Math.ceil(I*N);M.save();for(var C=0,D=J.length;C<D;C++){var H=Math.floor((J[C][0]-E)*N);var F=J[C][1];if(!F){continue}var K=F/G*L;if(F!==0&&K<1){K=1}M.fillStyle=this.prefs.block_color;M.fillRect(H,B-K,delta_x_px,K);var A=4;if(this.prefs.show_counts&&(M.measureText(F).width+A)<delta_x_px){M.fillStyle=this.prefs.label_color;M.textAlign="center";M.fillText(F,H+(delta_x_px/2),10)}}M.restore()};var c=function(z,D,F,G,B){n.call(this,z,D,F,G,B);if(this.prefs.min_value===undefined){var H=Infinity;for(var A=0,C=this.data.length;A<C;A++){H=Math.min(H,this.data[A][1])}this.prefs.min_value=H}if(this.prefs.max_value===undefined){var E=-Infinity;for(var A=0,C=this.data.length;A<C;A++){E=Math.max(E,this.data[A][1])}this.prefs.max_value=E}};c.prototype.default_prefs={min_value:undefined,max_value:undefined,mode:"Histogram",color:"#000",overflow_color:"#F66"};c.prototype.draw=function(N,M,K){var F=false,H=this.prefs.min_value,D=this.prefs.max_value,J=D-H,z=K,A=this.view_start,L=this.view_end-this.view_start,B=M/L,I=this.mode,T=this.data;N.save();var U=Math.round(K+H/J*K);if(I!=="Intensity"){N.fillStyle="#aaa";N.fillRect(0,U,M,1)}N.beginPath();var R,E,C;if(T.length>1){C=Math.ceil((T[1][0]-T[0][0])*B)}else{C=10}for(var O=0,P=T.length;O<P;O++){N.fillStyle=this.prefs.color;R=Math.round((T[O][0]-A)*B);E=T[O][1];var Q=false,G=false;if(E===null){if(F&&I==="Filled"){N.lineTo(R,z)}F=false;continue}if(E<H){G=true;E=H}else{if(E>D){Q=true;E=D}}if(I==="Histogram"){E=Math.round(E/J*z);N.fillRect(R,U,C,-E)}else{if(I==="Intensity"){E=255-Math.floor((E-H)/J*255);N.fillStyle="rgb("+E+","+E+","+E+")";N.fillRect(R,0,C,z)}else{E=Math.round(z-(E-H)/J*z);if(F){N.lineTo(R,E)}else{F=true;if(I==="Filled"){N.moveTo(R,z);N.lineTo(R,E)}else{N.moveTo(R,E)}}}}N.fillStyle=this.prefs.overflow_color;if(Q||G){var S;if(I==="Histogram"||I==="Intensity"){S=C}else{R-=2;S=4}if(Q){N.fillRect(R,0,S,3)}if(G){N.fillRect(R,z-3,S,3)}}N.fillStyle=this.prefs.color}if(I==="Filled"){if(F){N.lineTo(R,U);N.lineTo(0,U)}N.fill()}else{N.stroke()}N.restore()};var o=function(z){this.feature_positions={};this.slot_height=z;this.translation=0};o.prototype.map_feature_data=function(A,C,z,B){if(!this.feature_positions[C]){this.feature_positions[C]=[]}this.feature_positions[C].push({data:A,x_start:z,x_end:B})};o.prototype.get_feature_data=function(z,D){var C=Math.floor(D/this.slot_height),B;if(!this.feature_positions[C]){return null}z+=this.translation;for(var A=0;A<this.feature_positions[C].length;A++){B=this.feature_positions[C][A];if(z>=B.x_start&&z<=B.x_end){return B.data}}};var p=function(B,E,z,A,D,F,C){n.call(this,B,E,z,A,D);this.alpha_scaler=(F?F:new e());this.height_scaler=(C?C:new e())};p.prototype.default_prefs={block_color:"#FFF",connector_color:"#FFF"};v(p.prototype,{get_required_height:function(A){var z=y_scale=this.get_row_height(),B=this.mode;if(B==="no_detail"||B==="Squish"||B==="Pack"){z=A*y_scale}return z+Math.max(Math.round(y_scale/2),5)},draw:function(L,J,H,G){var R=this.data,E=this.view_start,N=this.view_end;L.save();L.fillStyle=this.prefs.block_color;L.textAlign="right";var I=this.view_end-this.view_start,F=J/I,M=this.get_row_height(),Q=new o(M),C;for(var O=0,P=R.length;O<P;O++){var B=R[O],D=B[0],K=B[1],z=B[2],A=(G&&G[D]!==undefined?G[D]:null);if((K<N&&z>E)&&(this.mode=="Dense"||A!==null)){C=this.draw_element(L,this.mode,B,A,E,N,F,M,J);Q.map_feature_data(B,A,C[0],C[1])}}L.restore();return Q},draw_element:function(F,B,H,D,C,E,G,A,z){console.log("WARNING: Unimplemented function.");return[0,0]}});var d=10,j=3,m=5,x=10,g=1,t=3,f=3,a=9,l=2,h="#ccc";var s=function(B,E,z,A,D,F,C){p.call(this,B,E,z,A,D,F,C)};v(s.prototype,p.prototype,{get_row_height:function(){var A=this.mode,z;if(A==="Dense"){z=d}else{if(A==="no_detail"){z=j}else{if(A==="Squish"){z=m}else{z=x}}}return z},draw_element:function(N,E,W,I,P,ah,al,an,z){var T=W[0],aj=W[1],ab=W[2],R=W[3],ac=Math.floor(Math.max(0,(aj-P)*al)),O=Math.ceil(Math.min(z,Math.max(0,(ab-P)*al))),aa=ac,am=O,Z=(E==="Dense"?0:(0+I))*an,M,af,S=null,ap=null,C=this.prefs.block_color,ae=this.prefs.label_color;N.globalAlpha=this.alpha_scaler.gen_val(W);if(E=="Dense"){I=1}if(E==="no_detail"){N.fillStyle=C;N.fillRect(ac,Z+5,O-ac,g)}else{var L=W[4],Y=W[5],ad=W[6],D=W[7];if(Y&&ad){S=Math.floor(Math.max(0,(Y-P)*al));ap=Math.ceil(Math.min(z,Math.max(0,(ad-P)*al)))}var ak,U;if(E==="Squish"||E==="Dense"){ak=1;U=f}else{ak=5;U=a}if(!D){if(W.strand){if(W.strand==="+"){N.fillStyle=N.canvas.manager.get_pattern("right_strand_inv")}else{if(W.strand==="-"){N.fillStyle=N.canvas.manager.get_pattern("left_strand_inv")}}}else{N.fillStyle=C}N.fillRect(ac,Z,O-ac,U)}else{var K,V;if(E==="Squish"||E==="Dense"){N.fillStyle=h;K=Z+Math.floor(f/2)+1;V=1}else{if(L){var K=Z;var V=U;if(L==="+"){N.fillStyle=N.canvas.manager.get_pattern("right_strand")}else{if(L==="-"){N.fillStyle=N.canvas.manager.get_pattern("left_strand")}}}else{N.fillStyle=h;K+=(f/2)+1;V=1}}N.fillRect(ac,K,O-ac,V);var F;for(var ai=0,B=D.length;ai<B;ai++){var G=D[ai],A=Math.floor(Math.max(0,(G[0]-P)*al)),X=Math.ceil(Math.min(z,Math.max((G[1]-P)*al)));if(A>X){continue}N.fillStyle=C;N.fillRect(A,Z+(U-ak)/2+1,X-A,ak);if(S!==undefined&&ad>Y&&!(A>ap||X<S)){var ag=Math.max(A,S),J=Math.min(X,ap);N.fillRect(ag,Z+1,J-ag,U);if(D.length==1&&E=="Pack"){if(L==="+"){N.fillStyle=N.canvas.manager.get_pattern("right_strand_inv")}else{if(L==="-"){N.fillStyle=N.canvas.manager.get_pattern("left_strand_inv")}}if(ag+14<J){ag+=2;J-=2}N.fillRect(ag,Z+1,J-ag,U)}}}if(E==="Pack"){N.globalAlpha=1;N.fillStyle="white";var H=this.height_scaler.gen_val(W),Q=Math.ceil(U*H),ao=Math.round((U-Q)/2);if(H!==1){N.fillRect(ac,K+1,O-ac,ao);N.fillRect(ac,K+U-ao+1,O-ac,ao)}}}N.globalAlpha=1;if(E==="Pack"&&aj>P){N.fillStyle=ae;if(P===0&&ac-N.measureText(R).width<0){N.textAlign="left";N.fillText(R,O+l,Z+8);am+=N.measureText(R).width+l}else{N.textAlign="right";N.fillText(R,ac-l,Z+8);aa-=N.measureText(R).width+l}}}N.globalAlpha=1;return[aa,am]}});var b=function(B,E,z,A,D,F,C){p.call(this,B,E,z,A,D,F,C)};v(b.prototype,p.prototype,{draw_element:function(S,N,H,D,V,B,K,T,Q){var H=data[i],J=H[0],R=H[1],C=H[2],M=H[3],F=Math.floor(Math.max(0,(R-V)*K)),I=Math.ceil(Math.min(Q,Math.max(0,(C-V)*K))),E=(N==="Dense"?0:(0+D))*T,z,W,A=null,L=null;if(no_label){S.fillStyle=block_color;S.fillRect(F+left_offset,E+5,I-F,1)}else{var U=H[4],P=H[5],G=H[6];z=9;W=1;S.fillRect(F+left_offset,E,I-F,z);if(N!=="Dense"&&M!==undefined&&R>V){S.fillStyle=label_color;if(V===0&&F-S.measureText(M).width<0){S.textAlign="left";S.fillText(M,I+2+left_offset,E+8)}else{S.textAlign="right";S.fillText(M,F-2+left_offset,E+8)}S.fillStyle=block_color}var O=U+" / "+P;if(R>V&&S.measureText(O).width<(I-F)){S.fillStyle="white";S.textAlign="center";S.fillText(O,left_offset+F+(I-F)/2,E+8);S.fillStyle=block_color}}return[F,I]}});var u=function(C,F,z,B,E,G,D,A){p.call(this,C,F,z,B,E,G,D);this.ref_seq=(A?A.data:null)};u.prototype.default_prefs=v({},p.prototype.default_prefs,{show_insertions:false});v(u.prototype,p.prototype,{get_row_height:function(){var z,A=this.mode;if(A==="Dense"){z=d}else{if(A==="Squish"){z=m}else{z=x;if(this.prefs.show_insertions){z*=2}}}return z},draw_read:function(W,R,N,ab,C,V,K,H,G){W.textAlign="center";var U=this,B=[ab,C],Q=0,X=0,T=0,z=W.canvas.manager.char_width_px;var ag=[];if((R==="Pack"||this.mode==="Auto")&&H!==undefined&&N>z){T=Math.round(N/2)}if(!K){K=[[0,H.length]]}for(var O=0,Z=K.length;O<Z;O++){var L=K[O],D="MIDNSHP=X"[L[0]],P=L[1];if(D==="H"||D==="S"){Q-=P}var I=V+Q,af=Math.floor(Math.max(0,(I-ab)*N)),J=Math.floor(Math.max(0,(I+P-ab)*N));if(af===J){J+=1}switch(D){case"H":break;case"S":case"M":case"=":if(is_overlap([I,I+P],B)){var S=H.slice(X,X+P);if(T>0){W.fillStyle=this.prefs.block_color;W.fillRect(af-T,G+1,J-af,9);W.fillStyle=h;for(var ad=0,A=S.length;ad<A;ad++){if(this.prefs.show_differences&&this.ref_seq){var M=this.ref_seq[I-ab+ad];if(!M||M.toLowerCase()===S[ad].toLowerCase()){continue}}if(I+ad>=ab&&I+ad<=C){var ae=Math.floor(Math.max(0,(I+ad-ab)*N));W.fillText(S[ad],ae,G+9)}}}else{W.fillStyle=this.prefs.block_color;W.fillRect(af,G+4,J-af,f)}}X+=P;Q+=P;break;case"N":W.fillStyle=h;W.fillRect(af-T,G+5,J-af,1);Q+=P;break;case"D":W.fillStyle="red";W.fillRect(af-T,G+4,J-af,3);Q+=P;break;case"P":break;case"I":var aa=af-T;if(is_overlap([I,I+P],B)){var S=H.slice(X,X+P);if(this.prefs.show_insertions){var F=af-(J-af)/2;if((R==="Pack"||this.mode==="Auto")&&H!==undefined&&N>z){W.fillStyle="yellow";W.fillRect(F-T,G-9,J-af,9);ag[ag.length]={type:"triangle",data:[aa,G+4,5]};W.fillStyle=h;switch(seq_tile_overlap){case (OVERLAP_START):S=S.slice(ab-I);break;case (OVERLAP_END):S=S.slice(0,I-C);break;case (CONTAINED_BY):break;case (CONTAINS):S=S.slice(ab-I,I-C);break}for(var ad=0,A=S.length;ad<A;ad++){var ae=Math.floor(Math.max(0,(I+ad-ab)*N));W.fillText(S[ad],ae-(J-af)/2,G)}}else{W.fillStyle="yellow";W.fillRect(F,G+(this.mode!=="Dense"?2:5),J-af,(R!=="Dense"?f:t))}}else{if((R==="Pack"||this.mode==="Auto")&&H!==undefined&&N>z){ag[ag.length]={type:"text",data:[S.length,aa,G+9]}}else{}}}X+=P;break;case"X":X+=P;break}}W.fillStyle="yellow";var ac,E,ah;for(var Y=0;Y<ag.length;Y++){ac=ag[Y];E=ac.type;ah=ac.data;if(E==="text"){W.save();W.font="bold "+W.font;W.fillText(ah[0],ah[1],ah[2]);W.restore()}else{if(E=="triangle"){r(W,ah[0],ah[1],ah[2])}}}},draw_element:function(S,N,F,C,V,A,J,T,Q){var I=F[0],R=F[1],B=F[2],K=F[3],E=Math.floor(Math.max(0,(R-V)*J)),G=Math.ceil(Math.min(Q,Math.max(0,(B-V)*J))),D=(N==="Dense"?0:(0+C))*T,W=this.prefs.block_color,H=this.prefs.label_color,P=0;if((N==="Pack"||this.mode==="Auto")&&J>S.canvas.manager.char_width_px){var P=Math.round(J/2)}S.fillStyle=W;if(F[5] instanceof Array){var O=Math.floor(Math.max(0,(F[4][0]-V)*J)),M=Math.ceil(Math.min(Q,Math.max(0,(F[4][1]-V)*J))),L=Math.floor(Math.max(0,(F[5][0]-V)*J)),z=Math.ceil(Math.min(Q,Math.max(0,(F[5][1]-V)*J)));if(F[4][1]>=V&&F[4][0]<=A&&F[4][2]){this.draw_read(S,N,J,V,A,F[4][0],F[4][2],F[4][3],D)}if(F[5][1]>=V&&F[5][0]<=A&&F[5][2]){this.draw_read(S,N,J,V,A,F[5][0],F[5][2],F[5][3],D)}if(L>M){S.fillStyle=h;q(S,M-P,D+5,L-P,D+5)}}else{S.fillStyle=W;this.draw_read(S,N,J,V,A,R,F[4],F[5],D)}if(N==="Pack"&&R>V){S.fillStyle=this.prefs.label_color;var U=1;if(U===0&&E-S.measureText(K).width<0){S.textAlign="left";S.fillText(K,G+l-P,D+8)}else{S.textAlign="right";S.fillText(K,E-l-P,D+8)}S.fillStyle=W}return[0,0]}});y.Scaler=e;y.SummaryTreePainter=w;y.LinePainter=c;y.LinkedFeaturePainter=s;y.ReadPainter=u;y.VariantPainter=b};(function(d){var c={};var b=function(e){return c[e]};var a=function(f,g){var e={};g(b,e);c[f]=e};a("class",class_module);a("slotting",slotting_module);a("painters",painters_module);a("trackster",trackster_module);for(key in c.trackster){d[key]=c.trackster[key]}})(window);
\ No newline at end of file
+var class_module=function(b,a){var c=function(){var f=arguments[0];for(var e=1;e<arguments.length;e++){var d=arguments[e];for(key in d){f[key]=d[key]}}return f};a.extend=c};var requestAnimationFrame=(function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(b,a){window.setTimeout(b,1000/60)}})();var BEFORE=1001,CONTAINS=1002,OVERLAP_START=1003,OVERLAP_END=1004,CONTAINED_BY=1005,AFTER=1006;var compute_overlap=function(e,b){var g=e[0],f=e[1],d=b[0],c=b[1],a;if(g<d){if(f<d){a=BEFORE}else{if(f<=c){a=OVERLAP_START}else{a=CONTAINS}}}else{if(g>c){a=AFTER}else{if(f<=c){a=CONTAINED_BY}else{a=OVERLAP_END}}}return a};var is_overlap=function(c,b){var a=compute_overlap(c,b);return(a!==BEFORE&&a!==AFTER)};var get_random_color=function(a){if(!a){a="#ffffff"}if(typeof(a)==="string"){a=[a]}for(var j=0;j<a.length;j++){a[j]=parseInt(a[j].slice(1),16)}var m=function(t,s,i){return((t*299)+(s*587)+(i*114))/1000};var e=function(u,t,v,r,i,s){return(Math.max(u,r)-Math.min(u,r))+(Math.max(t,i)-Math.min(t,i))+(Math.max(v,s)-Math.min(v,s))};var g,n,f,k,p,h,q,c,d,b,o,l=false;do{g=Math.random()*16777215;n=g|16711680;f=g|65280;k=g|255;d=m(n,f,k);l=true;for(var j=0;j<a.length;j++){p=a[j];h=p|16711680;q=p|65280;c=p|255;b=m(h,q,c);o=e(n,f,k,h,q,c);if((Math.abs(d-b)<125)||(o<500)){l=false;break}}}while(!l);return"#"+(16777216+g).toString(16).substr(1,6)};var trackster_module=function(f,X){var p=f("class").extend,s=f("slotting"),M=f("painters");var ae=function(af,ag){this.document=af;this.default_font=ag!==undefined?ag:"9px Monaco, Lucida Console, monospace";this.dummy_canvas=this.new_canvas();this.dummy_context=this.dummy_canvas.getContext("2d");this.dummy_context.font=this.default_font;this.char_width_px=this.dummy_context.measureText("A").width;this.patterns={};this.load_pattern("right_strand","/visualization/strand_right.png");this.load_pattern("left_strand","/visualization/strand_left.png");this.load_pattern("right_strand_inv","/visualization/strand_right_inv.png");this.load_pattern("left_strand_inv","/visualization/strand_left_inv.png")};p(ae.prototype,{load_pattern:function(af,aj){var ag=this.patterns,ah=this.dummy_context,ai=new Image();ai.src=image_path+aj;ai.onload=function(){ag[af]=ah.createPattern(ai,"repeat")}},get_pattern:function(af){return this.patterns[af]},new_canvas:function(){var af=this.document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(af)}af.manager=this;return af}});var n={};var l=function(af,ag){n[af.attr("id")]=ag};var m=function(af,ah,aj,ai){aj=".group";var ag={};n[af.attr("id")]=ai;af.bind("drag",{handle:"."+ah,relative:true},function(ar,at){var aq=$(this);var aw=$(this).parent(),an=aw.children(),ap=n[$(this).attr("id")],am,al,au,ak,ao;al=$(this).parents(aj);if(al.length!==0){au=al.position().top;ak=au+al.outerHeight();if(at.offsetY<au){$(this).insertBefore(al);var av=n[al.attr("id")];av.remove_drawable(ap);av.container.add_drawable_before(ap,av);return}else{if(at.offsetY>ak){$(this).insertAfter(al);var av=n[al.attr("id")];av.remove_drawable(ap);av.container.add_drawable(ap);return}}}al=null;for(ao=0;ao<an.length;ao++){am=$(an.get(ao));au=am.position().top;ak=au+am.outerHeight();if(am.is(aj)&&this!==am.get(0)&&at.offsetY>=au&&at.offsetY<=ak){if(at.offsetY-au<ak-at.offsetY){am.find(".content-div").prepend(this)}else{am.find(".content-div").append(this)}if(ap.container){ap.container.remove_drawable(ap)}n[am.attr("id")].add_drawable(ap);return}}for(ao=0;ao<an.length;ao++){if(at.offsetY<$(an.get(ao)).position().top){break}}if(ao===an.length){if(this!==an.get(ao-1)){aw.append(this);n[aw.attr("id")].move_drawable(ap,ao)}}else{if(this!==an.get(ao)){$(this).insertBefore(an.get(ao));n[aw.attr("id")].move_drawable(ap,(at.deltaY>0?ao-1:ao))}}}).bind("dragstart",function(){ag["border-top"]=af.css("border-top");ag["border-bottom"]=af.css("border-bottom");$(this).css({"border-top":"1px solid blue","border-bottom":"1px solid blue"})}).bind("dragend",function(){$(this).css(ag)})};X.moveable=m;var ad=16,H=9,E=20,T=H+2,z=100,J=12000,R=200,C=5,v=10,L=5000,w=100,o="There was an error in indexing this dataset. ",K="A converter for this dataset is not installed. Please check your datatypes_conf.xml file.",F="No data for this chrom/contig.",t="Currently indexing... please wait",x="Tool cannot be rerun: ",a="Loading data...",Y="Ready for display",d=10,u=5,B=5;function Z(ag,af){if(!af){af=0}var ah=Math.pow(10,af);return Math.round(ag*ah)/ah}var c=function(af){this.num_elements=af;this.clear()};p(c.prototype,{get:function(ag){var af=this.key_ary.indexOf(ag);if(af!==-1){if(this.obj_cache[ag].stale){this.key_ary.splice(af,1);delete this.obj_cache[ag]}else{this.move_key_to_end(ag,af)}}return this.obj_cache[ag]},set:function(ag,ah){if(!this.obj_cache[ag]){if(this.key_ary.length>=this.num_elements){var af=this.key_ary.shift();delete this.obj_cache[af]}this.key_ary.push(ag)}this.obj_cache[ag]=ah;return ah},move_key_to_end:function(ag,af){this.key_ary.splice(af,1);this.key_ary.push(ag)},clear:function(){this.obj_cache={};this.key_ary=[]},size:function(){return this.key_ary.length}});var S=function(ag,af,ah){c.call(this,ag);this.track=af;this.subset=(ah!==undefined?ah:true)};p(S.prototype,c.prototype,{load_data:function(ao,aj,am,ag,al){var an=this.track.view.chrom,ai={chrom:an,low:ao,high:aj,mode:am,resolution:ag,dataset_id:this.track.dataset_id,hda_ldda:this.track.hda_ldda};$.extend(ai,al);if(this.track.filters_manager){var ap=[];var af=this.track.filters_manager.filters;for(var ak=0;ak<af.length;ak++){ap[ap.length]=af[ak].name}ai.filter_cols=JSON.stringify(ap)}var ah=this;return $.getJSON(this.track.data_url,ai,function(aq){ah.set_data(ao,aj,am,aq)})},get_data:function(af,aj,ak,ag,ai){var ah=this.get_data_from_cache(af,aj,ak);if(ah){return ah}ah=this.load_data(af,aj,ak,ag,ai);this.set_data(af,aj,ak,ah);return ah},DEEP_DATA_REQ:"deep",BROAD_DATA_REQ:"breadth",get_more_data:function(an,ai,am,ah,al,aj){var ao=this.get_data_from_cache(an,ai,am);if(!ao){console.log("ERROR: no current data for: ",this.track,an,ai,am,ah,al);return}ao.stale=true;var ag=an;if(aj===this.DEEP_DATA_REQ){$.extend(al,{start_val:ao.data.length+1})}else{if(aj===this.BROAD_DATA_REQ){ag=(ao.max_high?ao.max_high:ao.data[ao.data.length-1][2])+1}}var af=this,ak=this.load_data(ag,ai,am,ah,al);new_data_available=$.Deferred();this.set_data(an,ai,am,new_data_available);$.when(ak).then(function(ap){if(ap.data){ap.data=ao.data.concat(ap.data);if(ap.max_low){ap.max_low=ao.max_low}if(ap.message){ap.message=ap.message.replace(/[0-9]+/,ap.data.length)}}af.set_data(an,ai,am,ap);new_data_available.resolve(ap)});return new_data_available},get_data_from_cache:function(af,ag,ah){return this.get(this.gen_key(af,ag,ah))},set_data:function(ag,ah,ai,af){return this.set(this.gen_key(ag,ah,ai),af)},gen_key:function(af,ah,ai){var ag=af+"_"+ah+"_"+ai;return ag},split_key:function(af){return af.split("_")}});var I=function(ag,af,ah){S.call(this,ag,af,ah)};p(I.prototype,S.prototype,c.prototype,{load_data:function(af,ai,aj,ag,ah){if(ag>1){return{data:null}}return S.prototype.load_data.call(this,af,ai,aj,ag,ah)}});var q=function(ai,ag,af,ah,aj){this.name=ai;this.view=ag;this.container=af;this.config=new G({track:this,params:[{key:"name",label:"Name",type:"text",default_value:ai}],saved_values:ah,onchange:function(){this.track.set_name(this.track.config.values.name)}});this.prefs=this.config.values;this.drag_handle_class=aj;this.is_overview=false};p(q.prototype,{init:function(){},request_draw:function(){},_draw:function(){},to_json:function(){},update_track_icons:function(){},set_name:function(af){this.old_name=this.name;this.name=af;this.name_div.text(this.name)},revert_name:function(){this.name=this.old_name;this.name_div.text(this.name)},remove:function(){this.container.remove_drawable(this);this.container_div.fadeOut("slow",function(){$(this).remove();view.update_intro_div();view.has_changes=true})}});var y=function(aj,ai,ag,af,ah,ak){q.call(this,ai,ag,af,ah,ak);this.obj_type=aj;this.drawables=[]};p(y.prototype,q.prototype,{init:function(){for(var af=0;af<this.drawables.length;af++){this.drawables[af].init()}},_draw:function(){for(var af=0;af<this.drawables.length;af++){this.drawables[af]._draw()}},to_json:function(){var ag=[];for(var af=0;af<this.drawables.length;af++){ag.push(this.drawables[af].to_json())}return{name:this.name,prefs:this.prefs,obj_type:this.obj_type,drawables:ag}},add_drawable:function(af){this.drawables.push(af);af.container=this},add_drawable_before:function(ah,af){var ag=this.drawables.indexOf(af);if(ag!=-1){this.drawables.splice(ag,0,ah);return true}return false},remove_drawable:function(ag){var af=this.drawables.indexOf(ag);if(af!=-1){this.drawables.splice(af,1);ag.container=null;return true}return false},move_drawable:function(ag,ah){var af=this.drawables.indexOf(ag);if(af!=-1){this.drawables.splice(af,1);this.drawables.splice(ah,0,ag);return true}return false}});var Q=function(ai,ag,af,ah){y.call(this,"DrawableGroup",ai,ag,af,ah,"group-handle");if(!Q.id_counter){Q.id_counter=0}var aj=Q.id_counter++;this.container_div=$("<div/>").addClass("group").attr("id","group_"+aj).appendTo(this.container.content_div);this.header_div=$("<div/>").addClass("track-header").appendTo(this.container_div);this.header_div.append($("<div/>").addClass(this.drag_handle_class));this.name_div=$("<div/>").addClass("group-name menubutton popup").text(this.name).appendTo(this.header_div);this.content_div=$("<div/>").addClass("content-div").attr("id","group_"+aj+"_content_div").appendTo(this.container_div);l(this.container_div,this);l(this.content_div,this);m(this.container_div,this.drag_handle_class,".group",this);this.update_track_icons()};p(Q.prototype,q.prototype,y.prototype,{update_track_icons:function(){var ag=this;var af={};af["Edit configuration"]=function(){var aj=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},ah=function(){ag.config.update_from_form($(".dialog-box"));hide_modal();$(window).unbind("keypress.check_enter_esc")},ai=function(ak){if((ak.keyCode||ak.which)===27){aj()}else{if((ak.keyCode||ak.which)===13){ah()}}};$(window).bind("keypress.check_enter_esc",ai);show_modal("Configure Group",ag.config.build_form(),{Cancel:aj,OK:ah})};af.Remove=function(){ag.remove()};make_popupmenu(ag.name_div,af)}});var ac=function(af,ai,ah,ag){y.call(this,"View");this.container=af;this.chrom=null;this.vis_id=ah;this.dbkey=ag;this.title=ai;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.init();this.canvas_manager=new ae(af.get(0).ownerDocument);this.reset()};p(ac.prototype,y.prototype,{init:function(){var ah=this.container,af=this;this.top_container=$("<div/>").addClass("top-container").appendTo(ah);this.browser_content_div=$("<div/>").addClass("content").css("position","relative").appendTo(ah);this.bottom_container=$("<div/>").addClass("bottom-container").appendTo(ah);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;l(this.viewport_container,af);this.intro_div=$("<div/>").addClass("intro");var ai=$("<div/>").text("Add Datasets to Visualization").addClass("action-button").appendTo(this.intro_div).click(function(){add_tracks()});this.nav_labeltrack=$("<div/>").addClass("nav-labeltrack").appendTo(this.bottom_container);this.nav_container=$("<div/>").addClass("nav-container").prependTo(this.top_container);this.nav=$("<div/>").addClass("nav").appendTo(this.nav_container);this.overview=$("<div/>").addClass("overview").appendTo(this.bottom_container);this.overview_viewport=$("<div/>").addClass("overview-viewport").appendTo(this.overview);this.overview_close=$("<a/>").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").addClass("no-autocomplete").append("<option value=''>Loading</option>").appendTo(this.nav_controls);var ag=function(aj){if(aj.type==="focusout"||(aj.keyCode||aj.which)===13||(aj.keyCode||aj.which)===27){if((aj.keyCode||aj.which)!==27){af.go_to($(this).val())}$(this).hide();$(this).val("");af.location_span.show();af.chrom_select.show()}};this.nav_input=$("<input/>").addClass("nav-input").hide().bind("keyup focusout",ag).appendTo(this.nav_controls);this.location_span=$("<span/>").addClass("location").appendTo(this.nav_controls);this.location_span.click(function(){af.location_span.hide();af.chrom_select.hide();af.nav_input.val(af.chrom+":"+af.low+"-"+af.high);af.nav_input.css("display","inline-block");af.nav_input.select();af.nav_input.focus()});if(this.vis_id!==undefined){this.hidden_input=$("<input/>").attr("type","hidden").val(this.vis_id).appendTo(this.nav_controls)}this.zo_link=$("<a id='zoom-out' />").click(function(){af.zoom_out();af.request_redraw()}).appendTo(this.nav_controls);this.zi_link=$("<a id='zoom-in' />").click(function(){af.zoom_in();af.request_redraw()}).appendTo(this.nav_controls);this.load_chroms_deferred=this.load_chroms({low:0});this.chrom_select.bind("change",function(){af.change_chrom(af.chrom_select.val())});this.browser_content_div.click(function(aj){$(this).find("input").trigger("blur")});this.browser_content_div.bind("dblclick",function(aj){af.zoom_in(aj.pageX,this.viewport_container)});this.overview_box.bind("dragstart",function(aj,ak){this.current_x=ak.offsetX}).bind("drag",function(aj,al){var am=al.offsetX-this.current_x;this.current_x=al.offsetX;var ak=Math.round(am/af.viewport_container.width()*(af.max_high-af.max_low));af.move_delta(-ak)});this.overview_close.click(function(){af.reset_overview()});this.viewport_container.bind("draginit",function(aj,ak){if(aj.clientX>af.viewport_container.width()-16){return false}}).bind("dragstart",function(aj,ak){ak.original_low=af.low;ak.current_height=aj.clientY;ak.current_x=ak.offsetX}).bind("drag",function(al,an){var aj=$(this);var ao=an.offsetX-an.current_x;var ak=aj.scrollTop()-(al.clientY-an.current_height);aj.scrollTop(ak);an.current_height=al.clientY;an.current_x=an.offsetX;var am=Math.round(ao/af.viewport_container.width()*(af.high-af.low));af.move_delta(am)}).bind("mousewheel",function(al,an,ak,aj){if(ak){var am=Math.round(-ak/af.viewport_container.width()*(af.high-af.low));af.move_delta(am)}});this.top_labeltrack.bind("dragstart",function(aj,ak){return $("<div />").css({height:af.browser_content_div.height()+af.top_labeltrack.height()+af.nav_labeltrack.height()+1,top:"0px",position:"absolute","background-color":"#ccf",opacity:0.5,"z-index":1000}).appendTo($(this))}).bind("drag",function(an,ao){$(ao.proxy).css({left:Math.min(an.pageX,ao.startX),width:Math.abs(an.pageX-ao.startX)});var ak=Math.min(an.pageX,ao.startX)-af.container.offset().left,aj=Math.max(an.pageX,ao.startX)-af.container.offset().left,am=(af.high-af.low),al=af.viewport_container.width();af.update_location(Math.round(ak/al*am)+af.low,Math.round(aj/al*am)+af.low)}).bind("dragend",function(ao,ap){var ak=Math.min(ao.pageX,ap.startX),aj=Math.max(ao.pageX,ap.startX),am=(af.high-af.low),al=af.viewport_container.width(),an=af.low;af.low=Math.round(ak/al*am)+an;af.high=Math.round(aj/al*am)+an;$(ap.proxy).remove();af.request_redraw()});this.add_label_track(new ab(this,{content_div:this.top_labeltrack}));this.add_label_track(new ab(this,{content_div:this.nav_labeltrack}));$(window).bind("resize",function(){af.resize_window()});$(document).bind("redraw",function(){af.redraw()});this.reset();$(window).trigger("resize");this.update_intro_div()},update_intro_div:function(){if(this.num_tracks===0){this.intro_div.appendTo(this.viewport_container)}else{this.intro_div.remove()}},update_location:function(af,ag){this.location_span.text(commatize(af)+" - "+commatize(ag));this.nav_input.val(this.chrom+":"+commatize(af)+"-"+commatize(ag))},load_chroms:function(ah){ah.num=w;$.extend(ah,(this.vis_id!==undefined?{vis_id:this.vis_id}:{dbkey:this.dbkey}));var af=this,ag=$.Deferred();$.ajax({url:chrom_url,data:ah,dataType:"json",success:function(aj){if(aj.chrom_info.length===0){alert("Invalid chromosome: "+ah.chrom);return}if(aj.reference){af.add_label_track(new A(af))}af.chrom_data=aj.chrom_info;var am='<option value="">Select Chrom/Contig</option>';for(var al=0,ai=af.chrom_data.length;al<ai;al++){var ak=af.chrom_data[al].chrom;am+='<option value="'+ak+'">'+ak+"</option>"}if(aj.prev_chroms){am+='<option value="previous">Previous '+w+"</option>"}if(aj.next_chroms){am+='<option value="next">Next '+w+"</option>"}af.chrom_select.html(am);af.chrom_start_index=aj.start_index;ag.resolve(aj)},error:function(){alert("Could not load chroms for this dbkey:",af.dbkey)}});return ag},change_chrom:function(ak,ag,am){if(!ak||ak==="None"){return}var ah=this;if(ak==="previous"){ah.load_chroms({low:this.chrom_start_index-w});return}if(ak==="next"){ah.load_chroms({low:this.chrom_start_index+w});return}var al=$.grep(ah.chrom_data,function(an,ao){return an.chrom===ak})[0];if(al===undefined){ah.load_chroms({chrom:ak},function(){ah.change_chrom(ak,ag,am)});return}else{if(ak!==ah.chrom){ah.chrom=ak;ah.chrom_select.val(ah.chrom);ah.max_high=al.len-1;ah.reset();ah.request_redraw(true);for(var aj=0,af=ah.drawables.length;aj<af;aj++){var ai=ah.drawables[aj];if(ai.init){ai.init()}}}if(ag!==undefined&&am!==undefined){ah.low=Math.max(ag,0);ah.high=Math.min(am,ah.max_high)}ah.reset_overview();ah.request_redraw()}},go_to:function(aj){aj=aj.replace(/ |,/g,"");var an=this,af,ai,ag=aj.split(":"),al=ag[0],am=ag[1];if(am!==undefined){try{var ak=am.split("-");af=parseInt(ak[0],10);ai=parseInt(ak[1],10)}catch(ah){return false}}an.change_chrom(al,af,ai)},move_fraction:function(ah){var af=this;var ag=af.high-af.low;this.move_delta(ah*ag)},move_delta:function(ah){var af=this;var ag=af.high-af.low;if(af.low-ah<af.max_low){af.low=af.max_low;af.high=af.max_low+ag}else{if(af.high-ah>af.max_high){af.high=af.max_high;af.low=af.max_high-ag}else{af.high-=ah;af.low-=ah}}af.request_redraw()},add_drawable:function(af){y.prototype.add_drawable.call(this,af);af.init();this.has_changes=true;this.update_intro_div()},add_label_track:function(af){af.view=this;af.init();this.label_tracks.push(af)},remove_drawable:function(ah,ag){y.prototype.remove_drawable.call(this,ah);if(ag){var af=this;ah.container_div.fadeOut("slow",function(){$(this).remove();af.update_intro_div()});this.has_changes=true}},reset:function(){this.low=this.max_low;this.high=this.max_high;this.viewport_container.find(".yaxislabel").remove()},request_redraw:function(an,af,am,ag){var al=this,aj=(ag?[ag]:al.drawables),ah;var ag;for(var ak=0;ak<aj.length;ak++){ag=aj[ak];ah=-1;for(var ai=0;ai<al.tracks_to_be_redrawn.length;ai++){if(al.tracks_to_be_redrawn[ai][0]===ag){ah=ai;break}}if(ah<0){al.tracks_to_be_redrawn.push([ag,af,am])}else{al.tracks_to_be_redrawn[ak][1]=af;al.tracks_to_be_redrawn[ak][2]=am}}requestAnimationFrame(function(){al._redraw(an)})},_redraw:function(ap){var am=this.low,ai=this.high;if(am<this.max_low){am=this.max_low}if(ai>this.max_high){ai=this.max_high}var ao=this.high-this.low;if(this.high!==0&&ao<this.min_separation){ai=am+this.min_separation}this.low=Math.floor(am);this.high=Math.ceil(ai);this.resolution=Math.pow(C,Math.ceil(Math.log((this.high-this.low)/R)/Math.log(C)));this.zoom_res=Math.pow(v,Math.max(0,Math.ceil(Math.log(this.resolution,v)/Math.log(v))));var af=(this.low/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var al=((this.high-this.low)/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var aq=13;this.overview_box.css({left:af,width:Math.max(aq,al)}).show();if(al<aq){this.overview_box.css("left",af-(aq-al)/2)}if(this.overview_highlight){this.overview_highlight.css({left:af,width:al})}this.update_location(this.low,this.high);if(!ap){var ah,ag,an;for(var aj=0,ak=this.tracks_to_be_redrawn.length;aj<ak;aj++){ah=this.tracks_to_be_redrawn[aj][0];ag=this.tracks_to_be_redrawn[aj][1];an=this.tracks_to_be_redrawn[aj][2];if(ah){ah._draw(ag,an)}}this.tracks_to_be_redrawn=[];for(aj=0,ak=this.label_tracks.length;aj<ak;aj++){this.label_tracks[aj]._draw()}}},zoom_in:function(ag,ah){if(this.max_high===0||this.high-this.low<this.min_separation){return}var ai=this.high-this.low,aj=ai/2+this.low,af=(ai/this.zoom_factor)/2;if(ag){aj=ag/this.viewport_container.width()*(this.high-this.low)+this.low}this.low=Math.round(aj-af);this.high=Math.round(aj+af);this.request_redraw()},zoom_out:function(){if(this.max_high===0){return}var ag=this.high-this.low,ah=ag/2+this.low,af=(ag*this.zoom_factor)/2;this.low=Math.round(ah-af);this.high=Math.round(ah+af);this.request_redraw()},resize_window:function(){this.viewport_container.height(this.container.height()-this.top_container.height()-this.bottom_container.height());this.nav_container.width(this.container.width());this.request_redraw()},set_overview:function(ah){if(this.overview_drawable){if(this.overview_drawable.dataset_id===ah.dataset_id){return}this.overview_viewport.find(".track").remove()}var ag=ah.copy({content_div:this.overview_viewport}),af=this;ag.header_div.hide();ag.is_overview=true;af.overview_drawable=ag;this.overview_drawable.postdraw_actions=function(){af.overview_highlight.show().height(af.overview_drawable.content_div.height());af.overview_viewport.height(af.overview_drawable.content_div.height()+af.overview_box.outerHeight());af.overview_close.show();af.resize_window()};this.overview_drawable.init();af.has_changes=true},reset_overview:function(){$(".tipsy").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 r=function(ah,al){this.track=ah;this.name=al.name;this.params=[];var at=al.params;for(var ai=0;ai<at.length;ai++){var an=at[ai],ag=an.name,ar=an.label,aj=unescape(an.html),au=an.value,ap=an.type;if(ap==="number"){this.params[this.params.length]=new g(ag,ar,aj,au,an.min,an.max)}else{if(ap=="select"){this.params[this.params.length]=new O(ag,ar,aj,au)}else{console.log("WARNING: unrecognized tool parameter type:",ag,ap)}}}this.parent_div=$("<div/>").addClass("dynamic-tool").hide();this.parent_div.bind("drag",function(aw){aw.stopPropagation()}).click(function(aw){aw.stopPropagation()}).bind("dblclick",function(aw){aw.stopPropagation()});var aq=$("<div class='tool-name'>").appendTo(this.parent_div).text(this.name);var ao=this.params;var am=this;$.each(this.params,function(ax,aA){var az=$("<div>").addClass("param-row").appendTo(am.parent_div);var aw=$("<div>").addClass("param-label").text(aA.label).appendTo(az);var ay=$("<div/>").addClass("slider").html(aA.html).appendTo(az);ay.find(":input").val(aA.value);$("<div style='clear: both;'/>").appendTo(az)});this.parent_div.find("input").click(function(){$(this).select()});var av=$("<div>").addClass("param-row").appendTo(this.parent_div);var ak=$("<input type='submit'>").attr("value","Run on complete dataset").appendTo(av);var af=$("<input type='submit'>").attr("value","Run on visible region").css("margin-left","3em").appendTo(av);var am=this;af.click(function(){am.run_on_region()});ak.click(function(){am.run_on_dataset()})};p(r.prototype,{get_param_values_dict:function(){var af={};this.parent_div.find(":input").each(function(){var ag=$(this).attr("name"),ah=$(this).val();af[ag]=JSON.stringify(ah)});return af},get_param_values:function(){var ag=[];var af={};this.parent_div.find(":input").each(function(){var ah=$(this).attr("name"),ai=$(this).val();if(ah){ag[ag.length]=ai}});return ag},run_on_dataset:function(){var af=this;af.run({dataset_id:this.track.original_dataset_id,tool_id:af.name},null,function(ag){show_modal(af.name+" is Running",af.name+" is running on the complete dataset. Tool outputs are in dataset's history.",{Close:hide_modal})})},run_on_region:function(){var ag={dataset_id:this.track.original_dataset_id,chrom:this.track.view.chrom,low:this.track.view.low,high:this.track.view.high,tool_id:this.name},aj=this.track,ah=ag.tool_id+aj.tool_region_and_parameters_str(ag.chrom,ag.low,ag.high),af;if(aj.container===view){var ai=new Q(this.name,this.track.view,this.track.container);aj.container.add_drawable(ai);aj.container.remove_drawable(aj);ai.add_drawable(aj);aj.container_div.appendTo(ai.content_div);af=ai}else{af=aj.container}var ak=new aj.constructor(ah,view,af,"hda");ak.init_for_tool_data();ak.change_mode(aj.mode);af.add_drawable(ak);ak.content_div.text("Starting job.");this.run(ag,ak,function(al){ak.dataset_id=al.dataset_id;ak.content_div.text("Running job.");ak.init()})},run:function(ag,ah,ai){$.extend(ag,this.get_param_values_dict());var af=function(){$.getJSON(rerun_tool_url,ag,function(aj){if(aj==="no converter"){ah.container_div.addClass("error");ah.content_div.text(K)}else{if(aj.error){ah.container_div.addClass("error");ah.content_div.text(x+aj.message)}else{if(aj==="pending"){ah.container_div.addClass("pending");ah.content_div.text("Converting input data so that it can be used quickly with tool.");setTimeout(af,2000)}else{ai(aj)}}}})};af()}});var O=function(ag,af,ah,ai){this.name=ag;this.label=af;this.html=ah;this.value=ai};var g=function(ah,ag,aj,ak,ai,af){O.call(this,ah,ag,aj,ak);this.min=ai;this.max=af};var h=function(ag,af,ah,ai){this.name=ag;this.index=af;this.tool_id=ah;this.tool_exp_name=ai};var V=function(ag,af,ah,ai){h.call(this,ag,af,ah,ai);this.low=-Number.MAX_VALUE;this.high=Number.MAX_VALUE;this.min=Number.MAX_VALUE;this.max=-Number.MAX_VALUE;this.container=null;this.slider=null;this.slider_label=null};p(V.prototype,{applies_to:function(af){if(af.length>this.index){return true}return false},keep:function(af){if(!this.applies_to(af)){return true}var ag=af[this.index];return(isNaN(ag)||(ag>=this.low&&ag<=this.high))},update_attrs:function(ag){var af=false;if(!this.applies_to(ag)){return af}if(ag[this.index]<this.min){this.min=Math.floor(ag[this.index]);af=true}if(ag[this.index]>this.max){this.max=Math.ceil(ag[this.index]);af=true}return af},update_ui_elt:function(){if(this.min!=this.max){this.container.show()}else{this.container.hide()}var ah=function(ak,ai){var aj=ai-ak;return(aj<=2?0.01:1)};var ag=this.slider.slider("option","min"),af=this.slider.slider("option","max");if(this.min<ag||this.max>af){this.slider.slider("option","min",this.min);this.slider.slider("option","max",this.max);this.slider.slider("option","step",ah(this.min,this.max));this.slider.slider("option","values",[this.min,this.max])}}});var aa=function(aq,ay){this.track=aq;this.filters=[];for(var at=0;at<ay.length;at++){var au=ay[at],az=au.name,af=au.type,ah=au.index,ax=au.tool_id,aw=au.tool_exp_name;if(af==="int"||af==="float"){this.filters[at]=new V(az,ah,ax,aw)}else{console.log("ERROR: unsupported filter: ",az,af)}}var ai=function(aA,aB,aC){aA.click(function(){var aD=aB.text();max=parseFloat(aC.slider("option","max")),input_size=(max<=1?4:max<=1000000?max.toString().length:6),multi_value=false;if(aC.slider("option","values")){input_size=2*input_size+1;multi_value=true}aB.text("");$("<input type='text'/>").attr("size",input_size).attr("maxlength",input_size).attr("value",aD).appendTo(aB).focus().select().click(function(aE){aE.stopPropagation()}).blur(function(){$(this).remove();aB.text(aD)}).keyup(function(aI){if(aI.keyCode===27){$(this).trigger("blur")}else{if(aI.keyCode===13){var aG=aC.slider("option","min"),aE=aC.slider("option","max"),aH=function(aJ){return(isNaN(aJ)||aJ>aE||aJ<aG)},aF=$(this).val();if(!multi_value){aF=parseFloat(aF);if(aH(aF)){alert("Parameter value must be in the range ["+aG+"-"+aE+"]");return $(this)}}else{aF=aF.split("-");aF=[parseFloat(aF[0]),parseFloat(aF[1])];if(aH(aF[0])||aH(aF[1])){alert("Parameter value must be in the range ["+aG+"-"+aE+"]");return $(this)}}aC.slider((multi_value?"values":"value"),aF)}}})})};this.parent_div=$("<div/>").addClass("filters").hide();this.parent_div.bind("drag",function(aA){aA.stopPropagation()}).click(function(aA){aA.stopPropagation()}).bind("dblclick",function(aA){aA.stopPropagation()}).bind("keydown",function(aA){aA.stopPropagation()});var av=$("<div/>").addClass("sliders").appendTo(this.parent_div);var an=this;$.each(this.filters,function(aD,aF){aF.container=$("<div/>").addClass("filter-row slider-row").appendTo(av);var aE=$("<div/>").addClass("elt-label").appendTo(aF.container);var aC=$("<span/>").addClass("slider-name").text(aF.name+" ").appendTo(aE);var aB=$("<span/>");var aH=$("<span/>").addClass("slider-value").appendTo(aE).append("[").append(aB).append("]");var aA=$("<div/>").addClass("slider").appendTo(aF.container);aF.control_element=$("<div/>").attr("id",aF.name+"-filter-control").appendTo(aA);var aG=[0,0];aF.control_element.slider({range:true,min:Number.MAX_VALUE,max:-Number.MIN_VALUE,values:[0,0],slide:function(aJ,aK){var aI=aK.values;aB.text(aI[0]+"-"+aI[1]);aF.low=aI[0];aF.high=aI[1];an.track.request_draw(true,true)},change:function(aI,aJ){aF.control_element.slider("option","slide").call(aF.control_element,aI,aJ)}});aF.slider=aF.control_element;aF.slider_label=aB;ai(aH,aB,aF.control_element);$("<div style='clear: both;'/>").appendTo(aF.container)});if(this.filters.length!==0){var ak=$("<div/>").addClass("param-row").appendTo(av);var am=$("<input type='submit'/>").attr("value","Run on complete dataset").appendTo(ak);var ag=this;am.click(function(){ag.run_on_dataset()})}var ap=$("<div/>").addClass("display-controls").appendTo(this.parent_div),ar,al,ao,aj={Transparency:function(aA){an.alpha_filter=aA},Height:function(aA){an.height_filter=aA}};$.each(aj,function(aC,aB){ar=$("<div/>").addClass("filter-row").appendTo(ap),al=$("<span/>").addClass("elt-label").text(aC+":").appendTo(ar),ao=$("<select/>").attr("name",aC+"_dropdown").css("float","right").appendTo(ar);$("<option/>").attr("value",-1).text("== None ==").appendTo(ao);for(var aA=0;aA<an.filters.length;aA++){$("<option/>").attr("value",aA).text(an.filters[aA].name).appendTo(ao)}ao.change(function(){$(this).children("option:selected").each(function(){var aD=parseInt($(this).val());aj[aC]((aD>=0?an.filters[aD]:null));an.track.request_draw(true,true)})});$("<div style='clear: both;'/>").appendTo(ar)});$("<div style='clear: both;'/>").appendTo(this.parent_div)};p(aa.prototype,{reset_filters:function(){for(var af=0;af<this.filters.length;af++){filter=this.filters[af];filter.slider.slider("option","values",[filter.min,filter.max])}this.alpha_filter=null;this.height_filter=null},run_on_dataset:function(){var an=function(ar,ap,aq){if(!(ap in ar)){ar[ap]=aq}return ar[ap]};var ah={},af,ag,ai;for(var aj=0;aj<this.filters.length;aj++){af=this.filters[aj];if(af.tool_id){if(af.min!=af.low){ag=an(ah,af.tool_id,[]);ag[ag.length]=af.tool_exp_name+" >= "+af.low}if(af.max!=af.high){ag=an(ah,af.tool_id,[]);ag[ag.length]=af.tool_exp_name+" <= "+af.high}}}var al=[];for(var ao in ah){al[al.length]=[ao,ah[ao]]}var am=al.length;(function ak(aw,at){var aq=at[0],ar=aq[0],av=aq[1],au="("+av.join(") and (")+")",ap={cond:au,input:aw,target_dataset_id:aw,tool_id:ar},at=at.slice(1);$.getJSON(run_tool_url,ap,function(ax){if(ax.error){show_modal("Filter Dataset","Error running tool "+ar,{Close:hide_modal})}else{if(at.length===0){show_modal("Filtering Dataset","Filter(s) are running on the complete dataset. Outputs are in dataset's history.",{Close:hide_modal})}else{ak(ax.dataset_id,at)}}})})(this.track.dataset_id,al)}});var D=function(af,ag){M.Scaler.call(this,ag);this.filter=af};D.prototype.gen_val=function(af){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(af[this.filter.index])-this.filter.low)/(this.filter.high-this.filter.low))};var G=function(af){this.track=af.track;this.params=af.params;this.values={};this.restore_values((af.saved_values?af.saved_values:{}));this.onchange=af.onchange};p(G.prototype,{restore_values:function(af){var ag=this;$.each(this.params,function(ah,ai){if(af[ai.key]!==undefined){ag.values[ai.key]=af[ai.key]}else{ag.values[ai.key]=ai.default_value}})},build_form:function(){var ag=this;var af=$("<div />");$.each(this.params,function(ak,ai){if(!ai.hidden){var ah="param_"+ak;var am=ag.values[ai.key];var ap=$("<div class='form-row' />").appendTo(af);ap.append($("<label />").attr("for",ah).text(ai.label+":"));if(ai.type==="bool"){ap.append($('<input type="checkbox" />').attr("id",ah).attr("name",ah).attr("checked",am))}else{if(ai.type==="text"){ap.append($('<input type="text"/>').attr("id",ah).val(am).click(function(){$(this).select()}))}else{if(ai.type==="color"){var al=$("<input />").attr("id",ah).attr("name",ah).val(am);var an=$("<div class='tipsy tipsy-north' style='position: absolute;' />").hide();var aj=$("<div style='background-color: black; padding: 10px;'></div>").appendTo(an);var ao=$("<div/>").appendTo(aj).farbtastic({width:100,height:100,callback:al,color:am});$("<div />").append(al).append(an).appendTo(ap).bind("click",function(aq){an.css({left:$(this).position().left+($(al).width()/2)-60,top:$(this).position().top+$(this.height)}).show();$(document).bind("click.color-picker",function(){an.hide();$(document).unbind("click.color-picker")});aq.stopPropagation()})}else{ap.append($("<input />").attr("id",ah).attr("name",ah).val(am))}}}}});return af},update_from_form:function(af){var ah=this;var ag=false;$.each(this.params,function(ai,ak){if(!ak.hidden){var al="param_"+ai;var aj=af.find("#"+al).val();if(ak.type==="float"){aj=parseFloat(aj)}else{if(ak.type==="int"){aj=parseInt(aj)}else{if(ak.type==="bool"){aj=af.find("#"+al).is(":checked")}}}if(aj!==ah.values[ak.key]){ah.values[ak.key]=aj;ag=true}}});if(ag){this.onchange()}}});var b=function(af,ai,ah,ag,aj){this.track=af;this.index=ai;this.low=ai*R*ah;this.high=(ai+1)*R*ah;this.resolution=ah;this.canvas=$("<div class='track-tile'/>").append(ag);this.data=aj;this.stale=false};b.prototype.predisplay_actions=function(){};var k=function(af,ai,ah,ag,aj,ak){b.call(this,af,ai,ah,ag,aj);this.max_val=ak};p(k.prototype,b.prototype);var P=function(af,aj,ai,ah,al,am,ak,ag){b.call(this,af,aj,ai,ah,al);this.mode=am;this.message=ak;this.feature_mapper=ag};p(P.prototype,b.prototype);P.prototype.predisplay_actions=function(){var ag=this,af={};if(ag.mode!=="Pack"){return}$(this.canvas).mousemove(function(ar){var am=$(this).offset(),aq=ar.pageX-am.left,ap=ar.pageY-am.top,aw=ag.feature_mapper.get_feature_data(aq,ap),an=(aw?aw[0]:null);$(this).siblings(".feature-popup").each(function(){if(!an||$(this).attr("id")!==an.toString()){$(this).remove()}});if(aw){var ai=af[an];if(!ai){var an=aw[0],at={name:aw[3],start:aw[1],end:aw[2],strand:aw[4]},al=ag.track.filters_manager.filters,ak;for(var ao=0;ao<al.length;ao++){ak=al[ao];at[ak.name]=aw[ak.index]}var ai=$("<div/>").attr("id",an).addClass("feature-popup"),av,au,ax=$("<table/>").appendTo(ai),ay;for(av in at){au=at[av];ay=$("<tr/>").appendTo(ax);$("<th/>").appendTo(ay).text(av);$("<td/>").attr("align","left").appendTo(ay).text(typeof(au)=="number"?Z(au,2):au)}af[an]=ai}ai.appendTo($(ag.canvas).parent());var aj=aq+parseInt(ag.canvas.css("left"))+7,ah=ap+parseInt(ag.canvas.css("top"))+7;ai.css("left",aj+"px").css("top",ah+"px")}else{if(!ar.isPropagationStopped()){ar.stopPropagation();$(this).siblings().each(function(){$(this).trigger(ar)})}}}).mouseleave(function(){$(this).siblings(".feature-popup").remove()})};var i=function(ai,aq,aj,am,ar,ah,ag){q.call(this,ai,aq,aj,{},"draghandle");this.data_url=(ah?ah:default_data_url);this.data_url_extra_params={};this.data_query_wait=(ag?ag:L);this.dataset_check_url=converted_datasets_state_url;if(!i.id_counter){i.id_counter=0}this.id=i.id_counter++;this.container_div=$("<div />").addClass("track").attr("id","track_"+this.id).css("position","relative");if(am){this.header_div=$("<div class='track-header' />").appendTo(this.container_div);if(this.view.editor){this.drag_div=$("<div/>").addClass(this.drag_handle_class).appendTo(this.header_div)}this.name_div=$("<div/>").addClass("track-name").appendTo(this.header_div).text(this.name).attr("id",this.name.replace(/\s+/g,"-").replace(/[^a-zA-Z0-9\-]/g,"").toLowerCase());this.icons_div=$("<div/>").css("float","left").appendTo(this.header_div).hide();this.settings_icon=$("<a/>").attr("href","javascript:void(0);").attr("title","Edit settings").addClass("icon-button settings-icon").tipsy({gravity:"s"}).appendTo(this.icons_div);this.overview_icon=$("<a/>").attr("href","javascript:void(0);").attr("title","Set as overview").addClass("icon-button overview-icon").tipsy({gravity:"s"}).appendTo(this.icons_div);this.filters_icon=$("<a/>").attr("href","javascript:void(0);").attr("title","Filters").addClass("icon-button filters-icon").tipsy({gravity:"s"}).appendTo(this.icons_div).hide();this.tools_icon=$("<a/>").attr("href","javascript:void(0);").attr("title","Tools").addClass("icon-button tools-icon").tipsy({gravity:"s"}).appendTo(this.icons_div).hide();this.remove_icon=$("<a/>").attr("href","javascript:void(0);").attr("title","Remove").addClass("icon-button remove-icon").tipsy({gravity:"s"}).appendTo(this.icons_div);var ak=this;this.header_div.dblclick(function(at){at.stopPropagation()});this.settings_icon.click(function(){var av=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},at=function(){ak.config.update_from_form($(".dialog-box"));hide_modal();$(window).unbind("keypress.check_enter_esc")},au=function(aw){if((aw.keyCode||aw.which)===27){av()}else{if((aw.keyCode||aw.which)===13){at()}}};$(window).bind("keypress.check_enter_esc",au);show_modal("Configure Track",ak.config.build_form(),{Cancel:av,OK:at})});this.overview_icon.click(function(){ak.view.set_overview(ak)});this.filters_icon.click(function(){ak.filters_div.toggle();ak.filters_manager.reset_filters()});this.tools_icon.click(function(){ak.dynamic_tool_div.toggle();if(ak.dynamic_tool_div.is(":visible")){ak.set_name(ak.name+ak.tool_region_and_parameters_str())}else{ak.revert_name()}$(".tipsy").remove()});this.remove_icon.click(function(){$(".tipsy").remove();ak.remove()});if(ak.display_modes!==undefined){if(ak.mode_div===undefined){ak.mode_div=$("<div class='right-float menubutton popup' />").appendTo(ak.header_div);var al=(ak.config&&ak.config.values.mode?ak.config.values.mode:ak.display_modes[0]);ak.mode=al;ak.mode_div.text(al);var af={};for(var an=0,ap=ak.display_modes.length;an<ap;an++){var ao=ak.display_modes[an];af[ao]=function(at){return function(){ak.change_mode(at)}}(ao)}make_popupmenu(ak.mode_div,af)}else{ak.mode_div.hide()}this.header_div.append($("<div/>").css("clear","both"));this.container_div.hover(function(){ak.icons_div.show()},function(){ak.icons_div.hide()})}}this.content_div=$("<div class='track-content'>").appendTo(this.container_div);this.container.content_div.append(this.container_div)};p(i.prototype,q.prototype,{get_type:function(){if(this instanceof ab){return"LabelTrack"}else{if(this instanceof A){return"ReferenceTrack"}else{if(this instanceof j){return"LineTrack"}else{if(this instanceof W){return"ReadTrack"}else{if(this instanceof U){return"VcfTrack"}else{if(this instanceof e){return"FeatureTrack"}}}}}}return""},init:function(){var af=this;af.enabled=false;af.tile_cache.clear();af.data_manager.clear();af.initial_canvas=undefined;af.content_div.css("height","auto");af.container_div.removeClass("nodata error pending");if(!af.dataset_id){return}$.getJSON(converted_datasets_state_url,{hda_ldda:af.hda_ldda,dataset_id:af.dataset_id,chrom:af.view.chrom},function(ag){if(!ag||ag==="error"||ag.kind==="error"){af.container_div.addClass("error");af.content_div.text(o);if(ag.message){var ah=$(" <a href='javascript:void(0);'></a>").text("View error").click(function(){show_modal("Trackster Error","<pre>"+ag.message+"</pre>",{Close:hide_modal})});af.content_div.append(ah)}}else{if(ag==="no converter"){af.container_div.addClass("error");af.content_div.text(K)}else{if(ag==="no data"||(ag.data!==undefined&&(ag.data===null||ag.data.length===0))){af.container_div.addClass("nodata");af.content_div.text(F)}else{if(ag==="pending"){af.container_div.addClass("pending");af.content_div.text(t);setTimeout(function(){af.init()},af.data_query_wait)}else{if(ag.status==="data"){if(ag.valid_chroms){af.valid_chroms=ag.valid_chroms;af.update_track_icons()}af.content_div.text(Y);if(af.view.chrom){af.content_div.text("");af.content_div.css("height",af.height_px+"px");af.enabled=true;$.when(af.predraw_init()).done(function(){af.container_div.removeClass("nodata error pending");af.request_draw()})}}}}}}});this.update_track_icons()},predraw_init:function(){}});var N=function(aj,ah,ag,am,ai,al,ak){i.call(this,aj,ah,ag,am,ai);var af=this,ah=af.view;m(af.container_div,af.drag_handle_class,".group",af);this.filters_manager=new aa(this,(al!==undefined?al:{}));this.filters_available=false;this.filters_visible=false;this.tool=(ak!==undefined&&obj_length(ak)>0?new r(this,ak):undefined);if(this.header_div){if(this.filters_manager){this.filters_div=this.filters_manager.parent_div;this.header_div.after(this.filters_div)}if(this.tool){this.dynamic_tool_div=this.tool.parent_div;this.header_div.after(this.dynamic_tool_div)}}};p(N.prototype,q.prototype,i.prototype,{copy:function(af){return new this.constructor(this.name,this.view,af,this.hda_ldda,this.dataset_id,this.prefs,this.filters,this.tool)},to_json: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,}},change_mode:function(ag){var af=this;af.mode_div.text(ag);af.mode=ag;af.config.values.mode=ag;af.tile_cache.clear();af.request_draw();return af},update_track_icons:function(){var af=this;if(af.filters_available>0){af.filters_icon.show()}else{af.filters_icon.hide()}if(af.tool){af.tools_icon.show()}else{af.tools_icon.hide()}},_gen_tile_cache_key:function(ag,ah,af){return ag+"_"+ah+"_"+af},request_draw:function(ag,af){this.view.request_redraw(false,ag,af,this)},_draw:function(ah,ap){if(!this.enabled){return}if(!(this instanceof A)&&(!this.dataset_id)){return}var ao=this.view.low,al=this.view.high,am=al-ao,ai=this.view.container.width(),at=ai/am,ak=this.view.resolution,ar=$("<div style='position: relative;'></div>");if(this.is_overview){ao=this.view.max_low;al=this.view.max_high;ak=Math.pow(C,Math.ceil(Math.log((view.max_high-view.max_low)/R)/Math.log(C)));at=ai/(view.max_high-view.max_low)}if(!ap){this.content_div.children().remove()}this.content_div.append(ar);this.max_height=0;var ag=Math.floor(ao/ak/R);var an=true;var aq=[];var af=0;while((ag*R*ak)<al){tile=this.draw_helper(ah,ai,ag,ak,ar,at);if(tile){aq.push(tile)}else{an=false}ag+=1;af++}var aj=this;if(an){aj.postdraw_actions(aq,ai,at,ap)}},postdraw_actions:function(aj,ak,al,af){var ah=this;var ai=false;for(var ag=0;ag<aj.length;ag++){if(aj[ag].message){ai=true;break}}if(ai){for(var ag=0;ag<aj.length;ag++){tile=aj[ag];if(!tile.message){tile.canvas.css("padding-top",E)}}}},draw_helper:function(ag,ah,ai,al,ar,aw,at,am){var aj=this,aq=this._gen_tile_cache_key(ah,aw,ai),an=ai*R*al,av=an+R*al;var ao=(ag?undefined:aj.tile_cache.get(aq));if(ao){aj.show_tile(ao,ar,aw);return ao}var ap=function(ax){return("isResolved" in ax)};var ak=true;var af=aj.data_manager.get_data(an,av,aj.mode,al,aj.data_url_extra_params);if(ap(af)){ak=false}var au;if(view.reference_track&&aw>view.canvas_manager.char_width_px){au=view.reference_track.data_manager.get_data(an,av,aj.mode,al,view.reference_track.data_url_extra_params);if(ap(au)){ak=false}}if(ak){p(af,am);var ao=aj.draw_tile(af,aj.mode,al,ai,aw,au);if(ao!==undefined){aj.tile_cache.set(aq,ao);aj.show_tile(ao,ar,aw)}return ao}$.when(af,au).then(function(){view.request_redraw(false,false,false,aj)});return null},show_tile:function(al,an,ao){var ah=this,ag=al.canvas,ak=ag;if(al.message){var ap=$("<div/>"),am=$("<div/>").addClass("tile-message").text(al.message).css({height:E-1,width:al.canvas.width}).appendTo(ap),aj=$("<a href='javascript:void(0);'/>").addClass("icon more-down").appendTo(am),af=$("<a href='javascript:void(0);'/>").addClass("icon more-across").appendTo(am);ap.append(ag);ak=ap;aj.click(function(){al.stale=true;ah.data_manager.get_more_data(al.low,al.high,ah.mode,al.resolution,{},ah.data_manager.DEEP_DATA_REQ);ah.request_draw()}).dblclick(function(aq){aq.stopPropagation()});af.click(function(){al.stale=true;ah.data_manager.get_more_data(al.low,al.high,ah.mode,al.resolution,{},ah.data_manager.BROAD_DATA_REQ);ah.request_draw()}).dblclick(function(aq){aq.stopPropagation()})}al.predisplay_actions();var ai=(al.low-(this.is_overview?this.view.max_low:this.view.low))*ao;if(this.left_offset){ai-=this.left_offset}ak.css({position:"absolute",top:0,left:ai,height:""});an.append(ak);ah.max_height=Math.max(ah.max_height,ak.height());ah.content_div.css("height",ah.max_height+"px");an.children().css("height",ah.max_height+"px")},_get_tile_bounds:function(af,ag){var ai=af*R*ag,aj=R*ag,ah=(ai+aj<=this.view.max_high?ai+aj:this.view.max_high);return[ai,ah]},tool_region_and_parameters_str:function(ah,af,ai){var ag=this,aj=(ah!==undefined&&af!==undefined&&ai!==undefined?ah+":"+af+"-"+ai:"all");return" - region=["+aj+"], parameters=["+ag.tool.get_param_values().join(", ")+"]"},init_for_tool_data:function(){this.data_url=raw_data_url;this.data_query_wait=1000;this.dataset_check_url=dataset_state_url;this.predraw_init=function(){var ag=this;var af=function(){if(ag.data_manager.size()===0){setTimeout(af,300)}else{ag.data_url=default_data_url;ag.data_query_wait=L;ag.dataset_state_url=converted_datasets_state_url;$.getJSON(ag.dataset_state_url,{dataset_id:ag.dataset_id,hda_ldda:ag.hda_ldda},function(ah){})}};af()}}});var ab=function(ag,af){i.call(this,"label",ag,af,false,{});this.container_div.addClass("label-track")};p(ab.prototype,i.prototype,{init:function(){this.enabled=true},_draw:function(){var ah=this.view,ai=ah.high-ah.low,al=Math.floor(Math.pow(10,Math.floor(Math.log(ai)/Math.log(10)))),af=Math.floor(ah.low/al)*al,aj=this.view.container.width(),ag=$("<div style='position: relative; height: 1.3em;'></div>");while(af<ah.high){var ak=(af-ah.low)/ai*aj;ag.append($("<div class='label'>"+commatize(af)+"</div>").css({position:"absolute",left:ak-1}));af+=al}this.content_div.children(":first").remove();this.content_div.append(ag)}});var A=function(af){N.call(this,"reference",af,{content_div:af.top_labeltrack},false,{});af.reference_track=this;this.left_offset=200;this.height_px=12;this.container_div.addClass("reference-track");this.content_div.css("background","none");this.content_div.css("min-height","0px");this.content_div.css("border","none");this.data_url=reference_url;this.data_url_extra_params={dbkey:af.dbkey};this.data_manager=new I(B,this,false);this.tile_cache=new c(u)};p(A.prototype,q.prototype,N.prototype,{init:function(){this.enabled=true},draw_tile:function(ap,al,ak,ag,aq){var aj=this,ah=R*ak;if(aq>this.view.canvas_manager.char_width_px){if(ap.data===null){aj.content_div.css("height","0px");return}var ai=this.view.canvas_manager.new_canvas();var ao=ai.getContext("2d");ai.width=Math.ceil(ah*aq+aj.left_offset);ai.height=aj.height_px;ao.font=ao.canvas.manager.default_font;ao.textAlign="center";ap=ap.data;for(var am=0,an=ap.length;am<an;am++){var af=Math.round(am*aq);ao.fillText(ap[am],af+aj.left_offset,10)}return new b(aj,ag,ak,ai,ap)}this.content_div.css("height","0px")}});var j=function(ak,ai,ah,al,af,aj){var ag=this;this.display_modes=["Histogram","Line","Filled","Intensity"];this.mode="Histogram";N.call(this,ak,ai,ah,true,aj);this.min_height_px=16;this.max_height_px=400;this.height_px=80;this.hda_ldda=al;this.dataset_id=af;this.original_dataset_id=af;this.data_manager=new S(B,this);this.tile_cache=new c(u);this.left_offset=0;this.config=new G({track:this,params:[{key:"name",label:"Name",type:"text",default_value:ak},{key:"color",label:"Color",type:"color",default_value: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:this.height_px,hidden:true}],saved_values:aj,onchange:function(){ag.set_name(ag.prefs.name);ag.vertical_range=ag.prefs.max_value-ag.prefs.min_value;$("#linetrack_"+ag.dataset_id+"_minval").text(ag.prefs.min_value);$("#linetrack_"+ag.dataset_id+"_maxval").text(ag.prefs.max_value);ag.tile_cache.clear();ag.request_draw()}});this.prefs=this.config.values;this.height_px=this.config.values.height;this.vertical_range=this.config.values.max_value-this.config.values.min_value;this.add_resize_handle()};p(j.prototype,q.prototype,N.prototype,{add_resize_handle:function(){var af=this;var ai=false;var ah=false;var ag=$("<div class='track-resize'>");$(af.container_div).hover(function(){ai=true;ag.show()},function(){ai=false;if(!ah){ag.hide()}});ag.hide().bind("dragstart",function(aj,ak){ah=true;ak.original_height=$(af.content_div).height()}).bind("drag",function(ak,al){var aj=Math.min(Math.max(al.original_height+al.deltaY,af.min_height_px),af.max_height_px);$(af.content_div).css("height",aj);af.height_px=aj;af.request_draw(true)}).bind("dragend",function(aj,ak){af.tile_cache.clear();ah=false;if(!ai){ag.hide()}af.config.values.height=af.height_px}).appendTo(af.container_div)},predraw_init:function(){var af=this;af.vertical_range=undefined;return $.getJSON(af.data_url,{stats:true,chrom:af.view.chrom,low:null,high:null,hda_ldda:af.hda_ldda,dataset_id:af.dataset_id},function(ag){af.container_div.addClass("line-track");var ai=ag.data;if(isNaN(parseFloat(af.prefs.min_value))||isNaN(parseFloat(af.prefs.max_value))){af.prefs.min_value=ai.min;af.prefs.max_value=ai.max;$("#track_"+af.dataset_id+"_minval").val(af.prefs.min_value);$("#track_"+af.dataset_id+"_maxval").val(af.prefs.max_value)}af.vertical_range=af.prefs.max_value-af.prefs.min_value;af.total_frequency=ai.total_frequency;af.container_div.find(".yaxislabel").remove();var aj=$("<div />").addClass("yaxislabel").attr("id","linetrack_"+af.dataset_id+"_minval").text(Z(af.prefs.min_value,3));var ah=$("<div />").addClass("yaxislabel").attr("id","linetrack_"+af.dataset_id+"_maxval").text(Z(af.prefs.max_value,3));ah.css({position:"absolute",top:"24px",left:"10px"});ah.prependTo(af.container_div);aj.css({position:"absolute",bottom:"2px",left:"10px"});aj.prependTo(af.container_div)})},draw_tile:function(ar,ak,aj,ah,aq){if(this.vertical_range===undefined){return}var af=this._get_tile_bounds(ah,aj),al=af[0],ap=af[1],ag=Math.ceil((ap-al)*aq),an=this.height_px;var ai=this.view.canvas_manager.new_canvas();ai.width=ag,ai.height=an;var ao=ai.getContext("2d");var am=new M.LinePainter(ar.data,al,ap,this.prefs,ak);am.draw(ao,ag,an);return new b(this.track,ah,aj,ai,ar.data)}});var e=function(af,al,ag,ak,an,am,ai,aj){var ah=this;this.display_modes=["Auto","Histogram","Dense","Squish","Pack"];N.call(this,af,al,ag,true,am,ai,aj);this.config=new G({track:this,params:[{key:"name",label:"Name",type:"text",default_value:af},{key:"block_color",label:"Block color",type:"color",default_value:get_random_color()},{key:"label_color",label:"Label color",type:"color",default_value:"black"},{key:"show_counts",label:"Show summary counts",type:"bool",default_value:true},{key:"mode",type:"string",default_value:this.mode,hidden:true},],saved_values:am,onchange:function(){ah.set_name(ah.prefs.name);ah.tile_cache.clear();ah.request_draw()}});this.prefs=this.config.values;this.height_px=0;this.container_div.addClass("feature-track");this.hda_ldda=ak;this.dataset_id=an;this.original_dataset_id=an;this.show_labels_scale=0.001;this.showing_details=false;this.summary_draw_height=30;this.inc_slots={};this.start_end_dct={};this.tile_cache=new c(d);this.data_manager=new S(20,this);this.left_offset=200;this.painter=M.LinkedFeaturePainter};p(e.prototype,q.prototype,N.prototype,{postdraw_actions:function(av,af,aw,au){N.prototype.postdraw_actions.call(this,av,au);var ai=this;if(au){var ak=ai.content_div.children();var al=false;for(var aj=ak.length-1,ap=0;aj>=ap;aj--){var ah=$(ak[aj]);if(al){ah.remove()}else{if(ah.children().length!==0){al=true}}}}if(ai.mode=="Histogram"){var ao=-1;for(var aj=0;aj<av.length;aj++){var at=av[aj].max_val;if(at>ao){ao=at}}for(var aj=0;aj<av.length;aj++){var ar=av[aj];if(ar.max_val!==ao){ar.canvas.remove();ai.draw_helper(true,af,ar.index,ar.resolution,ar.canvas.parent(),aw,[],{max:ao})}}}if(ai.filters_manager){var ag=ai.filters_manager.filters;for(var an=0;an<ag.length;an++){ag[an].update_ui_elt()}var am=false,aq;for(var aj=0;aj<av.length;aj++){if(av[aj].data.length){aq=av[aj].data[0];for(var an=0;an<ag.length;an++){if(ag[an].applies_to(aq)){am=true;break}}}}if(ai.filters_available!==am){ai.filters_available=am;if(!ai.filters_available){ai.filters_div.hide()}ai.update_track_icons()}}},update_auto_mode:function(af){if(this.mode=="Auto"){if(af=="no_detail"){af="feature spans"}else{if(af=="summary_tree"){af="coverage histogram"}}this.mode_div.text("Auto ("+af+")")}},incremental_slots:function(aj,ag,ai){var ah=this.view.canvas_manager.dummy_context,af=this.inc_slots[aj];if(!af||(af.mode!==ai)){af=new (s.FeatureSlotter)(aj,ai==="Pack",z,function(ak){return ah.measureText(ak)});af.mode=ai;this.inc_slots[aj]=af}return af.slot_features(ag)},get_summary_tree_data:function(aj,am,ah,av){if(av>ah-am){av=ah-am}var aq=Math.floor((ah-am)/av),au=[],ai=0;var ak=0,al=0,ap,at=0,an=[],ar,ao;var ag=function(ay,ax,az,aw){ay[0]=ax+az*aw;ay[1]=ax+(az+1)*aw};while(at<av&&ak!==aj.length){var af=false;for(;at<av&&!af;at++){ag(an,am,at,aq);for(al=ak;al<aj.length;al++){ap=aj[al].slice(1,3);if(is_overlap(ap,an)){af=true;break}}if(af){break}}data_start_index=al;au[au.length]=ar=[an[0],0];for(;al<aj.length;al++){ap=aj[al].slice(1,3);if(is_overlap(ap,an)){ar[1]++}else{break}}if(ar[1]>ai){ai=ar[1]}at++}return{max:ai,delta:aq,data:au}},draw_tile:function(au,ax,aB,aF,ap,ai){var ay=this,ak=ay._get_tile_bounds(aF,aB),aI=ak[0],ag=ak[1],aw=ag-aI,az=Math.ceil(aw*ap),aO=25,aj=this.left_offset,av,al;if(ax==="Auto"){if(au.dataset_type==="summary_tree"){ax=au.dataset_type}else{if(au.extra_info==="no_detail"||ay.is_overview){ax="no_detail"}else{var aN=au.data;if(this.view.high-this.view.low>J){ax="Squish"}else{ax="Pack"}}}this.update_auto_mode(ax)}if(ax==="summary_tree"||ax==="Histogram"){al=this.summary_draw_height;this.container_div.find(".yaxislabel").remove();var af=$("<div />").addClass("yaxislabel");af.text(au.max);af.css({position:"absolute",top:"24px",left:"10px",color:this.prefs.label_color});af.prependTo(this.container_div);var ah=this.view.canvas_manager.new_canvas();ah.width=az+aj;ah.height=al+T;if(au.dataset_type!="summary_tree"){var aq=this.get_summary_tree_data(au.data,aI,ag,200);if(au.max){aq.max=au.max}au=aq}var aK=new M.SummaryTreePainter(au,aI,ag,this.prefs);var aA=ah.getContext("2d");aA.translate(aj,T);aK.draw(aA,az,al);return new k(ay,aF,aB,ah,au.data,au.max)}var av,an=1;if(ax==="no_detail"||ax==="Squish"||ax==="Pack"){an=this.incremental_slots(ap,au.data,ax);av=this.inc_slots[ap].slots}var ao=[];if(au.data){var ar=this.filters_manager.filters;for(var aC=0,aE=au.data.length;aC<aE;aC++){var am=au.data[aC];var aD=false;var at;for(var aH=0,aM=ar.length;aH<aM;aH++){at=ar[aH];at.update_attrs(am);if(!at.keep(am)){aD=true;break}}if(!aD){ao.push(am)}}}var aL=(this.filters_manager.alpha_filter?new D(this.filters_manager.alpha_filter):null);var aJ=(this.filters_manager.height_filter?new D(this.filters_manager.height_filter):null);var aK=new (this.painter)(ao,aI,ag,this.prefs,ax,aL,aJ,ai);var al=Math.max(ad,aK.get_required_height(an));var ah=this.view.canvas_manager.new_canvas();var aG=null;ah.width=az+aj;ah.height=al;var aA=ah.getContext("2d");aA.fillStyle=this.prefs.block_color;aA.font=aA.canvas.manager.default_font;aA.textAlign="right";this.container_div.find(".yaxislabel").remove();if(au.data){aA.translate(aj,0);aG=aK.draw(aA,az,al,av);aG.translation=-aj}return new P(ay,aF,aB,ah,au.data,ax,au.message,aG)}});var U=function(ak,ah,ag,am,af,aj,al,ai){e.call(this,ak,ah,ag,am,af,aj,al,ai);this.config=new G({track:this,params:[{key:"name",label:"Name",type:"text",default_value:ak},{key:"block_color",label:"Block color",type:"color",default_value: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:aj,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=M.ReadPainter};p(U.prototype,q.prototype,N.prototype,e.prototype);var W=function(aj,ah,ag,al,af,ai,ak){e.call(this,aj,ah,ag,al,af,ai,ak);this.config=new G({track:this,params:[{key:"name",label:"Name",type:"text",default_value:aj},{key:"block_color",label:"Block color",type:"color",default_value: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_differences",label:"Show differences only",type:"bool",default_value:true},{key:"show_counts",label:"Show summary counts",type:"bool",default_value:true},{key:"mode",type:"string",default_value:this.mode,hidden:true},],saved_values:ai,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=M.ReadPainter;this.update_track_icons()};p(W.prototype,q.prototype,N.prototype,e.prototype);X.View=ac;X.DrawableGroup=Q;X.LineTrack=j;X.FeatureTrack=e;X.ReadTrack=W;X.VcfTrack=U};var slotting_module=function(c,b){var e=c("class").extend;var d=2,a=5;b.FeatureSlotter=function(i,h,f,g){this.slots={};this.start_end_dct={};this.w_scale=i;this.include_label=h;this.max_rows=f;this.measureText=g};e(b.FeatureSlotter.prototype,{slot_features:function(m){var p=this.w_scale,s=this.slots,h=this.start_end_dct,y=[],A=[],n=0,z=this.max_rows;for(var w=0,x=m.length;w<x;w++){var l=m[w],o=l[0];if(s[o]!==undefined){n=Math.max(n,s[o]);A.push(s[o])}else{y.push(w)}}var q=function(F,G){for(var E=0;E<=z;E++){var C=false,H=h[E];if(H!==undefined){for(var B=0,D=H.length;B<D;B++){var i=H[B];if(G>i[0]&&F<i[1]){C=true;break}}}if(!C){return E}}return -1};for(var w=0,x=y.length;w<x;w++){var l=m[y[w]],o=l[0],u=l[1],f=l[2],r=l[3],g=Math.floor(u*p),k=Math.ceil(f*p),v=this.measureText(r).width,j;if(r!==undefined&&this.include_label){v+=(d+a);if(g-v>=0){g-=v;j="left"}else{k+=v;j="right"}}var t=q(g,k);if(t>=0){if(h[t]===undefined){h[t]=[]}h[t].push([g,k]);s[o]=t;n=Math.max(n,t)}else{}}return n+1}})};var painters_module=function(i,w){var t=i("class").extend;var o=function(H,z,F,y,E,C){if(C===undefined){C=4}var B=y-z;var A=E-F;var D=Math.floor(Math.sqrt(B*B+A*A)/C);var I=B/D;var G=A/D;var x;for(x=0;x<D;x++,z+=I,F+=G){if(x%2!==0){continue}H.fillRect(z,F,C,1)}};var p=function(A,z,x,D){var C=z-D/2,B=z+D/2,E=x-Math.sqrt(D*3/2);A.beginPath();A.moveTo(C,E);A.lineTo(B,E);A.lineTo(z,x);A.lineTo(C,E);A.strokeStyle=this.fillStyle;A.fill();A.stroke();A.closePath()};var d=function(x){this.default_val=(x?x:1)};d.prototype.gen_val=function(x){return this.default_val};var l=function(z,B,x,y,A){this.data=z;this.view_start=B;this.view_end=x;this.prefs=t({},this.default_prefs,y);this.mode=A};l.prototype.default_prefs={};var u=function(z,B,x,y,A){l.call(this,z,B,x,y,A)};u.prototype.default_prefs={show_counts:false};u.prototype.draw=function(M,z,L){var E=this.view_start,O=this.view_end-this.view_start,N=z/O;var J=this.data.data,I=this.data.delta,G=this.data.max,B=L;delta_x_px=Math.ceil(I*N);M.save();for(var C=0,D=J.length;C<D;C++){var H=Math.floor((J[C][0]-E)*N);var F=J[C][1];if(!F){continue}var K=F/G*L;if(F!==0&&K<1){K=1}M.fillStyle=this.prefs.block_color;M.fillRect(H,B-K,delta_x_px,K);var A=4;if(this.prefs.show_counts&&(M.measureText(F).width+A)<delta_x_px){M.fillStyle=this.prefs.label_color;M.textAlign="center";M.fillText(F,H+(delta_x_px/2),10)}}M.restore()};var b=function(x,B,D,E,z){l.call(this,x,B,D,E,z);if(this.prefs.min_value===undefined){var F=Infinity;for(var y=0,A=this.data.length;y<A;y++){F=Math.min(F,this.data[y][1])}this.prefs.min_value=F}if(this.prefs.max_value===undefined){var C=-Infinity;for(var y=0,A=this.data.length;y<A;y++){C=Math.max(C,this.data[y][1])}this.prefs.max_value=C}};b.prototype.default_prefs={min_value:undefined,max_value:undefined,mode:"Histogram",color:"#000",overflow_color:"#F66"};b.prototype.draw=function(M,L,J){var E=false,G=this.prefs.min_value,C=this.prefs.max_value,I=C-G,x=J,z=this.view_start,K=this.view_end-this.view_start,A=L/K,H=this.mode,S=this.data;M.save();var T=Math.round(J+G/I*J);if(H!=="Intensity"){M.fillStyle="#aaa";M.fillRect(0,T,L,1)}M.beginPath();var Q,D,B;if(S.length>1){B=Math.ceil((S[1][0]-S[0][0])*A)}else{B=10}for(var N=0,O=S.length;N<O;N++){M.fillStyle=this.prefs.color;Q=Math.round((S[N][0]-z)*A);D=S[N][1];var P=false,F=false;if(D===null){if(E&&H==="Filled"){M.lineTo(Q,x)}E=false;continue}if(D<G){F=true;D=G}else{if(D>C){P=true;D=C}}if(H==="Histogram"){D=Math.round(D/I*x);M.fillRect(Q,T,B,-D)}else{if(H==="Intensity"){D=255-Math.floor((D-G)/I*255);M.fillStyle="rgb("+D+","+D+","+D+")";M.fillRect(Q,0,B,x)}else{D=Math.round(x-(D-G)/I*x);if(E){M.lineTo(Q,D)}else{E=true;if(H==="Filled"){M.moveTo(Q,x);M.lineTo(Q,D)}else{M.moveTo(Q,D)}}}}M.fillStyle=this.prefs.overflow_color;if(P||F){var R;if(H==="Histogram"||H==="Intensity"){R=B}else{Q-=2;R=4}if(P){M.fillRect(Q,0,R,3)}if(F){M.fillRect(Q,x-3,R,3)}}M.fillStyle=this.prefs.color}if(H==="Filled"){if(E){M.lineTo(Q,T);M.lineTo(0,T)}M.fill()}else{M.stroke()}M.restore()};var m=function(x){this.feature_positions={};this.slot_height=x;this.translation=0};m.prototype.map_feature_data=function(y,A,x,z){if(!this.feature_positions[A]){this.feature_positions[A]=[]}this.feature_positions[A].push({data:y,x_start:x,x_end:z})};m.prototype.get_feature_data=function(z,D){var C=Math.floor(D/this.slot_height),B;if(!this.feature_positions[C]){return null}z+=this.translation;for(var A=0;A<this.feature_positions[C].length;A++){B=this.feature_positions[C][A];if(z>=B.x_start&&z<=B.x_end){return B.data}}};var n=function(z,C,x,y,B,D,A){l.call(this,z,C,x,y,B);this.alpha_scaler=(D?D:new d());this.height_scaler=(A?A:new d())};n.prototype.default_prefs={block_color:"#FFF",connector_color:"#FFF"};t(n.prototype,{get_required_height:function(y){var x=y_scale=this.get_row_height(),z=this.mode;if(z==="no_detail"||z==="Squish"||z==="Pack"){x=y*y_scale}return x+Math.max(Math.round(y_scale/2),5)},draw:function(J,H,F,E){var P=this.data,C=this.view_start,L=this.view_end;J.save();J.fillStyle=this.prefs.block_color;J.textAlign="right";var G=this.view_end-this.view_start,D=H/G,K=this.get_row_height(),O=new m(K),A;for(var M=0,N=P.length;M<N;M++){var z=P[M],B=z[0],I=z[1],x=z[2],y=(E&&E[B]!==undefined?E[B]:null);if((I<L&&x>C)&&(this.mode=="Dense"||y!==null)){A=this.draw_element(J,this.mode,z,y,C,L,D,K,H);O.map_feature_data(z,y,A[0],A[1])}}J.restore();return O},draw_element:function(D,z,F,B,A,C,E,y,x){console.log("WARNING: Unimplemented function.");return[0,0]}});var c=10,h=3,k=5,v=10,f=1,r=3,e=3,a=9,j=2,g="#ccc";var q=function(z,C,x,y,B,D,A){n.call(this,z,C,x,y,B,D,A)};t(q.prototype,n.prototype,{get_row_height:function(){var y=this.mode,x;if(y==="Dense"){x=c}else{if(y==="no_detail"){x=h}else{if(y==="Squish"){x=k}else{x=v}}}return x},draw_element:function(L,C,U,G,N,af,aj,al,x){var R=U[0],ah=U[1],Z=U[2],P=U[3],aa=Math.floor(Math.max(0,(ah-N)*aj)),M=Math.ceil(Math.min(x,Math.max(0,(Z-N)*aj))),Y=aa,ak=M,X=(C==="Dense"?0:(0+G))*al,K,ad,Q=null,an=null,A=this.prefs.block_color,ac=this.prefs.label_color;L.globalAlpha=this.alpha_scaler.gen_val(U);if(C==="Dense"){G=1}if(C==="no_detail"){L.fillStyle=A;L.fillRect(aa,X+5,M-aa,f)}else{var J=U[4],W=U[5],ab=U[6],B=U[7];if(W&&ab){Q=Math.floor(Math.max(0,(W-N)*aj));an=Math.ceil(Math.min(x,Math.max(0,(ab-N)*aj)))}var ai,S;if(C==="Squish"||C==="Dense"){ai=1;S=e}else{ai=5;S=a}if(!B){if(U.strand){if(U.strand==="+"){L.fillStyle=L.canvas.manager.get_pattern("right_strand_inv")}else{if(U.strand==="-"){L.fillStyle=L.canvas.manager.get_pattern("left_strand_inv")}}}else{L.fillStyle=A}L.fillRect(aa,X,M-aa,S)}else{var I,T;if(C==="Squish"||C==="Dense"){L.fillStyle=g;I=X+Math.floor(e/2)+1;T=1}else{if(J){var I=X;var T=S;if(J==="+"){L.fillStyle=L.canvas.manager.get_pattern("right_strand")}else{if(J==="-"){L.fillStyle=L.canvas.manager.get_pattern("left_strand")}}}else{L.fillStyle=g;I+=(e/2)+1;T=1}}L.fillRect(aa,I,M-aa,T);var D;for(var ag=0,z=B.length;ag<z;ag++){var E=B[ag],y=Math.floor(Math.max(0,(E[0]-N)*aj)),V=Math.ceil(Math.min(x,Math.max((E[1]-N)*aj)));if(y>V){continue}L.fillStyle=A;L.fillRect(y,X+(S-ai)/2+1,V-y,ai);if(Q!==undefined&&ab>W&&!(y>an||V<Q)){var ae=Math.max(y,Q),H=Math.min(V,an);L.fillRect(ae,X+1,H-ae,S);if(B.length==1&&C=="Pack"){if(J==="+"){L.fillStyle=L.canvas.manager.get_pattern("right_strand_inv")}else{if(J==="-"){L.fillStyle=L.canvas.manager.get_pattern("left_strand_inv")}}if(ae+14<H){ae+=2;H-=2}L.fillRect(ae,X+1,H-ae,S)}}}if(C==="Pack"){L.globalAlpha=1;L.fillStyle="white";var F=this.height_scaler.gen_val(U),O=Math.ceil(S*F),am=Math.round((S-O)/2);if(F!==1){L.fillRect(aa,I+1,M-aa,am);L.fillRect(aa,I+S-am+1,M-aa,am)}}}L.globalAlpha=1;if(C==="Pack"&&ah>N){L.fillStyle=ac;if(N===0&&aa-L.measureText(P).width<0){L.textAlign="left";L.fillText(P,M+j,X+8);ak+=L.measureText(P).width+j}else{L.textAlign="right";L.fillText(P,aa-j,X+8);Y-=L.measureText(P).width+j}}}L.globalAlpha=1;return[Y,ak]}});var s=function(A,D,x,z,C,E,B,y){n.call(this,A,D,x,z,C,E,B);this.ref_seq=(y?y.data:null)};s.prototype.default_prefs=t({},n.prototype.default_prefs,{show_insertions:false});t(s.prototype,n.prototype,{get_row_height:function(){var x,y=this.mode;if(y==="Dense"){x=c}else{if(y==="Squish"){x=k}else{x=v;if(this.prefs.show_insertions){x*=2}}}return x},draw_read:function(U,P,L,Z,A,T,I,F,E){U.textAlign="center";var S=this,z=[Z,A],O=0,V=0,R=0,x=U.canvas.manager.char_width_px;var ae=[];if((P==="Pack"||this.mode==="Auto")&&F!==undefined&&L>x){R=Math.round(L/2)}if(!I){I=[[0,F.length]]}for(var M=0,X=I.length;M<X;M++){var J=I[M],B="MIDNSHP=X"[J[0]],N=J[1];if(B==="H"||B==="S"){O-=N}var G=T+O,ad=Math.floor(Math.max(0,(G-Z)*L)),H=Math.floor(Math.max(0,(G+N-Z)*L));if(ad===H){H+=1}switch(B){case"H":break;case"S":case"M":case"=":if(is_overlap([G,G+N],z)){var Q=F.slice(V,V+N);if(R>0){U.fillStyle=this.prefs.block_color;U.fillRect(ad-R,E+1,H-ad,9);U.fillStyle=g;for(var ab=0,y=Q.length;ab<y;ab++){if(this.prefs.show_differences&&this.ref_seq){var K=this.ref_seq[G-Z+ab];if(!K||K.toLowerCase()===Q[ab].toLowerCase()){continue}}if(G+ab>=Z&&G+ab<=A){var ac=Math.floor(Math.max(0,(G+ab-Z)*L));U.fillText(Q[ab],ac,E+9)}}}else{U.fillStyle=this.prefs.block_color;U.fillRect(ad,E+4,H-ad,e)}}V+=N;O+=N;break;case"N":U.fillStyle=g;U.fillRect(ad-R,E+5,H-ad,1);O+=N;break;case"D":U.fillStyle="red";U.fillRect(ad-R,E+4,H-ad,3);O+=N;break;case"P":break;case"I":var Y=ad-R;if(is_overlap([G,G+N],z)){var Q=F.slice(V,V+N);if(this.prefs.show_insertions){var D=ad-(H-ad)/2;if((P==="Pack"||this.mode==="Auto")&&F!==undefined&&L>x){U.fillStyle="yellow";U.fillRect(D-R,E-9,H-ad,9);ae[ae.length]={type:"triangle",data:[Y,E+4,5]};U.fillStyle=g;switch(compute_overlap([G,G+N],z)){case (OVERLAP_START):Q=Q.slice(Z-G);break;case (OVERLAP_END):Q=Q.slice(0,G-A);break;case (CONTAINED_BY):break;case (CONTAINS):Q=Q.slice(Z-G,G-A);break}for(var ab=0,y=Q.length;ab<y;ab++){var ac=Math.floor(Math.max(0,(G+ab-Z)*L));U.fillText(Q[ab],ac-(H-ad)/2,E)}}else{U.fillStyle="yellow";U.fillRect(D,E+(this.mode!=="Dense"?2:5),H-ad,(P!=="Dense"?e:r))}}else{if((P==="Pack"||this.mode==="Auto")&&F!==undefined&&L>x){ae.push({type:"text",data:[Q.length,Y,E+9]})}else{}}}V+=N;break;case"X":V+=N;break}}U.fillStyle="yellow";var aa,C,af;for(var W=0;W<ae.length;W++){aa=ae[W];C=aa.type;af=aa.data;if(C==="text"){U.save();U.font="bold "+U.font;U.fillText(af[0],af[1],af[2]);U.restore()}else{if(C=="triangle"){p(U,af[0],af[1],af[2])}}}},draw_element:function(Q,L,D,A,T,y,H,R,O){var G=D[0],P=D[1],z=D[2],I=D[3],C=Math.floor(Math.max(0,(P-T)*H)),E=Math.ceil(Math.min(O,Math.max(0,(z-T)*H))),B=(L==="Dense"?0:(0+A))*R,U=this.prefs.block_color,F=this.prefs.label_color,N=0;if((L==="Pack"||this.mode==="Auto")&&H>Q.canvas.manager.char_width_px){var N=Math.round(H/2)}Q.fillStyle=U;if(D[5] instanceof Array){var M=Math.floor(Math.max(0,(D[4][0]-T)*H)),K=Math.ceil(Math.min(O,Math.max(0,(D[4][1]-T)*H))),J=Math.floor(Math.max(0,(D[5][0]-T)*H)),x=Math.ceil(Math.min(O,Math.max(0,(D[5][1]-T)*H)));if(D[4][1]>=T&&D[4][0]<=y&&D[4][2]){this.draw_read(Q,L,H,T,y,D[4][0],D[4][2],D[4][3],B)}if(D[5][1]>=T&&D[5][0]<=y&&D[5][2]){this.draw_read(Q,L,H,T,y,D[5][0],D[5][2],D[5][3],B)}if(J>K){Q.fillStyle=g;o(Q,K-N,B+5,J-N,B+5)}}else{Q.fillStyle=U;this.draw_read(Q,L,H,T,y,P,D[4],D[5],B)}if(L==="Pack"&&P>T&&I!=="."){Q.fillStyle=this.prefs.label_color;var S=1;if(S===0&&C-Q.measureText(I).width<0){Q.textAlign="left";Q.fillText(I,E+j-N,B+8)}else{Q.textAlign="right";Q.fillText(I,C-j-N,B+8)}Q.fillStyle=U}return[0,0]}});w.Scaler=d;w.SummaryTreePainter=u;w.LinePainter=b;w.LinkedFeaturePainter=q;w.ReadPainter=s};(function(d){var c={};var b=function(e){return c[e]};var a=function(f,g){var e={};g(b,e);c[f]=e};a("class",class_module);a("slotting",slotting_module);a("painters",painters_module);a("trackster",trackster_module);for(key in c.trackster){d[key]=c.trackster[key]}})(window);
\ No newline at end of file
diff -r 42c8a6cfaa5b76204e978eedfd17647b05531b13 -r f05722e66a8a42e75f01a29b723ed50525e77e55 static/scripts/packed/trackster_ui.js
--- a/static/scripts/packed/trackster_ui.js
+++ b/static/scripts/packed/trackster_ui.js
@@ -1,1 +1,1 @@
-var add_bookmark=function(b,a){var g=$("#bookmarks-container"),d=$("<div/>").addClass("bookmark").appendTo(g),c=$("<div/>").addClass("delete-icon-container").appendTo(d).click(function(){d.slideUp("fast");d.remove();view.has_changes=true;return false}),e=$("<a href=''/>").addClass("icon-button delete").appendTo(c),f=$("<div/>").addClass("position").appendTo(d),h=$("<a href=''/>").text(b).appendTo(f).click(function(){view.go_to(b);return false});annotation_div=get_editable_text_elt(a,true).addClass("annotation").appendTo(d);view.has_changes=true;return d};var addable_objects={LineTrack:LineTrack,FeatureTrack:FeatureTrack,ReadTrack:ReadTrack,DrawableGroup:DrawableGroup};var track_from_dict=function(c,b){var a=new addable_objects[c.track_type](c.name,view,b,c.hda_ldda,c.dataset_id,c.prefs,c.filters,c.tool);if(c.mode){a.change_mode(c.mode)}return a};var drawable_collection_from_dict=function(f,a){var e=new addable_objects[f.obj_type](f.name,view,a,f.prefs,view.viewport_container,view);for(var d=0;d<f.drawables.length;d++){var b=f.drawables[d],c;if(b.track_type){c=track_from_dict(b,e)}else{c=drawable_collection_from_dict(b)}e.add_drawable(c);e.content_div.append(c.container_div)}return e};var drawable_from_dict=function(b,a){return(b.track_type?track_from_dict(b,a):drawable_collection_from_dict(b,a))};var create_visualization=function(b,e,g,c,a,d,f){view=new View(b,e,g,c);view.editor=true;$.when(view.load_chroms_deferred).then(function(){if(a){var k=a.chrom,p=a.start,h=a.end,m=a.overview;if(k&&(p!==undefined)&&h){view.change_chrom(k,p,h)}}if(d){var o;for(var j=0;j<d.length;j++){o=d[j];view.add_drawable(drawable_from_dict(o,view))}}var n;for(var j=0;j<view.drawables.length;j++){if(view.drawables[j].name===m){view.set_overview(view.drawables[j]);break}}if(f){var l;for(var j=0;j<f.length;j++){l=f[j];add_bookmark(l.position,l.annotation)}}view.has_changes=false});return view};var init_keyboard_nav=function(a){$(document).keydown(function(b){if($(b.srcElement).is(":input")){return}switch(b.which){case 37:a.move_fraction(0.25);break;case 38:var c=Math.round(a.viewport_container.height()/15);a.viewport_container.scrollTo("-="+c+"px");break;case 39:a.move_fraction(-0.25);break;case 40:var c=Math.round(a.viewport_container.height()/15);a.viewport_container.scrollTo("+="+c+"px");break}})};
\ No newline at end of file
+var add_bookmark=function(b,a){var g=$("#bookmarks-container"),d=$("<div/>").addClass("bookmark").appendTo(g),c=$("<div/>").addClass("delete-icon-container").appendTo(d).click(function(){d.slideUp("fast");d.remove();view.has_changes=true;return false}),e=$("<a href=''/>").addClass("icon-button delete").appendTo(c),f=$("<div/>").addClass("position").appendTo(d),h=$("<a href=''/>").text(b).appendTo(f).click(function(){view.go_to(b);return false});annotation_div=get_editable_text_elt(a,true).addClass("annotation").appendTo(d);view.has_changes=true;return d};var addable_objects={LineTrack:LineTrack,FeatureTrack:FeatureTrack,VcfTrack:VcfTrack,ReadTrack:ReadTrack,DrawableGroup:DrawableGroup};var track_from_dict=function(c,b){var a=new addable_objects[c.track_type](c.name,view,b,c.hda_ldda,c.dataset_id,c.prefs,c.filters,c.tool);if(c.mode){a.change_mode(c.mode)}return a};var drawable_collection_from_dict=function(f,a){var e=new addable_objects[f.obj_type](f.name,view,a,f.prefs,view.viewport_container,view);for(var d=0;d<f.drawables.length;d++){var b=f.drawables[d],c;if(b.track_type){c=track_from_dict(b,e)}else{c=drawable_collection_from_dict(b)}e.add_drawable(c);e.content_div.append(c.container_div)}return e};var drawable_from_dict=function(b,a){return(b.track_type?track_from_dict(b,a):drawable_collection_from_dict(b,a))};var create_visualization=function(b,e,g,c,a,d,f){view=new View(b,e,g,c);view.editor=true;$.when(view.load_chroms_deferred).then(function(){if(a){var k=a.chrom,p=a.start,h=a.end,m=a.overview;if(k&&(p!==undefined)&&h){view.change_chrom(k,p,h)}}if(d){var o;for(var j=0;j<d.length;j++){o=d[j];view.add_drawable(drawable_from_dict(o,view))}}var n;for(var j=0;j<view.drawables.length;j++){if(view.drawables[j].name===m){view.set_overview(view.drawables[j]);break}}if(f){var l;for(var j=0;j<f.length;j++){l=f[j];add_bookmark(l.position,l.annotation)}}view.has_changes=false});return view};var init_keyboard_nav=function(a){$(document).keydown(function(b){if($(b.srcElement).is(":input")){return}switch(b.which){case 37:a.move_fraction(0.25);break;case 38:var c=Math.round(a.viewport_container.height()/15);a.viewport_container.scrollTo("-="+c+"px");break;case 39:a.move_fraction(-0.25);break;case 40:var c=Math.round(a.viewport_container.height()/15);a.viewport_container.scrollTo("+="+c+"px");break}})};
\ No newline at end of file
diff -r 42c8a6cfaa5b76204e978eedfd17647b05531b13 -r f05722e66a8a42e75f01a29b723ed50525e77e55 static/scripts/trackster.js
--- a/static/scripts/trackster.js
+++ b/static/scripts/trackster.js
@@ -654,6 +654,8 @@
* associated with a view and container. They optionally have a drag handle class.
*/
var Drawable = function(name, view, container, prefs, drag_handle_class) {
+ if (!Drawable.id_counter) { Drawable.id_counter = 0; }
+ this.id = Drawable.id_counter++;
this.name = name;
this.view = view;
this.container = container;
@@ -677,7 +679,7 @@
request_draw: function() {},
_draw: function() {},
to_json: function() {},
- update_track_icons: function() {},
+ update_icons: function() {},
/**
* Set drawable name.
*/
@@ -804,13 +806,11 @@
DrawableCollection.call(this, "DrawableGroup", name, view, container, prefs, "group-handle");
// HTML elements.
- if (!DrawableGroup.id_counter) { DrawableGroup.id_counter = 0; }
- var group_id = DrawableGroup.id_counter++
- this.container_div = $("<div/>").addClass("group").attr("id", "group_" + group_id).appendTo(this.container.content_div);
+ this.container_div = $("<div/>").addClass("group").attr("id", "group_" + this.id).appendTo(this.container.content_div);
this.header_div = $("<div/>").addClass("track-header").appendTo(this.container_div);
this.header_div.append($("<div/>").addClass(this.drag_handle_class));
this.name_div = $("<div/>").addClass("group-name menubutton popup").text(this.name).appendTo(this.header_div);
- this.content_div = $("<div/>").addClass("content-div").attr("id", "group_" + group_id + "_content_div").appendTo(this.container_div);
+ this.content_div = $("<div/>").addClass("content-div").attr("id", "group_" + this.id + "_content_div").appendTo(this.container_div);
// Set up containers/moving for group: register both container_div and content div as container
// because both are used as containers (container div to recognize container, content_div to
@@ -819,14 +819,14 @@
is_container(this.content_div, this);
moveable(this.container_div, this.drag_handle_class, ".group", this);
- this.update_track_icons();
+ this.update_icons();
};
extend(DrawableGroup.prototype, Drawable.prototype, DrawableCollection.prototype, {
/**
* Make popup menu for group.
*/
- update_track_icons: function() {
+ update_icons: function() {
var group = this;
var group_dropdown = {};
@@ -941,7 +941,7 @@
}
};
this.nav_input = $("<input/>").addClass("nav-input").hide().bind("keyup focusout", submit_nav).appendTo(this.nav_controls);
- this.location_span = $("<span/>").addClass("location").appendTo(this.nav_controls);
+ this.location_span = $("<span/>").addClass("location").attr('original-title', 'Click to change location').tipsy( { gravity: 'n' } ).appendTo(this.nav_controls);
this.location_span.click(function() {
view.location_span.hide();
view.chrom_select.hide();
@@ -953,8 +953,11 @@
if (this.vis_id !== undefined) {
this.hidden_input = $("<input/>").attr("type", "hidden").val(this.vis_id).appendTo(this.nav_controls);
}
- this.zo_link = $("<a id='zoom-out' />").click(function() { view.zoom_out(); view.request_redraw(); }).appendTo(this.nav_controls);
- this.zi_link = $("<a id='zoom-in' />").click(function() { view.zoom_in(); view.request_redraw(); }).appendTo(this.nav_controls);
+
+ this.zo_link = $("<a/>").attr("id", "zoom-out").attr("title", "Zoom out").tipsy( {gravity: 'n'} )
+ .click(function() { view.zoom_out(); view.request_redraw(); }).appendTo(this.nav_controls);
+ this.zi_link = $("<a/>").attr("id", "zoom-in").attr("title", "Zoom in").tipsy( {gravity: 'n'} )
+ .click(function() { view.zoom_in(); view.request_redraw(); }).appendTo(this.nav_controls);
// Get initial set of chroms.
this.load_chroms_deferred = this.load_chroms({low: 0});
@@ -1069,11 +1072,10 @@
this.reset();
$(window).trigger("resize");
- this.update_intro_div();
},
/** Add or remove intro div depending on view state. */
update_intro_div: function() {
- if (this.num_tracks === 0) {
+ if (this.drawables.length === 0) {
this.intro_div.appendTo(this.viewport_container);
}
else {
@@ -1577,8 +1579,7 @@
// Set name of track to include tool name, parameters, and region used.
track_name = url_params.tool_id +
current_track.tool_region_and_parameters_str(url_params.chrom, url_params.low, url_params.high),
- container,
- new_track;
+ container;
// If track not in a group, create a group for it and add new track to group. If track
// already in group, add track to group.
@@ -1595,11 +1596,12 @@
else {
container = current_track.container;
}
- if (current_track instanceof FeatureTrack) {
- new_track = new ToolDataFeatureTrack(track_name, view, container, "hda");
- new_track.change_mode(current_track.mode);
- container.add_drawable(new_track);
- }
+
+ // Create and init new track.
+ var new_track = new current_track.constructor(track_name, view, container, "hda");
+ new_track.init_for_tool_data();
+ new_track.change_mode(current_track.mode);
+ container.add_drawable(new_track);
new_track.content_div.text("Starting job.");
// Run tool.
@@ -2316,7 +2318,6 @@
* ----> ReferenceTrack
* ----> FeatureTrack
* -------> ReadTrack
- * -------> ToolDataFeatureTrack
* -------> VcfTrack
*/
var Track = function(name, view, container, show_header, prefs, data_url, data_query_wait) {
@@ -2330,9 +2331,6 @@
this.data_url_extra_params = {}
this.data_query_wait = (data_query_wait ? data_query_wait : DEFAULT_DATA_QUERY_WAIT);
this.dataset_check_url = converted_datasets_state_url;
-
- if (!Track.id_counter) { Track.id_counter = 0; }
- this.id = Track.id_counter++;
//
// Create HTML element structure for track.
@@ -2476,9 +2474,6 @@
else if (this instanceof ReadTrack) {
return "ReadTrack";
}
- else if (this instanceof ToolDataFeatureTrack) {
- return "ToolDataFeatureTrack";
- }
else if (this instanceof VcfTrack) {
return "VcfTrack";
}
@@ -2538,7 +2533,7 @@
} else if (result['status'] === "data") {
if (result['valid_chroms']) {
track.valid_chroms = result['valid_chroms'];
- track.update_track_icons();
+ track.update_icons();
}
track.content_div.text(DATA_OK);
if (track.view.chrom) {
@@ -2554,7 +2549,7 @@
}
});
- this.update_track_icons();
+ this.update_icons();
},
/**
* Additional initialization required before drawing track for the first time.
@@ -2562,8 +2557,8 @@
predraw_init: function() {}
});
-var TiledTrack = function(name, view, container, show_header, prefs, filters_list, tool_dict, data_url, data_query_wait) {
- Track.call(this, name, view, container, show_header, prefs, data_url, data_query_wait);
+var TiledTrack = function(name, view, container, show_header, prefs, filters_list, tool_dict) {
+ Track.call(this, name, view, container, show_header, prefs);
var track = this,
view = track.view;
@@ -2632,7 +2627,7 @@
/**
* Update track's buttons.
*/
- update_track_icons: function() {
+ update_icons: function() {
var track = this;
//
@@ -2910,6 +2905,39 @@
region = (chrom !== undefined && low !== undefined && high !== undefined ?
chrom + ":" + low + "-" + high : "all");
return " - region=[" + region + "], parameters=[" + track.tool.get_param_values().join(", ") + "]";
+ },
+ /**
+ * Set up track to receive tool data.
+ */
+ init_for_tool_data: function() {
+ // Set up track to fetch initial data from raw data URL when the dataset--not the converted datasets--
+ // is ready.
+ this.data_url = raw_data_url;
+ this.data_query_wait = 1000;
+ this.dataset_check_url = dataset_state_url;
+
+ /**
+ * Predraw init sets up postdraw init.
+ */
+ this.predraw_init = function() {
+ // Postdraw init: once data has been fetched, reset data url, wait time and start indexing.
+ var track = this;
+ var post_init = function() {
+ if (track.data_manager.size() === 0) {
+ // Track still drawing initial data, so do nothing.
+ setTimeout(post_init, 300);
+ }
+ else {
+ // Track drawing done: reset dataset check, data URL, wait time and get dataset state to start
+ // indexing.
+ track.data_url = default_data_url;
+ track.data_query_wait = DEFAULT_DATA_QUERY_WAIT;
+ track.dataset_state_url = converted_datasets_state_url;
+ $.getJSON(track.dataset_state_url, {dataset_id : track.dataset_id, hda_ldda: track.hda_ldda}, function(track_data) {});
+ }
+ };
+ post_init();
+ }
}
});
@@ -3261,7 +3289,7 @@
if (!track.filters_available) {