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

09 Feb '10
details: http://www.bx.psu.edu/hg/galaxy/rev/b4ba343d3540
changeset: 3335:b4ba343d3540
user: Nate Coraor <nate(a)bx.psu.edu>
date: Fri Feb 05 10:04:04 2010 -0500
description:
Add (most of) Assaf Gordon's patch for allowing SGE options in the runner url, and add the same support to PBS. Please note that this should be considered a temporary implementation, and will be removed in the future.
diffstat:
lib/galaxy/jobs/__init__.py | 9 +++++
lib/galaxy/jobs/runners/pbs.py | 69 +++++++++++++++++++++++++----------------
lib/galaxy/jobs/runners/sge.py | 35 +++++++++++++++++----
3 files changed, 79 insertions(+), 34 deletions(-)
diffs (188 lines):
diff -r 51a1369fdf96 -r b4ba343d3540 lib/galaxy/jobs/__init__.py
--- a/lib/galaxy/jobs/__init__.py Fri Feb 05 09:23:19 2010 -0500
+++ b/lib/galaxy/jobs/__init__.py Fri Feb 05 10:04:04 2010 -0500
@@ -719,6 +719,7 @@
for outfile in [ str( o ) for o in output_paths ]:
sizes.append( ( outfile, os.stat( outfile ).st_size ) )
return sizes
+
def setup_external_metadata( self, exec_dir = None, tmp_dir = None, dataset_files_path = None, config_root = None, datatypes_config = None, set_extension = True, **kwds ):
# extension could still be 'auto' if this is the upload tool.
job = self.sa_session.query( model.Job ).get( self.job_id )
@@ -747,6 +748,14 @@
job_metadata = os.path.join( self.working_directory, TOOL_PROVIDED_JOB_METADATA_FILE ),
**kwds )
+ @property
+ def user( self ):
+ job = self.sa_session.query( model.Job ).get( self.job_id )
+ if job.history.user is None:
+ return 'anonymous@' + job.galaxy_session.remote_addr.split()[-1]
+ else:
+ return job.history.user.email
+
class DefaultJobDispatcher( object ):
def __init__( self, app ):
self.app = app
diff -r 51a1369fdf96 -r b4ba343d3540 lib/galaxy/jobs/runners/pbs.py
--- a/lib/galaxy/jobs/runners/pbs.py Fri Feb 05 09:23:19 2010 -0500
+++ b/lib/galaxy/jobs/runners/pbs.py Fri Feb 05 10:04:04 2010 -0500
@@ -124,12 +124,27 @@
def determine_pbs_queue( self, url ):
"""Determine what PBS queue we are submitting to"""
- url_split = url.split("/")
- queue = url_split[3]
- if queue == "":
- # None == server's default queue
- queue = None
- return queue
+ try:
+ return url.split('/')[3] or None
+ except:
+ return None
+
+ def determine_pbs_options( self, url ):
+ try:
+ opts = url.split('/')[4].strip().lstrip('-').split(' -')
+ assert opts != ['']
+ except:
+ return []
+ rval = []
+ for opt in opts:
+ name, value = opt.split( None, 1 )
+ if name == 'l':
+ resource_attrs = value.split(',')
+ for j, ( res, val ) in enumerate( [ a.split('=', 1) for a in resource_attrs ] ):
+ rval.append( dict( name = pbs.ATTR_l, value = val, resource = res ) )
+ else:
+ rval.append( dict( name = getattr( pbs, 'ATTR_' + name ), value = value ) )
+ return rval
def run_next( self ):
"""
@@ -175,6 +190,7 @@
( pbs_server_name, runner_url ) = self.determine_pbs_server( runner_url, rewrite = True )
pbs_queue_name = self.determine_pbs_queue( runner_url )
+ pbs_options = self.determine_pbs_options( runner_url )
c = pbs.pbs_connect( pbs_server_name )
if c <= 0:
job_wrapper.fail( "Unable to queue job for execution. Resubmitting the job may succeed." )
@@ -185,7 +201,6 @@
ofile = "%s/%s.o" % (self.app.config.cluster_files_directory, job_wrapper.job_id)
efile = "%s/%s.e" % (self.app.config.cluster_files_directory, job_wrapper.job_id)
-
output_fnames = job_wrapper.get_output_fnames()
# If an application server is set, we're staging
@@ -195,28 +210,28 @@
output_files = [ str( o ) for o in output_fnames ]
stagein = self.get_stage_in_out( job_wrapper.get_input_fnames() + output_files, symlink=True )
stageout = self.get_stage_in_out( output_files )
- job_attrs = pbs.new_attropl(5)
- job_attrs[0].name = pbs.ATTR_o
- job_attrs[0].value = pbs_ofile
- job_attrs[1].name = pbs.ATTR_e
- job_attrs[1].value = pbs_efile
- job_attrs[2].name = pbs.ATTR_stagein
- job_attrs[2].value = stagein
- job_attrs[3].name = pbs.ATTR_stageout
- job_attrs[3].value = stageout
- job_attrs[4].name = pbs.ATTR_N
- job_attrs[4].value = "%s_%s" % ( job_wrapper.job_id, job_wrapper.tool.id )
- exec_dir = os.path.abspath( job_wrapper.working_directory )
+ attrs = [
+ dict( name = pbs.ATTR_o, value = pbs_ofile ),
+ dict( name = pbs.ATTR_e, value = pbs_efile ),
+ dict( name = pbs.ATTR_stagein, value = stagein ),
+ dict( name = pbs.ATTR_stageout, value = stageout ),
+ ]
# If not, we're using NFS
else:
- job_attrs = pbs.new_attropl(3)
- job_attrs[0].name = pbs.ATTR_o
- job_attrs[0].value = ofile
- job_attrs[1].name = pbs.ATTR_e
- job_attrs[1].value = efile
- job_attrs[2].name = pbs.ATTR_N
- job_attrs[2].value = "%s_%s" % ( job_wrapper.job_id, job_wrapper.tool.id )
- exec_dir = os.path.abspath( job_wrapper.working_directory )
+ attrs = [
+ dict( name = pbs.ATTR_o, value = ofile ),
+ dict( name = pbs.ATTR_e, value = efile ),
+ ]
+
+ # define PBS job options
+ attrs.append( dict( name = pbs.ATTR_N, value = str( "%s_%s_%s" % ( job_wrapper.job_id, job_wrapper.tool.id, job_wrapper.user ) ) ) )
+ job_attrs = pbs.new_attropl( len( attrs ) + len( pbs_options ) )
+ for i, attr in enumerate( attrs + pbs_options ):
+ job_attrs[i].name = attr['name']
+ job_attrs[i].value = attr['value']
+ if 'resource' in attr:
+ job_attrs[i].resource = attr['resource']
+ exec_dir = os.path.abspath( job_wrapper.working_directory )
# write the job script
if self.app.config.pbs_stage_path != '':
diff -r 51a1369fdf96 -r b4ba343d3540 lib/galaxy/jobs/runners/sge.py
--- a/lib/galaxy/jobs/runners/sge.py Fri Feb 05 09:23:19 2010 -0500
+++ b/lib/galaxy/jobs/runners/sge.py Fri Feb 05 10:04:04 2010 -0500
@@ -94,12 +94,24 @@
def determine_sge_queue( self, url ):
"""Determine what SGE queue we are submitting to"""
- url_split = url.split("/")
- queue = url_split[3]
- if queue == "":
- # None == server's default queue
- queue = None
- return queue
+ try:
+ return url.split('/')[3] or None
+ except:
+ return None
+
+ def determine_sge_project( self, url ):
+ """Determine what SGE project we are submitting to"""
+ try:
+ return url.split('/')[4] or None
+ except:
+ return None
+
+ def determine_sge_tool_parameters( self, url ):
+ """Determine what are the tool's specific paramters"""
+ try:
+ return url.split('/')[5] or None
+ except:
+ return None
def queue_job( self, job_wrapper ):
"""Create SGE script for a job and submit it to the SGE queue"""
@@ -132,6 +144,8 @@
# TODO: support multiple cells
log.warning( "(%s) Using multiple SGE cells is not supported. This job will be submitted to the default cell." % job_wrapper.job_id )
sge_queue_name = self.determine_sge_queue( runner_url )
+ sge_project_name = self.determine_sge_project( runner_url )
+ sge_extra_params = self.determine_sge_tool_parameters ( runner_url )
# define job attributes
ofile = "%s/database/pbs/%s.o" % (os.getcwd(), job_wrapper.job_id)
@@ -140,8 +154,15 @@
jt.remoteCommand = "%s/database/pbs/galaxy_%s.sh" % (os.getcwd(), job_wrapper.job_id)
jt.outputPath = ":%s" % ofile
jt.errorPath = ":%s" % efile
+ nativeSpec = []
if sge_queue_name is not None:
- jt.setNativeSpecification( "-q %s" % sge_queue_name )
+ nativeSpec.append( "-q '%s'" % sge_queue_name )
+ if sge_project_name is not None:
+ nativeSpec.append( "-P '%s'" % sge_project_name)
+ if sge_extra_params is not None:
+ nativeSpec.append( sge_extra_params )
+ if len(nativeSpec)>0:
+ jt.nativeSpecification = ' '.join(nativeSpec)
script = sge_template % (job_wrapper.galaxy_lib_dir, os.path.abspath( job_wrapper.working_directory ), command_line)
fh = file( jt.remoteCommand, "w" )
1
0

09 Feb '10
details: http://www.bx.psu.edu/hg/galaxy/rev/51a1369fdf96
changeset: 3334:51a1369fdf96
user: Dan Blankenberg <dan(a)bx.psu.edu>
date: Fri Feb 05 09:23:19 2010 -0500
description:
Update GeneTrack to provide tool_id as part of GALAXY_URL and rename provided 'id' to destination name of 'input'.
diffstat:
lib/galaxy/datatypes/tracks.py | 13 ++++++-------
1 files changed, 6 insertions(+), 7 deletions(-)
diffs (33 lines):
diff -r 7af418485514 -r 51a1369fdf96 lib/galaxy/datatypes/tracks.py
--- a/lib/galaxy/datatypes/tracks.py Thu Feb 04 17:00:46 2010 -0500
+++ b/lib/galaxy/datatypes/tracks.py Fri Feb 05 09:23:19 2010 -0500
@@ -6,7 +6,7 @@
from galaxy import util
from galaxy.web import url_for
from galaxy.util.hash_util import hmac_new
-import urllib
+from urllib import quote_plus
log = logging.getLogger(__name__)
@@ -23,15 +23,14 @@
if hda.has_data:
# Get the disk file name and data id
file_name = hda.dataset.get_file_name()
- data_id = urllib.quote_plus( str( hda.id ) ) #can we name this 'input' in the passed params instead of 'id' to prevent GT from having to map 'id' to 'input'?
- galaxy_url = urllib.quote_plus( "%s%s" % ( base_url, url_for( controller = 'tool_runner' ) ) )
- tool_id = urllib.quote_plus( 'predict2genetrack' )
+ data_id = quote_plus( str( hda.id ) )
+ galaxy_url = quote_plus( "%s%s" % ( base_url, url_for( controller = 'tool_runner', tool_id='predict2genetrack' ) ) )
# Make it secure
- hashkey = urllib.quote_plus( hmac_new( app.config.tool_secret, file_name ) )
- encoded = urllib.quote_plus( binascii.hexlify( file_name ) )
+ hashkey = quote_plus( hmac_new( app.config.tool_secret, file_name ) )
+ encoded = quote_plus( binascii.hexlify( file_name ) )
for name, url in util.get_genetrack_sites():
if name.lower() in app.config.genetrack_display_sites:
# send both parameters filename and hashkey
- link = "%s?filename=%s&hashkey=%s&id=%s&GALAXY_URL=%s&tool_id=%s" % ( url, encoded, hashkey, data_id, galaxy_url, tool_id )
+ link = "%s?filename=%s&hashkey=%s&input=%s&GALAXY_URL=%s" % ( url, encoded, hashkey, data_id, galaxy_url )
ret_val.append( ( name, link ) )
return ret_val
1
0

