galaxy-commits
Threads by month
- ----- 2025 -----
- 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

08 Sep '10
# HG changeset patch -- Bitbucket.org
# Project galaxy-dist
# URL http://bitbucket.org/galaxy/galaxy-dist/overview
# User rc
# Date 1282836100 14400
# Node ID cd88e599e8fe64bf86ac059c61b130c8cbaf1b52
# Parent 7b9f46307153d0bba1b2253204ad28695d373313
removed print stmt
--- a/lib/galaxy/model/migrate/versions/0057_request_notify.py
+++ b/lib/galaxy/model/migrate/versions/0057_request_notify.py
@@ -53,9 +53,7 @@ def upgrade():
cmd = "SELECT id, notification FROM request"
result = db_session.execute( cmd )
for r in result:
- print r, str(r[1])
rr = from_json_string(str(r[1]))
- print r[0], type(rr), rr, rr['email'], rr['sample_states']
# remove the 'notify' column
try:
1
0

galaxy-dist commit 7b9f46307153: lims: email notification enhancements
by commits-noreply@bitbucket.org 08 Sep '10
by commits-noreply@bitbucket.org 08 Sep '10
08 Sep '10
# HG changeset patch -- Bitbucket.org
# Project galaxy-dist
# URL http://bitbucket.org/galaxy/galaxy-dist/overview
# User rc
# Date 1282835869 14400
# Node ID 7b9f46307153d0bba1b2253204ad28695d373313
# Parent d24fca10862b5b36ba3dbe8a9f318e2e77ef60f2
lims: email notification enhancements
- changed the notify field in the request table to JSONType to store recipient email address and other config details
- notification of specific sample state changes
- changes made to barcode scan AMQP handler to update sample state to also send email when required
- notification to multiple recipients
- request events history records notifications
- UI enhancements to the edit request page to allow users to change notification configurations
UI enhancements to the request page to show the request type state, user & notification details
--- a/scripts/galaxy_messaging/server/galaxyweb_interface.py
+++ b/scripts/galaxy_messaging/server/galaxyweb_interface.py
@@ -105,3 +105,19 @@ class GalaxyWebInterface(object):
s = ( "!" * ( 8 - len(s) % 8 ) ) + s
# Encrypt
return id_cipher.encrypt( s ).encode( 'hex' )
+
+ def update_request_state(self, request_id, sample_id):
+ params = urllib.urlencode(dict( cntrller='requests_admin',
+ request_id=request_id,
+ sample_id=sample_id))
+ url = self.base_url + "/requests_admin/update_request_state"
+ f = self.opener.open(url, params)
+ print url
+ print params
+ x = f.read()
+
+
+
+
+
+
--- a/templates/requests/common/new_request.mako
+++ b/templates/requests/common/new_request.mako
@@ -85,7 +85,7 @@
</div><div style="clear: both"></div></div>
- </form>
- </div>
+ </form>
+ </div></div>
%endif
--- a/scripts/galaxy_messaging/server/amqp_consumer.py
+++ b/scripts/galaxy_messaging/server/amqp_consumer.py
@@ -16,11 +16,18 @@ import xml.dom.minidom
import subprocess
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
+
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
pkg_resources.require( "amqplib" )
@@ -66,6 +73,7 @@ def get_value_index(dom, tag_name, index
def recv_callback(msg):
global config
+ global webconfig
# check the meesage type.
msg_type = msg.properties['application_headers'].get('msg_type')
log.debug('\nMESSAGE RECVD: '+str(msg_type))
@@ -88,12 +96,20 @@ def recv_callback(msg):
log.debug('Barcode: '+barcode)
log.debug('State: '+state)
# update the galaxy db
- galaxy = GalaxyDbInterface(dbconnstr)
- sample_id = galaxy.get_sample_id(field_name='bar_code', value=barcode)
+ galaxydb = GalaxyDbInterface(dbconnstr)
+ sample_id = galaxydb.get_sample_id(field_name='bar_code', value=barcode)
if sample_id == -1:
log.debug('Invalid barcode.')
return
- galaxy.change_state(sample_id, state)
+ 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), sample_id)
+ galaxyweb.logout()
def main():
if len(sys.argv) < 2:
@@ -108,6 +124,15 @@ def main():
for option in config.options("galaxy_amqp"):
amqp_config[option] = config.get("galaxy_amqp", option)
log.debug(str(amqp_config))
+ # web server config
+ global webconfig
+ webconfig = ConfigParser.ConfigParser()
+ webconfig.read('transfer_datasets.ini')
+
+
+
+
+
conn = amqp.Connection(host=amqp_config['host']+":"+amqp_config['port'],
userid=amqp_config['userid'],
password=amqp_config['password'],
--- a/templates/requests/common/sample_events.mako
+++ b/templates/requests/common/sample_events.mako
@@ -17,6 +17,13 @@
%endif
<div class="toolForm">
+ <div class="form-row">
+ <div class="toolParamHelp" style="clear: both;">
+ <b>Possible states: </b>
+ <% states = " > ".join([ ss.name for ss in sample.request.type.states ]) %>
+ ${states}
+ </div>
+ </div><table class="grid"><thead><tr>
--- a/templates/requests/common/edit_request.mako
+++ b/templates/requests/common/edit_request.mako
@@ -37,48 +37,86 @@
<a class="action-button" href="${h.url_for( controller=cntrller, action='list', operation='show', id=trans.security.encode_id(request.id))}"><span>Browse this request</span></a></li>
+ <li>
+ <a class="action-button" href="${h.url_for( controller=cntrller, action='list')}">
+ <span>Browse all requests</span></a>
+ </li></ul><div class="toolForm">
- <div class="toolFormTitle">Edit request "${request.name}"</div>
- %if len(select_request_type.options) == 1:
- There are no request types created for a new request.
- %else:
- <div class="toolFormBody">
- <form name="edit_request" id="edit_request" action="${h.url_for( controller='requests_common', cntrller=cntrller, action='edit', id=trans.security.encode_id(request.id))}" method="post" >
+ <div class="toolFormTitle">Edit sequencing request "${request.name}"</div>
+ <div class="toolFormBody">
+ <form name="edit_request" id="edit_request" action="${h.url_for( controller='requests_common', cntrller=cntrller, action='edit', id=trans.security.encode_id(request.id))}" method="post" >
+ %for i, field in enumerate(widgets):
<div class="form-row">
- <label>
- Select Request Type:
- </label>
- ${select_request_type.get_html()}
+ <label>${field['label']}</label>
+ ${field['widget'].get_html()}
+ %if field['label'] == 'Data library' and new_library:
+ ${new_library.get_html()}
+ %endif
+ <div class="toolParamHelp" style="clear: both;">
+ ${field['helptext']}
+ </div>
+ <div style="clear: both"></div></div>
-
- %if select_request_type.get_selected() != ('Select one', 'none'):
- %for i, field in enumerate(widgets):
- <div class="form-row">
- <label>${field['label']}</label>
- ${field['widget'].get_html()}
- %if field['label'] == 'Data library' and new_library:
- ${new_library.get_html()}
- %endif
- <div class="toolParamHelp" style="clear: both;">
- ${field['helptext']}
- </div>
- <div style="clear: both"></div>
- </div>
- %endfor
- <div class="form-row">
- <div style="float: left; width: 250px; margin-right: 10px;">
- <input type="hidden" name="refresh" value="true" size="40"/>
- </div>
- <div style="clear: both"></div>
- </div>
- <div class="form-row">
- <input type="submit" name="save_changes_request_button" value="Save changes"/>
- ##<input type="submit" name="edit_samples_button" value="Edit samples"/>
- </div>
- %endif
+ %endfor
+ <div class="form-row">
+ <div style="float: left; width: 250px; margin-right: 10px;">
+ <input type="hidden" name="refresh" value="true" size="40"/>
+ </div>
+ <div style="clear: both"></div>
+ </div>
+ <div class="form-row">
+ <input type="submit" name="save_changes_request_button" value="Save"/>
+ </div></form></div>
+ <div class="toolFormTitle">Email notification settings</div>
+ <div class="toolFormBody">
+ <form name="settings" id="settings" action="${h.url_for( controller='requests_common', cntrller=cntrller, action='email_settings', id=trans.security.encode_id(request.id))}" method="post" >
+ <%
+ email_user = ''
+ email_additional = []
+ for e in request.notification['email']:
+ if e == request.user.email:
+ email_user = 'checked'
+ else:
+ email_additional.append(e)
+ emails = '\r\n'.join(email_additional)
+
+ %>
+
+ <div class="form-row">
+ <label>Send to:</label>
+ <input type="checkbox" name="email_user" value="true" ${email_user}>${request.user.email} (Sequencing request owner)<input type="hidden" name="email_user" value="true">
+ </div>
+ <div class="form-row">
+ <label>Additional email addresses:</label>
+ <textarea name="email_additional" rows="3" cols="40">${emails}</textarea>
+ <div class="toolParamHelp" style="clear: both;">
+ Enter one email address per line
+ </div>
+ </div>
+ <div class="form-row">
+ <label>Select sample state(s) to send email notification:</label>
+ %for ss in request.type.states:
+ <%
+ email_state = ''
+ if ss.id in request.notification['sample_states']:
+ email_state = 'checked'
+ %>
+ <input type="checkbox" name=sample_state_${ss.id} value="true" ${email_state} >${ss.name}<input type="hidden" name=sample_state_${ss.id} value="true">
+ <br/>
+ %endfor
+ <div class="toolParamHelp" style="clear: both;">
+ Email notification would be sent when all the samples of this sequencing request are in the selected state(s).
+ </div>
+ </div>
+
+ <div class="form-row">
+ <input type="submit" name="save_button" value="Save"/>
+ </div>
+ </form>
+ </div>
+
</div>
-%endif
--- a/lib/galaxy/model/__init__.py
+++ b/lib/galaxy/model/__init__.py
@@ -15,7 +15,7 @@ from galaxy.datatypes.metadata import Me
from galaxy.security import RBACAgent, get_permitted_actions
from galaxy.util.hash_util import *
from galaxy.web.form_builder import *
-import logging
+import logging, smtplib, socket
log = logging.getLogger( __name__ )
from sqlalchemy.orm import object_session
import pexpect
@@ -1520,18 +1520,27 @@ class Request( object ):
REJECTED = 'Rejected',
COMPLETE = 'Complete' )
def __init__(self, name=None, desc=None, request_type=None, user=None,
- form_values=None, notify=None):
+ form_values=None, notification=None):
self.name = name
self.desc = desc
self.type = request_type
self.values = form_values
self.user = user
- self.notify = notify
+ self.notification = notification
self.samples_list = []
def state(self):
if self.events:
return self.events[0].state
return None
+ def common_state(self):
+ '''
+ This method returns the state of this request's sample when they are all
+ in one common state. If not this returns None
+ '''
+ for s in self.samples:
+ if s.current_state().id != self.samples[0].current_state().id:
+ return False
+ return self.samples[0].current_state()
def last_comment(self):
if self.events:
if self.events[0].comment:
@@ -1560,7 +1569,66 @@ class Request( object ):
if not s.library:
samples.append(s.name)
return samples
+ def send_email_notification(self, trans, common_state, final_state=False):
+ # check if an email notification is configured to be sent when the samples
+ # are in this state
+ if common_state.id not in self.notification['sample_states']:
+ return
+ comments = ''
+ # send email
+ if self.notification['email'] and trans.app.config.smtp_server is not None:
+ host = trans.request.host.split(':')[0]
+ if host in ['localhost', '127.0.0.1']:
+ host = socket.getfqdn()
+
+ body = """
+Galaxy Sample Tracking Notification
+===================================
+User: %(user)s
+
+Sequencing request: %(request_name)s
+Sequencing request type: %(request_type)s
+Sequencing request state: %(request_state)s
+
+Number of samples: %(num_samples)s
+All samples in state: %(sample_state)s
+
+"""
+ values = dict(user=self.user.email,
+ request_name=self.name,
+ request_type=self.type.name,
+ request_state=self.state(),
+ num_samples=str(len(self.samples)),
+ sample_state=common_state.name,
+ create_time=self.create_time,
+ submit_time=self.create_time)
+ body = body % values
+ # check if this is the final state of the samples
+ if final_state:
+ txt = "Sample Name -> Data Library/Folder\r\n"
+ for s in self.samples:
+ txt = txt + "%s -> %s/%s\r\n" % (s.name, s.library.name, s.folder.name)
+ body = body + txt
+ to = self.notification['email']
+ frm = 'galaxy-no-reply@' + host
+ subject = "Galaxy Sample Tracking notification: '%s' sequencing request" % self.name
+ message = "From: %s\r\nTo: %s\r\nSubject: %s\r\n\r\n%s" % (frm, ", ".join(to), subject, body)
+ try:
+ s = smtplib.SMTP()
+ s.connect(trans.app.config.smtp_server)
+ s.sendmail(frm, to, message)
+ s.quit()
+ comments = "Email notification sent to %s." % ", ".join(to).strip().strip(',')
+ except:
+ comments = "Email notification failed."
+ # 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"
+ if comments:
+ event = trans.app.model.RequestEvent(self, self.state(), comments)
+ trans.sa_session.add(event)
+ trans.sa_session.flush()
class RequestEvent( object ):
def __init__(self, request=None, request_state=None, comment=''):
@@ -1581,6 +1649,8 @@ class RequestType( object ):
self.request_form = request_form
self.sample_form = sample_form
self.datatx_info = datatx_info
+ def last_state(self):
+ return self.states[-1]
class RequestTypePermissions( object ):
def __init__( self, action, request_type, role ):
--- a/lib/galaxy/web/controllers/requests_common.py
+++ b/lib/galaxy/web/controllers/requests_common.py
@@ -13,7 +13,7 @@ from sqlalchemy.sql import select
import pexpect
import ConfigParser, threading, time
from amqplib import client_0_8 as amqp
-import csv
+import csv, smtplib, socket
log = logging.getLogger( __name__ )
@@ -151,9 +151,6 @@ class RequestsCommon( BaseController, Us
util.restore_text( params.get( 'desc', '' ) )),
helptext='(Optional)'))
widgets = widgets + request_type.request_form.get_widgets( user, **kwd )
- widgets.append(dict(label='Send email notification when the sequencing request is complete',
- widget=CheckboxField('email_notify', False),
- helptext='Email would be sent to the lab admin and the user for whom this request has been created.'))
return trans.fill_template( '/requests/common/new_request.mako',
cntrller=cntrller,
select_request_type=select_request_type,
@@ -188,17 +185,18 @@ class RequestsCommon( BaseController, Us
'''
params = util.Params( kwd )
cntrller = util.restore_text( params.get( 'cntrller', 'requests' ) )
- request_type = trans.sa_session.query( trans.app.model.RequestType ).get( int( params.select_request_type ) )
if request:
user = request.user
+ request_type = request.type
else:
+ request_type = trans.sa_session.query( trans.app.model.RequestType ).get( int( params.select_request_type ) )
if cntrller == 'requests_admin' and trans.user_is_admin():
user = trans.sa_session.query( trans.app.model.User ).get( int( params.get( 'select_user', '' ) ) )
elif cntrller == 'requests':
user = trans.user
name = util.restore_text(params.get('name', ''))
desc = util.restore_text(params.get('desc', ''))
- notify = CheckboxField.is_checked( params.get('email_notify', '') )
+ notification = dict(email=[user.email], sample_states=[request_type.last_state().id], body='', subject='')
# fields
values = []
for index, field in enumerate(request_type.request_form.fields):
@@ -223,7 +221,7 @@ class RequestsCommon( BaseController, Us
trans.sa_session.flush()
if not request:
request = trans.app.model.Request(name, desc, request_type,
- user, form_values, notify)
+ user, form_values, notification)
trans.sa_session.add( request )
trans.sa_session.flush()
trans.sa_session.refresh( request )
@@ -240,12 +238,66 @@ class RequestsCommon( BaseController, Us
request.desc = desc
request.type = request_type
request.user = user
- request.notify = notify
+ request.notification = notification
request.values = form_values
trans.sa_session.add( request )
trans.sa_session.flush()
return request
-
+ @web.expose
+ @web.require_login( "create/submit sequencing requests" )
+ def email_settings(self, trans, **kwd):
+ params = util.Params( kwd )
+ cntrller = util.restore_text( params.get( 'cntrller', 'requests' ) )
+ message = util.restore_text( params.get( 'message', '' ) )
+ status = params.get( 'status', 'done' )
+ try:
+ request = trans.sa_session.query( trans.app.model.Request ).get( trans.security.decode_id( params.get( 'id', None ) ) )
+ except:
+ return trans.response.send_redirect( web.url_for( controller=cntrller,
+ action='list',
+ status='error',
+ message="Invalid request ID") )
+ email_user = CheckboxField.is_checked( params.get('email_user', '') )
+ email_additional = params.get('email_additional', '').split('\r\n')
+ if email_user or email_additional:
+ emails = []
+ if email_user:
+ emails.append(request.user.email)
+ for e in email_additional:
+ emails.append(util.restore_text(e))
+ # check if valid email addresses
+ invalid = ''
+ for e in emails:
+ if len( e ) == 0 or "@" not in e or "." not in e:
+ invalid = e
+ break
+ if invalid:
+ message = "<b>%s</b> is not a valid email address." % invalid
+ return trans.response.send_redirect( web.url_for( controller='requests_common',
+ cntrller=cntrller,
+ action='edit',
+ show=True,
+ id=trans.security.encode_id(request.id),
+ message=message ,
+ status='error' ) )
+ else:
+ email_states = []
+ for i, ss in enumerate(request.type.states):
+ if CheckboxField.is_checked( params.get('sample_state_%i' % ss.id, '') ):
+ email_states.append(ss.id)
+ request.notification = dict(email=emails, sample_states=email_states,
+ body='', subject='')
+ trans.sa_session.flush()
+ trans.sa_session.refresh( request )
+ message = 'The changes made to the sequencing request has been saved'
+ return trans.response.send_redirect( web.url_for( controller='requests_common',
+ cntrller=cntrller,
+ action='show',
+ id=trans.security.encode_id(request.id),
+ message=message ,
+ status='done') )
+
+
@web.expose
@web.require_login( "create/submit sequencing requests" )
def edit(self, trans, **kwd):
@@ -262,9 +314,8 @@ class RequestsCommon( BaseController, Us
message="Invalid request ID") )
if params.get('show', False) == 'True':
return self.__edit_request(trans, **kwd)
- elif params.get('save_changes_request_button', False) == 'Save changes' \
+ elif params.get('save_changes_request_button', False) == 'Save' \
or params.get('edit_samples_button', False) == 'Edit samples':
- request_type = trans.sa_session.query( trans.app.model.RequestType ).get( int( params.select_request_type ) )
if not util.restore_text(params.get('name', '')):
message = 'Please enter the <b>Name</b> of the request'
kwd['status'] = 'error'
@@ -276,7 +327,7 @@ class RequestsCommon( BaseController, Us
**kwd) )
request = self.__save_request(trans, request, **kwd)
message = 'The changes made to the request named %s has been saved' % request.name
- if params.get('save_changes_request_button', False) == 'Save changes':
+ if params.get('save_changes_request_button', False) == 'Save':
return trans.response.send_redirect( web.url_for( controller=cntrller,
cntrller=cntrller,
action='list',
@@ -310,7 +361,7 @@ class RequestsCommon( BaseController, Us
cntrller = util.restore_text( params.get( 'cntrller', 'requests' ) )
message = util.restore_text( params.get( 'message', '' ) )
status = params.get( 'status', 'done' )
- select_request_type = self.__select_request_type(trans, request.type.id)
+ #select_request_type = self.__select_request_type(trans, request.type.id)
# list of widgets to be rendered on the request form
widgets = []
if util.restore_text( params.get( 'name', '' ) ):
@@ -328,12 +379,9 @@ class RequestsCommon( BaseController, Us
widget=TextField('desc', 40, desc),
helptext='(Optional)'))
widgets = widgets + request.type.request_form.get_widgets( request.user, request.values.content, **kwd )
- widgets.append(dict(label='Send email notification once the sequencing request is complete',
- widget=CheckboxField('email_notify', request.notify),
- helptext=''))
return trans.fill_template( 'requests/common/edit_request.mako',
cntrller=cntrller,
- select_request_type=select_request_type,
+ #select_request_type=select_request_type,
request_type=request.type,
request=request,
widgets=widgets,
@@ -399,6 +447,7 @@ class RequestsCommon( BaseController, Us
trans.sa_session.add( event )
trans.sa_session.add( request )
trans.sa_session.flush()
+ request.send_email_notification(trans, new_state)
return trans.response.send_redirect( web.url_for( controller=cntrller,
action='list',
id=trans.security.encode_id(request.id),
@@ -486,6 +535,22 @@ class RequestsCommon( BaseController, Us
events_list=events_list, request=request)
@web.expose
@web.require_login( "create/submit sequencing requests" )
+ def settings(self, trans, **kwd):
+ params = util.Params( kwd )
+ message = util.restore_text( params.get( 'message', '' ) )
+ cntrller = params.get( 'cntrller', 'requests' )
+ try:
+ request = trans.sa_session.query( trans.app.model.Request ).get( trans.security.decode_id(kwd['id']) )
+ except:
+ return trans.response.send_redirect( web.url_for( controller=cntrller,
+ action='list',
+ status='error',
+ message="Invalid request ID") )
+ return trans.fill_template( '/requests/common/settings.mako',
+ cntrller=cntrller, request=request)
+
+ @web.expose
+ @web.require_login( "create/submit sequencing requests" )
def show(self, trans, **kwd):
params = util.Params( kwd )
message = util.restore_text( params.get( 'message', '' ) )
@@ -807,6 +872,17 @@ class RequestsCommon( BaseController, Us
'Sample added to the system')
trans.sa_session.add( event )
trans.sa_session.flush()
+ # now check if all the samples' barcode has been entered.
+ # If yes then send notification email if configured
+ common_state = request.common_state()
+ if common_state:
+ if common_state.id == request.type.states[1].id:
+ event = trans.app.model.RequestEvent(request,
+ request.states.SUBMITTED,
+ "All samples are in %s state." % common_state.name)
+ trans.sa_session.add( event )
+ trans.sa_session.flush()
+ request.send_email_notification(trans, request.type.states[1])
sample.bar_code = current_samples[sample_index]['barcode']
trans.sa_session.add( sample )
trans.sa_session.flush()
@@ -962,21 +1038,16 @@ class RequestsCommon( BaseController, Us
# list of widgets to be rendered on the request form
request_details = []
# main details
- request_details.append(dict(label='User',
- value=str(request.user.email),
- helptext=''))
request_details.append(dict(label='Description',
value=request.desc,
helptext=''))
- request_details.append(dict(label='Type',
- value=request.type.name,
- helptext=''))
- request_details.append(dict(label='State',
- value=request.state(),
- helptext=''))
request_details.append(dict(label='Date created',
value=request.create_time,
helptext=''))
+ request_details.append(dict(label='Date updated',
+ value=request.update_time,
+ helptext=''))
+
# form fields
for index, field in enumerate(request.type.request_form.fields):
if field['required']:
@@ -996,13 +1067,6 @@ class RequestsCommon( BaseController, Us
request_details.append(dict(label=field['label'],
value=request.values.content[index],
helptext=field['helptext']+' ('+req+')'))
- if request.notify:
- notify = 'Yes'
- else:
- notify = 'No'
- request_details.append(dict(label='Send email notification once the sequencing request is complete',
- value=notify,
- helptext=''))
return request_details
@web.expose
@web.require_login( "create/submit sequencing requests" )
@@ -1089,3 +1153,5 @@ class RequestsCommon( BaseController, Us
dataset_files=sample.datasets,
message=message, status=status, files=[],
folder_path=folder_path )
+
+
--- a/templates/requests/common/show_request.mako
+++ b/templates/requests/common/show_request.mako
@@ -131,21 +131,35 @@ function showContent(vThis)
document.onkeypress = stopRKey
</script>
-%if request.submitted():
- <% samples_not_ready = request.sequence_run_ready() %>
- %if samples_not_ready:
- ${render_msg( "Select a target library and folder for all the samples before starting the sequence run", "warning" )}
- %endif
+<% samples_not_ready = request.sequence_run_ready() %>
+%if samples_not_ready:
+ ${render_msg( "Select a target data library and folder for all the samples before starting the sequence run", "warning" )}
%endif
%if request.rejected():
${render_msg( "Reason for rejection: "+request.last_comment(), "warning" )}
%endif
+%if message:
+ ${render_msg( message, status )}
+%endif
+
<div class="grid-header"><h2>Sequencing Request "${request.name}"</h2>
+ <div class="toolParamHelp" style="clear: both;">
+ <b>Type</b>: ${request.type.name}
+ %if cntrller == 'requests_admin':
+ | <b>User</b>: ${request.user.email}
+ %endif
+ %if request.state() == request.states.SUBMITTED:
+ | <b>State</b>: <i>${request.state()}</i>
+ %else:
+ | <b>State</b>: ${request.state()}
+ %endif
+ </div>
+
</div>
-
+<br/><ul class="manage-table-actions"><li><a class="action-button" id="seqreq-${request.id}-popup" class="menubutton">Sequencing Request Actions</a></li><div popupmenu="seqreq-${request.id}-popup">
@@ -153,10 +167,10 @@ function showContent(vThis)
<a class="action-button" confirm="More samples cannot be added to this request once it is submitted. Click OK to submit." href="${h.url_for( controller=cntrller, action='list', operation='Submit', id=trans.security.encode_id(request.id) )}"><span>Submit</span></a>
%endif
+ <a class="action-button" href="${h.url_for( controller=cntrller, action='list', operation='events', id=trans.security.encode_id(request.id) )}">
+ <span>History</span></a><a class="action-button" href="${h.url_for( controller=cntrller, action='list', operation='Edit', id=trans.security.encode_id(request.id))}"><span>Edit</span></a>
- <a class="action-button" href="${h.url_for( controller=cntrller, action='list', operation='events', id=trans.security.encode_id(request.id) )}">
- <span>History</span></a>
%if cntrller == 'requests_admin' and trans.user_is_admin():
%if request.submitted():
<a class="action-button" href="${h.url_for( controller=cntrller, action='list', operation='reject', id=trans.security.encode_id(request.id))}">
@@ -173,41 +187,71 @@ function showContent(vThis)
</ul>
-%if message:
- ${render_msg( message, status )}
-%endif
<div>
-<h3><img src="/static/images/fugue/toggle-expand.png" alt="Show" onclick="showContent(this);" style="cursor:pointer;"/> Request Information</h3>
-<div style="display:none;" >
- %for index, rd in enumerate(request_details):
- <div class="form-row">
- <label>${rd['label']}</label>
- %if not rd['value']:
- <i>None</i>
- %else:
- %if rd['label'] == 'State':
- <a href="${h.url_for( controller=cntrller, action='list', operation='events', id=trans.security.encode_id(request.id) )}">${rd['value']}</a>
- %else:
- ${rd['value']}
- %endif
- %endif
- </div>
- <div style="clear: both"></div>
- %endfor
- <div class="form-row">
- <ul class="manage-table-actions">
- <li>
- <a class="action-button" href="${h.url_for( controller=cntrller, action='list', operation='Edit', id=trans.security.encode_id(request.id))}">
- <span>Edit request details</span></a>
- </li>
- </ul>
- </div>
+ <h4><img src="/static/images/fugue/toggle-expand.png" alt="Show" onclick="showContent(this);" style="cursor:pointer;"/> Request Information</h4>
+ <div style="display:none;" >
+ <table class="grid" border="0">
+ <tbody>
+ <tr>
+ <td valign="top" width="50%">
+ %for index, rd in enumerate(request_details):
+ <div class="form-row">
+ <label>${rd['label']}:</label>
+ %if not rd['value']:
+ <i>None</i>
+ %else:
+ %if rd['label'] == 'State':
+ <a href="${h.url_for( controller=cntrller, action='list', operation='events', id=trans.security.encode_id(request.id) )}">${rd['value']}</a>
+ %else:
+ ${rd['value']}
+ %endif
+ %endif
+ </div>
+ <div style="clear: both"></div>
+ %endfor
+ </td>
+ <td valign="top" width="50%">
+ <div class="form-row">
+ <label>Email notification recipient(s):</label>
+ <% emails = ', '.join(request.notification['email']) %>
+ %if emails:
+ ${emails}
+ %else:
+ <i>None</i>
+ %endif
+ </div>
+ <div style="clear: both"></div>
+ <div class="form-row">
+ <label>Email notification on sample state(s):</label>
+ <%
+ states = []
+ for ss in request.type.states:
+ if ss.id in request.notification['sample_states']:
+ states.append(ss.name)
+ states = ', '.join(states)
+ %>
+ %if states:
+ ${states}
+ %else:
+ <i>None</i>
+ %endif
+ </div>
+ <div style="clear: both"></div>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ <div class="form-row">
+ <ul class="manage-table-actions">
+ <li>
+ <a class="action-button" href="${h.url_for( controller=cntrller, action='list', operation='Edit', id=trans.security.encode_id(request.id))}">
+ <span>Edit request information</span></a>
+ </li>
+ </ul>
+ </div>
+ </div></div>
-</div>
-
-
-
<br/>
@@ -395,12 +439,7 @@ function showContent(vThis)
<td>${info['name']}</td><td>${info['barcode']}</td>
%if sample.request.unsubmitted():
- ##<td>Unsubmitted</td>
- <td>
- <div id="history-name-container">
- <div id="history-name" class="tooltip editable-text" title="Click to rename history">Unsubmitted</div>
- </div>
- </td>
+ <td>Unsubmitted</td>
%else:
<td id="sampleState-${sample.id}">${render_sample_state( cntrller, sample )}</td>
%endif
--- a/lib/galaxy/web/controllers/requests_admin.py
+++ b/lib/galaxy/web/controllers/requests_admin.py
@@ -136,6 +136,7 @@ class RequestsGrid( grids.Grid ):
grids.GridOperation( "Reject", allow_multiple=False, condition=( lambda item: not item.deleted and item.submitted() ) ),
grids.GridOperation( "Delete", allow_multiple=True, condition=( lambda item: not item.deleted ) ),
grids.GridOperation( "Undelete", condition=( lambda item: item.deleted ) ),
+ grids.GridOperation( "Purge", allow_multiple=False, confirm="This will permanently delete the sequencing request. Click OK to proceed.", condition=( lambda item: item.deleted ) ),
]
global_actions = [
grids.GridAction( "Create new request", dict( controller='requests_common',
@@ -317,11 +318,6 @@ class RequestsAdmin( BaseController ):
cntrller='requests_admin',
action='events',
**kwd ) )
- if operation == "settings":
- return trans.response.send_redirect( web.url_for( controller='requests_common',
- cntrller='requests_admin',
- action='settings',
- **kwd ) )
elif operation == "reject":
return self.__reject_request( trans, **kwd )
elif operation == "view_type":
@@ -514,41 +510,52 @@ class RequestsAdmin( BaseController ):
id=trans.security.encode_id(request.id),
message='Bar codes have been saved for this request',
status='done'))
- def __set_request_state( self, trans, request ):
- # check if all the samples of the current request are in the final state
- complete = True
- for s in request.samples:
- if s.current_state().id != request.type.states[-1].id:
- complete = False
- if request.complete() and not complete:
- comments = "One or more samples moved back from the %s state" % request.type.states[-1].name
- event = trans.app.model.RequestEvent(request, request.states.SUBMITTED, comments)
- trans.sa_session.add( event )
- trans.sa_session.flush()
- elif complete:
- # change the request state to 'Complete'
- comments = "All samples of this request are in the last sample state (%s)." % request.type.states[-1].name
- event = trans.app.model.RequestEvent(request, request.states.COMPLETE, comments)
- trans.sa_session.add( event )
- trans.sa_session.flush()
- # now that the request is complete send the email notification to the
- # the user
- if request.notify and trans.app.config.smtp_server is not None:
- host = trans.request.host.split(':')[0]
- if host == 'localhost':
- host = socket.getfqdn()
- body = "The '%s' sequencing request (type: %s) is now complete. Datasets from all the samples are now available for analysis or download from the respective data libraries in Galaxy." % ( request.name, request.type.name )
- to = [request.user.email]
- frm = 'galaxy-no-reply@' + host
- subject = "Galaxy Sample Tracking: '%s' sequencing request in complete." % request.name
- message = "From: %s\r\nTo: %s\r\nSubject: %s\r\n\r\n%s" % (frm, ", ".join(to), subject, body)
- try:
- s = smtplib.SMTP()
- s.connect( trans.app.config.smtp_server )
- s.sendmail( frm, [ to ], message )
- s.close()
- except:
- pass
+ @web.expose
+ @web.require_admin
+ def update_request_state( self, trans, **kwd ):
+ params = util.Params( kwd )
+ try:
+ request = trans.sa_session.query( trans.app.model.Request ).get( int( params.get( 'request_id', None ) ) )
+ sample_id = int(params.get('sample_id', False))
+ except:
+ return trans.response.send_redirect( web.url_for( controller='requests_admin',
+ action='list',
+ status='error',
+ message="Invalid request ID",
+ **kwd) )
+ # check if all the samples of the current request are in the sample state
+ common_state = request.common_state()
+ if not common_state:
+ # if the current request state is complete and one of its samples moved from
+ # the final sample state, then move the request state to In-progress
+ if request.complete():
+ event = trans.app.model.RequestEvent(request, request.states.SUBMITTED, "One or more samples' state moved from the final sample state.")
+ trans.sa_session.add( event )
+ trans.sa_session.flush()
+ return trans.response.send_redirect( web.url_for( controller='requests_common',
+ cntrller='requests_admin',
+ action='sample_events',
+ sample_id=sample_id))
+ final_state = False
+ if common_state.id == request.type.last_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.last_state().name
+ state = request.states.COMPLETE
+ final_state = True
+ else:
+ comments = "All samples are in %s state." % common_state.name
+ state = request.states.SUBMITTED
+ event = trans.app.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
+ # are in this state
+# if common_state.id in request.notification['sample_states']:
+ request.send_email_notification(trans, common_state, final_state)
+ return trans.response.send_redirect( web.url_for( controller='requests_common',
+ cntrller='requests_admin',
+ action='sample_events',
+ sample_id=sample_id))
@web.expose
@web.require_admin
@@ -573,10 +580,10 @@ class RequestsAdmin( BaseController ):
event = trans.app.model.SampleEvent(sample, new_state, comments)
trans.sa_session.add( event )
trans.sa_session.flush()
- self.__set_request_state( trans, sample.request )
- return trans.response.send_redirect( web.url_for( controller='requests_common',
+ return trans.response.send_redirect( web.url_for( controller='requests_admin',
cntrller='requests_admin',
- action='sample_events',
+ action='update_request_state',
+ request_id=sample.request.id,
sample_id=sample.id))
#
# Data transfer from sequencer
@@ -1290,3 +1297,6 @@ class RequestsAdmin( BaseController ):
roles=roles,
status=status,
message=message)
+
+
+
--- a/test/base/twilltestcase.py
+++ b/test/base/twilltestcase.py
@@ -1503,7 +1503,7 @@ class TwillTestCase( unittest.TestCase )
def edit_request( self, request_id, name, new_name, new_desc, new_fields):
self.home()
self.visit_url( "%s/requests/list?operation=Edit&id=%s" % (self.url, self.security.encode_id(request_id) ) )
- self.check_page_for_string( 'Edit request "%s"' % name )
+ self.check_page_for_string( 'Edit sequencing request "%s"' % name )
tc.fv( "1", "name", new_name )
tc.fv( "1", "desc", new_desc )
for index, field_value in enumerate(new_fields):
--- a/lib/galaxy/model/mapping.py
+++ b/lib/galaxy/model/mapping.py
@@ -560,7 +560,7 @@ Request.table = Table('request', metadat
Column( "update_time", DateTime, default=now, onupdate=now ),
Column( "name", TrimmedString( 255 ), nullable=False ),
Column( "desc", TEXT ),
- Column( "notify", Boolean, default=False ),
+ Column( "notification", JSONType() ),
Column( "form_values_id", Integer, ForeignKey( "form_values.id" ), index=True ),
Column( "request_type_id", Integer, ForeignKey( "request_type.id" ), index=True ),
Column( "user_id", Integer, ForeignKey( "galaxy_user.id" ), index=True ),
--- /dev/null
+++ b/lib/galaxy/model/migrate/versions/0057_request_notify.py
@@ -0,0 +1,69 @@
+"""
+Migration script to modify the 'notify' field in the 'request' table from a boolean
+to a JSONType
+"""
+
+from sqlalchemy import *
+from sqlalchemy.orm import *
+from migrate import *
+from migrate.changeset import *
+from sqlalchemy.exc import *
+
+from galaxy.model.custom_types import *
+from galaxy.util.json import from_json_string, to_json_string
+
+import datetime
+now = datetime.datetime.utcnow
+
+import logging
+log = logging.getLogger( __name__ )
+
+metadata = MetaData( migrate_engine )
+db_session = scoped_session( sessionmaker( bind=migrate_engine, autoflush=False, autocommit=True ) )
+
+
+def upgrade():
+ print __doc__
+ metadata.reflect()
+ try:
+ Request_table = Table( "request", metadata, autoload=True )
+ except NoSuchTableError, e:
+ Request_table = None
+ log.debug( "Failed loading table 'request'" )
+
+
+ if Request_table:
+ # create the column again as JSONType
+ try:
+ col = Column( "notification", JSONType() )
+ col.create( Request_table )
+ assert col is Request_table.c.notification
+ except Exception, e:
+ log.debug( "Creating column 'notification' in the 'request' table failed: %s" % ( str( e ) ) )
+
+ cmd = "SELECT id, user_id, notify FROM request"
+ result = db_session.execute( cmd )
+ for r in result:
+ id = int(r[0])
+ notify_old = r[1]
+ notify_new = dict(email=[], sample_states=[], body='', subject='')
+ cmd = "update request set notification='%s' where id=%i" % (to_json_string(notify_new), id)
+ db_session.execute( cmd )
+
+ cmd = "SELECT id, notification FROM request"
+ result = db_session.execute( cmd )
+ for r in result:
+ print r, str(r[1])
+ rr = from_json_string(str(r[1]))
+ print r[0], type(rr), rr, rr['email'], rr['sample_states']
+
+ # remove the 'notify' column
+ try:
+ Request_table.c.notify.drop()
+ except Exception, e:
+ log.debug( "Deleting column 'notify' from the 'request' table failed: %s" % ( str( e ) ) )
+
+
+
+def downgrade():
+ pass
--- a/scripts/galaxy_messaging/server/galaxydb_interface.py
+++ b/scripts/galaxy_messaging/server/galaxydb_interface.py
@@ -57,6 +57,12 @@ class GalaxyDbInterface(object):
#log.debug('Sample ID: %i' % sample_id)
return sample_id
return -1
+
+ def get_request_id(self, sample_id):
+ query = select(columns=[self.sample_table.c.request_id],
+ whereclause=self.sample_table.c.id==sample_id)
+ request_id = query.execute().fetchall()[0][0]
+ return request_id
def current_state(self, sample_id):
'''
1
0

galaxy-dist commit d24fca10862b: Add support for all Galaxy form widget types to data library templates ( library templates now support SelectField, AddressField, CheckboxField, WorkflowField in addition to previously supported TextArea and TextField ).
by commits-noreply@bitbucket.org 08 Sep '10
by commits-noreply@bitbucket.org 08 Sep '10
08 Sep '10
# HG changeset patch -- Bitbucket.org
# Project galaxy-dist
# URL http://bitbucket.org/galaxy/galaxy-dist/overview
# User Greg Von Kuster <greg(a)bx.psu.edu>
# Date 1282834547 14400
# Node ID d24fca10862b5b36ba3dbe8a9f318e2e77ef60f2
# Parent af3ee1e9f9e3c0e51b7b18a323b3fa80460aa864
Add support for all Galaxy form widget types to data library templates ( library templates now support SelectField, AddressField, CheckboxField, WorkflowField in addition to previously supported TextArea and TextField ).
Create a new UsesFormDefinitionWidgets base controller class for use with all inheriting controllers that use Galaxy forms. Clean up some of the existing code by re-using mehtods in this new controller.
Fix bugs related to new user address creation and editing existing user addresses: (1) form contents are now actually checked and if required, error messages are displayed (2) since there is only 1 "address" row in the UserAddress table, eliminate the address1 / address2 form field combination that was appened together for storage in the table ( ther eis now only 1 address line on all forms ).
Fix functional tests to reflect above changes.
--- a/templates/mobile/manage_library.mako
+++ b/templates/mobile/manage_library.mako
@@ -1,7 +1,7 @@
<%inherit file="/base.mako"/><%namespace file="/message.mako" import="render_msg" /><%namespace file="/dataset/security_common.mako" import="render_permission_form" />
-<%namespace file="/library/common/common.mako" import="render_template_info" />
+<%namespace file="/library/common/common.mako" import="render_template_fields" /><% current_user_roles = trans.get_current_user_roles() %>
@@ -59,7 +59,7 @@
</div><div style="clear: both"></div><div class="toolForm">
- ${render_template_info( 'mobile', library, library.id, 'library' )}
+ ${render_template_fields( 'mobile', 'library', trans.security.encode_id( library.id ), widgets, widget_fields_have_contents, info_association, inherited )}
</div></div>
%endif
@@ -69,5 +69,5 @@
%endif
%if widgets:
- ${render_template_info( 'mobile', library, trans.security.encode_id( library.id ), 'edit_library_information', widgets )}
+ ${render_template_fields( 'mobile', 'library', trans.security.encode_id( library.id ), widgets, widget_fields_have_contents, info_association inherited )}
%endif
--- a/templates/library/common/library_dataset_info.mako
+++ b/templates/library/common/library_dataset_info.mako
@@ -1,6 +1,34 @@
<%inherit file="/base.mako"/><%namespace file="/message.mako" import="render_msg" />
-<%namespace file="/library/common/common.mako" import="render_template_info" />
+<%namespace file="/library/common/common.mako" import="render_template_fields" />
+
+<%def name="javascripts()">
+ ${parent.javascripts()}
+ <script type="text/javascript">
+ $( function() {
+ $( "select[refresh_on_change='true']").change( function() {
+ var refresh = false;
+ var refresh_on_change_values = $( this )[0].attributes.getNamedItem( 'refresh_on_change_values' )
+ if ( refresh_on_change_values ) {
+ refresh_on_change_values = refresh_on_change_values.value.split( ',' );
+ var last_selected_value = $( this )[0].attributes.getNamedItem( 'last_selected_value' );
+ for( i= 0; i < refresh_on_change_values.length; i++ ) {
+ if ( $( this )[0].value == refresh_on_change_values[i] || ( last_selected_value && last_selected_value.value == refresh_on_change_values[i] ) ){
+ refresh = true;
+ break;
+ }
+ }
+ }
+ else {
+ refresh = true;
+ }
+ if ( refresh ){
+ $( "#edit_info" ).submit();
+ }
+ });
+ });
+ </script>
+</%def>
%if library_dataset == library_dataset.library_dataset_dataset_association.library_dataset:
<b><i>This is the latest version of this library dataset</i></b>
@@ -63,5 +91,5 @@
%if widgets:
## Templates are not currently supported for library_datasets, only the associated ldda.
- ${render_template_info( cntrller, 'library_dataset', library_id, widgets, info_association=None, inherited=False, editable=False )}
+ ${render_template_fields( cntrller, 'library_dataset', library_id, widgets, widget_fields_have_contents, info_association=None, inherited=False, editable=False )}
%endif
--- a/templates/library/common/folder_info.mako
+++ b/templates/library/common/folder_info.mako
@@ -1,6 +1,34 @@
<%inherit file="/base.mako"/><%namespace file="/message.mako" import="render_msg" />
-<%namespace file="/library/common/common.mako" import="render_template_info" />
+<%namespace file="/library/common/common.mako" import="render_template_fields" />
+
+<%def name="javascripts()">
+ ${parent.javascripts()}
+ <script type="text/javascript">
+ $( function() {
+ $( "select[refresh_on_change='true']").change( function() {
+ var refresh = false;
+ var refresh_on_change_values = $( this )[0].attributes.getNamedItem( 'refresh_on_change_values' )
+ if ( refresh_on_change_values ) {
+ refresh_on_change_values = refresh_on_change_values.value.split( ',' );
+ var last_selected_value = $( this )[0].attributes.getNamedItem( 'last_selected_value' );
+ for( i= 0; i < refresh_on_change_values.length; i++ ) {
+ if ( $( this )[0].value == refresh_on_change_values[i] || ( last_selected_value && last_selected_value.value == refresh_on_change_values[i] ) ){
+ refresh = true;
+ break;
+ }
+ }
+ }
+ else {
+ refresh = true;
+ }
+ if ( refresh ){
+ $( "#edit_info" ).submit();
+ }
+ });
+ });
+ </script>
+</%def><%
from cgi import escape
@@ -53,5 +81,5 @@
</div></div>
%if widgets:
- ${render_template_info( cntrller=cntrller, item_type='folder', library_id=library_id, widgets=widgets, info_association=info_association, inherited=inherited, folder_id=trans.security.encode_id( folder.id ) )}
+ ${render_template_fields( cntrller=cntrller, item_type='folder', library_id=library_id, widgets=widgets, widget_fields_have_contents=widget_fields_have_contents, info_association=info_association, inherited=inherited, folder_id=trans.security.encode_id( folder.id ) )}
%endif
--- a/lib/galaxy/web/form_builder.py
+++ b/lib/galaxy/web/form_builder.py
@@ -384,8 +384,7 @@ class AddressField(BaseField):
return [ ( "short_desc", "Short address description"),
( "name", "Name" ),
( "institution", "Institution" ),
- ( "address1", "Address Line 1" ),
- ( "address2", "Address Line 2" ),
+ ( "address", "Address" ),
( "city", "City" ),
( "state", "State/Province/Region" ),
( "postal_code", "Postal Code" ),
@@ -437,8 +436,7 @@ class AddressField(BaseField):
else:
self.select_address.add_option('Add a new address', 'new')
return self.select_address.get_html()+address_html
-
-
+
class WorkflowField(BaseField):
def __init__(self, name, user=None, value=None, params=None):
self.name = name
--- a/lib/galaxy/web/base/controller.py
+++ b/lib/galaxy/web/base/controller.py
@@ -8,6 +8,7 @@ from galaxy.web import error, form, url_
from galaxy.model.orm import *
from galaxy.workflow.modules import *
from galaxy.web.framework import simplejson
+from galaxy.web.form_builder import AddressField, CheckboxField, SelectField, TextArea, TextField, WorkflowField
from Cheetah.Template import Template
@@ -290,7 +291,57 @@ class UsesHistory( SharableItemSecurity
if not show_deleted:
query = query.filter( trans.model.HistoryDatasetAssociation.deleted == False )
return query.all()
-
+
+class UsesFormDefinitionWidgets:
+ """Mixin for controllers that use Galaxy form objects."""
+ def widget_fields_have_contents( self, widgets ):
+ # Return True if any of the fields in widgets contain contents, widgets is a list of dictionaries that looks something like:
+ # [{'widget': <galaxy.web.form_builder.TextField object at 0x10867aa10>, 'helptext': 'Field 0 help (Optional)', 'label': 'Field 0'}]
+ for i, field in enumerate( widgets ):
+ if ( isinstance( field[ 'widget' ], TextArea ) or isinstance( field[ 'widget' ], TextField ) ) and field[ 'widget' ].value:
+ return True
+ if isinstance( field[ 'widget' ], SelectField ) and field[ 'widget' ].options:
+ for option_label, option_value, selected in field['widget'].options:
+ if selected:
+ return True
+ if isinstance( field[ 'widget' ], CheckboxField ) and field[ 'widget' ].checked:
+ return True
+ if isinstance( field[ 'widget' ], WorkflowField ) and field[ 'widget' ].value not in [ 'none', 'None', None ]:
+ return True
+ if isinstance( field[ 'widget' ], AddressField ) and field[ 'widget' ].value not in [ 'none', 'None', None ]:
+ return True
+ return False
+ def clean_field_contents( self, widgets, **kwd ):
+ params = util.Params( kwd )
+ field_contents = []
+ for index in range( len( widgets ) ):
+ widget = widgets[ index ][ 'widget' ]
+ field_value = params.get( 'field_%i' % ( index ), '' )
+ if isinstance( widget, CheckboxField ):
+ # CheckboxField values are lists if the checkbox is checked
+ field_value = str( widget.is_checked( field_value ) ).lower()
+ elif isinstance( widget, AddressField ):
+ # If the address was new, is has already been saved and widget.value is the new address.id
+ field_value = widget.value
+ field_contents.append( util.restore_text( field_value ) )
+ return field_contents
+ def save_widget_field( self, trans, field_obj, index, **kwd ):
+ # Save a form_builder field object
+ # TODO: Add support for other field types ( e.g., WorkflowField )
+ params = util.Params( kwd )
+ if isinstance( field_obj, trans.model.UserAddress ):
+ field_obj.desc = util.restore_text( params.get( 'field_%i_short_desc' % index, '' ) )
+ field_obj.name = util.restore_text( params.get( 'field_%i_name' % index, '' ) )
+ field_obj.institution = util.restore_text( params.get( 'field_%i_institution' % index, '' ) )
+ field_obj.address = util.restore_text( params.get( 'field_%i_address' % index, '' ) )
+ field_obj.city = util.restore_text( params.get( 'field_%i_city' % index, '' ) )
+ field_obj.state = util.restore_text( params.get( 'field_%i_state' % index, '' ) )
+ field_obj.postal_code = util.restore_text( params.get( 'field_%i_postal_code' % index, '' ) )
+ field_obj.country = util.restore_text( params.get( 'field_%i_country' % index, '' ) )
+ field_obj.phone = util.restore_text( params.get( 'field_%i_phone' % index, '' ) )
+ trans.sa_session.add( field_obj )
+ trans.sa_session.flush()
+
class Sharable:
""" Mixin for a controller that manages an item that can be shared. """
# Implemented methods.
--- a/test/functional/test_forms_and_requests.py
+++ b/test/functional/test_forms_and_requests.py
@@ -13,17 +13,15 @@ request_type_name = 'Test Requestype'
sample_states = [ ( 'New', 'Sample entered into the system' ),
( 'Received', 'Sample tube received' ),
( 'Done', 'Sequence run complete' ) ]
-address1 = dict( short_desc="Office",
- name="James+Bond",
- institution="MI6" ,
- address1="MI6+Headquarters",
- address2="",
- city="London",
- state="London",
- postal_code="007",
- country="United+Kingdom",
- phone="007-007-0007" )
-
+address_dict = dict( short_desc="Office",
+ name="James+Bond",
+ institution="MI6" ,
+ address="MI6+Headquarters",
+ city="London",
+ state="London",
+ postal_code="007",
+ country="United+Kingdom",
+ phone="007-007-0007" )
def get_latest_form(form_name):
fdc_list = sa_session.query( galaxy.model.FormDefinitionCurrent ) \
@@ -36,7 +34,6 @@ def get_latest_form(form_name):
return fdc.latest_form
return None
-
class TestFormsAndRequests( TwillTestCase ):
def test_000_initiate_users( self ):
"""Ensuring all required user accounts exist"""
@@ -114,7 +111,7 @@ class TestFormsAndRequests( TwillTestCas
def test_010_create_form( self ):
"""Testing creating a new form and editing it"""
self.logout()
- self.login( email='test(a)bx.psu.edu' )
+ self.login( email=admin_user.email )
# create a form
global form_one_name
desc = "This is Form One's description"
@@ -197,7 +194,6 @@ class TestFormsAndRequests( TwillTestCas
pass
self.logout()
self.login( email=admin_user.email )
-
def test_030_create_address_and_library( self ):
"""Testing address & library creation"""
# first create a library for the request so that it can be submitted later
@@ -249,22 +245,15 @@ class TestFormsAndRequests( TwillTestCas
assert folder_one is not None, 'Problem retrieving library folder named "%s" from the database' % name
# create address
self.logout()
- self.login( email='test1(a)bx.psu.edu', username='regular-user1' )
- self.add_user_address( regular_user1.id, address1 )
- global regular_user
- regular_user = sa_session.query( galaxy.model.User ) \
- .filter( galaxy.model.User.table.c.email=='test1(a)bx.psu.edu' ) \
- .first()
+ self.login( email=regular_user1.email )
+ self.add_user_address( regular_user1.id, address_dict )
global user_address
- user_address = sa_session.query( galaxy.model.UserAddress ) \
- .filter( and_( galaxy.model.UserAddress.table.c.desc==address1[ 'short_desc' ],
- galaxy.model.UserAddress.table.c.deleted==False ) ) \
- .first()
+ user_address = get_user_address( regular_user1, address_dict[ 'short_desc' ] )
def test_035_create_request( self ):
"""Testing creating, editing and submitting a request as a regular user"""
# login as a regular user
self.logout()
- self.login( email='test1(a)bx.psu.edu', username='regular-user1' )
+ self.login( email=regular_user1.email )
# set field values
fields = ['option1', str(user_address.id), 'field three value']
# create the request
@@ -302,7 +291,7 @@ class TestFormsAndRequests( TwillTestCas
"""Testing request lifecycle as it goes through all the states"""
# goto admin manage requests page
self.logout()
- self.login( email='test(a)bx.psu.edu' )
+ self.login( email=admin_user.email )
self.check_request_admin_grid(state=request_one.states.SUBMITTED, request_name=request_one.name)
self.visit_url( "%s/requests_admin/list?operation=show&id=%s" \
% ( self.url, self.security.encode_id( request_one.id ) ))
@@ -317,7 +306,7 @@ class TestFormsAndRequests( TwillTestCas
self.home()
sa_session.refresh( request_one )
self.logout()
- self.login( email='test1(a)bx.psu.edu', username='regular-user1' )
+ self.login( email=regular_user1.email )
# check if the request's state is now set to 'complete'
self.check_request_grid(state='Complete', request_name=request_one.name)
assert request_one.state is not request_one.states.COMPLETE, "The state of the request '%s' should be set to '%s'" \
@@ -325,11 +314,11 @@ class TestFormsAndRequests( TwillTestCas
def test_045_admin_create_request_on_behalf_of_regular_user( self ):
"""Testing creating and submitting a request as an admin on behalf of a regular user"""
self.logout()
- self.login( email='test(a)bx.psu.edu' )
+ self.login( email=admin_user.email )
request_name = "RequestTwo"
# simulate request creation
url_str = '%s/requests_common/new?cntrller=requests_admin&create_request_button=Save&select_request_type=%i&select_user=%i&name=%s&refresh=True&field_2=%s&field_0=%s&field_1=%i' \
- % ( self.url, request_type.id, regular_user.id, request_name, "field_2_value", 'option1', user_address.id )
+ % ( self.url, request_type.id, regular_user1.id, request_name, "field_2_value", 'option1', user_address.id )
print url_str
self.home()
self.visit_url( url_str )
@@ -363,7 +352,7 @@ class TestFormsAndRequests( TwillTestCas
def test_050_reject_request( self ):
'''Testing rejecting a request'''
self.logout()
- self.login( email='test(a)bx.psu.edu' )
+ self.login( email=admin_user.email )
self.reject_request( request_two.id, request_two.name, "Rejection test comment" )
sa_session.refresh( request_two )
# check if the request is showing in the 'rejected' filter
--- a/templates/library/common/library_info.mako
+++ b/templates/library/common/library_info.mako
@@ -1,6 +1,34 @@
<%inherit file="/base.mako"/><%namespace file="/message.mako" import="render_msg" />
-<%namespace file="/library/common/common.mako" import="render_template_info" />
+<%namespace file="/library/common/common.mako" import="render_template_fields" />
+
+<%def name="javascripts()">
+ ${parent.javascripts()}
+ <script type="text/javascript">
+ $( function() {
+ $( "select[refresh_on_change='true']").change( function() {
+ var refresh = false;
+ var refresh_on_change_values = $( this )[0].attributes.getNamedItem( 'refresh_on_change_values' )
+ if ( refresh_on_change_values ) {
+ refresh_on_change_values = refresh_on_change_values.value.split( ',' );
+ var last_selected_value = $( this )[0].attributes.getNamedItem( 'last_selected_value' );
+ for( i= 0; i < refresh_on_change_values.length; i++ ) {
+ if ( $( this )[0].value == refresh_on_change_values[i] || ( last_selected_value && last_selected_value.value == refresh_on_change_values[i] ) ){
+ refresh = true;
+ break;
+ }
+ }
+ }
+ else {
+ refresh = true;
+ }
+ if ( refresh ){
+ $( "#edit_info" ).submit();
+ }
+ });
+ });
+ </script>
+</%def><%
from cgi import escape
@@ -107,5 +135,5 @@
</div>
%if widgets:
- ${render_template_info( cntrller=cntrller, item_type='library', library_id=trans.security.encode_id( library.id ), widgets=widgets, info_association=info_association, inherited=inherited, editable=not( library.deleted ) )}
+ ${render_template_fields( cntrller=cntrller, item_type='library', library_id=trans.security.encode_id( library.id ), widgets=widgets, widget_fields_have_contents=widget_fields_have_contents, info_association=info_association, inherited=inherited, editable=not( library.deleted ) )}
%endif
--- a/lib/galaxy/web/controllers/user.py
+++ b/lib/galaxy/web/controllers/user.py
@@ -26,7 +26,7 @@ require_login_creation_template = requir
VALID_USERNAME_RE = re.compile( "^[a-z0-9\-]+$" )
-class User( BaseController ):
+class User( BaseController, UsesFormDefinitionWidgets ):
@web.expose
def index( self, trans, webapp='galaxy', **kwd ):
return trans.fill_template( '/user/index.mako', webapp=webapp )
@@ -263,17 +263,7 @@ class User( BaseController ):
if value == 'new':
# save this new address in the list of this user's addresses
user_address = trans.app.model.UserAddress( user=user )
- user_address.desc = util.restore_text(params.get('field_%i_short_desc' % index, ''))
- user_address.name = util.restore_text(params.get('field_%i_name' % index, ''))
- user_address.institution = util.restore_text(params.get('field_%i_institution' % index, ''))
- user_address.address = util.restore_text(params.get('field_%i_address1' % index, ''))+' '+util.restore_text(params.get('field_%i_address2' % index, ''))
- user_address.city = util.restore_text(params.get('field_%i_city' % index, ''))
- user_address.state = util.restore_text(params.get('field_%i_state' % index, ''))
- user_address.postal_code = util.restore_text(params.get('field_%i_postal_code' % index, ''))
- user_address.country = util.restore_text(params.get('field_%i_country' % index, ''))
- user_address.phone = util.restore_text(params.get('field_%i_phone' % index, ''))
- trans.sa_session.add( user_address )
- trans.sa_session.flush()
+ self.save_widget_field( trans, user_address, index, **kwd )
trans.sa_session.refresh( user )
values.append(int(user_address.id))
elif value == unicode('none'):
@@ -673,8 +663,7 @@ class User( BaseController ):
return trans.fill_template( 'user/permissions.mako' )
else:
# User not logged in, history group must be only public
- return trans.show_error_message( "You must be logged in to change your default permitted actions." )
-
+ return trans.show_error_message( "You must be logged in to change your default permitted actions." )
@web.expose
@web.require_login( "to get most recently used tool" )
@web.json_pretty
@@ -697,8 +686,7 @@ class User( BaseController ):
"minsizehint" : tool.uihints.get( 'minwidth', -1 ),
"description" : tool.description
}
- return tool_info
-
+ return tool_info
@web.expose
def manage_addresses(self, trans, **kwd):
if trans.user:
@@ -726,123 +714,151 @@ class User( BaseController ):
message = util.restore_text( params.get( 'message', '' ) )
status = params.get( 'status', 'done' )
admin_view = util.string_as_bool( params.get( 'admin_view', False ) )
- error = ''
- user = trans.sa_session.query( trans.app.model.User ).get( int( params.get( 'user_id', None ) ) )
+ user_id = params.get( 'user_id', False )
+ if not user_id:
+ # User must be logged in to create a new address
+ return trans.show_error_message( "You must be logged in to create a new address." )
+ user = trans.sa_session.query( trans.app.model.User ).get( int( user_id ) )
+ short_desc = util.restore_text( params.get( 'short_desc', '' ) )
+ name = util.restore_text( params.get( 'name', '' ) )
+ institution = util.restore_text( params.get( 'institution', '' ) )
+ address = util.restore_text( params.get( 'address', '' ) )
+ city = util.restore_text( params.get( 'city', '' ) )
+ state = util.restore_text( params.get( 'state', '' ) )
+ postal_code = util.restore_text( params.get( 'postal_code', '' ) )
+ country = util.restore_text( params.get( 'country', '' ) )
+ phone = util.restore_text( params.get( 'phone', '' ) )
+ ok = True
if not trans.app.config.allow_user_creation and not trans.user_is_admin():
return trans.show_error_message( 'User registration is disabled. Please contact your Galaxy administrator for an account.' )
- if params.get( 'save_new_address_button', None ) == 'Save':
- if not len( util.restore_text( params.get( 'short_desc', '' ) ) ):
- error = 'Enter a short description for this address'
- elif not len( util.restore_text( params.get( 'name', '' ) ) ):
- error = 'Enter the full name'
- elif not len( util.restore_text( params.get( 'institution', '' ) ) ):
- error = 'Enter the institution associated with the user'
- elif not len ( util.restore_text( params.get( 'address1', '' ) ) ):
- error = 'Enter the address'
- elif not len( util.restore_text( params.get( 'city', '' ) ) ):
- error = 'Enter the city'
- elif not len( util.restore_text( params.get( 'state', '' ) ) ):
- error = 'Enter the state/province/region'
- elif not len( util.restore_text( params.get( 'postal_code', '' ) ) ):
- error = 'Enter the postal code'
- elif not len( util.restore_text( params.get( 'country', '' ) ) ):
- error = 'Enter the country'
- else:
- user_address = trans.app.model.UserAddress( user=user )
- user_address.desc = util.restore_text( params.get( 'short_desc', '' ) )
- user_address.name = util.restore_text( params.get( 'name', '' ) )
- user_address.institution = util.restore_text( params.get( 'institution', '' ) )
- user_address.address = util.restore_text( params.get( 'address1', '' ) )+' '+util.restore_text( params.get( 'address2', '' ) )
- user_address.city = util.restore_text( params.get( 'city', '' ) )
- user_address.state = util.restore_text( params.get( 'state', '' ) )
- user_address.postal_code = util.restore_text( params.get( 'postal_code', '' ) )
- user_address.country = util.restore_text( params.get( 'country', '' ) )
- user_address.phone = util.restore_text( params.get( 'phone', '' ) )
+ if params.get( 'new_address_button', False ):
+ if not short_desc:
+ ok = False
+ message = 'Enter a short description for this address'
+ elif not name:
+ ok = False
+ message = 'Enter the name'
+ elif not institution:
+ ok = False
+ message = 'Enter the institution associated with the user'
+ elif not address:
+ ok = False
+ message = 'Enter the address'
+ elif not city:
+ ok = False
+ message = 'Enter the city'
+ elif not state:
+ ok = False
+ message = 'Enter the state/province/region'
+ elif not postal_code:
+ ok = False
+ message = 'Enter the postal code'
+ elif not country:
+ ok = False
+ message = 'Enter the country'
+ if ok:
+ user_address = trans.model.UserAddress( user=user,
+ desc=short_desc,
+ name=name,
+ institution=institution,
+ address=address,
+ city=city,
+ state=state,
+ postal_code=postal_code,
+ country=country,
+ phone=phone )
trans.sa_session.add( user_address )
trans.sa_session.flush()
- message = 'Address <b>%s</b> has been added' % user_address.desc
+ message = 'Address (%s) has been added' % user_address.desc
if admin_view:
return trans.response.send_redirect( web.url_for( controller='user',
action='show_info',
admin_view=admin_view,
user_id=user.id,
message=message,
- status='done') )
+ status='done' ) )
return trans.response.send_redirect( web.url_for( controller='user',
action='show_info',
message=message,
- status='done') )
- else:
- # show the address form with the current values filled in
- # create the widgets for each address field
- widgets = []
- widgets.append(dict(label='Short description',
- widget=TextField( 'short_desc', 40, '' ) ) )
- widgets.append(dict(label='Name',
- widget=TextField( 'name', 40, '' ) ) )
- widgets.append(dict(label='Institution',
- widget=TextField( 'institution', 40, '' ) ) )
- widgets.append(dict(label='Address Line 1',
- widget=TextField( 'address1', 40, '' ) ) )
- widgets.append(dict(label='Address Line 2',
- widget=TextField( 'address2', 40, '' ) ) )
- widgets.append(dict(label='City',
- widget=TextField( 'city', 40, '' ) ) )
- widgets.append(dict(label='State',
- widget=TextField( 'state', 40, '' ) ) )
- widgets.append(dict(label='Postal Code',
- widget=TextField( 'postal_code', 40, '' ) ) )
- widgets.append(dict(label='Country',
- widget=TextField( 'country', 40, '' ) ) )
- widgets.append(dict(label='Phone',
- widget=TextField( 'phone', 40, '' ) ) )
- return trans.fill_template( 'user/new_address.mako',
- user=user,
- admin_view=admin_view,
- widgets=widgets,
- message=message,
- status=status)
+ status='done' ) )
+ # Display the address form with the current values filled in
+ return trans.fill_template( 'user/new_address.mako',
+ user=user,
+ admin_view=admin_view,
+ short_desc=short_desc,
+ name=name,
+ institution=institution,
+ address=address,
+ city=city,
+ state=state,
+ postal_code=postal_code,
+ country=country,
+ phone=phone,
+ message=message,
+ status=status )
@web.expose
def edit_address( self, trans, **kwd ):
params = util.Params( kwd )
- user_id = params.get( 'user_id', None )
- address_id = params.get( 'address_id', None )
message = util.restore_text( params.get( 'message', '' ) )
status = params.get( 'status', 'done' )
admin_view = util.string_as_bool( params.get( 'admin_view', False ) )
- error = ''
+ user_id = params.get( 'user_id', False )
+ if not user_id:
+ # User must be logged in to create a new address
+ return trans.show_error_message( "You must be logged in to create a new address." )
user = trans.sa_session.query( trans.app.model.User ).get( int( user_id ) )
- user_address = trans.sa_session.query( trans.app.model.UserAddress ).get( int( address_id ) )
- if params.get( 'edit_address_button', None ) == 'Save changes':
- if not len( util.restore_text( params.get( 'short_desc', '' ) ) ):
- error = 'Enter a short description for this address'
- elif not len( util.restore_text( params.get( 'name', '' ) ) ):
- error = 'Enter the full name'
- elif not len( util.restore_text( params.get( 'institution', '' ) ) ):
- error = 'Enter the institution associated with the user'
- elif not len ( util.restore_text( params.get( 'address1', '' ) ) ):
- error = 'Enter the address'
- elif not len( util.restore_text( params.get( 'city', '' ) ) ):
- error = 'Enter the city'
- elif not len( util.restore_text( params.get( 'state', '' ) ) ):
- error = 'Enter the state/province/region'
- elif not len( util.restore_text( params.get( 'postal_code', '' ) ) ):
- error = 'Enter the postal code'
- elif not len( util.restore_text( params.get( 'country', '' ) ) ):
- error = 'Enter the country'
- else:
- user_address.desc = util.restore_text( params.get( 'short_desc', '' ) )
- user_address.name = util.restore_text( params.get( 'name', '' ) )
- user_address.institution = util.restore_text( params.get( 'institution', '' ) )
- user_address.address = util.restore_text( params.get( 'address1', '' ) )+' '+util.restore_text( params.get( 'address2', '' ) )
- user_address.city = util.restore_text( params.get( 'city', '' ) )
- user_address.state = util.restore_text( params.get( 'state', '' ) )
- user_address.postal_code = util.restore_text( params.get( 'postal_code', '' ) )
- user_address.country = util.restore_text( params.get( 'country', '' ) )
- user_address.phone = util.restore_text( params.get( 'phone', '' ) )
- trans.sa_session.add( user_address )
+ address_id = params.get( 'address_id', None )
+ if not address_id:
+ return trans.show_error_message( "No address_id received for editing." )
+ address_obj = trans.sa_session.query( trans.app.model.UserAddress ).get( int( address_id ) )
+ if params.get( 'edit_address_button', False ):
+ short_desc = util.restore_text( params.get( 'short_desc', '' ) )
+ name = util.restore_text( params.get( 'name', '' ) )
+ institution = util.restore_text( params.get( 'institution', '' ) )
+ address = util.restore_text( params.get( 'address', '' ) )
+ city = util.restore_text( params.get( 'city', '' ) )
+ state = util.restore_text( params.get( 'state', '' ) )
+ postal_code = util.restore_text( params.get( 'postal_code', '' ) )
+ country = util.restore_text( params.get( 'country', '' ) )
+ phone = util.restore_text( params.get( 'phone', '' ) )
+ ok = True
+ if not short_desc:
+ ok = False
+ message = 'Enter a short description for this address'
+ elif not name:
+ ok = False
+ message = 'Enter the name'
+ elif not institution:
+ ok = False
+ message = 'Enter the institution associated with the user'
+ elif not address:
+ ok = False
+ message = 'Enter the address'
+ elif not city:
+ ok = False
+ message = 'Enter the city'
+ elif not state:
+ ok = False
+ message = 'Enter the state/province/region'
+ elif not postal_code:
+ ok = False
+ message = 'Enter the postal code'
+ elif not country:
+ ok = False
+ message = 'Enter the country'
+ if ok:
+ address_obj.desc = short_desc
+ address_obj.name = name
+ address_obj.institution = institution
+ address_obj.address = address
+ address_obj.city = city
+ address_obj.state = state
+ address_obj.postal_code = postal_code
+ address_obj.country = country
+ address_obj.phone = phone
+ trans.sa_session.add( address_obj )
trans.sa_session.flush()
- message = 'Changes made to address <b>%s</b> are saved.' % user_address.desc
+ message = 'Address (%s) has been updated.' % address_obj.desc
if admin_view:
return trans.response.send_redirect( web.url_for( controller='user',
action='show_info',
@@ -853,38 +869,14 @@ class User( BaseController ):
return trans.response.send_redirect( web.url_for( controller='user',
action='show_info',
message=message,
- status='done') )
- else:
- # show the address form with the current values filled in
- # create the widgets for each address field
- widgets = []
- widgets.append(dict(label='Short description',
- widget=TextField( 'short_desc', 40, user_address.desc ) ) )
- widgets.append(dict(label='Name',
- widget=TextField( 'name', 40, user_address.name ) ) )
- widgets.append(dict(label='Institution',
- widget=TextField( 'institution', 40, user_address.institution ) ) )
- widgets.append(dict(label='Address Line 1',
- widget=TextField( 'address1', 40, user_address.address ) ) )
- widgets.append(dict(label='Address Line 2',
- widget=TextField( 'address2', 40, '' ) ) )
- widgets.append(dict(label='City',
- widget=TextField( 'city', 40, user_address.city ) ) )
- widgets.append(dict(label='State',
- widget=TextField( 'state', 40, user_address.state ) ) )
- widgets.append(dict(label='Postal Code',
- widget=TextField( 'postal_code', 40, user_address.postal_code ) ) )
- widgets.append(dict(label='Country',
- widget=TextField( 'country', 40, user_address.country ) ) )
- widgets.append(dict(label='Phone',
- widget=TextField( 'phone', 40, user_address.phone ) ) )
- return trans.fill_template( 'user/edit_address.mako',
- user=user,
- address=user_address,
- admin_view=admin_view,
- widgets=widgets,
- message=message,
- status=status)
+ status='done' ) )
+ # Display the address form with the current values filled in
+ return trans.fill_template( 'user/edit_address.mako',
+ user=user,
+ address_obj=address_obj,
+ admin_view=admin_view,
+ message=message,
+ status=status )
@web.expose
def delete_address( self, trans, address_id=None, user_id=None, admin_view=False ):
try:
@@ -897,12 +889,13 @@ class User( BaseController ):
message='Invalid address ID',
status='error' ) )
user_address.deleted = True
+ trans.sa_session.add( user_address )
trans.sa_session.flush()
return trans.response.send_redirect( web.url_for( controller='user',
action='show_info',
admin_view=admin_view,
user_id=user_id,
- message='Address <b>%s</b> deleted' % user_address.desc,
+ message='Address (%s) deleted' % user_address.desc,
status='done') )
@web.expose
def undelete_address( self, trans, address_id=None, user_id=None, admin_view=False ):
@@ -921,9 +914,8 @@ class User( BaseController ):
action='show_info',
admin_view=admin_view,
user_id=user_id,
- message='Address <b>%s</b> undeleted' % user_address.desc,
+ message='Address (%s) undeleted' % user_address.desc,
status='done') )
-
@web.expose
def set_user_pref_async( self, trans, pref_name, pref_value ):
""" Set a user preference asynchronously. If user is not logged in, do nothing. """
@@ -931,13 +923,11 @@ class User( BaseController ):
trans.log_action( trans.get_user(), "set_user_pref", "", { pref_name : pref_value } )
trans.user.preferences[pref_name] = pref_value
trans.sa_session.flush()
-
@web.expose
def log_user_action_async( self, trans, action, context, params ):
""" Log a user action asynchronously. If user is not logged in, do nothing. """
if trans.user:
trans.log_action( trans.get_user(), action, context, params )
-
@web.expose
@web.require_login()
def dbkeys( self, trans, **kwds ):
@@ -999,9 +989,7 @@ class User( BaseController ):
user=user,
dbkeys=dbkeys,
message=message,
- lines_skipped=lines_skipped )
-
-
+ lines_skipped=lines_skipped )
@web.expose
def api_keys( self, trans, **kwd ):
params = util.Params( kwd )
--- a/lib/galaxy/web/controllers/requests_common.py
+++ b/lib/galaxy/web/controllers/requests_common.py
@@ -17,7 +17,7 @@ import csv
log = logging.getLogger( __name__ )
-class RequestsCommon( BaseController ):
+class RequestsCommon( BaseController, UsesFormDefinitionWidgets ):
@web.json
def sample_state_updates( self, trans, ids=None, states=None, cntrller=None ):
@@ -207,17 +207,7 @@ class RequestsCommon( BaseController ):
if value == 'new':
# save this new address in the list of this user's addresses
user_address = trans.app.model.UserAddress( user=user )
- user_address.desc = util.restore_text(params.get('field_%i_short_desc' % index, ''))
- user_address.name = util.restore_text(params.get('field_%i_name' % index, ''))
- user_address.institution = util.restore_text(params.get('field_%i_institution' % index, ''))
- user_address.address = util.restore_text(params.get('field_%i_address1' % index, ''))+' '+util.restore_text(params.get('field_%i_address2' % index, ''))
- user_address.city = util.restore_text(params.get('field_%i_city' % index, ''))
- user_address.state = util.restore_text(params.get('field_%i_state' % index, ''))
- user_address.postal_code = util.restore_text(params.get('field_%i_postal_code' % index, ''))
- user_address.country = util.restore_text(params.get('field_%i_country' % index, ''))
- user_address.phone = util.restore_text(params.get('field_%i_phone' % index, ''))
- trans.sa_session.add( user_address )
- trans.sa_session.flush()
+ self.save_widget_field( trans, user_address, index, **kwd )
trans.sa_session.refresh( user )
values.append(int(user_address.id))
elif value == unicode('none'):
--- a/templates/library/common/new_folder.mako
+++ b/templates/library/common/new_folder.mako
@@ -1,6 +1,5 @@
<%inherit file="/base.mako"/><%namespace file="/message.mako" import="render_msg" />
-<%namespace file="/library/common/common.mako" import="render_template_info" /><br/<br/><ul class="manage-table-actions">
--- a/templates/user/edit_address.mako
+++ b/templates/user/edit_address.mako
@@ -1,7 +1,6 @@
<%inherit file="/base.mako"/><%namespace file="/message.mako" import="render_msg" />
-
%if message:
${render_msg( message, status )}
%endif
@@ -11,23 +10,87 @@
<ul class="manage-table-actions"><li>
- <a class="action-button" href="${h.url_for( controller='user', action='show_info', admin_view=admin_view, user_id=user.id)}">
- <span>Manage User Information</span></a>
+ <a class="action-button" href="${h.url_for( controller='user', action='show_info', admin_view=admin_view, user_id=user.id)}">Manage user information</a></li></ul><div class="toolForm">
-<form name="login_info" id="login_info" action="${h.url_for( controller='user', action='edit_address', admin_view=admin_view, address_id=address.id, user_id=user.id )}" method="post" ><div class="toolFormTitle">Edit address</div><div class="toolFormBody">
- %for field in widgets:
+ <form name="login_info" id="login_info" action="${h.url_for( controller='user', action='edit_address', admin_view=admin_view, address_id=address_obj.id, user_id=user.id )}" method="post" ><div class="form-row">
- <label>${field[ 'label' ]}</label>
- ${field[ 'widget' ].get_html()}
+ <label>Short Description:</label>
+ <div style="float: left; width: 250px; margin-right: 10px;">
+ <input type="text" name="short_desc" value="${address_obj.desc}" size="40">
+ </div>
+ <div class="toolParamHelp" style="clear: both;">Required</div>
+ <div style="clear: both"></div></div>
- %endfor
- <div class="form-row">
- <input type="submit" name="edit_address_button" value="Save changes">
- </div>
+ <div class="form-row">
+ <label>Name:</label>
+ <div style="float: left; width: 250px; margin-right: 10px;">
+ <input type="text" name="name" value="${address_obj.name}" size="40">
+ </div>
+ <div class="toolParamHelp" style="clear: both;">Required</div>
+ <div style="clear: both"></div>
+ </div>
+ <div class="form-row">
+ <label>Institution:</label>
+ <div style="float: left; width: 250px; margin-right: 10px;">
+ <input type="text" name="institution" value="${address_obj.institution}" size="40">
+ </div>
+ <div class="toolParamHelp" style="clear: both;">Required</div>
+ <div style="clear: both"></div>
+ </div>
+ <div class="form-row">
+ <label>Address Line 1:</label>
+ <div style="float: left; width: 250px; margin-right: 10px;">
+ <input type="text" name="address" value="${address_obj.address}" size="40">
+ </div>
+ <div class="toolParamHelp" style="clear: both;">Required</div>
+ <div style="clear: both"></div>
+ </div>
+ <div class="form-row">
+ <label>City:</label>
+ <div style="float: left; width: 250px; margin-right: 10px;">
+ <input type="text" name="city" value="${address_obj.city}" size="40">
+ </div>
+ <div class="toolParamHelp" style="clear: both;">Required</div>
+ <div style="clear: both"></div>
+ </div>
+ <div class="form-row">
+ <label>State/Province/Region:</label>
+ <div style="float: left; width: 250px; margin-right: 10px;">
+ <input type="text" name="state" value="${address_obj.state}" size="40">
+ </div>
+ <div class="toolParamHelp" style="clear: both;">Required</div>
+ <div style="clear: both"></div>
+ </div>
+ <div class="form-row">
+ <label>Postal Code:</label>
+ <div style="float: left; width: 250px; margin-right: 10px;">
+ <input type="text" name="postal_code" value="${address_obj.postal_code}" size="40">
+ </div>
+ <div class="toolParamHelp" style="clear: both;">Required</div>
+ <div style="clear: both"></div>
+ </div>
+ <div class="form-row">
+ <label>Country:</label>
+ <div style="float: left; width: 250px; margin-right: 10px;">
+ <input type="text" name="country" value="${address_obj.country}" size="40">
+ </div>
+ <div class="toolParamHelp" style="clear: both;">Required</div>
+ <div style="clear: both"></div>
+ </div>
+ <div class="form-row">
+ <label>Phone:</label>
+ <div style="float: left; width: 250px; margin-right: 10px;">
+ <input type="text" name="phone" value="${address_obj.phone}" size="40">
+ </div>
+ <div style="clear: both"></div>
+ </div>
+ <div class="form-row">
+ <input type="submit" name="edit_address_button" value="Save changes">
+ </div>
+ </form></div>
-</form></div>
--- a/templates/user/new_address.mako
+++ b/templates/user/new_address.mako
@@ -1,13 +1,12 @@
<%inherit file="/base.mako"/><%namespace file="/message.mako" import="render_msg" />
-
%if message:
${render_msg( message, status )}
%endif
</br></br>
-<h3>New address</h3>
+<h3>Add new address</h3><ul class="manage-table-actions"><li>
@@ -16,18 +15,83 @@
</li></ul><div class="toolForm">
-<form name="login_info" id="login_info" action="${h.url_for( controller='user', action='new_address', admin_view=admin_view, user_id=user.id )}" method="post" >
- <div class="toolFormTitle">New address</div>
+ <div class="toolFormTitle">Add new address</div><div class="toolFormBody">
- %for field in widgets:
+ <form name="login_info" id="login_info" action="${h.url_for( controller='user', action='new_address', admin_view=admin_view, user_id=user.id )}" method="post" ><div class="form-row">
- <label>${field[ 'label' ]}</label>
- ${field[ 'widget' ].get_html()}
+ <label>Short Description:</label>
+ <div style="float: left; width: 250px; margin-right: 10px;">
+ <input type="text" name="short_desc" value="${short_desc}" size="40">
+ </div>
+ <div class="toolParamHelp" style="clear: both;">Required</div>
+ <div style="clear: both"></div></div>
- %endfor
- <div class="form-row">
- <input type="submit" name="save_new_address_button" value="Save">
- </div>
+ <div class="form-row">
+ <label>Name:</label>
+ <div style="float: left; width: 250px; margin-right: 10px;">
+ <input type="text" name="name" value="${name}" size="40">
+ </div>
+ <div class="toolParamHelp" style="clear: both;">Required</div>
+ <div style="clear: both"></div>
+ </div>
+ <div class="form-row">
+ <label>Institution:</label>
+ <div style="float: left; width: 250px; margin-right: 10px;">
+ <input type="text" name="institution" value="${institution}" size="40">
+ </div>
+ <div class="toolParamHelp" style="clear: both;">Required</div>
+ <div style="clear: both"></div>
+ </div>
+ <div class="form-row">
+ <label>Address Line 1:</label>
+ <div style="float: left; width: 250px; margin-right: 10px;">
+ <input type="text" name="address" value="${address}" size="40">
+ </div>
+ <div class="toolParamHelp" style="clear: both;">Required</div>
+ <div style="clear: both"></div>
+ </div>
+ <div class="form-row">
+ <label>City:</label>
+ <div style="float: left; width: 250px; margin-right: 10px;">
+ <input type="text" name="city" value="${city}" size="40">
+ </div>
+ <div class="toolParamHelp" style="clear: both;">Required</div>
+ <div style="clear: both"></div>
+ </div>
+ <div class="form-row">
+ <label>State/Province/Region:</label>
+ <div style="float: left; width: 250px; margin-right: 10px;">
+ <input type="text" name="state" value="${state}" size="40">
+ </div>
+ <div class="toolParamHelp" style="clear: both;">Required</div>
+ <div style="clear: both"></div>
+ </div>
+ <div class="form-row">
+ <label>Postal Code:</label>
+ <div style="float: left; width: 250px; margin-right: 10px;">
+ <input type="text" name="postal_code" value="${postal_code}" size="40">
+ </div>
+ <div class="toolParamHelp" style="clear: both;">Required</div>
+ <div style="clear: both"></div>
+ </div>
+ <div class="form-row">
+ <label>Country:</label>
+ <div style="float: left; width: 250px; margin-right: 10px;">
+ <input type="text" name="country" value="${country}" size="40">
+ </div>
+ <div class="toolParamHelp" style="clear: both;">Required</div>
+ <div style="clear: both"></div>
+ </div>
+ <div class="form-row">
+ <label>Phone:</label>
+ <div style="float: left; width: 250px; margin-right: 10px;">
+ <input type="text" name="phone" value="${phone}" size="40">
+ </div>
+ <div style="clear: both"></div>
+ </div>
+ <div class="form-row">
+ <input type="submit" name="new_address_button" value="Save">
+ </div>
+ </form></div>
-</form></div>
--- a/test/base/twilltestcase.py
+++ b/test/base/twilltestcase.py
@@ -1573,19 +1573,19 @@ class TwillTestCase( unittest.TestCase )
def add_user_address( self, user_id, address_dict ):
self.home()
self.visit_url( "%s/user/new_address?admin_view=False&user_id=%i" % ( self.url, user_id ) )
- self.check_page_for_string( 'New address' )
+ self.check_page_for_string( 'Add new address' )
for field_name, value in address_dict.items():
tc.fv( "1", field_name, value )
- tc.submit( "save_new_address_button" )
- self.check_page_for_string( 'Address <b>%s</b> has been added' % address_dict[ 'short_desc' ] )
+ tc.submit( "new_address_button" )
+ self.check_page_for_string( 'Address (%s) has been added' % address_dict[ 'short_desc' ] )
def add_user_address_as_admin( self, user_id, address_dict ):
self.home()
self.visit_url( "%s/user/new_address?admin_view=True&user_id=%i" % ( self.url, user_id ) )
- self.check_page_for_string( 'New address' )
+ self.check_page_for_string( 'Add new address' )
for field_name, value in address_dict.items():
tc.fv( "1", field_name, value )
- tc.submit( "save_new_address_button" )
- self.check_page_for_string( 'Address <b>%s</b> has been added' % address_dict[ 'short_desc' ] )
+ tc.submit( "new_address_button" )
+ self.check_page_for_string( 'Address (%s) has been added' % address_dict[ 'short_desc' ] )
# Library stuff
def add_library_template( self, cntrller, item_type, library_id, form_id, form_name, folder_id=None, ldda_id=None ):
--- a/templates/library/common/common.mako
+++ b/templates/library/common/common.mako
@@ -1,5 +1,61 @@
-<%def name="render_template_info( cntrller, item_type, library_id, widgets, info_association, inherited, folder_id=None, ldda_id=None, editable=True )">
+<%def name="render_template_field( field )"><%
+ from galaxy.web.form_builder import AddressField, CheckboxField, SelectField, TextArea, TextField, WorkflowField
+
+ has_contents = False
+ value = ''
+ if isinstance( field[ 'widget' ], TextArea ) and field[ 'widget' ].value:
+ has_contents = True
+ label = field[ 'label' ]
+ value = '<pre>%s</pre>' % field[ 'widget' ].value
+ elif isinstance( field[ 'widget' ], TextField ) and field[ 'widget' ].value:
+ has_contents = True
+ label = field[ 'label' ]
+ value = field[ 'widget' ].value
+ elif isinstance( field[ 'widget' ], SelectField ) and field[ 'widget' ].options:
+ for option_label, option_value, selected in field['widget'].options:
+ if selected:
+ has_contents = True
+ label = field[ 'label' ]
+ value = option_value
+ elif isinstance( field[ 'widget' ], CheckboxField ) and field[ 'widget' ].checked:
+ has_contents = True
+ label = field[ 'label' ]
+ value = 'checked'
+ elif isinstance( field[ 'widget' ], WorkflowField ) and field[ 'widget' ].value not in [ 'none', 'None', None ]:
+ has_contents = True
+ label = field[ 'label' ]
+ widget = field[ 'widget' ]
+ workflow_user = widget.user
+ if workflow_user:
+ for workflow in workflow_user.stored_workflows:
+ if not workflow.deleted and str( widget.value ) == str( workflow.id ):
+ value = workflow.name
+ break
+ else:
+ # If we didn't find the selected workflow option above, we'll just print the value
+ value = field[ 'widget' ].value
+ elif isinstance( field[ 'widget' ], AddressField ) and field[ 'widget' ].value not in [ 'none', 'None', None ]:
+ has_contents = True
+ widget = field[ 'widget' ]
+ address = trans.sa_session.query( trans.model.UserAddress ).get( int( widget.value ) )
+ label = address.desc
+ value = address.get_html()
+ %>
+ %if has_contents:
+ <div class="form-row">
+ <label>${label}</label>
+ ${value}
+ <div class="toolParamHelp" style="clear: both;">
+ ${field[ 'helptext' ]}
+ </div>
+ <div style="clear: both"></div>
+ </div>
+ %endif
+</%def>
+
+<%def name="render_template_fields( cntrller, item_type, library_id, widgets, widget_fields_have_contents, info_association, inherited, folder_id=None, ldda_id=None, editable=True )">
+ <%
if item_type == 'library':
item = trans.sa_session.query( trans.app.model.Library ).get( trans.security.decode_id( library_id ) )
elif item_type == 'folder':
@@ -41,7 +97,7 @@
%endif
</div><div class="toolFormBody">
- <form name="edit_info" action="${h.url_for( controller='library_common', action='edit_template_info', cntrller=cntrller, item_type=item_type, library_id=library_id, num_widgets=len( widgets ), folder_id=folder_id, ldda_id=ldda_id, show_deleted=show_deleted )}" method="post">
+ <form name="edit_info" id="edit_info" action="${h.url_for( controller='library_common', action='edit_template_info', cntrller=cntrller, item_type=item_type, library_id=library_id, folder_id=folder_id, ldda_id=ldda_id, show_deleted=show_deleted )}" method="post">
%for i, field in enumerate( widgets ):
<div class="form-row"><label>${field[ 'label' ]}</label>
@@ -59,37 +115,17 @@
</div></div><p/>
- %else:
- <% contents = False %>
- %for i, field in enumerate( widgets ):
- %if field[ 'widget' ].value:
- <%
- contents = True
- break
- %>
- %endif
- %endfor
- %if contents:
- <p/>
- <div class="toolForm">
- <div class="toolFormTitle">Other information about ${item.name}</div>
- <div class="toolFormBody">
- %for i, field in enumerate( widgets ):
- %if field[ 'widget' ].value:
- <div class="form-row">
- <label>${field[ 'label' ]}</label>
- <pre>${field[ 'widget' ].value}</pre>
- <div class="toolParamHelp" style="clear: both;">
- ${field[ 'helptext' ]}
- </div>
- <div style="clear: both"></div>
- </div>
- %endif
- %endfor
- </div>
+ %elif widget_fields_have_contents:
+ <p/>
+ <div class="toolForm">
+ <div class="toolFormTitle">Other information about ${item.name}</div>
+ <div class="toolFormBody">
+ %for i, field in enumerate( widgets ):
+ ${render_template_field( field )}
+ %endfor
</div>
- <p/>
- %endif
+ </div>
+ <p/>
%endif
%endif
</%def>
--- a/lib/galaxy/web/controllers/library_common.py
+++ b/lib/galaxy/web/controllers/library_common.py
@@ -6,7 +6,6 @@ from galaxy.security import RBACAgent
from galaxy.util.json import to_json_string
from galaxy.tools.actions import upload_common
from galaxy.web.controllers.forms import get_all_forms
-from galaxy.web.form_builder import SelectField, CheckboxField
from galaxy.model.orm import *
from galaxy.util.streamball import StreamBall
import logging, tempfile, zipfile, tarfile, os, sys
@@ -52,7 +51,7 @@ except OSError:
pass
os.rmdir( tmpd )
-class LibraryCommon( BaseController ):
+class LibraryCommon( BaseController, UsesFormDefinitionWidgets ):
@web.json
def library_item_updates( self, trans, ids=None, states=None ):
# Avoid caching
@@ -160,9 +159,6 @@ class LibraryCommon( BaseController ):
use_panels=use_panels,
message=util.sanitize_text( message ),
status='error' ) )
- # See if we have any associated templates
- info_association, inherited = library.get_info_association()
- widgets = library.get_template_widgets( trans )
if params.get( 'library_info_button', False ):
# Deny modification if the user is not an admin and does not have the LIBRARY_MODIFY permission.
if not ( is_admin or trans.app.security_agent.can_modify_library_item( current_user_roles, library ) ):
@@ -201,11 +197,16 @@ class LibraryCommon( BaseController ):
show_deleted=show_deleted,
message=util.sanitize_text( message ),
status='done' ) )
+ # See if we have any associated templates
+ info_association, inherited = library.get_info_association()
+ widgets = library.get_template_widgets( trans )
+ widget_fields_have_contents = self.widget_fields_have_contents( widgets )
return trans.fill_template( '/library/common/library_info.mako',
cntrller=cntrller,
use_panels=use_panels,
library=library,
widgets=widgets,
+ widget_fields_have_contents=widget_fields_have_contents,
current_user_roles=current_user_roles,
show_deleted=show_deleted,
info_association=info_association,
@@ -402,11 +403,6 @@ class LibraryCommon( BaseController ):
show_deleted=show_deleted,
message=util.sanitize_text( message ),
status='error' ) )
- # See if we have any associated templates
- widgets = []
- info_association, inherited = folder.get_info_association()
- if info_association and ( not( inherited ) or info_association.inheritable ):
- widgets = folder.get_template_widgets( trans )
if params.get( 'rename_folder_button', False ):
# Deny modification if the user is not an admin and does not have the LIBRARY_MODIFY permission
if not ( is_admin or trans.app.security_agent.can_modify_library_item( current_user_roles, folder ) ):
@@ -439,12 +435,20 @@ class LibraryCommon( BaseController ):
show_deleted=show_deleted,
message=util.sanitize_text( message ),
status='done' ) )
+ # See if we have any associated templates
+ widgets = []
+ widget_fields_have_contents = False
+ info_association, inherited = folder.get_info_association()
+ if info_association and ( not( inherited ) or info_association.inheritable ):
+ widgets = folder.get_template_widgets( trans )
+ widget_fields_have_contents = self.widget_fields_have_contents( widgets )
return trans.fill_template( '/library/common/folder_info.mako',
cntrller=cntrller,
use_panels=use_panels,
folder=folder,
library_id=library_id,
widgets=widgets,
+ widget_fields_have_contents=widget_fields_have_contents,
current_user_roles=current_user_roles,
show_deleted=show_deleted,
info_association=info_association,
@@ -677,9 +681,11 @@ class LibraryCommon( BaseController ):
associated_lddas = []
# See if we have any associated templates
widgets = []
+ widget_fields_have_contents = False
info_association, inherited = ldda.get_info_association()
if info_association and ( not( inherited ) or info_association.inheritable ):
widgets = ldda.get_template_widgets( trans )
+ widget_fields_have_contents = self.widget_fields_have_contents( widgets )
return trans.fill_template( '/library/common/ldda_info.mako',
cntrller=cntrller,
use_panels=use_panels,
@@ -689,6 +695,7 @@ class LibraryCommon( BaseController ):
associated_lddas=associated_lddas,
show_deleted=show_deleted,
widgets=widgets,
+ widget_fields_have_contents=widget_fields_have_contents,
current_user_roles=current_user_roles,
info_association=info_association,
inherited=inherited,
@@ -1524,11 +1531,6 @@ class LibraryCommon( BaseController ):
show_deleted=show_deleted,
message=util.sanitize_text( message ),
status='error' ) )
- # See if we have any associated templates
- widgets = []
- info_association, inherited = library_dataset.library_dataset_dataset_association.get_info_association()
- if info_association and ( not( inherited ) or info_association.inheritable ):
- widgets = library_dataset.library_dataset_dataset_association.get_template_widgets( trans )
if params.get( 'edit_attributes_button', False ):
# Deny access if the user is not an admin and does not have the LIBRARY_MODIFY permission.
if not ( is_admin or trans.app.security_agent.can_modify_library_item( current_user_roles, library_dataset ) ):
@@ -1553,6 +1555,13 @@ class LibraryCommon( BaseController ):
trans.sa_session.flush()
message = "Information updated for library dataset '%s'." % library_dataset.name
status = 'done'
+ # See if we have any associated templates
+ widgets = []
+ widget_fields_have_contents = False
+ info_association, inherited = library_dataset.library_dataset_dataset_association.get_info_association()
+ if info_association and ( not( inherited ) or info_association.inheritable ):
+ widgets = library_dataset.library_dataset_dataset_association.get_template_widgets( trans )
+ widget_fields_have_contents = self.widget_fields_have_contents( widgets )
return trans.fill_template( '/library/common/library_dataset_info.mako',
cntrller=cntrller,
use_panels=use_panels,
@@ -1562,6 +1571,7 @@ class LibraryCommon( BaseController ):
info_association=info_association,
inherited=inherited,
widgets=widgets,
+ widget_fields_have_contents=widget_fields_have_contents,
show_deleted=show_deleted,
message=message,
status=status )
@@ -2134,7 +2144,7 @@ class LibraryCommon( BaseController ):
**kwd ) )
return trans.response.send_redirect( web.url_for( controller='forms', action='edit', **vars ) )
@web.expose
- def edit_template_info( self, trans, cntrller, item_type, library_id, num_widgets, folder_id=None, ldda_id=None, **kwd ):
+ def edit_template_info( self, trans, cntrller, item_type, library_id, folder_id=None, ldda_id=None, **kwd ):
# Edit the contents of the template fields without altering the template itself.
params = util.Params( kwd )
show_deleted = util.string_as_bool( params.get( 'show_deleted', False ) )
@@ -2156,10 +2166,28 @@ class LibraryCommon( BaseController ):
show_deleted=show_deleted,
message=util.sanitize_text( message ),
status='error' ) )
+ # We need the type of each template field widget
+ widgets = item.get_template_widgets( trans )
+ # The list of widgets may include an AddressField which we need to save if it is new
+ for index, widget_dict in enumerate( widgets ):
+ widget = widget_dict[ 'widget' ]
+ if isinstance( widget, AddressField ):
+ value = util.restore_text( params.get( 'field_%i' % index, '' ) )
+ if value == 'new':
+ if params.get( 'edit_info_button', False ):
+ # Save the new address
+ address = trans.app.model.UserAddress( user=trans.user )
+ self.save_widget_field( trans, address, index, **kwd )
+ widget.value = str( address.id )
+ else:
+ # Form was submitted via refresh_on_change
+ widget.value = 'new'
+ elif value == unicode( 'none' ):
+ widget.value = ''
+ else:
+ widget.value = value
# Save updated template field contents
- field_contents = []
- for index in range( int( num_widgets ) ):
- field_contents.append( util.restore_text( params.get( 'field_%i' % ( index ), '' ) ) )
+ field_contents = self.clean_field_contents( widgets, **kwd )
if field_contents:
# Since information templates are inherited, the template fields can be displayed on the information
# page for a folder or ldda when it has no info_association object. If the user has added
--- a/templates/library/common/ldda_info.mako
+++ b/templates/library/common/ldda_info.mako
@@ -1,6 +1,6 @@
<%inherit file="/base.mako"/><%namespace file="/message.mako" import="render_msg" />
-<%namespace file="/library/common/common.mako" import="render_template_info" />
+<%namespace file="/library/common/common.mako" import="render_template_fields" /><%
from galaxy import util
from galaxy.web.controllers.library_common import branch_deleted, get_containing_library_from_library_dataset
@@ -23,6 +23,34 @@
can_modify = can_manage = False
%>
+<%def name="javascripts()">
+ ${parent.javascripts()}
+ <script type="text/javascript">
+ $( function() {
+ $( "select[refresh_on_change='true']").change( function() {
+ var refresh = false;
+ var refresh_on_change_values = $( this )[0].attributes.getNamedItem( 'refresh_on_change_values' )
+ if ( refresh_on_change_values ) {
+ refresh_on_change_values = refresh_on_change_values.value.split( ',' );
+ var last_selected_value = $( this )[0].attributes.getNamedItem( 'last_selected_value' );
+ for( i= 0; i < refresh_on_change_values.length; i++ ) {
+ if ( $( this )[0].value == refresh_on_change_values[i] || ( last_selected_value && last_selected_value.value == refresh_on_change_values[i] ) ){
+ refresh = true;
+ break;
+ }
+ }
+ }
+ else {
+ refresh = true;
+ }
+ if ( refresh ){
+ $( "#edit_info" ).submit();
+ }
+ });
+ });
+ </script>
+</%def>
+
%if current_version:
<b><i>This is the latest version of this library dataset</i></b>
%else:
@@ -134,7 +162,7 @@
</div></div>
%if widgets:
- ${render_template_info( cntrller=cntrller, item_type='ldda', library_id=library_id, widgets=widgets, info_association=info_association, inherited=inherited, folder_id=trans.security.encode_id( ldda.library_dataset.folder.id ), ldda_id=trans.security.encode_id( ldda.id ), editable=False )}
+ ${render_template_fields( cntrller=cntrller, item_type='ldda', library_id=library_id, widgets=widgets, widget_fields_have_contents=widget_fields_have_contents, info_association=info_association, inherited=inherited, folder_id=trans.security.encode_id( ldda.library_dataset.folder.id ), ldda_id=trans.security.encode_id( ldda.id ), editable=False )}
%endif
%if trans.user_is_admin() and cntrller == 'library_admin':
%if associated_hdas:
--- a/test/base/test_db_util.py
+++ b/test/base/test_db_util.py
@@ -109,6 +109,13 @@ def get_user( email ):
return sa_session.query( galaxy.model.User ) \
.filter( galaxy.model.User.table.c.email==email ) \
.first()
+def get_user_address( user, short_desc ):
+ return sa_session.query( galaxy.model.UserAddress ) \
+ .filter( and_( galaxy.model.UserAddress.table.c.user_id==user.id,
+ galaxy.model.UserAddress.table.c.desc==short_desc,
+ galaxy.model.UserAddress.table.c.deleted==False ) ) \
+ .order_by( desc( galaxy.model.UserAddress.table.c.create_time ) ) \
+ .first()
def get_user_group_associations_by_group( group ):
return sa_session.query( galaxy.model.UserGroupAssociation ) \
.filter( galaxy.model.UserGroupAssociation.table.c.group_id == group.id ) \
--- a/templates/library/common/ldda_edit_info.mako
+++ b/templates/library/common/ldda_edit_info.mako
@@ -1,11 +1,35 @@
<%inherit file="/base.mako"/><%namespace file="/message.mako" import="render_msg" />
-<%namespace file="/library/common/common.mako" import="render_template_info" />
+<%namespace file="/library/common/common.mako" import="render_template_fields" /><% from galaxy import util %><%def name="javascripts()">
${parent.javascripts()}
${h.js("jquery.autocomplete", "autocomplete_tagging" )}
+ <script type="text/javascript">
+ $( function() {
+ $( "select[refresh_on_change='true']").change( function() {
+ var refresh = false;
+ var refresh_on_change_values = $( this )[0].attributes.getNamedItem( 'refresh_on_change_values' )
+ if ( refresh_on_change_values ) {
+ refresh_on_change_values = refresh_on_change_values.value.split( ',' );
+ var last_selected_value = $( this )[0].attributes.getNamedItem( 'last_selected_value' );
+ for( i= 0; i < refresh_on_change_values.length; i++ ) {
+ if ( $( this )[0].value == refresh_on_change_values[i] || ( last_selected_value && last_selected_value.value == refresh_on_change_values[i] ) ){
+ refresh = true;
+ break;
+ }
+ }
+ }
+ else {
+ refresh = true;
+ }
+ if ( refresh ){
+ $( "#edit_info" ).submit();
+ }
+ });
+ });
+ </script></%def><%def name="stylesheets()">
@@ -155,5 +179,5 @@
</div>
%endif
%if widgets:
- ${render_template_info( cntrller=cntrller, item_type='ldda', library_id=library_id, widgets=widgets, info_association=info_association, inherited=inherited, folder_id=trans.security.encode_id( ldda.library_dataset.folder.id ), ldda_id=trans.security.encode_id( ldda.id ) )}
+ ${render_template_fields( cntrller=cntrller, item_type='ldda', library_id=library_id, widgets=widgets, widget_fields_have_contents=widget_fields_have_contents, info_association=info_association, inherited=inherited, folder_id=trans.security.encode_id( ldda.library_dataset.folder.id ), ldda_id=trans.security.encode_id( ldda.id ) )}
%endif
1
0

galaxy-dist commit af3ee1e9f9e3: Removing accidentally leftover test line from Tophat wrapper
by commits-noreply@bitbucket.org 08 Sep '10
by commits-noreply@bitbucket.org 08 Sep '10
08 Sep '10
# HG changeset patch -- Bitbucket.org
# Project galaxy-dist
# URL http://bitbucket.org/galaxy/galaxy-dist/overview
# User Kelly Vincent <kpvincent(a)bx.psu.edu>
# Date 1282832971 14400
# Node ID af3ee1e9f9e3c0e51b7b18a323b3fa80460aa864
# Parent e95e14f5e7a0db167a276570495e38f044b17092
Removing accidentally leftover test line from Tophat wrapper
--- a/tools/ngs_rna/tophat_wrapper.py
+++ b/tools/ngs_rna/tophat_wrapper.py
@@ -180,7 +180,6 @@ def __main__():
# Copy SAM File.
shutil.copyfile( tmp_output_dir + "/accepted_hits.sam", options.accepted_hits_output_file )
- shutil.copyfile(tmp_output_dir + "/accepted_hits.sam", '/afs/bx.psu.edu/user/kpvincent/galaxy-commit/tophat_out.sam')
except Exception, e:
stop_err( 'Error in tophat:\n' + str( e ) )
finally:
1
0

galaxy-dist commit e95e14f5e7a0: Fix for the issue where multiple of the same action on separate outputs of a single tool were being overwritten as one.
by commits-noreply@bitbucket.org 08 Sep '10
by commits-noreply@bitbucket.org 08 Sep '10
08 Sep '10
# HG changeset patch -- Bitbucket.org
# Project galaxy-dist
# URL http://bitbucket.org/galaxy/galaxy-dist/overview
# User Dannon Baker <dannonbaker(a)me.com>
# Date 1282824612 14400
# Node ID e95e14f5e7a0db167a276570495e38f044b17092
# Parent 170229de46ca0b9ca21ea555d5085dd5224dcd79
Fix for the issue where multiple of the same action on separate outputs of a single tool were being overwritten as one.
--- a/lib/galaxy/jobs/actions/post.py
+++ b/lib/galaxy/jobs/actions/post.py
@@ -341,16 +341,17 @@ class ActionBox(object):
for key, val in incoming.iteritems():
if key.startswith('pja'):
sp = key.split('__')
+ ao_key = sp[2] + sp[1]
# flag / output_name / pjatype / desc
- if not sp[2] in npd:
- npd[sp[2]] = {'action_type' : sp[2],
+ if not ao_key in npd:
+ npd[ao_key] = {'action_type' : sp[2],
'output_name' : sp[1],
'action_arguments' : {}}
if len(sp) > 3:
if sp[3] == 'output_name':
- npd[sp[2]]['output_name'] = val
+ npd[ao_key]['output_name'] = val
else:
- npd[sp[2]]['action_arguments'][sp[3]] = val
+ npd[ao_key]['action_arguments'][sp[3]] = val
else:
# Not pja stuff.
pass
--- a/static/scripts/galaxy.workflow_editor.canvas.js
+++ b/static/scripts/galaxy.workflow_editor.canvas.js
@@ -413,8 +413,8 @@ function Workflow( canvas_container ) {
output_name : act.output_name,
action_arguments : act.action_arguments
}
- post_job_actions[ act.type + act.output_name ] = null;
- post_job_actions[ act.type + act.output_name ] = pja;
+ post_job_actions[ act.action_type + act.output_name ] = null;
+ post_job_actions[ act.action_type + act.output_name ] = pja;
});
}
if (!node.workflow_outputs){
1
0

galaxy-dist commit 170229de46ca: Fixing buildbot tests: added missing column join test files; regenerated and enhanced BWA test files; sorted tophat_out1.sam and specified sort=True in test for it
by commits-noreply@bitbucket.org 08 Sep '10
by commits-noreply@bitbucket.org 08 Sep '10
08 Sep '10
# HG changeset patch -- Bitbucket.org
# Project galaxy-dist
# URL http://bitbucket.org/galaxy/galaxy-dist/overview
# User Kelly Vincent <kpvincent(a)bx.psu.edu>
# Date 1282787501 14400
# Node ID 170229de46ca0b9ca21ea555d5085dd5224dcd79
# Parent 7fa394981ef6f8d079cd8dd776cba349baca958f
Fixing buildbot tests: added missing column join test files; regenerated and enhanced BWA test files; sorted tophat_out1.sam and specified sort=True in test for it
--- a/test-data/bwa_wrapper_in2.fastq
+++ b/test-data/bwa_wrapper_in2.fastq
@@ -1,4 +1,120 @@
-@081017-and-081020:1:1:1715:1759/2
-ACGCTCCTTTAAAATATC
-+/2
-IIIII$%*$G$A31I&&B
+@seq1/1
+GGACTCAGATAGTAATCC
++/1
+II#IIIIIII$5+.(9II
+@seq2/1
+ATTCGACCTATCCTTGCG
++/1
+IIIIIIIIIIIIIIIIII
+@seq3/1
+GTAACAAAGTTTGGATTG
++/1
+IIIIIIIIIIIIIIIIII
+@seq4/1
+AGCCGCTCGTCTTTTATG
++/1
+IIIIIIIIIIIIIIIIII
+@seq5/1
+CAGTTATATGGCTTTTGG
++/1
+IIIIIIIIIIIIIIIIII
+@seq6/1
+AGGCGCTCGTCTTGGTAT
++/1
+IIIIIIIIIIIIIIIIII
+@seq7/1
+TGTAGGTGGTCAACCAAT
++/1
+IIIIIIIIIIIIIIIIII
+@seq8/1
+ACACCCGTCCTTTACGTC
++/1
+IIIIIIIIIIIIIIIIII
+@seq9/1
+GCCGCTATTCAGGTTGTT
++/1
+IIIIIIIIIIIIIIIIII
+@seq10/1
+ATTCTTTCTTTTCGTATC
++/1
+IIIIIIIIIIIIIIIIII
+@seq11/1
+GCATTTCTACTCCTTCTC
++/1
+II#IIIIIII$5+.(9II
+@seq12/1
+CGCGCTTCGATAAAAATG
++/1
+IIIIIIIIIIIIIIIIII
+@seq13/1
+ATTTCTACTCTTTCTCAT
++/1
+IIIIIIIIIIIIIIIIII
+@seq14/1
+CCCTTTTGAATGTCACGC
++/1
+IIIIIIIIIIIIIIIIII
+@seq15/1
+CCAACTTACCAAGGTGGG
++/1
+IIIIIIIIIIIIIIIIII
+@seq16/1
+TCAGGGTATTAAAAGAGA
++/1
+IIIIIIIIIIIIIIIIII
+@seq17/1
+GTGATGTGCTTGCTACCG
++/1
+IIIIIIIIIIIIIIIIII
+@seq18/1
+TCAATCCCCCATGCTTGG
++/1
+IIIIIIIIIIIIIIIIII
+@seq19/1
+TTCCTGCGCTTAATGCTT
++/1
+IIIIIIIIIIIIIIIIII
+@seq20/1
+CTTATTACCATTTCAACT
++/1
+IIIIIIIIIIIIIIIIII
+@seq21/1
+CTGATACCAATAAAACCC
++/1
+II#IIIIIII$5+.(9II
+@seq22/1
+AATCAAACTTACCAAGGG
++/1
+IIIIIIIIIIIIIIIIII
+@seq23/1
+TGTGCTTCCCCAACTTGA
++/1
+IIIIIIIIIIIIIIIIII
+@seq24/1
+TTTCTCAATCCCCAATGC
++/1
+IIIIIIIIIIIIIIIIII
+@seq25/1
+TTGCTACTGACCGCTCTT
++/1
+IIIIIIIIIIIIIIIIII
+@seq26/1
+CCGCGTGAAATTTCTATG
++/1
+IIIIIIIIIIIIIIIIII
+@seq27/1
+CGCTAATCAAGTTGTTTC
++/1
+IIIIIIIIIIIIIIIIII
+@seq28/1
+AAAGAGATTATTTGTCGG
++/1
+IIIIIIIIIIIIIIIIII
+@seq29/1
+CAAATTAATGCGCGCTTC
++/1
+IIIIIIIIIIIIIIIIII
+@seq30/1
+ATCCCCTATGCTTGGCTT
++/1
+IIIIIIIIIIIIIIIIII
--- a/test-data/bwa_wrapper_out1.sam
+++ b/test-data/bwa_wrapper_out1.sam
@@ -1,1 +1,30 @@
-081017-and-081020:1:1:1715:1759 16 PHIX174 322 25 36M * 0 0 GATATTTTAAAGGAGCGTGGATTACTATCTGAGTCC B&&I13A$G$*%$IIIIIII9(.+5$IIIIIII#II XT:A:U NM:i:2 X0:i:1 X1:i:0 XM:i:2 XO:i:0 XG:i:0 MD:Z:2C8A24
+seq1 16 phiX 322 25 36M * 0 0 GATATTTTAAAGGAGCGTGGATTACTATCTGAGTCC B&&I13A$G$*%$IIIIIII9(.+5$IIIIIII#II XT:A:U NM:i:2 X0:i:1 X1:i:0 XM:i:2 XO:i:0 XG:i:0 MD:Z:2C8A24
+seq10 0 phiX 4149 37 17M1D19M * 0 0 ATTCTTTCTTTTCGTATCAGGGCGTTGAGTTCGATA IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII XT:A:U NM:i:2 X0:i:1 X1:i:0 XM:i:1 XO:i:1 XG:i:1 MD:Z:5G11^G19
+seq11 0 phiX 4072 37 18M1D18M * 0 0 GCATTTCTACTCCTTCTCATCCCCAATGCTTGGCTT II#IIIIIII$5+.(9IIIIIII$%*$G$A31I&&B XT:A:U NM:i:2 X0:i:1 X1:i:0 XM:i:1 XO:i:1 XG:i:1 MD:Z:12T5^A18
+seq12 4 * 0 0 * * 0 0 CGCGCTTCGATAAAAATGGGATTGGCGTTTCCAACC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
+seq13 4 * 0 0 * * 0 0 ATTTCTACTCTTTCTCATCCCCAATCCTTGCCTTCC IIIIIIIIIIIIIIIIIIIIIAAIIIIIIIIIIIII
+seq14 0 phiX 3998 37 21M1D15M * 0 0 CCCTTTTGAATGTCACGCTGATATTTTGACTTTGAG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII XT:A:U NM:i:2 X0:i:1 X1:i:0 XM:i:1 XO:i:1 XG:i:1 MD:Z:5C15^T15
+seq15 4 * 0 0 * * 0 0 CCAACTTACCAAGGTGGGTTACGAAACGCGACGCCG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
+seq16 4 * 0 0 * * 0 0 TCAGGGTATTAAAAGAGATTATTTTTCTCCAGCCAC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
+seq17 0 phiX 3034 37 19M1D17M * 0 0 GTGATGTGCTTGCTACCGAAACAATACTTTAGGCAT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII XT:A:U NM:i:2 X0:i:1 X1:i:0 XM:i:1 XO:i:1 XG:i:1 MD:Z:19^T9G7
+seq18 4 * 0 0 * * 0 0 TCAATCCCCCATGCTTGGCCGTTCCATAAGCAGATG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
+seq19 4 * 0 0 * * 0 0 TTCCTGCGCTTAATGCTTGAGCGTCCTGGTGCTGAT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
+seq2 0 phiX 141 37 36M * 0 0 ATTCGACCTATCCTTGCGCAGCTCGAGAAGCTCTTA IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII XT:A:U NM:i:0 X0:i:1 X1:i:0 XM:i:0 XO:i:0 XG:i:0 MD:Z:36
+seq20 0 phiX 1082 37 36M * 0 0 CTTATTACCATTTCAACTACTCCGGTTATCGCTGGC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII XT:A:U NM:i:0 X0:i:1 X1:i:0 XM:i:0 XO:i:0 XG:i:0 MD:Z:36
+seq21 0 phiX 1344 37 15M1D21M * 0 0 CTGATACCAATAAAACCCTAAGCATTTGGTTCAGGG II#IIIIIII$5+.(9IIIIIII$%*$G$A31I&&B XT:A:U NM:i:2 X0:i:1 X1:i:0 XM:i:1 XO:i:1 XG:i:1 MD:Z:15^T13T7
+seq22 4 * 0 0 * * 0 0 AATCAAACTTACCAAGGGGTTACGACGCGACGCCGT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
+seq23 4 * 0 0 * * 0 0 TGTGCTTCCCCAACTTGATTTAATAACCCTATAGAC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
+seq24 0 phiX 4084 37 17M1I18M * 0 0 TTTCTCAATCCCCAATGCCTTGGCTTCCCTAAGCAG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII XT:A:U NM:i:2 X0:i:1 X1:i:0 XM:i:1 XO:i:1 XG:i:1 MD:Z:27A7
+seq25 0 phiX 520 37 16M1I19M * 0 0 TTGCTACTGACCGCTCTTCGTGCTCGTTGCTGCGTT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII XT:A:U NM:i:2 X0:i:1 X1:i:0 XM:i:1 XO:i:1 XG:i:1 MD:Z:26C8
+seq26 0 phiX 1976 37 36M * 0 0 CCGCGTGAAATTTCTATGAAGGATGTTTTCCGTTCT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII XT:A:U NM:i:0 X0:i:1 X1:i:0 XM:i:0 XO:i:0 XG:i:0 MD:Z:36
+seq27 0 phiX 2598 37 20M1I15M * 0 0 CGCTAATCAAGTTGTTTCTGTTTGGTGCTGATATTG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII XT:A:U NM:i:2 X0:i:1 X1:i:0 XM:i:1 XO:i:1 XG:i:1 MD:Z:9G25
+seq28 4 * 0 0 * * 0 0 AAAGAGATTATTTGTCGGTCCAGCCACTAAAGTGAG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
+seq29 4 * 0 0 * * 0 0 CAAATTAATGCGCGCTTCGATAATGATTGGGGTATC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
+seq3 0 phiX 505 37 36M * 0 0 GTAACAAAGTTTGGATTGCTACTGACCGCTCTCGTG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII XT:A:U NM:i:0 X0:i:1 X1:i:0 XM:i:0 XO:i:0 XG:i:0 MD:Z:36
+seq30 0 phiX 4091 37 18M1I17M * 0 0 ATCCCCTATGCTTGGCTTACCATAAGCAGATGGATA IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII XT:A:U NM:i:2 X0:i:1 X1:i:0 XM:i:1 XO:i:1 XG:i:1 MD:Z:6A28
+seq4 4 * 0 0 * * 0 0 AGCCGCTCGTCTTTTATGTAGGTGGTCAACCATTTT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
+seq5 0 phiX 4985 25 36M * 0 0 CAGTTATATGGCTTTTGGTTTCTATGTGGCTTAATA IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII XT:A:U NM:i:2 X0:i:1 X1:i:0 XM:i:2 XO:i:0 XG:i:0 MD:Z:13G17A4
+seq6 0 phiX 925 37 11M1D25M * 0 0 AGGCGCTCGTCTTGGTATGTAGGTGGTCAACAATTT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII XT:A:U NM:i:1 X0:i:1 X1:i:0 XM:i:0 XO:i:1 XG:i:1 MD:Z:11^T25
+seq7 0 phiX 943 37 13M1I22M * 0 0 TGTAGGTGGTCAACCAATTTTAATTGCAGGGGCTTC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII XT:A:U NM:i:1 X0:i:1 X1:i:0 XM:i:0 XO:i:1 XG:i:1 MD:Z:35
+seq8 4 * 0 0 * * 0 0 ACACCCGTCCTTTACGTCATGCGCTCTATTCTCTGG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
+seq9 0 phiX 2596 37 16M1I19M * 0 0 GCCGCTATTCAGGTTGTTTTCTGTTGGTGCTGATAT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII XT:A:U NM:i:2 X0:i:1 X1:i:0 XM:i:1 XO:i:1 XG:i:1 MD:Z:7A27
--- a/tools/ngs_rna/tophat_wrapper.py
+++ b/tools/ngs_rna/tophat_wrapper.py
@@ -180,6 +180,7 @@ def __main__():
# Copy SAM File.
shutil.copyfile( tmp_output_dir + "/accepted_hits.sam", options.accepted_hits_output_file )
+ shutil.copyfile(tmp_output_dir + "/accepted_hits.sam", '/afs/bx.psu.edu/user/kpvincent/galaxy-commit/tophat_out.sam')
except Exception, e:
stop_err( 'Error in tophat:\n' + str( e ) )
finally:
--- /dev/null
+++ b/test-data/column_join_in13.tabular
@@ -0,0 +1,6 @@
+alpha beta gamma delta
+1 A I a i
+2 B II b ii
+5 C III c
+7 D IV d iii
+11 E V e iv
--- a/test-data/bwa_wrapper_out3.sam
+++ b/test-data/bwa_wrapper_out3.sam
@@ -1,2 +1,60 @@
-081017-and-081020:1:1:1715:1759 113 PHIX174 322 25 18M = 340 18 GATATTTTAAAGGAGCGT B&&I13A$G$*%$IIIII XT:A:U NM:i:2 SM:i:25 AM:i:25 X0:i:1 XM:i:2 XO:i:0 XG:i:0 MD:Z:2C8A6
-081017-and-081020:1:1:1715:1759 177 PHIX174 340 37 18M = 322 -18 GGATTACTATCTGAGTCC II9(.+5$IIIIIII#II XT:A:U NM:i:0 SM:i:37 AM:i:25 X0:i:1 XM:i:0 XO:i:0 XG:i:0 MD:Z:18
+seq1 113 phiX 340 37 18M = 322 -18 GGATTACTATCTGAGTCC II9(.+5$IIIIIII#II XT:A:U NM:i:0 SM:i:37 AM:i:25 X0:i:1 XM:i:0 XO:i:0 XG:i:0 MD:Z:18
+seq1 177 phiX 322 25 18M = 340 18 GATATTTTAAAGGAGCGT B&&I13A$G$*%$IIIII XT:A:U NM:i:2 SM:i:25 AM:i:25 X0:i:1 XM:i:2 XO:i:0 XG:i:0 MD:Z:2C8A6
+seq10 129 phiX 4168 37 18M = 4149 -19 AGGGCGTTGAGTTCGATA IIIIIIIIIIIIIIIIII XT:A:U NM:i:0 SM:i:37 AM:i:25 X0:i:1 XM:i:0 XO:i:0 XG:i:0 MD:Z:18
+seq10 65 phiX 4149 25 18M = 4168 19 ATTCTTTCTTTTCGTATC IIIIIIIIIIIIIIIIII XT:A:U NM:i:2 SM:i:25 AM:i:25 X0:i:1 XM:i:2 XO:i:0 XG:i:0 MD:Z:5G11G0
+seq11 129 phiX 4091 37 18M = 4072 -19 ATCCCCAATGCTTGGCTT IIIII$%*$G$A31I&&B XT:A:U NM:i:0 SM:i:37 AM:i:37 X0:i:1 XM:i:0 XO:i:0 XG:i:0 MD:Z:18
+seq11 65 phiX 4072 37 18M = 4091 19 GCATTTCTACTCCTTCTC II#IIIIIII$5+.(9II XT:A:U NM:i:1 SM:i:37 AM:i:37 X0:i:1 XM:i:1 XO:i:0 XG:i:0 MD:Z:12T5
+seq12 129 phiX 5365 25 18M = 5349 -16 GGATTGGCGTTTCCAACC IIIIIIIIIIIIIIIIII XT:A:U NM:i:2 SM:i:25 AM:i:25 X0:i:1 XM:i:2 XO:i:0 XG:i:0 MD:Z:0T9A7
+seq12 65 phiX 5349 37 18M = 5365 16 CGCGCTTCGATAAAAATG IIIIIIIIIIIIIIIIII XT:A:U NM:i:0 SM:i:37 AM:i:25 X0:i:1 XM:i:0 XO:i:0 XG:i:0 MD:Z:18
+seq13 129 phiX 4093 25 18M = 4074 -19 CCCCAATCCTTGCCTTCC IIIAAIIIIIIIIIIIII XT:A:U NM:i:2 SM:i:25 AM:i:25 X0:i:1 XM:i:2 XO:i:0 XG:i:0 MD:Z:7G4G5
+seq13 65 phiX 4074 37 18M = 4093 19 ATTTCTACTCTTTCTCAT IIIIIIIIIIIIIIIIII XT:A:U NM:i:1 SM:i:37 AM:i:25 X0:i:1 XM:i:1 XO:i:0 XG:i:0 MD:Z:17A0
+seq14 129 phiX 4016 37 3M1D15M = 3998 -18 TGATATTTTGACTTTGAG IIIIIIIIIIIIIIIIII XT:A:U NM:i:1 SM:i:37 AM:i:37 X0:i:1 XM:i:0 XO:i:1 XG:i:1 MD:Z:3^T15
+seq14 65 phiX 3998 37 18M = 4016 18 CCCTTTTGAATGTCACGC IIIIIIIIIIIIIIIIII XT:A:U NM:i:1 SM:i:37 AM:i:37 X0:i:1 XM:i:1 XO:i:0 XG:i:0 MD:Z:5C12
+seq15 129 phiX 5216 37 5M2I11M = 5198 -18 TTACGAAACGCGACGCCG IIIIIIIIIIIIIIIIII XT:A:U NM:i:2 SM:i:37 AM:i:37 X0:i:1 XM:i:0 XO:i:1 XG:i:2 MD:Z:16
+seq15 65 phiX 5198 37 18M = 5216 18 CCAACTTACCAAGGTGGG IIIIIIIIIIIIIIIIII XT:A:U NM:i:1 SM:i:37 AM:i:37 X0:i:1 XM:i:1 XO:i:0 XG:i:0 MD:Z:13C4
+seq16 129 phiX 2897 37 18M = 2880 -17 TTATTTTTCTCCAGCCAC IIIIIIIIIIIIIIIIII XT:A:U NM:i:1 SM:i:37 AM:i:37 X0:i:1 XM:i:1 XO:i:0 XG:i:0 MD:Z:6G11
+seq16 65 phiX 2880 37 10M1I7M = 2897 17 TCAGGGTATTAAAAGAGA IIIIIIIIIIIIIIIIII XT:A:U NM:i:2 SM:i:37 AM:i:37 X0:i:1 XM:i:1 XO:i:1 XG:i:1 MD:Z:5T11
+seq17 129 phiX 3053 25 18M = 3034 -19 AAACAATACTTTAGGCAT IIIIIIIIIIIIIIIIII XT:A:U NM:i:2 SM:i:25 AM:i:25 X0:i:1 XM:i:2 XO:i:0 XG:i:0 MD:Z:0T9G7
+seq17 65 phiX 3034 37 18M = 3053 19 GTGATGTGCTTGCTACCG IIIIIIIIIIIIIIIIII XT:A:U NM:i:0 SM:i:37 AM:i:25 X0:i:1 XM:i:0 XO:i:0 XG:i:0 MD:Z:18
+seq18 133 phiX 4088 0 * = 4088 0 CCGTTCCATAAGCAGATG IIIIIIIIIIIIIIIIII
+seq18 73 phiX 4088 37 18M = 4088 0 TCAATCCCCCATGCTTGG IIIIIIIIIIIIIIIIII XT:A:U NM:i:1 SM:i:37 AM:i:0 X0:i:1 XM:i:1 XO:i:0 XG:i:0 MD:Z:9A8
+seq19 129 phiX 3324 37 18M = 3304 -20 GAGCGTCCTGGTGCTGAT IIIIIIIIIIIIIIIIII XT:A:U NM:i:1 SM:i:37 AM:i:37 X0:i:1 XM:i:1 XO:i:0 XG:i:0 MD:Z:6G11
+seq19 65 phiX 3304 37 18M = 3324 20 TTCCTGCGCTTAATGCTT IIIIIIIIIIIIIIIIII XT:A:U NM:i:1 SM:i:37 AM:i:37 X0:i:1 XM:i:1 XO:i:0 XG:i:0 MD:Z:6A11
+seq2 129 phiX 159 37 18M = 141 -18 CAGCTCGAGAAGCTCTTA IIIIIIIIIIIIIIIIII XT:A:U NM:i:0 SM:i:37 AM:i:37 X0:i:1 XM:i:0 XO:i:0 XG:i:0 MD:Z:18
+seq2 65 phiX 141 37 18M = 159 18 ATTCGACCTATCCTTGCG IIIIIIIIIIIIIIIIII XT:A:U NM:i:0 SM:i:37 AM:i:37 X0:i:1 XM:i:0 XO:i:0 XG:i:0 MD:Z:18
+seq20 129 phiX 1100 37 18M = 1082 -18 ACTCCGGTTATCGCTGGC IIIIIIIIIIIIIIIIII XT:A:U NM:i:0 SM:i:37 AM:i:37 X0:i:1 XM:i:0 XO:i:0 XG:i:0 MD:Z:18
+seq20 65 phiX 1082 37 18M = 1100 18 CTTATTACCATTTCAACT IIIIIIIIIIIIIIIIII XT:A:U NM:i:0 SM:i:37 AM:i:37 X0:i:1 XM:i:0 XO:i:0 XG:i:0 MD:Z:18
+seq21 129 phiX 1363 37 18M = 1344 -19 TAAGCATTTGGTTCAGGG IIIII$%*$G$A31I&&B XT:A:U NM:i:1 SM:i:37 AM:i:37 X0:i:1 XM:i:1 XO:i:0 XG:i:0 MD:Z:10T7
+seq21 65 phiX 1344 37 18M = 1363 19 CTGATACCAATAAAACCC II#IIIIIII$5+.(9II XT:A:U NM:i:1 SM:i:37 AM:i:37 X0:i:1 XM:i:1 XO:i:0 XG:i:0 MD:Z:15T2
+seq22 137 phiX 5215 37 18M = 5215 0 GTTACGACGCGACGCCGT IIIIIIIIIIIIIIIIII XT:A:U NM:i:0 SM:i:37 AM:i:0 X0:i:1 XM:i:0 XO:i:0 XG:i:0 MD:Z:18
+seq22 69 phiX 5215 0 * = 5215 0 AATCAAACTTACCAAGGG IIIIIIIIIIIIIIIIII
+seq23 129 phiX 4308 25 18M = 4289 -19 TTTAATAACCCTATAGAC IIIIIIIIIIIIIIIIII XT:A:U NM:i:2 SM:i:25 AM:i:25 X0:i:1 XM:i:2 XO:i:0 XG:i:0 MD:Z:0A8A8
+seq23 65 phiX 4289 37 18M = 4308 19 TGTGCTTCCCCAACTTGA IIIIIIIIIIIIIIIIII XT:A:U NM:i:1 SM:i:37 AM:i:25 X0:i:1 XM:i:1 XO:i:0 XG:i:0 MD:Z:6C11
+seq24 129 phiX 4101 37 18M = 4084 -17 CTTGGCTTCCCTAAGCAG IIIIIIIIIIIIIIIIII XT:A:U NM:i:1 SM:i:37 AM:i:37 X0:i:1 XM:i:1 XO:i:0 XG:i:0 MD:Z:10A7
+seq24 65 phiX 4084 37 18M = 4101 17 TTTCTCAATCCCCAATGC IIIIIIIIIIIIIIIIII XT:A:U NM:i:0 SM:i:37 AM:i:37 X0:i:1 XM:i:0 XO:i:0 XG:i:0 MD:Z:18
+seq25 129 phiX 537 37 18M = 520 -17 CGTGCTCGTTGCTGCGTT IIIIIIIIIIIIIIIIII XT:A:U NM:i:1 SM:i:37 AM:i:37 X0:i:1 XM:i:1 XO:i:0 XG:i:0 MD:Z:9C8
+seq25 65 phiX 520 37 18M = 537 17 TTGCTACTGACCGCTCTT IIIIIIIIIIIIIIIIII XT:A:U NM:i:1 SM:i:37 AM:i:37 X0:i:1 XM:i:1 XO:i:0 XG:i:0 MD:Z:17C0
+seq26 129 phiX 1994 37 18M = 1976 -18 AAGGATGTTTTCCGTTCT IIIIIIIIIIIIIIIIII XT:A:U NM:i:0 SM:i:37 AM:i:37 X0:i:1 XM:i:0 XO:i:0 XG:i:0 MD:Z:18
+seq26 65 phiX 1976 37 18M = 1994 18 CCGCGTGAAATTTCTATG IIIIIIIIIIIIIIIIII XT:A:U NM:i:0 SM:i:37 AM:i:37 X0:i:1 XM:i:0 XO:i:0 XG:i:0 MD:Z:18
+seq27 129 phiX 2614 37 3M1D15M = 2598 -16 TGTTTGGTGCTGATATTG IIIIIIIIIIIIIIIIII XT:A:U NM:i:2 SM:i:37 AM:i:37 X0:i:1 XM:i:0 XO:i:1 XG:i:1 MD:Z:1C1^G15
+seq27 65 phiX 2598 37 18M = 2614 16 CGCTAATCAAGTTGTTTC IIIIIIIIIIIIIIIIII XT:A:U NM:i:1 SM:i:37 AM:i:37 X0:i:1 XM:i:1 XO:i:0 XG:i:0 MD:Z:9G8
+seq28 129 phiX 2906 37 18M = 2890 -16 TCCAGCCACTAAAGTGAG IIIIIIIIIIIIIIIIII XT:A:U NM:i:1 SM:i:37 AM:i:25 X0:i:1 XM:i:1 XO:i:0 XG:i:0 MD:Z:10T7
+seq28 65 phiX 2890 25 18M = 2906 16 AAAGAGATTATTTGTCGG IIIIIIIIIIIIIIIIII XT:A:U NM:i:2 SM:i:25 AM:i:25 X0:i:1 XM:i:2 XO:i:0 XG:i:0 MD:Z:16T0C0
+seq29 133 phiX 5339 0 * = 5339 0 GATAATGATTGGGGTATC IIIIIIIIIIIIIIIIII
+seq29 73 phiX 5339 37 18M = 5339 0 CAAATTAATGCGCGCTTC IIIIIIIIIIIIIIIIII XT:A:U NM:i:1 SM:i:37 AM:i:0 X0:i:1 XM:i:1 XO:i:0 XG:i:0 MD:Z:6T11
+seq3 129 phiX 523 37 18M = 505 -18 CTACTGACCGCTCTCGTG IIIIIIIIIIIIIIIIII XT:A:U NM:i:0 SM:i:37 AM:i:37 X0:i:1 XM:i:0 XO:i:0 XG:i:0 MD:Z:18
+seq3 65 phiX 505 37 18M = 523 18 GTAACAAAGTTTGGATTG IIIIIIIIIIIIIIIIII XT:A:U NM:i:0 SM:i:37 AM:i:37 X0:i:1 XM:i:0 XO:i:0 XG:i:0 MD:Z:18
+seq30 129 phiX 4108 37 18M = 4091 -17 ACCATAAGCAGATGGATA IIIIIIIIIIIIIIIIII XT:A:U NM:i:1 SM:i:37 AM:i:37 X0:i:1 XM:i:1 XO:i:0 XG:i:0 MD:Z:0T17
+seq30 65 phiX 4091 37 18M = 4108 17 ATCCCCTATGCTTGGCTT IIIIIIIIIIIIIIIIII XT:A:U NM:i:1 SM:i:37 AM:i:37 X0:i:1 XM:i:1 XO:i:0 XG:i:0 MD:Z:6A11
+seq4 137 phiX 945 37 18M = 945 0 TAGGTGGTCAACCATTTT IIIIIIIIIIIIIIIIII XT:A:U NM:i:1 SM:i:37 AM:i:0 X0:i:1 XM:i:1 XO:i:0 XG:i:0 MD:Z:12A5
+seq4 69 phiX 945 0 * = 945 0 AGCCGCTCGTCTTTTATG IIIIIIIIIIIIIIIIII
+seq5 129 phiX 5003 37 18M = 4985 -18 TTTCTATGTGGCTTAATA IIIIIIIIIIIIIIIIII XT:A:U NM:i:1 SM:i:37 AM:i:37 X0:i:1 XM:i:1 XO:i:0 XG:i:0 MD:Z:13A4
+seq5 65 phiX 4985 37 18M = 5003 18 CAGTTATATGGCTTTTGG IIIIIIIIIIIIIIIIII XT:A:U NM:i:1 SM:i:37 AM:i:37 X0:i:1 XM:i:1 XO:i:0 XG:i:0 MD:Z:13G4
+seq6 129 phiX 944 37 18M = 925 -19 GTAGGTGGTCAACAATTT IIIIIIIIIIIIIIIIII XT:A:U NM:i:0 SM:i:37 AM:i:37 X0:i:1 XM:i:0 XO:i:0 XG:i:0 MD:Z:18
+seq6 65 phiX 925 37 11M1D7M = 944 19 AGGCGCTCGTCTTGGTAT IIIIIIIIIIIIIIIIII XT:A:U NM:i:1 SM:i:37 AM:i:37 X0:i:1 XM:i:0 XO:i:1 XG:i:1 MD:Z:11^T7
+seq7 129 phiX 960 37 18M = 943 -17 TTTAATTGCAGGGGCTTC IIIIIIIIIIIIIIIIII XT:A:U NM:i:0 SM:i:37 AM:i:25 X0:i:1 XM:i:0 XO:i:0 XG:i:0 MD:Z:18
+seq7 65 phiX 943 25 18M = 960 17 TGTAGGTGGTCAACCAAT IIIIIIIIIIIIIIIIII XT:A:U NM:i:2 SM:i:25 AM:i:25 X0:i:1 XM:i:2 XO:i:0 XG:i:0 MD:Z:14A1T1
+seq8 137 phiX 1715 37 18M = 1715 0 ATGCGCTCTATTCTCTGG IIIIIIIIIIIIIIIIII XT:A:U NM:i:1 SM:i:37 AM:i:0 X0:i:1 XM:i:1 XO:i:0 XG:i:0 MD:Z:10A7
+seq8 69 phiX 1715 0 * = 1715 0 ACACCCGTCCTTTACGTC IIIIIIIIIIIIIIIIII
+seq9 129 phiX 2613 37 18M = 2596 -17 TTCTGTTGGTGCTGATAT IIIIIIIIIIIIIIIIII XT:A:U NM:i:0 SM:i:37 AM:i:37 X0:i:1 XM:i:0 XO:i:0 XG:i:0 MD:Z:18
+seq9 65 phiX 2596 37 18M = 2613 17 GCCGCTATTCAGGTTGTT IIIIIIIIIIIIIIIIII XT:A:U NM:i:1 SM:i:37 AM:i:37 X0:i:1 XM:i:1 XO:i:0 XG:i:0 MD:Z:7A10
--- a/test-data/tophat_out1.sam
+++ b/test-data/tophat_out1.sam
@@ -1,179 +1,179 @@
-test_mRNA_3_187_51 99 test_chromosome 53 255 75M = 163 0 TACTATTTGACTAGACTGGAGGCGCTTGCGACTGAGCTAGGACGTGCCACTACGGGGATGACGACTCGGACTACG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 NH:i:1
-test_mRNA_4_191_5d 163 test_chromosome 54 255 75M = 167 0 ACTATCTGACGAGACTGGAGGCGCTTGCGACTGAGCTAGGACGTACCATTACGCGGATGACGACTAGGACTACGG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:4 NH:i:1
-test_mRNA_5_197_46 97 test_chromosome 55 255 75M = 173 0 CTATCTGACTAGACTCGAGGCGCTTGCGTCTGAGCTAGGACGTGCCACTACGGGGATGACGACTAGGACTACGGA IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 NH:i:1
-test_mRNA_6_182_59 99 test_chromosome 56 255 75M = 158 0 TATCTGACTAGACTGGAGGCGCTTGCGACTGAGCTAGGACGTGCCAGTACGGGGATGACGACTAGGACTACGGAC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 NH:i:1
-test_mRNA_8_155_9 163 test_chromosome 58 255 75M = 131 0 TGTGACTAGACTGGAGGCGCTTGCGACTGAGCTAGGACGTGCCACTACGGGGATGACGACTAGGACTACGGACGG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 NH:i:1
-test_mRNA_8_197_1 99 test_chromosome 58 255 75M = 173 0 TCTGACTAGACTGGAGGCGCTTGCGACTGAGCTAGGACGTGACACTACGGGGATGGCGACTAGGACTACGGACGG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 NH:i:1
-test_mRNA_9_179_52 163 test_chromosome 59 255 75M = 155 0 CTGACTAGACTGGAGGCGCTCGCGACTGAGCTAGGACGTGCCACTACGGGGATGACGACTAGGACTACGGACGGA IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 NH:i:1
+test_mRNA_103_284_2a 161 test_chromosome 153 255 75M = 360 0 CGACTGGACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 NH:i:1
+test_mRNA_103_284_2a 81 test_chromosome 360 255 41M100N34M = 153 0 TTATTATCTTACTCGGACGTAGACGGATCGGCAACGGGACTTTTTCTACTTGAGACTGGGATCGAGGCGGACTTT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:0 XS:A:+ NH:i:1
+test_mRNA_104_274_1c 73 test_chromosome 350 255 51M100N24M * 0 0 CACTATTACTTTATTATCTTACTCGGACGTAGACGGATCGGCAACGGGACTTTTTCTACTTGAGACTGGGATCGA IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 XS:A:+ NH:i:1
+test_mRNA_104_278_3e 161 test_chromosome 154 255 75M = 354 0 GACTGGACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTTTTTGGCGCGCGGCCCTACGGCTG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 NH:i:1
+test_mRNA_104_278_3e 81 test_chromosome 354 255 47M100N28M = 154 0 ATTACTTTATTATCTTACTCGGACGTAGACGGATCGGCAACGGGACTTTTTCTACTTGAGACTGGAATCGAGGCG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 XS:A:+ NH:i:1
+test_mRNA_105_266_13 163 test_chromosome 155 255 75M = 242 0 ACTGGACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGA IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 NH:i:1
+test_mRNA_105_266_13 83 test_chromosome 242 255 9M100N50M100N16M = 155 0 CGATCCGCCACTATTACTTTATTATCTTACTCGGACGTAGACGGATCGGCAACGGGACTTTTTCTACTTGAGACT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 XS:A:+ NH:i:1
+test_mRNA_105_276_c 161 test_chromosome 155 255 75M = 352 0 ACTGGACTATTTAGGACGATCGGACTGAGGAAGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGA IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 NH:i:1
+test_mRNA_105_276_c 81 test_chromosome 352 255 49M100N26M = 155 0 CTATTACTTTATTATCTTACTCGGACGTAGACGGATCGGCAACGGGGCTTTTTCTACTTGAGACTGGGATCGAGG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 XS:A:+ NH:i:1
+test_mRNA_106_253_45 137 test_chromosome 156 255 75M * 0 0 CTGGACTATTTAGGTCGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 NH:i:1
+test_mRNA_107_286_5 161 test_chromosome 157 255 75M = 362 0 TGGACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGCATTTGGCGCGCGGCCCTACGGCTGAGC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 NH:i:1
+test_mRNA_107_286_5 81 test_chromosome 362 255 39M100N36M = 157 0 ATTATCTTACTCGGACGTAGACGGATCGGCAACGGGACTTTTTCTACTTGAGACTGGGATCGAGGCGGACTTTTT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:0 XS:A:+ NH:i:1
+test_mRNA_110_267_22 163 test_chromosome 160 255 75M = 243 0 ACTAGTTAGGGCGATCGGACTGAGGAGGGCAGTAGGACGCTACGTAGTTGGCGCGCGGCCCTACGACTGAGCGTC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:5 NH:i:1
+test_mRNA_110_267_22 83 test_chromosome 243 255 8M100N50M100N17M = 160 0 GATACGCCACTATTACTTTATTATCTTACTCGGACGTAGACGGATCGGCAACGGGACTTTTTCTACTTGAGACTG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:0 XS:A:+ NH:i:1
+test_mRNA_110_271_28 147 test_chromosome 247 255 4M100N50M100N21M = 160 0 CGCCACTATTACTTTATTATCTTACTCGGACGAAGACGGATCGGCAACGGGGCTTTTTCTACTTGAGACTGGGAT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 XS:A:+ NH:i:1
+test_mRNA_110_271_28 99 test_chromosome 160 255 75M = 247 0 ACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 NH:i:1
+test_mRNA_111_268_d 73 test_chromosome 244 255 7M100N50M100N18M * 0 0 ATACGCCACTATTATTTTATTATCTTACTCGGACGTAGACGGATCGGCAACGGGACTTTTTCTACTTGAGACTGG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 XS:A:+ NH:i:1
+test_mRNA_111_297_61 161 test_chromosome 161 255 75M = 373 0 CTATTTAGGACGATCGGACTGGGGAGGGCAGTAGGACGCTACGGATTTGGCGCGCGGCCCTACGGCTGAGCGTCG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:3 NH:i:1
+test_mRNA_111_297_61 81 test_chromosome 373 255 28M100N47M = 161 0 CGGACGTAGACGGATCCGCAACGGGACTTTTTCTACTTGAGACTGGGATCGAGGCGGACTTTTTAGGACGGGACT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 XS:A:+ NH:i:1
+test_mRNA_114_277_5b 161 test_chromosome 164 255 75M = 353 0 TTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGCCTGAGCGTCGAGC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 NH:i:1
+test_mRNA_114_277_5b 81 test_chromosome 353 255 48M100N27M = 164 0 TATTACTTTATTATCTTACTCGGAGGTAGACGGAACGGCAACGGGACTTTTTCTGCTTGAGACTGGGATCGAGGC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:4 XS:A:+ NH:i:1
+test_mRNA_116_271_2b 163 test_chromosome 166 255 75M = 247 0 TAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 NH:i:1
+test_mRNA_116_271_2b 83 test_chromosome 247 255 4M100N50M100N21M = 166 0 CGCCACTATTACTTTATTATCTTACTCGGACGTAGACAGATCGGCAACGGGACTTTTTCTACTTGAGACTGGGAT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 XS:A:+ NH:i:1
+test_mRNA_116_295_63 161 test_chromosome 166 255 75M = 371 0 TAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 NH:i:1
+test_mRNA_116_295_63 81 test_chromosome 371 255 30M100N45M = 166 0 CTCGGACGTAGACGGATCGGCAACGGGACTTTTTCTACTTGAGACTGGGATCGAGGCGGACTTTTTAGGACGGGA IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:0 XS:A:+ NH:i:1
+test_mRNA_118_297_f 161 test_chromosome 168 255 75M = 373 0 GGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 NH:i:1
+test_mRNA_118_297_f 81 test_chromosome 373 255 28M100N47M = 168 0 CGGACGTAGACGGATCGGCAACGGGACTTTTTCTACTTGAGACTGGGATCGAGGCGGACTTTTTAGGACGGGACT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:0 XS:A:+ NH:i:1
+test_mRNA_11_190_1a 147 test_chromosome 166 255 75M = 61 0 TAGGTCGATGGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGTGGCCCTACGGCTGAGCGTCGAGCTT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:4 NH:i:1
test_mRNA_11_190_1a 99 test_chromosome 61 255 75M = 166 0 GACTAGACTGGAGGCGCTTGCGACTGAGCTAGGACGTGCCACTACGGGGATGACGACTAGGACTACGGACGGACT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:0 NH:i:1
+test_mRNA_122_299_6 161 test_chromosome 172 255 75M = 375 0 GATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGCGATA IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 NH:i:1
+test_mRNA_122_299_6 81 test_chromosome 375 255 26M100N49M = 172 0 GACGTAGACGGAGCGGCAACGGGACTTTTTCTACTTGAGACTGGGATCGAGGCGGACTTTTTAGGACGGGACTTG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 XS:A:+ NH:i:1
+test_mRNA_125_280_48 145 test_chromosome 356 255 45M100N30M = 175 0 TACTTTATTATCTTACTCTGACGTAGACGGATCGGCAACGGGACTTTTTCTACTTGAGACTGGGAGCGAGGCGGA IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 XS:A:+ NH:i:1
+test_mRNA_125_280_48 97 test_chromosome 175 255 75M = 356 0 CGGACTGAGGAGGGCAGTAGGACGCTATGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGCGAAACGC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:3 NH:i:1
+test_mRNA_125_293_60 161 test_chromosome 175 255 75M = 369 0 CGGACTGAGGAGGGCAGTAGGACGCTATGTATTTGGCGCGCGGCCCTACGGCTGAGCTTCGAGGTTGCGATACGC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:4 NH:i:1
+test_mRNA_125_293_60 81 test_chromosome 369 255 32M100N43M = 175 0 TACTCGGACGTAGACGGATCGGCAACGGGACTTTTTCTACTTGAGACTGGGATCGAGGCGGACTTTTTAGGACGG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:0 XS:A:+ NH:i:1
+test_mRNA_126_282_18 161 test_chromosome 176 255 75M = 358 0 GGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGCGATACGCC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 NH:i:1
+test_mRNA_126_282_18 81 test_chromosome 358 255 43M100N32M = 176 0 CTTTATTATCTTACTCGGACGTAGACGGATCGGCAACGGGACTTTTTCTACTTGAGACTGGGATCGAGGCGGACT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:0 XS:A:+ NH:i:1
+test_mRNA_128_252_36 137 test_chromosome 228 255 23M100N52M * 0 0 GAGCGTCGAGCTTGCGATACGCCACTATTACTTTATTATCTTACTCGGACGTAGACGGATCGGGAACGGGACTTT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:4 XS:A:+ NH:i:1
+test_mRNA_131_260_33 147 test_chromosome 236 255 15M100N50M100N10M = 181 0 AGCTTGTGATACGCCACTATTACTTTATTATCTTACTCGGACGTAAACGGATCGGCCACGGGACTTTTTTTACTT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:4 XS:A:+ NH:i:1
+test_mRNA_131_260_33 99 test_chromosome 181 255 70M100N5M = 236 0 GAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGCGATACGCCACTAT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 XS:A:+ NH:i:1
+test_mRNA_145_300_37 163 test_chromosome 195 255 56M100N19M = 376 0 GACGCTACGTATTTGGCGCGGGGCCCTATGGCTGAGCGTCGAGCTTGCGATACGCCACTATTACTTTAGTATATT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:5 XS:A:+ NH:i:1
+test_mRNA_145_300_37 83 test_chromosome 376 255 25M100N50M = 195 0 ACGTAGACGGATCGGAAACGGGACTTTTTCTACTTGAGACTGGGATCGAGGCGGACTTTTTAGGACGGGACTTGC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 XS:A:+ NH:i:1
+test_mRNA_150_290_0 73 test_chromosome 366 255 35M100N40M * 0 0 TCTTACTCGGACGTAGACGGATCGCCAACGGGACTTTTTCTACTTGAGACTGAGACCGAGGCGGACTTTTTAGGA IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:3 XS:A:+ NH:i:1
+test_mRNA_151_286_e 137 test_chromosome 362 255 39M100N36M * 0 0 ATTATCTTACTCGGACGTAGACGGATCGGCAACGGGACTTTATCTACTTGAGACTGGGATCGAGGCGGACTTTTT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 XS:A:+ NH:i:1
+test_mRNA_151_297_1d 137 test_chromosome 373 255 28M100N47M * 0 0 CGGACGTAGACGGATCGGCAACGGGACTTTTTCTACTTGAGACTGGGATCGAGGCGGACATTTTAGGACGGGACT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 XS:A:+ NH:i:1
test_mRNA_16_194_10 163 test_chromosome 66 255 75M = 170 0 GACTGGATGCGCTTGCGACTGAGCTAGGACGTGCCACTACGGGGATGACGACTCGGACTACGGACGGACTTAAAG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:3 NH:i:1
+test_mRNA_16_194_10 83 test_chromosome 170 255 75M = 66 0 ACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGCGA IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 NH:i:1
+test_mRNA_172_294_4f 147 test_chromosome 370 255 31M100N44M = 222 0 ACTCGGACGTAGACGGGTCGGCAGCGGGACTTTTTCTACTTGAGACTGGGATCGAGGCGGACGTTTTAGGACGGG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:3 XS:A:+ NH:i:1
+test_mRNA_172_294_4f 99 test_chromosome 222 255 29M100N46M = 370 0 ACGGATGAGCGTCGAGCTTGCGATACGCCACTATTACTTTATTATCTTCCTCGGACGTAGACGGATCGCCAACGG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:3 XS:A:+ NH:i:1
test_mRNA_21_208_24 163 test_chromosome 71 255 75M = 184 0 GAGGCGCTTGCGACTGAGCTAGGACGTGCCACTACGGGGATGACGACTAGGACTACGGACGGACTTAGAGCGTCA IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:0 NH:i:1
+test_mRNA_21_208_24 83 test_chromosome 184 255 67M100N8M = 71 0 GAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGCCTGAGCGTCGAGCTTGCGATACGCCACTATTAC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 XS:A:+ NH:i:1
+test_mRNA_22_173_62 147 test_chromosome 149 255 75M = 72 0 GCAGCGACTGGACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTAC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 NH:i:1
test_mRNA_22_173_62 99 test_chromosome 72 255 75M = 149 0 AGGCGCTTGCGACTGAGCTAGGACGTGCCACTACGGGGATGACGACTAGGACTACGGACGGACTTAGAGCGTCAG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:0 NH:i:1
test_mRNA_23_186_42 163 test_chromosome 73 255 75M = 162 0 GGCGCTTGTGACTGAGCTAGGACGTGCCACTACGGGGATGAAGACTAGGACTACGGACGGACTTAGAGCGTCAGA IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 NH:i:1
+test_mRNA_23_186_42 83 test_chromosome 162 255 75M = 73 0 TATTTAGGACGATCGGACGGAGGAGGGCAGAAGGACGCTACGTATTTGGCGCGCGGCCCTACGACTGAGCGTCGA IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:4 NH:i:1
test_mRNA_26_189_30 163 test_chromosome 76 255 75M = 165 0 GCTTGCGACTGAGCTAGGACGTGCCACTACGGGGATGACGACTAGGACTACGGACGGACTTAGAGCGTCAGATGC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:0 NH:i:1
+test_mRNA_26_189_30 83 test_chromosome 165 255 75M = 76 0 TTAGGACGATCGGACTGAGGAGGGCAGTAGGACGGTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 NH:i:1
+test_mRNA_28_188_11 147 test_chromosome 164 255 75M = 78 0 TTTAGGACGATCGGACTGAGGAAGGCAGTAGGACGCTTCGTATTTGGCGCGAGGCCCTACGGCTGAGCGTCGAGC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:4 NH:i:1
test_mRNA_28_188_11 99 test_chromosome 78 255 75M = 164 0 TTGCGACTGAGCTAGGACGTGCCACTACGGGGATGACGACTAGGACTACGAACGGACTTAGAGCGTCAGATGCAG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 NH:i:1
test_mRNA_28_206_1f 73 test_chromosome 78 255 75M * 0 0 TTGCGACTGAGCTAGGACGTGCCACTACGGGGATGACGACTAGGACTACGGACGGACTTAGAGCGTCAGACGCAG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 NH:i:1
test_mRNA_30_231_3c 161 test_chromosome 80 255 75M = 207 0 GCGACTGAGCTAGGACGTGCCACTACGGGGATGACGACTAGGACTACGGACGGACTTAGAGCGTCAGATGCAGCG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:0 NH:i:1
+test_mRNA_30_231_3c 81 test_chromosome 207 255 44M100N31M = 80 0 TTGGCGCGCGGCCCTACGGCTAAGCGTCGAGCTTGCGATACGCCACTATTACTTTAATATCTTACTCGCACGTAG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:4 XS:A:+ NH:i:1
+test_mRNA_33_189_4a 73 test_chromosome 165 255 75M * 0 0 TTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACCTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGGGCT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:3 NH:i:1
test_mRNA_33_223_4e 73 test_chromosome 83 255 75M * 0 0 ACTGAGCTAGGACGTGCCACTACGGGGATGACGACTAGGACTACGGACGGACTTAGAGCGTCAGATGCAGCGACT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:0 NH:i:1
test_mRNA_36_146_27 163 test_chromosome 86 255 75M = 122 0 GCGCTAGGACGTGCCACTACGGGGATGACGACTAGGACTACAGACGGACTTAGAGCGTCAGATGCAGCGACTGGA IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 NH:i:1
+test_mRNA_36_146_27 83 test_chromosome 122 255 75M = 86 0 ACTACGGACGGACTTAGAGCGTCAGATGCAGCGACTGGACTATTTAGGACGATCGGACTGAGGAGTGCAGTAGGT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 NH:i:1
+test_mRNA_36_218_12 147 test_chromosome 194 255 57M100N18M = 86 0 GGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGCGATACGCCACTATTACTTTATTATCT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 XS:A:+ NH:i:1
test_mRNA_36_218_12 99 test_chromosome 86 255 75M = 194 0 GAGCTAGGACGTGCCACTACGGGGATGACGACTAGGACTACGGACGGCCTTAGAGCGTCAGATGCAGCGACTGGA IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 NH:i:1
+test_mRNA_38_199_29 147 test_chromosome 175 255 75M = 88 0 CGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGCGATACGC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 NH:i:1
test_mRNA_38_199_29 99 test_chromosome 88 255 75M = 175 0 GCTAGGACGTGCCACTACGGGGATGACGACTAGGACTACGGACGGACTTAGAGCGTCAGATGCAGCGACTGGACT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:0 NH:i:1
+test_mRNA_39_219_5c 147 test_chromosome 195 255 56M100N19M = 89 0 GACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCCAGCTTGCGATACGCCACTATTACTTTATTATCTT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 XS:A:+ NH:i:1
test_mRNA_39_219_5c 99 test_chromosome 89 255 75M = 195 0 CTAGGACGTCCCACTATGGGGATGACGACTAGGACTACGGACGGACTTAGAGCGTCAGATGCAGCGGCTGGACTA IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:3 NH:i:1
+test_mRNA_3_187_51 147 test_chromosome 163 255 75M = 53 0 ATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 NH:i:1
+test_mRNA_3_187_51 99 test_chromosome 53 255 75M = 163 0 TACTATTTGACTAGACTGGAGGCGCTTGCGACTGAGCTAGGACGTGCCACTACGGGGATGACGACTCGGACTACG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 NH:i:1
+test_mRNA_41_236_55 145 test_chromosome 212 255 39M100N36M = 91 0 GCGCGGCCCTACGGCTGAGCGTCGAGCTTGCGATACGCCACTATTACTTTATTATCTTACTCGGACGTAGACGGA IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 XS:A:+ NH:i:1
test_mRNA_41_236_55 97 test_chromosome 91 255 75M = 212 0 AGGACGTGCCACTACGGGGATGACGACTAGGACTACGGACGGACTTAGAGCGTCAGATGCAGCGACTGGAATATT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 NH:i:1
+test_mRNA_42_209_25 147 test_chromosome 185 255 66M100N9M = 92 0 AGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGCGATACGCCACTATTACT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 XS:A:+ NH:i:1
test_mRNA_42_209_25 99 test_chromosome 92 255 75M = 185 0 GGACGTGCCACTACGTGGATGACGACTAGGACTACGGACGGACTTAGAGCGTCAGATGCAGCGACTGGACTATTT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 NH:i:1
+test_mRNA_44_193_3f 147 test_chromosome 169 255 75M = 94 0 GACGATCGGACTGGGGAGAGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGCG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:3 NH:i:1
test_mRNA_44_193_3f 99 test_chromosome 94 255 75M = 169 0 ACGTGCCACTACGGGGATGACGACTAGGACTACGGACGGACTTAGAGCGTCAGATGCAGCGACTGGTCTATTTAG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 NH:i:1
+test_mRNA_44_197_35 147 test_chromosome 173 255 75M = 94 0 ATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGATCGTCGAGCTTGCGATAC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 NH:i:1
test_mRNA_44_197_35 99 test_chromosome 94 255 75M = 173 0 ACGTGCAACTACGGGGATGACGACTAGGACTACGGACGGACTTAGAGCGTCAGATGCAGCGACTGGACTATTTAG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 NH:i:1
test_mRNA_44_225_1e 163 test_chromosome 94 255 75M = 201 0 ACGTGCCACTACGGGGATGACGACTAGGACTACGGACGGACTTAGAGCGTCGGGTGCAGCGACTGGACTATTTAG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 NH:i:1
+test_mRNA_44_225_1e 83 test_chromosome 201 255 50M100N25M = 94 0 ACGTATATGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGCGATACGCCACTATTACTTTATTATCTTACTCGG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 XS:A:+ NH:i:1
test_mRNA_46_195_17 137 test_chromosome 96 255 75M * 0 0 GTGCCACTACGGGGATGACGACTAGGACTACGGACGGACTTAGAGCGTCAGATGCAGCGACTGGACTATTTAGGA IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:0 NH:i:1
+test_mRNA_46_232_2f 147 test_chromosome 208 255 43M100N32M = 96 0 TGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGCGATACGCCACTATTACTTTATTATCTTACTCGGACGTAGA IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 XS:A:+ NH:i:1
test_mRNA_46_232_2f 99 test_chromosome 96 255 75M = 208 0 GTGCCACTACGGGGATGACGACTAGGACTACGGCCGGACTTAGAGCGTCAGATGCAGCGACTGGACTATTTAGGA IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 NH:i:1
test_mRNA_48_207_39 73 test_chromosome 98 255 75M * 0 0 GCCCCTACGGGGATGACGACTAGGACTACGGACGGATTTAGACCGTCAGATGCAGCGACTGGACTATTTAGGACG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:3 NH:i:1
test_mRNA_48_249_20 161 test_chromosome 98 255 75M = 225 0 GCCACTACGGGGATGACGACTAGGACGACGGACGGACTTAGAGCGTCAGATGCAGCGACTGGACTATTTAGGACG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 NH:i:1
+test_mRNA_48_249_20 81 test_chromosome 225 255 26M100N49M = 98 0 GCTGAGCGTCGAGCTTGCGATACGCCACTATTACTTTACTATCTTACTCGGACGGAGACGGATCGGCAACGGGAC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:3 XS:A:+ NH:i:1
+test_mRNA_4_191_5d 163 test_chromosome 54 255 75M = 167 0 ACTATCTGACGAGACTGGAGGCGCTTGCGACTGAGCTAGGACGTACCATTACGCGGATGACGACTAGGACTACGG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:4 NH:i:1
+test_mRNA_4_191_5d 83 test_chromosome 167 255 75M = 54 0 AGGACGATCGGACTGAGTAGGGCAGTAGGACACTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:3 NH:i:1
test_mRNA_50_224_2d 163 test_chromosome 100 255 75M = 200 0 CACTACGAGGATGACGTCTAGGACTACGGACGGACTTAGAGCGTCAGACGCAGCGACTGGACTATTTAGGACGAT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:3 NH:i:1
+test_mRNA_50_224_2d 83 test_chromosome 200 255 51M100N24M = 100 0 TACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGCGATACGCCACTATTACTTTATTATCTTACTCG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 XS:A:+ NH:i:1
test_mRNA_51_194_47 163 test_chromosome 101 255 75M = 170 0 ACTACGGGGATGACGACTAGGACTACGGACGGACTTAGAGCGTCAGATGCAGCGACTGGACTATTTAGGACGATC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:0 NH:i:1
+test_mRNA_51_194_47 83 test_chromosome 170 255 75M = 101 0 ACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGCGA IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 NH:i:1
+test_mRNA_51_194_49 147 test_chromosome 170 255 75M = 101 0 ACGTTCGGACTGAGGAGGGCAGTAGGACGCCACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGCGG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:4 NH:i:1
test_mRNA_51_194_49 99 test_chromosome 101 255 75M = 170 0 ACTACGGGGATGACGACTAGGCCTACGGATGGACTTAGAGCGTCAGATGCAGCGACTGGACTATTTAGGACGATC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 NH:i:1
+test_mRNA_51_237_a 147 test_chromosome 213 255 38M100N37M = 101 0 CGCGGCCCTACGGCTGAGCGTCGAGCTTGCGATACGCCACTATTACTTTATTATCTTACTCGGACGTAGACGGAT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 XS:A:+ NH:i:1
test_mRNA_51_237_a 99 test_chromosome 101 255 75M = 213 0 ACTACGGGGATGACGACTAGGACTACGGACGGACTTAGAGCGTCAGATGCAGCGACTGGACTATTTAGGACGATC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:0 NH:i:1
+test_mRNA_51_248_14 145 test_chromosome 224 255 27M100N48M = 101 0 GGCTGAGCGTCGAGCTTGCGATACGCCACTATTACTTTATTATCTTACTCGGACGTAGACGGAACGGCAACGGGA IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:3 XS:A:+ NH:i:1
test_mRNA_51_248_14 97 test_chromosome 101 255 75M = 224 0 ACTACGGGGATGACGACGAGGACTACGGACGGACTTAGAGCGTCAGATGCAGCGACTGAACTTTTTAGGACGATC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:3 NH:i:1
+test_mRNA_52_261_1b 145 test_chromosome 237 255 14M100N50M100N11M = 102 0 GCTTGCGATACGCCACTATTACTTAATTATCTTACTCGGACGTAGAAGGATCGGCAACGGGACTTTTTCTACTTG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 XS:A:+ NH:i:1
test_mRNA_52_261_1b 97 test_chromosome 102 255 75M = 237 0 CTACGGGAATGACGACTAGGGCTACGGAGGGACTTACAGCGTCAGATGCAGCGACTGGACTATTTAGGACGATCG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:4 NH:i:1
+test_mRNA_53_212_19 147 test_chromosome 188 255 63M100N12M = 103 0 GCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGCGATACGCCACTATTTCTTTA IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 XS:A:+ NH:i:1
test_mRNA_53_212_19 99 test_chromosome 103 255 75M = 188 0 TACGGGGATGACGACTAGGACTACGGACGGACTTAGAGCGTCAGATGCAGCGACTGGAATATTTAGGACGATCGG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 NH:i:1
test_mRNA_53_272_5a 161 test_chromosome 103 255 75M = 248 0 TACGGGGATGACGACTAGGACTACGGACGGACTTAGAGCGTCAGATGCAGCGACTGGACTATTTAGGACGATCGG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:0 NH:i:1
+test_mRNA_53_272_5a 81 test_chromosome 248 255 3M100N50M100N22M = 103 0 GCCACTATTACTTTATTATCTTACTCGGACGTAGACGGATCGGCAACGGGACTTTTTCTACTTGACACTGGGATC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 XS:A:+ NH:i:1
+test_mRNA_56_183_56 147 test_chromosome 159 255 75M = 106 0 GACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 NH:i:1
test_mRNA_56_183_56 99 test_chromosome 106 255 75M = 159 0 GGGGATGACGACTAGGACTACGGACGGACTTAGAGCGTCAGATGCAGCGACTGGACTATTTGGGACGATCGGACT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 NH:i:1
+test_mRNA_57_231_8 147 test_chromosome 207 255 44M100N31M = 107 0 TTGGCGCGCGGCCCTAGGGCTGAGCGTCGAGCTTGCGATACGCCACTATTACTTTATTATCTTACTCGGACGTAG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 XS:A:+ NH:i:1
test_mRNA_57_231_8 99 test_chromosome 107 255 75M = 207 0 GGGATGACGACTAGGACTACGGACGGACTTAGAGCGTCAGATGCACCGACTGGACTATTTAGGACGATCGGACTG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 NH:i:1
test_mRNA_58_218_16 163 test_chromosome 108 255 75M = 194 0 GGATGACGACTAGGACTACGGACGGACTTAGAACGTCAGATGCAGCGACTGGACTATTTAGGACGATCGGACTGA IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 NH:i:1
+test_mRNA_58_218_16 83 test_chromosome 194 255 57M100N18M = 108 0 GGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGCGATACGCCACTATTACTTTATTATCT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 XS:A:+ NH:i:1
test_mRNA_58_220_3d 163 test_chromosome 108 255 75M = 196 0 GGATGACGACTAGGACTACGGACGGACTTAGAGCGTCAGATGCAGCGACTGGACTATTTAGGACGATCGGACTGA IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:0 NH:i:1
+test_mRNA_58_220_3d 83 test_chromosome 196 255 55M100N20M = 108 0 ACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGGTTGCGATACGCCACTATTACTTTATTATCTTC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:3 XS:A:+ NH:i:1
test_mRNA_58_234_7 163 test_chromosome 108 255 75M = 210 0 GGATGACGCCTAGGACTACGGACGGACTTAGAGCGTCAGATGCAGCGACTGGACTATTTAGGACGATCGGACTGA IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 NH:i:1
+test_mRNA_58_234_7 83 test_chromosome 210 255 41M100N34M = 108 0 GCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGCGATACGCCACTATTAGTTTATTATCTGACTCGGACGTAGACT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:4 XS:A:+ NH:i:1
+test_mRNA_5_197_46 145 test_chromosome 173 255 75M = 55 0 ATCGGACGGAGGAGGGCAGTAGGACGCTACGTATTTGGCGGGCGGCCCTACGGCTGAGCGTCGAGCTTGCGATAC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:3 NH:i:1
+test_mRNA_5_197_46 97 test_chromosome 55 255 75M = 173 0 CTATCTGACTAGACTCGAGGCGCTTGCGTCTGAGCTAGGACGTGCCACTACGGGGATGACGACTAGGACTACGGA IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 NH:i:1
test_mRNA_63_229_4c 163 test_chromosome 113 255 75M = 205 0 ACGACTAGGACTACGGACGGACTTAGAGCGTCAGATGCAGGGACTGGACTATTTAGGACGATCGGACTGAGGAGG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 NH:i:1
+test_mRNA_63_229_4c 83 test_chromosome 205 255 46M100N29M = 113 0 ATTTGGCGCGCGGCCCTACGGCTGAGTGTCGAGCTTGCGATACGCCACTATTACTTTATTATCTTACTCGGACGT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 XS:A:+ NH:i:1
+test_mRNA_65_238_2e 147 test_chromosome 214 255 37M100N38M = 115 0 GCGGCCCTACGGCTGCGCGTCGAGCTTGCGATACGCCACTATTACTTTATTATCTTACTCGGACGTAGACGGATC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 XS:A:+ NH:i:1
test_mRNA_65_238_2e 99 test_chromosome 115 255 75M = 214 0 GACTAGGACTACGGACGGACTTAGAGCGTCAGAAGCAGCGACTGGACTATTTAGGACGATCGGACTGAGGAGGGC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 NH:i:1
test_mRNA_69_229_23 163 test_chromosome 119 255 75M = 205 0 AGGACTACGGACGGACTTATAGGGTCAGATGCAGCGACTGGACTATTTAGGACGATCGGACTGAGGAGGGCAGTA IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 NH:i:1
-test_mRNA_36_146_27 83 test_chromosome 122 255 75M = 86 0 ACTACGGACGGACTTAGAGCGTCAGATGCAGCGACTGGACTATTTAGGACGATCGGACTGAGGAGTGCAGTAGGT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 NH:i:1
+test_mRNA_69_229_23 83 test_chromosome 205 255 46M100N29M = 119 0 CTTTGGCGCGCGGCCCTACGGCTGAGCGTCTAGCTTGCGATACGCCACTATTACTTTATTATCTTACTCGGACGT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:3 XS:A:+ NH:i:1
+test_mRNA_6_182_59 147 test_chromosome 158 255 75M = 56 0 GGACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 NH:i:1
+test_mRNA_6_182_59 99 test_chromosome 56 255 75M = 158 0 TATCTGACTAGACTGGAGGCGCTTGCGACTGAGCTAGGACGTGCCAGTACGGGGATGACGACTAGGACTACGGAC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 NH:i:1
test_mRNA_72_258_4 163 test_chromosome 122 255 75M = 234 0 ACTACGGACGGACTTAGAGCGTCAGATGCAGCAACTGGACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGA IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 NH:i:1
+test_mRNA_72_258_4 83 test_chromosome 234 255 17M100N50M100N8M = 122 0 CGAGCTTGCGATACGCCACTATTACTTTATTATCTTACTCGGACGTAGACGGATGGGCAACGGGACTTTTTCTAC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 XS:A:+ NH:i:1
+test_mRNA_73_240_34 147 test_chromosome 216 255 35M100N40M = 123 0 GGCCCTACGGCTGAGCGTCGAGCTTGCGATACGCCACTATTACTTTATTATCTTTCTCGGACGTAGACGGATCGG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 XS:A:+ NH:i:1
test_mRNA_73_240_34 99 test_chromosome 123 255 75M = 216 0 CTACGGACGGACTTAGAGCGTCAGATGCAGCGAATGGACTATTTAGGACGCTCGGACTGAGGAGGGCAGTAGGAC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 NH:i:1
+test_mRNA_73_259_5e 147 test_chromosome 235 255 16M100N50M100N9M = 123 0 GAGCTTGCGATACGCCACTATTACTGTATTATCTTACTCGGACGTAGACGGATCGGCAACGGGACTTTTTCTACT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 XS:A:+ NH:i:1
test_mRNA_73_259_5e 99 test_chromosome 123 255 75M = 235 0 CTACGGACGGACTTAGAGCGTCAGATGCTGCGACTGGACTATTTGGGACGATCGGACTGAGGAGGGCAGTAGGAC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 NH:i:1
test_mRNA_75_204_54 73 test_chromosome 125 255 75M * 0 0 ACGGACGGACTTCGAGCCTCAGATGCAGCGACTGGACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 NH:i:1
test_mRNA_75_235_21 73 test_chromosome 125 255 75M * 0 0 ACGGACGGACTTAGAGCGTCAGATGCAGCGACTGGACTATTTAGCACGATCGGACTGAGGAGGGCAGTAGAACGT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:3 NH:i:1
+test_mRNA_75_277_3b 145 test_chromosome 353 255 48M100N27M = 125 0 TATTACTTTATTATCTTACTCGGACGTAGACGGATCGGCAACGGGACTTTTTCTACCTGAGACTGGGATCGAGGC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 XS:A:+ NH:i:1
test_mRNA_75_277_3b 97 test_chromosome 125 255 75M = 353 0 ACGGACGGACTTAAAGCTTCAGATGCAGCGACAGGACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:3 NH:i:1
test_mRNA_77_256_2c 73 test_chromosome 127 255 75M * 0 0 GGACGGACTTAGAGCATCAGATGCAGCGACTGGACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTA IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 NH:i:1
+test_mRNA_78_276_4b 145 test_chromosome 352 255 49M100N26M = 128 0 CTATTACTTTATTATCTTACTCGGACGTAGACGGATCGGCAACGGGACTTTTTCTACTTGAGACTAGGATCGAGG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 XS:A:+ NH:i:1
test_mRNA_78_276_4b 97 test_chromosome 128 255 75M = 352 0 GACGGACTTAGAGCGTCAGATGCAGCGACTGGACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGGCGCTAC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 NH:i:1
test_mRNA_79_256_31 137 test_chromosome 129 255 75M * 0 0 ACGGACTTAGAGCGTCAGATGCAGCGACTGGACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:0 NH:i:1
test_mRNA_81_228_3a 163 test_chromosome 131 255 75M = 204 0 GGACTGAGAGCGTCAGATGCAGCGACTGGACTATTTAGGACGATCGGACTGAGGAGGGTAGTAGGACGCTACGTA IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 NH:i:1
+test_mRNA_81_228_3a 83 test_chromosome 204 255 47M100N28M = 131 0 TATTTGGCGCGCGGCCCTATGGCTGAGCGTCGAGCTTGCGATACGCCACTATTACTTTATTATCTTACTCGTAGG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:4 XS:A:+ NH:i:1
test_mRNA_81_245_4d 163 test_chromosome 131 255 75M = 221 0 GGACTTAGAGCGTCAGATGCAGCGACTGGACTATTTAGGACGATCGGACTGATGAGGGCAGTAGGACGCTACGTA IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 NH:i:1
-test_mRNA_8_155_9 83 test_chromosome 131 255 75M = 58 0 GGACTTCGAGCGTCAGATGCAGCGACTGTACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTA IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 NH:i:1
+test_mRNA_81_245_4d 83 test_chromosome 221 255 30M100N45M = 131 0 TACGGCTGAGCGTCGAGGTTGCGATACGCCACTATTACTTTATAATCTTACTCGGACGTAGACGGATCGGCAACG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 XS:A:+ NH:i:1
test_mRNA_82_255_2 137 test_chromosome 132 255 75M * 0 0 GACTTAGAGCGTCAGATGCAGCGACTGGACTTTTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTAT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 NH:i:1
+test_mRNA_82_271_58 147 test_chromosome 247 255 4M100N50M100N21M = 132 0 CGCCACTATTACTTTATTATCTTACTCGGACGTAGACGCATCGGCAACGGGACTTTTTCTACTTGAGACTGGGAT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 XS:A:+ NH:i:1
test_mRNA_82_271_58 99 test_chromosome 132 255 75M = 247 0 GACTTAGAGCGTCAGTTGCAGCGACTGGACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTAT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 NH:i:1
+test_mRNA_85_268_53 147 test_chromosome 244 255 7M100N50M100N18M = 135 0 ATACGCCACTATTACTTTATTATCTTACTCGGACGTAGACGGATCGTCAACGGGACTTTTTCTACTTGAGACTGG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 XS:A:+ NH:i:1
test_mRNA_85_268_53 99 test_chromosome 135 255 75M = 244 0 TTAGTGCGTCAGATGCAGCGACTGGACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 NH:i:1
+test_mRNA_85_275_38 137 test_chromosome 351 255 50M100N25M * 0 0 ACTCTTACTTTATTATCTTACTCGGACGTAGACGGATCGGCAACGGGACTTTTACTACTTGAGACTGGGATCGAG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 XS:A:+ NH:i:1
test_mRNA_87_250_57 163 test_chromosome 137 255 75M = 226 0 AGAGCGTCAGATGCAGAGACTGGACTATTTAGGACGATCGGACTGAGGAGTGCAGTAGGACGCTACGTATTTGGC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 NH:i:1
+test_mRNA_87_250_57 83 test_chromosome 226 255 25M100N50M = 137 0 ATGAGCGTCGAGCTTGCGATACGCCACTATTACTTTATTATCTTACTCGGACGTAGACGGATCGGCAACGGGACT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 XS:A:+ NH:i:1
test_mRNA_87_279_5f 161 test_chromosome 137 255 75M = 355 0 AGAGCGTCAGATGCAGCGACTGGACTATTTAGGACGATCGGACCGAGGAGGGCAGTAGGACGCTACGTATTTGGC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 NH:i:1
+test_mRNA_87_279_5f 81 test_chromosome 355 255 46M100N29M = 137 0 TTACTTTATTATCTTACTCGGACGTAGACGGATCGGCAACGGGACTTTTTCTACTTGAGACTGGGATCGAGGCGG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:0 XS:A:+ NH:i:1
test_mRNA_88_257_50 137 test_chromosome 138 255 75M * 0 0 GAGCGTCAGATGCAGCGACTGGACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:0 NH:i:1
test_mRNA_89_230_b 163 test_chromosome 139 255 75M = 206 0 AGCGTCAGGTGCAGCGACTGGACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 NH:i:1
+test_mRNA_89_230_b 83 test_chromosome 206 255 45M100N30M = 139 0 TCTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGCGATACGCCACTATTACTTTATTAACTCACTCGGACGTA IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:4 XS:A:+ NH:i:1
+test_mRNA_89_245_15 147 test_chromosome 221 255 30M100N45M = 139 0 TACGGCTGAGCGTCGAGCTTGCGATACGCCACTATTTCTCTATTATCTTACTCGGACGTAGACGGATCGGCAACG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 XS:A:+ NH:i:1
test_mRNA_89_245_15 99 test_chromosome 139 255 75M = 221 0 AGCGTCAGATGCAGCGACTGGACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:0 NH:i:1
test_mRNA_89_267_32 163 test_chromosome 139 255 75M = 243 0 AGCGTCAGATGCAGCGACTGGACTATTTAGGACGATCGGAGTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 NH:i:1
+test_mRNA_89_267_32 83 test_chromosome 243 255 8M100N50M100N17M = 139 0 GATACGGCACTATTACTTTATTATCTTTCTCGGACGTAGACGGATCGGCAACGGGACTTTTTCTACTTGAGACTG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 XS:A:+ NH:i:1
+test_mRNA_8_155_9 163 test_chromosome 58 255 75M = 131 0 TGTGACTAGACTGGAGGCGCTTGCGACTGAGCTAGGACGTGCCACTACGGGGATGACGACTAGGACTACGGACGG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 NH:i:1
+test_mRNA_8_155_9 83 test_chromosome 131 255 75M = 58 0 GGACTTCGAGCGTCAGATGCAGCGACTGTACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTA IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 NH:i:1
+test_mRNA_8_197_1 147 test_chromosome 173 255 75M = 58 0 ATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGCGATAC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 NH:i:1
+test_mRNA_8_197_1 99 test_chromosome 58 255 75M = 173 0 TCTGACTAGACTGGAGGCGCTTGCGACTGAGCTAGGACGTGACACTACGGGGATGGCGACTAGGACTACGGACGG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 NH:i:1
test_mRNA_91_256_41 73 test_chromosome 141 255 75M * 0 0 CGTCAGATGCAGCGACTGGACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:0 NH:i:1
+test_mRNA_92_250_44 147 test_chromosome 226 255 25M100N50M = 142 0 CTGAGCGTCGAGCTTGCGATACGCCACTATTACTTTATTATCTTACTCGGACGTAGACGGATCGGGTACGGGACT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 XS:A:+ NH:i:1
test_mRNA_92_250_44 99 test_chromosome 142 255 75M = 226 0 GTCAGATGCAGCGACTGGACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:0 NH:i:1
+test_mRNA_92_266_43 147 test_chromosome 242 255 9M100N50M100N16M = 142 0 CGATACGCCACTATTACTTTCTTATCTTACTCGGACGTAGACGGAGCGGCAACGGGACTTTTTCTACTTGAGACC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:3 XS:A:+ NH:i:1
test_mRNA_92_266_43 99 test_chromosome 142 255 75M = 242 0 GTCAGATGCAGCGACTGGACTATTTAGGACGATCGGACTCAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 NH:i:1
+test_mRNA_94_291_40 137 test_chromosome 367 255 34M100N41M * 0 0 CTTCCTGGGACGTAGACGGATCGGCAACGCGACATTTTCTACTTGAGACTGGGATCGAGGCGGACTTTTTGGGAC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:5 XS:A:+ NH:i:1
test_mRNA_96_238_3 163 test_chromosome 146 255 75M = 214 0 GATGCAGCGACTGGACTATTTAGGACGATCGGACGGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGACC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:3 NH:i:1
+test_mRNA_96_238_3 83 test_chromosome 214 255 37M100N38M = 146 0 GCGGCCCTACGGCTGAGCGTCGAGCTTGCGATACGCTACTAGTACTTTATTATCTTACGCGGACGTAGACGGATC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:4 XS:A:+ NH:i:1
+test_mRNA_97_275_26 145 test_chromosome 351 255 50M100N25M = 147 0 ACTATTACTTTATTATCTTAGTCGGACGTAGACGGATCGGAAACGGGACTCTTTCTACTTGAGACTGGGATCGAG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:3 XS:A:+ NH:i:1
test_mRNA_97_275_26 97 test_chromosome 147 255 75M = 351 0 ATGCAGCGACTGGACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 NH:i:1
-test_mRNA_22_173_62 147 test_chromosome 149 255 75M = 72 0 GCAGCGACTGGACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTAC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 NH:i:1
-test_mRNA_103_284_2a 161 test_chromosome 153 255 75M = 360 0 CGACTGGACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 NH:i:1
-test_mRNA_104_278_3e 161 test_chromosome 154 255 75M = 354 0 GACTGGACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTTTTTGGCGCGCGGCCCTACGGCTG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 NH:i:1
-test_mRNA_105_266_13 163 test_chromosome 155 255 75M = 242 0 ACTGGACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGA IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 NH:i:1
-test_mRNA_105_276_c 161 test_chromosome 155 255 75M = 352 0 ACTGGACTATTTAGGACGATCGGACTGAGGAAGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGA IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 NH:i:1
+test_mRNA_9_179_52 163 test_chromosome 59 255 75M = 155 0 CTGACTAGACTGGAGGCGCTCGCGACTGAGCTAGGACGTGCCACTACGGGGATGACGACTAGGACTACGGACGGA IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 NH:i:1
test_mRNA_9_179_52 83 test_chromosome 155 255 75M = 59 0 ACTGGACCATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGA IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 NH:i:1
-test_mRNA_106_253_45 137 test_chromosome 156 255 75M * 0 0 CTGGACTATTTAGGTCGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 NH:i:1
-test_mRNA_107_286_5 161 test_chromosome 157 255 75M = 362 0 TGGACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGCATTTGGCGCGCGGCCCTACGGCTGAGC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 NH:i:1
-test_mRNA_6_182_59 147 test_chromosome 158 255 75M = 56 0 GGACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 NH:i:1
-test_mRNA_56_183_56 147 test_chromosome 159 255 75M = 106 0 GACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 NH:i:1
-test_mRNA_110_267_22 163 test_chromosome 160 255 75M = 243 0 ACTAGTTAGGGCGATCGGACTGAGGAGGGCAGTAGGACGCTACGTAGTTGGCGCGCGGCCCTACGACTGAGCGTC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:5 NH:i:1
-test_mRNA_110_271_28 99 test_chromosome 160 255 75M = 247 0 ACTATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 NH:i:1
-test_mRNA_111_297_61 161 test_chromosome 161 255 75M = 373 0 CTATTTAGGACGATCGGACTGGGGAGGGCAGTAGGACGCTACGGATTTGGCGCGCGGCCCTACGGCTGAGCGTCG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:3 NH:i:1
-test_mRNA_23_186_42 83 test_chromosome 162 255 75M = 73 0 TATTTAGGACGATCGGACGGAGGAGGGCAGAAGGACGCTACGTATTTGGCGCGCGGCCCTACGACTGAGCGTCGA IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:4 NH:i:1
-test_mRNA_3_187_51 147 test_chromosome 163 255 75M = 53 0 ATTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 NH:i:1
-test_mRNA_114_277_5b 161 test_chromosome 164 255 75M = 353 0 TTTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGCCTGAGCGTCGAGC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 NH:i:1
-test_mRNA_28_188_11 147 test_chromosome 164 255 75M = 78 0 TTTAGGACGATCGGACTGAGGAAGGCAGTAGGACGCTTCGTATTTGGCGCGAGGCCCTACGGCTGAGCGTCGAGC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:4 NH:i:1
-test_mRNA_26_189_30 83 test_chromosome 165 255 75M = 76 0 TTAGGACGATCGGACTGAGGAGGGCAGTAGGACGGTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 NH:i:1
-test_mRNA_33_189_4a 73 test_chromosome 165 255 75M * 0 0 TTAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACCTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGGGCT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:3 NH:i:1
-test_mRNA_116_271_2b 163 test_chromosome 166 255 75M = 247 0 TAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 NH:i:1
-test_mRNA_116_295_63 161 test_chromosome 166 255 75M = 371 0 TAGGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 NH:i:1
-test_mRNA_11_190_1a 147 test_chromosome 166 255 75M = 61 0 TAGGTCGATGGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGTGGCCCTACGGCTGAGCGTCGAGCTT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:4 NH:i:1
-test_mRNA_4_191_5d 83 test_chromosome 167 255 75M = 54 0 AGGACGATCGGACTGAGTAGGGCAGTAGGACACTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:3 NH:i:1
-test_mRNA_118_297_f 161 test_chromosome 168 255 75M = 373 0 GGACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 NH:i:1
-test_mRNA_44_193_3f 147 test_chromosome 169 255 75M = 94 0 GACGATCGGACTGGGGAGAGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGCG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:3 NH:i:1
-test_mRNA_16_194_10 83 test_chromosome 170 255 75M = 66 0 ACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGCGA IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 NH:i:1
-test_mRNA_51_194_47 83 test_chromosome 170 255 75M = 101 0 ACGATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGCGA IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 NH:i:1
-test_mRNA_51_194_49 147 test_chromosome 170 255 75M = 101 0 ACGTTCGGACTGAGGAGGGCAGTAGGACGCCACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGCGG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:4 NH:i:1
-test_mRNA_122_299_6 161 test_chromosome 172 255 75M = 375 0 GATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGCGATA IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 NH:i:1
-test_mRNA_44_197_35 147 test_chromosome 173 255 75M = 94 0 ATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGATCGTCGAGCTTGCGATAC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 NH:i:1
-test_mRNA_5_197_46 145 test_chromosome 173 255 75M = 55 0 ATCGGACGGAGGAGGGCAGTAGGACGCTACGTATTTGGCGGGCGGCCCTACGGCTGAGCGTCGAGCTTGCGATAC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:3 NH:i:1
-test_mRNA_8_197_1 147 test_chromosome 173 255 75M = 58 0 ATCGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGCGATAC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 NH:i:1
-test_mRNA_125_280_48 97 test_chromosome 175 255 75M = 356 0 CGGACTGAGGAGGGCAGTAGGACGCTATGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGCGAAACGC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:3 NH:i:1
-test_mRNA_125_293_60 161 test_chromosome 175 255 75M = 369 0 CGGACTGAGGAGGGCAGTAGGACGCTATGTATTTGGCGCGCGGCCCTACGGCTGAGCTTCGAGGTTGCGATACGC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:4 NH:i:1
-test_mRNA_38_199_29 147 test_chromosome 175 255 75M = 88 0 CGGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGCGATACGC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 NH:i:1
-test_mRNA_126_282_18 161 test_chromosome 176 255 75M = 358 0 GGACTGAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGCGATACGCC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 NH:i:1
-test_mRNA_131_260_33 99 test_chromosome 181 255 70M100N5M = 236 0 GAGGAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGCGATACGCCACTAT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 XS:A:+ NH:i:1
-test_mRNA_21_208_24 83 test_chromosome 184 255 67M100N8M = 71 0 GAGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGCCTGAGCGTCGAGCTTGCGATACGCCACTATTAC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 XS:A:+ NH:i:1
-test_mRNA_42_209_25 147 test_chromosome 185 255 66M100N9M = 92 0 AGGGCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGCGATACGCCACTATTACT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 XS:A:+ NH:i:1
-test_mRNA_53_212_19 147 test_chromosome 188 255 63M100N12M = 103 0 GCAGTAGGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGCGATACGCCACTATTTCTTTA IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 XS:A:+ NH:i:1
-test_mRNA_36_218_12 147 test_chromosome 194 255 57M100N18M = 86 0 GGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGCGATACGCCACTATTACTTTATTATCT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 XS:A:+ NH:i:1
-test_mRNA_58_218_16 83 test_chromosome 194 255 57M100N18M = 108 0 GGACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGCGATACGCCACTATTACTTTATTATCT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 XS:A:+ NH:i:1
-test_mRNA_145_300_37 163 test_chromosome 195 255 56M100N19M = 376 0 GACGCTACGTATTTGGCGCGGGGCCCTATGGCTGAGCGTCGAGCTTGCGATACGCCACTATTACTTTAGTATATT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:5 XS:A:+ NH:i:1
-test_mRNA_39_219_5c 147 test_chromosome 195 255 56M100N19M = 89 0 GACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCCAGCTTGCGATACGCCACTATTACTTTATTATCTT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 XS:A:+ NH:i:1
-test_mRNA_58_220_3d 83 test_chromosome 196 255 55M100N20M = 108 0 ACGCTACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGGTTGCGATACGCCACTATTACTTTATTATCTTC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:3 XS:A:+ NH:i:1
-test_mRNA_50_224_2d 83 test_chromosome 200 255 51M100N24M = 100 0 TACGTATTTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGCGATACGCCACTATTACTTTATTATCTTACTCG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 XS:A:+ NH:i:1
-test_mRNA_44_225_1e 83 test_chromosome 201 255 50M100N25M = 94 0 ACGTATATGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGCGATACGCCACTATTACTTTATTATCTTACTCGG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 XS:A:+ NH:i:1
-test_mRNA_81_228_3a 83 test_chromosome 204 255 47M100N28M = 131 0 TATTTGGCGCGCGGCCCTATGGCTGAGCGTCGAGCTTGCGATACGCCACTATTACTTTATTATCTTACTCGTAGG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:4 XS:A:+ NH:i:1
-test_mRNA_63_229_4c 83 test_chromosome 205 255 46M100N29M = 113 0 ATTTGGCGCGCGGCCCTACGGCTGAGTGTCGAGCTTGCGATACGCCACTATTACTTTATTATCTTACTCGGACGT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 XS:A:+ NH:i:1
-test_mRNA_69_229_23 83 test_chromosome 205 255 46M100N29M = 119 0 CTTTGGCGCGCGGCCCTACGGCTGAGCGTCTAGCTTGCGATACGCCACTATTACTTTATTATCTTACTCGGACGT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:3 XS:A:+ NH:i:1
-test_mRNA_89_230_b 83 test_chromosome 206 255 45M100N30M = 139 0 TCTGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGCGATACGCCACTATTACTTTATTAACTCACTCGGACGTA IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:4 XS:A:+ NH:i:1
-test_mRNA_30_231_3c 81 test_chromosome 207 255 44M100N31M = 80 0 TTGGCGCGCGGCCCTACGGCTAAGCGTCGAGCTTGCGATACGCCACTATTACTTTAATATCTTACTCGCACGTAG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:4 XS:A:+ NH:i:1
-test_mRNA_57_231_8 147 test_chromosome 207 255 44M100N31M = 107 0 TTGGCGCGCGGCCCTAGGGCTGAGCGTCGAGCTTGCGATACGCCACTATTACTTTATTATCTTACTCGGACGTAG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 XS:A:+ NH:i:1
-test_mRNA_46_232_2f 147 test_chromosome 208 255 43M100N32M = 96 0 TGGCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGCGATACGCCACTATTACTTTATTATCTTACTCGGACGTAGA IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 XS:A:+ NH:i:1
-test_mRNA_58_234_7 83 test_chromosome 210 255 41M100N34M = 108 0 GCGCGCGGCCCTACGGCTGAGCGTCGAGCTTGCGATACGCCACTATTAGTTTATTATCTGACTCGGACGTAGACT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:4 XS:A:+ NH:i:1
-test_mRNA_41_236_55 145 test_chromosome 212 255 39M100N36M = 91 0 GCGCGGCCCTACGGCTGAGCGTCGAGCTTGCGATACGCCACTATTACTTTATTATCTTACTCGGACGTAGACGGA IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 XS:A:+ NH:i:1
-test_mRNA_51_237_a 147 test_chromosome 213 255 38M100N37M = 101 0 CGCGGCCCTACGGCTGAGCGTCGAGCTTGCGATACGCCACTATTACTTTATTATCTTACTCGGACGTAGACGGAT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 XS:A:+ NH:i:1
-test_mRNA_65_238_2e 147 test_chromosome 214 255 37M100N38M = 115 0 GCGGCCCTACGGCTGCGCGTCGAGCTTGCGATACGCCACTATTACTTTATTATCTTACTCGGACGTAGACGGATC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 XS:A:+ NH:i:1
-test_mRNA_96_238_3 83 test_chromosome 214 255 37M100N38M = 146 0 GCGGCCCTACGGCTGAGCGTCGAGCTTGCGATACGCTACTAGTACTTTATTATCTTACGCGGACGTAGACGGATC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:4 XS:A:+ NH:i:1
-test_mRNA_73_240_34 147 test_chromosome 216 255 35M100N40M = 123 0 GGCCCTACGGCTGAGCGTCGAGCTTGCGATACGCCACTATTACTTTATTATCTTTCTCGGACGTAGACGGATCGG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 XS:A:+ NH:i:1
-test_mRNA_81_245_4d 83 test_chromosome 221 255 30M100N45M = 131 0 TACGGCTGAGCGTCGAGGTTGCGATACGCCACTATTACTTTATAATCTTACTCGGACGTAGACGGATCGGCAACG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 XS:A:+ NH:i:1
-test_mRNA_89_245_15 147 test_chromosome 221 255 30M100N45M = 139 0 TACGGCTGAGCGTCGAGCTTGCGATACGCCACTATTTCTCTATTATCTTACTCGGACGTAGACGGATCGGCAACG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 XS:A:+ NH:i:1
-test_mRNA_172_294_4f 99 test_chromosome 222 255 29M100N46M = 370 0 ACGGATGAGCGTCGAGCTTGCGATACGCCACTATTACTTTATTATCTTCCTCGGACGTAGACGGATCGCCAACGG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:3 XS:A:+ NH:i:1
-test_mRNA_51_248_14 145 test_chromosome 224 255 27M100N48M = 101 0 GGCTGAGCGTCGAGCTTGCGATACGCCACTATTACTTTATTATCTTACTCGGACGTAGACGGAACGGCAACGGGA IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:3 XS:A:+ NH:i:1
-test_mRNA_48_249_20 81 test_chromosome 225 255 26M100N49M = 98 0 GCTGAGCGTCGAGCTTGCGATACGCCACTATTACTTTACTATCTTACTCGGACGGAGACGGATCGGCAACGGGAC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:3 XS:A:+ NH:i:1
-test_mRNA_87_250_57 83 test_chromosome 226 255 25M100N50M = 137 0 ATGAGCGTCGAGCTTGCGATACGCCACTATTACTTTATTATCTTACTCGGACGTAGACGGATCGGCAACGGGACT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 XS:A:+ NH:i:1
-test_mRNA_92_250_44 147 test_chromosome 226 255 25M100N50M = 142 0 CTGAGCGTCGAGCTTGCGATACGCCACTATTACTTTATTATCTTACTCGGACGTAGACGGATCGGGTACGGGACT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 XS:A:+ NH:i:1
-test_mRNA_128_252_36 137 test_chromosome 228 255 23M100N52M * 0 0 GAGCGTCGAGCTTGCGATACGCCACTATTACTTTATTATCTTACTCGGACGTAGACGGATCGGGAACGGGACTTT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:4 XS:A:+ NH:i:1
-test_mRNA_72_258_4 83 test_chromosome 234 255 17M100N50M100N8M = 122 0 CGAGCTTGCGATACGCCACTATTACTTTATTATCTTACTCGGACGTAGACGGATGGGCAACGGGACTTTTTCTAC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 XS:A:+ NH:i:1
-test_mRNA_73_259_5e 147 test_chromosome 235 255 16M100N50M100N9M = 123 0 GAGCTTGCGATACGCCACTATTACTGTATTATCTTACTCGGACGTAGACGGATCGGCAACGGGACTTTTTCTACT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 XS:A:+ NH:i:1
-test_mRNA_131_260_33 147 test_chromosome 236 255 15M100N50M100N10M = 181 0 AGCTTGTGATACGCCACTATTACTTTATTATCTTACTCGGACGTAAACGGATCGGCCACGGGACTTTTTTTACTT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:4 XS:A:+ NH:i:1
-test_mRNA_52_261_1b 145 test_chromosome 237 255 14M100N50M100N11M = 102 0 GCTTGCGATACGCCACTATTACTTAATTATCTTACTCGGACGTAGAAGGATCGGCAACGGGACTTTTTCTACTTG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 XS:A:+ NH:i:1
-test_mRNA_105_266_13 83 test_chromosome 242 255 9M100N50M100N16M = 155 0 CGATCCGCCACTATTACTTTATTATCTTACTCGGACGTAGACGGATCGGCAACGGGACTTTTTCTACTTGAGACT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 XS:A:+ NH:i:1
-test_mRNA_92_266_43 147 test_chromosome 242 255 9M100N50M100N16M = 142 0 CGATACGCCACTATTACTTTCTTATCTTACTCGGACGTAGACGGAGCGGCAACGGGACTTTTTCTACTTGAGACC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:3 XS:A:+ NH:i:1
-test_mRNA_110_267_22 83 test_chromosome 243 255 8M100N50M100N17M = 160 0 GATACGCCACTATTACTTTATTATCTTACTCGGACGTAGACGGATCGGCAACGGGACTTTTTCTACTTGAGACTG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:0 XS:A:+ NH:i:1
-test_mRNA_89_267_32 83 test_chromosome 243 255 8M100N50M100N17M = 139 0 GATACGGCACTATTACTTTATTATCTTTCTCGGACGTAGACGGATCGGCAACGGGACTTTTTCTACTTGAGACTG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 XS:A:+ NH:i:1
-test_mRNA_111_268_d 73 test_chromosome 244 255 7M100N50M100N18M * 0 0 ATACGCCACTATTATTTTATTATCTTACTCGGACGTAGACGGATCGGCAACGGGACTTTTTCTACTTGAGACTGG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 XS:A:+ NH:i:1
-test_mRNA_85_268_53 147 test_chromosome 244 255 7M100N50M100N18M = 135 0 ATACGCCACTATTACTTTATTATCTTACTCGGACGTAGACGGATCGTCAACGGGACTTTTTCTACTTGAGACTGG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 XS:A:+ NH:i:1
-test_mRNA_110_271_28 147 test_chromosome 247 255 4M100N50M100N21M = 160 0 CGCCACTATTACTTTATTATCTTACTCGGACGAAGACGGATCGGCAACGGGGCTTTTTCTACTTGAGACTGGGAT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 XS:A:+ NH:i:1
-test_mRNA_116_271_2b 83 test_chromosome 247 255 4M100N50M100N21M = 166 0 CGCCACTATTACTTTATTATCTTACTCGGACGTAGACAGATCGGCAACGGGACTTTTTCTACTTGAGACTGGGAT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 XS:A:+ NH:i:1
-test_mRNA_82_271_58 147 test_chromosome 247 255 4M100N50M100N21M = 132 0 CGCCACTATTACTTTATTATCTTACTCGGACGTAGACGCATCGGCAACGGGACTTTTTCTACTTGAGACTGGGAT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 XS:A:+ NH:i:1
-test_mRNA_53_272_5a 81 test_chromosome 248 255 3M100N50M100N22M = 103 0 GCCACTATTACTTTATTATCTTACTCGGACGTAGACGGATCGGCAACGGGACTTTTTCTACTTGACACTGGGATC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 XS:A:+ NH:i:1
-test_mRNA_104_274_1c 73 test_chromosome 350 255 51M100N24M * 0 0 CACTATTACTTTATTATCTTACTCGGACGTAGACGGATCGGCAACGGGACTTTTTCTACTTGAGACTGGGATCGA IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 XS:A:+ NH:i:1
-test_mRNA_85_275_38 137 test_chromosome 351 255 50M100N25M * 0 0 ACTCTTACTTTATTATCTTACTCGGACGTAGACGGATCGGCAACGGGACTTTTACTACTTGAGACTGGGATCGAG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 XS:A:+ NH:i:1
-test_mRNA_97_275_26 145 test_chromosome 351 255 50M100N25M = 147 0 ACTATTACTTTATTATCTTAGTCGGACGTAGACGGATCGGAAACGGGACTCTTTCTACTTGAGACTGGGATCGAG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:3 XS:A:+ NH:i:1
-test_mRNA_105_276_c 81 test_chromosome 352 255 49M100N26M = 155 0 CTATTACTTTATTATCTTACTCGGACGTAGACGGATCGGCAACGGGGCTTTTTCTACTTGAGACTGGGATCGAGG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 XS:A:+ NH:i:1
-test_mRNA_78_276_4b 145 test_chromosome 352 255 49M100N26M = 128 0 CTATTACTTTATTATCTTACTCGGACGTAGACGGATCGGCAACGGGACTTTTTCTACTTGAGACTAGGATCGAGG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 XS:A:+ NH:i:1
-test_mRNA_114_277_5b 81 test_chromosome 353 255 48M100N27M = 164 0 TATTACTTTATTATCTTACTCGGAGGTAGACGGAACGGCAACGGGACTTTTTCTGCTTGAGACTGGGATCGAGGC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:4 XS:A:+ NH:i:1
-test_mRNA_75_277_3b 145 test_chromosome 353 255 48M100N27M = 125 0 TATTACTTTATTATCTTACTCGGACGTAGACGGATCGGCAACGGGACTTTTTCTACCTGAGACTGGGATCGAGGC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 XS:A:+ NH:i:1
-test_mRNA_104_278_3e 81 test_chromosome 354 255 47M100N28M = 154 0 ATTACTTTATTATCTTACTCGGACGTAGACGGATCGGCAACGGGACTTTTTCTACTTGAGACTGGAATCGAGGCG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 XS:A:+ NH:i:1
-test_mRNA_87_279_5f 81 test_chromosome 355 255 46M100N29M = 137 0 TTACTTTATTATCTTACTCGGACGTAGACGGATCGGCAACGGGACTTTTTCTACTTGAGACTGGGATCGAGGCGG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:0 XS:A:+ NH:i:1
-test_mRNA_125_280_48 145 test_chromosome 356 255 45M100N30M = 175 0 TACTTTATTATCTTACTCTGACGTAGACGGATCGGCAACGGGACTTTTTCTACTTGAGACTGGGAGCGAGGCGGA IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 XS:A:+ NH:i:1
-test_mRNA_126_282_18 81 test_chromosome 358 255 43M100N32M = 176 0 CTTTATTATCTTACTCGGACGTAGACGGATCGGCAACGGGACTTTTTCTACTTGAGACTGGGATCGAGGCGGACT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:0 XS:A:+ NH:i:1
-test_mRNA_103_284_2a 81 test_chromosome 360 255 41M100N34M = 153 0 TTATTATCTTACTCGGACGTAGACGGATCGGCAACGGGACTTTTTCTACTTGAGACTGGGATCGAGGCGGACTTT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:0 XS:A:+ NH:i:1
-test_mRNA_107_286_5 81 test_chromosome 362 255 39M100N36M = 157 0 ATTATCTTACTCGGACGTAGACGGATCGGCAACGGGACTTTTTCTACTTGAGACTGGGATCGAGGCGGACTTTTT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:0 XS:A:+ NH:i:1
-test_mRNA_151_286_e 137 test_chromosome 362 255 39M100N36M * 0 0 ATTATCTTACTCGGACGTAGACGGATCGGCAACGGGACTTTATCTACTTGAGACTGGGATCGAGGCGGACTTTTT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 XS:A:+ NH:i:1
-test_mRNA_150_290_0 73 test_chromosome 366 255 35M100N40M * 0 0 TCTTACTCGGACGTAGACGGATCGCCAACGGGACTTTTTCTACTTGAGACTGAGACCGAGGCGGACTTTTTAGGA IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:3 XS:A:+ NH:i:1
-test_mRNA_94_291_40 137 test_chromosome 367 255 34M100N41M * 0 0 CTTCCTGGGACGTAGACGGATCGGCAACGCGACATTTTCTACTTGAGACTGGGATCGAGGCGGACTTTTTGGGAC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:5 XS:A:+ NH:i:1
-test_mRNA_125_293_60 81 test_chromosome 369 255 32M100N43M = 175 0 TACTCGGACGTAGACGGATCGGCAACGGGACTTTTTCTACTTGAGACTGGGATCGAGGCGGACTTTTTAGGACGG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:0 XS:A:+ NH:i:1
-test_mRNA_172_294_4f 147 test_chromosome 370 255 31M100N44M = 222 0 ACTCGGACGTAGACGGGTCGGCAGCGGGACTTTTTCTACTTGAGACTGGGATCGAGGCGGACGTTTTAGGACGGG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:3 XS:A:+ NH:i:1
-test_mRNA_116_295_63 81 test_chromosome 371 255 30M100N45M = 166 0 CTCGGACGTAGACGGATCGGCAACGGGACTTTTTCTACTTGAGACTGGGATCGAGGCGGACTTTTTAGGACGGGA IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:0 XS:A:+ NH:i:1
-test_mRNA_111_297_61 81 test_chromosome 373 255 28M100N47M = 161 0 CGGACGTAGACGGATCCGCAACGGGACTTTTTCTACTTGAGACTGGGATCGAGGCGGACTTTTTAGGACGGGACT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 XS:A:+ NH:i:1
-test_mRNA_118_297_f 81 test_chromosome 373 255 28M100N47M = 168 0 CGGACGTAGACGGATCGGCAACGGGACTTTTTCTACTTGAGACTGGGATCGAGGCGGACTTTTTAGGACGGGACT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:0 XS:A:+ NH:i:1
-test_mRNA_151_297_1d 137 test_chromosome 373 255 28M100N47M * 0 0 CGGACGTAGACGGATCGGCAACGGGACTTTTTCTACTTGAGACTGGGATCGAGGCGGACATTTTAGGACGGGACT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 XS:A:+ NH:i:1
-test_mRNA_122_299_6 81 test_chromosome 375 255 26M100N49M = 172 0 GACGTAGACGGAGCGGCAACGGGACTTTTTCTACTTGAGACTGGGATCGAGGCGGACTTTTTAGGACGGGACTTG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:2 XS:A:+ NH:i:1
-test_mRNA_145_300_37 83 test_chromosome 376 255 25M100N50M = 195 0 ACGTAGACGGATCGGAAACGGGACTTTTTCTACTTGAGACTGGGATCGAGGCGGACTTTTTAGGACGGGACTTGC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 XS:A:+ NH:i:1
--- a/test-data/bwa_wrapper_in3.fastq
+++ b/test-data/bwa_wrapper_in3.fastq
@@ -1,4 +1,120 @@
-@081017-and-081020:1:1:1715:1759/1
-GGACTCAGATAGTAATCC
-+/1
-II#IIIIIII$5+.(9II
+@seq1/2
+ACGCTCCTTTAAAATATC
++/2
+IIIII$%*$G$A31I&&B
+@seq2/2
+CAGCTCGAGAAGCTCTTA
++/2
+IIIIIIIIIIIIIIIIII
+@seq3/2
+CTACTGACCGCTCTCGTG
++/2
+IIIIIIIIIIIIIIIIII
+@seq4/2
+TAGGTGGTCAACCATTTT
++/2
+IIIIIIIIIIIIIIIIII
+@seq5/2
+TTTCTATGTGGCTTAATA
++/2
+IIIIIIIIIIIIIIIIII
+@seq6/2
+GTAGGTGGTCAACAATTT
++/2
+IIIIIIIIIIIIIIIIII
+@seq7/2
+TTTAATTGCAGGGGCTTC
++/2
+IIIIIIIIIIIIIIIIII
+@seq8/2
+ATGCGCTCTATTCTCTGG
++/2
+IIIIIIIIIIIIIIIIII
+@seq9/2
+TTCTGTTGGTGCTGATAT
++/2
+IIIIIIIIIIIIIIIIII
+@seq10/2
+AGGGCGTTGAGTTCGATA
++/2
+IIIIIIIIIIIIIIIIII
+@seq11/2
+ATCCCCAATGCTTGGCTT
++/2
+IIIII$%*$G$A31I&&B
+@seq12/2
+GGATTGGCGTTTCCAACC
++/2
+IIIIIIIIIIIIIIIIII
+@seq13/2
+CCCCAATCCTTGCCTTCC
++/2
+IIIAAIIIIIIIIIIIII
+@seq14/2
+TGATATTTTGACTTTGAG
++/2
+IIIIIIIIIIIIIIIIII
+@seq15/2
+TTACGAAACGCGACGCCG
++/2
+IIIIIIIIIIIIIIIIII
+@seq16/2
+TTATTTTTCTCCAGCCAC
++/2
+IIIIIIIIIIIIIIIIII
+@seq17/2
+AAACAATACTTTAGGCAT
++/2
+IIIIIIIIIIIIIIIIII
+@seq18/2
+CCGTTCCATAAGCAGATG
++/2
+IIIIIIIIIIIIIIIIII
+@seq19/2
+GAGCGTCCTGGTGCTGAT
++
+IIIIIIIIIIIIIIIIII
+@seq20/2
+ACTCCGGTTATCGCTGGC
++/2
+IIIIIIIIIIIIIIIIII
+@seq21/2
+TAAGCATTTGGTTCAGGG
++/2
+IIIII$%*$G$A31I&&B
+@seq22/2
+GTTACGACGCGACGCCGT
++/2
+IIIIIIIIIIIIIIIIII
+@seq23/2
+TTTAATAACCCTATAGAC
++/2
+IIIIIIIIIIIIIIIIII
+@seq24/2
+CTTGGCTTCCCTAAGCAG
++/2
+IIIIIIIIIIIIIIIIII
+@seq25/2
+CGTGCTCGTTGCTGCGTT
++/2
+IIIIIIIIIIIIIIIIII
+@seq26/2
+AAGGATGTTTTCCGTTCT
++/2
+IIIIIIIIIIIIIIIIII
+@seq27/2
+TGTTTGGTGCTGATATTG
++/2
+IIIIIIIIIIIIIIIIII
+@seq28/2
+TCCAGCCACTAAAGTGAG
++/2
+IIIIIIIIIIIIIIIIII
+@seq29/2
+GATAATGATTGGGGTATC
++/2
+IIIIIIIIIIIIIIIIII
+@seq30/2
+ACCATAAGCAGATGGATA
++/2
+IIIIIIIIIIIIIIIIII
--- /dev/null
+++ b/test-data/column_join_in15.tabular
@@ -0,0 +1,11 @@
+alpha beta gamma
+2 BBB II3 bbb i3
+3 CCC III3 ccc ii3
+4 DDD IV2 ddd iii3
+5 EEE V3 eee
+6 FFF VI3 fff iv3
+7 GGG VII3 ggg v3
+8 HHH VIII3 hhh
+9 III IX3 iii vi3
+10 JJJ X3 jjj vii3
+11 LLL XI3 lll
--- a/tools/ngs_rna/tophat_wrapper.xml
+++ b/tools/ngs_rna/tophat_wrapper.xml
@@ -263,7 +263,7 @@
<param name="input2" ftype="fastqsanger" value="tophat_in2.fq"/><param name="mate_inner_distance" value="20"/><param name="pSettingsType" value="preSet"/>
- <output name="accepted_hits" file="tophat_out1.sam"/>
+ <output name="accepted_hits" file="tophat_out1.sam" sort="True"/><output name="coverage" file="tophat_out2.wig"/><output name="junctions" file="tophat_out3.bed"/></test>
--- a/tools/sr_mapping/bwa_wrapper.xml
+++ b/tools/sr_mapping/bwa_wrapper.xml
@@ -108,9 +108,8 @@
BWA commands:
bwa aln -t 4 phiX test-data/bwa_wrapper_in1.fastq > bwa_wrapper_out1.sai
bwa samse phiX bwa_wrapper_out1.sai test-data/bwa_wrapper_in1.fastq >> bwa_wrapper_out1.sam
- phiX.fasta is the prefix for the reference
+ phiX.fa is the prefix for the reference files (phiX.fa.amb, phiX.fa.ann, phiX.fa.bwt, ...)
remove the comment lines (beginning with '@') from the resulting sam file
- note that 'phiX' should be 'PHIX174' to match what's in the indexed file
--><param name="refGenomeSource" value="indexed" /><param name="indices" value="phiX" />
@@ -118,7 +117,7 @@
<param name="input1" value="bwa_wrapper_in1.fastq" ftype="fastqsanger" /><param name="source_select" value="pre_set" /><param name="suppressHeader" value="true" />
- <output name="output" file="bwa_wrapper_out1.sam" ftype="sam" sort="true" />
+ <output name="output" file="bwa_wrapper_out1.sam" ftype="sam" sort="True" /></test><test><!--
@@ -126,8 +125,8 @@
cp test-data/phiX.fasta phiX.fasta
bwa index -a is phiX.fasta
bwa aln -n 0.04 -o 1 -e -1 -d 16 -i 5 -k 2 -t 4 -M 3 -O 11 -E 4 -R -N phiX.fasta test-data/bwa_wrapper_in1.fastq > bwa_wrapper_out2.sai
- bwa samse phiX.fasta bwa_wrapper_out2.sai test-data/bwa_wrapper_in1.fastq >> bwa_wrapper_out2.sam
- phiX.fasta is the prefix for the reference
+ bwa samse phiX.fasta bwa_wrapper_out2.sai test-data/bwa_wrapper_in1.fastq > bwa_wrapper_out2.sam
+ phiX.fa is the prefix for the reference files (phiX.fa.amb, phiX.fa.ann, phiX.fa.bwt, ...)
remove the comment lines (beginning with '@') from the resulting sam file
--><param name="refGenomeSource" value="history" />
@@ -152,17 +151,16 @@
<param name="maxInsertSize" value="500" /><param name="maxOccurPairing" value="100000" /><param name="suppressHeader" value="true" />
- <output name="output" file="bwa_wrapper_out2.sam" ftype="sam" sort="true" />
+ <output name="output" file="bwa_wrapper_out2.sam" ftype="sam" sort="True" /></test><test><!--
BWA commands:
- bwa aln -n 0.04 -o 1 -e -1 -d 16 -i 5 -k 2 -t 4 -M 3 -O 11 -E 4 -R -N phiX.fasta test-data/bwa_wrapper_in2.fastq > bwa_wrapper_out3a.sai
- bwa aln -n 0.04 -o 1 -e -1 -d 16 -i 5 -k 2 -t 4 -M 3 -O 11 -E 4 -R -N phiX.fasta test-data/bwa_wrapper_in3.fastq > bwa_wrapper_out3b.sai
- bwa sampe -a 500 -o 100000 phiX.fasta bwa_wrapper_out3a.sai bwa_wrapper_out3b.sai test-data/bwa_wrapper_in2.fastq test-data/bwa_wrapper_in3.fastq >> bwa_wrapper_out3.sam
- phiX.fasta is the prefix for the reference
+ bwa aln -n 0.04 -o 1 -e -1 -d 16 -i 5 -k 2 -t 4 -M 3 -O 11 -E 4 -R -N phiX.fa test-data/bwa_wrapper_in2.fastq > bwa_wrapper_out3a.sai
+ bwa aln -n 0.04 -o 1 -e -1 -d 16 -i 5 -k 2 -t 4 -M 3 -O 11 -E 4 -R -N phiX.fa test-data/bwa_wrapper_in3.fastq > bwa_wrapper_out3b.sai
+ bwa sampe -a 500 -o 100000 phiX.fasta bwa_wrapper_out3a.sai bwa_wrapper_out3b.sai test-data/bwa_wrapper_in2.fastq test-data/bwa_wrapper_in3.fastq > bwa_wrapper_out3.sam
+ phiX.fa is the prefix for the reference
remove the comment lines (beginning with '@') from the resulting sam file
- note that 'phiX' should be 'PHIX174' to match what's in the indexed file
--><param name="refGenomeSource" value="indexed" /><param name="indices" value="phiX" />
@@ -187,7 +185,7 @@
<param name="maxInsertSize" value="500" /><param name="maxOccurPairing" value="100000" /><param name="suppressHeader" value="true" />
- <output name="output" file="bwa_wrapper_out3.sam" ftype="sam" sort="true" />
+ <output name="output" file="bwa_wrapper_out3.sam" ftype="sam" sort="True" /></test></tests><help>
--- a/test-data/phiX.fasta
+++ b/test-data/phiX.fasta
@@ -1,79 +1,109 @@
>phiX
-GAGTTTTATCGCTTCCATGACGCAGAAGTTAACACTTTCGGATATTTCTGATGAGTCGAAAAATTATCTT
-GATAAAGCAGGAATTACTACTGCTTGTTTACGAATTAAATCGAAGTGGACTGCTGGCGGAAAATGAGAAA
-ATTCGACCTATCCTTGCGCAGCTCGAGAAGCTCTTACTTTGCGACCTTTCGCCATCAACTAACGATTCTG
-TCAAAAACTGACGCGTTGGATGAGGAGAAGTGGCTTAATATGCTTGGCACGTTCGTCAAGGACTGGTTTA
-GATATGAGTCACATTTTGTTCATGGTAGAGATTCTCTTGTTGACATTTTAAAAGAGCGTGGATTACTATC
-TGAGTCCGATGCTGTTCAACCACTAATAGGTAAGAAATCATGAGTCAAGTTACTGAACAATCCGTACGTT
-TCCAGACCGCTTTGGCCTCTATTAAGCTCATTCAGGCTTCTGCCGTTTTGGATTTAACCGAAGATGATTT
-CGATTTTCTGACGAGTAACAAAGTTTGGATTGCTACTGACCGCTCTCGTGCTCGTCGCTGCGTTGAGGCT
-TGCGTTTATGGTACGCTGGACTTTGTGGGATACCCTCGCTTTCCTGCTCCTGTTGAGTTTATTGCTGCCG
-TCATTGCTTATTATGTTCATCCCGTCAACATTCAAACGGCCTGTCTCATCATGGAAGGCGCTGAATTTAC
-GGAAAACATTATTAATGGCGTCGAGCGTCCGGTTAAAGCCGCTGAATTGTTCGCGTTTACCTTGCGTGTA
-CGCGCAGGAAACACTGACGTTCTTACTGACGCAGAAGAAAACGTGCGTCAAAAATTACGTGCGGAAGGAG
-TGATGTAATGTCTAAAGGTAAAAAACGTTCTGGCGCTCGCCCTGGTCGTCCGCAGCCGTTGCGAGGTACT
-AAAGGCAAGCGTAAAGGCGCTCGTCTTTGGTATGTAGGTGGTCAACAATTTTAATTGCAGGGGCTTCGGC
-CCCTTACTTGAGGATAAATTATGTCTAATATTCAAACTGGCGCCGAGCGTATGCCGCATGACCTTTCCCA
-TCTTGGCTTCCTTGCTGGTCAGATTGGTCGTCTTATTACCATTTCAACTACTCCGGTTATCGCTGGCGAC
-TCCTTCGAGATGGACGCCGTTGGCGCTCTCCGTCTTTCTCCATTGCGTCGTGGCCTTGCTATTGACTCTA
-CTGTAGACATTTTTACTTTTTATGTCCCTCATCGTCACGTTTATGGTGAACAGTGGATTAAGTTCATGAA
-GGATGGTGTTAATGCCACTCCTCTCCCGACTGTTAACACTACTGGTTATATTGACCATGCCGCTTTTCTT
-GGCACGATTAACCCTGATACCAATAAAATCCCTAAGCATTTGTTTCAGGGTTATTTGAATATCTATAACA
-ACTATTTTAAAGCGCCGTGGATGCCTGACCGTACCGAGGCTAACCCTAATGAGCTTAATCAAGATGATGC
-TCGTTATGGTTTCCGTTGCTGCCATCTCAAAAACATTTGGACTGCTCCGCTTCCTCCTGAGACTGAGCTT
-TCTCGCCAAATGACGACTTCTACCACATCTATTGACATTATGGGTCTGCAAGCTGCTTATGCTAATTTGC
-ATACTGACCAAGAACGTGATTACTTCATGCAGCGTTACCATGATGTTATTTCTTCATTTGGAGGTAAAAC
-CTCTTATGACGCTGACAACCGTCCTTTACTTGTCATGCGCTCTAATCTCTGGGCATCTGGCTATGATGTT
-GATGGAACTGACCAAACGTCGTTAGGCCAGTTTTCTGGTCGTGTTCAACAGACCTATAAACATTCTGTGC
-CGCGTTTCTTTGTTCCTGAGCATGGCACTATGTTTACTCTTGCGCTTGTTCGTTTTCCGCCTACTGCGAC
-TAAAGAGATTCAGTACCTTAACGCTAAAGGTGCTTTGACTTATACCGATATTGCTGGCGACCCTGTTTTG
-TATGGCAACTTGCCGCCGCGTGAAATTTCTATGAAGGATGTTTTCCGTTCTGGTGATTCGTCTAAGAAGT
-TTAAGATTGCTGAGGGTCAGTGGTATCGTTATGCGCCTTCGTATGTTTCTCCTGCTTATCACCTTCTTGA
-AGGCTTCCCATTCATTCAGGAACCGCCTTCTGGTGATTTGCAAGAACGCGTACTTATTCGCCACCATGAT
-TATGACCAGTGTTTCCAGTCCGTTCAGTTGTTGCAGTGGAATAGTCAGGTTAAATTTAATGTGACCGTTT
-ATCGCAATCTGCCGACCACTCGCGATTCAATCATGACTTCGTGATAAAAGATTGAGTGTGAGGTTATAAC
-GCCGAAGCGGTAAAAATTTTAATTTTTGCCGCTGAGGGGTTGACCAAGCGAAGCGCGGTAGGTTTTCTGC
-TTAGGAGTTTAATCATGTTTCAGACTTTTATTTCTCGCCATAATTCAAACTTTTTTTCTGATAAGCTGGT
-TCTCACTTCTGTTACTCCAGCTTCTTCGGCACCTGTTTTACAGACACCTAAAGCTACATCGTCAACGTTA
-TATTTTGATAGTTTGACGGTTAATGCTGGTAATGGTGGTTTTCTTCATTGCATTCAGATGGATACATCTG
-TCAACGCCGCTAATCAGGTTGTTTCTGTTGGTGCTGATATTGCTTTTGATGCCGACCCTAAATTTTTTGC
-CTGTTTGGTTCGCTTTGAGTCTTCTTCGGTTCCGACTACCCTCCCGACTGCCTATGATGTTTATCCTTTG
-AATGGTCGCCATGATGGTGGTTATTATACCGTCAAGGACTGTGTGACTATTGACGTCCTTCCCCGTACGC
-CGGGCAATAACGTTTATGTTGGTTTCATGGTTTGGTCTAACTTTACCGCTACTAAATGCCGCGGATTGGT
-TTCGCTGAATCAGGTTATTAAAGAGATTATTTGTCTCCAGCCACTTAAGTGAGGTGATTTATGTTTGGTG
-CTATTGCTGGCGGTATTGCTTCTGCTCTTGCTGGTGGCGCCATGTCTAAATTGTTTGGAGGCGGTCAAAA
-AGCCGCCTCCGGTGGCATTCAAGGTGATGTGCTTGCTACCGATAACAATACTGTAGGCATGGGTGATGCT
-GGTATTAAATCTGCCATTCAAGGCTCTAATGTTCCTAACCCTGATGAGGCCGCCCCTAGTTTTGTTTCTG
-GTGCTATGGCTAAAGCTGGTAAAGGACTTCTTGAAGGTACGTTGCAGGCTGGCACTTCTGCCGTTTCTGA
-TAAGTTGCTTGATTTGGTTGGACTTGGTGGCAAGTCTGCCGCTGATAAAGGAAAGGATACTCGTGATTAT
-CTTGCTGCTGCATTTCCTGAGCTTAATGCTTGGGAGCGTGCTGGTGCTGATGCTTCCTCTGCTGGTATGG
-TTGACGCCGGATTTGAGAATCAAAAAGAGCTTACTAAAATGCAACTGGACAATCAGAAAGAGATTGCCGA
-GATGCAAAATGAGACTCAAAAAGAGATTGCTGGCATTCAGTCGGCGACTTCACGCCAGAATACGAAAGAC
-CAGGTATATGCACAAAATGAGATGCTTGCTTATCAACAGAAGGAGTCTACTGCTCGCGTTGCGTCTATTA
-TGGAAAACACCAATCTTTCCAAGCAACAGCAGGTTTCCGAGATTATGCGCCAAATGCTTACTCAAGCTCA
-AACGGCTGGTCAGTATTTTACCAATGACCAAATCAAAGAAATGACTCGCAAGGTTAGTGCTGAGGTTGAC
-TTAGTTCATCAGCAAACGCAGAATCAGCGGTATGGCTCTTCTCATATTGGCGCTACTGCAAAGGATATTT
-CTAATGTCGTCACTGATGCTGCTTCTGGTGTGGTTGATATTTTTCATGGTATTGATAAAGCTGTTGCCGA
-TACTTGGAACAATTTCTGGAAAGACGGTAAAGCTGATGGTATTGGCTCTAATTTGTCTAGGAAATAACCG
-TCAGGATTGACACCCTCCCAATTGTATGTTTTCATGCCTCCAAATCTTGGAGGCTTTTTTATGGTTCGTT
-CTTATTACCCTTCTGAATGTCACGCTGATTATTTTGACTTTGAGCGTATCGAGGCTCTTAAACCTGCTAT
-TGAGGCTTGTGGCATTTCTACTCTTTCTCAATCCCCAATGCTTGGCTTCCATAAGCAGATGGATAACCGC
-ATCAAGCTCTTGGAAGAGATTCTGTCTTTTCGTATGCAGGGCGTTGAGTTCGATAATGGTGATATGTATG
-TTGACGGCCATAAGGCTGCTTCTGACGTTCGTGATGAGTTTGTATCTGTTACTGAGAAGTTAATGGATGA
-ATTGGCACAATGCTACAATGTGCTCCCCCAACTTGATATTAATAACACTATAGACCACCGCCCCGAAGGG
-GACGAAAAATGGTTTTTAGAGAACGAGAAGACGGTTACGCAGTTTTGCCGCAAGCTGGCTGCTGAACGCC
-CTCTTAAGGATATTCGCGATGAGTATAATTACCCCAAAAAGAAAGGTATTAAGGATGAGTGTTCAAGATT
-GCTGGAGGCCTCCACTATGAAATCGCGTAGAGGCTTTGCTATTCAGCGTTTGATGAATGCAATGCGACAG
-GCTCATGCTGATGGTTGGTTTATCGTTTTTGACACTCTCACGTTGGCTGACGACCGATTAGAGGCGTTTT
-ATGATAATCCCAATGCTTTGCGTGACTATTTTCGTGATATTGGTCGTATGGTTCTTGCTGCCGAGGGTCG
-CAAGGCTAATGATTCACACGCCGACTGCTATCAGTATTTTTGTGTGCCTGAGTATGGTACAGCTAATGGC
-CGTCTTCATTTCCATGCGGTGCACTTTATGCGGACACTTCCTACAGGTAGCGTTGACCCTAATTTTGGTC
-GTCGGGTACGCAATCGCCGCCAGTTAAATAGCTTGCAAAATACGTGGCCTTATGGTTACAGTATGCCCAT
-CGCAGTTCGCTACACGCAGGACGCTTTTTCACGTTCTGGTTGGTTGTGGCCTGTTGATGCTAAAGGTGAG
-CCGCTTAAAGCTACCAGTTATATGGCTGTTGGTTTCTATGTGGCTAAATACGTTAACAAAAAGTCAGATA
-TGGACCTTGCTGCTAAAGGTCTAGGAGCTAAAGAATGGAACAACTCACTAAAAACCAAGCTGTCGCTACT
-TCCCAAGAAGCTGTTCAGAATCAGAATGAGCCGCAACTTCGGGATGAAAATGCTCACAATGACAAATCTG
-TCCACGGAGTGCTTAATCCAACTTACCAAGCTGGGTTACGACGCGACGCCGTTCAACCAGATATTGAAGC
-AGAACGCAAAAAGAGAGATGAGATTGAGGCTGGGAAAAGTTACTGTAGCCGACGTTTTGGCGGCGCAACC
-TGTGACGACAAATCTGCTCAAATTTATGCGCGCTTCGATAAAAATGATTGGCGTATCCAACCTGCA
-
+GAGTTTTATCGCTTCCATGACGCAGAAGTTAACACTTTCGGATATTTCTG
+ATGAGTCGAAAAATTATCTTGATAAAGCAGGAATTACTACTGCTTGTTTA
+CGAATTAAATCGAAGTGGACTGCTGGCGGAAAATGAGAAAATTCGACCTA
+TCCTTGCGCAGCTCGAGAAGCTCTTACTTTGCGACCTTTCGCCATCAACT
+AACGATTCTGTCAAAAACTGACGCGTTGGATGAGGAGAAGTGGCTTAATA
+TGCTTGGCACGTTCGTCAAGGACTGGTTTAGATATGAGTCACATTTTGTT
+CATGGTAGAGATTCTCTTGTTGACATTTTAAAAGAGCGTGGATTACTATC
+TGAGTCCGATGCTGTTCAACCACTAATAGGTAAGAAATCATGAGTCAAGT
+TACTGAACAATCCGTACGTTTCCAGACCGCTTTGGCCTCTATTAAGCTCA
+TTCAGGCTTCTGCCGTTTTGGATTTAACCGAAGATGATTTCGATTTTCTG
+ACGAGTAACAAAGTTTGGATTGCTACTGACCGCTCTCGTGCTCGTCGCTG
+CGTTGAGGCTTGCGTTTATGGTACGCTGGACTTTGTGGGATACCCTCGCT
+TTCCTGCTCCTGTTGAGTTTATTGCTGCCGTCATTGCTTATTATGTTCAT
+CCCGTCAACATTCAAACGGCCTGTCTCATCATGGAAGGCGCTGAATTTAC
+GGAAAACATTATTAATGGCGTCGAGCGTCCGGTTAAAGCCGCTGAATTGT
+TCGCGTTTACCTTGCGTGTACGCGCAGGAAACACTGACGTTCTTACTGAC
+GCAGAAGAAAACGTGCGTCAAAAATTACGTGCaGAAGGAGTGATGTAATG
+TCTAAAGGTAAAAAACGTTCTGGCGCTCGCCCTGGTCGTCCGCAGCCGTT
+GCGAGGTACTAAAGGCAAGCGTAAAGGCGCTCGTCTTTGGTATGTAGGTG
+GTCAACAATTTTAATTGCAGGGGCTTCGGCCCCTTACTTGAGGATAAATT
+ATGTCTAATATTCAAACTGGCGCCGAGCGTATGCCGCATGACCTTTCCCA
+TCTTGGCTTCCTTGCTGGTCAGATTGGTCGTCTTATTACCATTTCAACTA
+CTCCGGTTATCGCTGGCGACTCCTTCGAGATGGACGCCGTTGGCGCTCTC
+CGTCTTTCTCCATTGCGTCGTGGCCTTGCTATTGACTCTACTGTAGACAT
+TTTTACTTTTTATGTCCCTCATCGTCACGTTTATGGTGAACAGTGGATTA
+AGTTCATGAAGGATGGTGTTAATGCCACTCCTCTCCCGACTGTTAACACT
+ACTGGTTATATTGACCATGCCGCTTTTCTTGGCACGATTAACCCTGATAC
+CAATAAAATCCCTAAGCATTTGTTTCAGGGTTATTTGAATATCTATAACA
+ACTATTTTAAAGCGCCGTGGATGCCTGACCGTACCGAGGCTAACCCTAAT
+GAGCTTAATCAAGATGATGCTCGTTATGGTTTCCGTTGCTGCCATCTCAA
+AAACATTTGGACTGCTCCGCTTCCTCCTGAGACTGAGCTTTCTCGCCAAA
+TGACGACTTCTACCACATCTATTGACATTATGGGTCTGCAAGCTGCTTAT
+GCTAATTTGCATACTGACCAAGAACGTGATTACTTCATGCAGCGTTACCg
+TGATGTTATTTCTTCATTTGGAGGTAAAACCTCTTATGACGCTGACAACC
+GTCCTTTACTTGTCATGCGCTCTAATCTCTGGGCATCTGGCTATGATGTT
+GATGGAACTGACCAAACGTCGTTAGGCCAGTTTTCTGGTCGTGTTCAACA
+GACCTATAAACATTCTGTGCCGCGTTTCTTTGTTCCTGAGCATGGCACTA
+TGTTTACTCTTGCGCTTGTTCGTTTTCCGCCTACTGCGACTAAAGAGATT
+CAGTACCTTAACGCTAAAGGTGCTTTGACTTATACCGATATTGCTGGCGA
+CCCTGTTTTGTATGGCAACTTGCCGCCGCGTGAAATTTCTATGAAGGATG
+TTTTCCGTTCTGGTGATTCGTCTAAGAAGTTTAAGATTGCTGAGGGTCAG
+TGGTATCGTTATGCGCCTTCGTATGTTTCTCCTGCTTATCACCTTCTTGA
+AGGCTTCCCATTCATTCAGGAACCGCCTTCTGGTGATTTGCAAGAACGCG
+TACTTATTCGCCACCATGATTATGACCAGTGTTTCCAGTCCGTTCAGTTG
+TTGCAGTGGAATAGTCAGGTTAAATTTAATGTGACCGTTTATCGCAATCT
+GCCGACCACTCGCGATTCAATCATGACTTCGTGATAAAAGATTGAGTGTG
+AGGTTATAACGCCGAAGCGGTAAAAATTTTAATTTTTGCCGCTGAGGGGT
+TGACCAAGCGAAGCGCGGTAGGTTTTCTGCTTAGGAGTTTAATCATGTTT
+CAGACTTTTATTTCTCGCCATAATTCAAACTTTTTTTCTGATAAGCTGGT
+TCTCACTTCTGTTACTCCAGCTTCTTCGGCACCTGTTTTACAGACACCTA
+AAGCTACATCGTCAACGTTATATTTTGATAGTTTGACGGTTAATGCTGGT
+AATGGTGGTTTTCTTCATTGCATTCAGATGGATACATCTGTCAACGCCGC
+TAATCAGGTTGTTTCTGTTGGTGCTGATATTGCTTTTGATGCCGACCCTA
+AATTTTTTGCCTGTTTGGTTCGCTTTGAGTCTTCTTCGGTTCCGACTACC
+CTCCCGACTGCCTATGATGTTTATCCTTTGAATGGTCGCCATGATGGTGG
+TTATTATACCGTCAAGGACTGTGTGACTATTGACGTCCTTCCCCGTACGC
+CGGGCAATAAtGTTTATGTTGGTTTCATGGTTTGGTCTAACTTTACCGCT
+ACTAAATGCCGCGGATTGGTTTCGCTGAATCAGGTTATTAAAGAGATTAT
+TTGTCTCCAGCCACTTAAGTGAGGTGATTTATGTTTGGTGCTATTGCTGG
+CGGTATTGCTTCTGCTCTTGCTGGTGGCGCCATGTCTAAATTGTTTGGAG
+GCGGTCAAAAAGCCGCCTCCGGTGGCATTCAAGGTGATGTGCTTGCTACC
+GATAACAATACTGTAGGCATGGGTGATGCTGGTATTAAATCTGCCATTCA
+AGGCTCTAATGTTCCTAACCCTGATGAGGCCGCCCCTAGTTTTGTTTCTG
+GTGCTATGGCTAAAGCTGGTAAAGGACTTCTTGAAGGTACGTTGCAGGCT
+GGCACTTCTGCCGTTTCTGATAAGTTGCTTGATTTGGTTGGACTTGGTGG
+CAAGTCTGCCGCTGATAAAGGAAAGGATACTCGTGATTATCTTGCTGCTG
+CATTTCCTGAGCTTAATGCTTGGGAGCGTGCTGGTGCTGATGCTTCCTCT
+GCTGGTATGGTTGACGCCGGATTTGAGAATCAAAAAGAGCTTACTAAAAT
+GCAACTGGACAATCAGAAAGAGATTGCCGAGATGCAAAATGAGACTCAAA
+AAGAGATTGCTGGCATTCAGTCGGCGACTTCACGCCAGAATACGAAAGAC
+CAGGTATATGCACAAAATGAGATGCTTGCTTATCAACAGAAGGAGTCTAC
+TGCTCGCGTTGCGTCTATTATGGAAAACACCAATCTTTCCAAGCAACAGC
+AGGTTTCCGAGATTATGCGCCAAATGCTTACTCAAGCTCAAACGGCTGGT
+CAGTATTTTACCAATGACCAAATCAAAGAAATGACTCGCAAGGTTAGTGC
+TGAGGTTGACTTAGTTCATCAGCAAACGCAGAATCAGCGGTATGGCTCTT
+CTCATATTGGCGCTACTGCAAAGGATATTTCTAATGTCGTCACTGATGCT
+GCTTCTGGTGTGGTTGATATTTTTCATGGTATTGATAAAGCTGTTGCCGA
+TACTTGGAACAATTTCTGGAAAGACGGTAAAGCTGATGGTATTGGCTCTA
+ATTTGTCTAGGAAATAACCGTCAGGATTGACACCCTCCCAATTGTATGTT
+TTCATGCCTCCAAATCTTGGAGGCTTTTTTATGGTTCGTTCTTATTACCC
+TTCTGAATGTCACGCTGATTATTTTGACTTTGAGCGTATCGAGGCTCTTA
+AACCTGCTATTGAGGCTTGTGGCATTTCTACTCTTTCTCAATCCCCAATG
+CTTGGCTTCCATAAGCAGATGGATAACCGCATCAAGCTCTTGGAAGAGAT
+TCTGTCTTTTCGTATGCAGGGCGTTGAGTTCGATAATGGTGATATGTATG
+TTGACGGCCATAAGGCTGCTTCTGACGTTCGTGATGAGTTTGTATCTGTT
+ACTGAGAAGTTAATGGATGAATTGGCACAATGCTACAATGTGCTCCCCCA
+ACTTGATATTAATAACACTATAGACCACCGCCCCGAAGGGGACGAAAAAT
+GGTTTTTAGAGAACGAGAAGACGGTTACGCAGTTTTGCCGCAAGCTGGCT
+GCTGAACGCCCTCTTAAGGATATTCGCGATGAGTATAATTACCCCAAAAA
+GAAAGGTATTAAGGATGAGTGTTCAAGATTGCTGGAGGCCTCCACTATGA
+AATCGCGTAGAGGCTTTaCTATTCAGCGTTTGATGAATGCAATGCGACAG
+GCTCATGCTGATGGTTGGTTTATCGTTTTTGACACTCTCACGTTGGCTGA
+CGACCGATTAGAGGCGTTTTATGATAATCCCAATGCTTTGCGTGACTATT
+TTCGTGATATTGGTCGTATGGTTCTTGCTGCCGAGGGTCGCAAGGCTAAT
+GATTCACACGCCGACTGCTATCAGTATTTTTGTGTGCCTGAGTATGGTAC
+AGCTAATGGCCGTCTTCATTTCCATGCGGTGCAtTTTATGCGGACACTTC
+CTACAGGTAGCGTTGACCCTAATTTTGGTCGTCGGGTACGCAATCGCCGC
+CAGTTAAATAGCTTGCAAAATACGTGGCCTTATGGTTACAGTATGCCCAT
+CGCAGTTCGCTACACGCAGGACGCTTTTTCACGTTCTGGTTGGTTGTGGC
+CTGTTGATGCTAAAGGTGAGCCGCTTAAAGCTACCAGTTATATGGCTGTT
+GGTTTCTATGTGGCTAAATACGTTAACAAAAAGTCAGATATGGACCTTGC
+TGCTAAAGGTCTAGGAGCTAAAGAATGGAACAACTCACTAAAAACCAAGC
+TGTCGCTACTTCCCAAGAAGCTGTTCAGAATCAGAATGAGCCGCAACTTC
+GGGATGAAAATGCTCACAATGACAAATCTGTCCACGGAGTGCTTAATCCA
+ACTTACCAAGCTGGGTTACGACGCGACGCCGTTCAACCAGATATTGAAGC
+AGAACGCAAAAAGAGAGATGAGATTGAGGCTGGGAAAAGTTACTGTAGCC
+GACGTTTTGGCGGCGCAACCTGTGACGACAAATCTGCTCAAATTTATGCG
+CGCTTCGATAAAAATGATTGGCGTATCCAACCTGCA
--- /dev/null
+++ b/test-data/column_join_out5.tabular
@@ -0,0 +1,12 @@
+1 i i2 0
+2 ii 0 i3
+3 0 ii2 ii3
+4 0 iii2 iii3
+5 0 0 0
+6 0 iv2 iv3
+7 iii 0 v3
+8 0 v2 0
+9 0 vi2 vi3
+10 0 vii2 vii3
+11 iv viii2 0
+alpha 0 epsilon 0
--- a/test-data/bwa_wrapper_in1.fastq
+++ b/test-data/bwa_wrapper_in1.fastq
@@ -1,4 +1,120 @@
-@081017-and-081020:1:1:1715:1759
+@seq1
GGACTCAGATAGTAATCCACGCTCCTTTAAAATATC
+
II#IIIIIII$5+.(9IIIIIII$%*$G$A31I&&B
+@seq2
+ATTCGACCTATCCTTGCGCAGCTCGAGAAGCTCTTA
++
+IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
+@seq3
+GTAACAAAGTTTGGATTGCTACTGACCGCTCTCGTG
++
+IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
+@seq4
+AGCCGCTCGTCTTTTATGTAGGTGGTCAACCATTTT
++
+IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
+@seq5
+CAGTTATATGGCTTTTGGTTTCTATGTGGCTTAATA
++
+IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
+@seq6
+AGGCGCTCGTCTTGGTATGTAGGTGGTCAACAATTT
++
+IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
+@seq7
+TGTAGGTGGTCAACCAATTTTAATTGCAGGGGCTTC
++
+IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
+@seq8
+ACACCCGTCCTTTACGTCATGCGCTCTATTCTCTGG
++
+IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
+@seq9
+GCCGCTATTCAGGTTGTTTTCTGTTGGTGCTGATAT
++
+IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
+@seq10
+ATTCTTTCTTTTCGTATCAGGGCGTTGAGTTCGATA
++
+IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
+@seq11
+GCATTTCTACTCCTTCTCATCCCCAATGCTTGGCTT
++
+II#IIIIIII$5+.(9IIIIIII$%*$G$A31I&&B
+@seq12
+CGCGCTTCGATAAAAATGGGATTGGCGTTTCCAACC
++
+IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
+@seq13
+ATTTCTACTCTTTCTCATCCCCAATCCTTGCCTTCC
++
+IIIIIIIIIIIIIIIIIIIIIAAIIIIIIIIIIIII
+@seq14
+CCCTTTTGAATGTCACGCTGATATTTTGACTTTGAG
++
+IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
+@seq15
+CCAACTTACCAAGGTGGGTTACGAAACGCGACGCCG
++
+IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
+@seq16
+TCAGGGTATTAAAAGAGATTATTTTTCTCCAGCCAC
++
+IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
+@seq17
+GTGATGTGCTTGCTACCGAAACAATACTTTAGGCAT
++
+IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
+@seq18
+TCAATCCCCCATGCTTGGCCGTTCCATAAGCAGATG
++
+IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
+@seq19
+TTCCTGCGCTTAATGCTTGAGCGTCCTGGTGCTGAT
++
+IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
+@seq20
+CTTATTACCATTTCAACTACTCCGGTTATCGCTGGC
++
+IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
+@seq21
+CTGATACCAATAAAACCCTAAGCATTTGGTTCAGGG
++
+II#IIIIIII$5+.(9IIIIIII$%*$G$A31I&&B
+@seq22
+AATCAAACTTACCAAGGGGTTACGACGCGACGCCGT
++
+IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
+@seq23
+TGTGCTTCCCCAACTTGATTTAATAACCCTATAGAC
++
+IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
+@seq24
+TTTCTCAATCCCCAATGCCTTGGCTTCCCTAAGCAG
++
+IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
+@seq25
+TTGCTACTGACCGCTCTTCGTGCTCGTTGCTGCGTT
++
+IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
+@seq26
+CCGCGTGAAATTTCTATGAAGGATGTTTTCCGTTCT
++
+IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
+@seq27
+CGCTAATCAAGTTGTTTCTGTTTGGTGCTGATATTG
++
+IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
+@seq28
+AAAGAGATTATTTGTCGGTCCAGCCACTAAAGTGAG
++
+IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
+@seq29
+CAAATTAATGCGCGCTTCGATAATGATTGGGGTATC
++
+IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
+@seq30
+ATCCCCTATGCTTGGCTTACCATAAGCAGATGGATA
++
+IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
--- /dev/null
+++ b/test-data/column_join_in14.tabular
@@ -0,0 +1,11 @@
+alpha beta gamma delta epsilon
+1 AA I2 aa i2
+2 BB II2 bb
+3 CC III2 cc ii2
+4 DD IV2 dd iii2
+6 EE V2 ee iv2
+7 FF VI2 ff
+8 GG VII2 gg v2
+9 HH VIII2 hh vi2
+10 II IX2 ii vii2
+11 JJ X2 jj viii2
--- a/test-data/bwa_wrapper_out2.sam
+++ b/test-data/bwa_wrapper_out2.sam
@@ -1,1 +1,30 @@
-081017-and-081020:1:1:1715:1759 16 phiX 322 25 36M * 0 0 GATATTTTAAAGGAGCGTGGATTACTATCTGAGTCC B&&I13A$G$*%$IIIIIII9(.+5$IIIIIII#II XT:A:U NM:i:2 X0:i:1 XM:i:2 XO:i:0 XG:i:0 MD:Z:2C8A24
+seq1 16 phiX 322 25 36M * 0 0 GATATTTTAAAGGAGCGTGGATTACTATCTGAGTCC B&&I13A$G$*%$IIIIIII9(.+5$IIIIIII#II XT:A:U NM:i:2 X0:i:1 XM:i:2 XO:i:0 XG:i:0 MD:Z:2C8A24
+seq10 0 phiX 4149 37 17M1D19M * 0 0 ATTCTTTCTTTTCGTATCAGGGCGTTGAGTTCGATA IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII XT:A:U NM:i:2 X0:i:1 XM:i:1 XO:i:1 XG:i:1 MD:Z:5G11^G19
+seq11 0 phiX 4072 37 18M1D18M * 0 0 GCATTTCTACTCCTTCTCATCCCCAATGCTTGGCTT II#IIIIIII$5+.(9IIIIIII$%*$G$A31I&&B XT:A:U NM:i:2 X0:i:1 XM:i:1 XO:i:1 XG:i:1 MD:Z:12T5^A18
+seq12 4 * 0 0 * * 0 0 CGCGCTTCGATAAAAATGGGATTGGCGTTTCCAACC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
+seq13 4 * 0 0 * * 0 0 ATTTCTACTCTTTCTCATCCCCAATCCTTGCCTTCC IIIIIIIIIIIIIIIIIIIIIAAIIIIIIIIIIIII
+seq14 0 phiX 3998 37 21M1D15M * 0 0 CCCTTTTGAATGTCACGCTGATATTTTGACTTTGAG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII XT:A:U NM:i:2 X0:i:1 XM:i:1 XO:i:1 XG:i:1 MD:Z:5C15^T15
+seq15 4 * 0 0 * * 0 0 CCAACTTACCAAGGTGGGTTACGAAACGCGACGCCG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
+seq16 4 * 0 0 * * 0 0 TCAGGGTATTAAAAGAGATTATTTTTCTCCAGCCAC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
+seq17 0 phiX 3034 37 19M1D17M * 0 0 GTGATGTGCTTGCTACCGAAACAATACTTTAGGCAT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII XT:A:U NM:i:2 X0:i:1 XM:i:1 XO:i:1 XG:i:1 MD:Z:19^T9G7
+seq18 4 * 0 0 * * 0 0 TCAATCCCCCATGCTTGGCCGTTCCATAAGCAGATG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
+seq19 4 * 0 0 * * 0 0 TTCCTGCGCTTAATGCTTGAGCGTCCTGGTGCTGAT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
+seq2 0 phiX 141 37 36M * 0 0 ATTCGACCTATCCTTGCGCAGCTCGAGAAGCTCTTA IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII XT:A:U NM:i:0 X0:i:1 XM:i:0 XO:i:0 XG:i:0 MD:Z:36
+seq20 0 phiX 1082 37 36M * 0 0 CTTATTACCATTTCAACTACTCCGGTTATCGCTGGC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII XT:A:U NM:i:0 X0:i:1 XM:i:0 XO:i:0 XG:i:0 MD:Z:36
+seq21 0 phiX 1344 37 15M1D21M * 0 0 CTGATACCAATAAAACCCTAAGCATTTGGTTCAGGG II#IIIIIII$5+.(9IIIIIII$%*$G$A31I&&B XT:A:U NM:i:2 X0:i:1 XM:i:1 XO:i:1 XG:i:1 MD:Z:15^T13T7
+seq22 4 * 0 0 * * 0 0 AATCAAACTTACCAAGGGGTTACGACGCGACGCCGT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
+seq23 4 * 0 0 * * 0 0 TGTGCTTCCCCAACTTGATTTAATAACCCTATAGAC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
+seq24 0 phiX 4084 37 17M1I18M * 0 0 TTTCTCAATCCCCAATGCCTTGGCTTCCCTAAGCAG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII XT:A:U NM:i:2 X0:i:1 XM:i:1 XO:i:1 XG:i:1 MD:Z:27A7
+seq25 0 phiX 520 37 16M1I19M * 0 0 TTGCTACTGACCGCTCTTCGTGCTCGTTGCTGCGTT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII XT:A:U NM:i:2 X0:i:1 XM:i:1 XO:i:1 XG:i:1 MD:Z:26C8
+seq26 0 phiX 1976 37 36M * 0 0 CCGCGTGAAATTTCTATGAAGGATGTTTTCCGTTCT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII XT:A:U NM:i:0 X0:i:1 XM:i:0 XO:i:0 XG:i:0 MD:Z:36
+seq27 0 phiX 2598 37 20M1I15M * 0 0 CGCTAATCAAGTTGTTTCTGTTTGGTGCTGATATTG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII XT:A:U NM:i:2 X0:i:1 XM:i:1 XO:i:1 XG:i:1 MD:Z:9G25
+seq28 4 * 0 0 * * 0 0 AAAGAGATTATTTGTCGGTCCAGCCACTAAAGTGAG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
+seq29 4 * 0 0 * * 0 0 CAAATTAATGCGCGCTTCGATAATGATTGGGGTATC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
+seq3 0 phiX 505 37 36M * 0 0 GTAACAAAGTTTGGATTGCTACTGACCGCTCTCGTG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII XT:A:U NM:i:0 X0:i:1 XM:i:0 XO:i:0 XG:i:0 MD:Z:36
+seq30 0 phiX 4091 37 18M1I17M * 0 0 ATCCCCTATGCTTGGCTTACCATAAGCAGATGGATA IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII XT:A:U NM:i:2 X0:i:1 XM:i:1 XO:i:1 XG:i:1 MD:Z:6A28
+seq4 4 * 0 0 * * 0 0 AGCCGCTCGTCTTTTATGTAGGTGGTCAACCATTTT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
+seq5 0 phiX 4985 25 36M * 0 0 CAGTTATATGGCTTTTGGTTTCTATGTGGCTTAATA IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII XT:A:U NM:i:2 X0:i:1 XM:i:2 XO:i:0 XG:i:0 MD:Z:13G17A4
+seq6 0 phiX 925 37 11M1D25M * 0 0 AGGCGCTCGTCTTGGTATGTAGGTGGTCAACAATTT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII XT:A:U NM:i:1 X0:i:1 XM:i:0 XO:i:1 XG:i:1 MD:Z:11^T25
+seq7 0 phiX 943 37 13M1I22M * 0 0 TGTAGGTGGTCAACCAATTTTAATTGCAGGGGCTTC IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII XT:A:U NM:i:1 X0:i:1 XM:i:0 XO:i:1 XG:i:1 MD:Z:35
+seq8 4 * 0 0 * * 0 0 ACACCCGTCCTTTACGTCATGCGCTCTATTCTCTGG IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
+seq9 0 phiX 2596 37 16M1I19M * 0 0 GCCGCTATTCAGGTTGTTTTCTGTTGGTGCTGATAT IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII XT:A:U NM:i:2 X0:i:1 XM:i:1 XO:i:1 XG:i:1 MD:Z:7A27
1
0

galaxy-dist commit d36d759bce05: Fix left padding issues on the edit attributes form
by commits-noreply@bitbucket.org 08 Sep '10
by commits-noreply@bitbucket.org 08 Sep '10
08 Sep '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 1282674785 14400
# Node ID d36d759bce05d7cd6db99b115ae8ebb549e09ce7
# Parent 5d3e57e28fb7fa524a47d3a9b7e99f73ebca6676
Fix left padding issues on the edit attributes form
--- a/templates/dataset/edit_attributes.mako
+++ b/templates/dataset/edit_attributes.mako
@@ -82,11 +82,13 @@
</form><form name="auto_detect" action="${h.url_for( controller='root', action='edit' )}" method="post"><input type="hidden" name="id" value="${data.id}"/>
- <div style="float: left; width: 250px; margin-right: 10px;">
- <input type="submit" name="detect" value="${_('Auto-detect')}"/>
- </div>
- <div class="toolParamHelp" style="clear: both;">
- This will inspect the dataset and attempt to correct the above column values if they are not accurate.
+ <div class="form-row">
+ <div style="float: left; width: 250px; margin-right: 10px;">
+ <input type="submit" name="detect" value="${_('Auto-detect')}"/>
+ </div>
+ <div class="toolParamHelp" style="clear: both;">
+ This will inspect the dataset and attempt to correct the above column values if they are not accurate.
+ </div></div></form>
%if data.missing_meta():
@@ -190,9 +192,9 @@
<form name="copy_hda" action="${h.url_for( controller='dataset', action='copy_datasets', source_dataset_ids=data.id, target_history_ids=data.history_id )}" method="post"><div class="form-row"><input type="submit" name="change" value="Copy history item"/>
- </div>
- <div class="toolParamHelp" style="clear: both;">
- Make a copy of this history item in your current history or any of your active histories.
+ <div class="toolParamHelp" style="clear: both;">
+ Make a copy of this history item in your current history or any of your active histories.
+ </div></div></form></div>
1
0

galaxy-dist commit 7fa394981ef6: Bug fixes and basic zoom feature for mutation viz tool
by commits-noreply@bitbucket.org 08 Sep '10
by commits-noreply@bitbucket.org 08 Sep '10
08 Sep '10
# HG changeset patch -- Bitbucket.org
# Project galaxy-dist
# URL http://bitbucket.org/galaxy/galaxy-dist/overview
# User rc
# Date 1282769259 14400
# Node ID 7fa394981ef6f8d079cd8dd776cba349baca958f
# Parent 95915784818931029539fd058c328e45470d34c2
Bug fixes and basic zoom feature for mutation viz tool
--- a/tools/mutation/visualize.py
+++ b/tools/mutation/visualize.py
@@ -85,8 +85,6 @@ def mainsvg(opts):
total = int(row[start_col+4])
diff = int(row[start_col+5])
imp = int(row[start_col+6])
-
- #print 'sample_index', sample_index, total
if total:
x = 16+(sample_index*(WIDTH+GAP))
y = 30+(count*(HEIGHT+GAP))
1
0

08 Sep '10
# HG changeset patch -- Bitbucket.org
# Project galaxy-dist
# URL http://bitbucket.org/galaxy/galaxy-dist/overview
# User rc
# Date 1282769169 14400
# Node ID 95915784818931029539fd058c328e45470d34c2
# Parent b1a9700382738ba805c20047f40541b06d33b04b
(no commit message)
--- a/tools/mutation/visualize.xml
+++ b/tools/mutation/visualize.xml
@@ -1,9 +1,16 @@
<tool id="mutation_visualize" name="Mutation Visualization" version="1.0.0"><description></description>
- <command interpreter="python">visualize.py --input-file=$input --output-file=$out_file1 $header_row</command>
+ <command interpreter="python">visualize.py --input-file=$input --output-file=$out_file1 --zoom=$zoom_value $header_row</command><inputs><param format="tabular" name="input" type="data" label="Compare sequences in"></param><param name="header_row" type="boolean" label="Header in dataset?" checked="yes" truevalue="" falsevalue="--noheaders"/>
+ <param name="zoom_value" type="select" label="Zoom">
+ <option value="1">1x</option>
+ <option value="2">2x</option>
+ <option value="3">3x</option>
+ <option value="4">4x</option>
+ <option value="5">5x</option>
+ </param></inputs><outputs><data format="svg" name="out_file1" />
--- a/tools/mutation/visualize.py
+++ b/tools/mutation/visualize.py
@@ -17,21 +17,21 @@ import svgfig as svg
COLS_PER_SAMPLE = 7
HEADER_COLS = 4
-SPACE_PAIRS = 0.8
-SPACE_SAMPLES = 1
+HEIGHT = 6
+WIDTH = 12
+BAR_WIDTH = 1.5
+GAP = 2
-HEIGHT = 4
-WIDTH = 8
colors = {'A':'blue', 'C':'green', 'G':'orange', 'T':'red'}
bases = ['A', 'C', 'G', 'T' ]
def mainsvg(opts):
- s = svg.SVG('g')
+ s = svg.SVG('g', transform="translate(20,0)")
# display legend
- for i, b in enumerate(bases):
+ for i, b in enumerate( bases ):
bt = svg.SVG("tspan", b, style="font-family:Verdana;font-size:3")
s.append(svg.SVG("text", bt, x=12+(i*10), y=8, stroke="none", fill="black"))
s.append(svg.SVG("rect", x=13+(i*10), y=5, width=4, height=3,
@@ -71,10 +71,10 @@ def mainsvg(opts):
#print 'position', position, ref, count
# display positions
- bt = svg.SVG("tspan", str(position), style="font-family:Verdana;font-size:3")
- s.append(svg.SVG("text", bt, x=9, y=33+(count*5), stroke="none", fill="black"))
- s.append(svg.SVG("rect", x=4, y=30+(count*5), width=10, height=4,
- stroke='none', fill=colors[ref.upper()], fill_opacity=0.3))
+ bt = svg.SVG("tspan", str(position), style="font-family:Verdana;font-size:4")
+ s.append(svg.SVG("text", bt, x=7, y=34+(count*(HEIGHT+GAP)), stroke="none", fill="black"))
+ s.append(svg.SVG("rect", x=0, y=30+(count*(HEIGHT+GAP)), width=14, height=HEIGHT,
+ stroke='none', fill=colors[ref.upper()], fill_opacity=0.2))
for sample_index in range(int((len(row)-HEADER_COLS)/COLS_PER_SAMPLE)):
start_col = HEADER_COLS+(COLS_PER_SAMPLE*sample_index)
@@ -88,10 +88,10 @@ def mainsvg(opts):
#print 'sample_index', sample_index, total
if total:
- x = 16+(sample_index*10)
- y = 30+(count*5)
+ x = 16+(sample_index*(WIDTH+GAP))
+ y = 30+(count*(HEIGHT+GAP))
width = WIDTH
- height = 4
+ height = HEIGHT
if imp == 1:
fill_opacity = 0.1
@@ -104,18 +104,21 @@ def mainsvg(opts):
stroke='none', fill='grey', fill_opacity=fill_opacity))
for base, value in enumerate([n_a, n_c, n_g, n_t]):
width = int(math.ceil(value / total * WIDTH))
- s.append(svg.SVG("rect", x=x, y=y, width=width, height=1,
+ s.append(svg.SVG("rect", x=x, y=y, width=width, height=BAR_WIDTH,
stroke='none', fill=colors[bases[base]], fill_opacity=0.6))
- y = y + 1
+ y = y + BAR_WIDTH
#print base, value, total, x, y, width
count=count+1
-
- w = str(int(700)) + "px"
- h = str(int(1000)) + "px"
- canv = svg.canvas(s, width=w, height=h, viewBox="0 0 200 300")
+
+ #print x, y
+
+ zoom = int(opts.zoom)
+ w = "%ipx" % (x*(10+zoom))
+ h = "%ipx" % (y*(2+zoom))
+ canv = svg.canvas(s, width=w, height=h, viewBox="0 0 %i %i" %(x+100, y+100))
canv.save(opts.output_file)
@@ -123,6 +126,7 @@ if __name__ == '__main__':
parser = optparse.OptionParser()
parser.add_option('-i', '--input-file', dest='input_file', action='store')
parser.add_option('-o', '--output-file', dest='output_file', action='store')
+ parser.add_option('-z', '--zoom', dest='zoom', action='store', default='1')
parser.add_option('-n', '--noheaders', dest='header_row', action='store_false', default=True)
(opts, args) = parser.parse_args()
mainsvg(opts)
1
0

08 Sep '10
# HG changeset patch -- Bitbucket.org
# Project galaxy-dist
# URL http://bitbucket.org/galaxy/galaxy-dist/overview
# User rc
# Date 1282753644 14400
# Node ID b1a9700382738ba805c20047f40541b06d33b04b
# Parent d36d759bce05d7cd6db99b115ae8ebb549e09ce7
added svg datatype
--- a/datatypes_conf.xml.sample
+++ b/datatypes_conf.xml.sample
@@ -105,6 +105,7 @@
<datatype extension="scf" type="galaxy.datatypes.binary:Scf" mimetype="application/octet-stream" display_in_upload="true"/><datatype extension="Sequences" type="galaxy.datatypes.assembly:Sequences" display_in_upload="false"/><datatype extension="sff" type="galaxy.datatypes.binary:Sff" mimetype="application/octet-stream" display_in_upload="true"/>
+ <datatype extension="svg" type="galaxy.datatypes.images:Image" mimetype="image/svg+xml"/><datatype extension="taxonomy" type="galaxy.datatypes.tabular:Taxonomy" display_in_upload="true"/><datatype extension="tabular" type="galaxy.datatypes.tabular:Tabular" display_in_upload="true"/><datatype extension="txt" type="galaxy.datatypes.data:Text" display_in_upload="true"/>
1
0

galaxy-dist commit 5d3e57e28fb7: Enhance grid framework to enable custom column sorting. Sort criteria are now mapped to a column, and the column defines the sorting to be done on the grid query. Default sorting behavior has not changed. In addition, column's model_class attribute now defaults to the grid's model_class; this should make column definitions more intuitive and shorter.
by commits-noreply@bitbucket.org 08 Sep '10
by commits-noreply@bitbucket.org 08 Sep '10
08 Sep '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 1282595659 14400
# Node ID 5d3e57e28fb7fa524a47d3a9b7e99f73ebca6676
# Parent 60448575467fef8f6a42d83906ee2a622511c541
Enhance grid framework to enable custom column sorting. Sort criteria are now mapped to a column, and the column defines the sorting to be done on the grid query. Default sorting behavior has not changed. In addition, column's model_class attribute now defaults to the grid's model_class; this should make column definitions more intuitive and shorter.
Used custom sorting functionality to enable (a) case-insensitive sorting of text fields and (b) case-insensitive sorting of published item by username.
--- a/templates/history/list_published.mako
+++ b/templates/history/list_published.mako
@@ -28,7 +28,7 @@
<div style="overflow: auto; height: 100%;"><div class="page-container" style="padding: 10px;">
- ${unicode( grid, 'utf-8' )}
+ ${h.to_unicode( grid )}
</div></div>
--- a/lib/galaxy/web/controllers/dataset.py
+++ b/lib/galaxy/web/controllers/dataset.py
@@ -107,14 +107,14 @@ class HistoryDatasetAssociationListGrid(
title = "Saved Datasets"
model_class = model.HistoryDatasetAssociation
template='/dataset/grid.mako'
- default_sort_key = "-create_time"
+ default_sort_key = "-update_time"
columns = [
- grids.TextColumn( "Name", key="name", model_class=model.HistoryDatasetAssociation,
+ grids.TextColumn( "Name", key="name",
# Link name to dataset's history.
- link=( lambda item: iff( item.history.deleted, None, dict( operation="switch", id=item.id ) ) ), filterable="advanced", attach_popup=True ),
+ link=( lambda item: iff( item.history.deleted, None, dict( operation="switch", id=item.id ) ) ), filterable="advanced", attach_popup=True ),
HistoryColumn( "History", key="history",
link=( lambda item: iff( item.history.deleted, None, dict( operation="switch_history", id=item.id ) ) ) ),
- grids.IndividualTagsColumn( "Tags", key="tags", model_class=model.HistoryDatasetAssociation, model_tag_association_class=model.HistoryDatasetAssociationTagAssociation, filterable="advanced", grid_name="HistoryDatasetAssocationListGrid" ),
+ grids.IndividualTagsColumn( "Tags", key="tags", model_tag_association_class=model.HistoryDatasetAssociationTagAssociation, filterable="advanced", grid_name="HistoryDatasetAssocationListGrid" ),
StatusColumn( "Status", key="deleted", attach_popup=False ),
grids.GridColumn( "Last Updated", key="update_time", format=time_ago ),
]
--- a/lib/galaxy/web/controllers/history.py
+++ b/lib/galaxy/web/controllers/history.py
@@ -38,16 +38,15 @@ class HistoryListGrid( grids.Grid ):
title = "Saved Histories"
model_class = model.History
template='/history/grid.mako'
- default_sort_key = "-create_time"
+ default_sort_key = "-update_time"
columns = [
- NameColumn( "Name", key="name", model_class=model.History,
+ NameColumn( "Name", key="name",
link=( lambda history: iff( history.deleted, None, dict( operation="Switch", id=history.id ) ) ),
attach_popup=True, filterable="advanced" ),
DatasetsByStateColumn( "Datasets (by state)", ncells=4 ),
- grids.IndividualTagsColumn( "Tags", key="tags", model_class=model.History, \
- model_tag_association_class=model.HistoryTagAssociation, \
+ grids.IndividualTagsColumn( "Tags", key="tags", model_tag_association_class=model.HistoryTagAssociation, \
filterable="advanced", grid_name="HistoryListGrid" ),
- grids.SharingStatusColumn( "Sharing", key="sharing", model_class=model.History, filterable="advanced", sortable=False ),
+ grids.SharingStatusColumn( "Sharing", key="sharing", filterable="advanced", sortable=False ),
grids.GridColumn( "Created", key="create_time", format=time_ago ),
grids.GridColumn( "Last Updated", key="update_time", format=time_ago ),
# Columns that are valid for filtering but are not visible.
@@ -130,10 +129,10 @@ class HistoryAllPublishedGrid( grids.Gri
default_filter = dict( public_url="All", username="All", tags="All" )
use_async = True
columns = [
- NameURLColumn( "Name", key="name", model_class=model.History, filterable="advanced" ),
- grids.OwnerAnnotationColumn( "Annotation", key="annotation", model_class=model.History, model_annotation_association_class=model.HistoryAnnotationAssociation, filterable="advanced" ),
- grids.OwnerColumn( "Owner", key="username", model_class=model.User, filterable="advanced", sortable=False ),
- grids.CommunityTagsColumn( "Community Tags", key="tags", model_class=model.History, model_tag_association_class=model.HistoryTagAssociation, filterable="advanced", grid_name="PublicHistoryListGrid" ),
+ NameURLColumn( "Name", key="name", filterable="advanced" ),
+ grids.OwnerAnnotationColumn( "Annotation", key="annotation", model_annotation_association_class=model.HistoryAnnotationAssociation, filterable="advanced" ),
+ grids.OwnerColumn( "Owner", key="owner", model_class=model.User, filterable="advanced" ),
+ grids.CommunityTagsColumn( "Community Tags", key="tags", model_tag_association_class=model.HistoryTagAssociation, filterable="advanced", grid_name="PublicHistoryListGrid" ),
grids.GridColumn( "Last Updated", key="update_time", format=time_ago )
]
columns.append(
--- a/lib/galaxy/web/controllers/workflow.py
+++ b/lib/galaxy/web/controllers/workflow.py
@@ -37,8 +37,8 @@ class StoredWorkflowListGrid( grids.Grid
default_filter = { "name" : "All", "tags": "All" }
default_sort_key = "-update_time"
columns = [
- grids.TextColumn( "Name", key="name", model_class=model.StoredWorkflow, attach_popup=True, filterable="advanced" ),
- grids.IndividualTagsColumn( "Tags", "tags", model.StoredWorkflow, model.StoredWorkflowTagAssociation, filterable="advanced", grid_name="StoredWorkflowListGrid" ),
+ grids.TextColumn( "Name", key="name", attach_popup=True, filterable="advanced" ),
+ grids.IndividualTagsColumn( "Tags", "tags", model_tag_association_class=model.StoredWorkflowTagAssociation, filterable="advanced", grid_name="StoredWorkflowListGrid" ),
StepsColumn( "Steps" ),
grids.GridColumn( "Created", key="create_time", format=time_ago ),
grids.GridColumn( "Last Updated", key="update_time", format=time_ago ),
@@ -67,10 +67,10 @@ class StoredWorkflowAllPublishedGrid( gr
default_filter = dict( public_url="All", username="All", tags="All" )
use_async = True
columns = [
- grids.PublicURLColumn( "Name", key="name", model_class=model.StoredWorkflow, filterable="advanced" ),
- grids.OwnerAnnotationColumn( "Annotation", key="annotation", model_class=model.StoredWorkflow, model_annotation_association_class=model.StoredWorkflowAnnotationAssociation, filterable="advanced" ),
- grids.OwnerColumn( "Owner", key="username", model_class=model.User, filterable="advanced", sortable=False ),
- grids.CommunityTagsColumn( "Community Tags", key="tags", model_class=model.StoredWorkflow, model_tag_association_class=model.StoredWorkflowTagAssociation, filterable="advanced", grid_name="PublicWorkflowListGrid" ),
+ grids.PublicURLColumn( "Name", key="name", filterable="advanced" ),
+ grids.OwnerAnnotationColumn( "Annotation", key="annotation", model_annotation_association_class=model.StoredWorkflowAnnotationAssociation, filterable="advanced" ),
+ grids.OwnerColumn( "Owner", key="owner", model_class=model.User, filterable="advanced" ),
+ grids.CommunityTagsColumn( "Community Tags", key="tags", model_tag_association_class=model.StoredWorkflowTagAssociation, filterable="advanced", grid_name="PublicWorkflowListGrid" ),
grids.GridColumn( "Last Updated", key="update_time", format=time_ago )
]
columns.append(
--- a/templates/visualization/list_published.mako
+++ b/templates/visualization/list_published.mako
@@ -28,7 +28,7 @@
<div style="overflow: auto; height: 100%;"><div class="page-container" style="padding: 10px;">
- ${unicode( grid, 'utf-8' )}
+ ${h.to_unicode( grid )}
</div></div>
--- a/templates/workflow/list_published.mako
+++ b/templates/workflow/list_published.mako
@@ -28,7 +28,7 @@
<div style="overflow: auto; height: 100%;"><div class="page-container" style="padding: 10px;">
- ${unicode( grid, 'utf-8' )}
+ ${h.to_unicode( grid )}
</div></div>
--- a/lib/galaxy/web/controllers/visualization.py
+++ b/lib/galaxy/web/controllers/visualization.py
@@ -12,11 +12,11 @@ class VisualizationListGrid( grids.Grid
default_sort_key = "-update_time"
default_filter = dict( title="All", deleted="False", tags="All", sharing="All" )
columns = [
- grids.TextColumn( "Title", key="title", model_class=model.Visualization, attach_popup=True,
+ grids.TextColumn( "Title", key="title", attach_popup=True,
link=( lambda item: dict( controller="tracks", action="browser", id=item.id ) ) ),
- grids.TextColumn( "Dbkey", key="dbkey", model_class=model.Visualization ),
- grids.IndividualTagsColumn( "Tags", key="tags", model_class=model.Visualization, model_tag_association_class=model.VisualizationTagAssociation, filterable="advanced", grid_name="VisualizationListGrid" ),
- grids.SharingStatusColumn( "Sharing", key="sharing", model_class=model.Visualization, filterable="advanced", sortable=False ),
+ grids.TextColumn( "Dbkey", key="dbkey" ),
+ grids.IndividualTagsColumn( "Tags", key="tags", model_tag_association_class=model.VisualizationTagAssociation, filterable="advanced", grid_name="VisualizationListGrid" ),
+ grids.SharingStatusColumn( "Sharing", key="sharing", filterable="advanced", sortable=False ),
grids.GridColumn( "Created", key="create_time", format=time_ago ),
grids.GridColumn( "Last Updated", key="update_time", format=time_ago ),
]
@@ -47,10 +47,10 @@ class VisualizationAllPublishedGrid( gri
default_sort_key = "-update_time"
default_filter = dict( title="All", username="All" )
columns = [
- grids.PublicURLColumn( "Title", key="title", model_class=model.Visualization, filterable="advanced" ),
- grids.OwnerAnnotationColumn( "Annotation", key="annotation", model_class=model.Visualization, model_annotation_association_class=model.VisualizationAnnotationAssociation, filterable="advanced" ),
- grids.OwnerColumn( "Owner", key="username", model_class=model.User, filterable="advanced", sortable=False ),
- grids.CommunityTagsColumn( "Community Tags", key="tags", model_class=model.Visualization, model_tag_association_class=model.VisualizationTagAssociation, filterable="advanced", grid_name="VisualizationAllPublishedGrid" ),
+ grids.PublicURLColumn( "Title", key="title", filterable="advanced" ),
+ grids.OwnerAnnotationColumn( "Annotation", key="annotation", model_annotation_association_class=model.VisualizationAnnotationAssociation, filterable="advanced" ),
+ grids.OwnerColumn( "Owner", key="owner", model_class=model.User, filterable="advanced" ),
+ grids.CommunityTagsColumn( "Community Tags", key="tags", model_tag_association_class=model.VisualizationTagAssociation, filterable="advanced", grid_name="VisualizationAllPublishedGrid" ),
grids.GridColumn( "Last Updated", key="update_time", format=time_ago )
]
columns.append(
--- a/templates/page/index.mako
+++ b/templates/page/index.mako
@@ -15,7 +15,7 @@
<div style="overflow: auto; height: 100%;"><div class="page-container" style="padding: 10px;">
- ${grid}
+ ${h.to_unicode( grid )}
<br><br><h2>Pages shared with you by others</h2>
--- a/lib/galaxy/web/controllers/page.py
+++ b/lib/galaxy/web/controllers/page.py
@@ -25,11 +25,11 @@ class PageListGrid( grids.Grid ):
default_filter = { "published" : "All", "tags" : "All", "title" : "All", "sharing" : "All" }
default_sort_key = "-create_time"
columns = [
- grids.TextColumn( "Title", key="title", model_class=model.Page, attach_popup=True, filterable="advanced" ),
+ grids.TextColumn( "Title", key="title", attach_popup=True, filterable="advanced" ),
URLColumn( "Public URL" ),
- grids.OwnerAnnotationColumn( "Annotation", key="annotation", model_class=model.Page, model_annotation_association_class=model.PageAnnotationAssociation, filterable="advanced" ),
- grids.IndividualTagsColumn( "Tags", key="tags", model_class=model.Page, model_tag_association_class=model.PageTagAssociation, filterable="advanced", grid_name="PageListGrid" ),
- grids.SharingStatusColumn( "Sharing", key="sharing", model_class=model.Page, filterable="advanced", sortable=False ),
+ grids.OwnerAnnotationColumn( "Annotation", key="annotation", model_annotation_association_class=model.PageAnnotationAssociation, filterable="advanced" ),
+ grids.IndividualTagsColumn( "Tags", key="tags", model_tag_association_class=model.PageTagAssociation, filterable="advanced", grid_name="PageListGrid" ),
+ grids.SharingStatusColumn( "Sharing", key="sharing", filterable="advanced", sortable=False ),
grids.GridColumn( "Created", key="create_time", format=time_ago ),
grids.GridColumn( "Last Updated", key="update_time", format=time_ago ),
]
@@ -61,10 +61,10 @@ class PageAllPublishedGrid( grids.Grid )
default_sort_key = "-update_time"
default_filter = dict( title="All", username="All" )
columns = [
- grids.PublicURLColumn( "Title", key="title", model_class=model.Page, filterable="advanced" ),
- grids.OwnerAnnotationColumn( "Annotation", key="annotation", model_class=model.Page, model_annotation_association_class=model.PageAnnotationAssociation, filterable="advanced" ),
- grids.OwnerColumn( "Owner", key="username", model_class=model.User, filterable="advanced", sortable=False ),
- grids.CommunityTagsColumn( "Community Tags", key="tags", model_class=model.Page, model_tag_association_class=model.PageTagAssociation, filterable="advanced", grid_name="PageAllPublishedGrid" ),
+ grids.PublicURLColumn( "Title", key="title", filterable="advanced" ),
+ grids.OwnerAnnotationColumn( "Annotation", key="annotation", model_annotation_association_class=model.PageAnnotationAssociation, filterable="advanced" ),
+ grids.OwnerColumn( "Owner", key="owner", model_class=model.User, filterable="advanced" ),
+ grids.CommunityTagsColumn( "Community Tags", key="tags", model_tag_association_class=model.PageTagAssociation, filterable="advanced", grid_name="PageAllPublishedGrid" ),
grids.GridColumn( "Last Updated", key="update_time", format=time_ago )
]
columns.append(
@@ -107,12 +107,12 @@ class HistorySelectionGrid( ItemSelectio
title = "Saved Histories"
model_class = model.History
columns = [
- ItemSelectionGrid.NameColumn( "Name", key="name", model_class=model.History, filterable="advanced" ),
- grids.IndividualTagsColumn( "Tags", key="tags", model_class=model.History, model_tag_association_class=model.HistoryTagAssociation, filterable="advanced"),
+ ItemSelectionGrid.NameColumn( "Name", key="name", filterable="advanced" ),
+ grids.IndividualTagsColumn( "Tags", key="tags", model_tag_association_class=model.HistoryTagAssociation, filterable="advanced"),
grids.GridColumn( "Last Updated", key="update_time", format=time_ago ),
# Columns that are valid for filtering but are not visible.
grids.DeletedColumn( "Deleted", key="deleted", visible=False, filterable="advanced" ),
- grids.SharingStatusColumn( "Sharing", key="sharing", model_class=model.History, filterable="advanced", sortable=False, visible=False ),
+ grids.SharingStatusColumn( "Sharing", key="sharing", filterable="advanced", sortable=False, visible=False ),
]
columns.append(
grids.MulticolFilterColumn(
@@ -130,12 +130,12 @@ class HistoryDatasetAssociationSelection
title = "Saved Datasets"
model_class = model.HistoryDatasetAssociation
columns = [
- ItemSelectionGrid.NameColumn( "Name", key="name", model_class=model.HistoryDatasetAssociation, filterable="advanced" ),
- grids.IndividualTagsColumn( "Tags", key="tags", model_class=model.HistoryDatasetAssociation, model_tag_association_class=model.HistoryDatasetAssociationTagAssociation, filterable="advanced"),
+ ItemSelectionGrid.NameColumn( "Name", key="name", filterable="advanced" ),
+ grids.IndividualTagsColumn( "Tags", key="tags", model_tag_association_class=model.HistoryDatasetAssociationTagAssociation, filterable="advanced"),
grids.GridColumn( "Last Updated", key="update_time", format=time_ago ),
# Columns that are valid for filtering but are not visible.
grids.DeletedColumn( "Deleted", key="deleted", visible=False, filterable="advanced" ),
- grids.SharingStatusColumn( "Sharing", key="sharing", model_class=model.HistoryDatasetAssociation, filterable="advanced", sortable=False, visible=False ),
+ grids.SharingStatusColumn( "Sharing", key="sharing", filterable="advanced", sortable=False, visible=False ),
]
columns.append(
grids.MulticolFilterColumn(
@@ -155,12 +155,12 @@ class WorkflowSelectionGrid( ItemSelecti
title = "Saved Workflows"
model_class = model.StoredWorkflow
columns = [
- ItemSelectionGrid.NameColumn( "Name", key="name", model_class=model.StoredWorkflow, filterable="advanced" ),
- grids.IndividualTagsColumn( "Tags", key="tags", model_class=model.StoredWorkflow, model_tag_association_class=model.StoredWorkflowTagAssociation, filterable="advanced"),
+ ItemSelectionGrid.NameColumn( "Name", key="name", filterable="advanced" ),
+ grids.IndividualTagsColumn( "Tags", key="tags", model_tag_association_class=model.StoredWorkflowTagAssociation, filterable="advanced"),
grids.GridColumn( "Last Updated", key="update_time", format=time_ago ),
# Columns that are valid for filtering but are not visible.
grids.DeletedColumn( "Deleted", key="deleted", visible=False, filterable="advanced" ),
- grids.SharingStatusColumn( "Sharing", key="sharing", model_class=model.StoredWorkflow, filterable="advanced", sortable=False, visible=False ),
+ grids.SharingStatusColumn( "Sharing", key="sharing", filterable="advanced", sortable=False, visible=False ),
]
columns.append(
grids.MulticolFilterColumn(
@@ -175,12 +175,12 @@ class PageSelectionGrid( ItemSelectionGr
title = "Saved Pages"
model_class = model.Page
columns = [
- grids.TextColumn( "Title", key="title", model_class=model.Page, filterable="advanced" ),
- grids.IndividualTagsColumn( "Tags", key="tags", model_class=model.Page, model_tag_association_class=model.PageTagAssociation, filterable="advanced"),
+ grids.TextColumn( "Title", key="title", filterable="advanced" ),
+ grids.IndividualTagsColumn( "Tags", key="tags", model_tag_association_class=model.PageTagAssociation, filterable="advanced"),
grids.GridColumn( "Last Updated", key="update_time", format=time_ago ),
# Columns that are valid for filtering but are not visible.
grids.DeletedColumn( "Deleted", key="deleted", visible=False, filterable="advanced" ),
- grids.SharingStatusColumn( "Sharing", key="sharing", model_class=model.Page, filterable="advanced", sortable=False, visible=False ),
+ grids.SharingStatusColumn( "Sharing", key="sharing", filterable="advanced", sortable=False, visible=False ),
]
columns.append(
grids.MulticolFilterColumn(
@@ -195,10 +195,10 @@ class VisualizationSelectionGrid( ItemSe
title = "Saved Visualizations"
model_class = model.Visualization
columns = [
- grids.TextColumn( "Title", key="title", model_class=model.Visualization, filterable="advanced" ),
- grids.TextColumn( "Type", key="type", model_class=model.Visualization ),
- grids.IndividualTagsColumn( "Tags", key="tags", model_class=model.Visualization, model_tag_association_class=model.VisualizationTagAssociation, filterable="advanced", grid_name="VisualizationListGrid" ),
- grids.SharingStatusColumn( "Sharing", key="sharing", model_class=model.Visualization, filterable="advanced", sortable=False ),
+ grids.TextColumn( "Title", key="title", filterable="advanced" ),
+ grids.TextColumn( "Type", key="type" ),
+ grids.IndividualTagsColumn( "Tags", key="tags", model_tag_association_class=model.VisualizationTagAssociation, filterable="advanced", grid_name="VisualizationListGrid" ),
+ grids.SharingStatusColumn( "Sharing", key="sharing", filterable="advanced", sortable=False ),
grids.GridColumn( "Last Updated", key="update_time", format=time_ago ),
]
columns.append(
@@ -299,8 +299,8 @@ class PageController( BaseController, Sh
return self.sharing( trans, **kwargs )
session.flush()
- # Build grid HTML and make sure to encode in utf-8 to support unicode characters.
- grid = unicode( self._page_list( trans, *args, **kwargs ), 'utf-8' )
+ # Build grid HTML.
+ grid = self._page_list( trans, *args, **kwargs )
# Build list of pages shared with user.
shared_by_others = trans.sa_session \
@@ -316,7 +316,7 @@ class PageController( BaseController, Sh
@web.expose
def list_published( self, trans, *args, **kwargs ):
- grid = unicode( self._all_published_list( trans, *args, **kwargs ), 'utf-8' )
+ grid = self._all_published_list( trans, *args, **kwargs )
if 'async' in kwargs:
return grid
else:
--- a/lib/galaxy/web/framework/helpers/grids.py
+++ b/lib/galaxy/web/framework/helpers/grids.py
@@ -4,6 +4,7 @@ from galaxy.web.framework.helpers import
from galaxy.web import url_for
from galaxy.util.json import from_json_string, to_json_string
from galaxy.util.odict import odict
+from galaxy.web.framework.helpers import to_unicode
import sys, logging, math
@@ -41,12 +42,25 @@ class Grid( object ):
if operation.allow_multiple:
self.has_multiple_item_operations = True
break
+
+ # If a column does not have a model class, set the column's model class
+ # to be the grid's model class.
+ for column in self.columns:
+ if not column.model_class:
+ column.model_class = self.model_class
+
def __call__( self, trans, **kwargs ):
+ #
+ # Get basics.
+ #
webapp = kwargs.get( 'webapp', 'galaxy' )
status = kwargs.get( 'status', None )
message = kwargs.get( 'message', None )
+
+ #
# Build a base filter and sort key that is the combination of the saved state and defaults.
# Saved state takes preference over defaults.
+ #
base_filter = {}
if self.default_filter:
# default_filter is a dictionary that provides a default set of filters based on the grid's columns.
@@ -70,8 +84,11 @@ class Grid( object ):
use_default_filter = False
if use_default_filter_str:
use_default_filter = ( use_default_filter_str.lower() == 'true' )
+
+ #
# Process filtering arguments to (a) build a query that represents the filter and (b) builds a
- # dictionary that denotes the current filter.
+ # dictionary that denotes the current filter.
+ #
cur_filter_dict = {}
for column in self.columns:
if column.key:
@@ -134,23 +151,39 @@ class Grid( object ):
if not isinstance( column_filter, basestring ):
column_filter = unicode(column_filter)
extra_url_args[ "f-" + column.key ] = column_filter.encode("utf-8")
+
+ #
# Process sort arguments.
+ #
sort_key = None
if 'sort' in kwargs:
sort_key = kwargs['sort']
elif base_sort_key:
sort_key = base_sort_key
- if sort_key:
+
+ if sort_key:
if sort_key.startswith( "-" ):
- # Can't use lower() on timestamp or integer objects, so func.lower() is not used here...
- query = query.order_by( self.model_class.table.c.get( sort_key[1:] ).desc() )
+ ascending = False
+ column_key = sort_key[1:]
else:
- # See reason for not using lower() to do case-insensitive sorting.
- query = query.order_by( self.model_class.table.c.get( sort_key ).asc() )
- extra_url_args['sort'] = sort_key
+ ascending = True
+ column_key = sort_key
+
+ # Sort key is a column key.
+ for column in self.columns:
+ if column.key == column_key:
+ query = column.sort( query, ascending )
+ break
+ extra_url_args['sort'] = sort_key
+
+ #
# There might be a current row
+ #
current_item = self.get_current_item( trans, **kwargs )
+
+ #
# Process page number.
+ #
if self.use_paging:
if 'page' in kwargs:
if kwargs['page'] == 'all':
@@ -175,7 +208,10 @@ class Grid( object ):
# Defaults.
page_num = 1
num_pages = 1
+
+ #
# Preserve grid state: save current filter and sort key.
+ #
if self.preserve_state:
pref_name = unicode( self.__class__.__name__ + self.cur_filter_pref_name )
trans.get_user().preferences[pref_name] = unicode( to_json_string( cur_filter_dict ) )
@@ -191,7 +227,10 @@ class Grid( object ):
params['async'] = ( 'async' in kwargs )
params['webapp'] = webapp
trans.log_action( trans.get_user(), unicode( "grid.view" ), context, params )
+
+ #
# Render grid.
+ #
def url( *args, **kwargs ):
# Only include sort/filter arguments if not linking to another
# page. This is a bit of a hack.
@@ -211,9 +250,14 @@ class Grid( object ):
else:
new_kwargs[ 'id' ] = trans.security.encode_id( id )
return url_for( **new_kwargs )
- use_panels = ( 'use_panels' in kwargs ) and ( kwargs['use_panels'] in [ True, 'True', 'true' ] )
- async_request = ( ( self.use_async ) and ( 'async' in kwargs ) and ( kwargs['async'] in [ True, 'True', 'true'] ) )
- return trans.fill_template( iff( async_request, self.async_template, self.template),
+ use_panels = ( kwargs.get( 'use_panels', False ) in [ True, 'True', 'true' ] )
+ async_request = ( ( self.use_async ) and ( kwargs.get( 'async', False ) in [ True, 'True', 'true'] ) )
+ # Currently, filling the template returns a str object; this requires decoding the string into a
+ # unicode object within mako templates. What probably should be done is to return the template as
+ # utf-8 unicode; however, this would require encoding the object as utf-8 before returning the grid
+ # results via a controller method, which is require substantial changes. Hence, for now, return grid
+ # as str.
+ return trans.fill_template( iff( async_request, self.async_template, self.template ),
grid=self,
query=query,
cur_page_num = page_num,
@@ -258,11 +302,14 @@ class Grid( object ):
return query
class GridColumn( object ):
- def __init__( self, label, grid=None, key=None, model_class=None, method=None, format=None, link=None, attach_popup=False, visible=True, ncells=1,
- # Valid values for filterable are ['standard', 'advanced', None]
- filterable=None, sortable=True ):
+ def __init__( self, label, key=None, model_class=None, method=None, format=None, \
+ link=None, attach_popup=False, visible=True, ncells=1, \
+ # Valid values for filterable are ['standard', 'advanced', None]
+ filterable=None, sortable=True ):
+ """
+ Create a grid column.
+ """
self.label = label
- self.grid = grid
self.key = key
self.model_class = model_class
self.method = method
@@ -272,12 +319,9 @@ class GridColumn( object ):
self.visible = visible
self.ncells = ncells
self.filterable = filterable
- # Currently can only sort of columns that have a database
- # representation, not purely derived.
- if self.key and sortable:
- self.sortable = True
- else:
- self.sortable = False
+ # Column must have a key to be sortable.
+ self.sortable = ( self.key is not None and sortable )
+
def get_value( self, trans, grid, item ):
if self.method:
value = getattr( grid, self.method )( trans, item )
@@ -288,10 +332,12 @@ class GridColumn( object ):
if self.format:
value = self.format( value )
return value
+
def get_link( self, trans, grid, item ):
if self.link and self.link( item ):
return self.link( item )
return None
+
def filter( self, trans, user, query, column_filter ):
""" Modify query to reflect the column filter. """
if column_filter == "All":
@@ -301,6 +347,7 @@ class GridColumn( object ):
elif column_filter == "False":
query = query.filter_by( **{ self.key: False } )
return query
+
def get_accepted_filters( self ):
""" Returns a list of accepted filters for this column. """
accepted_filters_vals = [ "False", "True", "All" ]
@@ -309,6 +356,15 @@ class GridColumn( object ):
args = { self.key: val }
accepted_filters.append( GridColumnFilter( val, args) )
return accepted_filters
+
+ def sort( self, query, ascending ):
+ """ Sort query using this column. """
+ if ascending:
+ query = query.order_by( self.model_class.table.c.get( self.key ).asc() )
+ else:
+ query = query.order_by( self.model_class.table.c.get( self.key ).desc() )
+ return query
+
class TextColumn( GridColumn ):
""" Generic column that employs freetext and, hence, supports freetext, case-independent filtering. """
@@ -332,6 +388,14 @@ class TextColumn( GridColumn ):
""" Returns a SQLAlchemy criterion derived for a single filter. Single filter is the most basic filter--usually a string--and cannot be a list. """
model_class_key_field = getattr( self.model_class, self.key )
return func.lower( model_class_key_field ).like( "%" + a_filter.lower() + "%" )
+
+ def sort( self, query, ascending ):
+ """ Sort column using case-insensitive alphabetical sorting. """
+ if ascending:
+ query = query.order_by( func.lower ( self.model_class.table.c.get( self.key ) ).asc() )
+ else:
+ query = query.order_by( func.lower( self.model_class.table.c.get( self.key ) ).desc() )
+ return query
class IntegerColumn( TextColumn ):
"""
@@ -357,7 +421,7 @@ class IntegerColumn( TextColumn ):
class OwnerAnnotationColumn( TextColumn, UsesAnnotations ):
""" Column that displays and filters item owner's annotations. """
- def __init__( self, col_name, key, model_class, model_annotation_association_class, filterable ):
+ def __init__( self, col_name, key, model_class=None, model_annotation_association_class=None, filterable=None ):
GridColumn.__init__( self, col_name, key=key, model_class=model_class, filterable=filterable )
self.sortable = False
self.model_annotation_association_class = model_annotation_association_class
@@ -375,11 +439,9 @@ class OwnerAnnotationColumn( TextColumn,
class CommunityTagsColumn( TextColumn ):
""" Column that supports community tags. """
- def __init__( self, col_name, key, model_class, model_tag_association_class, filterable, grid_name=None ):
- GridColumn.__init__( self, col_name, key=key, model_class=model_class, filterable=filterable )
+ def __init__( self, col_name, key, model_class=None, model_tag_association_class=None, filterable=None, grid_name=None ):
+ GridColumn.__init__( self, col_name, key=key, model_class=model_class, filterable=filterable, sortable=False )
self.model_tag_association_class = model_tag_association_class
- # Tags cannot be sorted.
- self.sortable = False
# Column-specific attributes.
self.grid_name = grid_name
def get_value( self, trans, grid, item ):
@@ -464,6 +526,15 @@ class OwnerColumn( TextColumn ):
""" Column that lists item's owner. """
def get_value( self, trans, grid, item ):
return item.user.username
+
+ def sort( self, query, ascending ):
+ """ Sort column using case-insensitive alphabetical sorting on item's username. """
+ if ascending:
+ query = query.order_by( func.lower ( self.model_class.username ).asc() )
+ else:
+ query = query.order_by( func.lower( self.model_class.username ).desc() )
+ return query
+
class PublicURLColumn( TextColumn ):
""" Column displays item's public URL based on username and slug. """
@@ -474,7 +545,7 @@ class PublicURLColumn( TextColumn ):
# TODO: provide link to set username.
return None
elif not item.user.slug:
- # TODO: provide link to set slg
+ # TODO: provide link to set slug.
return None
class DeletedColumn( GridColumn ):
--- a/templates/page/list_published.mako
+++ b/templates/page/list_published.mako
@@ -28,6 +28,7 @@
<div style="overflow: auto; height: 100%;"><div class="page-container" style="padding: 10px;">
- ${grid}
-
+ ${h.to_unicode( grid )}
+ </div>
+ </div></%def>
--- a/templates/visualization/list.mako
+++ b/templates/visualization/list.mako
@@ -13,7 +13,7 @@
<div style="overflow: auto; height: 100%;"><div class="page-container" style="padding: 10px;">
- ${grid}
+ ${h.to_unicode( grid )}
<br><br><h2>Visualizations shared with you by others</h2>
1
0
# HG changeset patch -- Bitbucket.org
# Project galaxy-dist
# URL http://bitbucket.org/galaxy/galaxy-dist/overview
# User Dannon Baker <dannonbaker(a)me.com>
# Date 1282572917 14400
# Node ID 60448575467fef8f6a42d83906ee2a622511c541
# Parent 26a0b620490dd8698deb907ecaa540e7fa19a6ee
# Parent 9bcd722236bd7d74784d7317bbe53fa3f050d101
Merge.
1
0

galaxy-dist commit 7242f2dffed3: Fixed another bug in column join so it will handle filling empty columns properly
by commits-noreply@bitbucket.org 08 Sep '10
by commits-noreply@bitbucket.org 08 Sep '10
08 Sep '10
# HG changeset patch -- Bitbucket.org
# Project galaxy-dist
# URL http://bitbucket.org/galaxy/galaxy-dist/overview
# User Kelly Vincent <kpvincent(a)bx.psu.edu>
# Date 1282338256 14400
# Node ID 7242f2dffed302ad6d0d727e43ede1ed65c39463
# Parent 8a3d3fba037061a818b4417978542ae7b71f2e1a
Fixed another bug in column join so it will handle filling empty columns properly
--- a/tools/new_operations/column_join.py
+++ b/tools/new_operations/column_join.py
@@ -241,10 +241,14 @@ def __main__():
new_split_line = split_line[:]
split_line = []
for i, item in enumerate( new_split_line ):
- if item:
+ col = i + 1
+ if not item:
+ try:
+ split_line.append( fill_empty[ i + 1 ] )
+ except KeyError:
+ split_line.append( item )
+ else:
split_line.append( item )
- else:
- split_line.append( fill_empty[ i + 1 ] )
# add actual data to be output below
if ''.join( split_line ):
for col in cols:
@@ -265,9 +269,11 @@ def __main__():
fout.write( '%s%s' % ( delimiter, delimiter.join( current_data ) ) )
elif current_data:
fout.write( '%s%s%s' % ( current, delimiter, delimiter.join( current_data ) ) )
+ last_lines = ''.join( current_lines )
+ else:
+ last_lines = None
last_loc = loc
old_current = current
- last_lines = ''.join( current_lines )
first_line = False
# fill trailing empty columns for final line
if last_loc < len( inputs ) - 1:
1
0

galaxy-dist commit 9bcd722236bd: Refactoring of grid framework in preparation for enhancing sorting. Removed unused keyword 'encoded_sort_key' and made all GridColumn constructor keyword parameters explicit.
by commits-noreply@bitbucket.org 08 Sep '10
by commits-noreply@bitbucket.org 08 Sep '10
08 Sep '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 1282492757 14400
# Node ID 9bcd722236bd7d74784d7317bbe53fa3f050d101
# Parent 3ab68d0ba173ea4b21317c79fdea907bd91f5a81
Refactoring of grid framework in preparation for enhancing sorting. Removed unused keyword 'encoded_sort_key' and made all GridColumn constructor keyword parameters explicit.
--- a/lib/galaxy/web/controllers/dataset.py
+++ b/lib/galaxy/web/controllers/dataset.py
@@ -114,7 +114,7 @@ class HistoryDatasetAssociationListGrid(
link=( lambda item: iff( item.history.deleted, None, dict( operation="switch", id=item.id ) ) ), filterable="advanced", attach_popup=True ),
HistoryColumn( "History", key="history",
link=( lambda item: iff( item.history.deleted, None, dict( operation="switch_history", id=item.id ) ) ) ),
- grids.IndividualTagsColumn( "Tags", "tags", model.HistoryDatasetAssociation, model.HistoryDatasetAssociationTagAssociation, filterable="advanced", grid_name="HistoryDatasetAssocationListGrid" ),
+ grids.IndividualTagsColumn( "Tags", key="tags", model_class=model.HistoryDatasetAssociation, model_tag_association_class=model.HistoryDatasetAssociationTagAssociation, filterable="advanced", grid_name="HistoryDatasetAssocationListGrid" ),
StatusColumn( "Status", key="deleted", attach_popup=False ),
grids.GridColumn( "Last Updated", key="update_time", format=time_ago ),
]
--- a/lib/galaxy/web/controllers/history.py
+++ b/lib/galaxy/web/controllers/history.py
@@ -44,7 +44,9 @@ class HistoryListGrid( grids.Grid ):
link=( lambda history: iff( history.deleted, None, dict( operation="Switch", id=history.id ) ) ),
attach_popup=True, filterable="advanced" ),
DatasetsByStateColumn( "Datasets (by state)", ncells=4 ),
- grids.IndividualTagsColumn( "Tags", "tags", model.History, model.HistoryTagAssociation, filterable="advanced", grid_name="HistoryListGrid" ),
+ grids.IndividualTagsColumn( "Tags", key="tags", model_class=model.History, \
+ model_tag_association_class=model.HistoryTagAssociation, \
+ filterable="advanced", grid_name="HistoryListGrid" ),
grids.SharingStatusColumn( "Sharing", key="sharing", model_class=model.History, filterable="advanced", sortable=False ),
grids.GridColumn( "Created", key="create_time", format=time_ago ),
grids.GridColumn( "Last Updated", key="update_time", format=time_ago ),
@@ -131,7 +133,7 @@ class HistoryAllPublishedGrid( grids.Gri
NameURLColumn( "Name", key="name", model_class=model.History, filterable="advanced" ),
grids.OwnerAnnotationColumn( "Annotation", key="annotation", model_class=model.History, model_annotation_association_class=model.HistoryAnnotationAssociation, filterable="advanced" ),
grids.OwnerColumn( "Owner", key="username", model_class=model.User, filterable="advanced", sortable=False ),
- grids.CommunityTagsColumn( "Community Tags", "tags", model.History, model.HistoryTagAssociation, filterable="advanced", grid_name="PublicHistoryListGrid" ),
+ grids.CommunityTagsColumn( "Community Tags", key="tags", model_class=model.History, model_tag_association_class=model.HistoryTagAssociation, filterable="advanced", grid_name="PublicHistoryListGrid" ),
grids.GridColumn( "Last Updated", key="update_time", format=time_ago )
]
columns.append(
--- a/lib/galaxy/web/controllers/workflow.py
+++ b/lib/galaxy/web/controllers/workflow.py
@@ -70,7 +70,7 @@ class StoredWorkflowAllPublishedGrid( gr
grids.PublicURLColumn( "Name", key="name", model_class=model.StoredWorkflow, filterable="advanced" ),
grids.OwnerAnnotationColumn( "Annotation", key="annotation", model_class=model.StoredWorkflow, model_annotation_association_class=model.StoredWorkflowAnnotationAssociation, filterable="advanced" ),
grids.OwnerColumn( "Owner", key="username", model_class=model.User, filterable="advanced", sortable=False ),
- grids.CommunityTagsColumn( "Community Tags", "tags", model.StoredWorkflow, model.StoredWorkflowTagAssociation, filterable="advanced", grid_name="PublicWorkflowListGrid" ),
+ grids.CommunityTagsColumn( "Community Tags", key="tags", model_class=model.StoredWorkflow, model_tag_association_class=model.StoredWorkflowTagAssociation, filterable="advanced", grid_name="PublicWorkflowListGrid" ),
grids.GridColumn( "Last Updated", key="update_time", format=time_ago )
]
columns.append(
--- a/lib/galaxy/web/controllers/visualization.py
+++ b/lib/galaxy/web/controllers/visualization.py
@@ -15,7 +15,7 @@ class VisualizationListGrid( grids.Grid
grids.TextColumn( "Title", key="title", model_class=model.Visualization, attach_popup=True,
link=( lambda item: dict( controller="tracks", action="browser", id=item.id ) ) ),
grids.TextColumn( "Dbkey", key="dbkey", model_class=model.Visualization ),
- grids.IndividualTagsColumn( "Tags", "tags", model.Visualization, model.VisualizationTagAssociation, filterable="advanced", grid_name="VisualizationListGrid" ),
+ grids.IndividualTagsColumn( "Tags", key="tags", model_class=model.Visualization, model_tag_association_class=model.VisualizationTagAssociation, filterable="advanced", grid_name="VisualizationListGrid" ),
grids.SharingStatusColumn( "Sharing", key="sharing", model_class=model.Visualization, filterable="advanced", sortable=False ),
grids.GridColumn( "Created", key="create_time", format=time_ago ),
grids.GridColumn( "Last Updated", key="update_time", format=time_ago ),
@@ -50,7 +50,7 @@ class VisualizationAllPublishedGrid( gri
grids.PublicURLColumn( "Title", key="title", model_class=model.Visualization, filterable="advanced" ),
grids.OwnerAnnotationColumn( "Annotation", key="annotation", model_class=model.Visualization, model_annotation_association_class=model.VisualizationAnnotationAssociation, filterable="advanced" ),
grids.OwnerColumn( "Owner", key="username", model_class=model.User, filterable="advanced", sortable=False ),
- grids.CommunityTagsColumn( "Community Tags", "tags", model.Visualization, model.VisualizationTagAssociation, filterable="advanced", grid_name="VisualizationAllPublishedGrid" ),
+ grids.CommunityTagsColumn( "Community Tags", key="tags", model_class=model.Visualization, model_tag_association_class=model.VisualizationTagAssociation, filterable="advanced", grid_name="VisualizationAllPublishedGrid" ),
grids.GridColumn( "Last Updated", key="update_time", format=time_ago )
]
columns.append(
--- a/lib/galaxy/web/controllers/page.py
+++ b/lib/galaxy/web/controllers/page.py
@@ -27,7 +27,8 @@ class PageListGrid( grids.Grid ):
columns = [
grids.TextColumn( "Title", key="title", model_class=model.Page, attach_popup=True, filterable="advanced" ),
URLColumn( "Public URL" ),
- grids.IndividualTagsColumn( "Tags", "tags", model.Page, model.PageTagAssociation, filterable="advanced", grid_name="PageListGrid" ),
+ grids.OwnerAnnotationColumn( "Annotation", key="annotation", model_class=model.Page, model_annotation_association_class=model.PageAnnotationAssociation, filterable="advanced" ),
+ grids.IndividualTagsColumn( "Tags", key="tags", model_class=model.Page, model_tag_association_class=model.PageTagAssociation, filterable="advanced", grid_name="PageListGrid" ),
grids.SharingStatusColumn( "Sharing", key="sharing", model_class=model.Page, filterable="advanced", sortable=False ),
grids.GridColumn( "Created", key="create_time", format=time_ago ),
grids.GridColumn( "Last Updated", key="update_time", format=time_ago ),
@@ -63,7 +64,7 @@ class PageAllPublishedGrid( grids.Grid )
grids.PublicURLColumn( "Title", key="title", model_class=model.Page, filterable="advanced" ),
grids.OwnerAnnotationColumn( "Annotation", key="annotation", model_class=model.Page, model_annotation_association_class=model.PageAnnotationAssociation, filterable="advanced" ),
grids.OwnerColumn( "Owner", key="username", model_class=model.User, filterable="advanced", sortable=False ),
- grids.CommunityTagsColumn( "Community Tags", "tags", model.Page, model.PageTagAssociation, filterable="advanced", grid_name="PageAllPublishedGrid" ),
+ grids.CommunityTagsColumn( "Community Tags", key="tags", model_class=model.Page, model_tag_association_class=model.PageTagAssociation, filterable="advanced", grid_name="PageAllPublishedGrid" ),
grids.GridColumn( "Last Updated", key="update_time", format=time_ago )
]
columns.append(
@@ -107,7 +108,7 @@ class HistorySelectionGrid( ItemSelectio
model_class = model.History
columns = [
ItemSelectionGrid.NameColumn( "Name", key="name", model_class=model.History, filterable="advanced" ),
- grids.IndividualTagsColumn( "Tags", "tags", model.History, model.HistoryTagAssociation, filterable="advanced"),
+ grids.IndividualTagsColumn( "Tags", key="tags", model_class=model.History, model_tag_association_class=model.HistoryTagAssociation, filterable="advanced"),
grids.GridColumn( "Last Updated", key="update_time", format=time_ago ),
# Columns that are valid for filtering but are not visible.
grids.DeletedColumn( "Deleted", key="deleted", visible=False, filterable="advanced" ),
@@ -130,7 +131,7 @@ class HistoryDatasetAssociationSelection
model_class = model.HistoryDatasetAssociation
columns = [
ItemSelectionGrid.NameColumn( "Name", key="name", model_class=model.HistoryDatasetAssociation, filterable="advanced" ),
- grids.IndividualTagsColumn( "Tags", "tags", model.HistoryDatasetAssociation, model.HistoryDatasetAssociationTagAssociation, filterable="advanced"),
+ grids.IndividualTagsColumn( "Tags", key="tags", model_class=model.HistoryDatasetAssociation, model_tag_association_class=model.HistoryDatasetAssociationTagAssociation, filterable="advanced"),
grids.GridColumn( "Last Updated", key="update_time", format=time_ago ),
# Columns that are valid for filtering but are not visible.
grids.DeletedColumn( "Deleted", key="deleted", visible=False, filterable="advanced" ),
@@ -155,7 +156,7 @@ class WorkflowSelectionGrid( ItemSelecti
model_class = model.StoredWorkflow
columns = [
ItemSelectionGrid.NameColumn( "Name", key="name", model_class=model.StoredWorkflow, filterable="advanced" ),
- grids.IndividualTagsColumn( "Tags", "tags", model.StoredWorkflow, model.StoredWorkflowTagAssociation, filterable="advanced"),
+ grids.IndividualTagsColumn( "Tags", key="tags", model_class=model.StoredWorkflow, model_tag_association_class=model.StoredWorkflowTagAssociation, filterable="advanced"),
grids.GridColumn( "Last Updated", key="update_time", format=time_ago ),
# Columns that are valid for filtering but are not visible.
grids.DeletedColumn( "Deleted", key="deleted", visible=False, filterable="advanced" ),
@@ -175,7 +176,7 @@ class PageSelectionGrid( ItemSelectionGr
model_class = model.Page
columns = [
grids.TextColumn( "Title", key="title", model_class=model.Page, filterable="advanced" ),
- grids.IndividualTagsColumn( "Tags", "tags", model.Page, model.PageTagAssociation, filterable="advanced"),
+ grids.IndividualTagsColumn( "Tags", key="tags", model_class=model.Page, model_tag_association_class=model.PageTagAssociation, filterable="advanced"),
grids.GridColumn( "Last Updated", key="update_time", format=time_ago ),
# Columns that are valid for filtering but are not visible.
grids.DeletedColumn( "Deleted", key="deleted", visible=False, filterable="advanced" ),
@@ -196,7 +197,7 @@ class VisualizationSelectionGrid( ItemSe
columns = [
grids.TextColumn( "Title", key="title", model_class=model.Visualization, filterable="advanced" ),
grids.TextColumn( "Type", key="type", model_class=model.Visualization ),
- grids.IndividualTagsColumn( "Tags", "tags", model.Visualization, model.VisualizationTagAssociation, filterable="advanced", grid_name="VisualizationListGrid" ),
+ grids.IndividualTagsColumn( "Tags", key="tags", model_class=model.Visualization, model_tag_association_class=model.VisualizationTagAssociation, filterable="advanced", grid_name="VisualizationListGrid" ),
grids.SharingStatusColumn( "Sharing", key="sharing", model_class=model.Visualization, filterable="advanced", sortable=False ),
grids.GridColumn( "Last Updated", key="update_time", format=time_ago ),
]
--- a/lib/galaxy/web/framework/helpers/grids.py
+++ b/lib/galaxy/web/framework/helpers/grids.py
@@ -140,15 +140,14 @@ class Grid( object ):
sort_key = kwargs['sort']
elif base_sort_key:
sort_key = base_sort_key
- encoded_sort_key = sort_key
if sort_key:
if sort_key.startswith( "-" ):
# Can't use lower() on timestamp or integer objects, so func.lower() is not used here...
query = query.order_by( self.model_class.table.c.get( sort_key[1:] ).desc() )
else:
- # See reason for not using lower() to do case-insensitive search.
+ # See reason for not using lower() to do case-insensitive sorting.
query = query.order_by( self.model_class.table.c.get( sort_key ).asc() )
- extra_url_args['sort'] = encoded_sort_key
+ extra_url_args['sort'] = sort_key
# There might be a current row
current_item = self.get_current_item( trans, **kwargs )
# Process page number.
@@ -222,7 +221,6 @@ class Grid( object ):
default_filter_dict=self.default_filter,
cur_filter_dict=cur_filter_dict,
sort_key=sort_key,
- encoded_sort_key=encoded_sort_key,
current_item=current_item,
ids = kwargs.get( 'id', [] ),
url = url,
@@ -260,10 +258,11 @@ class Grid( object ):
return query
class GridColumn( object ):
- def __init__( self, label, key=None, model_class=None, method=None, format=None, link=None, attach_popup=False, visible=True, ncells=1,
+ def __init__( self, label, grid=None, key=None, model_class=None, method=None, format=None, link=None, attach_popup=False, visible=True, ncells=1,
# Valid values for filterable are ['standard', 'advanced', None]
filterable=None, sortable=True ):
self.label = label
+ self.grid = grid
self.key = key
self.model_class = model_class
self.method = method
--- a/templates/grid_base.mako
+++ b/templates/grid_base.mako
@@ -255,7 +255,7 @@
}
// Add sort argument to URL args.
- url_args['sort'] = "${encoded_sort_key}";
+ url_args['sort'] = "${sort_key}";
// Add async keyword to URL args.
url_args['async'] = true;
1
0

galaxy-dist commit 26a0b620490d: Quick fix to hide outputs until they're nicer.
by commits-noreply@bitbucket.org 08 Sep '10
by commits-noreply@bitbucket.org 08 Sep '10
08 Sep '10
# HG changeset patch -- Bitbucket.org
# Project galaxy-dist
# URL http://bitbucket.org/galaxy/galaxy-dist/overview
# User Dannon Baker <dannonbaker(a)me.com>
# Date 1282572262 14400
# Node ID 26a0b620490dd8698deb907ecaa540e7fa19a6ee
# Parent d9e099daa8279880d5e054680ab28e8fc3064f77
Quick fix to hide outputs until they're nicer.
--- a/templates/workflow/list.mako
+++ b/templates/workflow/list.mako
@@ -58,7 +58,6 @@
<td><div popupmenu="wf-${i}-popup"><a class="action-button" href="${h.url_for( action='editor', id=trans.security.encode_id(workflow.id) )}" target="_parent">Edit</a>
- <a class="action-button" href="${h.url_for( action='tag_outputs', id=trans.security.encode_id(workflow.id) )}">Tag Outputs</a><a class="action-button" href="${h.url_for( controller='root', action='index', workflow_id=trans.security.encode_id(workflow.id) )}" target="_parent">Run</a><a class="action-button" href="${h.url_for( action='sharing', id=trans.security.encode_id(workflow.id) )}">Share or Publish</a><a class="action-button" href="${h.url_for( action='clone', id=trans.security.encode_id(workflow.id) )}">Clone</a>
--- a/templates/workflow/editor.mako
+++ b/templates/workflow/editor.mako
@@ -132,7 +132,7 @@
make_popupmenu( $("#workflow-options-button"), {
##"Create New" : create_new_workflow_dialog,
"Edit Attributes" : edit_workflow_attributes,
- "Edit Workflow Outputs": edit_workflow_outputs,
+ ##"Edit Workflow Outputs": edit_workflow_outputs,
"Layout": layout_editor,
"Save" : save_current_workflow,
##"Load a Workflow" : load_workflow,
@@ -399,7 +399,7 @@
}
function show_form_for_tool( text, node ) {
- $("#edit-attributes").hide();
+ $('.right-content').hide();
$("#right-content").show().html( text );
// Add metadata form to tool.
if (node) {
--- a/templates/workflow/tag_outputs.mako
+++ /dev/null
@@ -1,161 +0,0 @@
-<%inherit file="/base.mako"/>
-
-<%def name="javascripts()">
- ${parent.javascripts()}
- ${h.js( "jquery.autocomplete" )}
- <script type="text/javascript">
- $( function() {
- $( "select[refresh_on_change='true']").change( function() {
- $( "#tool_form" ).submit();
- });
- });
- </script>
-</%def>
-
-<%def name="stylesheets()">
- ${parent.stylesheets()}
- ${h.css( "autocomplete_tagging" )}
- <style type="text/css">
- div.toolForm{
- margin-top: 10px;
- margin-bottom: 10px;
- }
- </style>
-</%def>
-
-<%
-from galaxy.tools.parameters import DataToolParameter, RuntimeValue
-from galaxy.jobs.actions.post import ActionBox
-%>
-
-<%def name="do_inputs( inputs, values, errors, prefix, step, other_values = None )">
- %if other_values is None:
- <% other_values = values %>
- %endif
- %for input_index, input in enumerate( inputs.itervalues() ):
- %if input.type == "repeat":
- <div class="repeat-group">
- <div class="form-title-row"><b>${input.title_plural}</b></div>
- <% repeat_values = values[input.name] %>
- %for i in range( len( repeat_values ) ):
- %if input.name in errors:
- <% rep_errors = errors[input.name][i] %>
- %else:
- <% rep_errors = dict() %>
- %endif
- <div class="repeat-group-item">
- <% index = repeat_values[i]['__index__'] %>
- <div class="form-title-row"><b>${input.title} ${i + 1}</b></div>
- ${do_inputs( input.inputs, repeat_values[ i ], rep_errors, prefix + input.name + "_" + str(index) + "|", step, other_values )}
- ## <div class="form-row"><input type="submit" name="${step.id}|${prefix}${input.name}_${i}_remove" value="Remove ${input.title} ${i+1}" /></div>
- </div>
- %endfor
- ## <div class="form-row"><input type="submit" name="${step.id}|${prefix}${input.name}_add" value="Add new ${input.title}" /></div>
- </div>
- %elif input.type == "conditional":
- <% group_values = values[input.name] %>
- <% current_case = group_values['__current_case__'] %>
- <% new_prefix = prefix + input.name + "|" %>
- <% group_errors = errors.get( input.name, {} ) %>
- ${row_for_param( input.test_param, group_values[ input.test_param.name ], other_values, group_errors, prefix, step )}
- ${do_inputs( input.cases[ current_case ].inputs, group_values, group_errors, new_prefix, step, other_values )}
- %else:
- ${row_for_param( input, values[ input.name ], other_values, errors, prefix, step )}
- %endif
- %endfor
-</%def>
-
-<%def name="row_for_param( param, value, other_values, error_dict, prefix, step )">
- ## -- ${param.name} -- ${step.state.inputs} --
- %if error_dict.has_key( param.name ):
- <% cls = "form-row form-row-error" %>
- %else:
- <% cls = "form-row" %>
- %endif
- <div class="${cls}">
- <label>${param.get_label()}</label>
- <div>
- %if isinstance( param, DataToolParameter ):
- %if ( prefix + param.name ) in step.input_connections_by_name:
- <%
- conn = step.input_connections_by_name[ prefix + param.name ]
- %>
- Output dataset '${conn.output_name}' from step ${int(conn.output_step.order_index)+1}
- %else:
- ## FIXME: Initialize in the controller
- <%
- if value is None:
- value = other_values[ param.name ] = param.get_initial_value( t, other_values )
- %>
- ${param.get_html_field( t, value, other_values ).get_html( str(step.id) + "|" + prefix )}
- <input type="hidden" name="${step.id}|__force_update__${prefix}${param.name}" value="true" />
- %endif
- %elif isinstance( value, RuntimeValue ) or ( str(step.id) + '|__runtime__' + prefix + param.name ) in incoming:
- ## On the first load we may see a RuntimeValue, so we write
- ## an input field using the initial value for the param.
- ## Subsequents posts will no longer have the runtime value
- ## (since an actualy value will be posted) so we add a hidden
- ## field so we know to continue drawing form for this param.
- ## FIXME: This logic shouldn't be in the template. The
- ## controller should go through the inputs on the first
- ## load, fill in initial values where needed, and mark
- ## all that are runtime modifiable in some way.
- <% value = other_values[ param.name ] = param.get_initial_value( t, other_values ) %>
- ${param.get_html_field( t, value, other_values ).get_html( str(step.id) + "|" + prefix )}
- <input type="hidden" name="${step.id}|__runtime__${prefix}${param.name}" value="true" />
- %else:
- ${param.value_to_display_text( value, app )}
- %endif
- </div>
- %if step.upgrade_messages and param.name in step.upgrade_messages:
- <div class="warningmark">${step.upgrade_messages[param.name]}</div>
- %endif
- %if error_dict.has_key( param.name ):
- <div style="color: red; font-weight: bold; padding-top: 1px; padding-bottom: 3px;">
- <div style="width: 300px;"><img style="vertical-align: middle;" src="${h.url_for('/static/style/error_small.png')}"> <span style="vertical-align: middle;">${error_dict[param.name]}</span></div>
- </div>
- %endif
- <div style="clear: both"></div>
- </div>
-</%def>
-
-<h2>Set outputs for workflow "${workflow.name}"</h2>
-<p>Select the checkboxes for step outputs you would like to mark as whole-workflow outputs.</p>
-%if has_upgrade_messages:
-<div class="warningmessage">
- Problems were encourered when loading this workflow, likely due to tool
- version changes. Missing parameter values have been replaced with default.
- Please review the parameter values below.
-</div>
-%endif
-
-<form id="tool_form" name="tool_form" method="POST">
-## <input type="hidden" name="workflow_name" value="${workflow.name | h}" />
-%for i, step in enumerate( steps ):
- %if step.type == 'tool':
- <% tool = app.toolbox.tools_by_id[step.tool_id] %>
- <input type="hidden" name="${step.id}|tool_state" value="${step.state.encode( tool, app )}">
- <div class="toolForm">
- <div class="toolFormTitle">Step ${int(step.order_index)+1}: ${tool.name}</div>
- <div class="toolFormBody">
- % for output in tool.outputs:
- <div class='form-row'>
- %if step.workflow_outputs and output in [wf_output.output_name for wf_output in step.workflow_outputs]:
- <p>${output} <input type="checkbox" name="${step.id}|otag|${output}" checked /></p>
- %else:
- <p>${output} <input type="checkbox" name="${step.id}|otag|${output}"/></p>
- %endif
- </div>
- % endfor
- % if step.annotations:
- <hr/>
- <div class='form-row'>
- <label>Annotation:</label> ${step.annotations[0].annotation}
- </div>
- % endif
- </div>
- </div>
- %endif
-%endfor
-<input type="submit" name="save_outputs" value="Save output settings" />
-</form>
1
0

galaxy-dist commit 3ab68d0ba173: Fixes for performance problems with display link generation.
by commits-noreply@bitbucket.org 08 Sep '10
by commits-noreply@bitbucket.org 08 Sep '10
08 Sep '10
# HG changeset patch -- Bitbucket.org
# Project galaxy-dist
# URL http://bitbucket.org/galaxy/galaxy-dist/overview
# User James Taylor <james(a)jamestaylor.org>
# Date 1282421852 14400
# Node ID 3ab68d0ba173ea4b21317c79fdea907bd91f5a81
# Parent 7242f2dffed302ad6d0d727e43ede1ed65c39463
Fixes for performance problems with display link generation.
1) In "ucsc_links", "generate_display_viewport" was being called before the
check for configured UCSC browsers matching the dataset's build. Thus, Galaxy
would scan the start of the file for every dataset, regardless of whether UCSC
links were displayed in the UI
2) When generating the viewport, if an exception was thrown parsing the
chrom/start/end columns (for example, if the metadata was set wrong causing a
non-numeric string to be found in the start column) the loop would continue
WITHOUT executing the scan to end of line and update of the number of lines
processed. Thus, on any file with incorrect metadata, every line of the file
would be read and split.
--- a/lib/galaxy/datatypes/interval.py
+++ b/lib/galaxy/datatypes/interval.py
@@ -1,7 +1,7 @@
"""
Interval datatypes
+"""
-"""
import pkg_resources
pkg_resources.require( "bx-python" )
@@ -20,10 +20,8 @@ import math
log = logging.getLogger(__name__)
-#
-# contain the meta columns and the words that map to it
-# list aliases on the right side of the : in decreasing order of priority
-#
+# Contains the meta columns and the words that map to it; list aliases on the
+# right side of the : in decreasing order of priority
alias_spec = {
'chromCol' : [ 'chrom' , 'CHROMOSOME' , 'CHROM', 'Chromosome Name' ],
'startCol' : [ 'start' , 'START', 'chromStart', 'txStart', 'Start Position (bp)' ],
@@ -38,9 +36,11 @@ for key, value in alias_spec.items():
for elem in value:
alias_helper[elem] = key
-#Constants for configuring viewport generation
-VIEWPORT_READLINE_BUFFER_SIZE = 1048576 #1MB
-VIEWPORT_MAX_READS_PER_LINE = 10 # If a line is greater than VIEWPORT_MAX_READS_PER_LINE * VIEWPORT_READLINE_BUFFER_SIZE bytes in size, then we will not generate a viewport for that dataset
+# Constants for configuring viewport generation: If a line is greater than
+# VIEWPORT_MAX_READS_PER_LINE * VIEWPORT_READLINE_BUFFER_SIZE bytes in size,
+# then we will not generate a viewport for that dataset
+VIEWPORT_READLINE_BUFFER_SIZE = 1048576 # 1MB
+VIEWPORT_MAX_READS_PER_LINE = 10
class Interval( Tabular ):
"""Tab delimited data containing interval information"""
@@ -150,55 +150,66 @@ class Interval( Tabular ):
and dataset.metadata.endCol
except:
return False
+
def get_estimated_display_viewport( self, dataset, chrom_col = None, start_col = None, end_col = None ):
"""Return a chrom, start, stop tuple for viewing a file."""
viewport_feature_count = 100 # viewport should check at least 100 features; excludes comment lines
max_line_count = max( viewport_feature_count, 500 ) # maximum number of lines to check; includes comment lines
- if self.displayable( dataset ):
- try:
- chrom = None
- start = sys.maxint
- end = 0
- if chrom_col is None:
- chrom_col = int( dataset.metadata.chromCol ) - 1
- if start_col is None:
- start_col = int( dataset.metadata.startCol ) - 1
- if end_col is None:
- end_col = int( dataset.metadata.endCol ) - 1
- max_col = max( chrom_col, start_col, end_col )
- fh = open( dataset.file_name )
- while True:
+ if not self.displayable( dataset ):
+ return ( None, None, None )
+ try:
+ # If column indexes were not passwed, determine from metadata
+ if chrom_col is None:
+ chrom_col = int( dataset.metadata.chromCol ) - 1
+ if start_col is None:
+ start_col = int( dataset.metadata.startCol ) - 1
+ if end_col is None:
+ end_col = int( dataset.metadata.endCol ) - 1
+ # Scan lines of file to find a reasonable chromosome and range
+ chrom = None
+ start = sys.maxint
+ end = 0
+ max_col = max( chrom_col, start_col, end_col )
+ fh = open( dataset.file_name )
+ while True:
+ line = fh.readline( VIEWPORT_READLINE_BUFFER_SIZE )
+ # Stop if at end of file
+ if not line:
+ break
+ # Skip comment lines
+ if not line.startswith( '#' ):
+ try:
+ fields = line.rstrip().split( '\t' )
+ if len( fields ) > max_col:
+ if chrom is None or chrom == fields[ chrom_col ]:
+ start = min( start, int( fields[ start_col ] ) )
+ end = max( end, int( fields[ end_col ] ) )
+ # Set chrom last, in case start and end are not integers
+ chrom = fields[ chrom_col ]
+ viewport_feature_count -= 1
+ except Exception, e:
+ # Most likely a non-integer field has been encountered
+ # for start / stop. Just ignore and make sure we finish
+ # reading the line and decrementing the counters.
+ pass
+ # Make sure we are at the next new line
+ readline_count = VIEWPORT_MAX_READS_PER_LINE
+ while line.rstrip( '\n\r' ) == line:
+ assert readline_count > 0, Exception( 'Viewport readline count exceeded for dataset %s.' % dataset.id )
line = fh.readline( VIEWPORT_READLINE_BUFFER_SIZE )
if not line: break #EOF
- if not line.startswith( '#' ):
- try:
- fields = line.rstrip().split( '\t' )
- if len( fields ) > max_col:
- if chrom is None or chrom == fields[ chrom_col ]:
- start = min( start, int( fields[ start_col ] ) )
- end = max( end, int( fields[ end_col ] ) )
- chrom = fields[ chrom_col ] #set chrom last, in case start and end are not integers
- viewport_feature_count -= 1
- except Exception:
- #most likely a non-integer field has been encountered for start / stop
- continue
- #make sure we are at the next new line
- readline_count = VIEWPORT_MAX_READS_PER_LINE
- while line.rstrip( '\n\r' ) == line:
- assert readline_count > 0, Exception( 'Viewport readline count exceeded for dataset %s.' % dataset.id )
- line = fh.readline( VIEWPORT_READLINE_BUFFER_SIZE )
- if not line: break #EOF
- readline_count -= 1
- max_line_count -= 1
- if not viewport_feature_count or not max_line_count:
- #exceeded viewport or total line count to check
- break
- if chrom is not None:
- return ( chrom, str( start ), str( end ) ) #Necessary to return strings?
- except Exception, e:
- #unexpected error, possibly missing metadata
- log.exception( str( e ) )
- return ( None, None, None ) #could not determine viewport
+ readline_count -= 1
+ max_line_count -= 1
+ if not viewport_feature_count or not max_line_count:
+ #exceeded viewport or total line count to check
+ break
+ if chrom is not None:
+ return ( chrom, str( start ), str( end ) ) # Necessary to return strings?
+ except Exception, e:
+ # Unexpected error, possibly missing metadata
+ log.exception( "Exception caught attempting to generate viewport for dataset '%d'", dataset.id )
+ return ( None, None, None )
+
def as_ucsc_display_file( self, dataset, **kwd ):
"""Returns file contents with only the bed data"""
fd, temp_name = tempfile.mkstemp()
@@ -252,22 +263,39 @@ class Interval( Tabular ):
out = "Can't create peek %s" % str( exc )
return out
def ucsc_links( self, dataset, type, app, base_url ):
+ """
+ Generate links to UCSC genome browser sites based on the dbkey
+ and content of dataset.
+ """
+ # Filter UCSC sites to only those that are supported by this build and
+ # enabled.
+ valid_sites = [ ( name, url )
+ for name, url in util.get_ucsc_by_build( dataset.dbkey )
+ if name in app.config.ucsc_display_sites ]
+ if not valid_sites:
+ return []
+ # If there are any valid sites, we need to generate the estimated
+ # viewport
+ chrom, start, stop = self.get_estimated_display_viewport( dataset )
+ if chrom is None:
+ return []
+ # Accumulate links for valid sites
ret_val = []
- chrom, start, stop = self.get_estimated_display_viewport( dataset )
- if chrom is not None:
- for site_name, site_url in util.get_ucsc_by_build(dataset.dbkey):
- if site_name in app.config.ucsc_display_sites:
- # HACK: UCSC doesn't support https, so force http even
- # if our URL scheme is https. Making this work
- # requires additional hackery in your upstream proxy.
- # If UCSC ever supports https, remove this hack.
- internal_url = "%s" % url_for( controller='/dataset', dataset_id=dataset.id, action='display_at', filename='ucsc_' + site_name )
- if base_url.startswith( 'https://' ):
- base_url = base_url.replace( 'https', 'http', 1 )
- display_url = urllib.quote_plus( "%s%s/display_as?id=%i&display_app=%s&authz_method=display_at" % (base_url, url_for( controller='root' ), dataset.id, type) )
- redirect_url = urllib.quote_plus( "%sdb=%s&position=%s:%s-%s&hgt.customText=%%s" % (site_url, dataset.dbkey, chrom, start, stop ) )
- link = '%s?redirect_url=%s&display_url=%s' % ( internal_url, redirect_url, display_url )
- ret_val.append( (site_name, link) )
+ for site_name, site_url in valid_sites:
+ internal_url = url_for( controller='/dataset', dataset_id=dataset.id,
+ action='display_at', filename='ucsc_' + site_name )
+ # HACK: UCSC doesn't support https, so force http even if our URL
+ # scheme is https. Making this work requires additional
+ # hackery in your upstream proxy. If UCSC ever supports
+ # https, remove this hack.
+ if base_url.startswith( 'https://' ):
+ base_url = base_url.replace( 'https', 'http', 1 )
+ display_url = urllib.quote_plus( "%s%s/display_as?id=%i&display_app=%s&authz_method=display_at"
+ % (base_url, url_for( controller='root' ), dataset.id, type) )
+ redirect_url = urllib.quote_plus( "%sdb=%s&position=%s:%s-%s&hgt.customText=%%s"
+ % (site_url, dataset.dbkey, chrom, start, stop ) )
+ link = '%s?redirect_url=%s&display_url=%s' % ( internal_url, redirect_url, display_url )
+ ret_val.append( ( site_name, link ) )
return ret_val
def validate( self, dataset ):
"""Validate an interval file using the bx GenomicIntervalReader"""
1
0

galaxy-dist commit 8242280e5c74: Use image_path for workflows and show_modal instead of relative paths
by commits-noreply@bitbucket.org 08 Sep '10
by commits-noreply@bitbucket.org 08 Sep '10
08 Sep '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 1282330852 14400
# Node ID 8242280e5c74d1fb60daa12f2ddb37cc06bc7e75
# Parent 31fe9ca3a08849ac0160e7e25033487030babec0
Use image_path for workflows and show_modal instead of relative paths
--- a/static/scripts/packed/galaxy.panels.js
+++ b/static/scripts/packed/galaxy.panels.js
@@ -1,1 +1,1 @@
-function ensure_dd_helper(){if($("#DD-helper").length==0){$("<div id='DD-helper'/>").css({background:"white",opacity:0,zIndex:9000,position:"absolute",top:0,left:0,width:"100%",height:"100%"}).appendTo("body").hide()}}function make_left_panel(h,c,e){var g=false;var f=null;var d=function(i){var j=i;if(i<0){i=0}$(h).css("width",i);$(e).css("left",j);$(c).css("left",i+7);if(document.recalc){document.recalc()}};var a=function(){if(g){$(e).removeClass("hover");$(e).animate({left:f},"fast");$(h).css("left",-f).show().animate({left:0},"fast",function(){d(f);$(e).removeClass("hidden")});g=false}else{f=$(e).position().left;$(c).css("left",$(e).innerWidth());if(document.recalc){document.recalc()}$(e).removeClass("hover");$(h).animate({left:-f},"fast");$(e).animate({left:-1},"fast",function(){$(this).addClass("hidden")});g=true}};$(e).hover(function(){$(this).addClass("hover")},function(){$(this).removeClass("hover")}).bind("dragstart",function(i){$("#DD-helper").show()}).bind("dragend
",function(i){$("#DD-helper").hide()}).bind("drag",function(i){x=i.offsetX;x=Math.min(400,Math.max(100,x));if(g){$(h).css("left",0);$(e).removeClass("hidden");g=false}d(x)}).bind("dragclickonly",function(i){a()}).find("div").show();var b=function(i){if((g&&i=="show")||(!g&&i=="hide")){a()}};return{force_panel:b}}function make_right_panel(a,e,h){var j=false;var g=false;var c=null;var d=function(k){$(a).css("width",k);$(e).css("right",k+9);$(h).css("right",k).css("left","");if(document.recalc){document.recalc()}};var i=function(){if(j){$(h).removeClass("hover");$(h).animate({right:c},"fast");$(a).css("right",-c).show().animate({right:0},"fast",function(){d(c);$(h).removeClass("hidden")});j=false}else{c=$(document).width()-$(h).position().left-$(h).outerWidth();$(e).css("right",$(h).innerWidth()+1);if(document.recalc){document.recalc()}$(h).removeClass("hover");$(a).animate({right:-c},"fast");$(h).animate({right:-1},"fast",function(){$(this).addClass("hidden")});j=true}g=false}
;var b=function(k){var l=$(e).width()-(j?c:0);if(l<k){if(!j){i();g=true}}else{if(g){i();g=false}}};$(h).hover(function(){$(this).addClass("hover")},function(){$(this).removeClass("hover")}).bind("dragstart",function(k){$("#DD-helper").show()}).bind("dragend",function(k){$("#DD-helper").hide()}).bind("drag",function(k){x=k.offsetX;w=$(window).width();x=Math.min(w-100,x);x=Math.max(w-400,x);if(j){$(a).css("right",0);$(h).removeClass("hidden");j=false}d(w-x-$(this).outerWidth())}).bind("dragclickonly",function(k){i()}).find("div").show();var f=function(k){if((j&&k=="show")||(!j&&k=="hide")){i()}};return{handle_minwidth_hint:b,force_panel:f}}function hide_modal(){$(".dialog-box-container").fadeOut(function(){$("#overlay").hide();$(".dialog-box").find(".body").children().remove()})}function show_modal(g,c,e,d,f){if(g){$(".dialog-box").find(".title").html(g);$(".dialog-box").find(".unified-panel-header").show()}else{$(".dialog-box").find(".unified-panel-header").hide()}var a=$(".d
ialog-box").find(".buttons").html("");if(e){$.each(e,function(b,h){a.append($("<button/>").text(b).click(h));a.append(" ")});a.show()}else{a.hide()}var a=$(".dialog-box").find(".extra_buttons").html("");if(d){$.each(d,function(b,h){a.append($("<button/>").text(b).click(h));a.append(" ")});a.show()}else{a.hide()}if(c=="progress"){c=$("<img src='../images/yui/rel_interstitial_loading.gif')' />")}$(".dialog-box").find(".body").html(c);if(!$(".dialog-box-container").is(":visible")){$("#overlay").show();$(".dialog-box-container").fadeIn()}if(f){f()}}function show_in_overlay(c){var d=c.width||"600";var b=c.height||"400";var a=c.scroll||"auto";$("#overlay-background").bind("click.overlay",function(){hide_modal();$("#overlay-background").unbind("click.overlay")});show_modal(null,$("<div style='margin: -5px;'><img id='close_button' style='position:absolute;right:-17px;top:-15px;' src='../images/closebox.png'><iframe style='margin: 0; padding: 0;' src='"+c.url+"' width='"+d+"' height=
'"+b+"' scrolling='"+a+"' frameborder='0'></iframe></div>"));$("#close_button").bind("click",function(){hide_modal()})}$(function(){$(".tab").each(function(){var a=$(this).children(".submenu");if(a.length>0){if($.browser.msie){a.prepend("<iframe style=\"position: absolute; top: 0; left: 0; width: 100%; height: 100%; z-index: -1; filter:Alpha(Opacity='0');\"></iframe>")}$(this).hover(function(){a.show()},function(){a.hide()});a.click(function(){a.hide()})}})});function user_changed(a,b){if(a){$(".loggedin-only").show();$(".loggedout-only").hide();$("#user-email").text(a);if(b){$(".admin-only").show()}}else{$(".loggedin-only").hide();$(".loggedout-only").show();$(".admin-only").hide()}};
+function ensure_dd_helper(){if($("#DD-helper").length==0){$("<div id='DD-helper'/>").css({background:"white",opacity:0,zIndex:9000,position:"absolute",top:0,left:0,width:"100%",height:"100%"}).appendTo("body").hide()}}function make_left_panel(h,c,e){var g=false;var f=null;var d=function(i){var j=i;if(i<0){i=0}$(h).css("width",i);$(e).css("left",j);$(c).css("left",i+7);if(document.recalc){document.recalc()}};var a=function(){if(g){$(e).removeClass("hover");$(e).animate({left:f},"fast");$(h).css("left",-f).show().animate({left:0},"fast",function(){d(f);$(e).removeClass("hidden")});g=false}else{f=$(e).position().left;$(c).css("left",$(e).innerWidth());if(document.recalc){document.recalc()}$(e).removeClass("hover");$(h).animate({left:-f},"fast");$(e).animate({left:-1},"fast",function(){$(this).addClass("hidden")});g=true}};$(e).hover(function(){$(this).addClass("hover")},function(){$(this).removeClass("hover")}).bind("dragstart",function(i){$("#DD-helper").show()}).bind("dragend
",function(i){$("#DD-helper").hide()}).bind("drag",function(i){x=i.offsetX;x=Math.min(400,Math.max(100,x));if(g){$(h).css("left",0);$(e).removeClass("hidden");g=false}d(x)}).bind("dragclickonly",function(i){a()}).find("div").show();var b=function(i){if((g&&i=="show")||(!g&&i=="hide")){a()}};return{force_panel:b}}function make_right_panel(a,e,h){var j=false;var g=false;var c=null;var d=function(k){$(a).css("width",k);$(e).css("right",k+9);$(h).css("right",k).css("left","");if(document.recalc){document.recalc()}};var i=function(){if(j){$(h).removeClass("hover");$(h).animate({right:c},"fast");$(a).css("right",-c).show().animate({right:0},"fast",function(){d(c);$(h).removeClass("hidden")});j=false}else{c=$(document).width()-$(h).position().left-$(h).outerWidth();$(e).css("right",$(h).innerWidth()+1);if(document.recalc){document.recalc()}$(h).removeClass("hover");$(a).animate({right:-c},"fast");$(h).animate({right:-1},"fast",function(){$(this).addClass("hidden")});j=true}g=false}
;var b=function(k){var l=$(e).width()-(j?c:0);if(l<k){if(!j){i();g=true}}else{if(g){i();g=false}}};$(h).hover(function(){$(this).addClass("hover")},function(){$(this).removeClass("hover")}).bind("dragstart",function(k){$("#DD-helper").show()}).bind("dragend",function(k){$("#DD-helper").hide()}).bind("drag",function(k){x=k.offsetX;w=$(window).width();x=Math.min(w-100,x);x=Math.max(w-400,x);if(j){$(a).css("right",0);$(h).removeClass("hidden");j=false}d(w-x-$(this).outerWidth())}).bind("dragclickonly",function(k){i()}).find("div").show();var f=function(k){if((j&&k=="show")||(!j&&k=="hide")){i()}};return{handle_minwidth_hint:b,force_panel:f}}function hide_modal(){$(".dialog-box-container").fadeOut(function(){$("#overlay").hide();$(".dialog-box").find(".body").children().remove()})}function show_modal(g,c,e,d,f){if(g){$(".dialog-box").find(".title").html(g);$(".dialog-box").find(".unified-panel-header").show()}else{$(".dialog-box").find(".unified-panel-header").hide()}var a=$(".d
ialog-box").find(".buttons").html("");if(e){$.each(e,function(b,h){a.append($("<button/>").text(b).click(h));a.append(" ")});a.show()}else{a.hide()}var a=$(".dialog-box").find(".extra_buttons").html("");if(d){$.each(d,function(b,h){a.append($("<button/>").text(b).click(h));a.append(" ")});a.show()}else{a.hide()}if(c=="progress"){c=$("<img/>").attr("src",image_path+"/yui/rel_interstitial_loading.gif")}$(".dialog-box").find(".body").html(c);if(!$(".dialog-box-container").is(":visible")){$("#overlay").show();$(".dialog-box-container").fadeIn()}if(f){f()}}function show_in_overlay(c){var d=c.width||"600";var b=c.height||"400";var a=c.scroll||"auto";$("#overlay-background").bind("click.overlay",function(){hide_modal();$("#overlay-background").unbind("click.overlay")});show_modal(null,$("<div style='margin: -5px;'><img id='close_button' style='position:absolute;right:-17px;top:-15px;' src='../images/closebox.png'><iframe style='margin: 0; padding: 0;' src='"+c.url+"' width='"+d+"'
height='"+b+"' scrolling='"+a+"' frameborder='0'></iframe></div>"));$("#close_button").bind("click",function(){hide_modal()})}$(function(){$(".tab").each(function(){var a=$(this).children(".submenu");if(a.length>0){if($.browser.msie){a.prepend("<iframe style=\"position: absolute; top: 0; left: 0; width: 100%; height: 100%; z-index: -1; filter:Alpha(Opacity='0');\"></iframe>")}$(this).hover(function(){a.show()},function(){a.hide()});a.click(function(){a.hide()})}})});function user_changed(a,b){if(a){$(".loggedin-only").show();$(".loggedout-only").hide();$("#user-email").text(a);if(b){$(".admin-only").show()}}else{$(".loggedin-only").hide();$(".loggedout-only").show();$(".admin-only").hide()}};
--- a/static/scripts/packed/galaxy.workflow_editor.canvas.js
+++ b/static/scripts/packed/galaxy.workflow_editor.canvas.js
@@ -1,1 +1,1 @@
-function Terminal(a){this.element=a;this.connectors=[]}$.extend(Terminal.prototype,{connect:function(a){this.connectors.push(a);if(this.node){this.node.changed()}},disconnect:function(a){this.connectors.splice($.inArray(a,this.connectors),1);if(this.node){this.node.changed()}},redraw:function(){$.each(this.connectors,function(a,b){b.redraw()})},destroy:function(){$.each(this.connectors.slice(),function(a,b){b.destroy()})}});function OutputTerminal(a,b){Terminal.call(this,a);this.datatypes=b}OutputTerminal.prototype=new Terminal();function InputTerminal(a,b){Terminal.call(this,a);this.datatypes=b}InputTerminal.prototype=new Terminal();$.extend(InputTerminal.prototype,{can_accept:function(a){if(this.connectors.length<1){for(var c in this.datatypes){for(var b in a.datatypes){if(a.datatypes[b]=="input"||issubtype(a.datatypes[b],this.datatypes[c])){return true}}}}return false}});function Connector(b,a){this.canvas=null;this.dragging=false;this.inner_color="#FFFFFF";this.outer_col
or="#D8B365";if(b&&a){this.connect(b,a)}}$.extend(Connector.prototype,{connect:function(b,a){this.handle1=b;this.handle1.connect(this);this.handle2=a;this.handle2.connect(this)},destroy:function(){if(this.handle1){this.handle1.disconnect(this)}if(this.handle2){this.handle2.disconnect(this)}$(this.canvas).remove()},redraw:function(){var d=$("#canvas-container");if(!this.canvas){this.canvas=document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(this.canvas)}d.append($(this.canvas));if(this.dragging){this.canvas.style.zIndex="300"}}var n=function(c){return $(c).offset().left-d.offset().left};var i=function(c){return $(c).offset().top-d.offset().top};var h=n(this.handle1.element)+5;var g=i(this.handle1.element)+5;var p=n(this.handle2.element)+5;var m=i(this.handle2.element)+5;var f=100;var k=Math.min(h,p);var a=Math.max(h,p);var j=Math.min(g,m);var t=Math.max(g,m);var b=Math.min(Math.max(Math.abs(t-j)/2,100),300);var o=k-f;var s=j-f;var q=a
-k+2*f;var l=t-j+2*f;this.canvas.style.left=o+"px";this.canvas.style.top=s+"px";this.canvas.setAttribute("width",q);this.canvas.setAttribute("height",l);h-=o;g-=s;p-=o;m-=s;var r=this.canvas.getContext("2d");r.lineCap="round";r.strokeStyle=this.outer_color;r.lineWidth=7;r.beginPath();r.moveTo(h,g);r.bezierCurveTo(h+b,g,p-b,m,p,m);r.stroke();r.strokeStyle=this.inner_color;r.lineWidth=5;r.beginPath();r.moveTo(h,g);r.bezierCurveTo(h+b,g,p-b,m,p,m);r.stroke()}});function Node(a){this.element=a;this.input_terminals={};this.output_terminals={};this.tool_errors={}}$.extend(Node.prototype,{enable_input_terminal:function(d,a,b){var c=this;$(d).each(function(){var f=this.terminal=new InputTerminal(this,b);f.node=c;f.name=a;$(this).bind("dropstart",function(g){g.dragProxy.terminal.connectors[0].inner_color="#BBFFBB"}).bind("dropend",function(g){g.dragProxy.terminal.connectors[0].inner_color="#FFFFFF"}).bind("drop",function(g){(new Connector(g.dragTarget.terminal,g.dropTarget.terminal))
.redraw()}).bind("hover",function(){if(f.connectors.length>0){var g=$("<div class='callout'></div>").css({display:"none"}).appendTo("body").append($("<div class='buttons'></div>").append($("<img src='../images/delete_icon.png' />").click(function(){$.each(f.connectors,function(i,h){h.destroy()});g.remove()}))).bind("mouseleave",function(){$(this).remove()});g.css({top:$(this).offset().top-2,left:$(this).offset().left-g.width(),"padding-right":$(this).width()}).show()}});c.input_terminals[a]=f})},enable_output_terminal:function(d,a,b){var c=this;$(d).each(function(){var g=this;var f=this.terminal=new OutputTerminal(this,b);f.node=c;f.name=a;$(this).bind("dragstart",function(j){var i=$('<div class="drag-terminal" style="position: absolute;"></div>').appendTo("#canvas-container").get(0);i.terminal=new OutputTerminal(i);var k=new Connector();k.dragging=true;k.connect(this.terminal,i.terminal);$.dropManage({filter:function(h){return this.terminal.can_accept(f)}}).addClass("input-
terminal-active");return i}).bind("drag",function(i){var h=function(){var k=$(i.dragProxy).offsetParent().offset(),j=i.offsetX-k.left,l=i.offsetY-k.top;$(i.dragProxy).css({left:j,top:l});i.dragProxy.terminal.redraw();canvas_manager.update_viewport_overlay()};h();$("#canvas-container").get(0).scroll_panel.test(i,h)}).bind("dragend",function(h){h.dragProxy.terminal.connectors[0].destroy();$(h.dragProxy).remove();$.dropManage().removeClass("input-terminal-active");$("#canvas-container").get(0).scroll_panel.stop()});c.output_terminals[a]=f})},redraw:function(){$.each(this.input_terminals,function(a,b){b.redraw()});$.each(this.output_terminals,function(a,b){b.redraw()})},destroy:function(){$.each(this.input_terminals,function(a,b){b.destroy()});$.each(this.output_terminals,function(a,b){b.destroy()});workflow.remove_node(this);$(this.element).remove()},make_active:function(){$(this.element).addClass("toolForm-active")},make_inactive:function(){var a=this.element.get(0);(function(
b){b.removeChild(a);b.appendChild(a)})(a.parentNode);$(a).removeClass("toolForm-active")},init_field_data:function(g){var d=this.element;if(g.type){this.type=g.type}this.name=g.name;this.form_html=g.form_html;this.tool_state=g.tool_state;this.tool_errors=g.tool_errors;this.tooltip=g.tooltip?g.tooltip:"";this.annotation=g.annotation;this.post_job_actions=g.post_job_actions;if(this.tool_errors){d.addClass("tool-node-error")}else{d.removeClass("tool-node-error")}var c=this;var a=d.find(".toolFormBody");a.find("div").remove();var h=$("<div class='inputs'></div>").appendTo(a);$.each(g.data_inputs,function(j,b){var f=$("<div class='terminal input-terminal'></div>");c.enable_input_terminal(f,b.name,b.extensions);h.append($("<div class='form-row dataRow input-data-row' name='"+b.name+"'>"+b.label+"</div>").prepend(f))});if((g.data_inputs.length>0)&&(g.data_outputs.length>0)){a.append($("<div class='rule'></div>"))}$.each(g.data_outputs,function(k,b){var j=$("<div class='terminal out
put-terminal'></div>");c.enable_output_terminal(j,b.name,b.extensions);var f=b.name;if(b.extensions.indexOf("input")<0){f=f+" ("+b.extensions+")"}a.append($("<div class='form-row dataRow'>"+f+"</div>").append(j))});workflow.node_changed(this)},update_field_data:function(f){var c=$(this.element),d=this;this.tool_state=f.tool_state;this.form_html=f.form_html;this.tool_errors=f.tool_errors;this.annotation=f.annotation;this.post_job_actions=$.parseJSON(f.post_job_actions);if(this.tool_errors){c.addClass("tool-node-error")}else{c.removeClass("tool-node-error")}var g=c.find("div.inputs");var b=$("<div class='inputs'></div>");var a=g.find("div.input-data-row");$.each(f.data_inputs,function(k,h){var j=$("<div class='terminal input-terminal'></div>");d.enable_input_terminal(j,h.name,h.extensions);g.find("div[name="+h.name+"]").each(function(){$(this).find(".input-terminal").each(function(){var i=this.terminal.connectors[0];if(i){j[0].terminal.connectors[0]=i;i.handle2=j[0].terminal}}
);$(this).remove()});b.append($("<div class='form-row dataRow input-data-row' name='"+h.name+"'>"+h.label+"</div>").prepend(j))});g.replaceWith(b);g.find("div.input-data-row > .terminal").each(function(){this.terminal.destroy()});this.changed();this.redraw()},error:function(d){var a=$(this.element).find(".toolFormBody");a.find("div").remove();var c="<div style='color: red; text-style: italic;'>"+d+"</div>";this.form_html=c;a.html(c);workflow.node_changed(this)},changed:function(){workflow.node_changed(this)}});function Workflow(a){this.canvas_container=a;this.id_counter=0;this.nodes={};this.name=null;this.has_changes=false;this.active_form_has_changes=false}$.extend(Workflow.prototype,{add_node:function(a){a.id=this.id_counter;a.element.attr("id","wf-node-step-"+a.id);this.id_counter++;this.nodes[a.id]=a;this.has_changes=true;a.workflow=this},remove_node:function(a){if(this.active_node==a){this.clear_active_node()}delete this.nodes[a.id];this.has_changes=true},remove_all:fun
ction(){wf=this;$.each(this.nodes,function(b,a){a.destroy();wf.remove_node(a)})},to_simple:function(){var a={};$.each(this.nodes,function(c,f){var g={};$.each(f.input_terminals,function(h,i){g[i.name]=null;$.each(i.connectors,function(j,k){g[i.name]={id:k.handle1.node.id,output_name:k.handle1.name}})});var b={};if(f.post_job_actions){$.each(f.post_job_actions,function(j,h){var k={job_id:h.id,action_type:h.action_type,output_name:h.output_name,action_arguments:h.action_arguments};b[h.type+h.output_name]=null;b[h.type+h.output_name]=k})}var d={id:f.id,type:f.type,tool_id:f.tool_id,tool_state:f.tool_state,tool_errors:f.tool_errors,input_connections:g,position:$(f.element).position(),annotation:f.annotation,post_job_actions:f.post_job_actions};a[f.id]=d});return{steps:a}},from_simple:function(a){wf=this;var b=0;wf.name=a.name;$.each(a.steps,function(f,d){var c=prebuild_node("tool",d.name,d.tool_id);c.init_field_data(d);if(d.position){c.element.css({top:d.position.top,left:d.posi
tion.left})}c.id=d.id;wf.nodes[c.id]=c;b=Math.max(b,parseInt(f))});wf.id_counter=b+1;$.each(a.steps,function(f,d){var c=wf.nodes[f];$.each(d.input_connections,function(h,g){if(g){var i=wf.nodes[g.id];var j=new Connector();j.connect(i.output_terminals[g.output_name],c.input_terminals[h]);j.redraw()}})})},check_changes_in_active_form:function(){if(this.active_form_has_changes){this.has_changes=true;$("#right-content").find("form").submit();this.active_form_has_changes=false}},clear_active_node:function(){if(this.active_node){this.active_node.make_inactive();this.active_node=null}parent.show_form_for_tool("<div>No node selected</div>")},activate_node:function(a){if(this.active_node!=a){this.check_changes_in_active_form();this.clear_active_node();parent.show_form_for_tool(a.form_html+a.tooltip,a);a.make_active();this.active_node=a}},node_changed:function(a){this.has_changes=true;if(this.active_node==a){this.check_changes_in_active_form();parent.show_form_for_tool(a.form_html+a.t
ooltip,a)}},layout:function(){this.check_changes_in_active_form();this.has_changes=true;var i={};var b={};$.each(this.nodes,function(l,k){if(i[l]===undefined){i[l]=0}if(b[l]===undefined){b[l]=[]}});$.each(this.nodes,function(l,k){$.each(k.input_terminals,function(m,n){$.each(n.connectors,function(p,q){var o=q.handle1.node;i[k.id]+=1;b[o.id].push(k.id)})})});node_ids_by_level=[];while(true){level_parents=[];for(var a in i){if(i[a]==0){level_parents.push(a)}}if(level_parents.length==0){break}node_ids_by_level.push(level_parents);for(var f in level_parents){var j=level_parents[f];delete i[j];for(var g in b[j]){i[b[j][g]]-=1}}}if(i.length){return}var d=this.nodes;var h=80;v_pad=30;var c=h;$.each(node_ids_by_level,function(k,l){l.sort(function(p,o){return $(d[p].element).position().top-$(d[o].element).position().top});var m=0;var n=v_pad;$.each(l,function(o,r){var q=d[r];var p=$(q.element);$(p).css({top:n,left:c});m=Math.max(m,$(p).width());n+=$(p).height()+v_pad});c+=m+h});$.eac
h(d,function(k,l){l.redraw()})},bounds_for_all_nodes:function(){var d=Infinity,b=-Infinity,c=Infinity,a=-Infinity,f;$.each(this.nodes,function(h,g){e=$(g.element);f=e.position();d=Math.min(d,f.left);b=Math.max(b,f.left+e.width());c=Math.min(c,f.top);a=Math.max(a,f.top+e.width())});return{xmin:d,xmax:b,ymin:c,ymax:a}},fit_canvas_to_nodes:function(){var a=this.bounds_for_all_nodes();var f=this.canvas_container.position();var i=this.canvas_container.parent();var d=fix_delta(a.xmin,100);var h=fix_delta(a.ymin,100);d=Math.max(d,f.left);h=Math.max(h,f.top);var c=f.left-d;var g=f.top-h;var b=round_up(a.xmax+100,100)+d;var j=round_up(a.ymax+100,100)+h;b=Math.max(b,-c+i.width());j=Math.max(j,-g+i.height());this.canvas_container.css({left:c,top:g,width:b,height:j});this.canvas_container.children().each(function(){var k=$(this).position();$(this).css("left",k.left+d);$(this).css("top",k.top+h)})}});function fix_delta(a,b){if(a<b||a>3*b){new_pos=(Math.ceil(((a%b))/b)+1)*b;return(-(a-new
_pos))}return 0}function round_up(a,b){return Math.ceil(a/b)*b}function prebuild_node(l,j,r){var i=$("<div class='toolForm toolFormInCanvas'></div>");var g=new Node(i);g.type=l;if(l=="tool"){g.tool_id=r}var n=$("<div class='toolFormTitle unselectable'>"+j+"</div>");i.append(n);i.css("left",$(window).scrollLeft()+20);i.css("top",$(window).scrollTop()+20);var m=$("<div class='toolFormBody'></div>");var h="<div><img height='16' align='middle' src='../images/loading_small_white_bg.gif'/> loading tool info...</div>";m.append(h);g.form_html=h;i.append(m);var k=$("<div class='buttons' style='float: right;'></div>");k.append($("<img src='../images/delete_icon.png' />").click(function(b){g.destroy()}).hover(function(){$(this).attr("src","../images/delete_icon_dark.png")},function(){$(this).attr("src","../images/delete_icon.png")}));i.appendTo("#canvas-container");var d=$("#canvas-container").position();var c=$("#canvas-container").parent();var a=i.width();var q=i.height();i.css({left
:(-d.left)+(c.width()/2)-(a/2),top:(-d.top)+(c.height()/2)-(q/2)});k.prependTo(n);a+=(k.width()+10);i.css("width",a);$(i).bind("dragstart",function(){workflow.activate_node(g)}).bind("dragend",function(){workflow.node_changed(this);workflow.fit_canvas_to_nodes();canvas_manager.draw_overview()}).bind("dragclickonly",function(){workflow.activate_node(g)}).bind("drag",function(o){var f=$(this).offsetParent().offset(),b=o.offsetX-f.left,p=o.offsetY-f.top;$(this).css({left:b,top:p});$(this).find(".terminal").each(function(){this.terminal.redraw()})});return g}var ext_to_type=null;var type_to_type=null;function issubtype(b,a){b=ext_to_type[b];a=ext_to_type[a];return(type_to_type[b])&&(a in type_to_type[b])}function populate_datatype_info(a){ext_to_type=a.ext_to_class_name;type_to_type=a.class_to_classes}function ScrollPanel(a){this.panel=a}$.extend(ScrollPanel.prototype,{test:function(v,d){clearTimeout(this.timeout);var k=v.pageX,j=v.pageY,l=$(this.panel),c=l.position(),b=l.width(
),i=l.height(),w=l.parent(),s=w.width(),a=w.height(),r=w.offset(),p=r.left,m=r.top,A=p+w.width(),u=m+w.height(),B=-(b-(s/2)),z=-(i-(a/2)),g=(s/2),f=(a/2),h=false,q=5,o=23;if(k-q<p){if(c.left<g){var n=Math.min(o,g-c.left);l.css("left",c.left+n);h=true}}else{if(k+q>A){if(c.left>B){var n=Math.min(o,c.left-B);l.css("left",c.left-n);h=true}}else{if(j-q<m){if(c.top<f){var n=Math.min(o,f-c.top);l.css("top",c.top+n);h=true}}else{if(j+q>u){if(c.top>z){var n=Math.min(o,c.top-B);l.css("top",(c.top-n)+"px");h=true}}}}}if(h){d();var l=this;this.timeout=setTimeout(function(){l.test(v,d)},50)}},stop:function(b,a){clearTimeout(this.timeout)}});function CanvasManager(b,a){this.cv=b;this.cc=this.cv.find("#canvas-container");this.oc=a.find("#overview-canvas");this.ov=a.find("#overview-viewport");this.init_drag()}$.extend(CanvasManager.prototype,{init_drag:function(){var b=this;var a=function(f,g){f=Math.min(f,b.cv.width()/2);f=Math.max(f,-b.cc.width()+b.cv.width()/2);g=Math.min(g,b.cv.height()
/2);g=Math.max(g,-b.cc.height()+b.cv.height()/2);b.cc.css({left:f,top:g});b.update_viewport_overlay()};this.cc.each(function(){this.scroll_panel=new ScrollPanel(this)});var d,c;this.cv.bind("dragstart",function(g){var h=$(this).offset();var f=b.cc.position();c=f.top-h.top;d=f.left-h.left}).bind("drag",function(f){a(f.offsetX+d,f.offsetY+c)}).bind("dragend",function(){workflow.fit_canvas_to_nodes();b.draw_overview()});this.ov.bind("drag",function(k){var j=b.cc.width(),g=b.cc.height(),f=b.oc.width(),h=b.oc.height(),i=$(this).offsetParent().offset(),m=k.offsetX-i.left,l=k.offsetY-i.top;a(-(m/f*j),-(l/h*g))}).bind("dragend",function(){workflow.fit_canvas_to_nodes();b.draw_overview()});$("#overview-border").bind("drag",function(g){var i=$(this).offsetParent();var h=i.offset();var f=Math.max(i.width()-(g.offsetX-h.left),i.height()-(g.offsetY-h.top));$(this).css({width:f,height:f});b.draw_overview()});$("#overview-border div").bind("drag",function(f){})},update_viewport_overlay:fun
ction(){var b=this.cc,f=this.cv,a=this.oc,c=this.ov,d=b.width(),j=b.height(),i=a.width(),g=a.height(),h=b.position();c.css({left:-(h.left/d*i),top:-(h.top/j*g),width:(f.width()/d*i)-2,height:(f.height()/j*g)-2})},draw_overview:function(){var j=$("#overview-canvas"),m=j.parent().parent().width(),i=j.get(0).getContext("2d"),d=$("#canvas-container").width(),l=$("#canvas-container").height();var g,a,k,f;var h=this.cv.width();var b=this.cv.height();if(d<h&&l<b){k=d/h*m;f=(m-k)/2;g=l/b*m;a=(m-g)/2}else{if(d<l){a=0;g=m;k=Math.ceil(g*d/l);f=(m-k)/2}else{k=m;f=0;g=Math.ceil(k*l/d);a=(m-g)/2}}j.parent().css({left:f,top:a,width:k,height:g});j.attr("width",k);j.attr("height",g);i.fillStyle="#D2C099";i.strokeStyle="#D8B365";i.lineWidth=1;$.each(workflow.nodes,function(t,q){var s=$(q.element),n=s.position(),c=n.left/d*k,r=n.top/l*g,o=s.width()/d*k,p=s.height()/l*g;i.fillRect(c,r,o,p);i.strokeRect(c,r,o,p)});this.update_viewport_overlay()}});
+function Terminal(a){this.element=a;this.connectors=[]}$.extend(Terminal.prototype,{connect:function(a){this.connectors.push(a);if(this.node){this.node.changed()}},disconnect:function(a){this.connectors.splice($.inArray(a,this.connectors),1);if(this.node){this.node.changed()}},redraw:function(){$.each(this.connectors,function(a,b){b.redraw()})},destroy:function(){$.each(this.connectors.slice(),function(a,b){b.destroy()})}});function OutputTerminal(a,b){Terminal.call(this,a);this.datatypes=b}OutputTerminal.prototype=new Terminal();function InputTerminal(a,b){Terminal.call(this,a);this.datatypes=b}InputTerminal.prototype=new Terminal();$.extend(InputTerminal.prototype,{can_accept:function(a){if(this.connectors.length<1){for(var c in this.datatypes){for(var b in a.datatypes){if(a.datatypes[b]=="input"||issubtype(a.datatypes[b],this.datatypes[c])){return true}}}}return false}});function Connector(b,a){this.canvas=null;this.dragging=false;this.inner_color="#FFFFFF";this.outer_col
or="#D8B365";if(b&&a){this.connect(b,a)}}$.extend(Connector.prototype,{connect:function(b,a){this.handle1=b;this.handle1.connect(this);this.handle2=a;this.handle2.connect(this)},destroy:function(){if(this.handle1){this.handle1.disconnect(this)}if(this.handle2){this.handle2.disconnect(this)}$(this.canvas).remove()},redraw:function(){var d=$("#canvas-container");if(!this.canvas){this.canvas=document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(this.canvas)}d.append($(this.canvas));if(this.dragging){this.canvas.style.zIndex="300"}}var n=function(c){return $(c).offset().left-d.offset().left};var i=function(c){return $(c).offset().top-d.offset().top};var h=n(this.handle1.element)+5;var g=i(this.handle1.element)+5;var p=n(this.handle2.element)+5;var m=i(this.handle2.element)+5;var f=100;var k=Math.min(h,p);var a=Math.max(h,p);var j=Math.min(g,m);var t=Math.max(g,m);var b=Math.min(Math.max(Math.abs(t-j)/2,100),300);var o=k-f;var s=j-f;var q=a
-k+2*f;var l=t-j+2*f;this.canvas.style.left=o+"px";this.canvas.style.top=s+"px";this.canvas.setAttribute("width",q);this.canvas.setAttribute("height",l);h-=o;g-=s;p-=o;m-=s;var r=this.canvas.getContext("2d");r.lineCap="round";r.strokeStyle=this.outer_color;r.lineWidth=7;r.beginPath();r.moveTo(h,g);r.bezierCurveTo(h+b,g,p-b,m,p,m);r.stroke();r.strokeStyle=this.inner_color;r.lineWidth=5;r.beginPath();r.moveTo(h,g);r.bezierCurveTo(h+b,g,p-b,m,p,m);r.stroke()}});function Node(a){this.element=a;this.input_terminals={};this.output_terminals={};this.tool_errors={}}$.extend(Node.prototype,{enable_input_terminal:function(d,a,b){var c=this;$(d).each(function(){var f=this.terminal=new InputTerminal(this,b);f.node=c;f.name=a;$(this).bind("dropstart",function(g){g.dragProxy.terminal.connectors[0].inner_color="#BBFFBB"}).bind("dropend",function(g){g.dragProxy.terminal.connectors[0].inner_color="#FFFFFF"}).bind("drop",function(g){(new Connector(g.dragTarget.terminal,g.dropTarget.terminal))
.redraw()}).bind("hover",function(){if(f.connectors.length>0){var g=$("<div class='callout'></div>").css({display:"none"}).appendTo("body").append($("<div class='buttons'></div>").append($("<img/>").attr("src",image_path+"/delete_icon.png").click(function(){$.each(f.connectors,function(i,h){h.destroy()});g.remove()}))).bind("mouseleave",function(){$(this).remove()});g.css({top:$(this).offset().top-2,left:$(this).offset().left-g.width(),"padding-right":$(this).width()}).show()}});c.input_terminals[a]=f})},enable_output_terminal:function(d,a,b){var c=this;$(d).each(function(){var g=this;var f=this.terminal=new OutputTerminal(this,b);f.node=c;f.name=a;$(this).bind("dragstart",function(j){var i=$('<div class="drag-terminal" style="position: absolute;"></div>').appendTo("#canvas-container").get(0);i.terminal=new OutputTerminal(i);var k=new Connector();k.dragging=true;k.connect(this.terminal,i.terminal);$.dropManage({filter:function(h){return this.terminal.can_accept(f)}}).addClas
s("input-terminal-active");return i}).bind("drag",function(i){var h=function(){var k=$(i.dragProxy).offsetParent().offset(),j=i.offsetX-k.left,l=i.offsetY-k.top;$(i.dragProxy).css({left:j,top:l});i.dragProxy.terminal.redraw();canvas_manager.update_viewport_overlay()};h();$("#canvas-container").get(0).scroll_panel.test(i,h)}).bind("dragend",function(h){h.dragProxy.terminal.connectors[0].destroy();$(h.dragProxy).remove();$.dropManage().removeClass("input-terminal-active");$("#canvas-container").get(0).scroll_panel.stop()});c.output_terminals[a]=f})},redraw:function(){$.each(this.input_terminals,function(a,b){b.redraw()});$.each(this.output_terminals,function(a,b){b.redraw()})},destroy:function(){$.each(this.input_terminals,function(a,b){b.destroy()});$.each(this.output_terminals,function(a,b){b.destroy()});workflow.remove_node(this);$(this.element).remove()},make_active:function(){$(this.element).addClass("toolForm-active")},make_inactive:function(){var a=this.element.get(0);(
function(b){b.removeChild(a);b.appendChild(a)})(a.parentNode);$(a).removeClass("toolForm-active")},init_field_data:function(g){var d=this.element;if(g.type){this.type=g.type}this.name=g.name;this.form_html=g.form_html;this.tool_state=g.tool_state;this.tool_errors=g.tool_errors;this.tooltip=g.tooltip?g.tooltip:"";this.annotation=g.annotation;this.post_job_actions=g.post_job_actions;this.workflow_outputs=g.workflow_outputs;if(this.tool_errors){d.addClass("tool-node-error")}else{d.removeClass("tool-node-error")}var c=this;var a=d.find(".toolFormBody");a.find("div").remove();var h=$("<div class='inputs'></div>").appendTo(a);$.each(g.data_inputs,function(j,b){var f=$("<div class='terminal input-terminal'></div>");c.enable_input_terminal(f,b.name,b.extensions);h.append($("<div class='form-row dataRow input-data-row' name='"+b.name+"'>"+b.label+"</div>").prepend(f))});if((g.data_inputs.length>0)&&(g.data_outputs.length>0)){a.append($("<div class='rule'></div>"))}$.each(g.data_outpu
ts,function(k,b){var j=$("<div class='terminal output-terminal'></div>");c.enable_output_terminal(j,b.name,b.extensions);var f=b.name;if(b.extensions.indexOf("input")<0){f=f+" ("+b.extensions+")"}a.append($("<div class='form-row dataRow'>"+f+"</div>").append(j))});workflow.node_changed(this)},update_field_data:function(f){var c=$(this.element),d=this;this.tool_state=f.tool_state;this.form_html=f.form_html;this.tool_errors=f.tool_errors;this.annotation=f.annotation;this.post_job_actions=$.parseJSON(f.post_job_actions);if(this.tool_errors){c.addClass("tool-node-error")}else{c.removeClass("tool-node-error")}var g=c.find("div.inputs");var b=$("<div class='inputs'></div>");var a=g.find("div.input-data-row");$.each(f.data_inputs,function(k,h){var j=$("<div class='terminal input-terminal'></div>");d.enable_input_terminal(j,h.name,h.extensions);g.find("div[name="+h.name+"]").each(function(){$(this).find(".input-terminal").each(function(){var i=this.terminal.connectors[0];if(i){j[0].
terminal.connectors[0]=i;i.handle2=j[0].terminal}});$(this).remove()});b.append($("<div class='form-row dataRow input-data-row' name='"+h.name+"'>"+h.label+"</div>").prepend(j))});g.replaceWith(b);g.find("div.input-data-row > .terminal").each(function(){this.terminal.destroy()});this.changed();this.redraw()},error:function(d){var a=$(this.element).find(".toolFormBody");a.find("div").remove();var c="<div style='color: red; text-style: italic;'>"+d+"</div>";this.form_html=c;a.html(c);workflow.node_changed(this)},changed:function(){workflow.node_changed(this)}});function Workflow(a){this.canvas_container=a;this.id_counter=0;this.nodes={};this.name=null;this.has_changes=false;this.active_form_has_changes=false}$.extend(Workflow.prototype,{add_node:function(a){a.id=this.id_counter;a.element.attr("id","wf-node-step-"+a.id);this.id_counter++;this.nodes[a.id]=a;this.has_changes=true;a.workflow=this},remove_node:function(a){if(this.active_node==a){this.clear_active_node()}delete this
.nodes[a.id];this.has_changes=true},remove_all:function(){wf=this;$.each(this.nodes,function(b,a){a.destroy();wf.remove_node(a)})},to_simple:function(){var a={};$.each(this.nodes,function(c,f){var g={};$.each(f.input_terminals,function(h,i){g[i.name]=null;$.each(i.connectors,function(j,k){g[i.name]={id:k.handle1.node.id,output_name:k.handle1.name}})});var b={};if(f.post_job_actions){$.each(f.post_job_actions,function(j,h){var k={job_id:h.id,action_type:h.action_type,output_name:h.output_name,action_arguments:h.action_arguments};b[h.type+h.output_name]=null;b[h.type+h.output_name]=k})}if(!f.workflow_outputs){f.workflow_outputs=[]}var d={id:f.id,type:f.type,tool_id:f.tool_id,tool_state:f.tool_state,tool_errors:f.tool_errors,input_connections:g,position:$(f.element).position(),annotation:f.annotation,post_job_actions:f.post_job_actions,workflow_outputs:f.workflow_outputs};a[f.id]=d});return{steps:a}},from_simple:function(a){wf=this;var b=0;wf.name=a.name;$.each(a.steps,function
(f,d){var c=prebuild_node("tool",d.name,d.tool_id);c.init_field_data(d);if(d.position){c.element.css({top:d.position.top,left:d.position.left})}c.id=d.id;wf.nodes[c.id]=c;b=Math.max(b,parseInt(f))});wf.id_counter=b+1;$.each(a.steps,function(f,d){var c=wf.nodes[f];$.each(d.input_connections,function(h,g){if(g){var i=wf.nodes[g.id];var j=new Connector();j.connect(i.output_terminals[g.output_name],c.input_terminals[h]);j.redraw()}})})},check_changes_in_active_form:function(){if(this.active_form_has_changes){this.has_changes=true;$("#right-content").find("form").submit();this.active_form_has_changes=false}},clear_active_node:function(){if(this.active_node){this.active_node.make_inactive();this.active_node=null}parent.show_form_for_tool("<div>No node selected</div>")},activate_node:function(a){if(this.active_node!=a){this.check_changes_in_active_form();this.clear_active_node();parent.show_form_for_tool(a.form_html+a.tooltip,a);a.make_active();this.active_node=a}},node_changed:fun
ction(a){this.has_changes=true;if(this.active_node==a){this.check_changes_in_active_form();parent.show_form_for_tool(a.form_html+a.tooltip,a)}},layout:function(){this.check_changes_in_active_form();this.has_changes=true;var i={};var b={};$.each(this.nodes,function(l,k){if(i[l]===undefined){i[l]=0}if(b[l]===undefined){b[l]=[]}});$.each(this.nodes,function(l,k){$.each(k.input_terminals,function(m,n){$.each(n.connectors,function(p,q){var o=q.handle1.node;i[k.id]+=1;b[o.id].push(k.id)})})});node_ids_by_level=[];while(true){level_parents=[];for(var a in i){if(i[a]==0){level_parents.push(a)}}if(level_parents.length==0){break}node_ids_by_level.push(level_parents);for(var f in level_parents){var j=level_parents[f];delete i[j];for(var g in b[j]){i[b[j][g]]-=1}}}if(i.length){return}var d=this.nodes;var h=80;v_pad=30;var c=h;$.each(node_ids_by_level,function(k,l){l.sort(function(p,o){return $(d[p].element).position().top-$(d[o].element).position().top});var m=0;var n=v_pad;$.each(l,fun
ction(o,r){var q=d[r];var p=$(q.element);$(p).css({top:n,left:c});m=Math.max(m,$(p).width());n+=$(p).height()+v_pad});c+=m+h});$.each(d,function(k,l){l.redraw()})},bounds_for_all_nodes:function(){var d=Infinity,b=-Infinity,c=Infinity,a=-Infinity,f;$.each(this.nodes,function(h,g){e=$(g.element);f=e.position();d=Math.min(d,f.left);b=Math.max(b,f.left+e.width());c=Math.min(c,f.top);a=Math.max(a,f.top+e.width())});return{xmin:d,xmax:b,ymin:c,ymax:a}},fit_canvas_to_nodes:function(){var a=this.bounds_for_all_nodes();var f=this.canvas_container.position();var i=this.canvas_container.parent();var d=fix_delta(a.xmin,100);var h=fix_delta(a.ymin,100);d=Math.max(d,f.left);h=Math.max(h,f.top);var c=f.left-d;var g=f.top-h;var b=round_up(a.xmax+100,100)+d;var j=round_up(a.ymax+100,100)+h;b=Math.max(b,-c+i.width());j=Math.max(j,-g+i.height());this.canvas_container.css({left:c,top:g,width:b,height:j});this.canvas_container.children().each(function(){var k=$(this).position();$(this).css("left
",k.left+d);$(this).css("top",k.top+h)})}});function fix_delta(a,b){if(a<b||a>3*b){new_pos=(Math.ceil(((a%b))/b)+1)*b;return(-(a-new_pos))}return 0}function round_up(a,b){return Math.ceil(a/b)*b}function prebuild_node(l,j,r){var i=$("<div class='toolForm toolFormInCanvas'></div>");var g=new Node(i);g.type=l;if(l=="tool"){g.tool_id=r}var n=$("<div class='toolFormTitle unselectable'>"+j+"</div>");i.append(n);i.css("left",$(window).scrollLeft()+20);i.css("top",$(window).scrollTop()+20);var m=$("<div class='toolFormBody'></div>");var h="<div><img height='16' align='middle' src='"+image_path+"/loading_small_white_bg.gif'/> loading tool info...</div>";m.append(h);g.form_html=h;i.append(m);var k=$("<div class='buttons' style='float: right;'></div>");k.append($("<img/>").attr("src",image_path+"/delete_icon.png").click(function(b){g.destroy()}).hover(function(){$(this).attr("src",image_path+"/delete_icon_dark.png")},function(){$(this).attr("src",image_path+"/delete_icon.png")}));i.ap
pendTo("#canvas-container");var d=$("#canvas-container").position();var c=$("#canvas-container").parent();var a=i.width();var q=i.height();i.css({left:(-d.left)+(c.width()/2)-(a/2),top:(-d.top)+(c.height()/2)-(q/2)});k.prependTo(n);a+=(k.width()+10);i.css("width",a);$(i).bind("dragstart",function(){workflow.activate_node(g)}).bind("dragend",function(){workflow.node_changed(this);workflow.fit_canvas_to_nodes();canvas_manager.draw_overview()}).bind("dragclickonly",function(){workflow.activate_node(g)}).bind("drag",function(o){var f=$(this).offsetParent().offset(),b=o.offsetX-f.left,p=o.offsetY-f.top;$(this).css({left:b,top:p});$(this).find(".terminal").each(function(){this.terminal.redraw()})});return g}var ext_to_type=null;var type_to_type=null;function issubtype(b,a){b=ext_to_type[b];a=ext_to_type[a];return(type_to_type[b])&&(a in type_to_type[b])}function populate_datatype_info(a){ext_to_type=a.ext_to_class_name;type_to_type=a.class_to_classes}function ScrollPanel(a){this.p
anel=a}$.extend(ScrollPanel.prototype,{test:function(v,d){clearTimeout(this.timeout);var k=v.pageX,j=v.pageY,l=$(this.panel),c=l.position(),b=l.width(),i=l.height(),w=l.parent(),s=w.width(),a=w.height(),r=w.offset(),p=r.left,m=r.top,A=p+w.width(),u=m+w.height(),B=-(b-(s/2)),z=-(i-(a/2)),g=(s/2),f=(a/2),h=false,q=5,o=23;if(k-q<p){if(c.left<g){var n=Math.min(o,g-c.left);l.css("left",c.left+n);h=true}}else{if(k+q>A){if(c.left>B){var n=Math.min(o,c.left-B);l.css("left",c.left-n);h=true}}else{if(j-q<m){if(c.top<f){var n=Math.min(o,f-c.top);l.css("top",c.top+n);h=true}}else{if(j+q>u){if(c.top>z){var n=Math.min(o,c.top-B);l.css("top",(c.top-n)+"px");h=true}}}}}if(h){d();var l=this;this.timeout=setTimeout(function(){l.test(v,d)},50)}},stop:function(b,a){clearTimeout(this.timeout)}});function CanvasManager(b,a){this.cv=b;this.cc=this.cv.find("#canvas-container");this.oc=a.find("#overview-canvas");this.ov=a.find("#overview-viewport");this.init_drag()}$.extend(CanvasManager.prototype,{
init_drag:function(){var b=this;var a=function(f,g){f=Math.min(f,b.cv.width()/2);f=Math.max(f,-b.cc.width()+b.cv.width()/2);g=Math.min(g,b.cv.height()/2);g=Math.max(g,-b.cc.height()+b.cv.height()/2);b.cc.css({left:f,top:g});b.update_viewport_overlay()};this.cc.each(function(){this.scroll_panel=new ScrollPanel(this)});var d,c;this.cv.bind("dragstart",function(g){var h=$(this).offset();var f=b.cc.position();c=f.top-h.top;d=f.left-h.left}).bind("drag",function(f){a(f.offsetX+d,f.offsetY+c)}).bind("dragend",function(){workflow.fit_canvas_to_nodes();b.draw_overview()});this.ov.bind("drag",function(k){var j=b.cc.width(),g=b.cc.height(),f=b.oc.width(),h=b.oc.height(),i=$(this).offsetParent().offset(),m=k.offsetX-i.left,l=k.offsetY-i.top;a(-(m/f*j),-(l/h*g))}).bind("dragend",function(){workflow.fit_canvas_to_nodes();b.draw_overview()});$("#overview-border").bind("drag",function(g){var i=$(this).offsetParent();var h=i.offset();var f=Math.max(i.width()-(g.offsetX-h.left),i.height()-(g
.offsetY-h.top));$(this).css({width:f,height:f});b.draw_overview()});$("#overview-border div").bind("drag",function(f){})},update_viewport_overlay:function(){var b=this.cc,f=this.cv,a=this.oc,c=this.ov,d=b.width(),j=b.height(),i=a.width(),g=a.height(),h=b.position();c.css({left:-(h.left/d*i),top:-(h.top/j*g),width:(f.width()/d*i)-2,height:(f.height()/j*g)-2})},draw_overview:function(){var j=$("#overview-canvas"),m=j.parent().parent().width(),i=j.get(0).getContext("2d"),d=$("#canvas-container").width(),l=$("#canvas-container").height();var g,a,k,f;var h=this.cv.width();var b=this.cv.height();if(d<h&&l<b){k=d/h*m;f=(m-k)/2;g=l/b*m;a=(m-g)/2}else{if(d<l){a=0;g=m;k=Math.ceil(g*d/l);f=(m-k)/2}else{k=m;f=0;g=Math.ceil(k*l/d);a=(m-g)/2}}j.parent().css({left:f,top:a,width:k,height:g});j.attr("width",k);j.attr("height",g);i.fillStyle="#D2C099";i.strokeStyle="#D8B365";i.lineWidth=1;$.each(workflow.nodes,function(t,q){var s=$(q.element),n=s.position(),c=n.left/d*k,r=n.top/l*g,o=s.width
()/d*k,p=s.height()/l*g;i.fillRect(c,r,o,p);i.strokeRect(c,r,o,p)});this.update_viewport_overlay()}});
--- a/static/scripts/galaxy.panels.js
+++ b/static/scripts/galaxy.panels.js
@@ -193,7 +193,7 @@ function show_modal( title, body, button
b.hide();
}
if ( body == "progress" ) {
- body = $( "<img src='../images/yui/rel_interstitial_loading.gif')' />" );
+ body = $("<img/>").attr("src", image_path + "/yui/rel_interstitial_loading.gif");
}
$( ".dialog-box" ).find( ".body" ).html( body );
if ( ! $(".dialog-box-container").is( ":visible" ) ) {
--- a/static/scripts/galaxy.workflow_editor.canvas.js
+++ b/static/scripts/galaxy.workflow_editor.canvas.js
@@ -174,7 +174,7 @@ function Node( element ) {
.appendTo( "body" )
.append(
$("<div class='buttons'></div>").append(
- $("<img src='../images/delete_icon.png' />").click( function() {
+ $("<img/>").attr("src", image_path + '/delete_icon.png').click( function() {
$.each( terminal.connectors, function( _, x ) {
x.destroy();
});
@@ -648,18 +648,18 @@ function prebuild_node( type, title_text
f.append( title );
f.css( "left", $(window).scrollLeft() + 20 ); f.css( "top", $(window).scrollTop() + 20 );
var b = $("<div class='toolFormBody'></div>");
- var tmp = "<div><img height='16' align='middle' src='../images/loading_small_white_bg.gif'/> loading tool info...</div>";
+ var tmp = "<div><img height='16' align='middle' src='" +image_path+ "/loading_small_white_bg.gif'/> loading tool info...</div>";
b.append( tmp );
node.form_html = tmp;
f.append( b );
// Fix width to computed width
// Now add floats
var buttons = $("<div class='buttons' style='float: right;'></div>");
- buttons.append( $("<img src='../images/delete_icon.png' />").click( function( e ) {
+ buttons.append( $("<img/>").attr("src", image_path + '/delete_icon.png').click( function( e ) {
node.destroy();
} ).hover(
- function() { $(this).attr( 'src', "../images/delete_icon_dark.png" ); },
- function() { $(this).attr( 'src', "../images/delete_icon.png" ); }
+ function() { $(this).attr( "src", image_path + "/delete_icon_dark.png" ); },
+ function() { $(this).attr( "src", image_path + "/delete_icon.png" ); }
) );
// Place inside container
f.appendTo( "#canvas-container" );
1
0

galaxy-dist commit 31fe9ca3a088: Zero out optional metadata when file size exceeds max_optional_metadata_filesize cut off. Fixes a bug where an output which has metadata copied to it from an input would erroneously retain the input's value.
by commits-noreply@bitbucket.org 08 Sep '10
by commits-noreply@bitbucket.org 08 Sep '10
08 Sep '10
# HG changeset patch -- Bitbucket.org
# Project galaxy-dist
# URL http://bitbucket.org/galaxy/galaxy-dist/overview
# User Dan Blankenberg <dan(a)bx.psu.edu>
# Date 1282330290 14400
# Node ID 31fe9ca3a08849ac0160e7e25033487030babec0
# Parent 4464d55104b8a33407bf03d822612afd4a679eb0
Zero out optional metadata when file size exceeds max_optional_metadata_filesize cut off. Fixes a bug where an output which has metadata copied to it from an input would erroneously retain the input's value.
--- a/lib/galaxy/datatypes/sequence.py
+++ b/lib/galaxy/datatypes/sequence.py
@@ -151,6 +151,8 @@ class csFasta( Sequence ):
def set_meta( self, dataset, **kwd ):
if self.max_optional_metadata_filesize >= 0 and dataset.get_size() > self.max_optional_metadata_filesize:
+ dataset.metadata.data_lines = None
+ dataset.metadata.sequences = None
return
return Sequence.set_meta( self, dataset, **kwd )
@@ -164,6 +166,8 @@ class Fastq ( Sequence ):
in dataset.
"""
if self.max_optional_metadata_filesize >= 0 and dataset.get_size() > self.max_optional_metadata_filesize:
+ dataset.metadata.data_lines = None
+ dataset.metadata.sequences = None
return
data_lines = 0
sequences = 0
--- a/lib/galaxy/datatypes/qualityscore.py
+++ b/lib/galaxy/datatypes/qualityscore.py
@@ -66,6 +66,7 @@ class QualityScoreSOLiD ( QualityScore )
def set_meta( self, dataset, **kwd ):
if self.max_optional_metadata_filesize >= 0 and dataset.get_size() > self.max_optional_metadata_filesize:
+ dataset.metadata.data_lines = None
return
return QualityScore.set_meta( self, dataset, **kwd )
1
0

galaxy-dist commit 6358247a4559: Job running: When finishing jobs, don't flush until all datasets have finished processing. Otherwise, the terminal job state is set once the first dataset is processed, and if the runner restarts, remaining datasets will not be processed.
by commits-noreply@bitbucket.org 08 Sep '10
by commits-noreply@bitbucket.org 08 Sep '10
08 Sep '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 1282333327 14400
# Node ID 6358247a4559c9ec757484e16c618a831711fbc9
# Parent 8242280e5c74d1fb60daa12f2ddb37cc06bc7e75
Job running: When finishing jobs, don't flush until all datasets have finished processing. Otherwise, the terminal job state is set once the first dataset is processed, and if the runner restarts, remaining datasets will not be processed.
--- a/lib/galaxy/jobs/__init__.py
+++ b/lib/galaxy/jobs/__init__.py
@@ -523,7 +523,6 @@ class JobWrapper( object ):
if dataset.ext == 'auto':
dataset.extension = 'txt'
self.sa_session.add( dataset )
- self.sa_session.flush()
if context['stderr']:
dataset_assoc.dataset.dataset.state = model.Dataset.states.ERROR
else:
@@ -535,6 +534,10 @@ class JobWrapper( object ):
# panel stops checking for updates. So allow the
# self.sa_session.flush() at the bottom of this method set
# the state instead.
+
+ # Flush all the dataset and job changes above. Dataset state changes
+ # will now be seen by the user.
+ self.sa_session.flush()
# Save stdout and stderr
if len( stdout ) > 32768:
1
0

galaxy-dist commit 8a3d3fba0370: Issue # 352: Set content type of HistoryController.list_as_xml to be text/xml
by commits-noreply@bitbucket.org 08 Sep '10
by commits-noreply@bitbucket.org 08 Sep '10
08 Sep '10
# HG changeset patch -- Bitbucket.org
# Project galaxy-dist
# URL http://bitbucket.org/galaxy/galaxy-dist/overview
# User Greg Von Kuster <greg(a)bx.psu.edu>
# Date 1282334161 14400
# Node ID 8a3d3fba037061a818b4417978542ae7b71f2e1a
# Parent 6358247a4559c9ec757484e16c618a831711fbc9
Issue # 352: Set content type of HistoryController.list_as_xml to be text/xml
Issue # 353: Add additional history attributes to the <history> tag in the ~/templates/root/history_as_xml.mako template
--- a/templates/root/history_as_xml.mako
+++ b/templates/root/history_as_xml.mako
@@ -1,5 +1,5 @@
<?xml version="1.0"?>
-<history>
+<history id="${trans.security.encode_id( history.id )}" num="${len(history.datasets)}" name="${history.name}" create="${history.create_time}" update="${history.update_time}">
%if show_deleted:
%for data in history.activatable_datasets:
<data id="${data.id}" hid="${data.hid}" name="${data.name}" state="${data.state}" dbkey="${data.dbkey}">
--- a/lib/galaxy/web/controllers/history.py
+++ b/lib/galaxy/web/controllers/history.py
@@ -155,6 +155,7 @@ class HistoryController( BaseController,
@web.expose
def list_as_xml( self, trans ):
"""XML history list for functional tests"""
+ trans.response.set_content_type( 'text/xml' )
return trans.fill_template( "/history/list_as_xml.mako" )
stored_list_grid = HistoryListGrid()
1
0

galaxy-dist commit 4464d55104b8: Updated column join to handle situation when last column is a join column and a row is missing that column
by commits-noreply@bitbucket.org 08 Sep '10
by commits-noreply@bitbucket.org 08 Sep '10
08 Sep '10
# HG changeset patch -- Bitbucket.org
# Project galaxy-dist
# URL http://bitbucket.org/galaxy/galaxy-dist/overview
# User Kelly Vincent <kpvincent(a)bx.psu.edu>
# Date 1282329639 14400
# Node ID 4464d55104b8a33407bf03d822612afd4a679eb0
# Parent d9e099daa8279880d5e054680ab28e8fc3064f77
Updated column join to handle situation when last column is a join column and a row is missing that column
--- a/tools/new_operations/column_join.py
+++ b/tools/new_operations/column_join.py
@@ -208,7 +208,8 @@ def __main__():
hinges = [ h for h in hinges if h ]
current, loc = hinges[0], hinge_dict[ hinges[0] ]
# first output empty columns for vertical alignment (account for "missing" files)
- # write output if trailing empty columns
+ # write output for leading and trailing empty columns
+ # columns missing from actual file handled further below
current_data = []
if current != old_current:
# fill trailing empty columns with appropriate fill value
@@ -244,17 +245,25 @@ def __main__():
split_line.append( item )
else:
split_line.append( fill_empty[ i + 1 ] )
+ # add actual data to be output below
if ''.join( split_line ):
- # add actual data to be output below
for col in cols:
if col > hinge:
- current_data.append( split_line[ col - 1 ] )
+ # if this column doesn't exist, add the appropriate filler or empty column
+ try:
+ new_item = split_line[ col - 1 ]
+ except IndexError:
+ if fill_empty:
+ new_item = fill_empty[ col ]
+ else:
+ new_item = ''
+ current_data.append( new_item )
# grab next line for selected file
current_lines[ loc ] = tmp_input_files[ loc ].readline().rstrip( '\r\n' )
# write relevant data to file
- if current == old_current:
+ if current == old_current and current_data:
fout.write( '%s%s' % ( delimiter, delimiter.join( current_data ) ) )
- else:
+ elif current_data:
fout.write( '%s%s%s' % ( current, delimiter, delimiter.join( current_data ) ) )
last_loc = loc
old_current = current
--- a/tools/new_operations/column_join.xml
+++ b/tools/new_operations/column_join.xml
@@ -116,17 +116,29 @@ import simplejson
<param name="input" value="column_join_in12.pileup" ftype="pileup" /><output name="output" file="column_join_out4.pileup" ftype="tabular" /></test>
- </tests>
+ <test>
+ <!-- Test for handling missing column -->
+ <param name="input1" value="column_join_in13.tabular" ftype="tabular" />
+ <param name="hinge" value="1" />
+ <param name="columns" value="5" />
+ <param name="fill_empty_columns_switch" value="fill_empty" />
+ <param name="column_fill_type" value="single_fill_value" />
+ <param name="fill_value" value="0" />
+ <param name="input2" value="column_join_in14.tabular" ftype="tabular" />
+ <param name="input" value="column_join_in15.tabular" ftype="tabular" />
+ <output name="output" file="column_join_out5.tabular" ftype="tabular" />
+ </test>
+ </tests><help>
**What it does**
This tool allows you to join several files with the same column structure into one file, removing certain columns if necessary. The user needs to select a 'hinge', which is the number of left-most columns to match on. They also need to select the columns to include in the join, which should include the hinge columns, too.
-Note that the files are expected to have the same number of columns.
+Note that the files are expected to have the same number of columns. If for some reason the join column is missing (this only applies to the last column(s)), the tool attempts to handle this situation by inserting an empty item (or the appropriate filler) for that column on that row. This could lead to the situation where a row has a hinge but entirely empty or filled columns, if the hinge exists in at least one file but every file that has it is missing the join column. Also, note that the tool does not distinguish between a file missing the hinge altogether and a file having the hinge but missing the column (in both cases the column would be empty or filled). There is an example of this below.
-----
-**Example**
+**General Example**
Given the following files::
@@ -213,6 +225,36 @@ To join on columns 3 and 4 combining on
chr2 83 T 8
chr2 84 A 9
+**Example with missing columns**
+
+Given the following input files::
+
+ FILE 1
+ 1 A
+ 2 B b
+ 4 C c
+ 5 D
+ 6 E e
+
+ FILE 2
+ 1 M m
+ 2 N
+ 3 O o
+ 4 P p
+ 5 Q
+ 7 R r
+
+if we join only column 3 using column 1 as the hinge and with a fill value of '0', this is what will be output::
+
+ 1 0 m
+ 2 b 0
+ 3 0 o
+ 4 c p
+ 5 0 0
+ 6 e 0
+ 7 0 r
+
+Row 5 appears in both files with the missing column, so it's got nothing but fill values in the output file.
</help></tool>
1
0

galaxy-dist commit 368956bcef26: Standardize mouseover behavior for UI tabs.
by commits-noreply@bitbucket.org 08 Sep '10
by commits-noreply@bitbucket.org 08 Sep '10
08 Sep '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 1283444597 14400
# Node ID 368956bcef26af16b4f7694fb8f81fb6152cf6de
# Parent 833cfa90b33735f4f30f10d0d7e39cbf1a64d6d9
Standardize mouseover behavior for UI tabs.
--- a/templates/webapps/galaxy/base_panels.mako
+++ b/templates/webapps/galaxy/base_panels.mako
@@ -30,7 +30,7 @@
%if href:
<a target="${target}" href="${href}">${display}</a>
%else:
- ${display}
+ <a>${display}</a>
%endif
%if menu_options:
<div class="submenu">
1
0

galaxy-dist commit f09915c8da94: Library template improvements and miscellaneous fixes:
by commits-noreply@bitbucket.org 08 Sep '10
by commits-noreply@bitbucket.org 08 Sep '10
08 Sep '10
# HG changeset patch -- Bitbucket.org
# Project galaxy-dist
# URL http://bitbucket.org/galaxy/galaxy-dist/overview
# User Greg Von Kuster <greg(a)bx.psu.edu>
# Date 1283450357 14400
# Node ID f09915c8da9404b8642b96ee81d89afdccde8414
# Parent 121678c8a483061c531c37c8d2e398ae1baa315a
Library template improvements and miscellaneous fixes:
1. Add support for handling inherited library temnplates that include all supported field types ( AddressField, CheckboxField, SelectField, TextArea, TextField, WorkflowField ) to the upload form for library datasets. New userAddress objects can now be created on the upload forms.
2. Improve the UI for selecting tempaltes for library items - it is now clear that the displayed template is not useable since it is disabled and a message is displayed.
3. Automatically inherit template contents from parent for inherited templates.
4. Fix the AddressField UI to display the required fields for rendered html.
5. Add new test_library_templates.py functional test script.
.
--- /dev/null
+++ b/test/functional/test_library_templates.py
@@ -0,0 +1,219 @@
+from base.twilltestcase import *
+from base.test_db_util import *
+
+class TestLibraryFeatures( TwillTestCase ):
+ def test_000_initiate_users( self ):
+ """Ensuring all required user accounts exist"""
+ self.logout()
+ self.login( email='test1(a)bx.psu.edu', username='regular-user1' )
+ global regular_user1
+ regular_user1 = get_user( 'test1(a)bx.psu.edu' )
+ assert regular_user1 is not None, 'Problem retrieving user with email "test1(a)bx.psu.edu" from the database'
+ global regular_user1_private_role
+ regular_user1_private_role = get_private_role( regular_user1 )
+ self.logout()
+ self.login( email='test2(a)bx.psu.edu', username='regular-user2' )
+ global regular_user2
+ regular_user2 = get_user( 'test2(a)bx.psu.edu' )
+ assert regular_user2 is not None, 'Problem retrieving user with email "test2(a)bx.psu.edu" from the database'
+ global regular_user2_private_role
+ regular_user2_private_role = get_private_role( regular_user2 )
+ self.logout()
+ self.login( email='test3(a)bx.psu.edu', username='regular-user3' )
+ global regular_user3
+ regular_user3 = get_user( 'test3(a)bx.psu.edu' )
+ assert regular_user3 is not None, 'Problem retrieving user with email "test3(a)bx.psu.edu" from the database'
+ global regular_user3_private_role
+ regular_user3_private_role = get_private_role( regular_user3 )
+ self.logout()
+ self.login( email='test(a)bx.psu.edu', username='admin-user' )
+ global admin_user
+ admin_user = get_user( 'test(a)bx.psu.edu' )
+ assert admin_user is not None, 'Problem retrieving user with email "test(a)bx.psu.edu" from the database'
+ global admin_user_private_role
+ admin_user_private_role = get_private_role( admin_user )
+ def test_005_create_library_templates( self ):
+ """Testing creating several LibraryInformationTemplate form definitions"""
+ # Logged in as admin_user
+ for type in [ 'AddressField', 'CheckboxField', 'SelectField', 'TextArea', 'TextField', 'WorkflowField' ]:
+ form_desc = '%s description' % type
+ # Create form for library template
+ self.create_single_field_type_form_definition( name=type,
+ desc=form_desc,
+ formtype=galaxy.model.FormDefinition.types.LIBRARY_INFO_TEMPLATE,
+ field_type=type )
+ # Get all of the new form definitions for later use
+ global AddressField_form
+ AddressField_form = get_form( 'AddressField' )
+ global CheckboxField_form
+ CheckboxField_form = get_form( 'CheckboxField' )
+ global SelectField_form
+ SelectField_form = get_form( 'SelectField' )
+ global TextArea_form
+ TextArea_form = get_form( 'TextArea' )
+ global TextField_form
+ TextField_form = get_form( 'TextField' )
+ global WorkflowField_form
+ WorkflowField_form = get_form( 'WorkflowField' )
+ def test_010_create_libraries( self ):
+ """Testing creating a new library for each template"""
+ # Logged in as admin_user
+ for index, form in enumerate( [ AddressField_form, CheckboxField_form, SelectField_form, TextArea_form, TextField_form, WorkflowField_form ] ):
+ name = 'library%s' % str( index + 1 )
+ description = '%s description' % name
+ synopsis = '%s synopsis' % name
+ self.create_library( name=name, description=description, synopsis=synopsis )
+ # Get the libraries for later use
+ global library1
+ library1 = get_library( 'library1', 'library1 description', 'library1 synopsis' )
+ global library2
+ library2 = get_library( 'library2', 'library2 description', 'library2 synopsis' )
+ global library3
+ library3 = get_library( 'library3', 'library3 description', 'library3 synopsis' )
+ global library4
+ library4 = get_library( 'library4', 'library4 description', 'library4 synopsis' )
+ global library5
+ library5 = get_library( 'library5', 'library5 description', 'library5 synopsis' )
+ global library6
+ library6 = get_library( 'library6', 'library6 description', 'library6 synopsis' )
+ def test_015_add_template_to_library1( self ):
+ """Testing add an inheritable template containing an AddressField to library1"""
+ # Logged in as admin_user
+ # Add a template to library1
+ self.add_library_template( 'library_admin',
+ 'library',
+ self.security.encode_id( library1.id ),
+ self.security.encode_id( AddressField_form.id ),
+ AddressField_form.name )
+ def test_020_add_folder_to_library1( self ):
+ """Testing adding a root folder to library1"""
+ # Logged in as admin_user
+ # Add a root folder to library1
+ folder = library1.root_folder
+ name = "folder"
+ description = "folder description"
+ self.add_folder( 'library_admin',
+ self.security.encode_id( library1.id ),
+ self.security.encode_id( folder.id ),
+ name=name,
+ description=description )
+ global folder1
+ folder1 = get_folder( folder.id, name, description )
+ def test_025_check_library1( self ):
+ """Checking library1 and its root folder"""
+ # Logged in as admin_user
+ self.browse_library( 'library_admin',
+ self.security.encode_id( library1.id ),
+ check_str1=folder1.name,
+ check_str2=folder1.description )
+ # Make sure the template and contents were inherited to folder1
+ self.folder_info( 'library_admin',
+ self.security.encode_id( folder1.id ),
+ self.security.encode_id( library1.id ),
+ check_str1=AddressField_form.name,
+ check_str2='This is an inherited template and is not required to be used with this folder' )
+ def test_030_add_dataset_to_library1_root_folder( self ):
+ """
+ Testing adding a new library dataset to library1's root folder, and adding a new UserAddress
+ on the upload form.
+ """
+ # Logged in as admin_user
+ # The AddressField template should be inherited to the library dataset upload form. Passing
+ # the value 'new' should submit the form via refresh_on_change and allow new UserAddress information
+ # to be posted as part of the upload.
+ self.add_library_dataset( 'library_admin',
+ '1.bed',
+ self.security.encode_id( library1.id ),
+ self.security.encode_id( library1.root_folder.id ),
+ library1.root_folder.name,
+ file_type='bed',
+ dbkey='hg18',
+ root=True,
+ template_refresh_field_name='field_0',
+ template_refresh_field_contents='new',
+ field_0_short_desc='Office',
+ field_0_name='Dick',
+ field_0_institution='PSU',
+ field_0_address='32 O Street',
+ field_0_city='Anywhere',
+ field_0_state='AK',
+ field_0_postal_code='0000000',
+ field_0_country='USA' )
+ global ldda1
+ ldda1 = get_latest_ldda()
+ assert ldda1 is not None, 'Problem retrieving LibraryDatasetDatasetAssociation ldda1 from the database'
+ self.browse_library( 'library_admin',
+ self.security.encode_id( library1.id ),
+ check_str1='1.bed',
+ check_str2=admin_user.email )
+ # Make sure the library template contents were correctly saved
+ self.ldda_edit_info( 'library_admin',
+ self.security.encode_id( library1.id ),
+ self.security.encode_id( library1.root_folder.id ),
+ self.security.encode_id( ldda1.id ),
+ ldda1.name,
+ check_str1='Dick' )
+ def test_035_add_template_to_library2( self ):
+ """ Testing add an inheritable template containing an CheckboxField to library2"""
+ self.add_library_template( 'library_admin',
+ 'library',
+ self.security.encode_id( library2.id ),
+ self.security.encode_id( CheckboxField_form.id ),
+ CheckboxField_form.name )
+ def test_040_add_template_to_library3( self ):
+ """ Testing add an inheritable template containing an SelectField to library3"""
+ self.add_library_template( 'library_admin',
+ 'library',
+ self.security.encode_id( library3.id ),
+ self.security.encode_id( SelectField_form.id ),
+ SelectField_form.name )
+ def test_045_add_template_to_library4( self ):
+ """ Testing add an inheritable template containing an TextArea to library4"""
+ # Add an inheritable template to library4
+ self.add_library_template( 'library_admin',
+ 'library',
+ self.security.encode_id( library4.id ),
+ self.security.encode_id( TextArea_form.id ),
+ TextArea_form.name )
+ def test_050_add_template_to_library5( self ):
+ """ Testing add an inheritable template containing an TextField to library5"""
+ # Add an inheritable template to library5
+ self.add_library_template( 'library_admin',
+ 'library',
+ self.security.encode_id( library5.id ),
+ self.security.encode_id( TextField_form.id ),
+ TextField_form.name )
+ def test_055_add_template_to_library6( self ):
+ """ Testing add an inheritable template containing an WorkflowField to library6"""
+ # Add an inheritable template to library6
+ self.add_library_template( 'library_admin',
+ 'library',
+ self.security.encode_id( library6.id ),
+ self.security.encode_id( WorkflowField_form.id ),
+ WorkflowField_form.name )
+ def test_999_reset_data_for_later_test_runs( self ):
+ """Reseting data to enable later test runs to pass"""
+ # Logged in as admin_user
+ ##################
+ # Delete all form definitions
+ ##################
+ for form in [ AddressField_form, CheckboxField_form, SelectField_form, TextArea_form, TextField_form, WorkflowField_form ]:
+ self.mark_form_deleted( self.security.encode_id( form.form_definition_current.id ) )
+ ##################
+ # Purge all libraries
+ ##################
+ for library in [ library1, library2, library3, library4, library5, library6 ]:
+ self.delete_library_item( 'library_admin',
+ self.security.encode_id( library.id ),
+ self.security.encode_id( library.id ),
+ library.name,
+ item_type='library' )
+ self.purge_library( self.security.encode_id( library.id ), library.name )
+ ##################
+ # Make sure all users are associated only with their private roles
+ ##################
+ for user in [ admin_user, regular_user1, regular_user2, regular_user3 ]:
+ refresh( user )
+ if len( user.roles) != 1:
+ raise AssertionError( '%d UserRoleAssociations are associated with %s ( should be 1 )' % ( len( user.roles ), user.email ) )
+ self.logout()
--- a/lib/galaxy/web/form_builder.py
+++ b/lib/galaxy/web/form_builder.py
@@ -4,12 +4,19 @@ Classes for generating HTML forms
import logging,sys
from cgi import escape
+from galaxy.util import restore_text
+
log = logging.getLogger(__name__)
class BaseField(object):
def get_html( self, prefix="" ):
"""Returns the html widget corresponding to the parameter"""
raise TypeError( "Abstract Method" )
+ def get_disabled_str( self, disabled=False ):
+ if disabled:
+ return 'disabled="disabled"'
+ else:
+ return ''
@staticmethod
def form_field_types():
return ['TextField', 'TextArea', 'SelectField', 'CheckboxField', 'AddressField', 'WorkflowField']
@@ -31,9 +38,9 @@ class TextField(BaseField):
self.name = name
self.size = int( size or 10 )
self.value = value or ""
- def get_html( self, prefix="" ):
- return '<input type="text" name="%s%s" size="%d" value="%s">' \
- % ( prefix, self.name, self.size, escape(str(self.value), quote=True) )
+ def get_html( self, prefix="", disabled=False ):
+ return '<input type="text" name="%s%s" size="%d" value="%s" %s>' \
+ % ( prefix, self.name, self.size, escape( str( self.value ), quote=True ), self.get_disabled_str( disabled ) )
def set_size(self, size):
self.size = int( size )
@@ -52,7 +59,7 @@ class PasswordField(BaseField):
self.value = value or ""
def get_html( self, prefix="" ):
return '<input type="password" name="%s%s" size="%d" value="%s">' \
- % ( prefix, self.name, self.size, escape(str(self.value), quote=True) )
+ % ( prefix, self.name, self.size, escape( str( self.value ), quote=True ) )
def set_size(self, size):
self.size = int( size )
@@ -71,9 +78,9 @@ class TextArea(BaseField):
self.rows = int(self.size[0])
self.cols = int(self.size[-1])
self.value = value or ""
- def get_html( self, prefix="" ):
- return '<textarea name="%s%s" rows="%d" cols="%d">%s</textarea>' \
- % ( prefix, self.name, self.rows, self.cols, escape( str( self.value ), quote=True ) )
+ def get_html( self, prefix="", disabled=False ):
+ return '<textarea name="%s%s" rows="%d" cols="%d" %s>%s</textarea>' \
+ % ( prefix, self.name, self.rows, self.cols, self.get_disabled_str( disabled ), escape( str( self.value ), quote=True ) )
def set_size(self, rows, cols):
self.rows = rows
self.cols = cols
@@ -90,7 +97,7 @@ class CheckboxField(BaseField):
def __init__( self, name, checked=None ):
self.name = name
self.checked = ( checked == True ) or ( isinstance( checked, basestring ) and ( checked.lower() in ( "yes", "true", "on" ) ) )
- def get_html( self, prefix="" ):
+ def get_html( self, prefix="", disabled=False ):
if self.checked:
checked_text = "checked"
else:
@@ -100,8 +107,8 @@ class CheckboxField(BaseField):
# parsing the request, the value 'true' in the hidden field actually means it is NOT checked.
# See the is_checked() method below. The prefix is necessary in each case to ensure functional
# correctness when the param is inside a conditional.
- return '<input type="checkbox" name="%s%s" value="true" %s><input type="hidden" name="%s%s" value="true">' \
- % ( prefix, self.name, checked_text, prefix, self.name )
+ return '<input type="checkbox" name="%s%s" value="true" %s %s><input type="hidden" name="%s%s" value="true" %s>' \
+ % ( prefix, self.name, checked_text, self.get_disabled_str( disabled ), prefix, self.name, self.get_disabled_str( disabled ) )
@staticmethod
def is_checked( value ):
if value == True:
@@ -150,7 +157,7 @@ class HiddenField(BaseField):
self.name = name
self.value = value or ""
def get_html( self, prefix="" ):
- return '<input type="hidden" name="%s%s" value="%s">' % ( prefix, self.name, escape(str(self.value), quote=True) )
+ return '<input type="hidden" name="%s%s" value="%s">' % ( prefix, self.name, escape( str( self.value ), quote=True ) )
class SelectField(BaseField):
"""
@@ -210,14 +217,14 @@ class SelectField(BaseField):
self.refresh_on_change_text = ''
def add_option( self, text, value, selected = False ):
self.options.append( ( text, value, selected ) )
- def get_html( self, prefix="" ):
+ def get_html( self, prefix="", disabled=False ):
if self.display == "checkboxes":
- return self.get_html_checkboxes( prefix )
+ return self.get_html_checkboxes( prefix, disabled )
elif self.display == "radio":
- return self.get_html_radio( prefix )
+ return self.get_html_radio( prefix, disabled )
else:
- return self.get_html_default( prefix )
- def get_html_checkboxes( self, prefix="" ):
+ return self.get_html_default( prefix, disabled )
+ def get_html_checkboxes( self, prefix="", disabled=False ):
rval = []
ctr = 0
if len( self.options ) > 1:
@@ -227,12 +234,14 @@ class SelectField(BaseField):
if len(self.options) > 2 and ctr % 2 == 1:
style = " class=\"odd_row\""
if selected:
- rval.append( '<div%s><input type="checkbox" name="%s%s" value="%s" checked>%s</div>' % ( style, prefix, self.name, escape(str(value), quote=True), text) )
+ 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</div>' % ( style, prefix, self.name, escape(str(value), quote=True), text) )
+ 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 ) )
ctr += 1
return "\n".join( rval )
- def get_html_radio( self, prefix="" ):
+ def get_html_radio( self, prefix="", disabled=False ):
rval = []
ctr = 0
for text, value, selected in self.options:
@@ -241,11 +250,20 @@ class SelectField(BaseField):
style = " class=\"odd_row\""
if selected: selected_text = " checked"
else: selected_text = ""
- rval.append( '<div%s><input type="radio" name="%s%s"%s value="%s"%s>%s</div>' % ( style, prefix, self.name, self.refresh_on_change_text, escape(str(value), quote=True), selected_text, text ) )
+ rval.append( '<div%s><input type="radio" name="%s%s"%s value="%s"%s %s>%s</div>' % \
+ ( style,
+ prefix,
+ self.name,
+ self.refresh_on_change_text,
+ escape( str( value ), quote=True ),
+ selected_text,
+ self.get_disabled_str( disabled ),
+ text ) )
ctr += 1
return "\n".join( rval )
- def get_html_default( self, prefix="" ):
- if self.multiple: multiple = " multiple"
+ def get_html_default( self, prefix="", disabled=False ):
+ if self.multiple:
+ multiple = " multiple"
else: multiple = ""
rval = []
last_selected_value = ""
@@ -253,11 +271,13 @@ class SelectField(BaseField):
if selected:
selected_text = " selected"
last_selected_value = value
- else: selected_text = ""
- rval.append( '<option value="%s"%s>%s</option>' % ( escape(str(value), quote=True), selected_text, text ) )
+ else:
+ selected_text = ""
+ rval.append( '<option value="%s"%s>%s</option>' % ( escape( str( value ), quote=True ), selected_text, text ) )
if last_selected_value:
- last_selected_value = ' last_selected_value="%s"' % escape(str(last_selected_value), quote=True)
- rval.insert( 0, '<select name="%s%s"%s%s%s>' % ( prefix, self.name, multiple, self.refresh_on_change_text, last_selected_value ) )
+ last_selected_value = ' last_selected_value="%s"' % escape( str( last_selected_value ), quote=True )
+ rval.insert( 0, '<select name="%s%s"%s%s%s %s>' % \
+ ( prefix, self.name, multiple, self.refresh_on_change_text, last_selected_value, self.get_disabled_str( disabled ), ) )
rval.append( '</select>' )
return "\n".join( rval )
def get_selected(self):
@@ -381,61 +401,71 @@ class DrillDownField( BaseField ):
class AddressField(BaseField):
@staticmethod
def fields():
- return [ ( "short_desc", "Short address description"),
- ( "name", "Name" ),
- ( "institution", "Institution" ),
- ( "address", "Address" ),
- ( "city", "City" ),
- ( "state", "State/Province/Region" ),
- ( "postal_code", "Postal Code" ),
- ( "country", "Country" ),
- ( "phone", "Phone" ) ]
+ return [ ( "short_desc", "Short address description", "Required" ),
+ ( "name", "Name", "Required" ),
+ ( "institution", "Institution", "Required" ),
+ ( "address", "Address", "Required" ),
+ ( "city", "City", "Required" ),
+ ( "state", "State/Province/Region", "Required" ),
+ ( "postal_code", "Postal Code", "Required" ),
+ ( "country", "Country", "Required" ),
+ ( "phone", "Phone", "" ) ]
def __init__(self, name, user=None, value=None, params=None):
self.name = name
self.user = user
self.value = value
self.select_address = None
self.params = params
- def get_html(self):
- from galaxy import util
+ def get_html( self, disabled=False ):
address_html = ''
add_ids = ['none']
if self.user:
for a in self.user.addresses:
- add_ids.append(str(a.id))
- add_ids.append('new')
- self.select_address = SelectField(self.name,
- refresh_on_change=True,
- refresh_on_change_values=add_ids)
+ add_ids.append( str( a.id ) )
+ add_ids.append( 'new' )
+ self.select_address = SelectField( self.name,
+ refresh_on_change=True,
+ refresh_on_change_values=add_ids )
if self.value == 'none':
- self.select_address.add_option('Select one', 'none', selected=True)
+ self.select_address.add_option( 'Select one', 'none', selected=True )
else:
- self.select_address.add_option('Select one', 'none')
+ self.select_address.add_option( 'Select one', 'none' )
if self.user:
for a in self.user.addresses:
if not a.deleted:
- if self.value == str(a.id):
- self.select_address.add_option(a.desc, str(a.id), selected=True)
- # display this address
- address_html = '''<div class="form-row">
- %s
- </div>''' % a.get_html()
+ if self.value == str( a.id ):
+ self.select_address.add_option( a.desc, str( a.id ), selected=True )
+ # Display this address
+ address_html += '''
+ <div class="form-row">
+ %s
+ </div>
+ ''' % a.get_html()
else:
- self.select_address.add_option(a.desc, str(a.id))
+ self.select_address.add_option( a.desc, str( a.id ) )
if self.value == 'new':
- self.select_address.add_option('Add a new address', 'new', selected=True)
- for field_name, label in self.fields():
- add_field = TextField(self.name+'_'+field_name,
+ self.select_address.add_option( 'Add a new address', 'new', selected=True )
+ for field_name, label, help_text in self.fields():
+ add_field = TextField( self.name + '_' + field_name,
40,
- util.restore_text( self.params.get( self.name+'_'+field_name, '' ) ))
- address_html += ''' <div class="form-row">
- <label>%s</label>
+ restore_text( self.params.get( self.name + '_' + field_name, '' ) ) )
+ address_html += '''
+ <div class="form-row">
+ <label>%s</label>
+ %s
+ ''' % ( label, add_field.get_html( disabled=disabled ) )
+ if help_text:
+ address_html += '''
+ <div class="toolParamHelp" style="clear: both;">
%s
</div>
- ''' % (label, add_field.get_html())
+ ''' % help_text
+ address_html += '''
+ </div>
+ '''
else:
- self.select_address.add_option('Add a new address', 'new')
- return self.select_address.get_html()+address_html
+ self.select_address.add_option( 'Add a new address', 'new' )
+ return self.select_address.get_html( disabled=disabled ) + address_html
class WorkflowField(BaseField):
def __init__(self, name, user=None, value=None, params=None):
@@ -444,21 +474,20 @@ class WorkflowField(BaseField):
self.value = value
self.select_workflow = None
self.params = params
- def get_html(self):
- self.select_workflow = SelectField(self.name)
+ def get_html( self, disabled=False ):
+ self.select_workflow = SelectField( self.name )
if self.value == 'none':
- self.select_workflow.add_option('Select one', 'none', selected=True)
+ self.select_workflow.add_option( 'Select one', 'none', selected=True )
else:
- self.select_workflow.add_option('Select one', 'none')
+ self.select_workflow.add_option( 'Select one', 'none' )
if self.user:
for a in self.user.stored_workflows:
if not a.deleted:
- if str(self.value) == str(a.id):
- self.select_workflow.add_option(a.name, str(a.id), selected=True)
+ if str( self.value ) == str( a.id ):
+ self.select_workflow.add_option( a.name, str( a.id ), selected=True )
else:
- self.select_workflow.add_option(a.name, str(a.id))
- return self.select_workflow.get_html()
-
+ self.select_workflow.add_option( a.name, str( a.id ) )
+ return self.select_workflow.get_html( disabled=disabled )
def get_suite():
"""Get unittest suite for this module"""
--- a/lib/galaxy/web/base/controller.py
+++ b/lib/galaxy/web/base/controller.py
@@ -313,9 +313,9 @@ class UsesFormDefinitionWidgets:
return True
if isinstance( field[ 'widget' ], CheckboxField ) and field[ 'widget' ].checked:
return True
- if isinstance( field[ 'widget' ], WorkflowField ) and field[ 'widget' ].value not in [ 'none', 'None', None ]:
+ if isinstance( field[ 'widget' ], WorkflowField ) and str( field[ 'widget' ].value ).lower() not in [ 'none' ]:
return True
- if isinstance( field[ 'widget' ], AddressField ) and field[ 'widget' ].value not in [ 'none', 'None', None ]:
+ if isinstance( field[ 'widget' ], AddressField ) and str( field[ 'widget' ].value ).lower() not in [ 'none' ]:
return True
return False
def clean_field_contents( self, widgets, **kwd ):
@@ -332,9 +332,24 @@ class UsesFormDefinitionWidgets:
field_value = widget.value
field_contents.append( util.restore_text( field_value ) )
return field_contents
+ def field_param_values_ok( self, index, widget_type, **kwd ):
+ # Make sure required fields have contents, etc
+ # TODO: Add support for other field types ( e.g., WorkflowField, etc )
+ params = util.Params( kwd )
+ if widget_type == 'AddressField':
+ if not util.restore_text( params.get( 'field_%i_short_desc' % index, '' ) ) \
+ or not util.restore_text( params.get( 'field_%i_name' % index, '' ) ) \
+ or not util.restore_text( params.get( 'field_%i_institution' % index, '' ) ) \
+ or not util.restore_text( params.get( 'field_%i_address' % index, '' ) ) \
+ or not util.restore_text( params.get( 'field_%i_city' % index, '' ) ) \
+ or not util.restore_text( params.get( 'field_%i_state' % index, '' ) ) \
+ or not util.restore_text( params.get( 'field_%i_postal_code' % index, '' ) ) \
+ or not util.restore_text( params.get( 'field_%i_country' % index, '' ) ):
+ return False
+ return True
def save_widget_field( self, trans, field_obj, index, **kwd ):
# Save a form_builder field object
- # TODO: Add support for other field types ( e.g., WorkflowField )
+ # TODO: Add support for other field types ( e.g., WorkflowField, etc )
params = util.Params( kwd )
if isinstance( field_obj, trans.model.UserAddress ):
field_obj.desc = util.restore_text( params.get( 'field_%i_short_desc' % index, '' ) )
@@ -1227,6 +1242,7 @@ class Admin( object ):
# - Dataset where HistoryDatasetAssociation.dataset_id = Dataset.id
# - UserGroupAssociation where user_id == User.id
# - UserRoleAssociation where user_id == User.id EXCEPT FOR THE PRIVATE ROLE
+ # - UserAddress where user_id == User.id
# Purging Histories and Datasets must be handled via the cleanup_datasets.py script
webapp = kwd.get( 'webapp', 'galaxy' )
id = kwd.get( 'id', None )
@@ -1271,6 +1287,9 @@ class Admin( object ):
for ura in user.roles:
if ura.role_id != private_role.id:
trans.sa_session.delete( ura )
+ # Delete UserAddresses
+ for address in user.addresses:
+ trans.sa_session.delete( address )
# Purge the user
user.purged = True
trans.sa_session.add( user )
--- a/templates/library/common/upload.mako
+++ b/templates/library/common/upload.mako
@@ -12,8 +12,32 @@
%><%def name="javascripts()">
+ ${h.js("jquery.autocomplete", "autocomplete_tagging" )}
${parent.javascripts()}
- ${h.js("jquery.autocomplete", "autocomplete_tagging" )}
+ <script type="text/javascript">
+ $( function() {
+ $( "select[refresh_on_change='true']").change( function() {
+ var refresh = false;
+ var refresh_on_change_values = $( this )[0].attributes.getNamedItem( 'refresh_on_change_values' )
+ if ( refresh_on_change_values ) {
+ refresh_on_change_values = refresh_on_change_values.value.split( ',' );
+ var last_selected_value = $( this )[0].attributes.getNamedItem( 'last_selected_value' );
+ for( i= 0; i < refresh_on_change_values.length; i++ ) {
+ if ( $( this )[0].value == refresh_on_change_values[i] || ( last_selected_value && last_selected_value.value == refresh_on_change_values[i] ) ){
+ refresh = true;
+ break;
+ }
+ }
+ }
+ else {
+ refresh = true;
+ }
+ if ( refresh ){
+ $( "#upload_library_dataset" ).submit();
+ }
+ });
+ });
+ </script></%def><%def name="stylesheets()">
--- a/lib/galaxy/model/__init__.py
+++ b/lib/galaxy/model/__init__.py
@@ -862,7 +862,8 @@ class Library( object ):
# inherited is not applicable at the library level. The get_contents
# param is passed by callers that are inheriting a template - these
# are usually new library datsets for which we want to include template
- # fields on the upload form, but not the contents of the inherited template.
+ # fields on the upload form, but not necessarily the contents of the
+ # inherited template saved for the parent.
info_association, inherited = self.get_info_association()
if info_association:
template = info_association.template
@@ -939,7 +940,8 @@ class LibraryFolder( object ):
# See if we have any associated templates. The get_contents
# param is passed by callers that are inheriting a template - these
# are usually new library datsets for which we want to include template
- # fields on the upload form.
+ # fields on the upload form, but not necessarily the contents of the
+ # inherited template saved for the parent.
info_association, inherited = self.get_info_association()
if info_association:
if inherited:
@@ -948,7 +950,12 @@ class LibraryFolder( object ):
template = info_association.template
# See if we have any field contents, but only if the info_association was
# not inherited ( we do not want to display the inherited contents ).
- if not inherited and get_contents:
+ # (gvk: 8/30/10) Based on conversations with Dan, we agreed to ALWAYS inherit
+ # contents. We'll use this behavior until we hear from the community that
+ # contents should not be inherited. If we don't hear anything for a while,
+ # eliminate the old commented out behavior.
+ #if not inherited and get_contents:
+ if get_contents:
info = info_association.info
if info:
return template.get_widgets( trans.user, info.content )
@@ -1160,7 +1167,8 @@ class LibraryDatasetDatasetAssociation(
# See if we have any associated templatesThe get_contents
# param is passed by callers that are inheriting a template - these
# are usually new library datsets for which we want to include template
- # fields on the upload form.
+ # fields on the upload form, but not necessarily the contents of the
+ # inherited template saved for the parent.
info_association, inherited = self.get_info_association()
if info_association:
if inherited:
@@ -1169,7 +1177,12 @@ class LibraryDatasetDatasetAssociation(
template = info_association.template
# See if we have any field contents, but only if the info_association was
# not inherited ( we do not want to display the inherited contents ).
- if not inherited and get_contents:
+ # (gvk: 8/30/10) Based on conversations with Dan, we agreed to ALWAYS inherit
+ # contents. We'll use this behavior until we hear from the community that
+ # contents should not be inherited. If we don't hear anything for a while,
+ # eliminate the old commented out behavior.
+ #if not inherited and get_contents:
+ if get_contents:
info = info_association.info
if info:
return template.get_widgets( trans.user, info.content )
--- a/test/functional/test_user_info.py
+++ b/test/functional/test_user_info.py
@@ -126,7 +126,7 @@ class TestUserInfo( TwillTestCase ):
self.check_page_for_string( "Manage User Information" )
self.check_page_for_string( user_info_values[0] )
self.check_page_for_string( user_info_values[1] )
- self.check_page_for_string( '<input type="checkbox" name="field_2" value="true" checked>' )
+ self.check_page_for_string( '<input type="checkbox" name="field_2" value="true" checked >' )
def test_015_user_reqistration_single_user_info_forms( self ):
''' Testing user registration with a single user info form '''
# Logged in as regular_user_11
@@ -155,7 +155,7 @@ class TestUserInfo( TwillTestCase ):
self.check_page_for_string( "Manage User Information" )
self.check_page_for_string( user_info_values[0] )
self.check_page_for_string( user_info_values[1] )
- self.check_page_for_string( '<input type="checkbox" name="field_2" value="true" checked>' )
+ self.check_page_for_string( '<input type="checkbox" name="field_2" value="true" checked >' )
def test_020_edit_user_info( self ):
"""Testing editing user info as a regular user"""
# Logged in as regular_user_12
@@ -179,32 +179,23 @@ class TestUserInfo( TwillTestCase ):
# Test editing the user info
self.edit_user_info( ['Research', 'PSU'] )
def test_999_reset_data_for_later_test_runs( self ):
+ """Reseting data to enable later test runs to pass"""
# Logged in as regular_user_12
self.logout()
self.login( email=admin_user.email )
+ ##################
+ # Mark all forms deleted
+ ##################
+ for form_name in [ form_one_name ]:
+ form = get_form( form_name )
+ mark_form_deleted( form )
###############
- # Mark form_one as deleted ( form_two was marked deleted earlier )
+ # Purge appropriate users
###############
- form_latest = get_form( form_one_name )
- mark_form_deleted( form_latest )
- ###############
- # Manually delete the test_user11
- ###############
- self.mark_user_deleted( user_id=self.security.encode_id( regular_user11.id ), email=regular_user11.email )
- refresh( regular_user11 )
- self.purge_user( self.security.encode_id( regular_user11.id ), regular_user11.email )
- refresh( regular_user11 )
- # We should now only the the user and his private role
- delete_user_roles( regular_user11 )
- delete_obj( regular_user11 )
- ###############
- # Manually delete the test_user12
- ###############
- refresh( regular_user12 )
- self.mark_user_deleted( user_id=self.security.encode_id( regular_user12.id ), email=regular_user12.email )
- refresh( regular_user12 )
- self.purge_user( self.security.encode_id( regular_user12.id ), regular_user12.email )
- refresh( regular_user12 )
- # We should now only the the user and his private role
- delete_user_roles( regular_user12 )
- delete_obj( regular_user12 )
+ for user in [ regular_user11, regular_user12 ]:
+ self.mark_user_deleted( user_id=self.security.encode_id( user.id ), email=user.email )
+ refresh( user )
+ self.purge_user( self.security.encode_id( user.id ), user.email )
+ refresh( user )
+ delete_user_roles( user )
+ delete_obj( user )
--- a/templates/library/common/select_template.mako
+++ b/templates/library/common/select_template.mako
@@ -66,13 +66,18 @@
<input type="submit" name="add_template_button" value="Add template to ${item_desc}"/></div></form>
- %if template_select_list.get_selected() != ('Select one', 'none'):
- <div style="clear: both"></div>
+ </div>
+</div>
+<p/>
+%if template_select_list.get_selected() != ('Select one', 'none'):
+ <div class="toolForm">
+ <div class="toolFormTitle">Layout of selected template</div>
+ <div class="toolFormBody"><div class="form-row">
%for i, field in enumerate( widgets ):
<div class="form-row"><label>${field[ 'label' ]}</label>
- ${field[ 'widget' ].get_html()}
+ ${field[ 'widget' ].get_html( disabled=True )}
<div class="toolParamHelp" style="clear: both;">
${field[ 'helptext' ]}
</div>
@@ -80,6 +85,6 @@
</div>
%endfor
</div>
- %endif
+ </div></div>
-</div>
+%endif
--- a/test/base/twilltestcase.py
+++ b/test/base/twilltestcase.py
@@ -1406,6 +1406,45 @@ class TwillTestCase( unittest.TestCase )
self.check_page_for_string( desc )
self.check_page_for_string( formtype )
self.home()
+ # Form stuff
+ def create_single_field_type_form_definition( self, name, desc, formtype, field_type ):
+ """
+ Create a new form definition containing 1 field of a specified type ( AddressField, CheckboxField, SelectField,
+ TextArea, TextField, WorkflowField ). The form_type param value should not be 'Sequencing Sample Form,' use
+ create_form() above for that.
+ """
+ self.home()
+ # Create a new form definition
+ self.visit_url( "%s/forms/new" % self.url )
+ self.check_page_for_string( 'Create a new form definition' )
+ tc.fv( "1", "name", name )
+ tc.fv( "1", "description", desc )
+ tc.fv( "1", "form_type_selectbox", formtype )
+ tc.submit( "create_form_button" )
+ # Add 1 AddressField to the new form definition
+ field_name = 'field_name_0'
+ field_contents = field_type
+ field_help_name = 'field_helptext_0'
+ field_help_contents = '%s help' % field_type
+ field_default = 'field_default_0'
+ field_default_contents = '%s default contents' % field_type
+ tc.fv( "1", field_name, field_contents )
+ tc.fv( "1", field_help_name, field_help_contents )
+ self.refresh_form( 'field_type_0', field_type )
+ if field_type == 'SelectField':
+ # Add 2 options so our select list is functional
+ tc.submit( "addoption_0" )
+ tc.fv( "1", "field_0_option_0", "One" )
+ tc.submit( "addoption_0" )
+ tc.fv( "1", "field_0_option_1", "Two" )
+ tc.fv( "1", field_default, field_default_contents )
+ tc.submit( "save_changes_button" )
+ self.home()
+ self.visit_url( "%s/forms/manage" % self.url )
+ self.check_page_for_string( name )
+ self.check_page_for_string( desc )
+ self.check_page_for_string( formtype )
+ self.home()
def edit_form( self, form_current_id, form_name, new_form_name="Form One's Name (Renamed)", new_form_desc="This is Form One's description (Re-described)"):
"""
Edit form details; name & description
@@ -1459,6 +1498,15 @@ class TwillTestCase( unittest.TestCase )
check_str = "The form '%s' has been updated with the changes." % form_name
self.check_page_for_string( check_str )
self.home()
+ def mark_form_deleted( self, form_id ):
+ """Mark a form_definition as deleted"""
+ self.home()
+ url = "%s/forms/manage?operation=delete&id=%s" % ( self.url, form_id )
+ self.visit_url( url )
+ check_str = "1 form(s) is deleted."
+ self.check_page_for_string( check_str )
+ self.home()
+
# Requests stuff
def check_request_grid(self, state, request_name, deleted=False):
self.home()
@@ -1603,7 +1651,11 @@ class TwillTestCase( unittest.TestCase )
# Library stuff
def add_library_template( self, cntrller, item_type, library_id, form_id, form_name, folder_id=None, ldda_id=None ):
- """Add a new info template to a library item"""
+ """
+ Add a new info template to a library item - the template will ALWAYS BE SET TO INHERITABLE here. If you want to
+ dis-inherit your template, call the manage_library_template_inheritance() below immediately after you call this
+ method in your test code.
+ """
self.home()
if item_type == 'library':
url = "%s/library_common/add_template?cntrller=%s&item_type=%s&library_id=%s" % \
@@ -1616,11 +1668,31 @@ class TwillTestCase( unittest.TestCase )
( self.url, cntrller, item_type, library_id, folder_id, ldda_id )
self.visit_url( url )
self.check_page_for_string ( "Select a template for the" )
- tc.fv( '1', 'form_id', form_id )
- tc.fv( '1', 'inherit', '1' )
- tc.submit( 'add_template_button' )
+ self.refresh_form( "form_id", form_id )
+ # For some unknown reason, twill barfs if the form number ( 1 ) is used in the following
+ # rather than the form anme ( select_template ), so we have to use the form name.
+ tc.fv( "select_template", "inheritable", '1' )
+ tc.submit( "add_template_button" )
self.check_page_for_string = 'A template based on the form "%s" has been added to this' % form_name
self.home()
+ def manage_library_template_inheritance( self, cntrller, item_type, library_id, folder_id=None, ldda_id=None, inheritable=True ):
+ # If inheritable is True, the item is currently inheritable.
+ self.home()
+ if item_type == 'library':
+ url = "%s/library_common/manage_template_inheritance?cntrller=%s&item_type=%s&library_id=%s" % \
+ ( self.url, cntrller, item_type, library_id )
+ elif item_type == 'folder':
+ url = "%s/library_common/manage_template_inheritance?cntrller=%s&item_type=%s&library_id=%s&folder_id=%s" % \
+ ( self.url, cntrller, item_type, library_id, folder_id )
+ elif item_type == 'ldda':
+ url = "%s/library_common/manage_template_inheritance?cntrller=%s&item_type=%s&library_id=%s&folder_id=%s&ldda_id=%s" % \
+ ( self.url, cntrller, item_type, library_id, folder_id, ldda_id )
+ self.visit_url( url )
+ if inheritable:
+ self.check_page_for_string = 'will no longer be inherited to contained folders and datasets'
+ else:
+ self.check_page_for_string = 'will now be inherited to contained folders and datasets'
+ self.home()
def browse_libraries_admin( self, deleted=False, check_str1='', check_str2='', not_displayed1='' ):
self.visit_url( '%s/library_admin/browse_libraries?sort=name&f-description=All&f-name=All&f-deleted=%s' % ( self.url, str( deleted ) ) )
if check_str1:
@@ -1718,13 +1790,14 @@ class TwillTestCase( unittest.TestCase )
self.home()
# Library folder stuff
- def add_folder( self, controller, library_id, folder_id, name='Folder One', description='This is Folder One' ):
+ def add_folder( self, cntrller, library_id, folder_id, name='Folder One', description='This is Folder One' ):
"""Create a new folder"""
self.home()
- self.visit_url( "%s/library_common/create_folder?cntrller=%s&library_id=%s&parent_id=%s" % ( self.url, controller, library_id, folder_id ) )
+ url = "%s/library_common/create_folder?cntrller=%s&library_id=%s&parent_id=%s" % ( self.url, cntrller, library_id, folder_id )
+ self.visit_url( url )
self.check_page_for_string( 'Create a new folder' )
- tc.fv( "1", "name", name ) # form field 1 is the field named name...
- tc.fv( "1", "description", description ) # form field 2 is the field named description...
+ tc.fv( "1", "name", name )
+ tc.fv( "1", "description", description )
tc.submit( "new_folder_button" )
check_str = "The new folder named '%s' has been added to the data library." % name
self.check_page_for_string( check_str )
@@ -1765,14 +1838,32 @@ class TwillTestCase( unittest.TestCase )
# Library dataset stuff
def add_library_dataset( self, cntrller, filename, library_id, folder_id, folder_name,
file_type='auto', dbkey='hg18', roles=[], message='', root=False,
- template_field_name1='', template_field_contents1='', show_deleted='False',
- upload_option='upload_file' ):
+ template_field_name1='', template_field_contents1='',
+ template_refresh_field_name='', template_refresh_field_contents='',
+ field_0_short_desc='', field_0_name='', field_0_institution='',
+ field_0_address='', field_0_city='', field_0_state='', field_0_postal_code='',
+ field_0_country='', show_deleted='False', upload_option='upload_file' ):
"""Add a dataset to a folder"""
filename = self.get_filename( filename )
self.home()
self.visit_url( "%s/library_common/upload_library_dataset?cntrller=%s&library_id=%s&folder_id=%s&upload_option=%s&message=%s" % \
( self.url, cntrller, library_id, folder_id, upload_option, message.replace( ' ', '+' ) ) )
self.check_page_for_string( 'Upload files' )
+ # A template containing an AddressField may be displayed on the upload form.
+ # If this is the case, we need to refresh the form with the passeed tmplate_field_name1.
+ if template_refresh_field_name and template_refresh_field_contents:
+ self.refresh_form( template_refresh_field_name, template_refresh_field_contents )
+ tc.fv( "1", "field_0_short_desc", field_0_short_desc )
+ tc.fv( "1", "field_0_name", field_0_name )
+ tc.fv( "1", "field_0_institution", field_0_institution )
+ tc.fv( "1", "field_0_address", field_0_address )
+ tc.fv( "1", "field_0_city", field_0_city )
+ tc.fv( "1", "field_0_state", field_0_state )
+ tc.fv( "1", "field_0_postal_code", field_0_postal_code )
+ tc.fv( "1", "field_0_country", field_0_country )
+ # Add template field contents, if any...
+ if template_field_name1:
+ tc.fv( "1", template_field_name1, template_field_contents1 )
tc.fv( "1", "library_id", library_id )
tc.fv( "1", "folder_id", folder_id )
tc.fv( "1", "show_deleted", show_deleted )
@@ -1782,9 +1873,6 @@ class TwillTestCase( unittest.TestCase )
tc.fv( "1", "message", message.replace( '+', ' ' ) )
for role_id in roles:
tc.fv( "1", "roles", role_id )
- # Add template field contents, if any...
- if template_field_name1:
- tc.fv( "1", template_field_name1, template_field_contents1 )
tc.submit( "runtool_btn" )
if root:
check_str = "Added 1 datasets to the library '%s' (each is selected)." % folder_name
--- a/templates/library/common/common.mako
+++ b/templates/library/common/common.mako
@@ -22,7 +22,7 @@
has_contents = True
label = field[ 'label' ]
value = 'checked'
- elif isinstance( field[ 'widget' ], WorkflowField ) and field[ 'widget' ].value not in [ 'none', 'None', None ]:
+ elif isinstance( field[ 'widget' ], WorkflowField ) and str( field[ 'widget' ].value ).lower() not in [ 'none' ]:
has_contents = True
label = field[ 'label' ]
widget = field[ 'widget' ]
@@ -35,7 +35,7 @@
else:
# If we didn't find the selected workflow option above, we'll just print the value
value = field[ 'widget' ].value
- elif isinstance( field[ 'widget' ], AddressField ) and field[ 'widget' ].value not in [ 'none', 'None', None ]:
+ elif isinstance( field[ 'widget' ], AddressField ) and str( field[ 'widget' ].value ).lower() not in [ 'none' ]:
has_contents = True
widget = field[ 'widget' ]
address = trans.sa_session.query( trans.model.UserAddress ).get( int( widget.value ) )
@@ -69,71 +69,77 @@
else:
can_modify = False
%>
- %if widgets:
- %if editable and can_modify:
- <p/>
- <div class="toolForm">
- <div class="toolFormTitle">
- %if inherited:
- Other information <i>- this is an inherited template and is not required to be used with this ${item_type}</i>
- %else:
- Other information
- %endif
- %if info_association and not inherited and can_modify:
+ %if editable and can_modify:
+ <p/>
+ <div class="toolForm">
+ <div class="toolFormTitle">Other information
+ <a id="item-${item.id}-popup" class="popup-arrow" style="display: none;">▼</a>
+ <div popupmenu="item-${item.id}-popup">
+ %if info_association and inherited and can_modify:
## "inherited" will be true only if the info_association is not associated with the current item,
- ## in which case we do not want to render the following popup menu.
- <a id="item-${item.id}-popup" class="popup-arrow" style="display: none;">▼</a>
- <div popupmenu="item-${item.id}-popup">
- <a class="action-button" href="${h.url_for( controller='library_common', action='edit_template', cntrller=cntrller, item_type=item_type, library_id=library_id, folder_id=folder_id, ldda_id=ldda_id, show_deleted=show_deleted )}">Edit template</a>
- <a class="action-button" href="${h.url_for( controller='library_common', action='delete_template', cntrller=cntrller, item_type=item_type, library_id=library_id, folder_id=folder_id, ldda_id=ldda_id, show_deleted=show_deleted )}">Delete template</a>
- %if item_type not in [ 'ldda', 'library_dataset' ]:
- %if info_association.inheritable:
- <a class="action-button" href="${h.url_for( controller='library_common', action='manage_template_inheritance', cntrller=cntrller, item_type=item_type, library_id=library_id, folder_id=folder_id, ldda_id=ldda_id, show_deleted=show_deleted )}">Dis-inherit template</a>
- %else:
- <a class="action-button" href="${h.url_for( controller='library_common', action='manage_template_inheritance', cntrller=cntrller, item_type=item_type, library_id=library_id, folder_id=folder_id, ldda_id=ldda_id, show_deleted=show_deleted )}">Inherit template</a>
- %endif
+ ## which means that the currently display template has not yet been saved for the current item.
+ <a class="action-button" href="${h.url_for( controller='library_common', action='add_template', cntrller=cntrller, item_type=item_type, library_id=library_id, folder_id=folder_id, ldda_id=ldda_id, show_deleted=show_deleted )}">Select a different template</a>
+ %elif info_association and not inherited and can_modify:
+ <a class="action-button" href="${h.url_for( controller='library_common', action='edit_template', cntrller=cntrller, item_type=item_type, library_id=library_id, folder_id=folder_id, ldda_id=ldda_id, show_deleted=show_deleted )}">Edit template</a>
+ <a class="action-button" href="${h.url_for( controller='library_common', action='delete_template', cntrller=cntrller, item_type=item_type, library_id=library_id, folder_id=folder_id, ldda_id=ldda_id, show_deleted=show_deleted )}">Delete template</a>
+ %if item_type not in [ 'ldda', 'library_dataset' ]:
+ %if info_association.inheritable:
+ <a class="action-button" href="${h.url_for( controller='library_common', action='manage_template_inheritance', cntrller=cntrller, item_type=item_type, library_id=library_id, folder_id=folder_id, ldda_id=ldda_id, show_deleted=show_deleted )}">Dis-inherit template</a>
+ %else:
+ <a class="action-button" href="${h.url_for( controller='library_common', action='manage_template_inheritance', cntrller=cntrller, item_type=item_type, library_id=library_id, folder_id=folder_id, ldda_id=ldda_id, show_deleted=show_deleted )}">Inherit template</a>
%endif
- </div>
+ %endif
%endif
</div>
- <div class="toolFormBody">
- <form name="edit_info" id="edit_info" action="${h.url_for( controller='library_common', action='edit_template_info', cntrller=cntrller, item_type=item_type, library_id=library_id, folder_id=folder_id, ldda_id=ldda_id, show_deleted=show_deleted )}" method="post">
- %for i, field in enumerate( widgets ):
- <div class="form-row">
- <label>${field[ 'label' ]}</label>
- ${field[ 'widget' ].get_html()}
- <div class="toolParamHelp" style="clear: both;">
- ${field[ 'helptext' ]}
- </div>
- <div style="clear: both"></div>
+ </div>
+ <div class="toolFormBody">
+ %if inherited:
+ <div class="form-row">
+ <font color="red">
+ <b>
+ This is an inherited template and is not required to be used with this ${item_type}. You can
+ <a href="${h.url_for( controller='library_common', action='add_template', cntrller=cntrller, item_type=item_type, library_id=library_id, folder_id=folder_id, ldda_id=ldda_id, show_deleted=show_deleted )}"><font color="red">select a different template</font></a>
+ or fill in the desired fields and save this one. This template will not be assocaiated with this ${item_type} until you click the Save button.
+ </b>
+ </font>
+ </div>
+ %endif
+ <form name="edit_info" id="edit_info" action="${h.url_for( controller='library_common', action='edit_template_info', cntrller=cntrller, item_type=item_type, library_id=library_id, folder_id=folder_id, ldda_id=ldda_id, show_deleted=show_deleted )}" method="post">
+ %for i, field in enumerate( widgets ):
+ <div class="form-row">
+ <label>${field[ 'label' ]}</label>
+ ${field[ 'widget' ].get_html()}
+ <div class="toolParamHelp" style="clear: both;">
+ ${field[ 'helptext' ]}
</div>
- %endfor
- <div class="form-row">
- <input type="submit" name="edit_info_button" value="Save"/>
+ <div style="clear: both"></div></div>
- </form>
- </div>
+ %endfor
+ <div class="form-row">
+ <input type="submit" name="edit_info_button" value="Save"/>
+ </div>
+ </form></div>
- <p/>
- %elif widget_fields_have_contents:
- <p/>
- <div class="toolForm">
- <div class="toolFormTitle">Other information about ${item.name}</div>
- <div class="toolFormBody">
- %for i, field in enumerate( widgets ):
- ${render_template_field( field )}
- %endfor
- </div>
+ </div>
+ <p/>
+ %elif widget_fields_have_contents:
+ <p/>
+ <div class="toolForm">
+ <div class="toolFormTitle">Other information about ${item.name}</div>
+ <div class="toolFormBody">
+ %for i, field in enumerate( widgets ):
+ ${render_template_field( field )}
+ %endfor
</div>
- <p/>
- %endif
+ </div>
+ <p/>
%endif
</%def><%def name="render_upload_form( cntrller, upload_option, action, library_id, folder_id, replace_dataset, file_formats, dbkeys, widgets, roles, history, show_deleted )"><% import os, os.path %>
%if upload_option in [ 'upload_file', 'upload_directory', 'upload_paths' ]:
- <div class="toolForm" id="upload_library_dataset">
+ <div class="toolForm" id="upload_library_dataset_tool_form">
%if upload_option == 'upload_directory':
<div class="toolFormTitle">Upload a directory of files</div>
%elif upload_option == 'upload_paths':
@@ -142,7 +148,7 @@
<div class="toolFormTitle">Upload files</div>
%endif
<div class="toolFormBody">
- <form name="upload_library_dataset" action="${action}" enctype="multipart/form-data" method="post">
+ <form name="upload_library_dataset" id="upload_library_dataset" action="${action}" enctype="multipart/form-data" method="post"><input type="hidden" name="tool_id" value="upload1"/><input type="hidden" name="tool_state" value="None"/><input type="hidden" name="cntrller" value="${cntrller}"/>
--- a/lib/galaxy/web/controllers/library_common.py
+++ b/lib/galaxy/web/controllers/library_common.py
@@ -7,6 +7,7 @@ from galaxy.util.json import to_json_str
from galaxy.tools.actions import upload_common
from galaxy.model.orm import *
from galaxy.util.streamball import StreamBall
+from galaxy.web.form_builder import AddressField, CheckboxField, SelectField, TextArea, TextField, WorkflowField
import logging, tempfile, zipfile, tarfile, os, sys
if sys.version_info[:2] < ( 2, 6 ):
@@ -943,7 +944,7 @@ class LibraryCommon( BaseController, Use
# Check to see if the user selected roles to associate with the DATASET_ACCESS permission
# on the dataset that would cause accessibility issues.
roles = params.get( 'roles', False )
- error = None
+ error = False
if upload_option == 'upload_paths' and not trans.app.config.allow_library_path_paste:
error = True
message = '"allow_library_path_paste" is not defined in the Galaxy configuration file'
@@ -966,11 +967,41 @@ class LibraryCommon( BaseController, Use
status='error' ) )
else:
- # See if we have any inherited templates, but do not inherit contents.
+ # See if we have any inherited templates.
info_association, inherited = folder.get_info_association( inherited=True )
if info_association and info_association.inheritable:
template_id = str( info_association.template.id )
- widgets = folder.get_template_widgets( trans, get_contents=False )
+ widgets = folder.get_template_widgets( trans, get_contents=True )
+ processed_widgets = []
+ # The list of widgets may include an AddressField which we need to save if it is new
+ for index, widget_dict in enumerate( widgets ):
+ widget = widget_dict[ 'widget' ]
+ if isinstance( widget, AddressField ):
+ value = util.restore_text( params.get( 'field_%i' % index, '' ) )
+ if value == 'new':
+ if self.field_param_values_ok( index, 'AddressField', **kwd ):
+ # Save the new address
+ address = trans.app.model.UserAddress( user=trans.user )
+ self.save_widget_field( trans, address, index, **kwd )
+ widget.value = str( address.id )
+ widget_dict[ 'widget' ] = widget
+ processed_widgets.append( widget_dict )
+ # FIXME: ( hack ) It is now critical to update the value of 'field_%i', replacing the string
+ # 'new' with the new address id. This is necessary because the upload_dataset()
+ # method below calls the handle_library_params() method, which does not parse the
+ # widget fields, it instead pulls form values from kwd. See the FIXME comments in the
+ # handle_library_params() method...
+ kwd[ 'field_%i' % index ] = str( address.id )
+ else:
+ # The invalid address won't be saved, but we cannot dispaly error
+ # messages on the upload form due to the ajax upload already occurring.
+ # When we re-engineer the upload process ( currently under way ), we
+ # will be able to check the form values before the ajax upload occurs
+ # in the background. For now, we'll do nothing...
+ pass
+ else:
+ processed_widgets.append( widget_dict )
+ widgets = processed_widgets
else:
template_id = 'None'
widgets = []
@@ -1039,10 +1070,34 @@ class LibraryCommon( BaseController, Use
show_deleted=show_deleted,
message=util.sanitize_text( message ),
status=status ) )
- # See if we have any inherited templates, but do not inherit contents.
+ # Note: if the upload form was submitted due to refresh_on_demand for a form field, we cannot re-populate
+ # the field for the selected file ( files_0|file_data ) if the user selected one. This is because the value
+ # attribute of the html input file type field is typically ignored by browsers as a security precaution.
+
+ # See if we have any inherited templates.
info_association, inherited = folder.get_info_association( inherited=True )
if info_association and info_association.inheritable:
- widgets = folder.get_template_widgets( trans, get_contents=False )
+ widgets = folder.get_template_widgets( trans, get_contents=True )
+ # Handle form submission via refresh_on_change by keeping the contents of widget fields
+ populated_widgets = []
+ for index, widget_dict in enumerate( widgets ):
+ widget = widget_dict[ 'widget' ]
+ if isinstance( widget, AddressField ):
+ value = util.restore_text( params.get( 'field_%i' % index, '' ) )
+ if value:
+ if value == 'new':
+ # Adding a new address
+ widget.value = value
+ widget_dict[ 'widget' ] = widget
+ elif value == 'none':
+ widget.value = ''
+ widget_dict[ 'widget' ] = widget
+ else:
+ # An existing address object was selected
+ address_obj = trans.sa_session.query( trans.app.model.UserAddress ).get( int( value ) )
+ widget_dict[ 'widget' ] = address_obj
+ populated_widgets.append( widget_dict )
+ widgets = populated_widgets
else:
widgets = []
upload_option = params.get( 'upload_option', 'upload_file' )
@@ -1132,6 +1187,8 @@ class LibraryCommon( BaseController, Use
message = '"allow_library_path_paste" is not defined in the Galaxy configuration file'
# Some error handling should be added to this method.
try:
+ # FIXME: instead of passing params here ( chiech have been process by util.Params(), the original kwd
+ # should be passed so that complex objects that may have been included in the initial request remain.
library_bunch = upload_common.handle_library_params( trans, params, folder_id, replace_dataset )
except:
response_code = 500
@@ -2174,10 +2231,23 @@ class LibraryCommon( BaseController, Use
value = util.restore_text( params.get( 'field_%i' % index, '' ) )
if value == 'new':
if params.get( 'edit_info_button', False ):
- # Save the new address
- address = trans.app.model.UserAddress( user=trans.user )
- self.save_widget_field( trans, address, index, **kwd )
- widget.value = str( address.id )
+ if self.field_param_values_ok( index, 'AddressField', **kwd ):
+ # Save the new address
+ address = trans.app.model.UserAddress( user=trans.user )
+ self.save_widget_field( trans, address, index, **kwd )
+ widget.value = str( address.id )
+ else:
+ message = 'Required fields are missing contents.'
+ return trans.response.send_redirect( web.url_for( controller='library_common',
+ action=action,
+ cntrller=cntrller,
+ use_panels=use_panels,
+ library_id=library_id,
+ folder_id=folder_id,
+ id=id,
+ show_deleted=show_deleted,
+ message=util.sanitize_text( message ),
+ status='error' ) )
else:
# Form was submitted via refresh_on_change
widget.value = 'new'
--- a/templates/library/common/library_dataset_info.mako
+++ b/templates/library/common/library_dataset_info.mako
@@ -90,6 +90,5 @@
%endif
%if widgets:
- ## Templates are not currently supported for library_datasets, only the associated ldda.
${render_template_fields( cntrller, 'library_dataset', library_id, widgets, widget_fields_have_contents, info_association=None, inherited=False, editable=False )}
%endif
--- a/lib/galaxy/tools/actions/upload_common.py
+++ b/lib/galaxy/tools/actions/upload_common.py
@@ -35,6 +35,9 @@ def persist_uploads( params ):
params['files'] = new_files
return params
def handle_library_params( trans, params, folder_id, replace_dataset=None ):
+ # FIXME: the received params has already been parsed by util.Params() by the time it reaches here,
+ # so no complex objects remain. This is not good because it does not allow for those objects to be
+ # manipulated here. The receivd params should be the original kwd from the initial request.
library_bunch = util.bunch.Bunch()
library_bunch.replace_dataset = replace_dataset
library_bunch.message = params.get( 'message', '' )
@@ -42,9 +45,8 @@ def handle_library_params( trans, params
library_bunch.template_field_contents = []
template_id = params.get( 'template_id', None )
library_bunch.folder = trans.sa_session.query( trans.app.model.LibraryFolder ).get( trans.security.decode_id( folder_id ) )
- # We are inheriting the folder's info_association, so we did not
- # receive any inherited contents, but we may have redirected here
- # after the user entered template contents ( due to errors ).
+ # We are inheriting the folder's info_association, so we may have received inherited contents or we may have redirected
+ # here after the user entered template contents ( due to errors ).
if template_id not in [ None, 'None' ]:
library_bunch.template = trans.sa_session.query( trans.app.model.FormDefinition ).get( template_id )
for field_index in range( len( library_bunch.template.fields ) ):
--- a/lib/galaxy/web/controllers/tool_runner.py
+++ b/lib/galaxy/web/controllers/tool_runner.py
@@ -179,6 +179,8 @@ class ToolRunner( BaseController ):
replace_dataset = trans.sa_session.query( trans.app.model.LibraryDataset ).get( trans.security.decode_id( replace_id ) )
else:
replace_dataset = None
+ # FIXME: instead of passing params here ( chiech have been process by util.Params(), the original kwd
+ # should be passed so that complex objects that may have been included in the initial request remain.
library_bunch = upload_common.handle_library_params( trans, nonfile_params, nonfile_params.folder_id, replace_dataset )
else:
library_bunch = None
1
0

galaxy-dist commit 121678c8a483: lims: changed sequencing request menu group to sample tracking
by commits-noreply@bitbucket.org 08 Sep '10
by commits-noreply@bitbucket.org 08 Sep '10
08 Sep '10
# HG changeset patch -- Bitbucket.org
# Project galaxy-dist
# URL http://bitbucket.org/galaxy/galaxy-dist/overview
# User rc
# Date 1283447523 14400
# Node ID 121678c8a483061c531c37c8d2e398ae1baa315a
# Parent 368956bcef26af16b4f7694fb8f81fb6152cf6de
lims: changed sequencing request menu group to sample tracking
--- a/templates/webapps/galaxy/admin/index.mako
+++ b/templates/webapps/galaxy/admin/index.mako
@@ -110,7 +110,7 @@
</div><div class="toolSectionPad"></div><div class="toolSectionTitle">
- <span>Sequencing Requests</span>
+ <span>Sample Tracking</span></div><div class="toolSectionBody"><div class="toolSectionBg">
1
0

galaxy-dist commit d9e099daa827: Added missing Bowtie color loc file to setup.sh
by commits-noreply@bitbucket.org 08 Sep '10
by commits-noreply@bitbucket.org 08 Sep '10
08 Sep '10
# HG changeset patch -- Bitbucket.org
# Project galaxy-dist
# URL http://bitbucket.org/galaxy/galaxy-dist/overview
# User Kelly Vincent <kpvincent(a)bx.psu.edu>
# Date 1282317387 14400
# Node ID d9e099daa8279880d5e054680ab28e8fc3064f77
# Parent d8cf43c9a0b99ce386f4d5e701393b0372966f7a
Added missing Bowtie color loc file to setup.sh
--- a/setup.sh
+++ b/setup.sh
@@ -16,6 +16,7 @@ tool-data/bfast_indexes.loc.sample
tool-data/binned_scores.loc.sample
tool-data/blastdb.loc.sample
tool-data/bowtie_indices.loc.sample
+tool-data/bowtie_indices_color.loc.sample
tool-data/encode_datasets.loc.sample
tool-data/liftOver.loc.sample
tool-data/maf_index.loc.sample
1
0