galaxy-commits
Threads by month
- ----- 2025 -----
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- 15302 discussions

20 Nov '10
# HG changeset patch -- Bitbucket.org
# Project galaxy-dist
# URL http://bitbucket.org/galaxy/galaxy-dist/overview
# User rc
# Date 1288101623 14400
# Node ID 677bcc65f74f5a460277f089d0cdebf170f02831
# Parent 9e27a8ad881dc4451add6d518468a73dbc9028bc
sample_tracking:
- added web api methods to update requests, samples using restful api
- removed the old ad-doc web api
- modified the data transfer code to use this api
- code cleanup
--- a/scripts/galaxy_messaging/server/galaxyweb_interface.py
+++ /dev/null
@@ -1,122 +0,0 @@
-import ConfigParser
-import sys, os
-import array
-import time
-import optparse,array
-import shutil, traceback
-import urllib,urllib2, cookielib
-
-assert sys.version_info[:2] >= ( 2, 4 )
-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
-
-import pkg_resources
-pkg_resources.require( "pycrypto" )
-
-from Crypto.Cipher import Blowfish
-from Crypto.Util.randpool import RandomPool
-from Crypto.Util import number
-
-
-class GalaxyWebInterface(object):
- def __init__(self, server_host, server_port, datatx_email, datatx_password, config_id_secret):
- self.server_host = server_host
- self.server_port = server_port
- self.datatx_email = datatx_email
- self.datatx_password = datatx_password
- self.config_id_secret = config_id_secret
- # create url
- self.base_url = "http://%s:%s" % (self.server_host, self.server_port)
- # login
- url = "%s/user/login?email=%s&password=%s&login_button=Login" % (self.base_url, self.datatx_email, self.datatx_password)
- cj = cookielib.CookieJar()
- self.opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj))
- #print url
- f = self.opener.open(url)
- if f.read().find("ogged in as "+self.datatx_email) == -1:
- # if the user doesnt exist, create the user
- url = "%s/user/create?email=%s&username=%s&password=%s&confirm=%s&create_user_button=Submit" % ( self.base_url, self.datatx_email, self.datatx_email, self.datatx_password, self.datatx_password )
- f = self.opener.open(url)
- if f.read().find("ogged in as "+self.datatx_email) == -1:
- raise Exception("The "+self.datatx_email+" user could not login to Galaxy")
-
- def add_to_library(self, server_dir, library_id, folder_id, dbkey=''):
- '''
- This method adds the dataset file to the target data library & folder
- by opening the corresponding url in Galaxy server running.
- '''
- params = urllib.urlencode(dict( cntrller='library_admin',
- tool_id='upload1',
- tool_state='None',
- library_id=self.encode_id(library_id),
- folder_id=self.encode_id(folder_id),
- upload_option='upload_directory',
- file_type='auto',
- server_dir=os.path.basename(server_dir),
- dbkey=dbkey,
- show_dataset_id='True',
- runtool_btn='Upload to library'))
- url = self.base_url+"/library_common/upload_library_dataset"
- print url
- print params
- try:
- f = self.opener.open(url, params)
- if f.read().find("Data Library") == -1:
- raise Exception("Dataset could not be uploaded to the data library. URL: %s, PARAMS=%s" % (url, params))
- except:
- return 'ERROR', url, params
-
- def import_to_history(self, ldda_id, library_id, folder_id):
- params = urllib.urlencode(dict( cntrller='library_admin',
- show_deleted='False',
- library_id=self.encode_id(library_id),
- folder_id=self.encode_id(folder_id),
- ldda_ids=self.encode_id(ldda_id),
- do_action='import_to_history',
- use_panels='False'))
- #url = "http://lion.bx.psu.edu:8080/library_common/act_on_multiple_datasets?library…"
- url = self.base_url+"/library_common/act_on_multiple_datasets"
- f = self.opener.open(url, params)
- x = f.read()
- if x.find("1 dataset(s) have been imported into your history.") == -1:
- raise Exception("Dataset could not be imported into history")
-
- def run_workflow(self, workflow_id, hid, workflow_step):
- input = str(workflow_step)+'|input'
- params = urllib.urlencode({'id':self.encode_id(workflow_id),
- 'run_workflow': 'Run workflow',
- input: hid})
- url = self.base_url+"/workflow/run"
- f = self.opener.open(url, params)
-
- def logout(self):
- # finally logout
- f = self.opener.open(self.base_url+'/user/logout')
-
- def encode_id(self, obj_id ):
- id_cipher = Blowfish.new( self.config_id_secret )
- # Convert to string
- s = str( obj_id )
- # Pad to a multiple of 8 with leading "!"
- s = ( "!" * ( 8 - len(s) % 8 ) ) + s
- # Encrypt
- return id_cipher.encrypt( s ).encode( 'hex' )
-
- def update_request_state(self, request_id):
- params = urllib.urlencode(dict( cntrller='requests_admin',
- request_id=request_id))
- url = self.base_url + "/requests_common/update_request_state"
- f = self.opener.open(url, params)
- print url
- print params
- x = f.read()
-
-
-
-
-
-
--- /dev/null
+++ b/scripts/api/requests_update_state.py
@@ -0,0 +1,16 @@
+#!/usr/bin/env python
+
+
+import os, sys, traceback
+sys.path.insert( 0, os.path.dirname( __file__ ) )
+from common import update
+
+try:
+ data = {}
+ data[ 'update_type' ] = 'request_state'
+except IndexError:
+ print 'usage: %s key url' % os.path.basename( sys.argv[0] )
+ sys.exit( 1 )
+
+update( sys.argv[1], sys.argv[2], data, return_formatted=True )
+
--- a/lib/galaxy/web/buildapp.py
+++ b/lib/galaxy/web/buildapp.py
@@ -106,6 +106,7 @@ def app_factory( global_conf, **kwargs )
add_api_controllers( webapp, app )
webapp.api_mapper.resource( 'content', 'contents', path_prefix='/api/libraries/:library_id', parent_resources=dict( member_name='library', collection_name='libraries' ) )
webapp.api_mapper.resource( 'library', 'libraries', path_prefix='/api' )
+ webapp.api_mapper.resource( 'request', 'requests', path_prefix='/api' )
webapp.finalize_config()
# Wrap the webapp in some useful middleware
if kwargs.get( 'middleware', True ):
--- /dev/null
+++ b/scripts/api/sample_dataset_update_status.py
@@ -0,0 +1,22 @@
+#!/usr/bin/env python
+
+
+import os, sys, traceback
+sys.path.insert( 0, os.path.dirname( __file__ ) )
+from common import display
+from common import submit
+from common import update
+try:
+ data = {}
+ data[ 'update_type' ] = 'sample_dataset_transfer_status'
+ data[ 'sample_dataset_ids' ] = sys.argv[3].split(',')
+ data[ 'new_status' ] = sys.argv[4]
+except IndexError:
+ print 'usage: %s key url sample_dataset_ids new_state [error msg]' % os.path.basename( sys.argv[0] )
+ sys.exit( 1 )
+try:
+ data[ 'error_msg' ] = sys.argv[5]
+except IndexError:
+ data[ 'error_msg' ] = ''
+print data
+update( sys.argv[1], sys.argv[2], data, return_formatted=True )
--- a/scripts/galaxy_messaging/server/amqp_consumer.py
+++ b/scripts/galaxy_messaging/server/amqp_consumer.py
@@ -14,24 +14,22 @@ import sys, os
import optparse
import xml.dom.minidom
import subprocess
+import urllib2
from galaxydb_interface import GalaxyDbInterface
-new_path = [ os.path.join( os.getcwd(), "scripts/galaxy_messaging/server" ) ]
-new_path.extend( sys.path[1:] ) # remove scripts/ from the path
-sys.path = new_path
-from galaxyweb_interface import GalaxyWebInterface
+api_path = [ os.path.join( os.getcwd(), "scripts/api" ) ]
+sys.path.extend( api_path )
+import common as api
assert sys.version_info[:2] >= ( 2, 4 )
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
+from galaxy.web.api.requests import RequestsController
import pkg_resources
pkg_resources.require( "amqplib" )
-
from amqplib import client_0_8 as amqp
import logging
@@ -43,7 +41,12 @@ formatter = logging.Formatter("%(asctime
fh.setFormatter(formatter)
log.addHandler(fh)
+# data transfer script
+data_transfer_script = os.path.join( os.getcwd(),
+ "scripts/galaxy_messaging/server/data_transfer.py" )
+
global dbconnstr
+global webconfig
global config
def get_value(dom, tag_name):
@@ -71,84 +74,98 @@ def get_value_index(dom, tag_name, index
rc = rc + node.data
return rc
-def recv_callback(msg):
- global config
- global webconfig
+def start_data_transfer(message):
+ # fork a new process to transfer datasets
+ cmd = '%s "%s" "%s" "%s"' % ( "python",
+ data_transfer_script,
+ message.body,
+ sys.argv[1] ) # Galaxy config file name
+ pid = subprocess.Popen(cmd, shell=True).pid
+ log.debug('Started process (%i): %s' % (pid, str(cmd)))
+
+def update_sample_state(message):
+ dom = xml.dom.minidom.parseString(message.body)
+ barcode = get_value(dom, 'barcode')
+ state = get_value(dom, 'state')
+ log.debug('Barcode: ' + barcode)
+ log.debug('State: ' + state)
+ # update the sample state in Galaxy db
+ galaxydb = GalaxyDbInterface(dbconnstr)
+ sample_id = galaxydb.get_sample_id(field_name='bar_code', value=barcode)
+ if sample_id == -1:
+ log.debug('Invalid barcode.')
+ return
+ galaxydb.change_state(sample_id, state)
+ # after updating the sample state, update request status
+ request_id = galaxydb.get_request_id(sample_id)
+ update_request( request_id )
+
+def update_request( request_id ):
+ http_server_section = webconfig.get( "universe_wsgi_config", "http_server_section" )
+ encoded_request_id = api.encode_id( config.get( "app:main", "id_secret" ), request_id )
+ api_key = webconfig.get( "data_transfer_user_login_info", "api_key" )
+ data = dict( update_type=RequestsController.update_types.REQUEST )
+ url = "http://%s:%s/api/requests/%s" % ( config.get(http_server_section, "host"),
+ config.get(http_server_section, "port"),
+ encoded_request_id )
+ log.debug( 'Updating request %i' % request_id )
+ try:
+ api.update( api_key, url, data, return_formatted=False )
+ except urllib2.URLError, e:
+ log.debug( 'ERROR(update_request (%s)): %s' % ( str((self.api_key, url, data)), str(e) ) )
+
+def recv_callback(message):
# check the meesage type.
- msg_type = msg.properties['application_headers'].get('msg_type')
- log.debug('\nMESSAGE RECVD: '+str(msg_type))
+ msg_type = message.properties['application_headers'].get('msg_type')
+ log.debug( 'MESSAGE RECVD: ' + str( msg_type ) )
if msg_type == 'data_transfer':
- log.debug('DATA TRANSFER')
- # fork a new process to transfer datasets
- transfer_script = os.path.join(os.getcwd(),
- "scripts/galaxy_messaging/server/data_transfer.py")
- cmd = '%s "%s" "%s" "%s"' % ("python",
- transfer_script,
- msg.body,
- config.get("app:main", "id_secret") )
- pid = subprocess.Popen(cmd, shell=True).pid
- log.debug('Started process (%i): %s' % (pid, str(cmd)))
+ log.debug( 'DATA TRANSFER' )
+ start_data_transfer( message )
elif msg_type == 'sample_state_update':
- log.debug('SAMPLE STATE UPDATE')
- dom = xml.dom.minidom.parseString(msg.body)
- barcode = get_value(dom, 'barcode')
- state = get_value(dom, 'state')
- log.debug('Barcode: '+barcode)
- log.debug('State: '+state)
- # update the galaxy db
- galaxydb = GalaxyDbInterface(dbconnstr)
- sample_id = galaxydb.get_sample_id(field_name='bar_code', value=barcode)
- if sample_id == -1:
- log.debug('Invalid barcode.')
- return
- galaxydb.change_state(sample_id, state)
- # update the request state
- galaxyweb = GalaxyWebInterface(webconfig.get("universe_wsgi_config", "host"),
- webconfig.get("universe_wsgi_config", "port"),
- webconfig.get("data_transfer_user_login_info", "email"),
- webconfig.get("data_transfer_user_login_info", "password"),
- config.get("app:main", "id_secret"))
- galaxyweb.update_request_state(galaxydb.get_request_id(sample_id))
- galaxyweb.logout()
+ log.debug( 'SAMPLE STATE UPDATE' )
+ update_sample_state( message )
def main():
if len(sys.argv) < 2:
- print 'Usage: python amqp_consumer.py <Galaxy config file>'
+ print 'Usage: python amqp_consumer.py <Galaxy configuration file>'
return
global config
config = ConfigParser.ConfigParser()
- config.read(sys.argv[1])
+ config.read( sys.argv[1] )
global dbconnstr
dbconnstr = config.get("app:main", "database_connection")
amqp_config = {}
for option in config.options("galaxy_amqp"):
amqp_config[option] = config.get("galaxy_amqp", option)
- log.debug(str(amqp_config))
+ log.debug("PID: " + str(os.getpid()) + ", " + str(amqp_config))
# web server config
global webconfig
webconfig = ConfigParser.ConfigParser()
webconfig.read('transfer_datasets.ini')
-
-
-
-
-
+ # connect
conn = amqp.Connection(host=amqp_config['host']+":"+amqp_config['port'],
userid=amqp_config['userid'],
password=amqp_config['password'],
virtual_host=amqp_config['virtual_host'],
insist=False)
chan = conn.channel()
- chan.queue_declare(queue=amqp_config['queue'], durable=True, exclusive=True, auto_delete=False)
- chan.exchange_declare(exchange=amqp_config['exchange'], type="direct", durable=True, auto_delete=False,)
- chan.queue_bind(queue=amqp_config['queue'],
- exchange=amqp_config['exchange'],
- routing_key=amqp_config['routing_key'])
+ chan.queue_declare( queue=amqp_config['queue'],
+ durable=True,
+ exclusive=True,
+ auto_delete=False)
+ chan.exchange_declare( exchange=amqp_config['exchange'],
+ type="direct",
+ durable=True,
+ auto_delete=False,)
+ chan.queue_bind( queue=amqp_config['queue'],
+ exchange=amqp_config['exchange'],
+ routing_key=amqp_config['routing_key'])
- chan.basic_consume(queue=amqp_config['queue'],
- no_ack=True,
- callback=recv_callback,
- consumer_tag="testtag")
+ chan.basic_consume( queue=amqp_config['queue'],
+ no_ack=True,
+ callback=recv_callback,
+ consumer_tag="testtag")
+ log.debug('Connected to rabbitmq server - '+amqp_config['host']+":"+amqp_config['port'])
while True:
chan.wait()
chan.basic_cancel("testtag")
@@ -157,3 +174,5 @@ def main():
if __name__ == '__main__':
main()
+
+
--- a/lib/galaxy/model/__init__.py
+++ b/lib/galaxy/model/__init__.py
@@ -1584,6 +1584,7 @@ class Request( object ):
SUBMITTED = 'In Progress',
REJECTED = 'Rejected',
COMPLETE = 'Complete' )
+ api_collection_visible_keys = ( 'id', 'name', 'state' )
def __init__( self, name=None, desc=None, request_type=None, user=None, form_values=None, notification=None ):
self.name = name
self.desc = desc
@@ -1663,7 +1664,7 @@ class Request( object ):
# Send email
if trans.app.config.smtp_server is not None and self.notification and self.notification[ 'email' ]:
host = trans.request.host.split( ':' )[0]
- if host in [ 'localhost', '127.0.0.1' ]:
+ if host in [ 'localhost', '127.0.0.1', '0.0.0.0' ]:
host = socket.getfqdn()
body = """
Galaxy Sample Tracking Notification
@@ -1704,8 +1705,8 @@ All samples in state: %(sample_state
s.sendmail( frm, to, message )
s.quit()
comments = "Email notification sent to %s." % ", ".join( to ).strip().strip( ',' )
- except:
- comments = "Email notification failed."
+ except Exception,e:
+ comments = "Email notification failed. (%s)" % str(e)
# update the request history with the email notification event
elif not trans.app.config.smtp_server:
comments = "Email notification failed as SMTP server not set in config file"
@@ -1714,6 +1715,18 @@ All samples in state: %(sample_state
trans.sa_session.add( event )
trans.sa_session.flush()
return comments
+ def get_api_value( self, view='collection' ):
+ 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 )
+ except AttributeError:
+ rval[key] = None
+ return rval
class RequestEvent( object ):
def __init__(self, request=None, request_state=None, comment=''):
@@ -1734,7 +1747,7 @@ class RequestType( object ):
self.sample_form = sample_form
self.datatx_info = datatx_info
@property
- def state( self ):
+ def final_sample_state( self ):
# The states mapper for this object orders ascending
return self.states[-1]
@@ -1747,12 +1760,6 @@ class RequestTypePermissions( object ):
class Sample( object ):
bulk_operations = Bunch( CHANGE_STATE = 'Change state',
SELECT_LIBRARY = 'Select data library and folder' )
- transfer_status = Bunch( NOT_STARTED = 'Not started',
- IN_QUEUE = 'In queue',
- TRANSFERRING = 'Transferring dataset',
- ADD_TO_LIBRARY = 'Adding to data library',
- COMPLETE = 'Complete',
- ERROR = 'Error' )
def __init__(self, name=None, desc=None, request=None, form_values=None, bar_code=None, library=None, folder=None):
self.name = name
self.desc = desc
@@ -1776,21 +1783,21 @@ class Sample( object ):
def untransferred_dataset_files( self ):
untransferred_datasets = []
for dataset in self.datasets:
- if dataset.status == self.transfer_status.NOT_STARTED:
+ if dataset.status == SampleDataset.transfer_status.NOT_STARTED:
untransferred_datasets.append( dataset )
return untransferred_datasets
@property
def inprogress_dataset_files( self ):
inprogress_datasets = []
for dataset in self.datasets:
- if dataset.status not in [ self.transfer_status.NOT_STARTED, self.transfer_status.COMPLETE ]:
+ if dataset.status not in [ SampleDataset.transfer_status.NOT_STARTED, SampleDataset.transfer_status.COMPLETE ]:
inprogress_datasets.append( dataset )
return inprogress_datasets
@property
def transferred_dataset_files( self ):
transferred_datasets = []
for dataset in self.datasets:
- if dataset.status == self.transfer_status.COMPLETE:
+ if dataset.status == SampleDataset.transfer_status.COMPLETE:
transferred_datasets.append( dataset )
return transferred_datasets
def dataset_size( self, filepath ):
@@ -1818,6 +1825,12 @@ class SampleEvent( object ):
self.comment = comment
class SampleDataset( object ):
+ transfer_status = Bunch( NOT_STARTED = 'Not started',
+ IN_QUEUE = 'In queue',
+ TRANSFERRING = 'Transferring dataset',
+ ADD_TO_LIBRARY = 'Adding to data library',
+ COMPLETE = 'Complete',
+ ERROR = 'Error' )
def __init__(self, sample=None, name=None, file_path=None,
status=None, error_msg=None, size=None):
self.sample = sample
--- a/lib/galaxy/web/controllers/requests_common.py
+++ b/lib/galaxy/web/controllers/requests_common.py
@@ -275,7 +275,7 @@ class RequestsCommon( BaseController, Us
request_type = request.type
name = util.restore_text( params.get( 'name', '' ) )
desc = util.restore_text( params.get( 'desc', '' ) )
- notification = dict( email=[ user.email ], sample_states=[ request_type.state.id ], body='', subject='' )
+ notification = dict( email=[ user.email ], sample_states=[ request_type.final_sample_state.id ], body='', subject='' )
values = []
for index, field in enumerate( request_type.request_form.fields ):
field_type = field[ 'type' ]
@@ -416,11 +416,7 @@ class RequestsCommon( BaseController, Us
elif params.get( 'change_state_button', False ):
sample_event_comment = util.restore_text( params.get( 'sample_event_comment', '' ) )
new_state = trans.sa_session.query( trans.model.SampleState ).get( trans.security.decode_id( sample_state_id ) )
- for sample_id in selected_samples:
- sample = trans.sa_session.query( trans.model.Sample ).get( trans.security.decode_id( sample_id ) )
- event = trans.model.SampleEvent( sample, new_state, sample_event_comment )
- trans.sa_session.add( event )
- trans.sa_session.flush()
+ self.update_sample_state(trans, cntrller, selected_samples, new_state, comment=sample_event_comment )
return trans.response.send_redirect( web.url_for( controller='requests_common',
cntrller=cntrller,
action='update_request_state',
@@ -486,6 +482,22 @@ class RequestsCommon( BaseController, Us
status=status,
message=message )
@web.expose
+ def update_sample_state(self, trans, cntrller, sample_ids, new_state, comment=None ):
+ for sample_id in sample_ids:
+ try:
+ sample = trans.sa_session.query( trans.model.Sample ).get( trans.security.decode_id( sample_id ) )
+ except:
+ if cntrller == 'api':
+ trans.response.status = 400
+ return "Malformed sample id ( %s ) specified, unable to decode." % str( sample_id )
+ else:
+ return invalid_id_redirect( trans, cntrller, sample_id )
+ event = trans.model.SampleEvent( sample, new_state, comment )
+ trans.sa_session.add( event )
+ trans.sa_session.flush()
+ if cntrller == 'api':
+ return 200, 'Done'
+ @web.expose
@web.require_login( "delete sequencing requests" )
def delete_request( self, trans, cntrller, **kwd ):
params = util.Params( kwd )
@@ -640,6 +652,8 @@ class RequestsCommon( BaseController, Us
event = trans.model.RequestEvent( request, request.states.SUBMITTED, message )
trans.sa_session.add( event )
trans.sa_session.flush()
+ if cntrller == 'api':
+ return 200, message
return trans.response.send_redirect( web.url_for( controller='requests_common',
action='manage_request',
cntrller=cntrller,
@@ -647,7 +661,7 @@ class RequestsCommon( BaseController, Us
status=status,
message=message ) )
final_state = False
- request_type_state = request.type.state
+ request_type_state = request.type.final_sample_state
if common_state.id == request_type_state.id:
# since all the samples are in the final state, change the request state to 'Complete'
comments = "All samples of this request are in the last sample state (%s). " % request_type_state.name
@@ -656,7 +670,7 @@ class RequestsCommon( BaseController, Us
else:
comments = "All samples are in %s state. " % common_state.name
state = request.states.SUBMITTED
- event = trans.model.RequestEvent(request, state, comments)
+ event = trans.model.RequestEvent( request, state, comments )
trans.sa_session.add( event )
trans.sa_session.flush()
# check if an email notification is configured to be sent when the samples
@@ -666,6 +680,8 @@ class RequestsCommon( BaseController, Us
message = comments + retval
else:
message = comments
+ if cntrller == 'api':
+ return 200, message
return trans.response.send_redirect( web.url_for( controller='requests_common',
action='manage_request',
cntrller=cntrller,
--- a/scripts/galaxy_messaging/server/data_transfer.py
+++ b/scripts/galaxy_messaging/server/data_transfer.py
@@ -19,25 +19,26 @@ import urllib,urllib2, cookielib, shutil
import logging, time, datetime
import xml.dom.minidom
-sp = sys.path[0]
+log = logging.getLogger("datatx_"+str(os.getpid()))
+log.setLevel(logging.DEBUG)
+fh = logging.FileHandler("data_transfer.log")
+fh.setLevel(logging.DEBUG)
+formatter = logging.Formatter("%(asctime)s - %(name)s - %(message)s")
+fh.setFormatter(formatter)
+log.addHandler(fh)
-from galaxydb_interface import GalaxyDbInterface
-
-assert sys.version_info[:2] >= ( 2, 4 )
-new_path = [ sp ]
-new_path.extend( sys.path )
-sys.path = new_path
-
-from galaxyweb_interface import GalaxyWebInterface
+api_path = [ os.path.join( os.getcwd(), "scripts/api" ) ]
+sys.path.extend( api_path )
+import common as api
assert sys.version_info[:2] >= ( 2, 4 )
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.util.json import from_json_string, to_json_string
-from galaxy.model import Sample
+from galaxy.model import SampleDataset
+from galaxy.web.api.requests import RequestsController
from galaxy import eggs
import pkg_resources
pkg_resources.require( "pexpect" )
@@ -46,28 +47,19 @@ import pexpect
pkg_resources.require( "simplejson" )
import simplejson
-log = logging.getLogger("datatx_"+str(os.getpid()))
-log.setLevel(logging.DEBUG)
-fh = logging.FileHandler("data_transfer.log")
-fh.setLevel(logging.DEBUG)
-formatter = logging.Formatter("%(asctime)s - %(name)s - %(message)s")
-fh.setFormatter(formatter)
-log.addHandler(fh)
-
-
class DataTransfer(object):
- def __init__(self, msg, config_id_secret):
+ def __init__(self, msg, config_file):
log.info(msg)
self.dom = xml.dom.minidom.parseString(msg)
- self.host = self.get_value(self.dom, 'data_host')
- self.username = self.get_value(self.dom, 'data_user')
- self.password = self.get_value(self.dom, 'data_password')
+ self.sequencer_host = self.get_value(self.dom, 'data_host')
+ self.sequencer_username = self.get_value(self.dom, 'data_user')
+ self.sequencer_password = self.get_value(self.dom, 'data_password')
+ self.request_id = self.get_value(self.dom, 'request_id')
self.sample_id = self.get_value(self.dom, 'sample_id')
self.library_id = self.get_value(self.dom, 'library_id')
self.folder_id = self.get_value(self.dom, 'folder_id')
self.dataset_files = []
- self.config_id_secret = config_id_secret
count=0
while True:
dataset_id = self.get_value_index(self.dom, 'dataset_id', count)
@@ -82,21 +74,25 @@ class DataTransfer(object):
count=count+1
try:
# Retrieve the upload user login information from the config file
+ transfer_datasets_config = ConfigParser.ConfigParser()
+ transfer_datasets_config.read('transfer_datasets.ini')
+ self.data_transfer_user_email = transfer_datasets_config.get("data_transfer_user_login_info", "email")
+ self.data_transfer_user_password = transfer_datasets_config.get("data_transfer_user_login_info", "password")
+ self.api_key = transfer_datasets_config.get("data_transfer_user_login_info", "api_key")
+ self.http_server_section = transfer_datasets_config.get("universe_wsgi_config", "http_server_section")
config = ConfigParser.ConfigParser()
- config.read('transfer_datasets.ini')
- self.datatx_email = config.get("data_transfer_user_login_info", "email")
- self.datatx_password = config.get("data_transfer_user_login_info", "password")
- self.server_host = config.get("universe_wsgi_config", "host")
- self.server_port = config.get("universe_wsgi_config", "port")
- self.database_connection = config.get("universe_wsgi_config", "database_connection")
- self.import_dir = config.get("universe_wsgi_config", "library_import_dir")
+ config.read( config_file )
+ self.server_host = config.get(self.http_server_section, "host")
+ self.server_port = config.get(self.http_server_section, "port")
+ self.database_connection = config.get("app:main", "database_connection")
+ self.import_dir = config.get("app:main", "library_import_dir")
+ self.config_id_secret = config.get("app:main", "id_secret")
+
# create the destination directory within the import directory
self.server_dir = os.path.join( self.import_dir, 'datatx_'+str(os.getpid())+'_'+datetime.date.today().strftime("%d%b%Y") )
os.mkdir(self.server_dir)
if not os.path.exists(self.server_dir):
raise Exception
- # connect to db
- self.galaxydb = GalaxyDbInterface(self.database_connection)
except:
log.error(traceback.format_exc())
log.error('FATAL ERROR')
@@ -114,7 +110,7 @@ class DataTransfer(object):
# add the dataset to the given library
self.add_to_library()
# update the data transfer status in the db
- self.update_status(Sample.transfer_status.COMPLETE)
+ self.update_status(SampleDataset.transfer_status.COMPLETE)
# cleanup
#self.cleanup()
sys.exit(0)
@@ -149,15 +145,15 @@ class DataTransfer(object):
def print_ticks(d):
pass
for i, df in enumerate(self.dataset_files):
- self.update_status(Sample.transfer_status.TRANSFERRING, df['dataset_id'])
+ self.update_status(SampleDataset.transfer_status.TRANSFERRING, df['dataset_id'])
try:
- cmd = "scp %s@%s:'%s' '%s/%s'" % ( self.username,
- self.host,
- df['file'].replace(' ', '\ '),
- self.server_dir.replace(' ', '\ '),
- df['name'].replace(' ', '\ '))
+ cmd = "scp %s@%s:'%s' '%s/%s'" % ( self.sequencer_username,
+ self.sequencer_host,
+ df['file'].replace(' ', '\ '),
+ self.server_dir.replace(' ', '\ '),
+ df['name'].replace(' ', '\ ') )
log.debug(cmd)
- output = pexpect.run(cmd, events={'.ssword:*': self.password+'\r\n',
+ output = pexpect.run(cmd, events={'.ssword:*': self.sequencer_password+'\r\n',
pexpect.TIMEOUT:print_ticks},
timeout=10)
log.debug(output)
@@ -176,17 +172,21 @@ class DataTransfer(object):
This method adds the dataset file to the target data library & folder
by opening the corresponding url in Galaxy server running.
'''
+ self.update_status(SampleDataset.transfer_status.ADD_TO_LIBRARY)
try:
- self.update_status(Sample.transfer_status.ADD_TO_LIBRARY)
- log.debug("dir:%s, lib:%s, folder:%s" % (self.server_dir, str(self.library_id), str(self.folder_id)))
- galaxyweb = GalaxyWebInterface(self.server_host, self.server_port,
- self.datatx_email, self.datatx_password,
- self.config_id_secret)
- retval = galaxyweb.add_to_library(self.server_dir, self.library_id, self.folder_id)
- log.debug(str(retval))
- galaxyweb.logout()
- except Exception, e:
- log.debug(e)
+ data = {}
+ data[ 'folder_id' ] = api.encode_id( self.config_id_secret, '%s.%s' % ( 'folder', self.folder_id ) )
+ data[ 'file_type' ] = 'auto'
+ data[ 'server_dir' ] = self.server_dir
+ data[ 'dbkey' ] = ''
+ data[ 'upload_option' ] = 'upload_directory'
+ data[ 'create_type' ] = 'file'
+ url = "http://%s:%s/api/libraries/%s/contents" % ( self.server_host,
+ self.server_port,
+ api.encode_id( self.config_id_secret, self.library_id ) )
+ log.debug(str((self.api_key, url, data)))
+ retval = api.submit( self.api_key, url, data, return_formatted=False )
+ except:
self.error_and_exit(str(e))
def update_status(self, status, dataset_id='All', msg=''):
@@ -195,12 +195,27 @@ class DataTransfer(object):
'''
try:
log.debug('Setting status "%s" for dataset "%s" of sample "%s"' % ( status, str(dataset_id), str(self.sample_id) ) )
+ sample_dataset_ids = []
if dataset_id == 'All':
for dataset in self.dataset_files:
- self.galaxydb.set_sample_dataset_status(dataset['dataset_id'], status, msg)
+ sample_dataset_ids.append( api.encode_id( self.config_id_secret, dataset['dataset_id'] ) )
else:
- self.galaxydb.set_sample_dataset_status(dataset_id, status, msg)
+ sample_dataset_ids.append( api.encode_id( self.config_id_secret, dataset_id ) )
+ # update the transfer status
+ data = {}
+ data[ 'update_type' ] = RequestsController.update_types.SAMPLE_DATASET
+ data[ 'sample_dataset_ids' ] = sample_dataset_ids
+ data[ 'new_status' ] = status
+ data[ 'error_msg' ] = msg
+ url = "http://%s:%s/api/requests/%s" % ( self.server_host,
+ self.server_port,
+ api.encode_id( self.config_id_secret, self.request_id ) )
+ log.debug(str((self.api_key, url, data)))
+ retval = api.update( self.api_key, url, data, return_formatted=False )
log.debug('done.')
+ except urllib2.URLError, e:
+ log.debug( 'ERROR(sample_dataset_transfer_status (%s)): %s' % ( url, str(e) ) )
+ log.error(traceback.format_exc())
except:
log.error(traceback.format_exc())
log.error('FATAL ERROR')
--- a/templates/admin/requests/rename_datasets.mako
+++ b/templates/admin/requests/rename_datasets.mako
@@ -32,7 +32,7 @@
<tbody>
%for id in id_list:
<% sample_dataset = trans.sa_session.query( trans.model.SampleDataset ).get( trans.security.decode_id( id ) ) %>
- %if sample_dataset.status == trans.app.model.Sample.transfer_status.NOT_STARTED:
+ %if sample_dataset.status == trans.app.model.SampleDataset.transfer_status.NOT_STARTED:
<tr><td><% rename_datasets_for_sample_select_field = build_rename_datasets_for_sample_select_field( trans, sample_dataset ) %>
--- a/scripts/api/common.py
+++ b/scripts/api/common.py
@@ -10,6 +10,11 @@ import pkg_resources
pkg_resources.require( "simplejson" )
import simplejson
+pkg_resources.require( "pycrypto" )
+from Crypto.Cipher import Blowfish
+from Crypto.Util.randpool import RandomPool
+from Crypto.Util import number
+
def make_url( api_key, url, args=None ):
# Adds the API Key to the URL if it's not already there.
if args is None:
@@ -36,7 +41,15 @@ def post( api_key, url, data ):
req = urllib2.Request( url, headers = { 'Content-Type': 'application/json' }, data = simplejson.dumps( data ) )
return simplejson.loads( urllib2.urlopen( req ).read() )
-def display( api_key, url ):
+def put( api_key, url, data ):
+ # Do the actual PUT
+ url = make_url( api_key, url )
+ req = urllib2.Request( url, headers = { 'Content-Type': 'application/json' }, data = simplejson.dumps( data ))
+ req.get_method = lambda: 'PUT'
+ return simplejson.loads( urllib2.urlopen( req ).read() )
+
+
+def display( api_key, url, return_formatted=True ):
# Sends an API GET request and acts as a generic formatter for the JSON response.
try:
r = get( api_key, url )
@@ -47,6 +60,8 @@ def display( api_key, url ):
if type( r ) == unicode:
print 'error: %s' % r
return None
+ if not return_formatted:
+ return r
elif type( r ) == list:
# Response is a collection as defined in the REST style.
print 'Collection Members'
@@ -68,7 +83,7 @@ def display( api_key, url ):
else:
print 'response is unknown type: %s' % type( r )
-def submit( api_key, url, data ):
+def submit( api_key, url, data, return_formatted=True ):
# Sends an API POST request and acts as a generic formatter for the JSON response.
# 'data' will become the JSON payload read by Galaxy.
try:
@@ -77,6 +92,8 @@ def submit( api_key, url, data ):
print e
print e.read( 1024 )
sys.exit( 1 )
+ if not return_formatted:
+ return r
print 'Response'
print '--------'
if type( r ) == list:
@@ -96,3 +113,45 @@ def submit( api_key, url, data ):
print i
else:
print r
+
+def update( api_key, url, data, return_formatted=True ):
+ # Sends an API PUT request and acts as a generic formatter for the JSON response.
+ # 'data' will become the JSON payload read by Galaxy.
+ try:
+ r = put( api_key, url, data )
+ except urllib2.HTTPError, e:
+ print e
+ print e.read( 1024 )
+ sys.exit( 1 )
+ if not return_formatted:
+ return r
+ print 'Response'
+ print '--------'
+ if type( r ) == list:
+ # Currently the only implemented responses are lists of dicts, because
+ # submission creates some number of collection elements.
+ for i in r:
+ if type( i ) == dict:
+ if 'url' in i:
+ print i.pop( 'url' )
+ else:
+ print '----'
+ if 'name' in i:
+ print ' name: %s' % i.pop( 'name' )
+ for k, v in i.items():
+ print ' %s: %s' % ( k, v )
+ else:
+ print i
+ else:
+ print r
+
+# utility method to encode ID's
+def encode_id( config_id_secret, obj_id ):
+ id_cipher = Blowfish.new( config_id_secret )
+ # Convert to string
+ s = str( obj_id )
+ # Pad to a multiple of 8 with leading "!"
+ s = ( "!" * ( 8 - len(s) % 8 ) ) + s
+ # Encrypt
+ return id_cipher.encrypt( s ).encode( 'hex' )
+
--- a/lib/galaxy/web/controllers/requests_admin.py
+++ b/lib/galaxy/web/controllers/requests_admin.py
@@ -129,9 +129,9 @@ class DataTransferGrid( grids.Grid ):
visible=False,
filterable="standard" ) )
operations = [
- grids.GridOperation( "Start Transfer", allow_multiple=True, condition=( lambda item: item.status in [ model.Sample.transfer_status.NOT_STARTED ] ) ),
- grids.GridOperation( "Rename", allow_multiple=True, allow_popup=False, condition=( lambda item: item.status in [ model.Sample.transfer_status.NOT_STARTED ] ) ),
- grids.GridOperation( "Delete", allow_multiple=True, condition=( lambda item: item.status in [ model.Sample.transfer_status.NOT_STARTED ] ) ),
+ grids.GridOperation( "Start Transfer", allow_multiple=True, condition=( lambda item: item.status in [ model.SampleDataset.transfer_status.NOT_STARTED ] ) ),
+ grids.GridOperation( "Rename", allow_multiple=True, allow_popup=False, condition=( lambda item: item.status in [ model.SampleDataset.transfer_status.NOT_STARTED ] ) ),
+ grids.GridOperation( "Delete", allow_multiple=True, condition=( lambda item: item.status in [ model.SampleDataset.transfer_status.NOT_STARTED ] ) ),
]
def apply_query_filter( self, trans, query, **kwd ):
sample_id = kwd.get( 'sample_id', None )
@@ -506,7 +506,7 @@ class RequestsAdmin( BaseController, Use
name = self.__dataset_name( sample, filepath.split( '/' )[-1] )
sample_dataset = trans.model.SampleDataset( sample=sample,
file_path=filepath,
- status=sample.transfer_status.NOT_STARTED,
+ status=trans.app.model.SampleDataset.transfer_status.NOT_STARTED,
name=name,
error_msg='',
size=sample.dataset_size( filepath ) )
@@ -575,6 +575,7 @@ class RequestsAdmin( BaseController, Use
<data_host>%(DATA_HOST)s</data_host><data_user>%(DATA_USER)s</data_user><data_password>%(DATA_PASSWORD)s</data_password>
+ <request_id>%(REQUEST_ID)s</request_id><sample_id>%(SAMPLE_ID)s</sample_id><library_id>%(LIBRARY_ID)s</library_id><folder_id>%(FOLDER_ID)s</folder_id>
@@ -588,16 +589,17 @@ class RequestsAdmin( BaseController, Use
</dataset>'''
datasets = ''
for sample_dataset in selected_sample_datasets:
- if sample_dataset.status == sample.transfer_status.NOT_STARTED:
+ if sample_dataset.status == trans.app.model.SampleDataset.transfer_status.NOT_STARTED:
datasets = datasets + dataset_xml % dict( ID=str( sample_dataset.id ),
NAME=sample_dataset.name,
FILE=sample_dataset.file_path )
- sample_dataset.status = sample.transfer_status.IN_QUEUE
+ sample_dataset.status = trans.app.model.SampleDataset.transfer_status.IN_QUEUE
trans.sa_session.add( sample_dataset )
trans.sa_session.flush()
data = xml % dict( DATA_HOST=datatx_info['host'],
DATA_USER=datatx_info['username'],
DATA_PASSWORD=datatx_info['password'],
+ REQUEST_ID=str(sample.request.id),
SAMPLE_ID=str(sample.id),
LIBRARY_ID=str(sample.library.id),
FOLDER_ID=str(sample.folder.id),
@@ -644,6 +646,25 @@ class RequestsAdmin( BaseController, Use
sample_id=trans.security.encode_id( sample.id ),
status=status,
message=message) )
+ @web.expose
+ def update_sample_dataset_status(self, trans, cntrller, sample_dataset_ids, new_status, error_msg=None ):
+ # check if the new status is a valid transfer status
+ possible_status_list = [v[1] for v in trans.app.model.SampleDataset.transfer_status.items()]
+ if new_status not in possible_status_list:
+ trans.response.status = 400
+ return "The requested transfer status ( %s ) is not a valid transfer status." % new_status
+ for id in util.listify( sample_dataset_ids ):
+ try:
+ sd_id = trans.security.decode_id( id )
+ sample_dataset = trans.sa_session.query( trans.app.model.SampleDataset ).get( sd_id )
+ except:
+ trans.response.status = 400
+ return "Invalid sample dataset id ( %s ) specified." % str( id )
+ sample_dataset.status = new_status
+ sample_dataset.error_msg = error_msg
+ trans.sa_session.add( sample_dataset )
+ trans.sa_session.flush()
+ return 200, 'Done'
# Request Type Stuff
@web.expose
@web.require_admin
--- a/scripts/galaxy_messaging/server/galaxydb_interface.py
+++ b/scripts/galaxy_messaging/server/galaxydb_interface.py
@@ -28,7 +28,7 @@ class GalaxyDbInterface(object):
def __init__(self, dbstr):
self.dbstr = dbstr
self.db_engine = create_engine(self.dbstr)
- self.db_engine.echo = True
+ self.db_engine.echo = False
self.metadata = MetaData(self.db_engine)
self.session = sessionmaker(bind=self.db_engine)
self.event_table = Table('sample_event', self.metadata, autoload=True )
--- /dev/null
+++ b/scripts/api/sample_update_state.py
@@ -0,0 +1,23 @@
+#!/usr/bin/env python
+
+
+import os, sys, traceback
+sys.path.insert( 0, os.path.dirname( __file__ ) )
+from common import display
+from common import submit
+from common import update
+
+try:
+ data = {}
+ data[ 'update_type' ] = 'sample_state'
+ data[ 'sample_ids' ] = sys.argv[3].split(',')
+ data[ 'new_state' ] = sys.argv[4]
+except IndexError:
+ print 'usage: %s key url sample_ids new_state [comment]' % os.path.basename( sys.argv[0] )
+ sys.exit( 1 )
+try:
+ data[ 'comment' ] = sys.argv[5]
+except IndexError:
+ data[ 'comment' ] = ''
+
+update( sys.argv[1], sys.argv[2], data, return_formatted=True )
--- /dev/null
+++ b/lib/galaxy/web/api/requests.py
@@ -0,0 +1,130 @@
+"""
+API operations on a sample tracking system.
+"""
+import logging, os, string, shutil, urllib, re, socket
+from cgi import escape, FieldStorage
+from galaxy import util, datatypes, jobs, web, util
+from galaxy.web.base.controller import *
+from galaxy.util.sanitize_html import sanitize_html
+from galaxy.model.orm import *
+from galaxy.util.bunch import Bunch
+
+log = logging.getLogger( __name__ )
+
+class RequestsController( BaseController ):
+ update_types = Bunch( REQUEST = 'request_state',
+ SAMPLE = 'sample_state',
+ SAMPLE_DATASET = 'sample_dataset_transfer_status' )
+ update_type_values = [v[1] for v in update_types.items()]
+ @web.expose_api
+ def index( self, trans, **kwd ):
+ """
+ GET /api/requests
+ Displays a collection (list) of sequencing requests.
+ """
+ query = trans.sa_session.query( trans.app.model.Request )\
+ .filter( and_( trans.app.model.Request.table.c.user_id == trans.user.id \
+ and trans.app.model.Request.table.c.deleted == False ) ) \
+ .all()
+ rval = []
+ for request in query:
+ item = request.get_api_value()
+ item['url'] = url_for( 'requests', id=trans.security.encode_id( request.id ) )
+ item['id'] = trans.security.encode_id( item['id'] )
+ rval.append( item )
+ return rval
+
+ @web.expose_api
+ def update( self, trans, id, key, payload, **kwd ):
+ """
+ PUT /api/requests/{encoded_request_id}
+ Displays information about a sequencing request.
+ """
+ params = util.Params( kwd )
+ update_type = None
+ if 'update_type' not in payload:
+ trans.response.status = 400
+ return "Missing required 'update_type' parameter. Please consult the API documentation for help."
+ else:
+ update_type = payload.pop( 'update_type' )
+ if update_type not in self.update_type_values:
+ trans.response.status = 400
+ return "Invalid value for 'update_type' parameter ( %s ) specified. Please consult the API documentation for help." % update_type
+ try:
+ request_id = trans.security.decode_id( id )
+ except TypeError:
+ trans.response.status = 400
+ return "Malformed %s id ( %s ) specified, unable to decode." % ( update_type, str( id ) )
+ try:
+ request = trans.sa_session.query( trans.app.model.Request ).get( request_id )
+ except:
+ request = None
+ if not request or not ( trans.user_is_admin() or request.user.id == trans.user.id ):
+ trans.response.status = 400
+ return "Invalid request id ( %s ) specified." % str( request_id )
+ # check update type
+ if update_type == 'request_state':
+ return self.__update_request_state( trans, encoded_request_id=id )
+ elif update_type == 'sample_state':
+ return self.__update_sample_state( trans, request.type, **payload )
+ elif update_type == 'sample_dataset_transfer_status':
+ # update sample_dataset transfer status
+ return self.__update_sample_dataset_status( trans, **payload )
+
+
+ def __update_request_state( self, trans, encoded_request_id ):
+ requests_common_cntrller = trans.webapp.controllers['requests_common']
+ status, output = requests_common_cntrller.update_request_state( trans,
+ cntrller='api',
+ request_id=encoded_request_id )
+ return status, output
+ def __update_sample_state( self, trans, request_type, **payload ):
+ # only admin user may update sample state in Galaxy sample tracking
+ if not trans.user_is_admin():
+ trans.response.status = 400
+ return "only an admin user may update sample state in Galaxy sample tracking."
+ if 'sample_ids' not in payload or 'new_state' not in payload:
+ trans.response.status = 400
+ return "Missing one or more required parameters: 'sample_ids' and 'new_state'."
+ sample_ids = payload.pop( 'sample_ids' )
+ new_state_name = payload.pop( 'new_state' )
+ comment = payload.get( 'comment', '' )
+ # check if the new state is a valid sample state
+ possible_states = request_type.states
+ new_state = None
+ for state in possible_states:
+ if state.name == new_state_name:
+ new_state = state
+ if not new_state:
+ trans.response.status = 400
+ return "Invalid sample state requested ( %s )." % new_state
+ requests_common_cntrller = trans.webapp.controllers['requests_common']
+ status, output = requests_common_cntrller.update_sample_state( trans,
+ cntrller='api',
+ sample_ids=sample_ids,
+ new_state=new_state,
+ comment=comment )
+ return status, output
+
+ def __update_sample_dataset_status( self, trans, **payload ):
+ # only admin user may transfer sample datasets in Galaxy sample tracking
+ if not trans.user_is_admin():
+ trans.response.status = 400
+ return "Only an admin user may transfer sample datasets in Galaxy sample tracking and thus update transfer status."
+ if 'sample_dataset_ids' not in payload or 'new_status' not in payload:
+ trans.response.status = 400
+ return "Missing one or more required parameters: 'sample_dataset_ids' and 'new_status'."
+ sample_dataset_ids = payload.pop( 'sample_dataset_ids' )
+ new_status = payload.pop( 'new_status' )
+ error_msg = payload.get( 'error_msg', '' )
+ requests_admin_cntrller = trans.webapp.controllers['requests_admin']
+ status, output = requests_admin_cntrller.update_sample_dataset_status( trans,
+ cntrller='api',
+ sample_dataset_ids=sample_dataset_ids,
+ new_status=new_status,
+ error_msg=error_msg )
+ return status, output
+
+
+
+
--- a/templates/admin/requests/dataset.mako
+++ b/templates/admin/requests/dataset.mako
@@ -58,7 +58,7 @@
<label>Transfer status:</label><div style="float: left; width: 250px; margin-right: 10px;">
${sample_dataset.status}
- %if sample_dataset.status == sample.transfer_status.ERROR:
+ %if sample_dataset.status == trans.app.model.SampleDataset.transfer_status.ERROR:
<br/>
${sample_dataset.error_msg}
%endif
--- a/scripts/api/display.py
+++ b/scripts/api/display.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python
-import os, sys
+import os, sys, urllib2
sys.path.insert( 0, os.path.dirname( __file__ ) )
from common import display
@@ -9,3 +9,6 @@ try:
except TypeError:
print 'usage: %s key url' % os.path.basename( sys.argv[0] )
sys.exit( 1 )
+except urllib2.URLError, e:
+ print str(e)
+ sys.exit( 1 )
1
0

galaxy-dist commit 314f8a5d3823: Complete functional test for cuffcompare.
by commits-noreply@bitbucket.org 20 Nov '10
by commits-noreply@bitbucket.org 20 Nov '10
20 Nov '10
# HG changeset patch -- Bitbucket.org
# Project galaxy-dist
# URL http://bitbucket.org/galaxy/galaxy-dist/overview
# User jeremy goecks <jeremy.goecks(a)emory.edu>
# Date 1288119881 14400
# Node ID 314f8a5d38237c3f1fafccb522ee45aebfa8464f
# Parent 379d0701f198964fb964c3834cce7414cbc8f888
Complete functional test for cuffcompare.
--- /dev/null
+++ b/test-data/cuffcompare_out1.tmap
@@ -0,0 +1,51 @@
+ref_gene_id ref_id class_code cuff_gene_id cuff_id FMI FPKM FPKM_conf_lo FPKM_conf_hi cov len major_iso_id
+- - u CUFF.1 CUFF.1.1 100 20.607936 0.000000 49.751960 1.317073 41 CUFF.1.1
+- - u CUFF.3 CUFF.3.1 100 27.255658 0.000000 65.800979 1.741935 31 CUFF.3.1
+- - u CUFF.5 CUFF.5.1 100 31.293533 0.000000 75.549272 2.000000 27 CUFF.5.1
+- - u CUFF.7 CUFF.7.1 100 9.999117 0.000000 19.998234 0.639053 169 CUFF.7.1
+- - u CUFF.9 CUFF.9.1 100 17.776896 9.153835 26.399957 1.136139 404 CUFF.9.1
+- - u CUFF.11 CUFF.11.1 100 31.293533 0.000000 75.549272 2.000000 27 CUFF.11.1
+Xkr4 Xkr4 c CUFF.13 CUFF.13.1 100 10.695258 0.000000 25.820637 0.683544 79 CUFF.13.1
+Xkr4 Xkr4 i CUFF.15 CUFF.15.1 100 10.695258 0.000000 25.820637 0.683544 79 CUFF.15.1
+Xkr4 Xkr4 i CUFF.17 CUFF.17.1 100 8.710571 0.000000 21.029179 0.556701 97 CUFF.17.1
+Xkr4 Xkr4 i CUFF.19 CUFF.19.1 100 29.337687 3.097262 55.578113 1.875000 72 CUFF.19.1
+Xkr4 Xkr4 i CUFF.21 CUFF.21.1 100 13.851236 0.000000 33.439842 0.885246 61 CUFF.21.1
+Xkr4 Xkr4 i CUFF.23 CUFF.23.1 100 23.470150 0.000000 50.571145 1.500000 54 CUFF.23.1
+Xkr4 Xkr4 i CUFF.25 CUFF.25.1 100 14.567679 5.354270 23.781089 0.931034 290 CUFF.25.1
+Xkr4 Xkr4 i CUFF.27 CUFF.27.1 100 34.253732 0.000000 73.806535 2.189189 37 CUFF.27.1
+- - u CUFF.29 CUFF.29.1 100 107.103219 71.402146 142.804292 6.845070 142 CUFF.29.1
+- - u CUFF.31 CUFF.31.1 100 122.650461 40.883487 204.417435 7.838710 31 CUFF.31.1
+- - u CUFF.33 CUFF.33.1 100 109.527366 26.732460 192.322273 7.000000 27 CUFF.33.1
+- - u CUFF.35 CUFF.35.1 100 96.747183 61.420107 132.074259 6.183206 131 CUFF.35.1
+- - u CUFF.37 CUFF.37.1 100 104.085013 53.596365 154.573660 6.652174 69 CUFF.37.1
+- - u CUFF.39 CUFF.39.1 100 23.912983 0.000000 51.525317 1.528302 53 CUFF.39.1
+- - u CUFF.41 CUFF.41.1 100 10.695258 0.000000 25.820637 0.683544 79 CUFF.41.1
+- - u CUFF.43 CUFF.43.1 100 10.561567 0.000000 25.497879 0.675000 80 CUFF.43.1
+- - u CUFF.45 CUFF.45.1 100 20.708956 2.186303 39.231609 1.323529 102 CUFF.45.1
+- - u CUFF.47 CUFF.47.1 100 20.607936 0.000000 49.751960 1.317073 41 CUFF.47.1
+- - u CUFF.49 CUFF.49.1 100 15.646767 0.000000 46.940300 1.000000 27 CUFF.49.1
+- - u CUFF.51 CUFF.51.1 100 31.293533 0.000000 75.549272 2.000000 27 CUFF.51.1
+- - u CUFF.53 CUFF.53.1 100 31.293533 0.000000 75.549272 2.000000 27 CUFF.53.1
+- - u CUFF.55 CUFF.55.1 100 31.293533 0.000000 75.549272 2.000000 27 CUFF.55.1
+- - u CUFF.57 CUFF.57.1 100 15.646767 0.000000 46.940300 1.000000 27 CUFF.57.1
+- - u CUFF.59 CUFF.59.1 100 15.646767 0.000000 46.940300 1.000000 27 CUFF.59.1
+Xkr4 Xkr4 i CUFF.61 CUFF.61.1 100 45.263860 0.000000 97.530065 2.892857 28 CUFF.61.1
+Xkr4 Xkr4 i CUFF.63 CUFF.63.1 100 15.646767 0.000000 46.940300 1.000000 27 CUFF.63.1
+Xkr4 Xkr4 i CUFF.65 CUFF.65.1 100 15.362280 0.000000 37.087825 0.981818 55 CUFF.65.1
+Xkr4 Xkr4 i CUFF.67 CUFF.67.1 100 12.998852 0.000000 31.382005 0.830769 65 CUFF.67.1
+Xkr4 Xkr4 i CUFF.69 CUFF.69.1 100 10.058636 0.000000 24.283695 0.642857 84 CUFF.69.1
+Xkr4 Xkr4 i CUFF.71 CUFF.71.1 100 8.621688 0.000000 20.814595 0.551020 98 CUFF.71.1
+Xkr4 Xkr4 i CUFF.73 CUFF.73.1 100 15.362280 0.000000 37.087825 0.981818 55 CUFF.73.1
+Xkr4 Xkr4 i CUFF.75 CUFF.75.1 100 31.293533 0.000000 75.549272 2.000000 27 CUFF.75.1
+Xkr4 Xkr4 i CUFF.77 CUFF.77.1 100 16.248565 0.000000 39.227507 1.038462 52 CUFF.77.1
+Xkr4 Xkr4 i CUFF.79 CUFF.79.1 100 31.293533 0.000000 75.549272 2.000000 27 CUFF.79.1
+Xkr4 Xkr4 i CUFF.81 CUFF.81.1 100 13.201959 0.000000 31.872349 0.843750 64 CUFF.81.1
+Xkr4 Xkr4 i CUFF.83 CUFF.83.1 100 13.201959 0.000000 28.446269 0.843750 96 CUFF.83.1
+Xkr4 Xkr4 i CUFF.85 CUFF.85.1 100 31.293533 0.000000 75.549272 2.000000 27 CUFF.85.1
+Xkr4 Xkr4 i CUFF.87 CUFF.87.1 100 17.243375 0.000000 41.629191 1.102041 49 CUFF.87.1
+Xkr4 Xkr4 i CUFF.89 CUFF.89.1 100 16.567165 0.000000 39.996674 1.058824 51 CUFF.89.1
+Xkr4 Xkr4 i CUFF.91 CUFF.91.1 100 31.293533 0.000000 75.549272 2.000000 27 CUFF.91.1
+Xkr4 Xkr4 i CUFF.93 CUFF.93.1 100 21.664754 0.000000 52.303342 1.384615 39 CUFF.93.1
+Xkr4 Xkr4 i CUFF.95 CUFF.95.1 100 46.940300 0.000000 101.142289 3.000000 27 CUFF.95.1
+Xkr4 Xkr4 i CUFF.97 CUFF.97.1 100 21.481154 0.000000 46.285454 1.372881 59 CUFF.97.1
+Xkr4 Xkr4 i CUFF.99 CUFF.99.1 100 14.567679 0.000000 35.169489 0.931034 58 CUFF.99.1
--- /dev/null
+++ b/test-data/cuffcompare_out2.refmap
@@ -0,0 +1,2 @@
+ref_gene_id ref_id class_code cuff_id_list
+Xkr4 Xkr4 c CUFF.13|CUFF.13.1
--- a/tools/ngs_rna/cuffcompare_wrapper.xml
+++ b/tools/ngs_rna/cuffcompare_wrapper.xml
@@ -81,16 +81,15 @@
<param name="use_ref_annotation" value="Yes"/><param name="reference_annotation" value="cuffcompare_in3.gtf" ftype="gtf"/><param name="ignore_nonoverlapping_reference" value="Yes"/>
- ## HACK: need to specify output name and it needs to work (right now it uses the final output file)
- <output name="XXXX" file="cuffcompare_out6.tracking"/>
- <!--
- ## TODO: transcripts combined file as well.
+ <!-- Line diffs are the result of different locations for input files; this cannot be fixed as cuffcompare outputs
+ full input path for each input. -->
+ <output name="transcripts_accuracy" file="cuffcompare_out7.txt" lines_diff="6"/><output name="input1_tmap" file="cuffcompare_out1.tmap"/><output name="input1_refmap" file="cuffcompare_out2.refmap"/><output name="input2_tmap" file="cuffcompare_out3.tmap"/><output name="input2_refmap" file="cuffcompare_out4.refmap"/>
- <output name="transcripts_accuracy" file="cuffcompare_out7.txt"/>
- -->
+ <output name="transcripts_combined" file="cuffcompare_out5.gtf"/>
+ <output name="transcripts_tracking" file="cuffcompare_out6.tracking"/></test></tests>
--- /dev/null
+++ b/test-data/cuffcompare_out4.refmap
@@ -0,0 +1,1 @@
+ref_gene_id ref_id class_code cuff_id_list
--- /dev/null
+++ b/test-data/cuffcompare_out3.tmap
@@ -0,0 +1,51 @@
+ref_gene_id ref_id class_code cuff_gene_id cuff_id FMI FPKM FPKM_conf_lo FPKM_conf_hi cov len major_iso_id
+- - u CUFF.1 CUFF.1.1 100 35.211287 0.000000 85.007567 2.000000 27 CUFF.1.1
+- - u CUFF.3 CUFF.3.1 100 35.211287 0.000000 85.007567 2.000000 27 CUFF.3.1
+- - u CUFF.5 CUFF.5.1 100 21.226627 0.000000 59.889707 1.205672 27 CUFF.5.1
+- - u CUFF.7 CUFF.7.1 100 29.709524 19.806349 39.612698 1.687500 576 CUFF.7.1
+- - u CUFF.9 CUFF.9.1 100 34.072933 23.364686 44.781179 1.935341 565 CUFF.9.1
+- - u CUFF.11 CUFF.11.1 100 32.531777 24.582998 40.480555 1.847804 979 CUFF.11.1
+- - u CUFF.13 CUFF.13.1 100 16.582060 0.000000 35.729373 0.941860 86 CUFF.13.1
+- - u CUFF.15 CUFF.15.1 100 35.211287 0.000000 85.007567 2.000000 27 CUFF.15.1
+- - u CUFF.17 CUFF.17.1 100 35.211287 0.000000 85.007567 2.000000 27 CUFF.17.1
+- - u CUFF.19 CUFF.19.1 100 35.211287 0.000000 85.007567 2.000000 27 CUFF.19.1
+- - u CUFF.21 CUFF.21.1 100 35.211287 0.000000 85.007567 2.000000 27 CUFF.21.1
+- - u CUFF.23 CUFF.23.1 100 16.205195 0.000000 34.917342 0.920455 88 CUFF.23.1
+- - u CUFF.25 CUFF.25.1 100 35.211287 0.000000 85.007567 2.000000 27 CUFF.25.1
+- - u CUFF.26 CUFF.26.1 100 29.709524 0.000000 71.725135 1.687500 32 CUFF.26.1
+- - u CUFF.29 CUFF.29.1 100 13.581496 0.000000 32.788633 0.771429 70 CUFF.29.1
+- - u CUFF.31 CUFF.31.1 100 22.635827 0.000000 45.271655 1.285714 84 CUFF.31.1
+Xkr4 Xkr4 i CUFF.33 CUFF.33.1 100 23.767619 0.000000 57.380108 1.350000 40 CUFF.33.1
+Xkr4 Xkr4 i CUFF.35 CUFF.35.1 100 11.317914 0.000000 27.323861 0.642857 84 CUFF.35.1
+Xkr4 Xkr4 i CUFF.37 CUFF.37.1 100 11.500461 0.000000 24.780049 0.653226 124 CUFF.37.1
+Xkr4 Xkr4 i CUFF.39 CUFF.39.1 100 52.816931 0.000000 113.804669 3.000000 27 CUFF.39.1
+Xkr4 Xkr4 i CUFF.41 CUFF.41.1 100 43.213852 0.000000 93.112911 2.454545 33 CUFF.41.1
+Xkr4 Xkr4 i CUFF.43 CUFF.43.1 100 23.474191 0.000000 46.948383 1.333333 81 CUFF.43.1
+Xkr4 Xkr4 i CUFF.45 CUFF.45.1 100 20.667495 0.000000 49.895746 1.173913 46 CUFF.45.1
+Xkr4 Xkr4 i CUFF.47 CUFF.47.1 100 35.211287 0.000000 85.007567 2.000000 27 CUFF.47.1
+Xkr4 Xkr4 i CUFF.49 CUFF.49.1 100 35.211287 0.000000 85.007567 2.000000 27 CUFF.49.1
+Xkr4 Xkr4 i CUFF.51 CUFF.51.1 100 14.948188 7.228977 22.667399 0.849057 477 CUFF.51.1
+Xkr4 Xkr4 i CUFF.53 CUFF.53.1 100 52.816931 0.000000 113.804669 3.000000 27 CUFF.53.1
+Xkr4 Xkr4 i CUFF.55 CUFF.55.1 100 35.211287 0.000000 85.007567 2.000000 27 CUFF.55.1
+Xkr4 Xkr4 i CUFF.57 CUFF.57.1 100 35.211287 0.000000 85.007567 2.000000 27 CUFF.57.1
+Xkr4 Xkr4 i CUFF.59 CUFF.59.1 100 35.211287 0.000000 85.007567 2.000000 27 CUFF.59.1
+Xkr4 Xkr4 i CUFF.61 CUFF.61.1 100 13.204233 0.000000 31.877838 0.750000 72 CUFF.61.1
+Xkr4 Xkr4 i CUFF.63 CUFF.63.1 100 35.211287 0.000000 85.007567 2.000000 27 CUFF.63.1
+Xkr4 Xkr4 i CUFF.65 CUFF.65.1 100 31.170648 0.000000 62.341295 1.770492 61 CUFF.65.1
+Xkr4 Xkr4 i CUFF.67 CUFF.67.1 100 15.681351 3.378764 27.983938 0.890700 197 CUFF.67.1
+Xkr4 Xkr4 i CUFF.69 CUFF.69.1 100 18.799247 8.750627 28.847866 1.067797 354 CUFF.69.1
+Xkr4 Xkr4 i CUFF.71 CUFF.71.1 100 22.635827 0.000000 54.647722 1.285714 42 CUFF.71.1
+Xkr4 Xkr4 i CUFF.73 CUFF.73.1 100 35.211287 0.000000 85.007567 2.000000 27 CUFF.73.1
+Xkr4 Xkr4 i CUFF.75 CUFF.75.1 100 52.816931 0.000000 113.804669 3.000000 27 CUFF.75.1
+Xkr4 Xkr4 i CUFF.77 CUFF.77.1 100 17.605644 0.000000 52.816931 1.000000 27 CUFF.77.1
+Xkr4 Xkr4 i CUFF.79 CUFF.79.1 100 13.390208 0.000000 32.326821 0.760563 71 CUFF.79.1
+Xkr4 Xkr4 i CUFF.81 CUFF.81.1 100 11.211141 1.183592 21.238690 0.636792 212 CUFF.81.1
+Xkr4 Xkr4 i CUFF.83 CUFF.83.1 100 21.126772 0.000000 51.004540 1.200000 45 CUFF.83.1
+Xkr4 Xkr4 i CUFF.85 CUFF.85.1 100 19.014095 0.000000 38.028190 1.080000 100 CUFF.85.1
+Xkr4 Xkr4 i CUFF.87 CUFF.87.1 100 24.170460 0.000000 52.080103 1.372881 59 CUFF.87.1
+Xkr4 Xkr4 i CUFF.89 CUFF.89.1 100 29.709524 0.000000 64.015126 1.687500 48 CUFF.89.1
+Xkr4 Xkr4 i CUFF.91 CUFF.91.1 100 35.211287 0.000000 85.007567 2.000000 27 CUFF.91.1
+Xkr4 Xkr4 i CUFF.93 CUFF.93.1 100 35.211287 0.000000 85.007567 2.000000 27 CUFF.93.1
+Xkr4 Xkr4 i CUFF.95 CUFF.95.1 100 35.211287 0.000000 85.007567 2.000000 27 CUFF.95.1
+Xkr4 Xkr4 i CUFF.97 CUFF.97.1 100 35.211287 0.000000 85.007567 2.000000 27 CUFF.97.1
+Xkr4 Xkr4 i CUFF.99 CUFF.99.1 100 19.602160 0.000000 39.204320 1.113402 97 CUFF.99.1
--- /dev/null
+++ b/test-data/cuffcompare_out7.txt
@@ -0,0 +1,50 @@
+# Cuffcompare v0.9.1 | Command line was:
+#cuffcompare -r cuffcompare_in3.gtf -R cuffcompare_in1.gtf cuffcompare_in2.gtf
+#
+#> Genomic sequence: chr1
+# Query mRNAs : 50 in 50 loci (0 multi-exon transcripts)
+# (0 multi-transcript loci, ~1.0 transcripts per locus)
+# Reference mRNAs : 1 in 1 loci (1 multi-exon)
+# Corresponding super-loci: 1
+#--------------------| Sn | Sp | fSn | fSp
+ Base level: 2.2 2.3 - -
+ Exon level: 0.0 0.0 0.0 0.0
+ Intron level: 0.0 nan 0.0 100.0
+Intron chain level: 0.0 100.0 0.0 100.0
+ Transcript level: 0.0 0.0 0.0 0.0
+ Locus level: 0.0 0.0 0.0 0.0
+ Missed exons: 2/3 ( 66.7%)
+ Wrong exons: 49/50 ( 98.0%)
+ Missed introns: 2/2 (100.0%)
+ Missed loci: 0/1 ( 0.0%)
+ Wrong loci: 49/50 ( 98.0%)
+
+#= Summary for dataset: cuffcompare_in1.gtf :
+# Query mRNAs : 50 in 50 loci (0 multi-exon transcripts)
+# (0 multi-transcript loci, ~1.0 transcripts per locus)
+# Reference mRNAs : 1 in 1 loci (1 multi-exon)
+# Corresponding super-loci: 1
+#--------------------| Sn | Sp | fSn | fSp
+ Base level: 2.2 2.3 - -
+ Exon level: 0.0 0.0 0.0 0.0
+ Intron level: 0.0 nan 0.0 100.0
+Intron chain level: 0.0 100.0 0.0 100.0
+ Transcript level: 0.0 0.0 0.0 0.0
+ Locus level: 0.0 0.0 0.0 0.0
+ Missed exons: 2/3 ( 66.7%)
+ Wrong exons: 49/50 ( 98.0%)
+ Missed introns: 2/2 (100.0%)
+ Missed loci: 0/1 ( 0.0%)
+ Wrong loci: 49/50 ( 98.0%)
+#> Genomic sequence: chr1
+# Query mRNAs : 50 in 50 loci (0 multi-exon transcripts)
+# (0 multi-transcript loci, ~1.0 transcripts per locus)
+# Reference mRNAs : 0 in 0 loci (0 multi-exon)
+
+#= Summary for dataset: cuffcompare_in2.gtf :
+# Query mRNAs : 50 in 50 loci (0 multi-exon transcripts)
+# (0 multi-transcript loci, ~1.0 transcripts per locus)
+# Reference mRNAs : 0 in 0 loci (0 multi-exon)
+
+ Total union super-loci across all input datasets: 87
+ (0 multi-transcript, ~1.1 transcripts per locus)
1
0

galaxy-dist commit 262c91e3a2ea: Fix 'Select All' button in tool form due to a typo. Values next to checkboxes can now be clicked to check the corresponding box.
by commits-noreply@bitbucket.org 20 Nov '10
by commits-noreply@bitbucket.org 20 Nov '10
20 Nov '10
# HG changeset patch -- Bitbucket.org
# Project galaxy-dist
# URL http://bitbucket.org/galaxy/galaxy-dist/overview
# User Kanwei Li <kanwei(a)gmail.com>
# Date 1288117861 14400
# Node ID 262c91e3a2ea7d11d65875ec2af42526c92b7123
# Parent bdcbd7ab6e7fe0a6ed869d8a682660c0cebb7658
Fix 'Select All' button in tool form due to a typo. Values next to checkboxes can now be clicked to check the corresponding box.
--- a/static/june_2007_style/blue/base.css
+++ b/static/june_2007_style/blue/base.css
@@ -41,6 +41,7 @@ div.form-row-error{background:#FFCCCC;}
div.form-row label{font-weight:bold;display:block;margin-bottom:.2em;}
div.form-row-input{float:left;width:300px;}
div.form-row-input > input{max-width:300px;}
+div.form-row-input label{font-weight:normal;display:inline;}
div.form-row-error-message{width:300px;float:left;color:red;font-weight:bold;padding:3px 0 0 1em;}
select,input,textarea{font:inherit;font-size:115%;}
select,textarea,input[type="text"],input[type="file"],input[type="password"]{-webkit-box-sizing:border-box;max-width:300px;}
--- a/templates/tool_form.mako
+++ b/templates/tool_form.mako
@@ -24,7 +24,7 @@ from galaxy.util.expressions import Expr
file.attr( { name: 'replaced_file_input_' + file_name, disabled: true } );
// create a new hidden field which stores the filename and has the original name of the file input
var new_file_input = $(document.createElement('input'));
- new_file_input.attr( { "type", "hidden", "value": file_value, "name": file_name } );
+ new_file_input.attr( { "type": "hidden", "value": file_value, "name": file_name } );
file.after(new_file_input);
}
});
@@ -36,14 +36,10 @@ from galaxy.util.expressions import Expr
location.replace( '${h.url_for( controller='root', action='index', tool_id=tool.id )}' );
}
%endif
-function checkUncheckAll( name, check )
-{
- if ( check == 0 )
- {
+function checkUncheckAll( name, check ) {
+ if (!check) {
$("input[name=" + name + "][type='checkbox']").attr('checked', false);
- }
- else
- {
+ } else {
$("input[name=" + name + "][type='checkbox']").attr('checked', true );
}
}
@@ -260,7 +256,7 @@ function checkUncheckAll( name, check )
##inserts the Select All / Unselect All buttons for checkboxes
$( function() {
$("div.checkUncheckAllPlaceholder").each( function( i ) {
- $( this )[0].innerHTML = '<a class="action-button" onclick="checkUncheckAll( \'' + this.attributes.getNamedItem( 'checkbox_name' ).value + '\', 1 );"><span>Select All</span></a><a class="action-button" onclick="checkUncheckAll( \'' + this.attributes.getNamedItem( 'checkbox_name' ).value + '\', 0 );"><span>Unselect All</span></a>';
+ $( this )[0].innerHTML = '<a class="action-button" onclick="checkUncheckAll( \'' + this.attributes.getNamedItem( 'checkbox_name' ).value + '\', true );"><span>Select All</span></a><a class="action-button" onclick="checkUncheckAll( \'' + this.attributes.getNamedItem( 'checkbox_name' ).value + '\', false );"><span>Unselect All</span></a>';
});
});
--- a/lib/galaxy/web/form_builder.py
+++ b/lib/galaxy/web/form_builder.py
@@ -231,14 +231,14 @@ class SelectField(BaseField):
rval.append ( '<div class="checkUncheckAllPlaceholder" checkbox_name="%s%s"></div>' % ( prefix, self.name ) ) #placeholder for the insertion of the Select All/Unselect All buttons
for text, value, selected in self.options:
style = ""
+ escaped_value = escape( str( value ), quote=True )
if len(self.options) > 2 and ctr % 2 == 1:
style = " class=\"odd_row\""
+ selected_text = ""
if selected:
- rval.append( '<div%s><input type="checkbox" name="%s%s" value="%s" checked%s>%s</div>' % \
- ( style, prefix, self.name, escape( str( value ), quote=True ), self.get_disabled_str( disabled ), text ) )
- else:
- rval.append( '<div%s><input type="checkbox" name="%s%s" value="%s"%s>%s</div>' % \
- ( style, prefix, self.name, escape( str( value ), quote=True ), self.get_disabled_str( disabled ), text ) )
+ selected_text = "checked='checked'"
+ rval.append( '<div%s><input type="checkbox" name="%s%s" value="%s" id="%s" %s%s><label for="%s">%s</label></div>' % \
+ ( style, prefix, self.name, escaped_value, escaped_value, selected_text, self.get_disabled_str( disabled ), escaped_value, text ) )
ctr += 1
return "\n".join( rval )
def get_html_radio( self, prefix="", disabled=False ):
--- a/static/june_2007_style/base.css.tmpl
+++ b/static/june_2007_style/base.css.tmpl
@@ -219,6 +219,11 @@ div.form-row-input > input {
max-width: 300px;
}
+div.form-row-input label {
+ font-weight: normal;
+ display: inline;
+}
+
div.form-row-error-message {
width: 300px;
float: left;
1
0

galaxy-dist commit 141e7055d2c6: Update to Cufflinks tool suite: (a) better path joining; (b) update test data for cufflinks so that functional tests pass for v0.9.1; (c) add extensions to cuffcompare wrapper temporary inputs to fix #404.
by commits-noreply@bitbucket.org 20 Nov '10
by commits-noreply@bitbucket.org 20 Nov '10
20 Nov '10
# HG changeset patch -- Bitbucket.org
# Project galaxy-dist
# URL http://bitbucket.org/galaxy/galaxy-dist/overview
# User jeremy goecks <jeremy.goecks(a)emory.edu>
# Date 1288019385 14400
# Node ID 141e7055d2c633afee5262932adb1896ad0f937e
# Parent 7114d0f8d487536853cf25cf30bb86636bf0b24c
Update to Cufflinks tool suite: (a) better path joining; (b) update test data for cufflinks so that functional tests pass for v0.9.1; (c) add extensions to cuffcompare wrapper temporary inputs to fix #404.
--- a/test-data/cufflinks_out3.expr
+++ b/test-data/cufflinks_out3.expr
@@ -1,2 +1,2 @@
-gene_id bundle_id chr left right FPKM FPKM_conf_lo FPKM_conf_hi
-CUFF.1 6 test_chromosome 52 550 3.3557e+06 2.6976e+06 4.01381e+06
+gene_id bundle_id chr left right FPKM FPKM_conf_lo FPKM_conf_hi status
+CUFF.1 3 test_chromosome 52 550 4.46429e+06 4.46006e+06 4.46851e+06 OK
--- a/tools/ngs_rna/cuffcompare_wrapper.py
+++ b/tools/ngs_rna/cuffcompare_wrapper.py
@@ -42,13 +42,15 @@ def __main__():
# Add input files.
- # Need to symlink inputs so that output files are written to temp directory.
- input1_file_name = tmp_output_dir + "/input1"
+ # Need to symlink inputs so that output files are written to temp directory.
+ # Also need an extension for input file names so that cuffcompare produces
+ # output files properly.
+ input1_file_name = os.path.join( tmp_output_dir, "input1.gtf" )
os.symlink( options.input1, input1_file_name )
cmd += " %s" % input1_file_name
two_inputs = ( options.input2 != None)
if two_inputs:
- input2_file_name = tmp_output_dir + "/input2"
+ input2_file_name = os.path.join( tmp_output_dir, "input2.gtf" )
os.symlink( options.input2, input2_file_name )
cmd += " %s" % input2_file_name
@@ -78,7 +80,8 @@ def __main__():
raise Exception, stderr
# check that there are results in the output file
- if len( open( tmp_output_dir + "/cc_output", 'rb' ).read().strip() ) == 0:
+ cc_output_fname = os.path.join( tmp_output_dir, "cc_output")
+ if len( open( cc_output_fname, 'rb' ).read().strip() ) == 0:
raise Exception, 'The main output file is empty, there may be an error with your input file or settings.'
except Exception, e:
stop_err( 'Error running cuffcompare. ' + str( e ) )
@@ -86,14 +89,14 @@ def __main__():
# Copy output files from tmp directory to specified files.
try:
try:
- shutil.copyfile( tmp_output_dir + "/cc_output", options.transcripts_accuracy_output_file )
- shutil.copyfile( tmp_output_dir + "/input1.tmap", options.input1_tmap_output_file )
- shutil.copyfile( tmp_output_dir + "/input1.refmap", options.input1_refmap_output_file )
+ shutil.copyfile( os.path.join( tmp_output_dir, "cc_output" ), options.transcripts_accuracy_output_file )
+ shutil.copyfile( os.path.join( tmp_output_dir, "input1.tmap" ), options.input1_tmap_output_file )
+ shutil.copyfile( os.path.join( tmp_output_dir, "input1.refmap" ), options.input1_refmap_output_file )
if two_inputs:
- shutil.copyfile( tmp_output_dir + "/cc_output.combined.gtf", options.transcripts_combined_output_file )
- shutil.copyfile( tmp_output_dir + "/cc_output.tracking", options.transcripts_tracking_output_file )
- shutil.copyfile( tmp_output_dir + "/input2.tmap", options.input2_tmap_output_file )
- shutil.copyfile( tmp_output_dir + "/input2.refmap", options.input2_refmap_output_file )
+ shutil.copyfile( os.path.join( tmp_output_dir, "cc_output.combined.gtf" ), options.transcripts_combined_output_file )
+ shutil.copyfile( os.path.join( tmp_output_dir, "cc_output.tracking" ), options.transcripts_tracking_output_file )
+ shutil.copyfile( os.path.join( tmp_output_dir, "input2.tmap" ), options.input2_tmap_output_file )
+ shutil.copyfile( os.path.join( tmp_output_dir, "input2.refmap" ), options.input2_refmap_output_file )
except Exception, e:
stop_err( 'Error in cuffcompare:\n' + str( e ) )
finally:
--- a/test-data/cufflinks_out1.gtf
+++ b/test-data/cufflinks_out1.gtf
@@ -1,4 +1,4 @@
-test_chromosome Cufflinks transcript 53 550 1000 + . gene_id "CUFF.1"; transcript_id "CUFF.1.1"; FPKM "3355704.6979865772"; frac "1.000000"; conf_lo "2697596.861952"; conf_hi "4013812.534021"; cov "46.057047";
-test_chromosome Cufflinks exon 53 250 1000 + . gene_id "CUFF.1"; transcript_id "CUFF.1.1"; exon_number "1"; FPKM "3355704.6979865772"; frac "1.000000"; conf_lo "2697596.861952"; conf_hi "4013812.534021"; cov "46.057047";
-test_chromosome Cufflinks exon 351 400 1000 + . gene_id "CUFF.1"; transcript_id "CUFF.1.1"; exon_number "2"; FPKM "3355704.6979865772"; frac "1.000000"; conf_lo "2697596.861952"; conf_hi "4013812.534021"; cov "46.057047";
-test_chromosome Cufflinks exon 501 550 1000 + . gene_id "CUFF.1"; transcript_id "CUFF.1.1"; exon_number "3"; FPKM "3355704.6979865772"; frac "1.000000"; conf_lo "2697596.861952"; conf_hi "4013812.534021"; cov "46.057047";
+test_chromosome Cufflinks transcript 53 550 1000 + . gene_id "CUFF.1"; transcript_id "CUFF.1.1"; FPKM "4464285.7142857295"; frac "1.000000"; conf_lo "4460059.943012"; conf_hi "4468511.485559"; cov "61.272321";
+test_chromosome Cufflinks exon 53 250 1000 + . gene_id "CUFF.1"; transcript_id "CUFF.1.1"; exon_number "1"; FPKM "4464285.7142857295"; frac "1.000000"; conf_lo "4460059.943012"; conf_hi "4468511.485559"; cov "61.272321";
+test_chromosome Cufflinks exon 351 400 1000 + . gene_id "CUFF.1"; transcript_id "CUFF.1.1"; exon_number "2"; FPKM "4464285.7142857295"; frac "1.000000"; conf_lo "4460059.943012"; conf_hi "4468511.485559"; cov "61.272321";
+test_chromosome Cufflinks exon 501 550 1000 + . gene_id "CUFF.1"; transcript_id "CUFF.1.1"; exon_number "3"; FPKM "4464285.7142857295"; frac "1.000000"; conf_lo "4460059.943012"; conf_hi "4468511.485559"; cov "61.272321";
--- a/tools/ngs_rna/cuffdiff_wrapper.py
+++ b/tools/ngs_rna/cuffdiff_wrapper.py
@@ -98,7 +98,7 @@ def __main__():
raise Exception, stderr
# check that there are results in the output file
- if len( open( tmp_output_dir + "/isoforms.fpkm_tracking", 'rb' ).read().strip() ) == 0:
+ if len( open( os.path.join( tmp_output_dir, "isoforms.fpkm_tracking" ), 'rb' ).read().strip() ) == 0:
raise Exception, 'The main output file is empty, there may be an error with your input file or settings.'
except Exception, e:
stop_err( 'Error running cuffdiff. ' + str( e ) )
@@ -107,17 +107,17 @@ def __main__():
# Copy output files from tmp directory to specified files.
try:
try:
- shutil.copyfile( tmp_output_dir + "/isoforms.fpkm_tracking", options.isoforms_fpkm_tracking_output )
- shutil.copyfile( tmp_output_dir + "/genes.fpkm_tracking", options.genes_fpkm_tracking_output )
- shutil.copyfile( tmp_output_dir + "/cds.fpkm_tracking", options.cds_fpkm_tracking_output )
- shutil.copyfile( tmp_output_dir + "/tss_groups.fpkm_tracking", options.tss_groups_fpkm_tracking_output )
- shutil.copyfile( tmp_output_dir + "/0_1_isoform_exp.diff", options.isoforms_exp_output )
- shutil.copyfile( tmp_output_dir + "/0_1_gene_exp.diff", options.genes_exp_output )
- shutil.copyfile( tmp_output_dir + "/0_1_tss_group_exp.diff", options.tss_groups_exp_output )
- shutil.copyfile( tmp_output_dir + "/0_1_splicing.diff", options.splicing_diff_output )
- shutil.copyfile( tmp_output_dir + "/0_1_cds.diff", options.cds_diff_output )
- shutil.copyfile( tmp_output_dir + "/0_1_cds_exp.diff", options.cds_diff_output )
- shutil.copyfile( tmp_output_dir + "/0_1_promoters.diff", options.promoters_diff_output )
+ shutil.copyfile( os.path.join( tmp_output_dir, "isoforms.fpkm_tracking" ), options.isoforms_fpkm_tracking_output )
+ shutil.copyfile( os.path.join( tmp_output_dir, "genes.fpkm_tracking" ), options.genes_fpkm_tracking_output )
+ shutil.copyfile( os.path.join( tmp_output_dir, "cds.fpkm_tracking" ), options.cds_fpkm_tracking_output )
+ shutil.copyfile( os.path.join( tmp_output_dir, "tss_groups.fpkm_tracking" ), options.tss_groups_fpkm_tracking_output )
+ shutil.copyfile( os.path.join( tmp_output_dir, "0_1_isoform_exp.diff" ), options.isoforms_exp_output )
+ shutil.copyfile( os.path.join( tmp_output_dir, "0_1_gene_exp.diff" ), options.genes_exp_output )
+ shutil.copyfile( os.path.join( tmp_output_dir, "0_1_tss_group_exp.diff" ), options.tss_groups_exp_output )
+ shutil.copyfile( os.path.join( tmp_output_dir, "0_1_splicing.diff" ), options.splicing_diff_output )
+ shutil.copyfile( os.path.join( tmp_output_dir, "0_1_cds.diff" ), options.cds_diff_output )
+ shutil.copyfile( os.path.join( tmp_output_dir, "0_1_cds_exp.diff" ), options.cds_diff_output )
+ shutil.copyfile( os.path.join( tmp_output_dir, "0_1_promoters.diff" ), options.promoters_diff_output )
except Exception, e:
stop_err( 'Error in cuffdiff:\n' + str( e ) )
finally:
--- a/test-data/cufflinks_out2.expr
+++ b/test-data/cufflinks_out2.expr
@@ -1,2 +1,2 @@
-trans_id bundle_id chr left right FPKM FMI frac FPKM_conf_lo FPKM_conf_hi coverage length
-CUFF.1.1 6 test_chromosome 52 550 3.3557e+06 1 1 2.6976e+06 4.01381e+06 46.057 298
+trans_id bundle_id chr left right FPKM FMI frac FPKM_conf_lo FPKM_conf_hi coverage length effective_length status
+CUFF.1.1 3 test_chromosome 52 550 4.46429e+06 1 1 4.46006e+06 4.46851e+06 61.2723 298 224 OK
--- a/tools/ngs_rna/cufflinks_wrapper.py
+++ b/tools/ngs_rna/cufflinks_wrapper.py
@@ -91,7 +91,7 @@ def __main__():
raise Exception, stderr
# check that there are results in the output file
- if len( open( tmp_output_dir + "/transcripts.gtf", 'rb' ).read().strip() ) == 0:
+ if len( open( os.path.join( tmp_output_dir, "transcripts.gtf" ), 'rb' ).read().strip() ) == 0:
raise Exception, 'The main output file is empty, there may be an error with your input file or settings.'
except Exception, e:
stop_err( 'Error running cufflinks. ' + str( e ) )
@@ -99,9 +99,9 @@ def __main__():
# Copy output files from tmp directory to specified files.
try:
try:
- shutil.copyfile( tmp_output_dir + "/transcripts.gtf", options.assembled_isoforms_output_file )
- shutil.copyfile( tmp_output_dir + "/transcripts.expr", options.transcripts_expression_output_file )
- shutil.copyfile( tmp_output_dir + "/genes.expr", options.genes_expression_output_file )
+ shutil.copyfile( os.path.join( tmp_output_dir, "transcripts.gtf" ), options.assembled_isoforms_output_file )
+ shutil.copyfile( os.path.join( tmp_output_dir, "transcripts.expr" ), options.transcripts_expression_output_file )
+ shutil.copyfile( os.path.join( tmp_output_dir, "genes.expr" ), options.genes_expression_output_file )
except Exception, e:
stop_err( 'Error in tophat:\n' + str( e ) )
finally:
1
0

galaxy-dist commit aaacde471f03: When converting from GFF to BED, make all BED features with thick blocks.
by commits-noreply@bitbucket.org 20 Nov '10
by commits-noreply@bitbucket.org 20 Nov '10
20 Nov '10
# HG changeset patch -- Bitbucket.org
# Project galaxy-dist
# URL http://bitbucket.org/galaxy/galaxy-dist/overview
# User jeremy goecks <jeremy.goecks(a)emory.edu>
# Date 1288027566 14400
# Node ID aaacde471f036ea236155b9786e095382b391a9f
# Parent 141e7055d2c633afee5262932adb1896ad0f937e
When converting from GFF to BED, make all BED features with thick blocks.
--- a/tools/filters/gff_to_bed_converter.py
+++ b/tools/filters/gff_to_bed_converter.py
@@ -41,8 +41,12 @@ def get_bed_line( chrom, name, strand, b
# Bed format: chrom, chromStart, chromEnd, name, score, strand, \
# thickStart, thickEnd, itemRgb, blockCount, blockSizes, blockStarts
#
+ # Render complete feature with thick blocks. There's no clear way to do this unless
+ # we analyze the block names, but making everything thick makes more sense than
+ # making everything thin.
+ #
return "%s\t%i\t%i\t%s\t0\t%s\t%i\t%i\t0\t%i\t%s\t%s\n" % \
- ( chrom, t_start, t_end, name, strand, t_start, t_start, len( block_starts ),
+ ( chrom, t_start, t_end, name, strand, t_start, t_end, len( block_starts ),
",".join( block_sizes ), ",".join( block_starts ) )
def __main__():
1
0

galaxy-dist commit 30f83bcaf314: Only read the first 32K of stdout/stderr from jobs since that's all we're saving anyway. fileobj.read() is bad for the job runner when a tool prints 60GB of errors...
by commits-noreply@bitbucket.org 20 Nov '10
by commits-noreply@bitbucket.org 20 Nov '10
20 Nov '10
# HG changeset patch -- Bitbucket.org
# Project galaxy-dist
# URL http://bitbucket.org/galaxy/galaxy-dist/overview
# User Nate Coraor <nate(a)bx.psu.edu>
# Date 1288037514 14400
# Node ID 30f83bcaf31451915ccf68c398a8e0ce0a3c80bb
# Parent 5ee2200b2b6df5cbd31f21440124c7ae0bcbe10b
Only read the first 32K of stdout/stderr from jobs since that's all we're saving anyway. fileobj.read() is bad for the job runner when a tool prints 60GB of errors...
--- a/lib/galaxy/jobs/runners/sge.py
+++ b/lib/galaxy/jobs/runners/sge.py
@@ -312,8 +312,8 @@ class SGEJobRunner( object ):
try:
ofh = file(ofile, "r")
efh = file(efile, "r")
- stdout = ofh.read()
- stderr = efh.read()
+ stdout = ofh.read( 32768 )
+ stderr = efh.read( 32768 )
except:
stdout = ''
stderr = 'Job output not returned from cluster'
--- a/lib/galaxy/jobs/runners/pbs.py
+++ b/lib/galaxy/jobs/runners/pbs.py
@@ -496,8 +496,8 @@ class PBSJobRunner( object ):
try:
ofh = file(ofile, "r")
efh = file(efile, "r")
- stdout = ofh.read()
- stderr = efh.read()
+ stdout = ofh.read( 32768 )
+ stderr = efh.read( 32768 )
except:
stdout = ''
stderr = 'Job output not returned by PBS: the output datasets were deleted while the job was running, the job was manually dequeued or there was a cluster error.'
--- a/lib/galaxy/jobs/runners/local.py
+++ b/lib/galaxy/jobs/runners/local.py
@@ -95,8 +95,8 @@ class LocalJobRunner( object ):
if sleep_time < 8:
# So we don't stat every second
sleep_time *= 2
- stdout = proc.stdout.read()
- stderr = proc.stderr.read()
+ stdout = proc.stdout.read( 32768 )
+ stderr = proc.stderr.read( 32768 )
proc.wait() # reap
log.debug('execution finished: %s' % command_line)
except Exception, exc:
--- a/lib/galaxy/jobs/runners/drmaa.py
+++ b/lib/galaxy/jobs/runners/drmaa.py
@@ -272,8 +272,8 @@ class DRMAAJobRunner( object ):
try:
ofh = file(ofile, "r")
efh = file(efile, "r")
- stdout = ofh.read()
- stderr = efh.read()
+ stdout = ofh.read( 32768 )
+ stderr = efh.read( 32768 )
except:
stdout = ''
stderr = 'Job output not returned from cluster'
1
0

galaxy-dist commit 5ee2200b2b6d: "Fix" zip uploads for Python < 2.6. The scare quotes are because in Python < 2.6 you can't read a zip member without loading the entire member into memory...
by commits-noreply@bitbucket.org 20 Nov '10
by commits-noreply@bitbucket.org 20 Nov '10
20 Nov '10
# HG changeset patch -- Bitbucket.org
# Project galaxy-dist
# URL http://bitbucket.org/galaxy/galaxy-dist/overview
# User Nate Coraor <nate(a)bx.psu.edu>
# Date 1288037409 14400
# Node ID 5ee2200b2b6df5cbd31f21440124c7ae0bcbe10b
# Parent aaacde471f036ea236155b9786e095382b391a9f
"Fix" zip uploads for Python < 2.6. The scare quotes are because in Python < 2.6 you can't read a zip member without loading the entire member into memory...
--- a/tools/data_source/upload.py
+++ b/tools/data_source/upload.py
@@ -270,22 +270,36 @@ def add_file( dataset, registry, json_fi
stdout = 'ZIP file contained more than one file, only the first file was added to Galaxy.'
break
fd, uncompressed = tempfile.mkstemp( prefix='data_id_%s_upload_zip_' % dataset.dataset_id, dir=os.path.dirname( dataset.path ), text=False )
- zipped_file = z.open( name )
- while 1:
+ if sys.version_info[:2] >= ( 2, 6 ):
+ zipped_file = z.open( name )
+ while 1:
+ try:
+ chunk = zipped_file.read( CHUNK_SIZE )
+ except IOError:
+ os.close( fd )
+ os.remove( uncompressed )
+ file_err( 'Problem decompressing zipped data', dataset, json_file )
+ return
+ if not chunk:
+ break
+ os.write( fd, chunk )
+ os.close( fd )
+ zipped_file.close()
+ uncompressed_name = name
+ unzipped = True
+ else:
+ # python < 2.5 doesn't have a way to read members in chunks(!)
try:
- chunk = zipped_file.read( CHUNK_SIZE )
+ outfile = open( uncompressed, 'wb' )
+ outfile.write( z.read( name ) )
+ outfile.close()
+ uncompressed_name = name
+ unzipped = True
except IOError:
os.close( fd )
os.remove( uncompressed )
file_err( 'Problem decompressing zipped data', dataset, json_file )
return
- if not chunk:
- break
- os.write( fd, chunk )
- os.close( fd )
- zipped_file.close()
- uncompressed_name = name
- unzipped = True
z.close()
# Replace the zipped file with the decompressed file
if uncompressed is not None:
1
0

galaxy-dist commit 7114d0f8d487: Fix for a bug I introduced in NoseHTML changes.
by commits-noreply@bitbucket.org 20 Nov '10
by commits-noreply@bitbucket.org 20 Nov '10
20 Nov '10
# HG changeset patch -- Bitbucket.org
# Project galaxy-dist
# URL http://bitbucket.org/galaxy/galaxy-dist/overview
# User Nate Coraor <nate(a)bx.psu.edu>
# Date 1287858470 14400
# Node ID 7114d0f8d487536853cf25cf30bb86636bf0b24c
# Parent bb93b5da724b8f0420ed5cb2371075b08947d0db
Fix for a bug I introduced in NoseHTML changes.
--- a/eggs.ini
+++ b/eggs.ini
@@ -38,7 +38,7 @@ GeneTrack = 2.0.0_beta_1
lrucache = 0.2
Mako = 0.2.5
nose = 0.11.1
-NoseHTML = 0.4
+NoseHTML = 0.4.1
NoseTestDiff = 0.1
Paste = 1.6
PasteDeploy = 1.3.3
1
0

galaxy-dist commit bb93b5da724b: Added a simple plugin for Nose that shows a diff-style output of failed tests,
by commits-noreply@bitbucket.org 20 Nov '10
by commits-noreply@bitbucket.org 20 Nov '10
20 Nov '10
# HG changeset patch -- Bitbucket.org
# Project galaxy-dist
# URL http://bitbucket.org/galaxy/galaxy-dist/overview
# User Nate Coraor <nate(a)bx.psu.edu>
# Date 1287806338 14400
# Node ID bb93b5da724b8f0420ed5cb2371075b08947d0db
# Parent 6ce4e430b6a0d69e6397ca96a01350401ae05d20
Added a simple plugin for Nose that shows a diff-style output of failed tests,
and added an error-only file to the Nose HTML plugin. This should make
buildbot more useful.
--- a/eggs.ini
+++ b/eggs.ini
@@ -38,7 +38,8 @@ GeneTrack = 2.0.0_beta_1
lrucache = 0.2
Mako = 0.2.5
nose = 0.11.1
-NoseHTML = 0.3.1
+NoseHTML = 0.4
+NoseTestDiff = 0.1
Paste = 1.6
PasteDeploy = 1.3.3
PasteScript = 1.7.3
--- a/scripts/functional_tests.py
+++ b/scripts/functional_tests.py
@@ -12,6 +12,7 @@ from galaxy import eggs
eggs.require( "nose" )
eggs.require( "NoseHTML" )
+eggs.require( "NoseTestDiff" )
eggs.require( "twill==0.9" )
eggs.require( "Paste" )
eggs.require( "PasteDeploy" )
1
0

galaxy-dist commit 9e27a8ad881d: trackster: Fix shared visualizations
by commits-noreply@bitbucket.org 20 Nov '10
by commits-noreply@bitbucket.org 20 Nov '10
20 Nov '10
# HG changeset patch -- Bitbucket.org
# Project galaxy-dist
# URL http://bitbucket.org/galaxy/galaxy-dist/overview
# User Kanwei Li <kanwei(a)gmail.com>
# Date 1288046966 14400
# Node ID 9e27a8ad881dc4451add6d518468a73dbc9028bc
# Parent 30f83bcaf31451915ccf68c398a8e0ce0a3c80bb
trackster: Fix shared visualizations
- Add excanvas support for IE <9 to trackster, but performance is bad
- Refactor unused/duplicate init code for trackster
- Fix IE workflow bug with Input Datasets
- Fix IE search button displaying twice
--- a/templates/workflow/editor.mako
+++ b/templates/workflow/editor.mako
@@ -563,7 +563,7 @@
data.push( { name: '_', value: "true" } );
}
}).each( function() {
- form = this;
+ var form = this;
$(this).find( "select[refresh_on_change='true']").change( function() {
$(form).submit();
});
--- a/static/scripts/packed/trackster.js
+++ b/static/scripts/packed/trackster.js
@@ -1,1 +1,1 @@
-var DENSITY=200,FEATURE_LEVELS=10,MAX_FEATURE_DEPTH=50,CONNECTOR_COLOR="#ccc",DATA_ERROR="There was an error in indexing this dataset.",DATA_NOCONVERTER="A converter for this dataset is not installed. Please check your datatypes_conf.xml file.",DATA_NONE="No data for this chrom/contig.",DATA_PENDING="Currently indexing... please wait",DATA_LOADING="Loading data...",FILTERABLE_CLASS="filterable",CACHED_TILES_FEATURE=10,CACHED_TILES_LINE=30,CACHED_DATA=5,CONTEXT=$("<canvas></canvas>").get(0).getContext("2d"),PX_PER_CHAR=CONTEXT.measureText("A").width,RIGHT_STRAND,LEFT_STRAND;var right_img=new Image();right_img.src=image_path+"/visualization/strand_right.png";right_img.onload=function(){RIGHT_STRAND=CONTEXT.createPattern(right_img,"repeat")};var left_img=new Image();left_img.src=image_path+"/visualization/strand_left.png";left_img.onload=function(){LEFT_STRAND=CONTEXT.createPattern(left_img,"repeat")};var right_img_inv=new Image();right_img_inv.src=image_path+"/visualization/st
rand_right_inv.png";right_img_inv.onload=function(){RIGHT_STRAND_INV=CONTEXT.createPattern(right_img_inv,"repeat")};var left_img_inv=new Image();left_img_inv.src=image_path+"/visualization/strand_left_inv.png";left_img_inv.onload=function(){LEFT_STRAND_INV=CONTEXT.createPattern(left_img_inv,"repeat")};function round_1000(a){return Math.round(a*1000)/1000}var Cache=function(a){this.num_elements=a;this.clear()};$.extend(Cache.prototype,{get:function(b){var a=this.key_ary.indexOf(b);if(a!=-1){this.key_ary.splice(a,1);this.key_ary.push(b)}return this.obj_cache[b]},set:function(b,c){if(!this.obj_cache[b]){if(this.key_ary.length>=this.num_elements){var a=this.key_ary.shift();delete this.obj_cache[a]}this.key_ary.push(b)}this.obj_cache[b]=c;return c},clear:function(){this.obj_cache={};this.key_ary=[]}});var View=function(a,d,c,b){this.container=a;this.vis_id=c;this.dbkey=b;this.title=d;this.tracks=[];this.label_tracks=[];this.max_low=0;this.max_high=0;this.num_tracks=0;this.track_i
d_counter=0;this.zoom_factor=3;this.min_separation=30;this.has_changes=false;this.init();this.reset()};$.extend(View.prototype,{init:function(){var c=this.container,a=this;this.top_labeltrack=$("<div/>").addClass("top-labeltrack").appendTo(c);this.content_div=$("<div/>").addClass("content").css("position","relative").appendTo(c);this.viewport_container=$("<div/>").addClass("viewport-container").addClass("viewport-container").appendTo(this.content_div);this.intro_div=$("<div/>").addClass("intro").text("Select a chrom from the dropdown below").hide();this.nav_container=$("<div/>").addClass("nav-container").appendTo(c);this.nav_labeltrack=$("<div/>").addClass("nav-labeltrack").appendTo(this.nav_container);this.nav=$("<div/>").addClass("nav").appendTo(this.nav_container);this.overview=$("<div/>").addClass("overview").appendTo(this.nav);this.overview_viewport=$("<div/>").addClass("overview-viewport").appendTo(this.overview);this.overview_close=$("<a href='javascript:void(0);'>Clo
se Overview</a>").addClass("overview-close").hide().appendTo(this.overview_viewport);this.overview_highlight=$("<div />").addClass("overview-highlight").hide().appendTo(this.overview_viewport);this.overview_box_background=$("<div/>").addClass("overview-boxback").appendTo(this.overview_viewport);this.overview_box=$("<div/>").addClass("overview-box").appendTo(this.overview_viewport);this.default_overview_height=this.overview_box.height();this.nav_controls=$("<div/>").addClass("nav-controls").appendTo(this.nav);this.chrom_form=$("<form/>").attr("action",function(){void (0)}).appendTo(this.nav_controls);this.chrom_select=$("<select/>").attr({name:"chrom"}).css("width","15em").addClass("no-autocomplete").append("<option value=''>Loading</option>").appendTo(this.chrom_form);var b=function(d){if(d.type==="focusout"||(d.keyCode||d.which)===13||(d.keyCode||d.which)===27){if((d.keyCode||d.which)!==27){a.go_to($(this).val())}$(this).hide();a.location_span.show();a.chrom_select.show();r
eturn false}};this.nav_input=$("<input/>").addClass("nav-input").hide().bind("keypress focusout",b).appendTo(this.chrom_form);this.location_span=$("<span/>").addClass("location").appendTo(this.chrom_form);this.location_span.bind("click",function(){a.location_span.hide();a.chrom_select.hide();a.nav_input.css("display","inline-block");a.nav_input.select();a.nav_input.focus()});if(this.vis_id!==undefined){this.hidden_input=$("<input/>").attr("type","hidden").val(this.vis_id).appendTo(this.chrom_form)}this.zo_link=$("<a/>").click(function(){a.zoom_out();a.redraw()}).html('<img src="'+image_path+'/fugue/magnifier-zoom-out.png" />').appendTo(this.chrom_form);this.zi_link=$("<a/>").click(function(){a.zoom_in();a.redraw()}).html('<img src="'+image_path+'/fugue/magnifier-zoom.png" />').appendTo(this.chrom_form);$.ajax({url:chrom_url,data:(this.vis_id!==undefined?{vis_id:this.vis_id}:{dbkey:this.dbkey}),dataType:"json",success:function(d){if(d.reference){a.add_label_track(new Referenc
eTrack(a))}a.chrom_data=d.chrom_info;var f='<option value="">Select Chrom/Contig</option>';for(i in a.chrom_data){var e=a.chrom_data[i]["chrom"];f+='<option value="'+e+'">'+e+"</option>"}a.chrom_select.html(f);a.intro_div.show();a.chrom_select.bind("change",function(){a.change_chrom(a.chrom_select.val())})},error:function(){alert("Could not load chroms for this dbkey:",a.dbkey)}});this.content_div.bind("dblclick",function(d){a.zoom_in(d.pageX,this.viewport_container)});this.overview_box.bind("dragstart",function(d){this.current_x=d.offsetX}).bind("drag",function(d){var g=d.offsetX-this.current_x;this.current_x=d.offsetX;var f=Math.round(g/a.viewport_container.width()*(a.max_high-a.max_low));a.move_delta(-f)});this.overview_close.bind("click",function(){for(var d in a.tracks){a.tracks[d].is_overview=false}$(this).siblings().filter("canvas").remove();$(this).parent().css("height",a.overview_box.height());a.overview_highlight.hide();$(this).hide()});this.viewport_container.bind
("dragstart",function(d){this.original_low=a.low;this.current_height=d.clientY;this.current_x=d.offsetX;this.enable_pan=(d.clientX<a.viewport_container.width()-16)?true:false}).bind("drag",function(g){if(!this.enable_pan||this.in_reordering){return}var d=$(this);var j=g.offsetX-this.current_x;var f=d.scrollTop()-(g.clientY-this.current_height);d.scrollTop(f);this.current_height=g.clientY;this.current_x=g.offsetX;var h=Math.round(j/a.viewport_container.width()*(a.high-a.low));a.move_delta(h)});this.top_labeltrack.bind("dragstart",function(d){this.drag_origin_x=d.clientX;this.drag_origin_pos=d.clientX/a.viewport_container.width()*(a.high-a.low)+a.low;this.drag_div=$("<div />").css({height:a.content_div.height()+30,top:"0px",position:"absolute","background-color":"#cfc",border:"1px solid #6a6",opacity:0.5,"z-index":1000}).appendTo($(this))}).bind("drag",function(j){var f=Math.min(j.clientX,this.drag_origin_x)-a.container.offset().left,d=Math.max(j.clientX,this.drag_origin_x)-a.
container.offset().left,h=(a.high-a.low),g=a.viewport_container.width();a.update_location(Math.round(f/g*h)+a.low,Math.round(d/g*h)+a.low);this.drag_div.css({left:f+"px",width:(d-f)+"px"})}).bind("dragend",function(k){var f=Math.min(k.clientX,this.drag_origin_x),d=Math.max(k.clientX,this.drag_origin_x),h=(a.high-a.low),g=a.viewport_container.width(),j=a.low;a.low=Math.round(f/g*h)+j;a.high=Math.round(d/g*h)+j;this.drag_div.remove();a.redraw()});this.add_label_track(new LabelTrack(this,this.top_labeltrack));this.add_label_track(new LabelTrack(this,this.nav_labeltrack))},update_location:function(a,b){this.location_span.text(commatize(a)+" - "+commatize(b));this.nav_input.val(this.chrom+":"+commatize(a)+"-"+commatize(b))},change_chrom:function(d,a,f){var c=this;var e=$.grep(c.chrom_data,function(h,j){return h.chrom===d})[0];if(e===undefined){return}if(d!==c.chrom){c.chrom=d;if(!c.chrom){c.intro_div.show()}else{c.intro_div.hide()}c.chrom_select.val(c.chrom);c.max_high=e.len;c.re
set();c.redraw(true);for(var g in c.tracks){var b=c.tracks[g];if(b.init){b.init()}}}if(a!==undefined&&f!==undefined){c.low=Math.max(a,0);c.high=Math.min(f,c.max_high)}c.reset_overview();c.redraw()},go_to:function(f){var k=this,b=f.split(":"),h=b[0],j=b[1];if(j!==undefined){try{var g=j.split("-"),a=parseInt(g[0].replace(/,/g,"")),d=parseInt(g[1].replace(/,/g,""))}catch(c){return false}}k.change_chrom(h,a,d)},move_delta:function(c){var a=this;var b=a.high-a.low;if(a.low-c<a.max_low){a.low=a.max_low;a.high=a.max_low+b}else{if(a.high-c>a.max_high){a.high=a.max_high;a.low=a.max_high-b}else{a.high-=c;a.low-=c}}a.redraw()},add_track:function(a){a.view=this;a.track_id=this.track_id_counter;this.tracks.push(a);if(a.init){a.init()}a.container_div.attr("id","track_"+a.track_id);this.track_id_counter+=1;this.num_tracks+=1},add_label_track:function(a){a.view=this;this.label_tracks.push(a)},remove_track:function(a){this.has_changes=true;a.container_div.fadeOut("slow",function(){$(this).re
move()});delete this.tracks[this.tracks.indexOf(a)];this.num_tracks-=1},reset:function(){this.low=this.max_low;this.high=this.max_high;this.viewport_container.find(".yaxislabel").remove()},redraw:function(h){var g=this.high-this.low,f=this.low,b=this.high;if(f<this.max_low){f=this.max_low}if(b>this.max_high){b=this.max_high}if(this.high!==0&&g<this.min_separation){b=f+this.min_separation}this.low=Math.floor(f);this.high=Math.ceil(b);this.resolution=Math.pow(10,Math.ceil(Math.log((this.high-this.low)/200)/Math.LN10));this.zoom_res=Math.pow(FEATURE_LEVELS,Math.max(0,Math.ceil(Math.log(this.resolution,FEATURE_LEVELS)/Math.log(FEATURE_LEVELS))));var a=this.low/(this.max_high-this.max_low)*this.overview_viewport.width();var e=(this.high-this.low)/(this.max_high-this.max_low)*this.overview_viewport.width();var j=13;this.overview_box.css({left:a,width:Math.max(j,e)}).show();if(e<j){this.overview_box.css("left",a-(j-e)/2)}if(this.overview_highlight){this.overview_highlight.css({left
:a,width:e})}this.update_location(this.low,this.high);if(!h){for(var c=0,d=this.tracks.length;c<d;c++){if(this.tracks[c]&&this.tracks[c].enabled){this.tracks[c].draw()}}for(var c=0,d=this.label_tracks.length;c<d;c++){this.label_tracks[c].draw()}}},zoom_in:function(b,c){if(this.max_high===0||this.high-this.low<this.min_separation){return}var d=this.high-this.low,e=d/2+this.low,a=(d/this.zoom_factor)/2;if(b){e=b/this.viewport_container.width()*(this.high-this.low)+this.low}this.low=Math.round(e-a);this.high=Math.round(e+a);this.redraw()},zoom_out:function(){if(this.max_high===0){return}var b=this.high-this.low,c=b/2+this.low,a=(b*this.zoom_factor)/2;this.low=Math.round(c-a);this.high=Math.round(c+a);this.redraw()},reset_overview:function(){this.overview_viewport.find("canvas").remove();this.overview_viewport.height(this.default_overview_height);this.overview_box.height(this.default_overview_height);this.overview_close.hide();this.overview_highlight.hide()}});var Filter=functio
n(b,a,c){this.name=b;this.index=a;this.value=c};var NumberFilter=function(b,a){this.name=b;this.index=a;this.low=-Number.MAX_VALUE;this.high=Number.MAX_VALUE;this.slider_min=Number.MAX_VALUE;this.slider_max=-Number.MAX_VALUE;this.slider=null;this.slider_label=null};$.extend(NumberFilter.prototype,{applies_to:function(a){if(a.length>this.index){return true}return false},keep:function(a){if(!this.applies_to(a)){return true}return(a[this.index]>=this.low&&a[this.index]<=this.high)},update_attrs:function(b){var a=false;if(!this.applies_to(b)){return a}if(b[this.index]<this.slider_min){this.slider_min=b[this.index];a=true}if(b[this.index]>this.slider_max){this.slider_max=b[this.index];a=false}return a},update_ui_elt:function(){var b=this.slider.slider("option","min"),a=this.slider.slider("option","max");if(this.slider_min<b||this.slider_max>a){this.slider.slider("option","min",this.slider_min);this.slider.slider("option","max",this.slider_max);this.slider.slider("option","values"
,[this.slider_min,this.slider_max])}}});var get_filters=function(a){var g=[];for(var d=0;d<a.length;d++){var f=a[d];var c=f.name,e=f.type,b=f.index;if(e=="int"||e=="float"){g[d]=new NumberFilter(c,b)}else{g[d]=new Filter(c,b,e)}}return g};var Track=function(b,a,d,c){this.name=b;this.view=a;this.parent_element=d;this.filters=(c!==undefined?get_filters(c):[]);this.init_global()};$.extend(Track.prototype,{init_global:function(){this.container_div=$("<div />").addClass("track").css("position","relative");if(!this.hidden){this.header_div=$("<div class='track-header' />").appendTo(this.container_div);if(this.view.editor){this.drag_div=$("<div class='draghandle' />").appendTo(this.header_div)}this.name_div=$("<div class='menubutton popup' />").appendTo(this.header_div);this.name_div.text(this.name);this.name_div.attr("id",this.name.replace(/\s+/g,"-").replace(/[^a-zA-Z0-9\-]/g,"").toLowerCase())}this.filtering_div=$("<div class='track-filters'>").appendTo(this.container_div);this.f
iltering_div.hide();this.filtering_div.bind("drag",function(k){k.stopPropagation()});var b=$("<table class='filters'>").appendTo(this.filtering_div);var c=this;for(var e=0;e<this.filters.length;e++){var a=this.filters[e];var f=$("<tr>").appendTo(b);var g=$("<th class='filter-info'>").appendTo(f);var j=$("<span class='name'>").appendTo(g);j.text(a.name+" ");var d=$("<span class='values'>").appendTo(g);var h=$("<td>").appendTo(f);a.control_element=$("<div id='"+a.name+"-filter-control' style='width: 200px; position: relative'>").appendTo(h);a.control_element.slider({range:true,min:Number.MAX_VALUE,max:-Number.MIN_VALUE,values:[0,0],slide:function(l,m){var k=m.values;d.text("["+k[0]+"-"+k[1]+"]");a.low=k[0];a.high=k[1];c.draw(true)},change:function(k,l){a.control_element.slider("option","slide").call(a.control_element,k,l)}});a.slider=a.control_element;a.slider_label=d}this.content_div=$("<div class='track-content'>").appendTo(this.container_div);this.parent_element.append(thi
s.container_div)},init_each:function(c,b){var a=this;a.enabled=false;a.data_queue={};a.tile_cache.clear();a.data_cache.clear();a.initial_canvas=undefined;a.content_div.css("height","auto");if(!a.content_div.text()){a.content_div.text(DATA_LOADING)}a.container_div.removeClass("nodata error pending");if(a.view.chrom){$.getJSON(data_url,c,function(d){if(!d||d==="error"||d.kind==="error"){a.container_div.addClass("error");a.content_div.text(DATA_ERROR);if(d.message){var f=a.view.tracks.indexOf(a);var e=$("<a href='javascript:void(0);'></a>").attr("id",f+"_error");e.text("Click to view error");$("#"+f+"_error").live("click",function(){show_modal("Trackster Error","<pre>"+d.message+"</pre>",{Close:hide_modal})});a.content_div.append(e)}}else{if(d==="no converter"){a.container_div.addClass("error");a.content_div.text(DATA_NOCONVERTER)}else{if(d.data!==undefined&&(d.data===null||d.data.length===0)){a.container_div.addClass("nodata");a.content_div.text(DATA_NONE)}else{if(d==="pending
"){a.container_div.addClass("pending");a.content_div.text(DATA_PENDING);setTimeout(function(){a.init()},5000)}else{a.content_div.text("");a.content_div.css("height",a.height_px+"px");a.enabled=true;b(d);a.draw()}}}}})}else{a.container_div.addClass("nodata");a.content_div.text(DATA_NONE)}}});var TiledTrack=function(){var d=this,c=d.view;if(d.hidden){return}if(d.display_modes!==undefined){if(d.mode_div===undefined){d.mode_div=$("<div class='right-float menubutton popup' />").appendTo(d.header_div);var h=d.display_modes[0];d.mode=h;d.mode_div.text(h);var a=function(j){d.mode_div.text(j);d.mode=j;d.tile_cache.clear();d.draw()};var f={};for(var e in d.display_modes){var g=d.display_modes[e];f[g]=function(j){return function(){a(j)}}(g)}make_popupmenu(d.mode_div,f)}else{d.mode_div.hide()}}var b={};b["Set as overview"]=function(){c.overview_viewport.find("canvas").remove();d.is_overview=true;d.set_overview();for(var j in c.tracks){if(c.tracks[j]!==d){c.tracks[j].is_overview=false}}}
;b["Edit configuration"]=function(){var l=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},j=function(){d.update_options(d.track_id);hide_modal();$(window).unbind("keypress.check_enter_esc")},k=function(m){if((m.keyCode||m.which)===27){l()}else{if((m.keyCode||m.which)===13){j()}}};$(window).bind("keypress.check_enter_esc",k);show_modal("Configure Track",d.gen_options(d.track_id),{Cancel:l,OK:j})};if(d.filters.length>0){b["Show filters"]=function(){var j;if(!d.filtering_div.is(":visible")){j="Hide filters";d.filters_visible=true}else{j="Show filters";d.filters_visible=false}$("#"+d.name_div.attr("id")+"-menu").find("li").eq(2).text(j);d.filtering_div.toggle()}}b.Remove=function(){c.remove_track(d);if(c.num_tracks===0){$("#no-tracks").show()}};d.popup_menu=make_popupmenu(d.name_div,b);show_hide_popupmenu_options(d.popup_menu,"(Show|Hide) filters",false)};$.extend(TiledTrack.prototype,Track.prototype,{draw:function(b){var m=this.view.low,g=this.view.high,h=
g-m,f=this.view.resolution;var p=$("<div style='position: relative;'></div>"),q=this.content_div.width()/h,k;this.content_div.append(p),this.max_height=0;var a=Math.floor(m/f/DENSITY);var l=new Object();while((a*DENSITY*f)<g){var n=this.content_div.width()+"_"+q+"_"+a;var e=this.tile_cache.get(n);if(!b&&e){var j=a*DENSITY*f;var d=(j-m)*q;if(this.left_offset){d-=this.left_offset}e.css({left:d});this.show_tile(e,p)}else{this.delayed_draw(this,n,m,g,a,f,p,q,l)}a+=1}var c=this;var o=setInterval(function(){if(l.length!=0){if(c.content_div.children().length>1){c.content_div.children(":first").remove()}for(var r=0;r<c.filters.length;r++){c.filters[r].update_ui_elt()}clearInterval(o)}},50)},delayed_draw:function(c,h,g,e,b,d,j,k,f){var a=setTimeout(function(){if(!(g>c.view.high||e<c.view.low)){tile_element=c.draw_tile(d,b,j,k);if(tile_element){if(!c.initial_canvas){c.initial_canvas=$(tile_element).clone();var n=tile_element.get(0).getContext("2d");var l=c.initial_canvas.get(0).getCon
text("2d");var m=n.getImageData(0,0,n.canvas.width,n.canvas.height);l.putImageData(m,0,0);c.set_overview()}c.tile_cache.set(h,tile_element);c.show_tile(tile_element,j)}}delete f.id},50);f.id=true},show_tile:function(a,c){var b=this;c.append(a);b.max_height=Math.max(b.max_height,a.height());b.content_div.css("height",b.max_height+"px");if(a.hasClass(FILTERABLE_CLASS)){show_hide_popupmenu_options(b.popup_menu,"(Show|Hide) filters");if(b.filters_visible){b.filtering_div.show()}}else{show_hide_popupmenu_options(b.popup_menu,"(Show|Hide) filters",false);b.filtering_div.hide()}},set_overview:function(){var a=this.view;if(this.initial_canvas&&this.is_overview){a.overview_close.show();a.overview_viewport.append(this.initial_canvas);a.overview_highlight.show().height(this.initial_canvas.height());a.overview_viewport.height(this.initial_canvas.height()+a.overview_box.height())}$(window).trigger("resize")}});var LabelTrack=function(a,b){this.track_type="LabelTrack";this.hidden=true;Tra
ck.call(this,null,a,b);this.container_div.addClass("label-track")};$.extend(LabelTrack.prototype,Track.prototype,{draw:function(){var c=this.view,d=c.high-c.low,g=Math.floor(Math.pow(10,Math.floor(Math.log(d)/Math.log(10)))),a=Math.floor(c.low/g)*g,e=this.content_div.width(),b=$("<div style='position: relative; height: 1.3em;'></div>");while(a<c.high){var f=(a-c.low)/d*e;b.append($("<div class='label'>"+commatize(a)+"</div>").css({position:"absolute",left:f-1}));a+=g}this.content_div.children(":first").remove();this.content_div.append(b)}});var ReferenceTrack=function(a){this.track_type="ReferenceTrack";this.hidden=true;Track.call(this,null,a,a.top_labeltrack);TiledTrack.call(this);this.left_offset=200;this.height_px=12;this.container_div.addClass("reference-track");this.dummy_canvas=$("<canvas></canvas>").get(0).getContext("2d");this.data_queue={};this.data_cache=new Cache(CACHED_DATA);this.tile_cache=new Cache(CACHED_TILES_LINE)};$.extend(ReferenceTrack.prototype,TiledTrac
k.prototype,{get_data:function(d,b){var c=this,a=b*DENSITY*d,f=(b+1)*DENSITY*d,e=d+"_"+b;if(!c.data_queue[e]){c.data_queue[e]=true;$.ajax({url:reference_url,dataType:"json",data:{chrom:this.view.chrom,low:a,high:f,dbkey:this.view.dbkey},success:function(g){c.data_cache.set(e,g);delete c.data_queue[e];c.draw()},error:function(h,g,j){console.log(h,g,j)}})}},draw_tile:function(f,b,l,p){var g=b*DENSITY*f,d=DENSITY*f,e=$("<canvas class='tile'></canvas>"),o=e.get(0).getContext("2d"),k=f+"_"+b;if(p>PX_PER_CHAR){if(this.data_cache.get(k)===undefined){this.get_data(f,b);return}var n=this.data_cache.get(k);if(n===null){this.content_div.css("height","0px");return}e.get(0).width=Math.ceil(d*p+this.left_offset);e.get(0).height=this.height_px;e.css({position:"absolute",top:0,left:(g-this.view.low)*p-this.left_offset});for(var h=0,m=n.length;h<m;h++){var a=Math.round(h*p),j=Math.round(p/2);o.fillText(n[h],a+this.left_offset+j,10)}l.append(e);return e}this.content_div.css("height","0px")}})
;var LineTrack=function(d,b,a,c){this.track_type="LineTrack";this.display_modes=["Histogram","Line","Filled","Intensity"];this.mode="Histogram";Track.call(this,d,b,b.viewport_container);TiledTrack.call(this);this.height_px=80;this.dataset_id=a;this.data_cache=new Cache(CACHED_DATA);this.tile_cache=new Cache(CACHED_TILES_LINE);this.prefs={color:"black",min_value:undefined,max_value:undefined,mode:this.mode};if(c.min_value!==undefined){this.prefs.min_value=c.min_value}if(c.max_value!==undefined){this.prefs.max_value=c.max_value}};$.extend(LineTrack.prototype,TiledTrack.prototype,{init:function(){var a=this,b=a.view.tracks.indexOf(a);a.vertical_range=undefined;this.init_each({stats:true,chrom:a.view.chrom,low:null,high:null,dataset_id:a.dataset_id},function(c){a.container_div.addClass("line-track");data=c.data;if(isNaN(parseFloat(a.prefs.min_value))||isNaN(parseFloat(a.prefs.max_value))){a.prefs.min_value=data.min;a.prefs.max_value=data.max;$("#track_"+b+"_minval").val(a.prefs.
min_value);$("#track_"+b+"_maxval").val(a.prefs.max_value)}a.vertical_range=a.prefs.max_value-a.prefs.min_value;a.total_frequency=data.total_frequency;a.container_div.find(".yaxislabel").remove();var e=$("<div />").addClass("yaxislabel").attr("id","linetrack_"+b+"_minval").text(round_1000(a.prefs.min_value));var d=$("<div />").addClass("yaxislabel").attr("id","linetrack_"+b+"_maxval").text(round_1000(a.prefs.max_value));d.css({position:"absolute",top:"22px",left:"10px"});d.prependTo(a.container_div);e.css({position:"absolute",top:a.height_px+11+"px",left:"10px"});e.prependTo(a.container_div)})},get_data:function(d,b){var c=this,a=b*DENSITY*d,f=(b+1)*DENSITY*d,e=d+"_"+b;if(!c.data_queue[e]){c.data_queue[e]=true;$.ajax({url:data_url,dataType:"json",data:{chrom:this.view.chrom,low:a,high:f,dataset_id:this.dataset_id,resolution:this.view.resolution},success:function(g){data=g.data;c.data_cache.set(e,data);delete c.data_queue[e];c.draw()},error:function(h,g,j){console.log(h,g,j)}
})}},draw_tile:function(p,s,c,e){if(this.vertical_range===undefined){return}var t=s*DENSITY*p,a=DENSITY*p,b=$("<canvas class='tile'></canvas>"),w=p+"_"+s;if(this.data_cache.get(w)===undefined){this.get_data(p,s);return}var j=this.data_cache.get(w);if(j===null){return}b.css({position:"absolute",top:0,left:(t-this.view.low)*e});b.get(0).width=Math.ceil(a*e);b.get(0).height=this.height_px;var o=b.get(0).getContext("2d"),k=false,l=this.prefs.min_value,g=this.prefs.max_value,n=this.vertical_range,u=this.total_frequency,d=this.height_px,m=this.mode;o.beginPath();o.fillStyle=this.prefs.color;if(data.length>1){var f=Math.ceil((data[1][0]-data[0][0])*e)}else{var f=10}var v,h;for(var q=0,r=data.length;q<r;q++){v=Math.round((data[q][0]-t)*e);h=data[q][1];if(h===null){if(k&&m==="Filled"){o.lineTo(v,d)}k=false;continue}if(h<l){h=l}else{if(h>g){h=g}}if(m==="Histogram"){h=Math.round(d-(h-l)/n*d);o.fillRect(v,h,f,d-h)}else{if(m==="Intensity"){h=255-Math.floor((h-l)/n*255);o.fillStyle="rgb("
+h+","+h+","+h+")";o.fillRect(v,0,f,d)}else{h=Math.round(d-(h-l)/n*d);if(k){o.lineTo(v,h)}else{k=true;if(m==="Filled"){o.moveTo(v,d);o.lineTo(v,h)}else{o.moveTo(v,h)}}}}}if(m==="Filled"){if(k){o.lineTo(v,d)}o.fill()}else{o.stroke()}c.append(b);return b},gen_options:function(n){var a=$("<div />").addClass("form-row");var e="track_"+n+"_color",b=$("<label />").attr("for",e).text("Color:"),c=$("<input />").attr("id",e).attr("name",e).val(this.prefs.color),h="track_"+n+"_minval",m=$("<label></label>").attr("for",h).text("Min value:"),d=(this.prefs.min_value===undefined?"":this.prefs.min_value),l=$("<input></input>").attr("id",h).val(d),k="track_"+n+"_maxval",g=$("<label></label>").attr("for",k).text("Max value:"),j=(this.prefs.max_value===undefined?"":this.prefs.max_value),f=$("<input></input>").attr("id",k).val(j);return a.append(m).append(l).append(g).append(f).append(b).append(c)},update_options:function(c){var a=$("#track_"+c+"_minval").val(),b=$("#track_"+c+"_maxval").val()
;color=$("#track_"+c+"_color").val();if(a!==this.prefs.min_value||b!==this.prefs.max_value||color!==this.prefs.color){this.prefs.min_value=parseFloat(a);this.prefs.max_value=parseFloat(b);this.prefs.color=color;this.vertical_range=this.prefs.max_value-this.prefs.min_value;$("#linetrack_"+c+"_minval").text(this.prefs.min_value);$("#linetrack_"+c+"_maxval").text(this.prefs.max_value);this.tile_cache.clear();this.draw()}}});var FeatureTrack=function(d,b,a,e,c){this.track_type="FeatureTrack";this.display_modes=["Auto","Dense","Squish","Pack"];Track.call(this,d,b,b.viewport_container,e);TiledTrack.call(this);this.height_px=0;this.container_div.addClass("feature-track");this.dataset_id=a;this.zo_slots={};this.show_labels_scale=0.001;this.showing_details=false;this.vertical_detail_px=10;this.vertical_nodetail_px=2;this.summary_draw_height=30;this.default_font="9px Monaco, Lucida Console, monospace";this.inc_slots={};this.data_queue={};this.s_e_by_tile={};this.tile_cache=new Cache(C
ACHED_TILES_FEATURE);this.data_cache=new Cache(20);this.left_offset=200;this.prefs={block_color:"#444",label_color:"black",show_counts:true};if(c.block_color!==undefined){this.prefs.block_color=c.block_color}if(c.label_color!==undefined){this.prefs.label_color=c.label_color}if(c.show_counts!==undefined){this.prefs.show_counts=c.show_counts}};$.extend(FeatureTrack.prototype,TiledTrack.prototype,{init:function(){var a=this,b="initial";this.init_each({low:a.view.max_low,high:a.view.max_high,dataset_id:a.dataset_id,chrom:a.view.chrom,resolution:this.view.resolution,mode:a.mode},function(c){a.mode_div.show();a.data_cache.set(b,c);a.draw()})},get_data:function(a,d){var b=this,c=a+"_"+d;if(!b.data_queue[c]){b.data_queue[c]=true;$.getJSON(data_url,{chrom:b.view.chrom,low:a,high:d,dataset_id:b.dataset_id,resolution:this.view.resolution,mode:this.mode},function(e){b.data_cache.set(c,e);delete b.data_queue[c];b.draw()})}},incremental_slots:function(a,h,c,r){if(!this.inc_slots[a]){this.
inc_slots[a]={};this.inc_slots[a].w_scale=a;this.inc_slots[a].mode=r;this.s_e_by_tile[a]={}}var n=this.inc_slots[a].w_scale,z=[],l=0,b=$("<canvas></canvas>").get(0).getContext("2d"),o=this.view.max_low;var B=[];if(this.inc_slots[a].mode!==r){delete this.inc_slots[a];this.inc_slots[a]={mode:r,w_scale:n};delete this.s_e_by_tile[a];this.s_e_by_tile[a]={}}for(var w=0,x=h.length;w<x;w++){var g=h[w],m=g[0];if(this.inc_slots[a][m]!==undefined){l=Math.max(l,this.inc_slots[a][m]);B.push(this.inc_slots[a][m])}else{z.push(w)}}for(var w=0,x=z.length;w<x;w++){var g=h[z[w]],m=g[0],s=g[1],d=g[2],q=g[3],e=Math.floor((s-o)*n),f=Math.ceil((d-o)*n);if(q!==undefined&&!c){var t=b.measureText(q).width;if(e-t<0){f+=t}else{e-=t}}var v=0;while(v<=MAX_FEATURE_DEPTH){var p=true;if(this.s_e_by_tile[a][v]!==undefined){for(var u=0,A=this.s_e_by_tile[a][v].length;u<A;u++){var y=this.s_e_by_tile[a][v][u];if(f>y[0]&&e<y[1]){p=false;break}}}if(p){if(this.s_e_by_tile[a][v]===undefined){this.s_e_by_tile[a][v]=
[]}this.s_e_by_tile[a][v].push([e,f]);this.inc_slots[a][m]=v;l=Math.max(l,v);break}v++}}return l},rect_or_text:function(r,m,s,b,q,f,h,e){r.textAlign="center";var l=0,p=Math.round(m/2);for(cig_id in h){var k=h[cig_id],d="MIDNSHP"[k[0]],n=k[1];if(d==="H"||d==="S"){l-=n}var g=q+l,v=Math.floor(Math.max(0,(g-s)*m)),j=Math.floor(Math.max(0,(g+n-s)*m));switch(d){case"S":case"H":case"M":var o=f.slice(l,n);if((this.mode==="Pack"||this.mode==="Auto")&&f!==undefined&&m>PX_PER_CHAR){r.fillStyle=this.prefs.block_color;r.fillRect(v+this.left_offset,e+1,j-v,9);r.fillStyle=CONNECTOR_COLOR;for(var t=0,a=o.length;t<a;t++){if(g+t>=s&&g+t<=b){var u=Math.floor(Math.max(0,(g+t-s)*m));r.fillText(o[t],u+this.left_offset+p,e+9)}}}else{r.fillStyle=this.prefs.block_color;r.fillRect(v+this.left_offset,e+4,j-v,3)}break;case"N":r.fillStyle=CONNECTOR_COLOR;r.fillRect(v+this.left_offset,e+5,j-v,1);break;case"D":r.fillStyle="red";r.fillRect(v+this.left_offset,e+4,j-v,3);break;case"P":case"I":break}l+=n}},dr
aw_tile:function(ah,o,s,aw){var N=o*DENSITY*ah,am=(o+1)*DENSITY*ah,M=am-N;var ao=(!this.initial_canvas?"initial":N+"_"+am);var I=this.data_cache.get(ao);var e;if(I===undefined||(this.mode!=="Auto"&&I.dataset_type==="summary_tree")){this.data_queue[[N,am]]=true;this.get_data(N,am);return}var a=Math.ceil(M*aw),S=$("<canvas class='tile'></canvas>"),aj=this.prefs.label_color,l=this.prefs.block_color,r=this.mode,z=25,af=(r==="Squish")||(r==="Dense")&&(r!=="Pack")||(r==="Auto"&&(I.extra_info==="no_detail")),X=this.left_offset,av,D,ax;if(I.dataset_type==="summary_tree"){D=this.summary_draw_height}else{if(r==="Dense"){D=z;ax=10}else{ax=(af?this.vertical_nodetail_px:this.vertical_detail_px);var A=(aw<0.0001?1/view.zoom_res:aw);D=this.incremental_slots(A,I.data,af,r)*ax+z;av=this.inc_slots[A]}}S.css({position:"absolute",top:0,left:(N-this.view.low)*aw-X});S.get(0).width=a+X;S.get(0).height=D;s.parent().css("height",Math.max(this.height_px,D)+"px");var J=S.get(0).getContext("2d");J.fil
lStyle=l;J.font=this.default_font;J.textAlign="right";this.container_div.find(".yaxislabel").remove();if(I.dataset_type=="summary_tree"){var Z=I.data,L=I.max,q=I.avg,b=Math.ceil(I.delta*aw);var p=$("<div />").addClass("yaxislabel").text(L);p.css({position:"absolute",top:"22px",left:"10px"});p.prependTo(this.container_div);for(var aq=0,H=Z.length;aq<H;aq++){var ab=Math.floor((Z[aq][0]-N)*aw);var aa=Z[aq][1];if(!aa){continue}var an=aa/L*this.summary_draw_height;J.fillStyle="black";J.fillRect(ab+X,this.summary_draw_height-an,b,an);if(this.prefs.show_counts&&J.measureText(aa).width<b){J.fillStyle="#bbb";J.textAlign="center";J.fillText(aa,ab+X+(b/2),this.summary_draw_height-5)}}e="Summary";s.append(S);return S}if(I.message){S.css({border:"solid red","border-width":"2px 2px 2px 0px"});J.fillStyle="red";J.textAlign="left";J.fillText(I.message,100+X,ax)}var ae=false;if(I.data.length!=0){ae=true;for(var at=0;at<this.filters.length;at++){if(!this.filters[at].applies_to(I.data[0])){ae=
false}}}if(ae){S.addClass(FILTERABLE_CLASS)}var au=I.data;var ap=0;for(var aq=0,H=au.length;aq<H;aq++){var T=au[aq],R=T[0],ar=T[1],ad=T[2],O=T[3];if(av[R]===undefined){continue}var ac=false;var V;for(var at=0;at<this.filters.length;at++){V=this.filters[at];V.update_attrs(T);if(!V.keep(T)){ac=true;break}}if(ac){continue}if(ar<=am&&ad>=N){var ag=Math.floor(Math.max(0,(ar-N)*aw)),K=Math.ceil(Math.min(a,Math.max(0,(ad-N)*aw))),Y=(r==="Dense"?1:(1+av[R]))*ax;if(I.dataset_type==="bai"){var v=T[4];J.fillStyle=l;if(T[5] instanceof Array){var E=Math.floor(Math.max(0,(T[5][0]-N)*aw)),Q=Math.ceil(Math.min(a,Math.max(0,(T[5][1]-N)*aw))),C=Math.floor(Math.max(0,(T[6][0]-N)*aw)),w=Math.ceil(Math.min(a,Math.max(0,(T[6][1]-N)*aw)));if(T[5][1]>=N&&T[5][0]<=am){this.rect_or_text(J,aw,N,am,T[5][0],T[5][2],v,Y)}if(T[6][1]>=N&&T[6][0]<=am){this.rect_or_text(J,aw,N,am,T[6][0],T[6][2],v,Y)}if(C>Q){J.fillStyle=CONNECTOR_COLOR;J.fillRect(Q+X,Y+5,C-Q,1)}}else{J.fillStyle=l;this.rect_or_text(J,aw,N,am
,ar,O,v,Y)}if(r!=="Dense"&&!af&&ar>N){J.fillStyle=this.prefs.label_color;if(o===0&&ag-J.measureText(O).width<0){J.textAlign="left";J.fillText(R,K+2+X,Y+8)}else{J.textAlign="right";J.fillText(R,ag-2+X,Y+8)}J.fillStyle=l}}else{if(I.dataset_type==="interval_index"){if(af){J.fillStyle=l;J.fillRect(ag+X,Y+5,K-ag,1)}else{var G=T[4],W=T[5],ai=T[6],h=T[7];var F,ak,P=null,ay=null;if(W&&ai){P=Math.floor(Math.max(0,(W-N)*aw));ay=Math.ceil(Math.min(a,Math.max(0,(ai-N)*aw)))}if(r!=="Dense"&&O!==undefined&&ar>N){J.fillStyle=aj;if(o===0&&ag-J.measureText(O).width<0){J.textAlign="left";J.fillText(O,K+2+X,Y+8)}else{J.textAlign="right";J.fillText(O,ag-2+X,Y+8)}J.fillStyle=l}if(h){if(G){if(G=="+"){J.fillStyle=RIGHT_STRAND}else{if(G=="-"){J.fillStyle=LEFT_STRAND}}J.fillRect(ag+X,Y,K-ag,10);J.fillStyle=l}for(var ao=0,g=h.length;ao<g;ao++){var u=h[ao],d=Math.floor(Math.max(0,(u[0]-N)*aw)),U=Math.ceil(Math.min(a,Math.max((u[1]-N)*aw)));if(d>U){continue}F=5;ak=3;J.fillRect(d+X,Y+ak,U-d,F);if(P!==un
defined&&!(d>ay||U<P)){F=9;ak=1;var al=Math.max(d,P),B=Math.min(U,ay);J.fillRect(al+X,Y+ak,B-al,F)}}}else{F=9;ak=1;J.fillRect(ag+X,Y+ak,K-ag,F);if(T.strand){if(T.strand=="+"){J.fillStyle=RIGHT_STRAND_INV}else{if(T.strand=="-"){J.fillStyle=LEFT_STRAND_INV}}J.fillRect(ag+X,Y,K-ag,10);J.fillStyle=l}}}}else{if(I.dataset_type==="vcf"){if(af){J.fillStyle=l;J.fillRect(ag+X,Y+5,K-ag,1)}else{var t=T[4],n=T[5],c=T[6];F=9;ak=1;J.fillRect(ag+X,Y,K-ag,F);if(r!=="Dense"&&O!==undefined&&ar>N){J.fillStyle=aj;if(o===0&&ag-J.measureText(O).width<0){J.textAlign="left";J.fillText(O,K+2+X,Y+8)}else{J.textAlign="right";J.fillText(O,ag-2+X,Y+8)}J.fillStyle=l}var m=t+" / "+n;if(ar>N&&J.measureText(m).width<(K-ag)){J.fillStyle="white";J.textAlign="center";J.fillText(m,X+ag+(K-ag)/2,Y+8);J.fillStyle=l}}}}}ap++}}return S},gen_options:function(j){var a=$("<div />").addClass("form-row");var e="track_"+j+"_block_color",l=$("<label />").attr("for",e).text("Block color:"),m=$("<input />").attr("id",e).attr
("name",e).val(this.prefs.block_color),k="track_"+j+"_label_color",g=$("<label />").attr("for",k).text("Text color:"),h=$("<input />").attr("id",k).attr("name",k).val(this.prefs.label_color),f="track_"+j+"_show_count",c=$("<label />").attr("for",f).text("Show summary counts"),b=$('<input type="checkbox" style="float:left;"></input>').attr("id",f).attr("name",f).attr("checked",this.prefs.show_counts),d=$("<div />").append(b).append(c);return a.append(l).append(m).append(g).append(h).append(d)},update_options:function(e){var b=$("#track_"+e+"_block_color").val(),d=$("#track_"+e+"_label_color").val(),c=$("#track_"+e+"_mode option:selected").val(),a=$("#track_"+e+"_show_count").attr("checked");if(b!==this.prefs.block_color||d!==this.prefs.label_color||a!==this.prefs.show_counts){this.prefs.block_color=b;this.prefs.label_color=d;this.prefs.show_counts=a;this.tile_cache.clear();this.draw()}}});var ReadTrack=function(d,b,a,e,c){FeatureTrack.call(this,d,b,a,e,c);this.track_type="Rea
dTrack";this.vertical_detail_px=10;this.vertical_nodetail_px=5};$.extend(ReadTrack.prototype,TiledTrack.prototype,FeatureTrack.prototype,{});
+var DENSITY=200,FEATURE_LEVELS=10,MAX_FEATURE_DEPTH=50,CONNECTOR_COLOR="#ccc",DATA_ERROR="There was an error in indexing this dataset.",DATA_NOCONVERTER="A converter for this dataset is not installed. Please check your datatypes_conf.xml file.",DATA_NONE="No data for this chrom/contig.",DATA_PENDING="Currently indexing... please wait",DATA_LOADING="Loading data...",FILTERABLE_CLASS="filterable",CACHED_TILES_FEATURE=10,CACHED_TILES_LINE=30,CACHED_DATA=5,DUMMY_CANVAS=document.createElement("canvas"),RIGHT_STRAND,LEFT_STRAND;if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(DUMMY_CANVAS)}CONTEXT=DUMMY_CANVAS.getContext("2d");PX_PER_CHAR=CONTEXT.measureText("A").width;var right_img=new Image();right_img.src=image_path+"/visualization/strand_right.png";right_img.onload=function(){RIGHT_STRAND=CONTEXT.createPattern(right_img,"repeat")};var left_img=new Image();left_img.src=image_path+"/visualization/strand_left.png";left_img.onload=function(){LEFT_STRAND=CONTEXT.createP
attern(left_img,"repeat")};var right_img_inv=new Image();right_img_inv.src=image_path+"/visualization/strand_right_inv.png";right_img_inv.onload=function(){RIGHT_STRAND_INV=CONTEXT.createPattern(right_img_inv,"repeat")};var left_img_inv=new Image();left_img_inv.src=image_path+"/visualization/strand_left_inv.png";left_img_inv.onload=function(){LEFT_STRAND_INV=CONTEXT.createPattern(left_img_inv,"repeat")};function round_1000(a){return Math.round(a*1000)/1000}var Cache=function(a){this.num_elements=a;this.clear()};$.extend(Cache.prototype,{get:function(b){var a=this.key_ary.indexOf(b);if(a!=-1){this.key_ary.splice(a,1);this.key_ary.push(b)}return this.obj_cache[b]},set:function(b,c){if(!this.obj_cache[b]){if(this.key_ary.length>=this.num_elements){var a=this.key_ary.shift();delete this.obj_cache[a]}this.key_ary.push(b)}this.obj_cache[b]=c;return c},clear:function(){this.obj_cache={};this.key_ary=[]}});var View=function(a,d,c,b){this.container=a;this.vis_id=c;this.dbkey=b;this.t
itle=d;this.tracks=[];this.label_tracks=[];this.max_low=0;this.max_high=0;this.num_tracks=0;this.track_id_counter=0;this.zoom_factor=3;this.min_separation=30;this.has_changes=false;this.init();this.reset()};$.extend(View.prototype,{init:function(){var c=this.container,a=this;this.top_labeltrack=$("<div/>").addClass("top-labeltrack").appendTo(c);this.content_div=$("<div/>").addClass("content").css("position","relative").appendTo(c);this.viewport_container=$("<div/>").addClass("viewport-container").addClass("viewport-container").appendTo(this.content_div);this.intro_div=$("<div/>").addClass("intro").text("Select a chrom from the dropdown below").hide();this.nav_container=$("<div/>").addClass("nav-container").appendTo(c);this.nav_labeltrack=$("<div/>").addClass("nav-labeltrack").appendTo(this.nav_container);this.nav=$("<div/>").addClass("nav").appendTo(this.nav_container);this.overview=$("<div/>").addClass("overview").appendTo(this.nav);this.overview_viewport=$("<div/>").addCla
ss("overview-viewport").appendTo(this.overview);this.overview_close=$("<a href='javascript:void(0);'>Close Overview</a>").addClass("overview-close").hide().appendTo(this.overview_viewport);this.overview_highlight=$("<div />").addClass("overview-highlight").hide().appendTo(this.overview_viewport);this.overview_box_background=$("<div/>").addClass("overview-boxback").appendTo(this.overview_viewport);this.overview_box=$("<div/>").addClass("overview-box").appendTo(this.overview_viewport);this.default_overview_height=this.overview_box.height();this.nav_controls=$("<div/>").addClass("nav-controls").appendTo(this.nav);this.chrom_form=$("<form/>").attr("action",function(){void (0)}).appendTo(this.nav_controls);this.chrom_select=$("<select/>").attr({name:"chrom"}).css("width","15em").addClass("no-autocomplete").append("<option value=''>Loading</option>").appendTo(this.chrom_form);var b=function(d){if(d.type==="focusout"||(d.keyCode||d.which)===13||(d.keyCode||d.which)===27){if((d.keyC
ode||d.which)!==27){a.go_to($(this).val())}$(this).hide();a.location_span.show();a.chrom_select.show();return false}};this.nav_input=$("<input/>").addClass("nav-input").hide().bind("keypress focusout",b).appendTo(this.chrom_form);this.location_span=$("<span/>").addClass("location").appendTo(this.chrom_form);this.location_span.bind("click",function(){a.location_span.hide();a.chrom_select.hide();a.nav_input.css("display","inline-block");a.nav_input.select();a.nav_input.focus()});if(this.vis_id!==undefined){this.hidden_input=$("<input/>").attr("type","hidden").val(this.vis_id).appendTo(this.chrom_form)}this.zo_link=$("<a/>").click(function(){a.zoom_out();a.redraw()}).html('<img src="'+image_path+'/fugue/magnifier-zoom-out.png" />').appendTo(this.chrom_form);this.zi_link=$("<a/>").click(function(){a.zoom_in();a.redraw()}).html('<img src="'+image_path+'/fugue/magnifier-zoom.png" />').appendTo(this.chrom_form);$.ajax({url:chrom_url,data:(this.vis_id!==undefined?{vis_id:this.vis_id
}:{dbkey:this.dbkey}),dataType:"json",success:function(d){if(d.reference){a.add_label_track(new ReferenceTrack(a))}a.chrom_data=d.chrom_info;var f='<option value="">Select Chrom/Contig</option>';for(i in a.chrom_data){var e=a.chrom_data[i]["chrom"];f+='<option value="'+e+'">'+e+"</option>"}a.chrom_select.html(f);a.intro_div.show();a.chrom_select.bind("change",function(){a.change_chrom(a.chrom_select.val())})},error:function(){alert("Could not load chroms for this dbkey:",a.dbkey)}});this.content_div.bind("dblclick",function(d){a.zoom_in(d.pageX,this.viewport_container)});this.overview_box.bind("dragstart",function(d){this.current_x=d.offsetX}).bind("drag",function(d){var g=d.offsetX-this.current_x;this.current_x=d.offsetX;var f=Math.round(g/a.viewport_container.width()*(a.max_high-a.max_low));a.move_delta(-f)});this.overview_close.bind("click",function(){for(var d in a.tracks){a.tracks[d].is_overview=false}$(this).siblings().filter("canvas").remove();$(this).parent().css("he
ight",a.overview_box.height());a.overview_highlight.hide();$(this).hide()});this.viewport_container.bind("dragstart",function(d){this.original_low=a.low;this.current_height=d.clientY;this.current_x=d.offsetX;this.enable_pan=(d.clientX<a.viewport_container.width()-16)?true:false}).bind("drag",function(g){if(!this.enable_pan||this.in_reordering){return}var d=$(this);var j=g.offsetX-this.current_x;var f=d.scrollTop()-(g.clientY-this.current_height);d.scrollTop(f);this.current_height=g.clientY;this.current_x=g.offsetX;var h=Math.round(j/a.viewport_container.width()*(a.high-a.low));a.move_delta(h)});this.top_labeltrack.bind("dragstart",function(d){this.drag_origin_x=d.clientX;this.drag_origin_pos=d.clientX/a.viewport_container.width()*(a.high-a.low)+a.low;this.drag_div=$("<div />").css({height:a.content_div.height()+30,top:"0px",position:"absolute","background-color":"#cfc",border:"1px solid #6a6",opacity:0.5,"z-index":1000}).appendTo($(this))}).bind("drag",function(j){var f=Math
.min(j.clientX,this.drag_origin_x)-a.container.offset().left,d=Math.max(j.clientX,this.drag_origin_x)-a.container.offset().left,h=(a.high-a.low),g=a.viewport_container.width();a.update_location(Math.round(f/g*h)+a.low,Math.round(d/g*h)+a.low);this.drag_div.css({left:f+"px",width:(d-f)+"px"})}).bind("dragend",function(k){var f=Math.min(k.clientX,this.drag_origin_x),d=Math.max(k.clientX,this.drag_origin_x),h=(a.high-a.low),g=a.viewport_container.width(),j=a.low;a.low=Math.round(f/g*h)+j;a.high=Math.round(d/g*h)+j;this.drag_div.remove();a.redraw()});this.add_label_track(new LabelTrack(this,this.top_labeltrack));this.add_label_track(new LabelTrack(this,this.nav_labeltrack));$(window).bind("resize",function(){a.resize_window()});$(document).bind("redraw",function(){a.redraw()});this.reset();$(window).trigger("resize")},update_location:function(a,b){this.location_span.text(commatize(a)+" - "+commatize(b));this.nav_input.val(this.chrom+":"+commatize(a)+"-"+commatize(b))},change_chr
om:function(d,a,f){var c=this;var e=$.grep(c.chrom_data,function(h,j){return h.chrom===d})[0];if(e===undefined){return}if(d!==c.chrom){c.chrom=d;if(!c.chrom){c.intro_div.show()}else{c.intro_div.hide()}c.chrom_select.val(c.chrom);c.max_high=e.len;c.reset();c.redraw(true);for(var g in c.tracks){var b=c.tracks[g];if(b.init){b.init()}}}if(a!==undefined&&f!==undefined){c.low=Math.max(a,0);c.high=Math.min(f,c.max_high)}c.reset_overview();c.redraw()},go_to:function(f){var k=this,b=f.split(":"),h=b[0],j=b[1];if(j!==undefined){try{var g=j.split("-"),a=parseInt(g[0].replace(/,/g,"")),d=parseInt(g[1].replace(/,/g,""))}catch(c){return false}}k.change_chrom(h,a,d)},move_delta:function(c){var a=this;var b=a.high-a.low;if(a.low-c<a.max_low){a.low=a.max_low;a.high=a.max_low+b}else{if(a.high-c>a.max_high){a.high=a.max_high;a.low=a.max_high-b}else{a.high-=c;a.low-=c}}a.redraw()},add_track:function(a){a.view=this;a.track_id=this.track_id_counter;this.tracks.push(a);if(a.init){a.init()}a.contai
ner_div.attr("id","track_"+a.track_id);this.track_id_counter+=1;this.num_tracks+=1},add_label_track:function(a){a.view=this;this.label_tracks.push(a)},remove_track:function(a){this.has_changes=true;a.container_div.fadeOut("slow",function(){$(this).remove()});delete this.tracks[this.tracks.indexOf(a)];this.num_tracks-=1},reset:function(){this.low=this.max_low;this.high=this.max_high;this.viewport_container.find(".yaxislabel").remove()},redraw:function(h){var g=this.high-this.low,f=this.low,b=this.high;if(f<this.max_low){f=this.max_low}if(b>this.max_high){b=this.max_high}if(this.high!==0&&g<this.min_separation){b=f+this.min_separation}this.low=Math.floor(f);this.high=Math.ceil(b);this.resolution=Math.pow(10,Math.ceil(Math.log((this.high-this.low)/200)/Math.LN10));this.zoom_res=Math.pow(FEATURE_LEVELS,Math.max(0,Math.ceil(Math.log(this.resolution,FEATURE_LEVELS)/Math.log(FEATURE_LEVELS))));var a=(this.low/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var e=((t
his.high-this.low)/(this.max_high-this.max_low)*this.overview_viewport.width())||0;var j=13;this.overview_box.css({left:a,width:Math.max(j,e)}).show();if(e<j){this.overview_box.css("left",a-(j-e)/2)}if(this.overview_highlight){this.overview_highlight.css({left:a,width:e})}this.update_location(this.low,this.high);if(!h){for(var c=0,d=this.tracks.length;c<d;c++){if(this.tracks[c]&&this.tracks[c].enabled){this.tracks[c].draw()}}for(var c=0,d=this.label_tracks.length;c<d;c++){this.label_tracks[c].draw()}}},zoom_in:function(b,c){if(this.max_high===0||this.high-this.low<this.min_separation){return}var d=this.high-this.low,e=d/2+this.low,a=(d/this.zoom_factor)/2;if(b){e=b/this.viewport_container.width()*(this.high-this.low)+this.low}this.low=Math.round(e-a);this.high=Math.round(e+a);this.redraw()},zoom_out:function(){if(this.max_high===0){return}var b=this.high-this.low,c=b/2+this.low,a=(b*this.zoom_factor)/2;this.low=Math.round(c-a);this.high=Math.round(c+a);this.redraw()},resize_
window:function(){this.viewport_container.height(this.container.height()-this.nav_container.height()-45);this.nav_container.width(this.container.width());this.redraw()},reset_overview:function(){this.overview_viewport.find("canvas").remove();this.overview_viewport.height(this.default_overview_height);this.overview_box.height(this.default_overview_height);this.overview_close.hide();this.overview_highlight.hide()}});var Filter=function(b,a,c){this.name=b;this.index=a;this.value=c};var NumberFilter=function(b,a){this.name=b;this.index=a;this.low=-Number.MAX_VALUE;this.high=Number.MAX_VALUE;this.slider_min=Number.MAX_VALUE;this.slider_max=-Number.MAX_VALUE;this.slider=null;this.slider_label=null};$.extend(NumberFilter.prototype,{applies_to:function(a){if(a.length>this.index){return true}return false},keep:function(a){if(!this.applies_to(a)){return true}return(a[this.index]>=this.low&&a[this.index]<=this.high)},update_attrs:function(b){var a=false;if(!this.applies_to(b)){return a
}if(b[this.index]<this.slider_min){this.slider_min=b[this.index];a=true}if(b[this.index]>this.slider_max){this.slider_max=b[this.index];a=false}return a},update_ui_elt:function(){var b=this.slider.slider("option","min"),a=this.slider.slider("option","max");if(this.slider_min<b||this.slider_max>a){this.slider.slider("option","min",this.slider_min);this.slider.slider("option","max",this.slider_max);this.slider.slider("option","values",[this.slider_min,this.slider_max])}}});var get_filters=function(a){var g=[];for(var d=0;d<a.length;d++){var f=a[d];var c=f.name,e=f.type,b=f.index;if(e=="int"||e=="float"){g[d]=new NumberFilter(c,b)}else{g[d]=new Filter(c,b,e)}}return g};var Track=function(b,a,d,c){this.name=b;this.view=a;this.parent_element=d;this.filters=(c!==undefined?get_filters(c):[]);this.init_global()};$.extend(Track.prototype,{init_global:function(){this.container_div=$("<div />").addClass("track").css("position","relative");if(!this.hidden){this.header_div=$("<div class=
'track-header' />").appendTo(this.container_div);if(this.view.editor){this.drag_div=$("<div class='draghandle' />").appendTo(this.header_div)}this.name_div=$("<div class='menubutton popup' />").appendTo(this.header_div);this.name_div.text(this.name);this.name_div.attr("id",this.name.replace(/\s+/g,"-").replace(/[^a-zA-Z0-9\-]/g,"").toLowerCase())}this.filtering_div=$("<div class='track-filters'>").appendTo(this.container_div);this.filtering_div.hide();this.filtering_div.bind("drag",function(k){k.stopPropagation()});var b=$("<table class='filters'>").appendTo(this.filtering_div);var c=this;for(var e=0;e<this.filters.length;e++){var a=this.filters[e];var f=$("<tr>").appendTo(b);var g=$("<th class='filter-info'>").appendTo(f);var j=$("<span class='name'>").appendTo(g);j.text(a.name+" ");var d=$("<span class='values'>").appendTo(g);var h=$("<td>").appendTo(f);a.control_element=$("<div id='"+a.name+"-filter-control' style='width: 200px; position: relative'>").appendTo(h);a.contr
ol_element.slider({range:true,min:Number.MAX_VALUE,max:-Number.MIN_VALUE,values:[0,0],slide:function(l,m){var k=m.values;d.text("["+k[0]+"-"+k[1]+"]");a.low=k[0];a.high=k[1];c.draw(true)},change:function(k,l){a.control_element.slider("option","slide").call(a.control_element,k,l)}});a.slider=a.control_element;a.slider_label=d}this.content_div=$("<div class='track-content'>").appendTo(this.container_div);this.parent_element.append(this.container_div)},init_each:function(c,b){var a=this;a.enabled=false;a.data_queue={};a.tile_cache.clear();a.data_cache.clear();a.initial_canvas=undefined;a.content_div.css("height","auto");if(!a.content_div.text()){a.content_div.text(DATA_LOADING)}a.container_div.removeClass("nodata error pending");if(a.view.chrom){$.getJSON(data_url,c,function(d){if(!d||d==="error"||d.kind==="error"){a.container_div.addClass("error");a.content_div.text(DATA_ERROR);if(d.message){var f=a.view.tracks.indexOf(a);var e=$("<a href='javascript:void(0);'></a>").attr("id"
,f+"_error");e.text("Click to view error");$("#"+f+"_error").live("click",function(){show_modal("Trackster Error","<pre>"+d.message+"</pre>",{Close:hide_modal})});a.content_div.append(e)}}else{if(d==="no converter"){a.container_div.addClass("error");a.content_div.text(DATA_NOCONVERTER)}else{if(d.data!==undefined&&(d.data===null||d.data.length===0)){a.container_div.addClass("nodata");a.content_div.text(DATA_NONE)}else{if(d==="pending"){a.container_div.addClass("pending");a.content_div.text(DATA_PENDING);setTimeout(function(){a.init()},5000)}else{a.content_div.text("");a.content_div.css("height",a.height_px+"px");a.enabled=true;b(d);a.draw()}}}}})}else{a.container_div.addClass("nodata");a.content_div.text(DATA_NONE)}}});var TiledTrack=function(){var d=this,c=d.view;if(d.hidden){return}if(d.display_modes!==undefined){if(d.mode_div===undefined){d.mode_div=$("<div class='right-float menubutton popup' />").appendTo(d.header_div);var h=d.display_modes[0];d.mode=h;d.mode_div.text(h)
;var a=function(j){d.mode_div.text(j);d.mode=j;d.tile_cache.clear();d.draw()};var f={};for(var e in d.display_modes){var g=d.display_modes[e];f[g]=function(j){return function(){a(j)}}(g)}make_popupmenu(d.mode_div,f)}else{d.mode_div.hide()}}var b={};b["Set as overview"]=function(){c.overview_viewport.find("canvas").remove();d.is_overview=true;d.set_overview();for(var j in c.tracks){if(c.tracks[j]!==d){c.tracks[j].is_overview=false}}};b["Edit configuration"]=function(){var l=function(){hide_modal();$(window).unbind("keypress.check_enter_esc")},j=function(){d.update_options(d.track_id);hide_modal();$(window).unbind("keypress.check_enter_esc")},k=function(m){if((m.keyCode||m.which)===27){l()}else{if((m.keyCode||m.which)===13){j()}}};$(window).bind("keypress.check_enter_esc",k);show_modal("Configure Track",d.gen_options(d.track_id),{Cancel:l,OK:j})};if(d.filters.length>0){b["Show filters"]=function(){var j;if(!d.filtering_div.is(":visible")){j="Hide filters";d.filters_visible=tru
e}else{j="Show filters";d.filters_visible=false}$("#"+d.name_div.attr("id")+"-menu").find("li").eq(2).text(j);d.filtering_div.toggle()}}b.Remove=function(){c.remove_track(d);if(c.num_tracks===0){$("#no-tracks").show()}};d.popup_menu=make_popupmenu(d.name_div,b);show_hide_popupmenu_options(d.popup_menu,"(Show|Hide) filters",false)};$.extend(TiledTrack.prototype,Track.prototype,{draw:function(b){var m=this.view.low,g=this.view.high,h=g-m,f=this.view.resolution;var p=$("<div style='position: relative;'></div>"),q=this.content_div.width()/h,k;this.content_div.append(p),this.max_height=0;var a=Math.floor(m/f/DENSITY);var l=new Object();while((a*DENSITY*f)<g){var n=this.content_div.width()+"_"+q+"_"+a;var e=this.tile_cache.get(n);if(!b&&e){var j=a*DENSITY*f;var d=(j-m)*q;if(this.left_offset){d-=this.left_offset}e.css({left:d});this.show_tile(e,p)}else{this.delayed_draw(this,n,m,g,a,f,p,q,l)}a+=1}var c=this;var o=setInterval(function(){if(l.length!=0){if(c.content_div.children().le
ngth>1){c.content_div.children(":first").remove()}for(var r=0;r<c.filters.length;r++){c.filters[r].update_ui_elt()}clearInterval(o)}},50)},delayed_draw:function(c,h,g,e,b,d,j,k,f){var a=setTimeout(function(){if(!(g>c.view.high||e<c.view.low)){tile_element=c.draw_tile(d,b,j,k);if(tile_element){if(!c.initial_canvas&&!window.G_vmlCanvasManager){c.initial_canvas=$(tile_element).clone();var n=tile_element.get(0).getContext("2d");var l=c.initial_canvas.get(0).getContext("2d");var m=n.getImageData(0,0,n.canvas.width,n.canvas.height);l.putImageData(m,0,0);c.set_overview()}c.tile_cache.set(h,tile_element);c.show_tile(tile_element,j)}}delete f.id},50);f.id=true},show_tile:function(a,c){var b=this;c.append(a);b.max_height=Math.max(b.max_height,a.height());b.content_div.css("height",b.max_height+"px");if(a.hasClass(FILTERABLE_CLASS)){show_hide_popupmenu_options(b.popup_menu,"(Show|Hide) filters");if(b.filters_visible){b.filtering_div.show()}}else{show_hide_popupmenu_options(b.popup_menu
,"(Show|Hide) filters",false);b.filtering_div.hide()}},set_overview:function(){var a=this.view;if(this.initial_canvas&&this.is_overview){a.overview_close.show();a.overview_viewport.append(this.initial_canvas);a.overview_highlight.show().height(this.initial_canvas.height());a.overview_viewport.height(this.initial_canvas.height()+a.overview_box.height())}$(window).trigger("resize")}});var LabelTrack=function(a,b){this.track_type="LabelTrack";this.hidden=true;Track.call(this,null,a,b);this.container_div.addClass("label-track")};$.extend(LabelTrack.prototype,Track.prototype,{draw:function(){var c=this.view,d=c.high-c.low,g=Math.floor(Math.pow(10,Math.floor(Math.log(d)/Math.log(10)))),a=Math.floor(c.low/g)*g,e=this.content_div.width(),b=$("<div style='position: relative; height: 1.3em;'></div>");while(a<c.high){var f=(a-c.low)/d*e;b.append($("<div class='label'>"+commatize(a)+"</div>").css({position:"absolute",left:f-1}));a+=g}this.content_div.children(":first").remove();this.con
tent_div.append(b)}});var ReferenceTrack=function(a){this.track_type="ReferenceTrack";this.hidden=true;Track.call(this,null,a,a.top_labeltrack);TiledTrack.call(this);this.left_offset=200;this.height_px=12;this.container_div.addClass("reference-track");this.data_queue={};this.data_cache=new Cache(CACHED_DATA);this.tile_cache=new Cache(CACHED_TILES_LINE)};$.extend(ReferenceTrack.prototype,TiledTrack.prototype,{get_data:function(d,b){var c=this,a=b*DENSITY*d,f=(b+1)*DENSITY*d,e=d+"_"+b;if(!c.data_queue[e]){c.data_queue[e]=true;$.ajax({url:reference_url,dataType:"json",data:{chrom:this.view.chrom,low:a,high:f,dbkey:this.view.dbkey},success:function(g){c.data_cache.set(e,g);delete c.data_queue[e];c.draw()},error:function(h,g,j){console.log(h,g,j)}})}},draw_tile:function(f,b,l,p){var g=b*DENSITY*f,d=DENSITY*f,k=f+"_"+b;var e=document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(e)}e=$(e);var o=e.get(0).getContext("2d");if(p>PX_PER_CHAR){if(t
his.data_cache.get(k)===undefined){this.get_data(f,b);return}var n=this.data_cache.get(k);if(n===null){this.content_div.css("height","0px");return}e.get(0).width=Math.ceil(d*p+this.left_offset);e.get(0).height=this.height_px;e.css({position:"absolute",top:0,left:(g-this.view.low)*p-this.left_offset});for(var h=0,m=n.length;h<m;h++){var a=Math.round(h*p),j=Math.round(p/2);o.fillText(n[h],a+this.left_offset+j,10)}l.append(e);return e}this.content_div.css("height","0px")}});var LineTrack=function(d,b,a,c){this.track_type="LineTrack";this.display_modes=["Histogram","Line","Filled","Intensity"];this.mode="Histogram";Track.call(this,d,b,b.viewport_container);TiledTrack.call(this);this.height_px=80;this.dataset_id=a;this.data_cache=new Cache(CACHED_DATA);this.tile_cache=new Cache(CACHED_TILES_LINE);this.prefs={color:"black",min_value:undefined,max_value:undefined,mode:this.mode}};$.extend(LineTrack.prototype,TiledTrack.prototype,{init:function(){var a=this,b=a.view.tracks.indexOf(a
);a.vertical_range=undefined;this.init_each({stats:true,chrom:a.view.chrom,low:null,high:null,dataset_id:a.dataset_id},function(c){a.container_div.addClass("line-track");data=c.data;if(isNaN(parseFloat(a.prefs.min_value))||isNaN(parseFloat(a.prefs.max_value))){a.prefs.min_value=data.min;a.prefs.max_value=data.max;$("#track_"+b+"_minval").val(a.prefs.min_value);$("#track_"+b+"_maxval").val(a.prefs.max_value)}a.vertical_range=a.prefs.max_value-a.prefs.min_value;a.total_frequency=data.total_frequency;a.container_div.find(".yaxislabel").remove();var e=$("<div />").addClass("yaxislabel").attr("id","linetrack_"+b+"_minval").text(round_1000(a.prefs.min_value));var d=$("<div />").addClass("yaxislabel").attr("id","linetrack_"+b+"_maxval").text(round_1000(a.prefs.max_value));d.css({position:"absolute",top:"22px",left:"10px"});d.prependTo(a.container_div);e.css({position:"absolute",top:a.height_px+11+"px",left:"10px"});e.prependTo(a.container_div)})},get_data:function(d,b){var c=this,a
=b*DENSITY*d,f=(b+1)*DENSITY*d,e=d+"_"+b;if(!c.data_queue[e]){c.data_queue[e]=true;$.ajax({url:data_url,dataType:"json",data:{chrom:this.view.chrom,low:a,high:f,dataset_id:this.dataset_id,resolution:this.view.resolution},success:function(g){data=g.data;c.data_cache.set(e,data);delete c.data_queue[e];c.draw()},error:function(h,g,j){console.log(h,g,j)}})}},draw_tile:function(p,s,c,e){if(this.vertical_range===undefined){return}var t=s*DENSITY*p,a=DENSITY*p,w=p+"_"+s;var b=document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(b)}b=$(b);if(this.data_cache.get(w)===undefined){this.get_data(p,s);return}var j=this.data_cache.get(w);if(j===null){return}b.css({position:"absolute",top:0,left:(t-this.view.low)*e});b.get(0).width=Math.ceil(a*e);b.get(0).height=this.height_px;var o=b.get(0).getContext("2d"),k=false,l=this.prefs.min_value,g=this.prefs.max_value,n=this.vertical_range,u=this.total_frequency,d=this.height_px,m=this.mode;o.beginPath();o.
fillStyle=this.prefs.color;if(data.length>1){var f=Math.ceil((data[1][0]-data[0][0])*e)}else{var f=10}var v,h;for(var q=0,r=data.length;q<r;q++){v=Math.round((data[q][0]-t)*e);h=data[q][1];if(h===null){if(k&&m==="Filled"){o.lineTo(v,d)}k=false;continue}if(h<l){h=l}else{if(h>g){h=g}}if(m==="Histogram"){h=Math.round(d-(h-l)/n*d);o.fillRect(v,h,f,d-h)}else{if(m==="Intensity"){h=255-Math.floor((h-l)/n*255);o.fillStyle="rgb("+h+","+h+","+h+")";o.fillRect(v,0,f,d)}else{h=Math.round(d-(h-l)/n*d);if(k){o.lineTo(v,h)}else{k=true;if(m==="Filled"){o.moveTo(v,d);o.lineTo(v,h)}else{o.moveTo(v,h)}}}}}if(m==="Filled"){if(k){o.lineTo(v,d)}o.fill()}else{o.stroke()}c.append(b);return b},gen_options:function(n){var a=$("<div />").addClass("form-row");var e="track_"+n+"_color",b=$("<label />").attr("for",e).text("Color:"),c=$("<input />").attr("id",e).attr("name",e).val(this.prefs.color),h="track_"+n+"_minval",m=$("<label></label>").attr("for",h).text("Min value:"),d=(this.prefs.min_value===und
efined?"":this.prefs.min_value),l=$("<input></input>").attr("id",h).val(d),k="track_"+n+"_maxval",g=$("<label></label>").attr("for",k).text("Max value:"),j=(this.prefs.max_value===undefined?"":this.prefs.max_value),f=$("<input></input>").attr("id",k).val(j);return a.append(m).append(l).append(g).append(f).append(b).append(c)},update_options:function(c){var a=$("#track_"+c+"_minval").val(),b=$("#track_"+c+"_maxval").val();color=$("#track_"+c+"_color").val();if(a!==this.prefs.min_value||b!==this.prefs.max_value||color!==this.prefs.color){this.prefs.min_value=parseFloat(a);this.prefs.max_value=parseFloat(b);this.prefs.color=color;this.vertical_range=this.prefs.max_value-this.prefs.min_value;$("#linetrack_"+c+"_minval").text(this.prefs.min_value);$("#linetrack_"+c+"_maxval").text(this.prefs.max_value);this.tile_cache.clear();this.draw()}}});var FeatureTrack=function(d,b,a,e,c){this.track_type="FeatureTrack";this.display_modes=["Auto","Dense","Squish","Pack"];Track.call(this,d,b,
b.viewport_container,e);TiledTrack.call(this);this.height_px=0;this.container_div.addClass("feature-track");this.dataset_id=a;this.zo_slots={};this.show_labels_scale=0.001;this.showing_details=false;this.vertical_detail_px=10;this.vertical_nodetail_px=2;this.summary_draw_height=30;this.default_font="9px Monaco, Lucida Console, monospace";this.inc_slots={};this.data_queue={};this.s_e_by_tile={};this.tile_cache=new Cache(CACHED_TILES_FEATURE);this.data_cache=new Cache(20);this.left_offset=200;this.prefs={block_color:"#444",label_color:"black",show_counts:true}};$.extend(FeatureTrack.prototype,TiledTrack.prototype,{init:function(){var a=this,b="initial";this.init_each({low:a.view.max_low,high:a.view.max_high,dataset_id:a.dataset_id,chrom:a.view.chrom,resolution:this.view.resolution,mode:a.mode},function(c){a.mode_div.show();a.data_cache.set(b,c);a.draw()})},get_data:function(a,d){var b=this,c=a+"_"+d;if(!b.data_queue[c]){b.data_queue[c]=true;$.getJSON(data_url,{chrom:b.view.chr
om,low:a,high:d,dataset_id:b.dataset_id,resolution:this.view.resolution,mode:this.mode},function(e){b.data_cache.set(c,e);delete b.data_queue[c];b.draw()})}},incremental_slots:function(a,g,b,q){if(!this.inc_slots[a]){this.inc_slots[a]={};this.inc_slots[a].w_scale=a;this.inc_slots[a].mode=q;this.s_e_by_tile[a]={}}var m=this.inc_slots[a].w_scale,y=[],h=0,n=this.view.max_low;var A=[];if(this.inc_slots[a].mode!==q){delete this.inc_slots[a];this.inc_slots[a]={mode:q,w_scale:m};delete this.s_e_by_tile[a];this.s_e_by_tile[a]={}}for(var v=0,w=g.length;v<w;v++){var f=g[v],l=f[0];if(this.inc_slots[a][l]!==undefined){h=Math.max(h,this.inc_slots[a][l]);A.push(this.inc_slots[a][l])}else{y.push(v)}}for(var v=0,w=y.length;v<w;v++){var f=g[y[v]],l=f[0],r=f[1],c=f[2],p=f[3],d=Math.floor((r-n)*m),e=Math.ceil((c-n)*m);if(p!==undefined&&!b){var s=CONTEXT.measureText(p).width;if(d-s<0){e+=s}else{d-=s}}var u=0;while(u<=MAX_FEATURE_DEPTH){var o=true;if(this.s_e_by_tile[a][u]!==undefined){for(var t
=0,z=this.s_e_by_tile[a][u].length;t<z;t++){var x=this.s_e_by_tile[a][u][t];if(e>x[0]&&d<x[1]){o=false;break}}}if(o){if(this.s_e_by_tile[a][u]===undefined){this.s_e_by_tile[a][u]=[]}this.s_e_by_tile[a][u].push([d,e]);this.inc_slots[a][l]=u;h=Math.max(h,u);break}u++}}return h},rect_or_text:function(r,m,s,b,q,f,h,e){r.textAlign="center";var l=0,p=Math.round(m/2);for(cig_id in h){var k=h[cig_id],d="MIDNSHP"[k[0]],n=k[1];if(d==="H"||d==="S"){l-=n}var g=q+l,v=Math.floor(Math.max(0,(g-s)*m)),j=Math.floor(Math.max(0,(g+n-s)*m));switch(d){case"S":case"H":case"M":var o=f.slice(l,n);if((this.mode==="Pack"||this.mode==="Auto")&&f!==undefined&&m>PX_PER_CHAR){r.fillStyle=this.prefs.block_color;r.fillRect(v+this.left_offset,e+1,j-v,9);r.fillStyle=CONNECTOR_COLOR;for(var t=0,a=o.length;t<a;t++){if(g+t>=s&&g+t<=b){var u=Math.floor(Math.max(0,(g+t-s)*m));r.fillText(o[t],u+this.left_offset+p,e+9)}}}else{r.fillStyle=this.prefs.block_color;r.fillRect(v+this.left_offset,e+4,j-v,3)}break;case"N":
r.fillStyle=CONNECTOR_COLOR;r.fillRect(v+this.left_offset,e+5,j-v,1);break;case"D":r.fillStyle="red";r.fillRect(v+this.left_offset,e+4,j-v,3);break;case"P":case"I":break}l+=n}},draw_tile:function(ah,o,t,aw){var O=o*DENSITY*ah,am=(o+1)*DENSITY*ah,N=am-O;var ao=(!this.initial_canvas?"initial":O+"_"+am);var J=this.data_cache.get(ao);var e;if(J===undefined||(this.mode!=="Auto"&&J.dataset_type==="summary_tree")){this.data_queue[[O,am]]=true;this.get_data(O,am);return}var a=Math.ceil(N*aw),r=$("<canvas class='tile'></canvas>"),aj=this.prefs.label_color,l=this.prefs.block_color,s=this.mode,A=25,af=(s==="Squish")||(s==="Dense")&&(s!=="Pack")||(s==="Auto"&&(J.extra_info==="no_detail")),X=this.left_offset,av,E,ax;var r=document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(r)}r=$(r);if(J.dataset_type==="summary_tree"){E=this.summary_draw_height}else{if(s==="Dense"){E=A;ax=10}else{ax=(af?this.vertical_nodetail_px:this.vertical_detail_px);var B=(aw
<0.0001?1/view.zoom_res:aw);E=this.incremental_slots(B,J.data,af,s)*ax+A;av=this.inc_slots[B]}}r.css({position:"absolute",top:0,left:(O-this.view.low)*aw-X});r.get(0).width=a+X;r.get(0).height=E;t.parent().css("height",Math.max(this.height_px,E)+"px");var K=r.get(0).getContext("2d");K.fillStyle=l;K.font=this.default_font;K.textAlign="right";this.container_div.find(".yaxislabel").remove();if(J.dataset_type=="summary_tree"){var Z=J.data,M=J.max,q=J.avg,b=Math.ceil(J.delta*aw);var p=$("<div />").addClass("yaxislabel").text(M);p.css({position:"absolute",top:"22px",left:"10px"});p.prependTo(this.container_div);for(var aq=0,I=Z.length;aq<I;aq++){var ab=Math.floor((Z[aq][0]-O)*aw);var aa=Z[aq][1];if(!aa){continue}var an=aa/M*this.summary_draw_height;K.fillStyle="black";K.fillRect(ab+X,this.summary_draw_height-an,b,an);if(this.prefs.show_counts&&K.measureText(aa).width<b){K.fillStyle="#bbb";K.textAlign="center";K.fillText(aa,ab+X+(b/2),this.summary_draw_height-5)}}e="Summary";t.appe
nd(r);return r}if(J.message){r.css({border:"solid red","border-width":"2px 2px 2px 0px"});K.fillStyle="red";K.textAlign="left";K.fillText(J.message,100+X,ax)}var ae=false;if(J.data.length!=0){ae=true;for(var at=0;at<this.filters.length;at++){if(!this.filters[at].applies_to(J.data[0])){ae=false}}}if(ae){r.addClass(FILTERABLE_CLASS)}var au=J.data;var ap=0;for(var aq=0,I=au.length;aq<I;aq++){var T=au[aq],S=T[0],ar=T[1],ad=T[2],P=T[3];if(av[S]===undefined){continue}var ac=false;var V;for(var at=0;at<this.filters.length;at++){V=this.filters[at];V.update_attrs(T);if(!V.keep(T)){ac=true;break}}if(ac){continue}if(ar<=am&&ad>=O){var ag=Math.floor(Math.max(0,(ar-O)*aw)),L=Math.ceil(Math.min(a,Math.max(0,(ad-O)*aw))),Y=(s==="Dense"?1:(1+av[S]))*ax;if(J.dataset_type==="bai"){var w=T[4];K.fillStyle=l;if(T[5] instanceof Array){var F=Math.floor(Math.max(0,(T[5][0]-O)*aw)),R=Math.ceil(Math.min(a,Math.max(0,(T[5][1]-O)*aw))),D=Math.floor(Math.max(0,(T[6][0]-O)*aw)),z=Math.ceil(Math.min(a,Mat
h.max(0,(T[6][1]-O)*aw)));if(T[5][1]>=O&&T[5][0]<=am){this.rect_or_text(K,aw,O,am,T[5][0],T[5][2],w,Y)}if(T[6][1]>=O&&T[6][0]<=am){this.rect_or_text(K,aw,O,am,T[6][0],T[6][2],w,Y)}if(D>R){K.fillStyle=CONNECTOR_COLOR;K.fillRect(R+X,Y+5,D-R,1)}}else{K.fillStyle=l;this.rect_or_text(K,aw,O,am,ar,P,w,Y)}if(s!=="Dense"&&!af&&ar>O){K.fillStyle=this.prefs.label_color;if(o===0&&ag-K.measureText(P).width<0){K.textAlign="left";K.fillText(S,L+2+X,Y+8)}else{K.textAlign="right";K.fillText(S,ag-2+X,Y+8)}K.fillStyle=l}}else{if(J.dataset_type==="interval_index"){if(af){K.fillStyle=l;K.fillRect(ag+X,Y+5,L-ag,1)}else{var H=T[4],W=T[5],ai=T[6],h=T[7];var G,ak,Q=null,ay=null;if(W&&ai){Q=Math.floor(Math.max(0,(W-O)*aw));ay=Math.ceil(Math.min(a,Math.max(0,(ai-O)*aw)))}if(s!=="Dense"&&P!==undefined&&ar>O){K.fillStyle=aj;if(o===0&&ag-K.measureText(P).width<0){K.textAlign="left";K.fillText(P,L+2+X,Y+8)}else{K.textAlign="right";K.fillText(P,ag-2+X,Y+8)}K.fillStyle=l}if(h){if(H){if(H=="+"){K.fillStyle=
RIGHT_STRAND}else{if(H=="-"){K.fillStyle=LEFT_STRAND}}K.fillRect(ag+X,Y,L-ag,10);K.fillStyle=l}for(var ao=0,g=h.length;ao<g;ao++){var v=h[ao],d=Math.floor(Math.max(0,(v[0]-O)*aw)),U=Math.ceil(Math.min(a,Math.max((v[1]-O)*aw)));if(d>U){continue}G=5;ak=3;K.fillRect(d+X,Y+ak,U-d,G);if(Q!==undefined&&!(d>ay||U<Q)){G=9;ak=1;var al=Math.max(d,Q),C=Math.min(U,ay);K.fillRect(al+X,Y+ak,C-al,G)}}}else{G=9;ak=1;K.fillRect(ag+X,Y+ak,L-ag,G);if(T.strand){if(T.strand=="+"){K.fillStyle=RIGHT_STRAND_INV}else{if(T.strand=="-"){K.fillStyle=LEFT_STRAND_INV}}K.fillRect(ag+X,Y,L-ag,10);K.fillStyle=l}}}}else{if(J.dataset_type==="vcf"){if(af){K.fillStyle=l;K.fillRect(ag+X,Y+5,L-ag,1)}else{var u=T[4],n=T[5],c=T[6];G=9;ak=1;K.fillRect(ag+X,Y,L-ag,G);if(s!=="Dense"&&P!==undefined&&ar>O){K.fillStyle=aj;if(o===0&&ag-K.measureText(P).width<0){K.textAlign="left";K.fillText(P,L+2+X,Y+8)}else{K.textAlign="right";K.fillText(P,ag-2+X,Y+8)}K.fillStyle=l}var m=u+" / "+n;if(ar>O&&K.measureText(m).width<(L-ag)){
K.fillStyle="white";K.textAlign="center";K.fillText(m,X+ag+(L-ag)/2,Y+8);K.fillStyle=l}}}}}ap++}}return r},gen_options:function(j){var a=$("<div />").addClass("form-row");var e="track_"+j+"_block_color",l=$("<label />").attr("for",e).text("Block color:"),m=$("<input />").attr("id",e).attr("name",e).val(this.prefs.block_color),k="track_"+j+"_label_color",g=$("<label />").attr("for",k).text("Text color:"),h=$("<input />").attr("id",k).attr("name",k).val(this.prefs.label_color),f="track_"+j+"_show_count",c=$("<label />").attr("for",f).text("Show summary counts"),b=$('<input type="checkbox" style="float:left;"></input>').attr("id",f).attr("name",f).attr("checked",this.prefs.show_counts),d=$("<div />").append(b).append(c);return a.append(l).append(m).append(g).append(h).append(d)},update_options:function(e){var b=$("#track_"+e+"_block_color").val(),d=$("#track_"+e+"_label_color").val(),c=$("#track_"+e+"_mode option:selected").val(),a=$("#track_"+e+"_show_count").attr("checked");i
f(b!==this.prefs.block_color||d!==this.prefs.label_color||a!==this.prefs.show_counts){this.prefs.block_color=b;this.prefs.label_color=d;this.prefs.show_counts=a;this.tile_cache.clear();this.draw()}}});var ReadTrack=function(d,b,a,e,c){FeatureTrack.call(this,d,b,a,e,c);this.track_type="ReadTrack";this.vertical_detail_px=10;this.vertical_nodetail_px=5};$.extend(ReadTrack.prototype,TiledTrack.prototype,FeatureTrack.prototype,{});
--- a/static/scripts/trackster.js
+++ b/static/scripts/trackster.js
@@ -15,10 +15,15 @@ var DENSITY = 200,
CACHED_TILES_FEATURE = 10,
CACHED_TILES_LINE = 30,
CACHED_DATA = 5,
- CONTEXT = $("<canvas></canvas>").get(0).getContext("2d"),
- PX_PER_CHAR = CONTEXT.measureText("A").width,
+ DUMMY_CANVAS = document.createElement("canvas"),
RIGHT_STRAND, LEFT_STRAND;
+if (window.G_vmlCanvasManager) {
+ G_vmlCanvasManager.initElement(DUMMY_CANVAS);
+}
+CONTEXT = DUMMY_CANVAS.getContext("2d");
+PX_PER_CHAR = CONTEXT.measureText("A").width;
+
var right_img = new Image();
right_img.src = image_path + "/visualization/strand_right.png";
right_img.onload = function() {
@@ -255,6 +260,12 @@ var View = function( container, title, v
this.add_label_track( new LabelTrack( this, this.top_labeltrack ) );
this.add_label_track( new LabelTrack( this, this.nav_labeltrack ) );
+
+ $(window).bind("resize", function() { view.resize_window(); });
+ $(document).bind("redraw", function() { view.redraw(); });
+
+ this.reset();
+ $(window).trigger("resize");
},
update_location: function(low, high) {
this.location_span.text( commatize(low) + ' - ' + commatize(high) );
@@ -348,22 +359,7 @@ var View = function( container, title, v
track.container_div.fadeOut('slow', function() { $(this).remove(); });
delete this.tracks[this.tracks.indexOf(track)];
this.num_tracks -= 1;
- },/* No longer needed as config is done inline, one track at a time
- update_options: function() {
- this.has_changes = true;
- var sorted = $("ul#sortable-ul").sortable('toArray');
- for (var id_i in sorted) {
- var id = sorted[id_i].split("_li")[0].split("track_")[1];
- this.viewport_container.append( $("#track_" + id) );
- }
-
- for (var track_id in view.tracks) {
- var track = view.tracks[track_id];
- if (track && track.update_options) {
- track.update_options(track_id);
- }
- }
- },*/
+ },
reset: function() {
this.low = this.max_low;
this.high = this.max_high;
@@ -391,8 +387,8 @@ var View = function( container, title, v
this.zoom_res = Math.pow( FEATURE_LEVELS, Math.max(0,Math.ceil( Math.log( this.resolution, FEATURE_LEVELS ) / Math.log(FEATURE_LEVELS) )));
// Overview
- var left_px = this.low / (this.max_high - this.max_low) * this.overview_viewport.width();
- var width_px = (this.high - this.low)/(this.max_high - this.max_low) * this.overview_viewport.width();
+ var left_px = ( this.low / (this.max_high - this.max_low) * this.overview_viewport.width() ) || 0;
+ var width_px = ( (this.high - this.low)/(this.max_high - this.max_low) * this.overview_viewport.width() ) || 0;
var min_width_px = 13;
this.overview_box.css({ left: left_px, width: Math.max(min_width_px, width_px) }).show();
@@ -440,6 +436,11 @@ var View = function( container, title, v
this.high = Math.round(cur_center + new_half);
this.redraw();
},
+ resize_window: function() {
+ this.viewport_container.height( this.container.height() - this.nav_container.height() - 45 );
+ this.nav_container.width( this.container.width() );
+ this.redraw();
+ },
reset_overview: function() {
this.overview_viewport.find("canvas").remove();
this.overview_viewport.height(this.default_overview_height);
@@ -816,8 +817,8 @@ var TiledTrack = function() {
if ( !(low > track.view.high || high < track.view.low) ) {
tile_element = track.draw_tile( resolution, tile_index, parent_element, w_scale );
if (tile_element) {
- // Store initial canvas in we need to use it for overview
- if (!track.initial_canvas) {
+ // Store initial canvas in case we need to use it for overview
+ if (!track.initial_canvas && !window.G_vmlCanvasManager) {
track.initial_canvas = $(tile_element).clone();
var src_ctx = tile_element.get(0).getContext("2d");
var tgt_ctx = track.initial_canvas.get(0).getContext("2d");
@@ -905,7 +906,6 @@ var ReferenceTrack = function (view) {
this.left_offset = 200;
this.height_px = 12;
this.container_div.addClass( "reference-track" );
- this.dummy_canvas = $("<canvas></canvas>").get(0).getContext("2d");
this.data_queue = {};
this.data_cache = new Cache(CACHED_DATA);
this.tile_cache = new Cache(CACHED_TILES_LINE);
@@ -934,10 +934,14 @@ var ReferenceTrack = function (view) {
draw_tile: function( resolution, tile_index, parent_element, w_scale ) {
var tile_low = tile_index * DENSITY * resolution,
tile_length = DENSITY * resolution,
- canvas = $("<canvas class='tile'></canvas>"),
- ctx = canvas.get(0).getContext("2d"),
key = resolution + "_" + tile_index;
+ var canvas = document.createElement("canvas");
+ if (window.G_vmlCanvasManager) { G_vmlCanvasManager.initElement(canvas); } // EXCANVAS HACK
+ canvas = $(canvas);
+
+ var ctx = canvas.get(0).getContext("2d");
+
if (w_scale > PX_PER_CHAR) {
if (this.data_cache.get(key) === undefined) {
this.get_data( resolution, tile_index );
@@ -983,8 +987,6 @@ var LineTrack = function ( name, view, d
this.data_cache = new Cache(CACHED_DATA);
this.tile_cache = new Cache(CACHED_TILES_LINE);
this.prefs = { 'color': 'black', 'min_value': undefined, 'max_value': undefined, 'mode': this.mode };
- if (prefs.min_value !== undefined) { this.prefs.min_value = prefs.min_value; }
- if (prefs.max_value !== undefined) { this.prefs.max_value = prefs.max_value; }
};
$.extend( LineTrack.prototype, TiledTrack.prototype, {
init: function() {
@@ -1056,9 +1058,12 @@ var LineTrack = function ( name, view, d
var tile_low = tile_index * DENSITY * resolution,
tile_length = DENSITY * resolution,
- canvas = $("<canvas class='tile'></canvas>"),
key = resolution + "_" + tile_index;
+ var canvas = document.createElement("canvas");
+ if (window.G_vmlCanvasManager) { G_vmlCanvasManager.initElement(canvas); } // EXCANVAS HACK
+ canvas = $(canvas);
+
if (this.data_cache.get(key) === undefined) {
this.get_data( resolution, tile_index );
return;
@@ -1204,9 +1209,6 @@ var FeatureTrack = function ( name, view
this.left_offset = 200;
this.prefs = { 'block_color': '#444', 'label_color': 'black', 'show_counts': true };
- if (prefs.block_color !== undefined) { this.prefs.block_color = prefs.block_color; }
- if (prefs.label_color !== undefined) { this.prefs.label_color = prefs.label_color; }
- if (prefs.show_counts !== undefined) { this.prefs.show_counts = prefs.show_counts; }
};
$.extend( FeatureTrack.prototype, TiledTrack.prototype, {
init: function() {
@@ -1249,7 +1251,6 @@ var FeatureTrack = function ( name, view
var w_scale = this.inc_slots[level].w_scale,
undone = [],
highest_slot = 0, // To measure how big to draw canvas
- dummy_canvas = $("<canvas></canvas>").get(0).getContext("2d"),
max_low = this.view.max_low;
var slotted = [];
@@ -1284,7 +1285,7 @@ var FeatureTrack = function ( name, view
f_end = Math.ceil( (feature_end - max_low) * w_scale );
if (feature_name !== undefined && !no_detail) {
- var text_len = dummy_canvas.measureText(feature_name).width;
+ var text_len = CONTEXT.measureText(feature_name).width;
if (f_start - text_len < 0) {
f_end += text_len;
} else {
@@ -1395,7 +1396,7 @@ var FeatureTrack = function ( name, view
}
var width = Math.ceil( tile_span * w_scale ),
- new_canvas = $("<canvas class='tile'></canvas>"),
+ canvas = $("<canvas class='tile'></canvas>"),
label_color = this.prefs.label_color,
block_color = this.prefs.block_color,
mode = this.mode,
@@ -1404,6 +1405,10 @@ var FeatureTrack = function ( name, view
left_offset = this.left_offset,
slots, required_height, y_scale;
+ var canvas = document.createElement("canvas");
+ if (window.G_vmlCanvasManager) { G_vmlCanvasManager.initElement(canvas); } // EXCANVAS HACK
+ canvas = $(canvas);
+
if (result.dataset_type === "summary_tree") {
required_height = this.summary_draw_height;
} else if (mode === "Dense") {
@@ -1417,16 +1422,16 @@ var FeatureTrack = function ( name, view
slots = this.inc_slots[inc_scale];
}
- new_canvas.css({
+ canvas.css({
position: "absolute",
top: 0,
left: ( tile_low - this.view.low ) * w_scale - left_offset
});
- new_canvas.get(0).width = width + left_offset;
- new_canvas.get(0).height = required_height;
+ canvas.get(0).width = width + left_offset;
+ canvas.get(0).height = required_height;
parent_element.parent().css("height", Math.max(this.height_px, required_height) + "px");
// console.log(( tile_low - this.view.low ) * w_scale, tile_index, w_scale);
- var ctx = new_canvas.get(0).getContext("2d");
+ var ctx = canvas.get(0).getContext("2d");
ctx.fillStyle = block_color;
ctx.font = this.default_font;
ctx.textAlign = "right";
@@ -1460,12 +1465,12 @@ var FeatureTrack = function ( name, view
}
}
cur_mode = "Summary";
- parent_element.append( new_canvas );
- return new_canvas;
+ parent_element.append( canvas );
+ return canvas;
}
if (result.message) {
- new_canvas.css({
+ canvas.css({
border: "solid red",
"border-width": "2px 2px 2px 0px"
});
@@ -1488,7 +1493,7 @@ var FeatureTrack = function ( name, view
}
}
if ( filterable ) {
- new_canvas.addClass(FILTERABLE_CLASS);
+ canvas.addClass(FILTERABLE_CLASS);
}
// Draw data points.
@@ -1680,7 +1685,7 @@ var FeatureTrack = function ( name, view
j++;
}
}
- return new_canvas;
+ return canvas;
}, gen_options: function(track_id) {
var container = $("<div />").addClass("form-row");
--- a/templates/grid_common.mako
+++ b/templates/grid_common.mako
@@ -64,7 +64,7 @@
<span class="search-box"><% value = iff( column.filterable == "standard", column.label.lower(), "") %><input class="search-box-input" id="input-${column.key}-filter" name="f-${column.key}" type="text" value="${value}" size="15"/>
- <button class="submit-image" type="submit" title='Search'/>
+ <button class="submit-image" type="submit" title='Search'><span style="display: none;"></button></span></form>
%else:
--- a/templates/tracks/browser.mako
+++ b/templates/tracks/browser.mako
@@ -62,6 +62,11 @@
<%def name="javascripts()">
${parent.javascripts()}
+
+<!--[if lt IE 9]>
+ <script type='text/javascript' src="${h.url_for('/static/scripts/excanvas.js')}"></script>
+<![endif]-->
+
${h.js( "galaxy.base", "galaxy.panels", "json2", "jquery", "jquery.event.drag", "jquery.autocomplete", "trackster", "jquery.ui.sortable.slider" )}
<script type="text/javascript">
@@ -103,22 +108,6 @@
}
});
%endif
-
- $(document).bind( "redraw", function() {
- view.redraw();
- });
-
- // To adjust the size of the viewport to fit the fixed-height footer
- var refresh = function() {
- if (view !== undefined) {
- view.viewport_container.height( $("#center").height() - $(".nav-container").height() - 40 );
- view.nav_container.width( $("#center").width() );
- view.redraw();
- }
- };
- $(window).bind( "resize", function() { refresh(); } );
- $("#right-border").bind( "click dragend", function() { refresh(); } );
- $(window).trigger( "resize" );
// Execute initializer for EDITOR specific javascript
function init() {
@@ -227,47 +216,6 @@
error: function() { alert("Could not save visualization"); }
});
});
-
- function sidebar_box(track) {
- if (!track.hidden) {
- var track_id = track.track_id,
- label = $('<label for="track_' + track_id + 'title">' + track.name + '</label>'),
- title = $('<div class="historyItemTitle"></div>'),
- icon_div = $('<div class="historyItemButtons"></div>');
- del_icon = $('<a href="#" class="icon-button delete" />'),
- edit_icon = $('<a href="#" class="icon-button edit" />'),
- body = $('<div class="historyItemBody"></div>'),
- li = $('<li class="sortable"></li>').attr("id", "track_" + track_id + "_li"),
- div = $('<div class="historyItemContainer historyItem"></div>'),
- editable = $('<div style="display:none"></div>').attr("id", "track_" + track_id + "_editable");
-
- edit_icon.bind("click", function() {
- $("#track_" + track_id + "_editable").toggle();
- });
- del_icon.bind("click", function() {
- $("#track_" + track_id + "_li").fadeOut('slow', function() { $("#track_" + track_id + "_li").remove(); });
- view.remove_track(track);
- if (view.num_tracks === 0) {
- $("#no-tracks").show();
- }
- });
- icon_div.append(edit_icon).append(del_icon);
- title.append(label).prepend(icon_div);
- if (track.gen_options) {
- editable.append(track.gen_options(track_id)).appendTo(body);
- }
- div.append(title).append(body).appendTo(li);
- $("ul#sortable-ul").append(li);
- }
- };
-
- // Populate sort/move ul
- for (var track_id in view.tracks) {
- var track = view.tracks[track_id];
- sidebar_box(track);
- }
-
- $(window).trigger("resize");
};
});
--- a/templates/visualization/display.mako
+++ b/templates/visualization/display.mako
@@ -3,23 +3,12 @@
<%def name="javascripts()"><% config = item_data %>
${parent.javascripts()}
- ${h.js( "jquery.event.drag", "jquery.autocomplete", "jquery.mousewheel", "trackster" )}
- <script type="text/javascript">
- var view;
- // To adjust the size of the viewport to fit the fixed-height footer
- var refresh = function( e ) {
- if (view !== undefined) {
- view.viewport_container.height( $("#center").height() - $(".nav-container").height() - 40 );
- view.nav_container.width( $("#center").width() );
- view.redraw();
- }
- };
- $(window).bind( "resize", function(e) { refresh(e); } );
- $("#right-border").bind( "click dragend", function(e) { refresh(e); } );
- $(window).trigger( "resize" );
- </script>
+ <!--[if lt IE 9]>
+ <script type='text/javascript' src="${h.url_for('/static/scripts/excanvas.js')}"></script>
+ <![endif]-->
+ ${h.js( "jquery.event.drag", "jquery.autocomplete", "trackster" )}
</%def><%def name="stylesheets()">
@@ -55,16 +44,21 @@
var data_url = "${h.url_for( controller='/tracks', action='data' )}",
reference_url = "${h.url_for( controller='/tracks', action='reference' )}",
chrom_url = "${h.url_for( controller='/tracks', action='chroms' )}",
- view;
-
- var container_element = $("#${visualization.id}");
- view = new View( container_element, "${config.get('chrom')}", "${config.get('title') | h}", "${config.get('vis_id')}", "${config.get('dbkey')}" );
+ view,
+ container_element = $("#${visualization.id}");
+
+ if (container_element.parents(".item-content").length > 0) { // Embedded viz
+ container_element.parents(".item-content").css( { "max-height": "none", "overflow": "visible" } );
+ } else { // Viewing just one shared viz
+ container_element = $("#center");
+ $("#right-border").live("click", function() { view.resize_window(); });
+ }
+ view = new View( container_element, "${config.get('title') | h}", "${config.get('vis_id')}", "${config.get('dbkey')}" );
%for track in config.get('tracks'):
view.add_track(
new ${track["track_type"]}( "${track['name'] | h}", view, ${track['dataset_id']}, ${track['prefs']} )
);
%endfor
- container_element.parents(".item-content").css( { "max-height": "none", "overflow": "visible" } );
</script></%def>
1
0