09 Feb '10
details: http://www.bx.psu.edu/hg/galaxy/rev/7af418485514
changeset: 3333:7af418485514
user: rc
date: Thu Feb 04 17:00:46 2010 -0500
description:
LIMS data acquisition: now the data transfer user logs out after the transfer is complete
diffstat:
lib/galaxy/web/controllers/requests_admin.py | 13 +++++++++--
scripts/galaxy_messaging/server/data_transfer.py | 26 +++++++++++++++++------
templates/admin/requests/show_request.mako | 2 +-
3 files changed, 30 insertions(+), 11 deletions(-)
diffs (104 lines):
diff -r ef0622415211 -r 7af418485514 lib/galaxy/web/controllers/requests_admin.py
--- a/lib/galaxy/web/controllers/requests_admin.py Thu Feb 04 16:23:32 2010 -0500
+++ b/lib/galaxy/web/controllers/requests_admin.py Thu Feb 04 17:00:46 2010 -0500
@@ -1449,8 +1449,14 @@
dataset_files=sample.dataset_files)
elif params.get( 'start_transfer_button', False ):
for f in files_list:
- sample.dataset_files.append([os.path.join(folder_path, f),
- sample.transfer_status.NOT_STARTED])
+ if f[-1] == os.sep:
+ # the selected item is a folder so transfer all the
+ # folder contents
+ sample.dataset_files.append([os.path.join(folder_path, f),
+ sample.transfer_status.NOT_STARTED])
+ else:
+ sample.dataset_files.append([os.path.join(folder_path, f),
+ sample.transfer_status.NOT_STARTED])
trans.sa_session.add( sample )
trans.sa_session.flush()
return self.__start_datatx(trans, sample)
@@ -1547,7 +1553,8 @@
trans.sa_session.flush()
return trans.response.send_redirect( web.url_for( controller='requests_admin',
action='show_datatx_page',
- sample_id=trans.security.encode_id(sample.id)))
+ sample_id=trans.security.encode_id(sample.id),
+ folder_path=os.path.dirname(dfile)))
diff -r ef0622415211 -r 7af418485514 scripts/galaxy_messaging/server/data_transfer.py
--- a/scripts/galaxy_messaging/server/data_transfer.py Thu Feb 04 16:23:32 2010 -0500
+++ b/scripts/galaxy_messaging/server/data_transfer.py Thu Feb 04 17:00:46 2010 -0500
@@ -44,6 +44,13 @@
logging.basicConfig(filename=logfile, level=logging.DEBUG,
format="%(asctime)s [%(levelname)s] %(message)s")
+class DataTransferException(Exception):
+ def __init__(self, value):
+ self.msg = value
+ def __str__(self):
+ return repr(self.msg)
+
+
class DataTransfer(object):
def __init__(self, host, username, password, remote_file, sample_id,
@@ -102,14 +109,14 @@
self.error_and_exit()
- def error_and_exit(self):
+ def error_and_exit(self, msg=''):
'''
This method is called any exception is raised. This prints the traceback
and terminates this script
'''
logging.error(traceback.format_exc())
- logging.error('FATAL ERROR')
- self.update_status('Error')
+ logging.error('FATAL ERROR.'+msg)
+ self.update_status('Error.'+msg)
sys.exit(1)
def transfer_file(self):
@@ -159,7 +166,7 @@
url = "%s/user/create?email=%s&username=%s&password=%s&confirm=%s&create_user_button=Submit" % ( base_url, email, email, password, password )
f = opener.open(url)
if f.read().find("Now logged in as "+email) == -1:
- raise Exception
+ raise DataTransferException("The "+email+" user could not login to Galaxy")
# after login, add dataset to the library
params = urllib.urlencode(dict( cntrller='library_admin',
tool_id='upload1',
@@ -177,9 +184,14 @@
logging.debug(url)
logging.debug(params)
f = opener.open(url, params)
- #print f.read()
- except:
- self.error_and_exit()
+ if f.read().find("Data Library") == -1:
+ raise DataTransferException("Dataset could not be uploaded to the data library")
+ # finally logout
+ f = opener.open(base_url+'/user/logout')
+ if f.read().find("You are no longer logged in.") == -1:
+ raise DataTransferException("The "+email+" user could not logout of Galaxy")
+ except DataTransferException, (e):
+ self.error_and_exit(e.msg)
def update_status(self, status):
'''
diff -r ef0622415211 -r 7af418485514 templates/admin/requests/show_request.mako
--- a/templates/admin/requests/show_request.mako Thu Feb 04 16:23:32 2010 -0500
+++ b/templates/admin/requests/show_request.mako Thu Feb 04 17:00:46 2010 -0500
@@ -43,7 +43,7 @@
</script>
<style type="text/css">
.msg_head {
- padding: 15px 0px;
+ padding: 10px 0px;
cursor: pointer;
}
1
0
details: http://www.bx.psu.edu/hg/galaxy/rev/ef0622415211
changeset: 3332:ef0622415211
user: jeremy goecks <jeremy.goecks(a)emory.edu>
date: Thu Feb 04 16:23:32 2010 -0500
description:
Make slugging editing possible on IE.
diffstat:
static/scripts/galaxy.base.js | 2 ++
templates/sharing_base.mako | 21 +++++++++++++++------
2 files changed, 17 insertions(+), 6 deletions(-)
diffs (59 lines):
diff -r 212ee5294e56 -r ef0622415211 static/scripts/galaxy.base.js
--- a/static/scripts/galaxy.base.js Thu Feb 04 11:56:58 2010 -0500
+++ b/static/scripts/galaxy.base.js Thu Feb 04 16:23:32 2010 -0500
@@ -222,6 +222,8 @@
t.blur( function() {
$(this).remove();
$("#" + text_elt_id).show();
+ if (on_finish != null)
+ on_finish(t);
});
t.keyup( function( e ) {
if ( e.keyCode == 27 ) {
diff -r 212ee5294e56 -r ef0622415211 templates/sharing_base.mako
--- a/templates/sharing_base.mako Thu Feb 04 11:56:58 2010 -0500
+++ b/templates/sharing_base.mako Thu Feb 04 16:23:32 2010 -0500
@@ -25,10 +25,9 @@
//
var on_start = function( text_elt )
{
- // Because text element is inside a URL, need to disable click so that clicking on element does not trigger URL.
- $( text_elt ).click( function() {
- return false;
- });
+ // Replace URL with URL text.
+ $('#item-url').hide();
+ $('#item-url-text').show();
// Allow only lowercase alphanumeric and '-' characters in slug.
text_elt.keyup(function(){
@@ -38,9 +37,15 @@
var on_finish = function( text_elt )
{
+ // Replace URL text with URL.
+ $('#item-url-text').hide();
+ $('#item-url').show();
+
// Set URL to new value.
+ var new_url = $('#item-url-text').text();
var item_url_obj = $('#item-url');
- item_url_obj.attr( "href", item_url_obj.text() );
+ item_url_obj.attr( "href", new_url );
+ item_url_obj.text( new_url );
};
<% controller_name = get_controller_name( item ) %>
@@ -117,7 +122,11 @@
url = h.url_for( action='display_by_username_and_slug', username=trans.get_user().username, slug=item.slug, qualified=True )
url_parts = url.split("/")
%>
- <a id="item-url" href="${url}" target="_top">${"/".join( url_parts[:-1] )}/<span id='item-identifier'>${url_parts[-1]}</span></a>
+ <a id="item-url" href="${url}" target="_top">${url}</a>
+ <span id="item-url-text" style="display: none">
+ ${"/".join( url_parts[:-1] )}/<span id='item-identifier'>${url_parts[-1]}</span>
+ </span>
+
<a href="#" id="edit-identifier"><img src="${h.url_for('/static/images/pencil.png')}"/></a>
</blockquote>
1
0

09 Feb '10
details: http://www.bx.psu.edu/hg/galaxy/rev/212ee5294e56
changeset: 3331:212ee5294e56
user: gua110
date: Thu Feb 04 11:56:58 2010 -0500
description:
Added functional test for hyphy NJ tree builder.
diffstat:
test-data/dnds_out.dat | 12 ---
test-data/nj_tree_inp.fasta | 134 ++++++++++++++++++++++++++++++++++
tools/hyphy/hyphy_nj_tree_wrapper.xml | 5 +-
3 files changed, 135 insertions(+), 16 deletions(-)
diffs (176 lines):
diff -r 3626bd87bff9 -r 212ee5294e56 test-data/dnds_out.dat
--- a/test-data/dnds_out.dat Thu Feb 04 11:42:25 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,12 +0,0 @@
-GENE BP S_sites NS_sites Stop_codons LogL omega omega_range AC AT CG CT GT Tree
-1 1554 355.669 1129.12 1 -2747.41 0.101159 0.0765061-0.130636 1 1 1 1 1 (human:0,chimp:0.00240762,mouse:0.146649)
-2 3795 924.935 2749.35 1 -5781.01 0.0179485 0.0119925-0.02562 1 1 1 1 1 (human:0.0004305,chimp:0.00147714,mouse:0.144943)
-3 1194 272.323 881.914 1 -2043.72 0.0578339 0.0372207-0.0849736 1 1 1 1 1 (human:0.00285309,chimp:0.00410455,mouse:0.11988)
-4 1146 248.261 850.364 1 -1871.67 0.012771 0.00548036-0.0247371 1 1 1 1 1 (human:0,chimp:0.00093192,mouse:0.147209)
-5 1500 366.374 1086.09 2 -2522.97 0.0331894 0.0203743-0.0505255 1 1 1 1 1 (human:0,chimp:0.00225976,mouse:0.156089)
-6 3444 824.107 2475.54 1 -5459.18 0.0439755 0.0326426-0.0576899 1 1 1 1 1 (human:0.000512784,chimp:0.00203485,mouse:0.126653)
-7 2175 505.186 1587.7 0 -3307.52 0.0712367 0.0564019-0.088443 1 1 1 1 1 (human:0.00229486,chimp:0.00236745,mouse:0.226418)
-8 3519 792.702 2601.36 0 -6219.39 0.0669992 0.0568977-0.078214 1 1 1 1 1 (human:0.00103092,chimp:0.00431199,mouse:0.251293)
-9 501 100.22 376.039 1 -834.329 0.13041 0.0835498-0.192248 1 1 1 1 1 (human:0,chimp:0,mouse:0.150462)
-10 633 160.252 453.228 1 -618.997 0.0150887 0.00250412-0.0467112 1 1 1 1 1 (human:0,chimp:0.00611143,mouse:0.104315)
-11 915 229.705 658.82 0 -1664.02 0.299737 0.227826-0.385548 1 1 1 1 1 (human:0.0045721,chimp:0,mouse:0.145563)
diff -r 3626bd87bff9 -r 212ee5294e56 test-data/nj_tree_inp.fasta
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/nj_tree_inp.fasta Thu Feb 04 11:56:58 2010 -0500
@@ -0,0 +1,134 @@
+>hg17.chr7(+):127471195-127471526|hg17_0
+gtttgccatcttttgctgctctagggaatccagcagctgtcaccatgtaaacaagcccaggctagaccaGTTACCCTCATC---ATCTTAGCTGATAGCCAGCCAGCCACCACAGGCAtgagtcaggccatattgctggacccacagaattatgagctaaataaatagtcttgggttaagccactaagttttaggcatagtgtgttatgtaTCTCACAAACATATAAGACTGTGTGTTTGTTGACTGGAGGAAGAGATGCTATAAAGACCACCTTTTAAAACTTCCCAAATACTGCCACTGATGTCCTGATGGAGG-------------------------------------------------------TATGAA---------AACATCCACTAA
+>panTro1.chr6(+):129885076-129885407|panTro1_0
+gtttgccatcttttgctgctcttgggaatccagcagctgtcaccatgtaaacaagcccaggctagaccaGTTACCCTCATC---ATCTTAGCTGATAGCCAGCCAGCCACCACAGGCAtgagtcaggccatattgctggacccacagaattatgagctaaataaatagtcttgggttaagccactaagttttaggcatagtgtgttatgtaTCTCACAAACATATAAGACTGTGTGTTTGTTGACTGGAGGAAGAGATGCTATAAAGACCACCTTTTGAAACTTCCCAAATACTGCCACTGATGTCCTGATGGAGG-------------------------------------------------------TATGAA---------AACATCCACTAA
+>rheMac2.chr3(+):165787989-165788319|rheMac2_0
+gcttgccatcttttgatgctcttgggaatccagcagctgtcaccat-taaacaagcccaggctagaccaGTTACCCTCATC---ATCTTAGCTGATAGCCAGCCAGCCACCATAGGCAtgagtcaggccatagtgctggacccacagaattatgagctaaataagtagtgttgggttaagtcactaagttttaggcatagtgtgttatgtagcTCACAAACATATAAGACTGTGTGTTTTTTGACTGGAGGAAGAGATGCCATAAAGACCACCTTTTGAAACTTCTCAAATACTGCCATTGATGTGCTGATGGAGG-------------------------------------------------------TATGAA---------AACATCCACTAA
+>rn3.chr4(+):56178191-56178473|rn3_0
+CTTCACTCTCATTTGCTGTT----------------CTGTCACTATGGAGACAAACACAGGCTAGCCCAGTTACTATCTTGATCACAGCAGCTGT----CAGCTAGCTGCCACTCACAGGAATAAGGCCATACCATT-GATCCACTGAACCTTGATCTAGGAATTTGGC----------------------TGGGGCCAGTTTGCGGTGTCACTCATGA--CTCTAAGATTGTGTGTTTG----CTCCAGGAAGAGACGGCAAGAGGATTACCTTTAAAAGGTTCGG-AGTCTAGCTGTAGACAGCCCAATGGG---------------------------------------------------------TATAAC---------AATACTCACTAA
+>mm7.chr6(+):28984529-28984886|mm7_0
+CTCCACTCTCGTTTGCTGTT----------------CTGTCACCATGGAAACAAACG-AGGGTGGTCCAGTTACTATCTTG---ACTGCAGCTGG----CAGTCAGTTGCCACT--CAGGAATAAGGCTATGCCATT-GATCCACTGAACCGTGATCTGGAAACCTGGCTGTTGTTT-------CAAGCCTTGGGGCCAGTTTGCGGTGTTACTCATGA--CTCTAAGATCGTGTGCTTG----CTGCAGGAAGAGACAGCAAGGGGGTTACATTTAAAAAGCCCCC-AGTTTAGCTATAGGCAGGCCAACAGGTGTAAAAATACTCACTAGTAATGGGCTGAACTCATGGAGGTAGCATTAGTGAGACACTGTAACTGTTTTTTTAAAAATCACTAA
+
+>hg17.chr7(+):127471526-127471584|hg17_1
+AATTTGTGGTTTATTCATTTTTCATTATTTTGTTTAAGGAGGTCTATAGTGGAAGAGG
+>mm7.chr6(+):28984886-28984940|mm7_1
+----AACGTTTCATTGATTGCTCATCATTTAAAAAAAGAAATTCCTCAGTGGAAGAGG
+>rheMac2.chr3(+):165788319-165788377|rheMac2_1
+AATTTGTGGTTTATTTATTTTTCATTATTTTGTTTAAGGAGGTCTATAGTGGAAGAGG
+>panTro1.chr6(+):129885407-129885465|panTro1_1
+AATTTGTGGTTTATTCGTTTTTCATTATTTTGTTTAAGGAGGTCTATAGTGGAAGAGG
+
+>hg17.chr7(+):127471584-127471688|hg17_2
+GAGATATTT-GGggaaatttt-gtatagactagctt--tcacgatgttagggaattattattgtgtgataatggtcttgcagttac-acagaaattcttcctta-ttttt
+>panTro1.chr6(+):129885465-129885569|panTro1_2
+GAGACATTT-GGggaaatttt-gtatagactagctt--tcacgatgttagggagttattattgtgtgataatggtcttgcagttac-acagaaattcttcctta-ttttt
+>rheMac2.chr3(+):165788377-165788482|rheMac2_2
+GAGATATTT-GGggaaatttg-gtatagactagctt--tcatgatgtaagggagttatttttgtgtgataatggccctacagttac-acagaaattcttccttatttttt
+>canFam2.chr14(-):11090703-11090811|canFam2_2
+gagatattt-gggggaatttgaatgtagtgttgctcttttgtgatgctaagaaattataattgtctgatgatagtctcgtggttatgggggaaatgcttcctta-ttttt
+>bosTau2.chr4(-):50243931-50244034|bosTau2_2
+-agacattg-ggtaaaattcaaatgcagactagctc----atgatgttaaagaattactcttgtgtggtaatggtcttgtgatagagatagaaatgcttcctta-ttttt
+>rn3.chr4(+):56182200-56182295|rn3_2
+----TATTTGGGGGAAATATG-ATGTGCA----CTT--CCATGATCTTAAAGAATTGCTACTGTTTGATAGTGATCTTATGGTTAA-ATAAAAAAAAT--CTTA-GTTGT
+>dasNov1.scaffold_256527(+):298-392|dasNov1_2
+GAGACATTT-GGAGAAATTTG-----------Aatt--tcatgatgttaaggaattacttttgtatgatgatggtcttgtggctat-gtagaatttcttccgtg-tttta
+
+>hg17.chr7(+):127471688-127471871|hg17_3
+tgggaagcaccaaagta-------gggataaaatgtcatgatgtgtgcaatacactttaaaatgtttttgccaaaa----------taattaa-------------------------tgaagc--aaatatg---gaaaataataattattaaatctaggt-----gatgggtatattgtagttcactatagtattgcacacttttctgtatgtttaaatttttcattta--------------------------aaaa-
+>panTro1.chr6(+):129885569-129885752|panTro1_3
+tgggaaacaccaaagta-------gggataaaatgtcatgatgtgtgcaatacgctttaaaatatttttgccaaaa----------taattaa-------------------------tgaagc--aaatatg---gaaaataataattattaaatctaggt-----gatgggtatattgtagttcactatagtattgcacacttttctgtatgtttaaaattttcattta--------------------------aaaa-
+>rheMac2.chr3(+):165788482-165788684|rheMac2_3
+tgggaagcacaaaagta-------gggataaaatgtcatgatgtgtacaatatgctttaaaatatttttgccaaaa----------taattaa-------------------------tgaagc--aaatatg---gaaaataataactgttaaatctaggt-----gttgggtatattgcagttcattatgttattgcacacttttctgtgtgtttaaaattttcatttaaaaatatgttttaaaaatg-------aaaa-
+>rn3.chr4(+):56182295-56182489|rn3_3
+TAGAAAATACTCAAATATTTAGGGGCGTGACAATGTCACAGTGTCTGCAATTTGCTTTAAAGATTTTT-----AAA----------TATTTAAAAAAGTTTTAATAATTTTGAAAAACTGAAGCTACACTATG---GGAAGTGGTAATTGTTACATATGGGT-----AATAAGTAT-----AATTCGTTATATTAT-------TTTTC------TTAGAATTTTTCATTTG--------------------------AAAA-
+>bosTau2.chr4(-):50243792-50243930|bosTau2_3
+agataaacacttaagtattta---aggatgaaacgccctgatgtttgtaatttgctttagaatattttagccaaaa----------gaattaa-------------------------tgatgc--aaatatg--caaaaagagta--cgttaaacctaa-----------------------------------------------------atttgCGATTttcattta--------------------------aaaa-
+>canFam2.chr14(-):11090345-11090505|canFam2_3
+agacacaaactgaagtattta---aggatgaaatgtcatgatgtttgcaattggctttaaaatattttagccaaaa-----------agtaaa-------------------------tgaagc--AAATATG--GGAAGACAATAATCATTAAATCTAGGT-----GATGCATAC---------------------------TTTTCCATATGTTTGAAATTTTCATTTA--------------------------AAAA-
+>dasNov1.scaffold_256527(+):393-625|dasNov1_3
+agacgcatgctgaagcatgta---aggataaaatgtcgtggtgtttgtaatttattctaaaacattttagccaaaaacaaataaataaataaa-------------------------tgaagc--aaatatgggggaaatgtttaattgttaaatctagatttaacacggtatataccgtgcttcattatactagtctctacttttccatgtgtttgaaattttCATTAAAATGTTTGTTTGTTGTCTGTTTTAATGAAAT
+
+>hg17.chr7(+):127471871-127471910|hg17_4
+actttgagctagacaccaggctatgagcta-ggagcatag
+>rheMac2.chr3(+):165788684-165788723|rheMac2_4
+actttgagctagataccaggttatgagcta-ggagcatag
+>panTro1.chr6(+):129885752-129885791|panTro1_4
+actttgagctagacaccaggctatgagcta-ggagcatag
+>bosTau2.chr4(-):50243734-50243773|bosTau2_4
+tcttcgtgcaacgcacggggctatcaatgt-gggatacag
+>canFam2.chr14(-):11090081-11090120|canFam2_4
+ACATCAtgctagatcctggactatgagctg-ggtatatag
+>dasNov1.scaffold_256527(+):625-665|dasNov1_4
+CCTTTGTGCTAGCCACTGGGATGAAAGCTAGGGAACACAG
+
+>hg17.chr7(+):127471910-127472074|hg17_5
+caatgaccaa----------------------------------------------------------------------------------------------atagactcctaccaa-ctc-aaagaatgcacattctCTG-GGAAACATGTTTCCATTAGGAAGCCTCGAATGCAATGTGACTGTGGTCTCCAGGACCTG-TGTGATCCTGGCTTTTCCTGTTCCCTCCG---CATCATCACTGCAGGTGTGTTTTCCCAAG
+>panTro1.chr6(+):129885791-129885955|panTro1_5
+caatgaccaa----------------------------------------------------------------------------------------------atagactcctaccaa-ctc-aaagaatgcacattctCTG-GGAAACATGTTTCCATTAGGAAGCCTCGAATGCAATGTGACTGTGGTCTCCAGGACATG-TGTGATCCTGGCTTTTCCTGTTCCCTCTG---CATCATCACTGCAGGTGTATTTTCCCAAG
+>rheMac2.chr3(+):165788723-165788885|rheMac2_5
+caatgaccaa----------------------------------------------------------------------------------------------atagacccctaccga-ctc-aaagaatgtacattctTTG-GGAAACATGTTTCCATCAGAAAATCTCAAATGCAATGTGACTGGGGTCTCCAGGACCTG-TGTGAGCCTGGCTTTTCCTGTTCCCTCCA---CATCATCACTGCAGGTGTATTTTCCC--G
+>mm7.chr6(+):28990714-28990875|mm7_5
+caaaaaccaa------------------------------------------------------------------------------------------------aaaaACCTATAGC-CTC-ACAGGGTGGGTTGTCTTTG-AGGAACATGCATCCGCTAGAAAGTCCCAAGTACACTATGACAGTTG--CCCAGGCCCCGCCTTAAACCTGGTTTTCCTGGTTTCTTTCA---CATCATTACCACGAATATATTTCCTCAAG
+>rn3.chr4(+):56183448-56183705|rn3_5
+--ATGACCAATATACACTGTTTACATGTATAGCATTGTGAATGGAGACATAAAAAGATAATCTAGCTTTGTGCTAGGTAGGTGCTGAGCTCTTAACAGTGCTGGGCAGAAACCTATAAC-CTC-ACAGGGTGGGTTGTCTTTG-AGGAGCGTGCTAACCCTAGGAAGTCTCAAATACAATGTGATGGTTGCCCCCAGGCACCACCTTGAACCTGGTCTTCCTGGTTTCTTTCA---CACCATTACCACAAATACATTTTCTCAGG
+>bosTau2.chr4(-):50243566-50243734|bosTau2_5
+atgtgaacaa---------------------------------------------------------------------------------------------aacggacccgtgtgggactcggcggagcacacagattttgcgggagCACGTTCCCGTTAGGAAGTCTCTGATGCAATACGACCGGTGCCTTCAGGACCTG-TG--AGGCTGACTTTCCTTA-CCCCTCCACACCATCATCAAGGCAGGTGTGATTTTCCAGG
+>canFam2.chr14(-):11089913-11090081|canFam2_5
+cagtgaacaa---------------------------------------------------------------------------------------------aacagagccctgcagt-cttgatggagcacacaacctttg-gggaaCATGTTTCCATAAGAAAGTCTCCAATGTGATCTGA-TGGTGCCGCCAGGACCTA-TGTCAGCCTACCGTTCCATGTCCCCTCCACACCATCATCACTGCAGGTGTGTTTTCCCACA
+>dasNov1.scaffold_256527(+):665-786|dasNov1_5
+CAGTGAGCAA-----------------------------------------------------------------------------------------------CAGCCTGGCTCCGT-CC--GGGGGCCGCTCAGCAGCTC-GGGAGCGTGGAGACG---GGAAGTCTGTCACGCGATGCG-----------CTGGGCCCG------------CTGTTCCCGCCCCCCTCC---CCCC----------------TTTCCCAAG
+
+>hg17.chr7(+):127472074-127472258|hg17_6
+TTTTAAA------CATTTACCTTCCCAGTGGCCTTGCGTCTAGAGGAATCCCTGTATAGTGGT-ACATGAATATAACACATAACAAA-AATCATCTCTATGGTGTGTGTTGTTCCTGGGGTTCAattcagcaaatttt-ccc-tgggcacccatgtgttcttggcactggaaaagtaccgggactgaaacagtt
+>panTro1.chr6(+):129885955-129886139|panTro1_6
+TTTTAAA------CATTTACCTTCCCAGTGGCCTTGCGTCTAGAGGAATCCCTGTATAGTGGT-ACATGAATATAACACATAACAAA-AATCATCTCTATGGTGTGTGTTGTTCCTGGGGTTCAattcagcaaatttt-tcc-tgggcacccatgtgttcttggcactggaaaagtaccgggactgaaacagtt
+>rheMac2.chr3(+):165788885-165789069|rheMac2_6
+TTTTAAA------CATTTACTCTCCCAGTAGCCTTGCATCTCGAGGAATCCCTGTATAGTGGT-ACATGAATATAACACATAACAAA-AATCATCTGTACGGTGTGTGTTGTTCCTGGGGTTCAattcagcaaatttt-tcc-tgggcacccctgtgttcttggcactggaaaagtaccaggacttaaatagta
+>mm7.chr6(+):28990875-28991025|mm7_6
+TTTAAAGAAAGTACCCCCTCCTTTCCAGT-GCCTCAAATCTAGAAGAATATTCATAGTGAAGT-GC------------------------ACAGCCGGGTGGTGCATGGTA-ATCTGGAAGTCACCTCTGCAAATCTT-TCC----------------TGTTGGTGCTGTGAAGGCACCAGGACTTCAAGAGTA
+>rn3.chr4(+):56183705-56183879|rn3_6
+TTTAAAAGAAGT-CCCACTCCTTTCCAGT-GCCCTAGATCTAGAAGCACATTCATAATGATGT-ACAC-----TAACCC----------GACAGCTGTGTGGTATATGGTA-TCCCGGAAGTCACCTCAGCAAACCTT-TCCCGGGGAACCTACATGGTGTTGGTGCTGTGAAGGTACCAGGTTGTCAAGGGTA
+>canFam2.chr14(-):11089743-11089913|canFam2_6
+TTTTAAA------TATCTGC-TTCCCGGTGGCCTTGAGTCTAGAGGAGTCCCCCCACTATGGTGGCACTAATACTGAAGGTCAGAAATAATCAGTTCTGTGGTGCATGTTGCCCCTGAGGTTCTGTTCGGGAAACTTC-TTC-TGAGCAC----ATGCACCTGGCACTGCAAACGTACCAGGA-----------
+>dasNov1.scaffold_256527(+):786-964|dasNov1_6
+TTTTAAA------AATTTACCTTCCCAGTGGCGGTGAATCCGGAGGAATACGGAAACTGGGGC-GCACTACCATGACACGTGTCAAA-AATCAGTTCCGTGGTCCGTGGAGGGCCTGGGGTTC------GAAAATCTTGTCC-CGAGCACCCCCGTGCGCCTGGCACCGCGACAGTGACAGGACTGAAGCGTG-
+
+>hg17.chr7(+):127472258-127472280|hg17_7
+gatggccca-atccctgtcctct-
+>panTro1.chr6(+):129886139-129886161|panTro1_7
+gatggccca-atccctgtcctct-
+>rheMac2.chr3(+):165789069-165789091|rheMac2_7
+gatggccca-atccctgtcctct-
+>mm7.chr6(+):28991025-28991048|mm7_7
+AATGGCAGAGGGCTCTGTTCTCT-
+>rn3.chr4(+):56183879-56183902|rn3_7
+AATGGCAGAGGCCCCTGTTCTCT-
+>canFam2.chr14(-):11089526-11089548|canFam2_7
+GGAGACTTG-ATGCCTGCCTTCC-
+>dasNov1.scaffold_256527(+):964-987|dasNov1_7
+GACGGCCAG-ACCTCTGCCCTCGG
+
+>hg17.chr7(+):127472280-127472681|hg17_8
+taaaacctaagggaggagaTGGAAAG-GGGCACCCAACCCAGACTGAGAGACAGGAATTAGCTGCAAGGGGAACTAGGAAAAGCTTCTTTA---AGGATG--GAGAGGCCCTA-GTGGAATGGGGAGATTCTTCCGGGAGAAGCGATGGATGCACAGTTGGGCATCCCCACAGACGGACTGGAAAGAAAAAAGGCCTGGAGGAATCA------ATGTGC-AATGTATGTGTGTTCCCTGGTTcaagggctgg-gaactttctcta--aagggccaggtagaaaacattttaggctttctaagccaagg---caaaattgaggat-attacatgggtacttatacaacaagaataaacaatt---tacacaa-ttttttgttgacagaattcaaaa---ctttat----agacac---agaaatgcaaatttcctgt
+>panTro1.chr6(+):129886161-129886562|panTro1_8
+taaaacctaagggaggagaTGGAAAG-GGGCACCCAACCCAGACTGAGAGACAGGAATTAGCTGCAAGGGGAACTAGGAAAAGCTTCTTTA---AGGATG--GAGAGACCCTA-GTGGAATGGGGAGATTCTTCCGGGAGAAGCGATGGATGCGCAGTTGGGCATCCCCACAGACGGACTGGAAAGAAAAAAGGCCTGGAGGAATCA------ATGTGC-AATGTATGTGTGTTCCCTGGTTcaagggctgg-gaactttctcta--aagggccaggtagaaaacattttaggctttctaagccaagg---caaaattgaggat-attacatgggtacttatacaacaagaataaacaatt---tacacaa-ttttttgttgacagaattcaaaa---ctttat----agacac---agaaatgtaaatttcctgt
+>rheMac2.chr3(+):165789091-165789492|rheMac2_8
+taaaacctaatggaggagatggaATG-GGTCACCCAACCCGGACTGAGAGACAGGAATTAGCTGCAAGGGTAACCAGGACAAGCTTCTCTA---ATGATG--GAGAGACCCTA-GTGGAATGGGGAGATTCTTCTGGGAGAAGCGATGGATTCGTAGTTGGGCATCCCCACAGAGGGACTGGAAAGAAAAAAGACCTGGAGGAACCA------ATGTGC-AATGTATGTGTGTTTCCTGGTTcaagggctggcaaactttctcta--aagggccagatagaaaacattttaggctttgtaagccaagg---caaaatcgaggag-attacatgggtacttatacaacaagaataaacaatt---tccacaa--tttttattcacagaattcaaaa---ctttat----agacac---agaaatgtaaatttcctgt
+>rn3.chr4(+):56183902-56184219|rn3_8
+------------------------------------GTCCATAGTCAAAG------------------------------AAGCCTCTCAG---ATGGAG--AGCAGGGCCTATGCAAAAGAGGGGGCTTCTGTAGGCAGAAGGGATGGACTAGCCTCCGGACATAGCCATAGAGAGGCTGGCAGGACTGAGACCCAGGAGAAGCCAGCGCAGGTGTGCGGGCGTGTGTATATTTCATAGTTTGCAGGTTGG----------------------------CAAACAATTCCTGCTTTGCAGGCCAAGA---GGAAACTGAAGGTGACCCCGTGAGTGCTTAC---ACAAGAGAAAACAAG-------ACAA-TTTTTGGTTGACCAAATTCAGAA---CTTTATTTGAGGATGC---TAAAGTTTAAATTTCTTTT
+>canFam2.chr14(-):11089143-11089523|canFam2_8
+TACAGCCTGTGGGCAGAGGTGGGAAGAGGTCACGCAAGCCAGTTGGAATGAGGGGAGTTGGCTGGAAAGGTGACCAGGACAAGCTACTTCAACCAGGAAG--AAGAGACCCCG-GTG----------------CTTGGAGAAGGCCTGATTGAGCAGTCCTGCATGCCCGCCCAC-GACTGGCAGGAATAAAGACCCAGAAGAGCTA------ACGTGC-AATGTA------TTTTCTAGTTCCAgggttggcaaactttctctct-aagggtgggatgataaacattttaggcttttcagaccaaga---ggcgacatcagag-ggtatgtaggt---------acaagagggaaaagttgcccccggaa-ttttttg--gataaaattcaaaa---ctttacttagggatgc---caaaatgtaaacttcatat
+>dasNov1.scaffold_256527(+):987-1401|dasNov1_8
+CTAAATCTCGCGGAGAAGGTGGAACA-GGTTACCCAAACCCGACCGAG-GAGGCGAGTTG---GAAACGGCGACTGGGACAAGCTCCCTCA---GAGACGGAGAGAGACCCCA-GTGGAAGGGGGGAGAGGCTCTTAGGGAAACGATGGGGGGACCCGCCCGCACCCGCACAGAGGCGCTGGCAGGCACAGCGGCCCCGAGGAGCCC------AGGAGC-AGGGC-TGTGT-TCCCCTGCATcaggggttggcaaactttttctgcaaagggccagatagtaaatattttaggctttgcaaaccaagaagtagaaagggaggcc-attatgtacgtatttatatagcaagagagaacattt---cccacaatttttttattgacagaatttaaaacttctttattgatgaacaccaaagaaacttgaatttcatat
+
+>hg17.chr7(+):127472681-127472715|hg17_9
+aattttcccat---gagaactattcttcttttgtttt
+>rheMac2.chr3(+):165789492-165789526|rheMac2_9
+aattttcacat---aagaactattcttcttttgtttt
+>panTro1.chr6(+):129886562-129886596|panTro1_9
+aattttcccgt---gagaactattcttcttttgtttt
+>canFam2.chr14(-):11089108-11089143|canFam2_9
+aatggtcatgt--ccataactattcttcttttatttt
+>dasNov1.scaffold_256527(+):1401-1433|dasNov1_9
+aattttcacatatcacgaagtatttttttttt-----
+
diff -r 3626bd87bff9 -r 212ee5294e56 tools/hyphy/hyphy_nj_tree_wrapper.xml
--- a/tools/hyphy/hyphy_nj_tree_wrapper.xml Thu Feb 04 11:42:25 2010 -0500
+++ b/tools/hyphy/hyphy_nj_tree_wrapper.xml Thu Feb 04 11:56:58 2010 -0500
@@ -29,17 +29,14 @@
<requirements>
<requirement type="binary">ps2pdf</requirement>
</requirements>
- <!--
- test fails for pdf generated by hyphy. Commenting out that particular output breaks the test again.
<tests>
<test>
- <param name="input1" value="cf_maf2fasta.dat"/>
+ <param name="input1" value="nj_tree_inp.fasta"/>
<param name="distance_metric" value="TN93"/>
<output name="out_file1" file="nj_tree_newick_out.tabular"/>
<output name="out_file2" file="nj_tree_pdf_out.pdf"/>
</test>
</tests>
- -->
<help>
This tool takes a single or multiple FASTA alignment file and builds Neighbor Joining Trees using HYPHY_, a maximum likelihood analyses package.
1
0

09 Feb '10
details: http://www.bx.psu.edu/hg/galaxy/rev/3626bd87bff9
changeset: 3330:3626bd87bff9
user: rc
date: Thu Feb 04 11:42:25 2010 -0500
description:
sample config file for specifying the user
diffstat:
transfer_datasets.ini.sample | 5 +++++
1 files changed, 5 insertions(+), 0 deletions(-)
diffs (9 lines):
diff -r 37b55fad152b -r 3626bd87bff9 transfer_datasets.ini.sample
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/transfer_datasets.ini.sample Thu Feb 04 11:42:25 2010 -0500
@@ -0,0 +1,5 @@
+# Galaxy LIMS Transfer Datasets Configuration File
+
+[data_transfer_user_login_info]
+#email = user(a)example.com
+#password =
1
0
details: http://www.bx.psu.edu/hg/galaxy/rev/37b55fad152b
changeset: 3329:37b55fad152b
user: rc
date: Thu Feb 04 11:01:45 2010 -0500
description:
Sequencer data acquisition for LIMS
- Add a data transfer script which fetches datasets from the sequencer
- transfer_datasets.ini for setting up the separate user to login to Galaxy programmatically to add datasets to the data libraries.
- Added a dataset transfer page which includes remote file browser to select files for transfer
Removed library & folder foreign keys from the request table and added them to the sample table. Also the sample table now has a dataset_files column to store the datatsets and the their transfer status.
Add an egg for pexpect which is used in the remote file browser.
The request_type table has a new column datatx_info which stores all the login info for the sequencer machine
diffstat:
eggs.ini | 2 +
lib/galaxy/model/__init__.py | 76 +-
lib/galaxy/model/mapping.py | 16 +-
lib/galaxy/model/migrate/versions/0019_request_library_folder.py | 2 +-
lib/galaxy/model/migrate/versions/0037_samples_library.py | 124 +
lib/galaxy/web/controllers/requests.py | 472 +++--
lib/galaxy/web/controllers/requests_admin.py | 766 ++++++---
lib/galaxy/web/framework/__init__.py | 4 +-
scripts/galaxy_messaging/server/daemon.py | 34 +
scripts/galaxy_messaging/server/data_transfer.py | 211 ++
scripts/galaxy_messaging/server/galaxydb_interface.py | 11 +
templates/admin/forms/edit_form.mako | 42 +-
templates/admin/forms/show_form_read_only.mako | 6 +-
templates/admin/requests/create_request_type.mako | 16 +
templates/admin/requests/get_data.mako | 135 +
templates/admin/requests/show_request.mako | 313 ++-
templates/admin/requests/view_request_type.mako | 37 +-
templates/requests/show_data.mako | 86 +
templates/requests/show_request.mako | 299 ++-
test/base/twilltestcase.py | 25 +-
test/functional/test_forms_and_requests.py | 18 +-
21 files changed, 1981 insertions(+), 714 deletions(-)
diffs (truncated from 3628 to 3000 lines):
diff -r 44fff02fb036 -r 37b55fad152b eggs.ini
--- a/eggs.ini Thu Feb 04 10:44:36 2010 -0500
+++ b/eggs.ini Thu Feb 04 11:01:45 2010 -0500
@@ -40,6 +40,7 @@
Paste = 1.6
PasteDeploy = 1.3.3
PasteScript = 1.7.3
+pexpect = 2.3
Routes = 1.11
simplejson = 1.5
SQLAlchemy = 0.5.6
@@ -72,6 +73,7 @@
DRMAA_python = http://gridengine.sunsource.net/files/documents/7/36/DRMAA-python-0.2.tar.gz
MySQL_python = http://superb-west.dl.sourceforge.net/sourceforge/mysql-python/MySQL-python… http://downloads.mysql.com/archives/mysql-5.0/mysql-5.0.67.tar.gz
pbs_python = http://ftp.sara.nl/pub/outgoing/pbs_python-2.9.4.tar.gz
+pexpect = http://pexpect.sourceforge.net/pexpect-2.3.tar.gz
psycopg2 = http://initd.org/pub/software/psycopg/PSYCOPG-2-0/psycopg2-2.0.6.tar.gz ftp://ftp-archives.postgresql.org/pub/source/v8.2.6/postgresql-8.2.6.tar.bz2
pycrypto = http://www.amk.ca/files/python/crypto/pycrypto-2.0.1.tar.gz
pysam = http://bitbucket.org/kanwei/kanwei-pysam/get/e3c601a062fd.gz
diff -r 44fff02fb036 -r 37b55fad152b lib/galaxy/model/__init__.py
--- a/lib/galaxy/model/__init__.py Thu Feb 04 10:44:36 2010 -0500
+++ b/lib/galaxy/model/__init__.py Thu Feb 04 11:01:45 2010 -0500
@@ -53,6 +53,25 @@
if role not in roles:
roles.append( role )
return roles
+ def accessible_libraries(self, trans, actions):
+ # get all permitted libraries for this user
+ all_libraries = trans.sa_session.query( trans.app.model.Library ) \
+ .filter( trans.app.model.Library.table.c.deleted == False ) \
+ .order_by( trans.app.model.Library.name )
+ roles = self.all_roles()
+ actions_to_check = actions
+ # The libraries dictionary looks like: { library : '1,2' }, library : '3' }
+ # Its keys are the libraries that should be displayed for the current user and whose values are a
+ # string of comma-separated folder ids, of the associated folders the should NOT be displayed.
+ # The folders that should not be displayed may not be a complete list, but it is ultimately passed
+ # to the calling method to keep from re-checking the same folders when the library / folder
+ # select lists are rendered.
+ libraries = {}
+ for library in all_libraries:
+ can_show, hidden_folder_ids = trans.app.security_agent.show_library_item( self, roles, library, actions_to_check )
+ if can_show:
+ libraries[ library ] = hidden_folder_ids
+ return libraries
class Job( object ):
"""
@@ -1206,21 +1225,15 @@
self.form_definition_current = form_definition_current
self.type = form_type
self.layout = layout
- def fields_of_grid(self, layout_grid_name):
- fields_dict = {}
- if not layout_grid_name:
- for i, f in enumerate(self.fields):
- fields_dict[i] = f
- else:
- layout_index = -1
- for index, lg_name in enumerate(self.layout):
- if lg_name == layout_grid_name:
- layout_index = index
- break
- for i, f in enumerate(self.fields):
- if f['layout'] == str(layout_index):
- fields_dict[i] = f
- return fields_dict
+ def fields_of_grid(self, grid_index):
+ '''
+ This method returns the list of fields belonging to the given grid.
+ '''
+ gridfields = {}
+ for i, f in enumerate(self.fields):
+ if str(f['layout']) == str(grid_index):
+ gridfields[i] = f
+ return gridfields
def get_widgets( self, user, contents=[], **kwd ):
'''
Return the list of widgets that comprise a form definition,
@@ -1254,6 +1267,9 @@
if field[ 'type' ] == 'TextField':
field_widget.set_size( 40 )
field_widget.value = value
+ if field[ 'type' ] == 'NumberField':
+ field_widget.set_size( 40 )
+ field_widget.value = value
elif field[ 'type' ] == 'TextArea':
field_widget.set_size( 3, 40 )
field_widget.value = value
@@ -1297,14 +1313,12 @@
REJECTED = 'Rejected',
COMPLETE = 'Complete')
def __init__(self, name=None, desc=None, request_type=None, user=None,
- form_values=None, library=None, folder=None):
+ form_values=None):
self.name = name
self.desc = desc
self.type = request_type
self.values = form_values
self.user = user
- self.library = library
- self.folder = folder
self.samples_list = []
def state(self):
if self.events:
@@ -1340,23 +1354,45 @@
self.comment = comment
class RequestType( object ):
- def __init__(self, name=None, desc=None, request_form=None, sample_form=None):
+ def __init__(self, name=None, desc=None, request_form=None, sample_form=None,
+ datatx_info=None):
self.name = name
self.desc = desc
self.request_form = request_form
self.sample_form = sample_form
+ self.datatx_info = datatx_info
class Sample( object ):
- def __init__(self, name=None, desc=None, request=None, form_values=None, bar_code=None):
+ transfer_status = Bunch( NOT_STARTED = 'Not started',
+ IN_PROGRESS = 'In progress',
+ COMPLETE = 'Complete',
+ ERROR = 'Error')
+ def __init__(self, name=None, desc=None, request=None, form_values=None,
+ bar_code=None, library=None, folder=None, dataset_files=None):
self.name = name
self.desc = desc
self.request = request
self.values = form_values
self.bar_code = bar_code
+ self.library = library
+ self.folder = folder
+ self.dataset_files = dataset_files
def current_state(self):
if self.events:
return self.events[0].state
return None
+ def untransfered_dataset_files(self):
+ count = 0
+ for df, status in self.dataset_files:
+ if status == self.transfer_status.NOT_STARTED:
+ count = count + 1
+ return count
+ def inprogress_dataset_files(self):
+ count = 0
+ for df, status in self.dataset_files:
+ if status == self.transfer_status.IN_PROGRESS:
+ count = count + 1
+ return count
class SampleState( object ):
def __init__(self, name=None, desc=None, request_type=None):
diff -r 44fff02fb036 -r 37b55fad152b lib/galaxy/model/mapping.py
--- a/lib/galaxy/model/mapping.py Thu Feb 04 10:44:36 2010 -0500
+++ b/lib/galaxy/model/mapping.py Thu Feb 04 11:01:45 2010 -0500
@@ -606,6 +606,7 @@
Column( "desc", TEXT ),
Column( "request_form_id", Integer, ForeignKey( "form_definition.id" ), index=True ),
Column( "sample_form_id", Integer, ForeignKey( "form_definition.id" ), index=True ),
+ Column( "datatx_info", JSONType() ),
Column( "deleted", Boolean, index=True, default=False ) )
FormValues.table = Table('form_values', metadata,
@@ -624,8 +625,6 @@
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 ),
- Column( "library_id", Integer, ForeignKey( "library.id" ), index=True ),
- Column( "folder_id", Integer, ForeignKey( "library_folder.id" ), index=True ),
Column( "deleted", Boolean, index=True, default=False ) )
RequestEvent.table = Table('request_event', metadata,
@@ -645,6 +644,9 @@
Column( "form_values_id", Integer, ForeignKey( "form_values.id" ), index=True ),
Column( "request_id", Integer, ForeignKey( "request.id" ), index=True ),
Column( "bar_code", TrimmedString( 255 ), index=True ),
+ Column( "library_id", Integer, ForeignKey( "library.id" ), index=True ),
+ Column( "folder_id", Integer, ForeignKey( "library_folder.id" ), index=True ),
+ Column( "dataset_files", JSONType() ),
Column( "deleted", Boolean, index=True, default=False ) )
SampleState.table = Table('sample_state', metadata,
@@ -838,6 +840,10 @@
primaryjoin=( Sample.table.c.form_values_id == FormValues.table.c.id ) ),
request=relation( Request,
primaryjoin=( Sample.table.c.request_id == Request.table.c.id ) ),
+ folder=relation( LibraryFolder,
+ primaryjoin=( Sample.table.c.folder_id == LibraryFolder.table.c.id ) ),
+ library=relation( Library,
+ primaryjoin=( Sample.table.c.library_id == Library.table.c.id ) ),
) )
assign_mapper( context, FormValues, FormValues.table,
@@ -856,11 +862,7 @@
backref="requests" ),
samples=relation( Sample,
primaryjoin=( Request.table.c.id == Sample.table.c.request_id ),
- order_by=asc(Sample.table.c.update_time) ),
- folder=relation( LibraryFolder,
- primaryjoin=( Request.table.c.folder_id == LibraryFolder.table.c.id ) ),
- library=relation( Library,
- primaryjoin=( Request.table.c.library_id == Library.table.c.id ) ),
+ order_by=asc(Sample.table.c.id) ),
events=relation( RequestEvent, backref="request",
order_by=desc(RequestEvent.table.c.update_time) )
) )
diff -r 44fff02fb036 -r 37b55fad152b lib/galaxy/model/migrate/versions/0019_request_library_folder.py
--- a/lib/galaxy/model/migrate/versions/0019_request_library_folder.py Thu Feb 04 10:44:36 2010 -0500
+++ b/lib/galaxy/model/migrate/versions/0019_request_library_folder.py Thu Feb 04 11:01:45 2010 -0500
@@ -47,7 +47,7 @@
try:
LibraryFolder_table = Table( "library_folder", metadata, autoload=True )
except NoSuchTableError:
- Request_table = None
+ LibraryFolder_table = None
log.debug( "Failed loading table library_folder" )
# Add 1 foreign key constraint to the library_folder table
if Request_table and LibraryFolder_table:
diff -r 44fff02fb036 -r 37b55fad152b lib/galaxy/model/migrate/versions/0037_samples_library.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/galaxy/model/migrate/versions/0037_samples_library.py Thu Feb 04 11:01:45 2010 -0500
@@ -0,0 +1,124 @@
+"""
+This migration script removes the library_id & folder_id fields in the 'request' table and
+adds the same to the 'sample' table. This also adds a 'datatx' column to request_type table
+to store the sequencer login information. Finally, this adds a 'dataset_files' column to
+the sample table.
+"""
+from sqlalchemy import *
+from sqlalchemy.orm import *
+from migrate import *
+from migrate.changeset import *
+import sys, logging
+from galaxy.model.custom_types import *
+from sqlalchemy.exc import *
+
+log = logging.getLogger( __name__ )
+log.setLevel(logging.DEBUG)
+handler = logging.StreamHandler( sys.stdout )
+format = "%(name)s %(levelname)s %(asctime)s %(message)s"
+formatter = logging.Formatter( format )
+handler.setFormatter( formatter )
+log.addHandler( handler )
+
+metadata = MetaData( migrate_engine )
+
+
+def upgrade():
+ print __doc__
+ # Load existing tables
+ metadata.reflect()
+ # retuest_type table
+ try:
+ RequestType_table = Table( "request_type", metadata, autoload=True )
+ except NoSuchTableError:
+ RequestType_table = None
+ log.debug( "Failed loading table request_type" )
+ if RequestType_table:
+ # Add the datatx_info column in 'request_type' table
+ try:
+ col = Column( "datatx_info", JSONType() )
+ col.create( RequestType_table )
+ assert col is RequestType_table.c.datatx_info
+ except Exception, e:
+ log.debug( "Adding column 'datatx_info' to request_type table failed: %s" % ( str( e ) ) )
+ # request table
+ try:
+ Request_table = Table( "request", metadata, autoload=True )
+ except NoSuchTableError:
+ Request_table = None
+ log.debug( "Failed loading table request" )
+ if Request_table:
+ # Delete the library_id column in 'request' table
+ try:
+ Request_table.c.library_id.drop()
+ except Exception, e:
+ log.debug( "Deleting column 'library_id' to request table failed: %s" % ( str( e ) ) )
+ # Delete the folder_id column in 'request' table
+ try:
+ Request_table.c.folder_id.drop()
+ except Exception, e:
+ log.debug( "Deleting column 'folder_id' to request table failed: %s" % ( str( e ) ) )
+ # sample table
+ try:
+ Sample_table = Table( "sample", metadata, autoload=True )
+ except NoSuchTableError:
+ Sample_table = None
+ log.debug( "Failed loading table sample" )
+ if Sample_table:
+ # Add the dataset_files column in 'sample' table
+ try:
+ col = Column( "dataset_files", JSONType() )
+ col.create( Sample_table )
+ assert col is Sample_table.c.dataset_files
+ except Exception, e:
+ log.debug( "Adding column 'dataset_files' to sample table failed: %s" % ( str( e ) ) )
+ # library table
+ try:
+ Library_table = Table( "library", metadata, autoload=True )
+ except NoSuchTableError:
+ Library_table = None
+ log.debug( "Failed loading table library" )
+ if Library_table:
+ # Add the library_id column in 'sample' table
+ try:
+ col = Column( "library_id", Integer, index=True )
+ col.create( Sample_table )
+ assert col is Sample_table.c.library_id
+ except Exception, e:
+ log.debug( "Adding column 'library_id' to sample table failed: %s" % ( str( e ) ) )
+ # add the foreign key constraint
+ try:
+ cons = ForeignKeyConstraint( [Sample_table.c.library_id],
+ [Library_table.c.id],
+ name='sample_library_id_fk' )
+ # Create the constraint
+ cons.create()
+ except Exception, e:
+ log.debug( "Adding foreign key constraint 'sample_library_id_fk' to table 'library' failed: %s" % ( str( e ) ) )
+ # library_folder table
+ try:
+ LibraryFolder_table = Table( "library_folder", metadata, autoload=True )
+ except NoSuchTableError:
+ LibraryFolder_table = None
+ log.debug( "Failed loading table library_folder" )
+ if LibraryFolder_table:
+ # Add the library_id column in 'sample' table
+ try:
+ col = Column( "folder_id", Integer, index=True )
+ col.create( Sample_table )
+ assert col is Sample_table.c.folder_id
+ except Exception, e:
+ log.debug( "Adding column 'folder_id' to sample table failed: %s" % ( str( e ) ) )
+ # add the foreign key constraint
+ try:
+ cons = ForeignKeyConstraint( [Sample_table.c.folder_id],
+ [LibraryFolder_table.c.id],
+ name='sample_folder_id_fk' )
+ # Create the constraint
+ cons.create()
+ except Exception, e:
+ log.debug( "Adding foreign key constraint 'sample_folder_id_fk' to table 'library_folder' failed: %s" % ( str( e ) ) )
+
+
+def downgrade():
+ pass
diff -r 44fff02fb036 -r 37b55fad152b lib/galaxy/web/controllers/requests.py
--- a/lib/galaxy/web/controllers/requests.py Thu Feb 04 10:44:36 2010 -0500
+++ b/lib/galaxy/web/controllers/requests.py Thu Feb 04 11:01:45 2010 -0500
@@ -178,30 +178,6 @@
% rejected
# Render the list view
return self.request_grid( trans, **kwd )
- def __show_request(self, trans, **kwd):
- params = util.Params( kwd )
- msg = util.restore_text( params.get( 'msg', '' ) )
- messagetype = params.get( 'messagetype', 'done' )
- add_sample = params.get('add_sample', False)
- 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='requests',
- action='list',
- status='error',
- message="Invalid request ID" ) )
- current_samples = []
- for s in request.samples:
- current_samples.append([s.name, s.values.content])
- if add_sample:
- current_samples.append(['Sample_%i' % (len(current_samples)+1),['' for field in request.type.sample_form.fields]])
- return trans.fill_template( '/requests/show_request.mako',
- request=request,
- request_details=self.request_details(trans, request.id),
- current_samples = current_samples,
- sample_copy=self.__copy_sample(current_samples),
- details='hide', edit_mode='False',
- msg=msg, messagetype=messagetype )
def __request_events(self, trans, **kwd):
try:
request = trans.sa_session.query( trans.app.model.Request ).get( trans.security.decode_id(kwd['id']) )
@@ -239,22 +215,6 @@
request_details.append(dict(label='Date created',
value=request.create_time,
helptext=''))
- # library associated
- if request.library:
- value = request.library.name
- else:
- value = None
- request_details.append( dict( label='Data library',
- value=value,
- helptext='Data library where the resultant dataset will be stored' ) )
- # folder associated
- if request.folder:
- value = request.folder.name
- else:
- value = None
- request_details.append( dict( label='Data library folder',
- value=value,
- helptext='Data library folder where the resultant dataset will be stored' ) )
# form fields
for index, field in enumerate(request.type.request_form.fields):
if field['required']:
@@ -276,36 +236,190 @@
value=request.values.content[index],
helptext=field['helptext']+' ('+req+')'))
return request_details
- def __update_samples(self, request, **kwd):
+ def __show_request(self, trans, **kwd):
+ params = util.Params( kwd )
+ msg = util.restore_text( params.get( 'msg', '' ) )
+ messagetype = params.get( 'messagetype', 'done' )
+ add_sample = params.get('add_sample', False)
+ 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='requests',
+ action='list',
+ status='error',
+ message="Invalid request ID") )
+ # get all data libraries accessible to this user
+ libraries = request.user.accessible_libraries( trans, [ trans.app.security_agent.permitted_actions.LIBRARY_ADD ] )
+ current_samples = []
+ for i, s in enumerate(request.samples):
+ lib_widget, folder_widget = self.__library_widgets(trans, request.user, i, libraries, s, **kwd)
+ current_samples.append(dict(name=s.name,
+ barcode=s.bar_code,
+ library=s.library,
+ folder=s.folder,
+ dataset_files=s.dataset_files,
+ field_values=s.values.content,
+ lib_widget=lib_widget,
+ folder_widget=folder_widget))
+ if add_sample:
+ lib_widget, folder_widget = self.__library_widgets(trans, request.user,
+ len(current_samples)+1,
+ libraries, None, **kwd)
+ current_samples.append(dict(name='Sample_%i' % (len(current_samples)+1),
+ barcode='',
+ library=None,
+ folder=None,
+ dataset_files=[],
+ field_values=['' for field in request.type.sample_form.fields],
+ lib_widget=lib_widget,
+ folder_widget=folder_widget))
+ return trans.fill_template( '/requests/show_request.mako',
+ request=request,
+ request_details=self.request_details(trans, request.id),
+ current_samples=current_samples,
+ sample_copy=self.__copy_sample(current_samples),
+ details='hide', edit_mode=util.restore_text( params.get( 'edit_mode', 'False' ) ),
+ msg=msg, messagetype=messagetype )
+ def __library_widgets(self, trans, user, sample_index, libraries, sample=None, **kwd):
+ '''
+ This method creates the data library & folder selectbox for creating &
+ editing samples. First we get a list of all the libraries accessible to
+ the current user and display it in a selectbox. If the user has selected an
+ existing library then display all the accessible sub folders of the selected
+ data library.
+ '''
+ params = util.Params( kwd )
+ # data library selectbox
+ lib_id = params.get( "sample_%i_library_id" % sample_index, 'none' )
+ selected_lib = None
+ if sample and lib_id == 'none':
+ if sample.library:
+ lib_id = str(sample.library.id)
+ selected_lib = sample.library
+ # create data library selectbox with refresh on change enabled
+ lib_id_list = ['new'] + [str(lib.id) for lib in libraries.keys()]
+ lib_widget = SelectField( "sample_%i_library_id" % sample_index,
+ refresh_on_change=True,
+ refresh_on_change_values=lib_id_list )
+ # fill up the options in the Library selectbox
+ # first option 'none' is the value for "Select one" option
+ if lib_id == 'none':
+ lib_widget.add_option('Select one', 'none', selected=True)
+ else:
+ lib_widget.add_option('Select one', 'none')
+ # all the libraries available to the selected user
+ for lib, hidden_folder_ids in libraries.items():
+ if str(lib.id) == lib_id:
+ lib_widget.add_option(lib.name, lib.id, selected=True)
+ selected_lib, selected_hidden_folder_ids = lib, hidden_folder_ids.split(',')
+ else:
+ lib_widget.add_option(lib.name, lib.id)
+ lib_widget.refresh_on_change_values.append(lib.id)
+ # create the folder selectbox
+ folder_widget = SelectField( "sample_%i_folder_id" % sample_index )
+ # when editing a request, either the user has already selected a subfolder or not
+ if sample:
+ if sample.folder:
+ current_fid = sample.folder.id
+ else:
+ # when a folder not yet associated with the request then the
+ # the current folder is set to the root_folder of the
+ # parent data library if present.
+ if sample.library:
+ current_fid = sample.library.root_folder.id
+ else:
+ current_fid = params.get( "sample_%i_folder_id" % sample_index, 'none' )
+ else:
+ current_fid = 'none'
+ # first option
+ if lib_id == 'none':
+ folder_widget.add_option('Select one', 'none', selected=True)
+ else:
+ folder_widget.add_option('Select one', 'none')
+ if selected_lib:
+ # get all show-able folders for the selected library
+ showable_folders = trans.app.security_agent.get_showable_folders( user, user.all_roles(),
+ selected_lib,
+ [ trans.app.security_agent.permitted_actions.LIBRARY_ADD ],
+ selected_hidden_folder_ids )
+ for f in showable_folders:
+ if str(f.id) == str(current_fid):
+ folder_widget.add_option(f.name, f.id, selected=True)
+ else:
+ folder_widget.add_option(f.name, f.id)
+ return lib_widget, folder_widget
+ def __update_samples(self, trans, request, **kwd):
'''
This method retrieves all the user entered sample information and
returns an list of all the samples and their field values
'''
params = util.Params( kwd )
+ details = params.get( 'details', 'hide' )
+ edit_mode = params.get( 'edit_mode', 'False' )
+ # get all data libraries accessible to this user
+ libraries = request.user.accessible_libraries( trans, [ trans.app.security_agent.permitted_actions.LIBRARY_ADD ] )
+
current_samples = []
- for s in request.samples:
- current_samples.append([s.name, s.values.content])
- index = len(request.samples)
+ for i, s in enumerate(request.samples):
+ lib_widget, folder_widget = self.__library_widgets(trans, request.user, i, libraries, s, **kwd)
+ current_samples.append(dict(name=s.name,
+ barcode=s.bar_code,
+ library=s.library,
+ folder=s.folder,
+ field_values=s.values.content,
+ lib_widget=lib_widget,
+ folder_widget=folder_widget))
+ if edit_mode == 'False':
+ sample_index = len(request.samples)
+ else:
+ sample_index = 0
while True:
- if params.get( 'sample_%i_name' % index, '' ):
- sample_index = index
- sample_name = util.restore_text( params.get( 'sample_%i_name' % sample_index, '' ) )
- sample_values = []
+ if params.get( 'sample_%i_name' % sample_index, '' ):
+ # data library
+ try:
+ library = trans.sa_session.query( trans.app.model.Library ).get( int( params.get( 'sample_%i_library_id' % sample_index, None ) ) )
+ except:
+ library = None
+ # folder
+ try:
+ folder = trans.sa_session.query( trans.app.model.LibraryFolder ).get( int( params.get( 'sample_%i_folder_id' % sample_index, None ) ) )
+ except:
+ if library:
+ folder = library.root_folder
+ else:
+ folder = None
+ sample_info = dict( name=util.restore_text( params.get( 'sample_%i_name' % sample_index, '' ) ),
+ barcode=util.restore_text( params.get( 'sample_%i_barcode' % sample_index, '' ) ),
+ library=library,
+ folder=folder)
+ sample_info['field_values'] = []
for field_index in range(len(request.type.sample_form.fields)):
- sample_values.append(util.restore_text( params.get( 'sample_%i_field_%i' % (sample_index, field_index), '' ) ))
- current_samples.append([sample_name, sample_values])
- index = index + 1
+ sample_info['field_values'].append(util.restore_text( params.get( 'sample_%i_field_%i' % (sample_index, field_index), '' ) ))
+ if edit_mode == 'False':
+ sample_info['lib_widget'], sample_info['folder_widget'] = self.__library_widgets(trans,
+ request.user,
+ sample_index,
+ libraries,
+ None, **kwd)
+ current_samples.append(sample_info)
+ else:
+ sample_info['lib_widget'], sample_info['folder_widget'] = self.__library_widgets(trans,
+ request.user,
+ sample_index,
+ libraries,
+ request.samples[sample_index],
+ **kwd)
+ current_samples[sample_index] = sample_info
+ sample_index = sample_index + 1
else:
break
- details = params.get( 'details', 'hide' )
- edit_mode = params.get( 'edit_mode', 'False' )
- return current_samples, details, edit_mode
+ return current_samples, details, edit_mode, libraries
def __copy_sample(self, current_samples):
copy_list = SelectField('copy_sample')
copy_list.add_option('None', -1, selected=True)
for i, s in enumerate(current_samples):
- copy_list.add_option(s[0], i)
- return copy_list
+ copy_list.add_option(s['name'], i)
+ return copy_list
@web.expose
@web.require_login( "create/submit sequencing requests" )
def show_request(self, trans, **kwd):
@@ -321,7 +435,7 @@
message="Invalid request ID",
**kwd) )
# get the user entered sample details
- current_samples, details, edit_mode = self.__update_samples( request, **kwd )
+ current_samples, details, edit_mode, libraries = self.__update_samples( trans, request, **kwd )
if params.get('import_samples_button', False) == 'Import samples':
try:
file_obj = params.get('file_data', '')
@@ -349,10 +463,27 @@
src_sample_index = int(params.get( 'copy_sample', -1 ))
if src_sample_index == -1:
# empty sample
- current_samples.append(['Sample_%i' % (len(current_samples)+1),['' for field in request.type.sample_form.fields]])
+ lib_widget, folder_widget = self.__library_widgets(trans, request.user,
+ len(current_samples),
+ libraries, None, **kwd)
+ current_samples.append(dict(name='Sample_%i' % (len(current_samples)+1),
+ barcode='',
+ library=None,
+ folder=None,
+ field_values=['' for field in request.type.sample_form.fields],
+ lib_widget=lib_widget,
+ folder_widget=folder_widget))
else:
- current_samples.append([current_samples[src_sample_index][0]+'_%i' % (len(current_samples)+1),
- [val for val in current_samples[src_sample_index][1]]])
+ lib_widget, folder_widget = self.__library_widgets(trans, request.user,
+ len(current_samples),
+ libraries, None, **kwd)
+ current_samples.append(dict(name=current_samples[src_sample_index]['name']+'_%i' % (len(current_samples)+1),
+ barcode='',
+ library_id='none',
+ folder_id='none',
+ field_values=[val for val in current_samples[src_sample_index]['field_values']],
+ lib_widget=lib_widget,
+ folder_widget=folder_widget))
return trans.fill_template( '/requests/show_request.mako',
request=request,
request_details=self.request_details(trans, request.id),
@@ -365,13 +496,13 @@
msg = ''
for index in range(len(current_samples)-len(request.samples)):
sample_index = index + len(request.samples)
- sample_name = current_samples[sample_index][0]
+ sample_name = current_samples[sample_index]['name']
if not sample_name.strip():
msg = 'Please enter the name of sample number %i' % sample_index
break
count = 0
for i in range(len(current_samples)):
- if sample_name == current_samples[i][0]:
+ if sample_name == current_samples[i]['name']:
count = count + 1
if count > 1:
msg = "This request has <b>%i</b> samples with the name <b>%s</b>.\nSamples belonging to a request must have unique names." % (count, sample_name)
@@ -388,34 +519,45 @@
if edit_mode == 'False':
for index in range(len(current_samples)-len(request.samples)):
sample_index = len(request.samples)
- sample_name = util.restore_text( params.get( 'sample_%i_name' % sample_index, '' ) )
- sample_values = []
- for field_index in range(len(request.type.sample_form.fields)):
- sample_values.append(util.restore_text( params.get( 'sample_%i_field_%i' % (sample_index, field_index), '' ) ))
- form_values = trans.app.model.FormValues(request.type.sample_form, sample_values)
+ form_values = trans.app.model.FormValues(request.type.sample_form,
+ current_samples[sample_index]['field_values'])
trans.sa_session.add( form_values )
trans.sa_session.flush()
- s = trans.app.model.Sample(sample_name, '', request, form_values)
+ s = trans.app.model.Sample(current_samples[sample_index]['name'], '',
+ request, form_values,
+ current_samples[sample_index]['barcode'],
+ current_samples[sample_index]['library'],
+ current_samples[sample_index]['folder'],
+ dataset_files=[])
trans.sa_session.add( s )
trans.sa_session.flush()
else:
+ messagetype = 'done'
+ msg = 'Changes made to the sample(s) are saved. '
for sample_index in range(len(current_samples)):
- sample_name = current_samples[sample_index][0]
- new_sample_name = util.restore_text( params.get( 'sample_%i_name' % sample_index, '' ) )
- sample_values = []
- for field_index in range(len(request.type.sample_form.fields)):
- sample_values.append(util.restore_text( params.get( 'sample_%i_field_%i' % (sample_index, field_index), '' ) ))
- sample = request.has_sample(sample_name)
- if sample:
- form_values = trans.sa_session.query( trans.app.model.FormValues ).get( sample.values.id )
- form_values.content = sample_values
- sample.name = new_sample_name
- trans.sa_session.add( sample )
- trans.sa_session.flush()
+ sample = request.samples[sample_index]
+ sample.name = current_samples[sample_index]['name']
+ sample.library = current_samples[sample_index]['library']
+ sample.folder = current_samples[sample_index]['folder']
+ if request.submitted():
+ bc_msg = self.__validate_barcode(trans, sample, current_samples[sample_index]['barcode'])
+ if bc_msg:
+ messagetype = 'error'
+ msg += bc_msg
+ else:
+ sample.bar_code = current_samples[sample_index]['barcode']
+ trans.sa_session.add( sample )
+ trans.sa_session.flush()
+ form_values = trans.sa_session.query( trans.app.model.FormValues ).get( sample.values.id )
+ form_values.content = current_samples[sample_index]['field_values']
+ trans.sa_session.add( form_values )
+ trans.sa_session.flush()
return trans.response.send_redirect( web.url_for( controller='requests',
- action='list',
- operation='show_request',
- id=trans.security.encode_id(request.id)) )
+ action='list',
+ operation='show_request',
+ id=trans.security.encode_id(request.id),
+ messagetype=messagetype,
+ msg=msg ))
elif params.get('edit_samples_button', False) == 'Edit samples':
edit_mode = 'True'
return trans.fill_template( '/requests/show_request.mako',
@@ -423,13 +565,21 @@
request_details=self.request_details(trans, request.id),
current_samples=current_samples,
sample_copy=self.__copy_sample(current_samples),
- details=details,
+ details=details, libraries=libraries,
edit_mode=edit_mode)
elif params.get('cancel_changes_button', False) == 'Cancel':
return trans.response.send_redirect( web.url_for( controller='requests',
action='list',
operation='show_request',
id=trans.security.encode_id(request.id)) )
+ else:
+ return trans.fill_template( '/requests/show_request.mako',
+ request=request,
+ request_details=self.request_details(trans, request.id),
+ current_samples=current_samples,
+ sample_copy=self.__copy_sample(current_samples),
+ details=details, libraries=libraries,
+ edit_mode=edit_mode, messagetype=messagetype, msg=msg)
@web.expose
@@ -441,7 +591,7 @@
request = trans.sa_session.query( trans.app.model.Request ).get( int( params.get( 'request_id', 0 ) ) )
current_samples, details, edit_mode = self.__update_samples( request, **kwd )
sample_index = int(params.get('sample_id', 0))
- sample_name = current_samples[sample_index][0]
+ sample_name = current_samples[sample_index]['name']
s = request.has_sample(sample_name)
if s:
trans.sa_session.delete( s )
@@ -454,23 +604,6 @@
sample_copy=self.__copy_sample(current_samples),
details=details,
edit_mode=edit_mode)
-
- @web.expose
- @web.require_login( "create/submit sequencing requests" )
- def toggle_request_details(self, trans, **kwd):
- params = util.Params( kwd )
- msg = util.restore_text( params.get( 'msg', '' ) )
- messagetype = params.get( 'messagetype', 'done' )
- # TODO: Fix the following - can we get a Request.id == 0???
- request = trans.sa_session.query( trans.app.model.Request ).get(int(params.get('request_id', 0)))
- current_samples, details, edit_mode = self.__update_samples( request, **kwd )
- return trans.fill_template( '/requests/show_request.mako',
- request=request,
- request_details=self.request_details(trans, request.id),
- current_samples = current_samples,
- sample_copy=self.__copy_sample(current_samples),
- details=details,
- edit_mode=edit_mode)
def __select_request_type(self, trans, rtid):
requesttype_list = trans.sa_session.query( trans.app.model.RequestType )\
.order_by( trans.app.model.RequestType.name.asc() )
@@ -563,10 +696,6 @@
widget=TextField('desc', 40,
util.restore_text( params.get( 'desc', '' ) )),
helptext='(Optional)'))
-
- # libraries selectbox
- libui = self.__library_ui(trans, request=None, **kwd)
- widgets = widgets + libui
widgets = widgets + request_type.request_form.get_widgets( trans.user, **kwd )
return trans.fill_template( '/requests/new_request.mako',
select_request_type=select_request_type,
@@ -574,110 +703,6 @@
widgets=widgets,
msg=msg,
messagetype=messagetype)
- def __library_ui(self, trans, request=None, **kwd):
- '''
- This method creates the data library & folder selectbox for new &
- editing requests. First we get a list of all the libraries accessible to
- the current user and display it in a selectbox. If the user has select an
- existing library then display all the accessible sub folders of the selected
- data library.
- '''
- params = util.Params( kwd )
- lib_id = params.get( 'library_id', 'none' )
- selected_lib = None
- # if editing a request and the user has already associated a library to
- # this request, then set the selected_lib to the request.library
- if request and lib_id == 'none':
- if request.library:
- lib_id = str(request.library.id)
- selected_lib = request.library
- # get all permitted libraries for this user
- all_libraries = trans.sa_session.query( trans.app.model.Library ) \
- .filter( trans.app.model.Library.table.c.deleted == False ) \
- .order_by( trans.app.model.Library.name )
- current_user_roles = trans.get_current_user_roles()
- actions_to_check = [ trans.app.security_agent.permitted_actions.LIBRARY_ADD ]
- libraries = odict()
- for library in all_libraries:
- can_show, hidden_folder_ids = trans.app.security_agent.show_library_item( trans.user, current_user_roles, library, actions_to_check )
- if can_show:
- libraries[ library ] = hidden_folder_ids
- # create data library selectbox with refresh on change enabled
- lib_id_list = ['new'] + [str(lib.id) for lib in libraries.keys()]
- lib_list = SelectField( 'library_id', refresh_on_change=True, refresh_on_change_values=lib_id_list )
- # fill up the options in the Library selectbox
- # first option 'none' is the value for "Select one" option
- if lib_id == 'none':
- lib_list.add_option('Select one', 'none', selected=True)
- else:
- lib_list.add_option('Select one', 'none')
- # add all the libraries available to the user to the library selectbox
- for lib, hidden_folder_ids in libraries.items():
- if str(lib.id) == lib_id:
- lib_list.add_option(lib.name, lib.id, selected=True)
- selected_lib, selected_hidden_folder_ids = lib, hidden_folder_ids.split(',')
- else:
- lib_list.add_option(lib.name, lib.id)
- lib_list.refresh_on_change_values.append(lib.id)
- # new library option
- if lib_id == 'new':
- lib_list.add_option('Create a new data library', 'new', selected=True)
- else:
- lib_list.add_option('Create a new data library', 'new')
- # data library widget
- lib_widget = dict(label='Data library',
- widget=lib_list,
- helptext='Data library where the resultant dataset will be stored.')
- # show the folder widget only if the user has selected a valid library above
- if selected_lib:
- # when editing a request, either the user has already selected a subfolder or not
- if request:
- if request.folder:
- current_fid = request.folder.id
- else:
- # when a folder not yet associated with the request then the
- # the current folder is set to the root_folder of the
- # parent data library if present.
- if request.library:
- current_fid = request.library.root_folder.id
- else:
- current_fid = params.get( 'folder_id', 'none' )
- else:
- current_fid = params.get( 'folder_id', 'none' )
- # create the folder selectbox
- folder_list = SelectField( 'folder_id')
- # first option
- if lib_id == 'none':
- folder_list.add_option('Select one', 'none', selected=True)
- else:
- folder_list.add_option('Select one', 'none')
- # get all show-able folders for the selected library
- showable_folders = trans.app.security_agent.get_showable_folders( trans.user,
- current_user_roles,
- selected_lib,
- actions_to_check,
- selected_hidden_folder_ids )
- # add all the folders to the folder selectbox
- for f in showable_folders:
- if str(f.id) == str(current_fid):
- folder_list.add_option(f.name, f.id, selected=True)
- else:
- folder_list.add_option(f.name, f.id)
- # folder widget
- folder_widget = dict(label='Folder',
- widget=folder_list,
- helptext='Folder of the selected data library where the resultant dataset will be stored.')
- if lib_id == 'new':
- new_lib = dict(label='Create a new data library',
- widget=TextField('new_library_name', 40,
- util.restore_text( params.get( 'new_library_name', '' ) )),
- helptext='Enter a name here to request a new data library')
- return [lib_widget, new_lib]
- else:
- if selected_lib:
- return [lib_widget, folder_widget]
- else:
- return [lib_widget]
def __validate(self, trans, request):
'''
Validates the request entered by the user
@@ -747,8 +772,7 @@
trans.sa_session.flush()
if not request:
request = trans.app.model.Request(name, desc, request_type,
- trans.user, form_values,
- library=library, folder=folder)
+ trans.user, form_values)
trans.sa_session.add( request )
trans.sa_session.flush()
trans.sa_session.refresh( request )
@@ -763,8 +787,6 @@
request.type = request_type
request.user = trans.user
request.values = form_values
- request.library = library
- request.folder = folder
trans.sa_session.add( request )
trans.sa_session.flush()
return request
@@ -844,9 +866,6 @@
widgets.append(dict(label='Description',
widget=TextField('desc', 40, desc),
helptext='(Optional)'))
- # libraries selectbox
- libui = self.__library_ui(trans, request, **kwd)
- widgets = widgets + libui
widgets = widgets + request.type.request_form.get_widgets( trans.user, request.values.content, **kwd )
return trans.fill_template( '/requests/edit_request.mako',
select_request_type=select_request_type,
@@ -966,3 +985,22 @@
events_list=events_list,
sample_name=sample.name,
request=sample.request)
+ #
+ # Data transfer from sequencer
+ #
+ @web.expose
+ @web.require_login( "create/submit sequencing requests" )
+ def show_datatx_page( self, trans, **kwd ):
+ params = util.Params( kwd )
+ msg = util.restore_text( params.get( 'msg', '' ) )
+ messagetype = params.get( 'messagetype', 'done' )
+ try:
+ sample = trans.sa_session.query( trans.app.model.Sample ).get( trans.security.decode_id( kwd['sample_id'] ) )
+ except:
+ return trans.response.send_redirect( web.url_for( controller='requests',
+ action='list',
+ status='error',
+ message="Invalid sample ID",
+ **kwd) )
+ return trans.fill_template( '/requests/show_data.mako',
+ sample=sample, dataset_files=sample.dataset_files )
diff -r 44fff02fb036 -r 37b55fad152b lib/galaxy/web/controllers/requests_admin.py
--- a/lib/galaxy/web/controllers/requests_admin.py Thu Feb 04 10:44:36 2010 -0500
+++ b/lib/galaxy/web/controllers/requests_admin.py Thu Feb 04 11:01:45 2010 -0500
@@ -10,6 +10,8 @@
from galaxy.web.controllers.forms import get_all_forms
from sqlalchemy.sql.expression import func, and_
from sqlalchemy.sql import select
+import pexpect
+import ConfigParser
log = logging.getLogger( __name__ )
@@ -110,9 +112,9 @@
visible=False,
filterable="advanced" ),
StateColumn( "State",
+ key='state',
model_class=model.Request,
event_class=model.RequestEvent,
- key='state',
filterable="advanced",
link=( lambda item: iff( item.deleted, None, dict( operation="events", id=item.id ) ) ),
),
@@ -201,6 +203,8 @@
grids.GridAction( "Create new request type", dict( controller='requests_admin',
action='create_request_type' ) )
]
+
+
#
# ---- Request Controller ------------------------------------------------------
#
@@ -208,6 +212,7 @@
class RequestsAdmin( BaseController ):
request_grid = RequestsGrid()
requesttype_grid = RequestTypeGrid()
+
@web.expose
@web.require_admin
@@ -243,33 +248,10 @@
return self.__request_events( trans, **kwd )
elif operation == "view_type":
return self.__view_request_type( trans, **kwd )
-
+ elif operation == "upload_datasets":
+ return self.__upload_datasets( trans, **kwd )
# Render the grid view
return self.request_grid( trans, **kwd )
- def __show_request(self, trans, **kwd):
- params = util.Params( kwd )
- msg = util.restore_text( params.get( 'msg', '' ) )
- messagetype = params.get( 'messagetype', 'done' )
- add_sample = params.get('add_sample', False)
- 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='requests_admin',
- action='list',
- status='error',
- message="Invalid request ID") )
- current_samples = []
- for s in request.samples:
- current_samples.append([s.name, s.values.content])
- if add_sample:
- current_samples.append(['Sample_%i' % (len(current_samples)+1),['' for field in request.type.sample_form.fields]])
- return trans.fill_template( '/admin/requests/show_request.mako',
- request=request,
- request_details=self.request_details(trans, request.id),
- current_samples = current_samples,
- sample_copy=self.__copy_sample(current_samples),
- details='hide', edit_mode='False',
- msg=msg, messagetype=messagetype )
@web.expose
@web.require_admin
def edit(self, trans, **kwd):
@@ -346,9 +328,6 @@
widgets.append(dict(label='Description',
widget=TextField('desc', 40, desc),
helptext='(Optional)'))
- # libraries selectbox
- libui = self.__library_ui(trans, request.user, request, **kwd)
- widgets = widgets + libui
widgets = widgets + request.type.request_form.get_widgets( request.user, request.values.content, **kwd )
return trans.fill_template( '/admin/requests/edit_request.mako',
select_request_type=select_request_type,
@@ -504,6 +483,9 @@
events_list.append((event.state, time_ago(event.update_time), event.comment))
return trans.fill_template( '/admin/requests/events.mako',
events_list=events_list, request=request)
+
+ def __upload_datasets(self, trans, **kwd):
+ return trans.fill_template( '/admin/requests/upload_datasets.mako' )
#
#---- Request Creation ----------------------------------------------------------
#
@@ -609,9 +591,6 @@
widget=TextField('desc', 40,
util.restore_text( params.get( 'desc', '' ) )),
helptext='(Optional)'))
- # libraries selectbox
- libui = self.__library_ui(trans, user, **kwd)
- widgets = widgets + libui
widgets = widgets + request_type.request_form.get_widgets( user, **kwd )
return trans.fill_template( '/admin/requests/new_request.mako',
select_request_type=select_request_type,
@@ -640,119 +619,6 @@
else:
select_user.add_option(user.email, user.id)
return select_user
- def __library_ui(self, trans, user, request=None, **kwd):
- '''
- This method creates the data library & folder selectbox for new &
- editing requests. First we get a list of all the libraries accessible to
- the current user and display it in a selectbox. If the user has select an
- existing library then display all the accessible sub folders of the selected
- data library.
- '''
- params = util.Params( kwd )
- lib_id = params.get( 'library_id', 'none' )
- # if editing a request and the user has already associated a library to
- # this request, then set the selected_lib to the request.library
- selected_lib = None
- if request and lib_id == 'none':
- if request.library:
- lib_id = str(request.library.id)
- selected_lib = request.library
- # if new request no user is selected initially, none of the libraries are
- # listed in the selectfield
- if not user:
- libraries = {}
- else:
- # get all permitted libraries for this user
- all_libraries = trans.sa_session.query( trans.app.model.Library ) \
- .filter( trans.app.model.Library.table.c.deleted == False ) \
- .order_by( trans.app.model.Library.name )
- roles = user.all_roles()
- actions_to_check = [ trans.app.security_agent.permitted_actions.LIBRARY_ADD ]
- # The libraries dictionary looks like: { library : '1,2' }, library : '3' }
- # Its keys are the libraries that should be displayed for the current user and whose values are a
- # string of comma-separated folder ids, of the associated folders the should NOT be displayed.
- # The folders that should not be displayed may not be a complete list, but it is ultimately passed
- # to the calling method to keep from re-checking the same folders when the library / folder
- # select lists are rendered.
- libraries = {}
- for library in all_libraries:
- can_show, hidden_folder_ids = trans.app.security_agent.show_library_item( user, roles, library, actions_to_check )
- if can_show:
- libraries[ library ] = hidden_folder_ids
- # create data library selectbox with refresh on change enabled
- lib_id_list = ['new'] + [str(lib.id) for lib in libraries.keys()]
- lib_list = SelectField( 'library_id', refresh_on_change=True, refresh_on_change_values=lib_id_list )
- # fill up the options in the Library selectbox
- # first option 'none' is the value for "Select one" option
- if lib_id == 'none':
- lib_list.add_option('Select one', 'none', selected=True)
- else:
- lib_list.add_option('Select one', 'none')
- # all the libraries available to the selected user
- for lib, hidden_folder_ids in libraries.items():
- if str(lib.id) == lib_id:
- lib_list.add_option(lib.name, lib.id, selected=True)
- selected_lib, selected_hidden_folder_ids = lib, hidden_folder_ids.split(',')
- else:
- lib_list.add_option(lib.name, lib.id)
- lib_list.refresh_on_change_values.append(lib.id)
- # new data library option
- if lib_id == 'new':
- lib_list.add_option('Create a new data library', 'new', selected=True)
- else:
- lib_list.add_option('Create a new data library', 'new')
- # widget
- lib_widget = dict(label='Data library',
- widget=lib_list,
- helptext='Data library where the resultant dataset will be stored.')
- # show the folder widget only if the user has selected a valid library above
- if selected_lib:
- # when editing a request, either the user has already selected a subfolder or not
- if request:
- if request.folder:
- current_fid = request.folder.id
- else:
- # when a folder not yet associated with the request then the
- # the current folder is set to the root_folder of the
- # parent data library if present.
- if request.library:
- current_fid = request.library.root_folder.id
- else:
- current_fid = params.get( 'folder_id', 'none' )
- else:
- current_fid = params.get( 'folder_id', 'none' )
- # create the folder selectbox
- folder_list = SelectField( 'folder_id')
- # first option
- if lib_id == 'none':
- folder_list.add_option('Select one', 'none', selected=True)
- else:
- folder_list.add_option('Select one', 'none')
- # get all show-able folders for the selected library
- showable_folders = trans.app.security_agent.get_showable_folders( user, roles,
- selected_lib,
- actions_to_check,
- selected_hidden_folder_ids )
- for f in showable_folders:
- if str(f.id) == str(current_fid):
- folder_list.add_option(f.name, f.id, selected=True)
- else:
- folder_list.add_option(f.name, f.id)
- # folder widget
- folder_widget = dict(label='Folder',
- widget=folder_list,
- helptext='Folder of the selected data library where the resultant dataset will be stored.')
- if lib_id == 'new':
- new_lib = dict(label='Create a new data library',
- widget=TextField('new_library_name', 40,
- util.restore_text( params.get( 'new_library_name', '' ) )),
- helptext='Enter a name here to request a new data library')
- return [lib_widget, new_lib]
- else:
- if selected_lib:
- return [lib_widget, folder_widget]
- else:
- return [lib_widget]
def __validate(self, trans, request):
'''
Validates the request entered by the user
@@ -787,18 +653,6 @@
user = trans.sa_session.query( trans.app.model.User ).get( int( params.get( 'select_user', '' ) ) )
name = util.restore_text(params.get('name', ''))
desc = util.restore_text(params.get('desc', ''))
- # library
- try:
- library = trans.sa_session.query( trans.app.model.Library ).get( int( params.get( 'library_id', None ) ) )
- except:
- library = None
- try:
- folder = trans.sa_session.query( trans.app.model.LibraryFolder ).get( int( params.get( 'folder_id', None ) ) )
- except:
- if library:
- folder = library.root_folder
- else:
- folder = None
# fields
values = []
for index, field in enumerate(request_type.request_form.fields):
@@ -833,8 +687,7 @@
trans.sa_session.flush()
if not request:
request = trans.app.model.Request(name, desc, request_type,
- user, form_values,
- library=library, folder=folder)
+ user, form_values)
trans.sa_session.add( request )
trans.sa_session.flush()
trans.sa_session.refresh( request )
@@ -852,46 +705,195 @@
request.type = request_type
request.user = user
request.values = form_values
- request.library = library
- request.folder = folder
trans.sa_session.add( request )
trans.sa_session.flush()
-
return request
-
-
#
#---- Request Page ----------------------------------------------------------
#
- def __update_samples(self, request, **kwd):
+ def __show_request(self, trans, **kwd):
+ params = util.Params( kwd )
+ msg = util.restore_text( params.get( 'msg', '' ) )
+ messagetype = params.get( 'messagetype', 'done' )
+ add_sample = params.get('add_sample', False)
+ 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='requests_admin',
+ action='list',
+ status='error',
+ message="Invalid request ID") )
+ # get all data libraries accessible to this user
+ libraries = request.user.accessible_libraries( trans, [ trans.app.security_agent.permitted_actions.LIBRARY_ADD ] )
+ current_samples = []
+ for i, s in enumerate(request.samples):
+ lib_widget, folder_widget = self.__library_widgets(trans, request.user, i, libraries, s, **kwd)
+ current_samples.append(dict(name=s.name,
+ barcode=s.bar_code,
+ library=s.library,
+ folder=s.folder,
+ dataset_files=s.dataset_files,
+ field_values=s.values.content,
+ lib_widget=lib_widget,
+ folder_widget=folder_widget))
+ if add_sample:
+ lib_widget, folder_widget = self.__library_widgets(trans, request.user,
+ len(current_samples)+1,
+ libraries, None, **kwd)
+ current_samples.append(dict(name='Sample_%i' % (len(current_samples)+1),
+ barcode='',
+ library=None,
+ folder=None,
+ dataset_files=[],
+ field_values=['' for field in request.type.sample_form.fields],
+ lib_widget=lib_widget,
+ folder_widget=folder_widget))
+ return trans.fill_template( '/admin/requests/show_request.mako',
+ request=request,
+ request_details=self.request_details(trans, request.id),
+ current_samples=current_samples,
+ sample_copy=self.__copy_sample(current_samples),
+ details='hide', edit_mode=util.restore_text( params.get( 'edit_mode', 'False' ) ),
+ msg=msg, messagetype=messagetype )
+ def __library_widgets(self, trans, user, sample_index, libraries, sample=None, **kwd):
+ '''
+ This method creates the data library & folder selectbox for creating &
+ editing samples. First we get a list of all the libraries accessible to
+ the current user and display it in a selectbox. If the user has selected an
+ existing library then display all the accessible sub folders of the selected
+ data library.
+ '''
+ params = util.Params( kwd )
+ # data library selectbox
+ lib_id = params.get( "sample_%i_library_id" % sample_index, 'none' )
+ selected_lib = None
+ if sample and lib_id == 'none':
+ if sample.library:
+ lib_id = str(sample.library.id)
+ selected_lib = sample.library
+ # create data library selectbox with refresh on change enabled
+ lib_id_list = ['new'] + [str(lib.id) for lib in libraries.keys()]
+ lib_widget = SelectField( "sample_%i_library_id" % sample_index,
+ refresh_on_change=True,
+ refresh_on_change_values=lib_id_list )
+ # fill up the options in the Library selectbox
+ # first option 'none' is the value for "Select one" option
+ if lib_id == 'none':
+ lib_widget.add_option('Select one', 'none', selected=True)
+ else:
+ lib_widget.add_option('Select one', 'none')
+ # all the libraries available to the selected user
+ for lib, hidden_folder_ids in libraries.items():
+ if str(lib.id) == lib_id:
+ lib_widget.add_option(lib.name, lib.id, selected=True)
+ selected_lib, selected_hidden_folder_ids = lib, hidden_folder_ids.split(',')
+ else:
+ lib_widget.add_option(lib.name, lib.id)
+ lib_widget.refresh_on_change_values.append(lib.id)
+ # create the folder selectbox
+ folder_widget = SelectField( "sample_%i_folder_id" % sample_index )
+ # when editing a request, either the user has already selected a subfolder or not
+ if sample:
+ if sample.folder:
+ current_fid = sample.folder.id
+ else:
+ # when a folder not yet associated with the request then the
+ # the current folder is set to the root_folder of the
+ # parent data library if present.
+ if sample.library:
+ current_fid = sample.library.root_folder.id
+ else:
+ current_fid = params.get( "sample_%i_folder_id" % sample_index, 'none' )
+ else:
+ current_fid = 'none'
+ # first option
+ if lib_id == 'none':
+ folder_widget.add_option('Select one', 'none', selected=True)
+ else:
+ folder_widget.add_option('Select one', 'none')
+ if selected_lib:
+ # get all show-able folders for the selected library
+ showable_folders = trans.app.security_agent.get_showable_folders( user, user.all_roles(),
+ selected_lib,
+ [ trans.app.security_agent.permitted_actions.LIBRARY_ADD ],
+ selected_hidden_folder_ids )
+ for f in showable_folders:
+ if str(f.id) == str(current_fid):
+ folder_widget.add_option(f.name, f.id, selected=True)
+ else:
+ folder_widget.add_option(f.name, f.id)
+ return lib_widget, folder_widget
+ def __update_samples(self, trans, request, **kwd):
'''
This method retrieves all the user entered sample information and
returns an list of all the samples and their field values
'''
params = util.Params( kwd )
+ details = params.get( 'details', 'hide' )
+ edit_mode = params.get( 'edit_mode', 'False' )
+ # get all data libraries accessible to this user
+ libraries = request.user.accessible_libraries( trans, [ trans.app.security_agent.permitted_actions.LIBRARY_ADD ] )
+
current_samples = []
- for s in request.samples:
- current_samples.append([s.name, s.values.content])
- index = len(request.samples)
+ for i, s in enumerate(request.samples):
+ lib_widget, folder_widget = self.__library_widgets(trans, request.user, i, libraries, s, **kwd)
+ current_samples.append(dict(name=s.name,
+ barcode=s.bar_code,
+ library=s.library,
+ folder=s.folder,
+ field_values=s.values.content,
+ lib_widget=lib_widget,
+ folder_widget=folder_widget))
+ if edit_mode == 'False':
+ sample_index = len(request.samples)
+ else:
+ sample_index = 0
while True:
- if params.get( 'sample_%i_name' % index, '' ):
- sample_index = index
- sample_name = util.restore_text( params.get( 'sample_%i_name' % sample_index, '' ) )
- sample_values = []
+ if params.get( 'sample_%i_name' % sample_index, '' ):
+ # data library
+ try:
+ library = trans.sa_session.query( trans.app.model.Library ).get( int( params.get( 'sample_%i_library_id' % sample_index, None ) ) )
+ except:
+ library = None
+ # folder
+ try:
+ folder = trans.sa_session.query( trans.app.model.LibraryFolder ).get( int( params.get( 'sample_%i_folder_id' % sample_index, None ) ) )
+ except:
+ if library:
+ folder = library.root_folder
+ else:
+ folder = None
+ sample_info = dict( name=util.restore_text( params.get( 'sample_%i_name' % sample_index, '' ) ),
+ barcode=util.restore_text( params.get( 'sample_%i_barcode' % sample_index, '' ) ),
+ library=library,
+ folder=folder)
+ sample_info['field_values'] = []
for field_index in range(len(request.type.sample_form.fields)):
- sample_values.append(util.restore_text( params.get( 'sample_%i_field_%i' % (sample_index, field_index), '' ) ))
- current_samples.append([sample_name, sample_values])
- index = index + 1
+ sample_info['field_values'].append(util.restore_text( params.get( 'sample_%i_field_%i' % (sample_index, field_index), '' ) ))
+ if edit_mode == 'False':
+ sample_info['lib_widget'], sample_info['folder_widget'] = self.__library_widgets(trans,
+ request.user,
+ sample_index,
+ libraries,
+ None, **kwd)
+ current_samples.append(sample_info)
+ else:
+ sample_info['lib_widget'], sample_info['folder_widget'] = self.__library_widgets(trans,
+ request.user,
+ sample_index,
+ libraries,
+ request.samples[sample_index],
+ **kwd)
+ current_samples[sample_index] = sample_info
+ sample_index = sample_index + 1
else:
break
- details = params.get( 'details', 'hide' )
- edit_mode = params.get( 'edit_mode', 'False' )
- return current_samples, details, edit_mode
+ return current_samples, details, edit_mode, libraries
def __copy_sample(self, current_samples):
copy_list = SelectField('copy_sample')
copy_list.add_option('None', -1, selected=True)
for i, s in enumerate(current_samples):
- copy_list.add_option(s[0], i)
+ copy_list.add_option(s['name'], i)
return copy_list
@web.expose
@web.require_login( "create/submit sequencing requests" )
@@ -908,7 +910,7 @@
message="Invalid request ID",
**kwd) )
# get the user entered sample details
- current_samples, details, edit_mode = self.__update_samples( request, **kwd )
+ current_samples, details, edit_mode, libraries = self.__update_samples( trans, request, **kwd )
if params.get('import_samples_button', False) == 'Import samples':
try:
file_obj = params.get('file_data', '')
@@ -936,10 +938,27 @@
src_sample_index = int(params.get( 'copy_sample', -1 ))
if src_sample_index == -1:
# empty sample
- current_samples.append(['Sample_%i' % (len(current_samples)+1),['' for field in request.type.sample_form.fields]])
+ lib_widget, folder_widget = self.__library_widgets(trans, request.user,
+ len(current_samples),
+ libraries, None, **kwd)
+ current_samples.append(dict(name='Sample_%i' % (len(current_samples)+1),
+ barcode='',
+ library=None,
+ folder=None,
+ field_values=['' for field in request.type.sample_form.fields],
+ lib_widget=lib_widget,
+ folder_widget=folder_widget))
else:
- current_samples.append([current_samples[src_sample_index][0]+'_%i' % (len(current_samples)+1),
- [val for val in current_samples[src_sample_index][1]]])
+ lib_widget, folder_widget = self.__library_widgets(trans, request.user,
+ len(current_samples),
+ libraries, None, **kwd)
+ current_samples.append(dict(name=current_samples[src_sample_index]['name']+'_%i' % (len(current_samples)+1),
+ barcode='',
+ library_id='none',
+ folder_id='none',
+ field_values=[val for val in current_samples[src_sample_index]['field_values']],
+ lib_widget=lib_widget,
+ folder_widget=folder_widget))
return trans.fill_template( '/admin/requests/show_request.mako',
request=request,
request_details=self.request_details(trans, request.id),
@@ -952,13 +971,13 @@
msg = ''
for index in range(len(current_samples)-len(request.samples)):
sample_index = index + len(request.samples)
- sample_name = current_samples[sample_index][0]
+ sample_name = current_samples[sample_index]['name']
if not sample_name.strip():
msg = 'Please enter the name of sample number %i' % sample_index
break
count = 0
for i in range(len(current_samples)):
- if sample_name == current_samples[i][0]:
+ if sample_name == current_samples[i]['name']:
count = count + 1
if count > 1:
msg = "This request has <b>%i</b> samples with the name <b>%s</b>.\nSamples belonging to a request must have unique names." % (count, sample_name)
@@ -975,37 +994,45 @@
if edit_mode == 'False':
for index in range(len(current_samples)-len(request.samples)):
sample_index = len(request.samples)
- sample_name = util.restore_text( params.get( 'sample_%i_name' % sample_index, '' ) )
- sample_values = []
- for field_index in range(len(request.type.sample_form.fields)):
- sample_values.append(util.restore_text( params.get( 'sample_%i_field_%i' % (sample_index, field_index), '' ) ))
- form_values = trans.app.model.FormValues(request.type.sample_form, sample_values)
+ form_values = trans.app.model.FormValues(request.type.sample_form,
+ current_samples[sample_index]['field_values'])
trans.sa_session.add( form_values )
trans.sa_session.flush()
- s = trans.app.model.Sample(sample_name, '', request, form_values)
+ s = trans.app.model.Sample(current_samples[sample_index]['name'], '',
+ request, form_values,
+ current_samples[sample_index]['barcode'],
+ current_samples[sample_index]['library'],
+ current_samples[sample_index]['folder'],
+ dataset_files=[])
trans.sa_session.add( s )
trans.sa_session.flush()
else:
- for index in range(len(current_samples)):
- sample_index = index
- sample_name = current_samples[sample_index][0]
- new_sample_name = util.restore_text( params.get( 'sample_%i_name' % sample_index, '' ) )
- sample_values = []
- for field_index in range(len(request.type.sample_form.fields)):
- sample_values.append(util.restore_text( params.get( 'sample_%i_field_%i' % (sample_index, field_index), '' ) ))
- sample = request.has_sample(sample_name)
- if sample:
- form_values = trans.sa_session.query( trans.app.model.FormValues ).get( sample.values.id )
- form_values.content = sample_values
- trans.sa_session.add( form_values )
- trans.sa_session.flush()
- sample.name = new_sample_name
- trans.sa_session.add( sample )
- trans.sa_session.flush()
+ messagetype = 'done'
+ msg = 'Changes made to the sample(s) are saved. '
+ for sample_index in range(len(current_samples)):
+ sample = request.samples[sample_index]
+ sample.name = current_samples[sample_index]['name']
+ sample.library = current_samples[sample_index]['library']
+ sample.folder = current_samples[sample_index]['folder']
+ if request.submitted():
+ bc_msg = self.__validate_barcode(trans, sample, current_samples[sample_index]['barcode'])
+ if bc_msg:
+ messagetype = 'error'
+ msg += bc_msg
+ else:
+ sample.bar_code = current_samples[sample_index]['barcode']
+ trans.sa_session.add( sample )
+ trans.sa_session.flush()
+ form_values = trans.sa_session.query( trans.app.model.FormValues ).get( sample.values.id )
+ form_values.content = current_samples[sample_index]['field_values']
+ trans.sa_session.add( form_values )
+ trans.sa_session.flush()
return trans.response.send_redirect( web.url_for( controller='requests_admin',
action='list',
operation='show_request',
- id=trans.security.encode_id(request.id)) )
+ id=trans.security.encode_id(request.id),
+ messagetype=messagetype,
+ msg=msg ))
elif params.get('edit_samples_button', False) == 'Edit samples':
edit_mode = 'True'
return trans.fill_template( '/admin/requests/show_request.mako',
@@ -1013,13 +1040,21 @@
request_details=self.request_details(trans, request.id),
current_samples=current_samples,
sample_copy=self.__copy_sample(current_samples),
- details=details,
+ details=details, libraries=libraries,
edit_mode=edit_mode)
elif params.get('cancel_changes_button', False) == 'Cancel':
return trans.response.send_redirect( web.url_for( controller='requests_admin',
action='list',
operation='show_request',
id=trans.security.encode_id(request.id)) )
+ else:
+ return trans.fill_template( '/admin/requests/show_request.mako',
+ request=request,
+ request_details=self.request_details(trans, request.id),
+ current_samples=current_samples,
+ sample_copy=self.__copy_sample(current_samples),
+ details=details, libraries=libraries,
+ edit_mode=edit_mode, messagetype=messagetype, msg=msg)
@web.expose
@@ -1029,9 +1064,9 @@
msg = util.restore_text( params.get( 'msg', '' ) )
messagetype = params.get( 'messagetype', 'done' )
request = trans.sa_session.query( trans.app.model.Request ).get( int( params.get( 'request_id', 0 ) ) )
- current_samples, details, edit_mode = self.__update_samples( request, **kwd )
+ current_samples, details, edit_mode, libraries = self.__update_samples( trans, request, **kwd )
sample_index = int(params.get('sample_id', 0))
- sample_name = current_samples[sample_index][0]
+ sample_name = current_samples[sample_index]['name']
s = request.has_sample(sample_name)
if s:
trans.sa_session.delete( s )
@@ -1044,22 +1079,6 @@
sample_copy=self.__copy_sample(current_samples),
details=details,
edit_mode=edit_mode)
-
- @web.expose
- @web.require_login( "create/submit sequencing requests" )
- def toggle_request_details(self, trans, **kwd):
- params = util.Params( kwd )
- msg = util.restore_text( params.get( 'msg', '' ) )
- messagetype = params.get( 'messagetype', 'done' )
- request = trans.sa_session.query( trans.app.model.Request ).get( int( params.get( 'request_id', 0 ) ) )
- current_samples, details, edit_mode = self.__update_samples( request, **kwd )
- return trans.fill_template( '/admin/requests/show_request.mako',
- request=request,
- request_details=self.request_details(trans, request.id),
- current_samples = current_samples,
- sample_copy=self.__copy_sample(current_samples),
- details=details,
- edit_mode=edit_mode)
@web.expose
@web.require_admin
def request_details(self, trans, id):
@@ -1085,23 +1104,6 @@
request_details.append(dict(label='Date created',
value=request.create_time,
helptext=''))
- # library associated
- if request.library:
- value=request.library.name
- else:
- value = None
- request_details.append(dict(label='Data library',
- value=value,
- helptext='Data library where the resultant dataset will be stored'))
- # folder associated
- if request.folder:
- value = request.folder.name
- else:
- value = None
- request_details.append( dict( label='Data library folder',
- value=value,
- helptext='Data library folder where the resultant dataset will be stored' ) )
-
# form fields
for index, field in enumerate(request.type.request_form.fields):
if field['required']:
@@ -1122,6 +1124,33 @@
value=request.values.content[index],
helptext=field['helptext']+' ('+req+')'))
return request_details
+ def __validate_barcode(self, trans, sample, barcode):
+ '''
+ This method makes sure that the given barcode about to be assigned to
+ the given sample is gobally unique. That is, barcodes must be unique
+ across requests in Galaxy LIMS
+ '''
+ msg = ''
+ for index in range(len(sample.request.samples)):
+ # check for empty bar code
+ if not barcode.strip():
+ msg = 'Please fill the barcode for sample <b>%s</b>.' % samples[index].name
+ break
+ # check all the saved bar codes
+ all_samples = trans.sa_session.query( trans.app.model.Sample )
+ for s in all_samples:
+ if barcode == s.bar_code:
+ if sample.id == s.id:
+ continue
+ else:
+ msg = '''The bar code <b>%s</b> of sample <b>%s</b>
+ belongs another sample. The sample bar codes must be
+ unique throughout the system''' % \
+ (barcode, sample.name)
+ break
+ if msg:
+ break
+ return msg
@web.expose
@web.require_admin
def bar_codes(self, trans, **kwd):
@@ -1233,7 +1262,12 @@
for s in request.samples:
if s.current_state().id != request.type.states[-1].id:
complete = False
- if complete:
+ if request.complete() and not complete:
+ comments = "Sample(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()
+ 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)
@@ -1279,7 +1313,7 @@
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 )
+ #self.__set_request_state( trans, sample.request )
return trans.response.send_redirect( web.url_for( controller='requests_admin',
action='show_events',
sample_id=sample.id))
@@ -1306,7 +1340,217 @@
return trans.fill_template( '/admin/samples/events.mako',
events_list=events_list,
sample=sample, widgets=widgets, title=title)
+
+ #
+ # Data transfer from sequencer
+ #
+ @web.expose
+ @web.require_admin
+ def show_datatx_page( self, trans, **kwd ):
+ params = util.Params( kwd )
+ msg = util.restore_text( params.get( 'msg', '' ) )
+ messagetype = params.get( 'messagetype', 'done' )
+ try:
+ sample = trans.sa_session.query( trans.app.model.Sample ).get( trans.security.decode_id( kwd['sample_id'] ) )
+ except:
+ return trans.response.send_redirect( web.url_for( controller='requests_admin',
+ action='list',
+ status='error',
+ message="Invalid sample ID",
+ **kwd) )
+ return trans.fill_template( '/admin/requests/get_data.mako',
+ sample=sample, dataset_files=sample.dataset_files,
+ msg=msg, messagetype=messagetype, files=[],
+ folder_path=util.restore_text( params.get( 'folder_path', '' ) ))
+ def __get_files(self, trans, sample, folder_path):
+ '''
+ This method retrieves the filenames to be transfer from the remote host.
+ '''
+ datatx_info = sample.request.type.datatx_info
+ if not datatx_info['host'] or not datatx_info['username'] or not datatx_info['password']:
+ msg = "Error in sequencer login information."
+ return trans.response.send_redirect( web.url_for( controller='requests_admin',
+ action='show_datatx_page',
+ sample_id=trans.security.encode_id(sample.id),
+ messagetype='error',
+ msg=msg))
+ def print_ticks(d):
+ pass
+ cmd = 'ssh %s@%s "ls -F %s"' % ( datatx_info['username'],
+ datatx_info['host'],
+ folder_path)
+ output = pexpect.run(cmd, events={'.ssword:*': datatx_info['password']+'\r\n',
+ pexpect.TIMEOUT:print_ticks},
+ timeout=10)
+ if 'No such file or directory' in output:
+ msg = "No such folder (%s) exists on the sequencer." % folder_path
+ return trans.response.send_redirect( web.url_for( controller='requests_admin',
+ action='show_datatx_page',
+ sample_id=trans.security.encode_id(sample.id),
+ msg=msg, messagetype='error',
+ folder_path=folder_path ))
+ files = output.split()[2:]
+ return files
+
+ @web.expose
+ @web.require_admin
+ def get_data(self, trans, **kwd):
+ try:
+ sample = trans.sa_session.query( trans.app.model.Sample ).get( kwd['sample_id'] )
+ except:
+ return trans.response.send_redirect( web.url_for( controller='requests_admin',
+ action='list',
+ status='error',
+ message="Invalid sample ID" ) )
+ params = util.Params( kwd )
+ msg = util.restore_text( params.get( 'msg', '' ) )
+ messagetype = params.get( 'messagetype', 'done' )
+ folder_path = util.restore_text( params.get( 'folder_path', '' ) )
+ files_list = util.listify( params.get( 'files_list', '' ) )
+ if not folder_path:
+ return trans.fill_template( '/admin/requests/get_data.mako',
+ sample=sample, files=[],
+ dataset_files=sample.dataset_files,
+ folder_path=folder_path )
+ if folder_path[-1] != os.sep:
+ folder_path = folder_path+os.sep
+ if params.get( 'browse_button', False ):
+ # get the filenames from the remote host
+ files = self.__get_files(trans, sample, folder_path)
+ return trans.fill_template( '/admin/requests/get_data.mako',
+ sample=sample, files=files,
+ dataset_files=sample.dataset_files,
+ folder_path=folder_path )
+ elif params.get( 'folder_up', False ):
+ if folder_path[-1] == os.sep:
+ folder_path = os.path.dirname(folder_path[:-1])
+ # get the filenames from the remote host
+ files = self.__get_files(trans, sample, folder_path)
+ return trans.fill_template( '/admin/requests/get_data.mako',
+ sample=sample, files=files,
+ dataset_files=sample.dataset_files,
+ folder_path=folder_path )
+ elif params.get( 'open_folder', False ):
+ if len(files_list) == 1:
+ folder_path = os.path.join(folder_path, files_list[0])
+ # get the filenames from the remote host
+ files = self.__get_files(trans, sample, folder_path)
+ return trans.fill_template( '/admin/requests/get_data.mako',
+ sample=sample, files=files,
+ dataset_files=sample.dataset_files,
+ folder_path=folder_path )
+ elif params.get( 'remove_dataset_button', False ):
+ dataset_index = int(params.get( 'dataset_index', 0 ))
+ del sample.dataset_files[dataset_index]
+ trans.sa_session.add( sample )
+ trans.sa_session.flush()
+ return trans.fill_template( '/admin/requests/get_data.mako',
+ sample=sample,
+ dataset_files=sample.dataset_files)
+ elif params.get( 'start_transfer_button', False ):
+ for f in files_list:
+ sample.dataset_files.append([os.path.join(folder_path, f),
+ sample.transfer_status.NOT_STARTED])
+ trans.sa_session.add( sample )
+ trans.sa_session.flush()
+ return self.__start_datatx(trans, sample)
+
+ def __setup_datatx_user(self, trans, library, folder):
+ '''
+ This method sets up the datatx user:
+ - Checks if the user exists already, if not creates the user
+ - Checks if the user had ADD_LIBRARY permission on the target library
+ and the target folder, if not sets up the permissions.
+ '''
+ # Retrieve the upload user login information from the config file
+ config = ConfigParser.ConfigParser()
+ config.read('transfer_datasets.ini')
+ email = config.get("data_transfer_user_login_info", "email")
+ password = config.get("data_transfer_user_login_info", "password")
+ # check if the user already exists
+ datatx_user = trans.sa_session.query( trans.app.model.User ) \
+ .filter( trans.app.model.User.table.c.email==email ) \
+ .first()
+ if not datatx_user:
+ # if not create the user
+ datatx_user = trans.app.model.User( email=email )
+ datatx_user.set_password_cleartext( password )
+ if trans.app.config.use_remote_user:
+ datatx_user.external = True
+ trans.sa_session.add( datatx_user )
+ trans.sa_session.flush()
+ trans.app.security_agent.create_private_user_role( datatx_user )
+ trans.app.security_agent.user_set_default_permissions( datatx_user, history=False, dataset=False )
+ for role in datatx_user.all_roles():
+ if role.name == datatx_user.email and role.description == 'Private Role for %s' % datatx_user.email:
+ datatx_user_private_role = role
+ break
+ def check_permission(item_actions, role):
+ for item_permission in item_actions:
+ if item_permission.action == trans.app.security_agent.permitted_actions.LIBRARY_ADD.action \
+ and item_permission.role.id == role.id:
+ return True
+ return False
+ # check if this user has 'add' permissions on the target library & folder
+ # if not, set 'ADD' permission
+ if not check_permission(library.actions, datatx_user_private_role):
+ lp = trans.app.model.LibraryPermissions( trans.app.security_agent.permitted_actions.LIBRARY_ADD.action,
+ library,
+ datatx_user_private_role )
+ trans.sa_session.add( lp )
+ if not check_permission(folder.actions, datatx_user_private_role):
+ dp = trans.app.model.LibraryFolderPermissions( trans.app.security_agent.permitted_actions.LIBRARY_ADD.action,
+ folder,
+ datatx_user_private_role )
+ trans.sa_session.add( dp )
+ trans.sa_session.flush()
+ return datatx_user
+
+ def __start_datatx(self, trans, sample):
+ # data transfer user
+ datatx_user = self.__setup_datatx_user(trans, sample.library, sample.folder)
+ # validate sequecer information
+ datatx_info = sample.request.type.datatx_info
+ if not datatx_info['host'] or \
+ not datatx_info['username'] or \
+ not datatx_info['password']:
+ msg = "Error in sequencer login information."
+ return trans.response.send_redirect( web.url_for( controller='requests_admin',
+ action='show_datatx_page',
+ sample_id=trans.security.encode_id(sample.id),
+ messagetype='error',
+ msg=msg))
+ transfer_script = "scripts/galaxy_messaging/server/daemon.py"
+ for index, dataset in enumerate(sample.dataset_files):
+ dfile = dataset[0]
+ status = dataset[1]
+ if status == sample.transfer_status.NOT_STARTED:
+ cmd = "python %s %s %s %s %s %s %s %s %s" % ( transfer_script,
+ datatx_info['host'],
+ datatx_info['username'],
+ datatx_info['password'],
+ dfile,
+ sample.id,
+ index,
+ trans.security.encode_id(sample.library.id),
+ trans.security.encode_id(sample.folder.id))
+ # set the transfer status
+ sample.dataset_files[index][1] = sample.transfer_status.IN_PROGRESS
+ trans.sa_session.add( sample )
+ trans.sa_session.flush()
+ os.system(cmd)
+ # set the sample state to the last state
+ if sample.current_state().id != sample.request.type.states[-1].id:
+ event = trans.app.model.SampleEvent(sample, sample.request.type.states[-1],
+ 'The dataset are ready & are being transfered to Galaxy')
+ trans.sa_session.add( event )
+ trans.sa_session.flush()
+ return trans.response.send_redirect( web.url_for( controller='requests_admin',
+ action='show_datatx_page',
+ sample_id=trans.security.encode_id(sample.id)))
+
+
##
#### Request Type Stuff ###################################################
##
@@ -1379,16 +1623,36 @@
msg=msg,
messagetype=messagetype)
elif params.get( 'save_request_type', False ):
- st, msg = self.__save_request_type(trans, **kwd)
- if not st:
+ rt, msg = self.__save_request_type(trans, **kwd)
+ if not rt:
return trans.fill_template( '/admin/requests/create_request_type.mako',
forms=get_all_forms( trans ),
msg=msg,
messagetype='error')
return trans.response.send_redirect( web.url_for( controller='requests_admin',
action='manage_request_types',
- message='Request type <b>%s</b> has been created' % st.name,
+ message='Request type <b>%s</b> has been created' % rt.name,
status='done') )
+ elif params.get( 'save_changes', False ):
+ try:
+ rt = trans.sa_session.query( trans.app.model.RequestType ).get( int(kwd['rt_id']) )
+ except:
+ return trans.response.send_redirect( web.url_for( controller='requests_admin',
+ action='manage_request_types',
+ msg='Invalid request type ID',
+ messagetype='error') )
+ # data transfer info
+ rt.datatx_info = dict(host=util.restore_text( params.get( 'host', '' ) ),
+ username=util.restore_text( params.get( 'username', '' ) ),
+ password=util.restore_text( params.get( 'password', '' ) ))
+ trans.sa_session.add( rt )
+ trans.sa_session.flush()
+ return trans.response.send_redirect( web.url_for( controller='requests_admin',
+ action='manage_request_types',
+ operation='view',
+ id=trans.security.encode_id(rt.id),
+ msg='Changes made to request type <b>%s</b> has been saved' % rt.name,
+ messagetype='done') )
else:
rt_info, rt_states = self.__create_request_type_form(trans, **kwd)
return trans.fill_template( '/admin/requests/create_request_type.mako',
@@ -1448,6 +1712,10 @@
rt.desc = util.restore_text( params.get( 'desc', '' ) )
rt.request_form = trans.sa_session.query( trans.app.model.FormDefinition ).get( int( params.request_form_id ) )
rt.sample_form = trans.sa_session.query( trans.app.model.FormDefinition ).get( int( params.sample_form_id ) )
+ # data transfer info
+ rt.datatx_info = dict(host=util.restore_text( params.get( 'host', '' ) ),
+ username=util.restore_text( params.get( 'username', '' ) ),
+ password=util.restore_text( params.get( 'password', '' ) ))
trans.sa_session.add( rt )
trans.sa_session.flush()
# set sample states
diff -r 44fff02fb036 -r 37b55fad152b lib/galaxy/web/framework/__init__.py
--- a/lib/galaxy/web/framework/__init__.py Thu Feb 04 10:44:36 2010 -0500
+++ b/lib/galaxy/web/framework/__init__.py Thu Feb 04 11:01:45 2010 -0500
@@ -30,7 +30,9 @@
pkg_resources.require( "SQLAlchemy >= 0.4" )
from sqlalchemy import and_
-
+
+pkg_resources.require( "pexpect" )
+
import logging
log = logging.getLogger( __name__ )
diff -r 44fff02fb036 -r 37b55fad152b scripts/galaxy_messaging/server/daemon.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/galaxy_messaging/server/daemon.py Thu Feb 04 11:01:45 2010 -0500
@@ -0,0 +1,34 @@
+#!/usr/bin/python
+"""
+
+Data Transfer Script Daemon
+
+This script is called from Galaxy LIMS once the lab admin starts the data
+transfer process using the user interface. This creates a child process and
+this child process starts the data_transfer.py script as a new process
+
+This script passes all the arguments from Galaxy LIMS to the data_transfer.py script
+
+Usage:
+
+python daemon.py <sequencer_host>
+ <username>
+ <password>
+ <source_file>
+ <sample_id>
+ <dataset_index>
+ <library_id>
+ <folder_id>
+"""
+
+import sys, os
+# Perform first fork.
+try:
+ pid = os.fork( )
+ if pid > 0:
+ sys.exit(0) # Exit first parent.
+except OSError, e:
+ sys.stderr.write("fork #1 failed: (%d) %sn" % (e.errno, e.strerror))
+ sys.exit(1)
+os.execv(os.path.join( os.getcwd(), "scripts/galaxy_messaging/server/data_transfer.py"), sys.argv)
+
diff -r 44fff02fb036 -r 37b55fad152b scripts/galaxy_messaging/server/data_transfer.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/galaxy_messaging/server/data_transfer.py Thu Feb 04 11:01:45 2010 -0500
@@ -0,0 +1,211 @@
+#!/usr/bin/python
+"""
+
+Data Transfer Script: Sequencer to Galaxy
+
+This script is called from Galaxy LIMS once the lab admin starts the data
+transfer process using the user interface.
+
+Usage:
+
+python data_transfer.py <sequencer_host>
+ <username>
+ <password>
+ <source_file>
+ <sample_id>
+ <dataset_index>
+ <library_id>
+ <folder_id>
+"""
+
+import ConfigParser
+import sys, os, time, traceback
+import optparse
+import urllib,urllib2, cookielib, shutil
+import logging
+from galaxydb_interface import GalaxyDbInterface
+
+assert sys.version_info[:2] >= ( 2, 4 )
+new_path = [ os.path.join( os.getcwd(), "lib" ) ]
+new_path.extend( sys.path[1:] ) # remove scripts/ from the path
+sys.path = new_path
+
+from galaxy.util.json import from_json_string, to_json_string
+from galaxy import eggs
+import pkg_resources
+pkg_resources.require( "pexpect" )
+import pexpect
+
+pkg_resources.require( "simplejson" )
+import simplejson
+
+curr_dir = os.getcwd()
+logfile = os.path.join(curr_dir, 'data_transfer.log')
+logging.basicConfig(filename=logfile, level=logging.DEBUG,
+ format="%(asctime)s [%(levelname)s] %(message)s")
+
+class DataTransfer(object):
+
+ def __init__(self, host, username, password, remote_file, sample_id,
+ dataset_index, library_id, folder_id):
+ self.host = host
+ self.username = username
+ self.password = password
+ self.remote_file = remote_file
+ self.sample_id = sample_id
+ self.dataset_index = dataset_index
+ self.library_id = library_id
+ self.folder_id = folder_id
+ try:
+ # Retrieve the upload user login information from the config file
+ config = ConfigParser.ConfigParser()
+ config.read('universe_wsgi.ini')
+ self.server_host = config.get("server:main", "host")
+ self.server_port = config.get("server:main", "port")
+ self.database_connection = config.get("app:main", "database_connection")
+ self.import_dir = config.get("app:main", "library_import_dir")
+ # create the destination directory within the import directory
+ self.server_dir = os.path.join( self.import_dir, 'datatx_'+str(os.getpid()) )
+ os.mkdir(self.server_dir)
+ if not os.path.exists(self.server_dir):
+ raise Exception
+ except:
+ logging.error(traceback.format_exc())
+ logging.error('FATAL ERROR')
+ if self.database_connection:
+ self.update_status('Error')
+ sys.exit(1)
+
+ def start(self):
+ '''
+ This method executes the file transfer from the sequencer, adds the dataset
+ to the data library & finally updates the data transfer status in the db
+ '''
+ # datatx
+ self.transfer_file()
+ # add the dataset to the given library
+ self.add_to_library()
+ # update the data transfer status in the db
+ self.update_status('Complete')
+ # cleanup
+ self.cleanup()
+ sys.exit(0)
+
+ def cleanup(self):
+ '''
+ remove the directory created to store the dataset files temporarily
+ before adding the same to the data library
+ '''
+ try:
+ shutil.rmtree( self.server_dir )
+ except:
+ self.error_and_exit()
+
+
+ def error_and_exit(self):
+ '''
+ This method is called any exception is raised. This prints the traceback
+ and terminates this script
+ '''
+ logging.error(traceback.format_exc())
+ logging.error('FATAL ERROR')
+ self.update_status('Error')
+ sys.exit(1)
+
+ def transfer_file(self):
+ '''
+ This method executes a scp process using pexpect library to transfer
+ the dataset file from the remote sequencer to the Galaxy server
+ '''
+ def print_ticks(d):
+ pass
+ try:
+ cmd = "scp %s@%s:%s %s" % ( self.username,
+ self.host,
+ self.remote_file,
+ self.server_dir)
+ logging.debug(cmd)
+ output = pexpect.run(cmd, events={'.ssword:*': self.password+'\r\n',
+ pexpect.TIMEOUT:print_ticks},
+ timeout=10)
+ logging.debug(output)
+ if not os.path.exists(os.path.join(self.server_dir, os.path.basename(self.remote_file))):
+ raise Exception
+ except:
+ self.error_and_exit()
+
+
+ def add_to_library(self):
+ '''
+ This method adds the dataset file to the target data library & folder
+ by opening the corresponding url in Galaxy server running.
+ '''
+ try:
+ logging.debug('Adding %s to library...' % os.path.basename(self.remote_file))
+ # Retrieve the upload user login information from the config file
+ config = ConfigParser.ConfigParser()
+ config.read('transfer_datasets.ini')
+ email = config.get("data_transfer_user_login_info", "email")
+ password = config.get("data_transfer_user_login_info", "password")
+ # create url
+ base_url = "http://%s:%s" % (self.server_host, self.server_port)
+ # login
+ url = "%s/user/login?email=%s&password=%s" % (base_url, email, password)
+ cj = cookielib.CookieJar()
+ opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj))
+ f = opener.open(url)
+ if f.read().find("Now logged in as "+email) == -1:
+ # if the user doesnt exist, create the user
+ url = "%s/user/create?email=%s&username=%s&password=%s&confirm=%s&create_user_button=Submit" % ( base_url, email, email, password, password )
+ f = opener.open(url)
+ if f.read().find("Now logged in as "+email) == -1:
+ raise Exception
+ # after login, add dataset to the library
+ params = urllib.urlencode(dict( cntrller='library_admin',
+ tool_id='upload1',
+ tool_state='None',
+ library_id=self.library_id,
+ folder_id=self.folder_id,
+ upload_option='upload_directory',
+ file_type='auto',
+ server_dir=os.path.basename(self.server_dir),
+ dbkey='',
+ runtool_btn='Upload to library'))
+ #url = "http://localhost:8080/library_common/upload_library_dataset?cntrller=librar…"
+ #url = base_url+"/library_common/upload_library_dataset?library_id=adb5f5c93f827949&tool_id=upload1&file_type=auto&server_dir=datatx_22858&dbkey=%3F&upload_option=upload_directory&folder_id=529fd61ab1c6cc36&cntrller=library_admin&tool_state=None&runtool_btn=Upload+to+library"
+ url = base_url+"/library_common/upload_library_dataset"
+ logging.debug(url)
+ logging.debug(params)
+ f = opener.open(url, params)
+ #print f.read()
+ except:
+ self.error_and_exit()
+
+ def update_status(self, status):
+ '''
+
+ '''
+ try:
+ galaxy = GalaxyDbInterface(self.database_connection)
+ df = from_json_string(galaxy.get_sample_dataset_files(self.sample_id))
+ logging.debug(df)
+ df[self.dataset_index][1] = status
+
+ galaxy.set_sample_dataset_files(self.sample_id, to_json_string(df))
+ logging.debug("######################\n"+str(from_json_string(galaxy.get_sample_dataset_files(self.sample_id))[self.dataset_index]))
+ except:
+ logging.error(traceback.format_exc())
+ logging.error('FATAL ERROR')
+ sys.exit(1)
+
+if __name__ == '__main__':
+ logging.info('STARTING %i %s' % (os.getpid(), str(sys.argv)))
+ logging.info('daemonized %i' % os.getpid())
+ #
+ # Start the daemon
+ #
+ dt = DataTransfer(sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4],
+ int(sys.argv[5]), int(sys.argv[6]), sys.argv[7], sys.argv[8])
+ dt.start()
+
+
diff -r 44fff02fb036 -r 37b55fad152b scripts/galaxy_messaging/server/galaxydb_interface.py
--- a/scripts/galaxy_messaging/server/galaxydb_interface.py Thu Feb 04 10:44:36 2010 -0500
+++ b/scripts/galaxy_messaging/server/galaxydb_interface.py Thu Feb 04 11:01:45 2010 -0500
@@ -12,6 +12,7 @@
new_path.extend( sys.path[1:] ) # remove scripts/ from the path
sys.path = new_path
from galaxy import eggs
+from galaxy.model.custom_types import *
import pkg_resources
pkg_resources.require( "psycopg2" )
import psycopg2
@@ -126,6 +127,16 @@
request_id=self.request_id,
state=request_state,
comment='All samples of this request have finished processing.')
+
+ def get_sample_dataset_files(self, sample_id):
+ subsubquery = select(columns=[self.sample_table.c.dataset_files],
+ whereclause=self.sample_table.c.id==sample_id)
+ return subsubquery.execute().fetchall()[0][0]
+
+ def set_sample_dataset_files(self, sample_id, value):
+ u = self.sample_table.update(whereclause=self.sample_table.c.id==sample_id)
+ u.execute(dataset_files=value)
+
diff -r 44fff02fb036 -r 37b55fad152b templates/admin/forms/edit_form.mako
--- a/templates/admin/forms/edit_form.mako Thu Feb 04 10:44:36 2010 -0500
+++ b/templates/admin/forms/edit_form.mako Thu Feb 04 11:01:45 2010 -0500
@@ -30,6 +30,25 @@
});
</script>
+<script type="text/javascript">
+$(document).ready(function(){
+ //hide the all of the element with class msg_body
+ $(".msg_body").hide();
+ //toggle the componenet with class msg_body
+ $(".msg_head").click(function(){
+ $(this).next(".msg_body").slideToggle(450);
+ });
+});
+</script>
+<style type="text/css">
+.msg_head {
+ padding: 0px 0px;
+ cursor: pointer;
+}
+
+}
+</style>
+
<%def name="render_selectbox_options( index, field_attr )">
%if field_attr[0] == 'Type':
%if field_attr[1].get_selected()[0] == 'SelectField':
@@ -55,11 +74,16 @@
%endif
</%def>
-<%def name="render_field( index, field )">
+<%def name="render_field( index, field, saved )">
+ %if saved:
+ <h4 class="msg_head">
+ <div class="form-row">${index+1}. ${field[0][1].value} (${field[2][1].get_selected()[1]})</div>
+ </h4>
+ <div class="msg_body">
+ %else:
+ <div class="msg_body2">
+ %endif
<div class="repeat-group-item">
- <div class="form-row">
- <label>Field ${1+index}</label>
- </div>
%for field_attr in field:
<div class="form-row">
<label>${field_attr[0]}</label>
@@ -70,7 +94,9 @@
<div class="form-row">
<input type="submit" name="remove_button" value="Remove field ${index+1}"/>
</div>
- </div>
+ </div>
+ </div>
+
</%def>
<%def name="render_layout( index, widget )">
@@ -109,7 +135,11 @@
%endif
<div class="toolFormTitle">Fields (${len(form.fields)})</div>
%for ctr, field in enumerate(field_details):
- ${render_field( ctr, field )}
+ %if ctr < len(form.fields):
+ ${render_field( ctr, field, True )}
+ %else:
+ ${render_field( ctr, field, False )}
+ %endif
%endfor
<div class="form-row">
<input type="submit" name="add_field_button" value="Add field"/>
diff -r 44fff02fb036 -r 37b55fad152b templates/admin/forms/show_form_read_only.mako
--- a/templates/admin/forms/show_form_read_only.mako Thu Feb 04 10:44:36 2010 -0500
+++ b/templates/admin/forms/show_form_read_only.mako Thu Feb 04 11:01:45 2010 -0500
@@ -8,7 +8,9 @@
<%def name="render_grid( grid_index, grid_name, fields_dict )">
%if grid_name:
- <div class="toolFormTitle">${grid_name}</div>
+ <div class="form-row">
+ <h4>${grid_name}</h4>
+ </div>
%endif
<div style="clear: both"></div>
<table class="grid">
@@ -83,7 +85,7 @@
${render_grid( 0, '', form.fields_of_grid( None ) )}
%else:
%for grid_index, grid_name in enumerate(form.layout):
- ${render_grid( grid_index, grid_name, form.fields_of_grid( grid_name ) )}
+ ${render_grid( grid_index, grid_name, form.fields_of_grid( grid_index ) )}
%endfor
%endif
%else:
diff -r 44fff02fb036 -r 37b55fad152b templates/admin/requests/create_request_type.mako
--- a/templates/admin/requests/create_request_type.mako Thu Feb 04 10:44:36 2010 -0500
+++ b/templates/admin/requests/create_request_type.mako Thu Feb 04 11:01:45 2010 -0500
@@ -49,6 +49,22 @@
<div class="form-row">
<input type="submit" name="add_state_button" value="Add state"/>
</div>
+ <div class="toolFormTitle">Sequencer information</div>
+ <div class="form-row">
+ This information is only needed for transferring data from sequencer to Galaxy
+ </div>
+ <div class="form-row">
+ <label>Hostname or IP Address:</label>
+ <input type="text" name="host" value="" size="40"/>
+ </div>
+ <div class="form-row">
+ <label>Username:</label>
+ <input type="text" name="username" value="" size="40"/>
+ </div>
+ <div class="form-row">
+ <label>Password:</label>
+ <input type="password" name="password" value="" size="40"/>
+ </div>
<div class="form-row">
<div style="float: left; width: 250px; margin-right: 10px;">
<input type="hidden" name="new" value="submitted" size="40"/>
diff -r 44fff02fb036 -r 37b55fad152b templates/admin/requests/get_data.mako
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/admin/requests/get_data.mako Thu Feb 04 11:01:45 2010 -0500
@@ -0,0 +1,135 @@
+<%inherit file="/base.mako"/>
+<%namespace file="/message.mako" import="render_msg" />
+
+
+%if msg:
+ ${render_msg( msg, messagetype )}
+%endif
+
+<script type="text/javascript">
+$(document).ready(function(){
+ //hide the all of the element with class msg_body
+ $(".msg_body").hide();
+ //toggle the componenet with class msg_body
+ $(".msg_head").click(function(){
+ $(this).next(".msg_body").slideToggle(450);
+ });
+});
+</script>
+<style type="text/css">
+.msg_head {
+ padding: 0px 0px;
+ cursor: pointer;
+}
+
+}
+</style>
+
+
+<h2>Data transfer from Sequencer</h2>
+<h3>Sample "${sample.name}" of Request "${sample.request.name}"</h3>
+
+<ul class="manage-table-actions">
+## %if sample.request.submitted() and sample.untransfered_dataset_files():
+## <li>
+## <a class="action-button" href="${h.url_for( controller='requests_admin', action='start_datatx', id=trans.security.encode_id(sample.id) )}">
+## <span>Start data transfer</span></a>
+## </li>
+## %endif
+ %if sample.request.submitted() and sample.inprogress_dataset_files():
+ <li>
+ <a class="action-button" href="${h.url_for( controller='requests_admin', action='show_datatx_page', sample_id=trans.security.encode_id(sample.id) )}">
+ <span>Refresh this page</span></a>
+ </li>
+ %endif
+ <li>
+ <a class="action-button" href="${h.url_for( controller='requests_admin', action='manage_request_types', operation='view', id=trans.security.encode_id(sample.request.type.id) )}">
+ <span>Sequencer information</span></a>
+ </li>
+ <li>
+ <a class="action-button" href="${h.url_for( controller='library_common', action='browse_library', cntrller='library', id=trans.security.encode_id( sample.library.id ) )}">
+ <span>${sample.library.name} Data Library</span></a>
+ </li>
+ <li>
+ <a class="action-button" href="${h.url_for( controller='requests_admin', action='list', operation='show_request', id=trans.security.encode_id(sample.request.id) )}">
+ <span>Browse this request</span></a>
+ </li>
+</ul>
+
+<div class="toolForm">
+ <form name="get_data" action="${h.url_for( controller='requests_admin', action='get_data', sample_id=sample.id)}" method="post" >
+ %if len(dataset_files):
+ <div class="form-row">
+ <h4>Datasets Transfered</h4>
+ <div class="form-row">
+ <table class="grid">
+ <thead>
+ <tr>
+ <th>Dataset File</th>
+ <th>Transfer Status</th>
+ ##<th>Data Library</th>
+ <th></th>
+ </tr>
+ <thead>
+ <tbody>
+ %for dataset_index, dataset_file in enumerate(dataset_files):
+ ${sample_dataset_files( dataset_index, dataset_file[0], dataset_file[1] )}
+ %endfor
+ </tbody>
+ </table>
+ </div>
+ </div>
+ %endif
+ <div class="form-row">
+ <h4>Select files for transfer</h4>
+ <div style="width: 60%;">
+ <div class="form-row">
+ <label>Folder path on the sequencer:</label>
+ <input type="text" name="folder_path" value="${folder_path}" size="100"/>
+ <input type="submit" name="browse_button" value="List contents"/>
+ <input type="submit" name="open_folder" value="Open folder"/>
+ <input type="submit" name="folder_up" value="Up"/>
+ </div>
+ <div class="form-row">
+ <select name="files_list" id="files_list" style="max-width: 98%; width: 98%; height: 150px; font-size: 100%;" multiple>
+ %for index, f in enumerate(files):
+ <option value="${f}">${f}</option>
+ %endfor
+ </select>
+ </div>
+ <div class="form-row">
+ <input type="submit" name="start_transfer_button" value="Transfer"/>
+ </div>
+ </div>
+ </div>
+ </form>
+</div>
+
+<%def name="sample_dataset_files( dataset_index, dataset_file, status )">
+ <tr>
+ <td>
+## <label class="msg_head"><a href="${h.url_for( controller='requests_admin', action='show_dataset_file', sample_id=trans.security.encode_id(sample.id), dataset_index=dataset_index )}">${dataset_file.split('/')[-1]}</a></label>
+ <div class="msg_head"><u>${dataset_file.split('/')[-1]}</u></div>
+ <div class="msg_body">
+ ${dataset_file}
+ </div>
+ </td>
+ <td>
+ %if status == sample.transfer_status.IN_PROGRESS:
+ <i>${status}</i>
+ %else:
+ ${status}
+ %endif
+ </td>
+ ##<td></td>
+ %if status == sample.transfer_status.NOT_STARTED:
+ <td>
+ <a class="action-button" href="${h.url_for( controller='requests_admin', action='get_data', sample_id=sample.id, remove_dataset_button=True, dataset_index=dataset_index )}">
+ <img src="${h.url_for('/static/images/delete_icon.png')}" />
+ <span></span></a>
+ </td>
+ %else:
+ <td></td>
+ %endif
+ </tr>
+</%def>
\ No newline at end of file
diff -r 44fff02fb036 -r 37b55fad152b templates/admin/requests/show_request.mako
--- a/templates/admin/requests/show_request.mako Thu Feb 04 10:44:36 2010 -0500
+++ b/templates/admin/requests/show_request.mako Thu Feb 04 11:01:45 2010 -0500
@@ -5,6 +5,51 @@
${render_msg( msg, messagetype )}
%endif
+<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 ){
+ $( "#show_request" ).submit();
+ }
+ });
+});
+</script>
+
+
+<script type="text/javascript">
+$(document).ready(function(){
+ //hide the all of the element with class msg_body
+ $(".msg_body").hide();
+ //toggle the componenet with class msg_body
+ $(".msg_head").click(function(){
+ $(this).next(".msg_body").slideToggle(450);
+ });
+});
+</script>
+<style type="text/css">
+.msg_head {
+ padding: 15px 0px;
+ cursor: pointer;
+}
+
+}
+</style>
+
%if request.rejected():
${render_msg( "Reason for rejection: "+request.last_comment(), "warning" )}
%endif
@@ -27,37 +72,144 @@
<span>Reject request</span></a>
</li>
%endif
- %if request.submitted() and request.samples:
- <li>
- <a class="action-button" href="${h.url_for( controller='requests_admin', action='bar_codes', request_id=request.id)}">
- <span>Bar codes</span></a>
- </li>
- %endif
+## %if request.submitted() and request.samples:
+## <li>
+## <a class="action-button" href="${h.url_for( controller='requests_admin', action='bar_codes', request_id=request.id)}">
+## <span>Bar codes</span></a>
+## </li>
+## %endif
<li>
<a class="action-button" href="${h.url_for( controller='requests_admin', action='list', operation='events', id=trans.security.encode_id(request.id) )}">
<span>History</span></a>
</li>
+
</ul>
+<%def name="show_basic_info_form( sample_index, sample, info )">
+ <td>
+ <input type="text" name=sample_${sample_index}_name value="${info['name']}" size="10"/>
+ <div class="toolParamHelp" style="clear: both;">
+ <i>${' (required)' }</i>
+ </div>
+ </td>
+ %if sample:
+ %if sample.request.unsubmitted():
+ <td></td>
+ %else:
+ <td><input type="text" name=sample_${sample_index}_barcode value="${info['barcode']}" size="10"/></td>
+ %endif
+ %else:
+ <td></td>
+ %endif
+ %if sample:
+ %if sample.request.unsubmitted():
+ <td>Unsubmitted</td>
+ %else:
+ <td><a href="${h.url_for( controller='requests_admin', action='show_events', sample_id=sample.id)}">${sample.current_state().name}</a></td>
+ %endif
+ %else:
+ <td></td>
+ %endif
+ <td>${info['lib_widget'].get_html()}</td>
+ <td>${info['folder_widget'].get_html()}</td>
+ %if request.submitted() or request.complete():
+ %if sample:
+ <td><a href="${h.url_for( controller='requests_admin', action='show_datatx_page', sample_id=trans.security.encode_id(sample.id) )}">${len(sample.dataset_files)}</a></td>
+ %else:
+ <td><a href="${h.url_for( controller='requests_admin', action='show_datatx_page', sample_id=trans.security.encode_id(sample.id) )}">Add</a></td>
+ %endif
+ %endif
+</%def>
-<%def name="render_sample_form( index, sample_name, sample_values, grid_index, fields_dict )">
- %if grid_index == 0:
- <td>
- <input type="text" name=sample_${index}_name value="${sample_name}" size="10"/>
- <div class="toolParamHelp" style="clear: both;">
- <i>${' (required)' }</i>
- </div>
- </td>
- <td>
- </td>
- <td>
- </td>
- %else:
- <td>
- ${sample_name}
- </td>
- %endif
+## This function displays the "Basic Information" grid
+<%def name="render_basic_info_grid()">
+ <h4>Sample Information</h4>
+ <table class="grid">
+ <thead>
+ <tr>
+ <th>Name</th>
+ <th>Barcode</th>
+ <th>State</th>
+ <th>Data Library</th>
+ <th>Folder</th>
+ %if request.submitted() or request.complete():
+ <th>Dataset(s)</th>
+ %endif
+ <th></th>
+ </tr>
+ <thead>
+ <tbody>
+ <%
+ trans.sa_session.refresh( request )
+ %>
+ %for sample_index, info in enumerate(current_samples):
+ <%
+ if sample_index in range(len(request.samples)):
+ sample = request.samples[sample_index]
+ else:
+ sample = None
+ %>
+ %if edit_mode == 'True':
+ <tr>
+ ${show_basic_info_form( sample_index, sample, info )}
+ </tr>
+ %else:
+ <tr>
+ %if sample_index in range(len(request.samples)):
+ <td>${info['name']}</td>
+ <td>${info['barcode']}</td>
+ <td>
+ %if sample:
+ %if sample.request.unsubmitted():
+ Unsubmitted
+ %else:
+ <a href="${h.url_for( controller='requests_admin', action='show_events', sample_id=sample.id)}">${sample.current_state().name}</a>
+ %endif
+ %endif
+ </td>
+ %if info['library']:
+ <td><a href="${h.url_for( controller='library_common', action='browse_library', cntrller='library', id=trans.security.encode_id( info['library'].id ) )}">${info['library'].name}</a></td>
+ %else:
+ <td></td>
+ %endif
+ %if info['folder']:
+ <td>${info['folder'].name}</td>
+ %else:
+ <td></td>
+ %endif
+ %if request.submitted() or request.complete():
+ <td>
+ <a href="${h.url_for( controller='requests_admin', action='show_datatx_page', sample_id=trans.security.encode_id(sample.id) )}">${len(sample.dataset_files)}</a>
+ </td>
+ %endif
+
+
+ %else:
+ ${show_basic_info_form( sample_index, sample, info )}
+ %endif
+ %if request.unsubmitted() or request.rejected():
+ <td>
+ %if sample:
+ %if sample.request.unsubmitted():
+ <a class="action-button" href="${h.url_for( controller='requests_admin', action='delete_sample', request_id=request.id, sample_id=sample_index )}">
+ <img src="${h.url_for('/static/images/delete_icon.png')}" />
+ <span></span></a>
+ %endif
+ %endif
+ </td>
+ %endif
+ </tr>
+ %endif
+ %endfor
+ </tbody>
+ </table>
+</%def>
+
+<%def name="render_sample_form( index, sample_name, sample_values, fields_dict )">
+ <td>
+ ${sample_name}
+ </td>
%for field_index, field in fields_dict.items():
<td>
%if field['type'] == 'TextField':
@@ -75,7 +227,7 @@
%elif field['type'] == 'CheckboxField':
<input type="checkbox" name="sample_${index}_field_${field_index}" value="Yes"/>
%elif field['type'] == 'NumberField':
- <input type=int name="sample_${index}_field_${field_index}" value="${sample_values[field_index]}" size="7"/>
+ <input type="int" name="sample_${index}_field_${field_index}" value="${sample_values[field_index]}" size="7"/>
%endif
<div class="toolParamHelp" style="clear: both;">
<i>${'('+field['required']+')' }</i>
@@ -84,24 +236,14 @@
%endfor
</%def>
-<%def name="render_sample( index, sample, grid_index, fields_dict )">
+<%def name="render_sample( index, sample_name, sample_values, fields_dict )">
<td>
- ${sample.name}
+ ${sample_name}
</td>
- %if grid_index == 0:
- <td>${sample.bar_code}</td>
- <td>
- %if sample.request.new():
- Unsubmitted
- %else:
- <a href="${h.url_for( controller='requests_admin', action='show_events', sample_id=sample.id)}">${sample.current_state().name}</a>
- %endif
- </td>
- %endif
%for field_index, field in fields_dict.items():
<td>
- %if sample.values.content[field_index]:
- ${sample.values.content[field_index]}
+ %if sample_values[field_index]:
+ ${sample_values[field_index]}
%else:
<i>None</i>
%endif
@@ -111,22 +253,16 @@
<div class="toolForm">
<div class="form-row">
- %if details == "show":
- <a href="${h.url_for( controller='requests_admin', action='toggle_request_details', request_id=request.id, details="hide" )}">Hide request details</a>
- </div>
+ <div class="msg_list">
+ <h4 class="msg_head">Request Information</h4>
+ <div class="msg_body">
%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'] == 'Data library':
- %if rd['value']:
- <a href="${h.url_for( controller='library_common', action='browse_library', cntrller='requests_admin', id=trans.security.encode_id( request.library.id ) )}">${rd['value']}</a>
- %else:
- <i>None</i>
- %endif
- %elif rd['label'] == 'State':
+ %if rd['label'] == 'State':
<a href="${h.url_for( controller='requests_admin', action='list', operation='events', id=trans.security.encode_id(request.id) )}">${rd['value']}</a>
%else:
${rd['value']}
@@ -144,25 +280,27 @@
</ul>
</div>
</div>
- %else:
- <a href="${h.url_for( controller='requests_admin', action='toggle_request_details', request_id=request.id, details="show" )}">Show request details</a>
- %endif
+ </div>
+ </div>
</div>
+
<%def name="render_grid( grid_index, grid_name, fields_dict )">
+ <div class="msg_list">
%if grid_name:
- <div class="toolFormTitle">${grid_name}</div>
+ <h4 class="msg_head">${grid_name}</h4>
+ %else:
+ <h4>Grid ${grid_index}</h4>
%endif
- <div style="clear: both"></div>
+ %if edit_mode == 'False' or len(current_samples) <= len(request.samples):
+ <div class="msg_body">
+ %else:
+ <div class="msg_body2">
+ %endif
<table class="grid">
<thead>
<tr>
- <th>No.</th>
- <th>Sample Name</th>
- %if grid_index == 0:
- <th>Barcode</th>
- <th>State</th>
- %endif
+ <th>Name</th>
%for index, field in fields_dict.items():
<th>
${field['label']}
@@ -181,50 +319,36 @@
%for sample_index, sample in enumerate(current_samples):
%if edit_mode == 'True':
<tr>
- <td>${sample_index+1}</td>
- ${render_sample_form( sample_index, sample[0], sample[1], grid_index, fields_dict)}
- <td>
- %if request.unsubmitted() and grid_index == 0:
- <a class="action-button" href="${h.url_for( controller='requests_admin', action='delete_sample', request_id=request.id, sample_id=sample_index)}">
- <img src="${h.url_for('/static/images/delete_icon.png')}" />
- <span></span></a>
- %endif
- </td>
+ ${render_sample_form( sample_index, sample['name'], sample['field_values'], fields_dict)}
</tr>
%else:
<tr>
- <td>${sample_index+1}</td>
%if sample_index in range(len(request.samples)):
- ${render_sample( sample_index, request.samples[sample_index], grid_index, fields_dict )}
+ ${render_sample( sample_index, sample['name'], sample['field_values'], fields_dict )}
%else:
- ${render_sample_form( sample_index, sample[0], sample[1], grid_index, fields_dict)}
+ ${render_sample_form( sample_index, sample['name'], sample['field_values'], fields_dict)}
%endif
- <td>
- %if grid_index == 0:
- <a class="action-button" href="${h.url_for( controller='requests_admin', action='delete_sample', request_id=request.id, sample_id=sample_index)}">
- <img src="${h.url_for('/static/images/delete_icon.png')}" />
- <span></span></a>
- %endif
- </td>
</tr>
%endif
%endfor
</tbody>
</table>
+ </div>
+ </div>
</%def>
<div class="toolForm">
##<div class="toolFormTitle">Samples (${len(request.samples)})</div>
<form id="show_request" name="show_request" action="${h.url_for( controller='requests_admin', action='show_request', edit_mode=edit_mode )}" enctype="multipart/form-data" method="post" >
<div class="form-row">
- %if current_samples:
- %if not request.type.sample_form.layout:
- ${render_grid( 0, "", request.type.sample_form.fields_of_grid( None ) )}
- %else:
- %for grid_index, grid_name in enumerate(request.type.sample_form.layout):
- ${render_grid( grid_index, grid_name, request.type.sample_form.fields_of_grid( grid_name ) )}
- %endfor
- %endif
+ %if current_samples:
+ ## first render the basic info grid
+ ${render_basic_info_grid()}
+ ## then render the other grid(s)
+ <% trans.sa_session.refresh( request.type.sample_form ) %>
+ %for grid_index, grid_name in enumerate(request.type.sample_form.layout):
+ ${render_grid( grid_index, grid_name, request.type.sample_form.fields_of_grid( grid_index ) )}
+ %endfor
%else:
<label>There are no samples.</label>
%endif
@@ -233,6 +357,7 @@
<table class="grid">
<tbody>
<tr>
+ %if not request.complete():
<div class="form-row">
<td>
%if current_samples and not request.complete():
@@ -254,6 +379,7 @@
</td>
%endif
</div>
+ %endif
</tr>
</tbody>
</table>
@@ -264,15 +390,18 @@
<input type="hidden" name="refresh" value="true" size="40"/>
</div>
<div style="clear: both"></div>
- </div>
- <div class="form-row">
- %if edit_mode == 'True':
+ </div>
+ %if edit_mode == 'True':
+ <div class="form-row">
<input type="submit" name="save_samples_button" value="Save"/>
<input type="submit" name="cancel_changes_button" value="Cancel"/>
- %elif request.unsubmitted():
+ </div>
+ %elif request.unsubmitted():
+ <div class="form-row">
<input type="submit" name="save_samples_button" value="Save"/>
- %endif
- </div>
+ </div>
+ %endif
+
%endif
<input type="hidden" name="request_id" value="${request.id}" />
</form>
diff -r 44fff02fb036 -r 37b55fad152b templates/admin/requests/view_request_type.mako
--- a/templates/admin/requests/view_request_type.mako Thu Feb 04 10:44:36 2010 -0500
+++ b/templates/admin/requests/view_request_type.mako Thu Feb 04 11:01:45 2010 -0500
@@ -6,9 +6,11 @@
${render_msg( msg, messagetype )}
%endif
+<h2>Request Type "${request_type.name}"</h2>
+
<div class="toolForm">
<div class="toolFormTitle">Request type information</div>
- <form name="library">
+ <form name="view_request_type" action="${h.url_for( controller='requests_admin', action='create_request_type', rt_id=request_type.id)}" method="post" >
<div class="form-row">
<label>Name</label>
${request_type.name}
@@ -32,12 +34,31 @@
${request_type.sample_form.name}
</div>
<div class="toolFormTitle">Possible sample states</div>
- %for element_count, state in enumerate(states_list):
- <div class="form-row">
- <label>${1+element_count}. ${state.name}</label>
- ${state.desc}
- </div>
- <div style="clear: both"></div>
- %endfor
+ %for element_count, state in enumerate(states_list):
+ <div class="form-row">
+ <label>${1+element_count}. ${state.name}</label>
+ ${state.desc}
+ </div>
+ <div style="clear: both"></div>
+ %endfor
+ <div class="toolFormTitle">Sequencer information</div>
+ <div class="form-row">
+ This information is only needed for transferring data from sequencer to Galaxy
+ </div>
+ <div class="form-row">
+ <label>Hostname or IP Address:</label>
+ <input type="text" name="host" value="${request_type.datatx_info['host']}" size="40"/>
+ </div>
1
0

09 Feb '10
details: http://www.bx.psu.edu/hg/galaxy/rev/44fff02fb036
changeset: 3328:44fff02fb036
user: jeremy goecks <jeremy.goecks(a)emory.edu>
date: Thu Feb 04 10:44:36 2010 -0500
description:
Add error checking for public username. Username must have between 3 and 255 characters and be unique.
diffstat:
lib/galaxy/web/controllers/user.py | 23 +++++++++++++++++++++--
1 files changed, 21 insertions(+), 2 deletions(-)
diffs (47 lines):
diff -r 8570bf26275d -r 44fff02fb036 lib/galaxy/web/controllers/user.py
--- a/lib/galaxy/web/controllers/user.py Thu Feb 04 10:11:50 2010 -0500
+++ b/lib/galaxy/web/controllers/user.py Thu Feb 04 10:44:36 2010 -0500
@@ -327,6 +327,19 @@
elif trans.sa_session.query( trans.app.model.User ).filter_by(email=email).all():
error = "User with that email already exists"
return error
+ def __validate_username(self, trans, params, username, user=None):
+ error = None
+ if user:
+ if user.username == username:
+ return None
+ if len( username ) < 3:
+ error = "Username must be at least 3 characters long"
+ elif len( username ) > 255:
+ error = "Username cannot be more than 255 characters"
+ elif trans.sa_session.query( trans.app.model.User ).filter_by( username=username ).all():
+ error = "User with that username already exists"
+ return error
+
def __validate_password(self, trans, params, password, confirm):
error = None
if len(password) < 6:
@@ -482,8 +495,8 @@
# Editing login info (email & username)
#
if params.get('login_info_button', None) == 'Save':
- email = util.restore_text( params.get('email', '') )
- username = util.restore_text( params.get('username', '') )
+ email = util.restore_text( params.get('email', '') ).lower()
+ username = util.restore_text( params.get('username', '') ).lower()
# validate the new values
error = self.__validate_email(trans, params, email, user)
if error:
@@ -491,6 +504,12 @@
action='show_info',
msg=error,
messagetype='error') )
+ error = self.__validate_username( trans, params, username, user )
+ if error:
+ return trans.response.send_redirect( web.url_for( controller='user',
+ action='show_info',
+ msg=error,
+ messagetype='error') )
# the new email & username
user.email = email
user.username = username
1
0

09 Feb '10
details: http://www.bx.psu.edu/hg/galaxy/rev/8570bf26275d
changeset: 3327:8570bf26275d
user: jeremy goecks <jeremy.goecks(a)emory.edu>
date: Thu Feb 04 10:11:50 2010 -0500
description:
Added slug editing. Also updated/added HTML escaping on display templates.
diffstat:
lib/galaxy/web/base/controller.py | 6 ++++
lib/galaxy/web/controllers/history.py | 11 +++++++-
lib/galaxy/web/controllers/page.py | 9 ++++++
lib/galaxy/web/controllers/workflow.py | 9 ++++++
static/images/pencil.png | 0
static/scripts/galaxy.base.js | 16 ++++++++++-
templates/dataset/display.mako | 10 ++++---
templates/display_base.mako | 8 +++---
templates/display_common.mako | 2 +
templates/history/display.mako | 2 +-
templates/root/history.mako | 4 +-
templates/sharing_base.mako | 43 +++++++++++++++++++++++++++++++-
templates/workflow/display.mako | 2 +-
templates/workflow/editor.mako | 4 +-
templates/workflow/list.mako | 4 +-
15 files changed, 109 insertions(+), 21 deletions(-)
diffs (350 lines):
diff -r da557305232f -r 8570bf26275d lib/galaxy/web/base/controller.py
--- a/lib/galaxy/web/base/controller.py Thu Feb 04 09:18:17 2010 -0500
+++ b/lib/galaxy/web/base/controller.py Thu Feb 04 10:11:50 2010 -0500
@@ -204,6 +204,12 @@
return self.sharing( trans, id, **kwargs )
# Abstract methods.
+
+ @web.expose
+ @web.require_login( "modify Galaxy items" )
+ def set_slug_async( self, trans, id, new_slug ):
+ """ Set item slug asynchronously. """
+ pass
@web.expose
@web.require_login( "share Galaxy items" )
diff -r da557305232f -r 8570bf26275d lib/galaxy/web/controllers/history.py
--- a/lib/galaxy/web/controllers/history.py Thu Feb 04 09:18:17 2010 -0500
+++ b/lib/galaxy/web/controllers/history.py Thu Feb 04 10:11:50 2010 -0500
@@ -395,7 +395,16 @@
trans.sa_session.flush()
return
-
+
+ @web.expose
+ @web.require_login( "modify Galaxy items" )
+ def set_slug_async( self, trans, id, new_slug ):
+ history = self.get_history( trans, id )
+ if history:
+ history.slug = new_slug
+ trans.sa_session.flush()
+ return
+
@web.expose
def name_autocomplete_data( self, trans, q=None, limit=None, timestamp=None ):
"""Return autocomplete data for history names"""
diff -r da557305232f -r 8570bf26275d lib/galaxy/web/controllers/page.py
--- a/lib/galaxy/web/controllers/page.py Thu Feb 04 09:18:17 2010 -0500
+++ b/lib/galaxy/web/controllers/page.py Thu Feb 04 10:11:50 2010 -0500
@@ -541,6 +541,15 @@
return
@web.expose
+ @web.require_login( "modify Galaxy items" )
+ def set_slug_async( self, trans, id, new_slug ):
+ page = self.get_page( trans, id )
+ if page:
+ page.slug = new_slug
+ trans.sa_session.flush()
+ return
+
+ @web.expose
@web.json
@web.require_login( "use Galaxy pages" )
def get_name_and_link_async( self, trans, id=None ):
diff -r da557305232f -r 8570bf26275d lib/galaxy/web/controllers/workflow.py
--- a/lib/galaxy/web/controllers/workflow.py Thu Feb 04 09:18:17 2010 -0500
+++ b/lib/galaxy/web/controllers/workflow.py Thu Feb 04 10:11:50 2010 -0500
@@ -383,6 +383,15 @@
return
@web.expose
+ @web.require_login( "modify Galaxy items" )
+ def set_slug_async( self, trans, id, new_slug ):
+ stored = get_stored_workflow( trans, id )
+ if stored:
+ stored.slug = new_slug
+ trans.sa_session.flush()
+ return
+
+ @web.expose
@web.json
@web.require_login( "use Galaxy workflows" )
def get_name_and_link_async( self, trans, id=None ):
diff -r da557305232f -r 8570bf26275d static/images/pencil.png
Binary file static/images/pencil.png has changed
diff -r da557305232f -r 8570bf26275d static/scripts/galaxy.base.js
--- a/static/scripts/galaxy.base.js Thu Feb 04 09:18:17 2010 -0500
+++ b/static/scripts/galaxy.base.js Thu Feb 04 10:11:50 2010 -0500
@@ -211,7 +211,7 @@
//
// Edit and save text asynchronously.
//
-function async_save_text(click_to_edit_elt, text_elt_id, save_url, text_parm_name, use_textarea, num_rows)
+function async_save_text(click_to_edit_elt, text_elt_id, save_url, text_parm_name, use_textarea, num_rows, on_start, on_finish)
{
$("#" + click_to_edit_elt).click( function() {
var old_text = $("#" + text_elt_id).text()
@@ -236,13 +236,25 @@
$.ajax({
url: save_url,
data: ajax_data,
- error: function() { alert( "Text editing for elt " + text_elt_id + " failed" ) },
+ error: function() {
+ alert( "Text editing for elt " + text_elt_id + " failed" );
+ // TODO: call finish or no? For now, let's not because error occurred.
+ },
success: function() {
+ // Set new text and call finish method.
$("#" + text_elt_id).text( new_text );
+ if (on_finish != null)
+ on_finish(t);
}
});
}
});
+
+ // Call onstart method if it exists.
+ if (on_start != null)
+ on_start(t);
+
+ // Replace text with input object and focus & select.
$("#" + text_elt_id).hide();
t.insertAfter( $("#" + text_elt_id) );
t.focus();
diff -r da557305232f -r 8570bf26275d templates/dataset/display.mako
--- a/templates/dataset/display.mako Thu Feb 04 09:18:17 2010 -0500
+++ b/templates/dataset/display.mako Thu Feb 04 10:11:50 2010 -0500
@@ -18,7 +18,7 @@
</%def>
<%def name="title()">
- Galaxy | ${get_class_display_name( item.__class__ )} | ${get_item_name( item )}
+ Galaxy | ${get_class_display_name( item.__class__ )} | ${get_item_name( item ) | h}
</%def>
<%def name="render_item_links( data )">
@@ -43,7 +43,7 @@
<div class="unified-panel-header" unselectable="on">
<div class="unified-panel-header-inner">
${get_class_display_name( item.__class__ )}
- | ${get_item_name( item )}
+ | ${get_item_name( item ) | h}
</div>
</div>
@@ -72,11 +72,13 @@
<div style="padding: 10px;">
<h4>Author</h4>
- <p>${item.history.user.username}</p>
+ <p>${item.history.user.username | h}</p>
<div><img src="http://www.gravatar.com/avatar/${h.md5(item.history.user.email)}?s=150"></div>
- ## Page meta. No page meta for datasets for now.
+ ## Page meta.
+
+ ## No links for datasets right now.
## Tags.
<p>
diff -r da557305232f -r 8570bf26275d templates/display_base.mako
--- a/templates/display_base.mako Thu Feb 04 09:18:17 2010 -0500
+++ b/templates/display_base.mako Thu Feb 04 10:11:50 2010 -0500
@@ -13,13 +13,13 @@
<%namespace file="/display_common.mako" import="*" />
<%def name="title()">
- Galaxy | ${iff( item.published, "Published ", iff( item.importable , "Accessible ", iff( item.users_shared_with, "Shared ", "Private " ) ) ) + get_class_display_name( item.__class__ )} | ${get_item_name( item )}
+ Galaxy | ${iff( item.published, "Published ", iff( item.importable , "Accessible ", iff( item.users_shared_with, "Shared ", "Private " ) ) ) + get_class_display_name( item.__class__ )} | ${get_item_name( item ) | h}
</%def>
<%def name="init()">
<%
self.has_left_panel=False
- self.has_right_panel=item.published
+ self.has_right_panel=True
self.message_box_visible=False
self.active_view="user"
self.overlay_visible=False
@@ -152,7 +152,7 @@
<div style="padding: 10px;">
<h4>Author</h4>
- <p>${item.user.username}</p>
+ <p>${item.user.username | h}</p>
<div><img src="http://www.gravatar.com/avatar/${h.md5(item.user.email)}?s=150"></div>
@@ -162,7 +162,7 @@
<h4>Related ${item_plural}</h4>
<p>
<a href="${href_to_all_items}">All published ${item_plural.lower()}</a><br>
- <a href="${href_to_user_items}">${item_plural} owned by ${item.user.username}</a>
+ <a href="${href_to_user_items}">Published ${item_plural.lower()} by ${item.user.username | h}</a>
## Tags.
<h4>Tags</strong></h4>
diff -r da557305232f -r 8570bf26275d templates/display_common.mako
--- a/templates/display_common.mako Thu Feb 04 09:18:17 2010 -0500
+++ b/templates/display_common.mako Thu Feb 04 10:11:50 2010 -0500
@@ -1,6 +1,8 @@
##
## Utilities for sharing items and displaying shared items.
+## HACK: these should probably go in the web helper object.
##
+
<%! from galaxy import model %>
## Get display name for a class.
diff -r da557305232f -r 8570bf26275d templates/history/display.mako
--- a/templates/history/display.mako Thu Feb 04 09:18:17 2010 -0500
+++ b/templates/history/display.mako Thu Feb 04 10:11:50 2010 -0500
@@ -241,7 +241,7 @@
<%def name="render_item( history, datasets )">
<div id="history-name-area" class="historyLinks" style="color: gray; font-weight: bold; padding: 0px 0px 5px 0px">
- <div id="history-name">${history.get_display_name()}</div>
+ <div id="history-name">${history.get_display_name() | h}</div>
</div>
%if history.deleted:
diff -r da557305232f -r 8570bf26275d templates/root/history.mako
--- a/templates/root/history.mako Thu Feb 04 09:18:17 2010 -0500
+++ b/templates/root/history.mako Thu Feb 04 10:11:50 2010 -0500
@@ -276,7 +276,7 @@
<div id="history-name-area" class="historyLinks" style="color: gray; font-weight: bold;">
<div style="float: right"><a id="history-rename" title="Rename" class="icon-button edit" target="galaxy_main" href="${h.url_for( controller='history', action='rename' )}"></a></div>
- <div id="history-name">${h.escape( history.get_display_name() )}</div>
+ <div id="history-name">${history.get_display_name() | h}</div>
</div>
%if history.deleted:
@@ -311,7 +311,7 @@
<label>Annotation / Notes:</label>
<div style="float: right"><a id="history-annotate" title="Annotate" class="icon-button edit" target="galaxy_main" href="${h.url_for( controller='history', action='annotate_async' )}"></a></div>
%if annotation:
- <div id="history-annotation">${h.escape(annotation)}</div>
+ <div id="history-annotation">${annotation | h}</div>
%else:
<div id="history-annotation"></div>
%endif
diff -r da557305232f -r 8570bf26275d templates/sharing_base.mako
--- a/templates/sharing_base.mako Thu Feb 04 09:18:17 2010 -0500
+++ b/templates/sharing_base.mako Thu Feb 04 10:11:50 2010 -0500
@@ -15,6 +15,40 @@
Sharing and Publishing ${get_class_display_name( item.__class__ )} '${get_item_name( item )}'
</%def>
+<%def name="javascripts()">
+ ${parent.javascripts()}
+ <script type="text/javascript">
+ $(document).ready( function()
+ {
+ //
+ // Set up slug-editing functionality.
+ //
+ var on_start = function( text_elt )
+ {
+ // Because text element is inside a URL, need to disable click so that clicking on element does not trigger URL.
+ $( text_elt ).click( function() {
+ return false;
+ });
+
+ // Allow only lowercase alphanumeric and '-' characters in slug.
+ text_elt.keyup(function(){
+ text_elt.val( $(this).val().replace(/\s+/g,'-').replace(/[^a-zA-Z0-9\-]/g,'').toLowerCase() )
+ });
+ };
+
+ var on_finish = function( text_elt )
+ {
+ // Set URL to new value.
+ var item_url_obj = $('#item-url');
+ item_url_obj.attr( "href", item_url_obj.text() );
+ };
+
+ <% controller_name = get_controller_name( item ) %>
+ async_save_text("edit-identifier", "item-identifier", "${h.url_for( controller=controller_name, action='set_slug_async', id=trans.security.encode_id( item.id ) )}", "new_slug", false, 0, on_start, on_finish);
+ });
+ </script>
+</%def>
+
<%def name="stylesheets()">
${parent.stylesheets()}
<style>
@@ -77,9 +111,14 @@
This ${item_class_name_lc} <strong>${item_status}</strong>.
<div>
<p>Anyone can view and import this ${item_class_name_lc} by visiting the following URL:
- <% url = h.url_for( action='display_by_username_and_slug', username=trans.get_user().username, slug=item.slug, qualified=True ) %>
+
<blockquote>
- <a href="${url}" target="_top">${url}</a>
+ <%
+ url = h.url_for( action='display_by_username_and_slug', username=trans.get_user().username, slug=item.slug, qualified=True )
+ url_parts = url.split("/")
+ %>
+ <a id="item-url" href="${url}" target="_top">${"/".join( url_parts[:-1] )}/<span id='item-identifier'>${url_parts[-1]}</span></a>
+ <a href="#" id="edit-identifier"><img src="${h.url_for('/static/images/pencil.png')}"/></a>
</blockquote>
%if item.published:
diff -r da557305232f -r 8570bf26275d templates/workflow/display.mako
--- a/templates/workflow/display.mako Thu Feb 04 09:18:17 2010 -0500
+++ b/templates/workflow/display.mako Thu Feb 04 10:11:50 2010 -0500
@@ -78,7 +78,7 @@
</%def>
<%def name="render_item( workflow, steps )">
- <h2>${workflow.name}</h2>
+ <h2>${workflow.name | h}</h2>
%for i, step in enumerate( steps ):
%if step.type == 'tool' or step.type is None:
<% tool = app.toolbox.tools_by_id[step.tool_id] %>
diff -r da557305232f -r 8570bf26275d templates/workflow/editor.mako
--- a/templates/workflow/editor.mako Thu Feb 04 09:18:17 2010 -0500
+++ b/templates/workflow/editor.mako Thu Feb 04 10:11:50 2010 -0500
@@ -784,7 +784,7 @@
<div id="workflow-name-area" class="form-row">
<label>Name:</label>
<div style="float: right"><a id="workflow-rename" title="Rename" class="icon-button edit" target="galaxy_main" href="${h.url_for( controller='workflow', action='rename_sync' )}"></a></div>
- <div id="workflow-name">${h.escape( stored.name )}</div>
+ <div id="workflow-name">${stored.name | h}</div>
<div style="clear: both"></div>
</div>
## Workflow tags.
@@ -809,7 +809,7 @@
<div id="workflow-annotation-area" class="form-row">
<label>Annotation / Notes:</label>
<div style="float: right"><a id="workflow-annotate" title="Annotate" class="icon-button edit" target="galaxy_main" href="${h.url_for( controller='workflow', action='annotate_async' )}"></a></div>
- <div id="workflow-annotation">${h.escape( annotation )}</div>
+ <div id="workflow-annotation">${annotation | h}</div>
<div style="clear: both"></div>
<div class="toolParamHelp">Add an annotation or notes to a workflow; annotations are available when a workflow is viewed.</div>
</div>
diff -r da557305232f -r 8570bf26275d templates/workflow/list.mako
--- a/templates/workflow/list.mako Thu Feb 04 09:18:17 2010 -0500
+++ b/templates/workflow/list.mako Thu Feb 04 10:11:50 2010 -0500
@@ -38,7 +38,7 @@
<tr>
<td>
<div class="menubutton" style="float: left;" id="wf-${i}-popup">
- ${workflow.name}
+ ${workflow.name | h}
</div>
</td>
<td>${len(workflow.latest_workflow.steps)}</td>
@@ -76,7 +76,7 @@
<% workflow = association.stored_workflow %>
<tr>
<td>
- <a class="menubutton" id="shared-${i}-popup" href="${h.url_for( action='run', id=trans.security.encode_id(workflow.id) )}">${workflow.name}</a>
+ <a class="menubutton" id="shared-${i}-popup" href="${h.url_for( action='run', id=trans.security.encode_id(workflow.id) )}">${workflow.name | h}</a>
</td>
<td>${workflow.user.email}</td>
<td>${len(workflow.latest_workflow.steps)}</td>
1
0

09 Feb '10
details: http://www.bx.psu.edu/hg/galaxy/rev/da557305232f
changeset: 3326:da557305232f
user: Greg Von Kuster <greg(a)bx.psu.edu>
date: Thu Feb 04 09:18:17 2010 -0500
description:
Miscellaneous code cleanup: clean up old code in form_builder, adding important comments for the CheckboxField class; make the functional test diff checker for PDF files more flexible; allow tab chars to be mapped so they can be properly stored in the db.
diffstat:
lib/galaxy/util/__init__.py | 3 ++-
lib/galaxy/web/form_builder.py | 36 ++++++++++++++++++++----------------
test/base/twilltestcase.py | 42 ++++++++++++++++++++++++++++--------------
3 files changed, 50 insertions(+), 31 deletions(-)
diffs (134 lines):
diff -r a213a1d8ac03 -r da557305232f lib/galaxy/util/__init__.py
--- a/lib/galaxy/util/__init__.py Wed Feb 03 19:44:01 2010 -0500
+++ b/lib/galaxy/util/__init__.py Thu Feb 04 09:18:17 2010 -0500
@@ -122,7 +122,8 @@
'}' :'__cc__',
'@' : '__at__',
'\n' : '__cn__',
- '\r' : '__cr__'
+ '\r' : '__cr__',
+ '\t' : '__tc__'
}
def restore_text(text):
diff -r a213a1d8ac03 -r da557305232f lib/galaxy/web/form_builder.py
--- a/lib/galaxy/web/form_builder.py Wed Feb 03 19:44:01 2010 -0500
+++ b/lib/galaxy/web/form_builder.py Thu Feb 04 09:18:17 2010 -0500
@@ -88,7 +88,7 @@
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) )
+ % ( prefix, self.name, self.rows, self.cols, escape( str( self.value ), quote=True ) )
def set_size(self, rows, cols):
self.rows = rows
self.cols = cols
@@ -104,27 +104,31 @@
"""
def __init__( self, name, checked=None ):
self.name = name
- self.checked = ( checked == True ) or ( type( checked ) == type( 'a' ) and ( checked.lower() in ( "yes", "true", "on" ) ) )
+ self.checked = ( checked == True ) or ( isinstance( checked, basestring ) and ( checked.lower() in ( "yes", "true", "on" ) ) )
def get_html( self, prefix="" ):
if self.checked:
checked_text = "checked"
- else: checked_text = ""
+ else:
+ checked_text = ""
+ # The hidden field is necessary because if the check box is not checked on the form, it will
+ # not be included in the request params. The hidden field ensure that this will happen. When
+ # 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 )
@staticmethod
def is_checked( value ):
- if value == True: # wierd behaviour caused by following check for 2 valued list - wtf? ross august 22
- return value
- if type( value ) == list and len( value ) == 2:
- return True
- else:
- return False
+ if value == True:
+ return value
+ # This may look strange upon initial inspection, but see the comments in the get_html() method
+ # above for clarification. Basically, if value is not True, then it will always be a list with
+ # 2 input fields ( a checkbox and a hidden field ) if the checkbox is checked. If it is not
+ # checked, then value will be only the hidden field.
+ return isinstance( value, list ) and len( value ) == 2
def set_checked(self, value):
- if type(value) == type('a'):
- if value.lower() in [ "yes", "true", "on" ]:
- self.checked = True
- else:
- self.checked = False
+ if isinstance( value, basestring ):
+ self.checked = value.lower() in [ "yes", "true", "on" ]
else:
self.checked = value
@@ -335,8 +339,8 @@
self.name = name
self.multiple = multiple or False
self.options = options
- if value is not None:
- if not isinstance( value, list ): value = [ value ]
+ if value and not isinstance( value, list ):
+ value = [ value ]
else:
value = []
self.value = value
diff -r a213a1d8ac03 -r da557305232f test/base/twilltestcase.py
--- a/test/base/twilltestcase.py Wed Feb 03 19:44:01 2010 -0500
+++ b/test/base/twilltestcase.py Thu Feb 04 09:18:17 2010 -0500
@@ -53,21 +53,35 @@
files_differ = True
if files_differ:
diff = difflib.unified_diff( local_file, history_data, "local_file", "history_data" )
- diff_slice = list( islice( diff, 40 ) )
+ diff_slice = list( islice( diff, 40 ) )
if file1.endswith( '.pdf' ) or file2.endswith( '.pdf' ):
- # PDF files contain both a creation and modification date, so we need to
- # handle these differences. As long as the rest of the PDF file does not differ,
- # we're ok.
- if len( diff_slice ) == 13 and \
- diff_slice[6].startswith( '-/CreationDate' ) and diff_slice[7].startswith( '-/ModDate' ) \
- and diff_slice[8].startswith( '+/CreationDate' ) and diff_slice[9].startswith( '+/ModDate' ):
- return True
- for line in diff_slice:
- for char in line:
- if ord( char ) > 128:
- raise AssertionError( "Binary data detected, not displaying diff" )
- raise AssertionError( "".join( diff_slice ) )
- return True
+ # PDF files contain creation dates, modification dates, ids and descriptions that change with each
+ # new file, so we need to handle these differences. As long as the rest of the PDF file does
+ # not differ we're ok.
+ valid_diff_strs = [ 'description', 'createdate', 'creationdate', 'moddate', 'id' ]
+ valid_diff = False
+ for line in diff_slice:
+ # Make sure to lower case strings before checking.
+ line = line.lower()
+ # Diff lines will always start with a + or - character, but handle special cases: '--- local_file \n', '+++ history_data \n'
+ if ( line.startswith( '+' ) or line.startswith( '-' ) ) and line.find( 'local_file' ) < 0 and line.find( 'history_data' ) < 0:
+ for vdf in valid_diff_strs:
+ if line.find( vdf ) < 0:
+ valid_diff = False
+ else:
+ valid_diff = True
+ # Stop checking as soon as we know we have a valid difference
+ break
+ if not valid_diff:
+ # Print out diff_slice so we can see what failed
+ print "###### diff_slice ######"
+ raise AssertionError( "".join( diff_slice ) )
+ break
+ else:
+ for line in diff_slice:
+ for char in line:
+ if ord( char ) > 128:
+ raise AssertionError( "Binary data detected, not displaying diff" )
def get_filename( self, filename ):
full = os.path.join( self.file_dir, filename)
1
0