diff --git a/lib/galaxy/datatypes/images.py b/lib/galaxy/datatypes/images.py index 2d45aefce1a..f4b01f8d59b 100644 --- a/lib/galaxy/datatypes/images.py +++ b/lib/galaxy/datatypes/images.py @@ -252,14 +252,17 @@ class Bam( data.Binary ): index_file = dataset.metadata.spec['bam_index'].param.new_file( dataset = dataset ) tmp_dir = tempfile.gettempdir() tmpf1 = tempfile.NamedTemporaryFile(dir=tmp_dir) + tmpf1bai = '%s.bai' % tmpf1.name try: subprocess.check_call(['cd', tmp_dir], shell=True) subprocess.check_call('cp %s %s' % (dataset.file_name, tmpf1.name), shell=True) subprocess.check_call('samtools index %s' % tmpf1.name, shell=True) - subprocess.check_call('cp %s.bai %s' % (tmpf1.name, index_file.file_name), shell=True) + subprocess.check_call('cp %s %s' % (tmpf1bai, index_file.file_name), shell=True) except subprocess.CalledProcessError: sys.stderr.write('There was a problem creating the index for the BAM file\n') tmpf1.close() + if os.path.exists(tmpf1bai): + os.remove(tmpf1bai) dataset.metadata.bam_index = index_file def set_peek( self, dataset ): if not dataset.dataset.purged: diff --git a/tool-data/sam_fa_indices.loc.sample b/tool-data/sam_fa_indices.loc.sample new file mode 100644 index 00000000000..245a6c8b051 --- /dev/null +++ b/tool-data/sam_fa_indices.loc.sample @@ -0,0 +1,27 @@ +#This is a sample file distributed with Galaxy that enables tools +#to use a directory of Samtools indexed sequences data files. You will need +#to create these data files and then create a sam_fa_indices.loc file +#similar to this one (store it in this directory ) that points to +#the directories in which those files are stored. The sam_fa_indices.loc +#file has this format (white space characters are TAB characters): +# +# +# +#So, for example, if you had hg18 indexed stored in +#/depot/data2/galaxy/sam/, +#then the sam_fa_indices.loc entry would look like this: +# +#hg18 /depot/data2/galaxy/sam/hg18.fa +# +#and your /depot/data2/galaxy/sam/ directory +#would contain hg18.fa and hg18.fa.fai files: +# +#-rw-r--r-- 1 james universe 830134 2005-09-13 10:12 hg18.fa +#-rw-r--r-- 1 james universe 527388 2005-09-13 10:12 hg18.fa.fai +# +#Your sam_fa_indices.loc file should include an entry per line for +#each index set you have stored. The file in the path does actually +#exist, but it should never be directly used. Instead, the name serves +#as a prefix for the index file. For example: +# +#hg18 /depot/data2/galaxy/sam/hg18.fa diff --git a/tool_conf.xml.sample b/tool_conf.xml.sample index ce0e35ab935..9ea1f52ebef 100644 --- a/tool_conf.xml.sample +++ b/tool_conf.xml.sample @@ -331,9 +331,13 @@ -
+
+ + + +
diff --git a/tools/samtools/sam_merge.py b/tools/samtools/sam_merge.py new file mode 100644 index 00000000000..6f6c7db926c --- /dev/null +++ b/tools/samtools/sam_merge.py @@ -0,0 +1,21 @@ +#! /usr/bin/python + +import os, sys + +def stop_err( msg ): + sys.stderr.write( msg ) + sys.exit() + +def __main__(): + infile = sys.argv[1] + outfile = sys.argv[2] + if len( sys.argv ) < 3: + stop_err( 'No files to merge' ) + filenames = sys.argv[3:] + cmd1 = 'samtools merge %s %s %s' % (outfile, infile, ' '.join(filenames)) + try: + os.system(cmd1) + except Exception, eq: + stop_err('Error running SAMtools merge tool\n' + str(eq)) + +if __name__ == "__main__" : __main__() \ No newline at end of file diff --git a/tools/samtools/sam_merge.xml b/tools/samtools/sam_merge.xml new file mode 100644 index 00000000000..621ef0e6641 --- /dev/null +++ b/tools/samtools/sam_merge.xml @@ -0,0 +1,32 @@ + + merges BAM files together + + sam_merge.py + $input1 + $output1 + $input2 + #for $i in $inputs + ${i.input} + #end for + + + + + + + + + + + + + + +**What it does** + +This tool uses SAMTools_' merge command to merge any number of BAM files together into one BAM file. + +.. _SAMTools: http://samtools.sourceforge.net/samtools.shtml + + + diff --git a/tools/samtools/sam_merge_code.py b/tools/samtools/sam_merge_code.py new file mode 100644 index 00000000000..70ce29f2bb2 --- /dev/null +++ b/tools/samtools/sam_merge_code.py @@ -0,0 +1,35 @@ +import sets +from galaxy.tools.parameters import DataToolParameter + +def validate_input( trans, error_map, param_values, page_param_map ): + dbkeys = sets.Set() + data_param_names = sets.Set() + data_params = 0 + for name, param in page_param_map.iteritems(): + if isinstance( param, DataToolParameter ): + # for each dataset parameter + if param_values.get(name, None) != None: + dbkeys.add( param_values[name].dbkey ) + data_params += 1 + # check meta data +# try: +# param = param_values[name] +# startCol = int( param.metadata.startCol ) +# endCol = int( param.metadata.endCol ) +# chromCol = int( param.metadata.chromCol ) +# if param.metadata.strandCol is not None: +# strandCol = int ( param.metadata.strandCol ) +# else: +# strandCol = 0 +# except: +# error_msg = "The attributes of this dataset are not properly set. " + \ +# "Click the pencil icon in the history item to set the chrom, start, end and strand columns." +# error_map[name] = error_msg + data_param_names.add( name ) + if len( dbkeys ) > 1: + for name in data_param_names: + error_map[name] = "All datasets must belong to same genomic build, " \ + "this dataset is linked to build '%s'" % param_values[name].dbkey + if data_params != len(data_param_names): + for name in data_param_names: + error_map[name] = "A dataset of the appropriate type is required" \ No newline at end of file diff --git a/tools/samtools/sam_pileup.py b/tools/samtools/sam_pileup.py new file mode 100644 index 00000000000..f84bd90d6e5 --- /dev/null +++ b/tools/samtools/sam_pileup.py @@ -0,0 +1,89 @@ +#! /usr/bin/python + +""" +Creates a pileup file from a bam file and a reference. + +usage: %prog [options] + -i, --input1=i: bam file + -o, --output1=o: Output pileup + -r, --ref=r: Reference file type + -n, --ownFile=n: User-supplied fasta reference file + -d, --dbkey=d: dbkey of user-supplied file + -x, --indexDir=x: Index directory + -b, --bamIndex=b: BAM index file + +usage: %prog input1 output1 ref_type refFile ownFile dbkey index_dir bam_index +""" + +import os, sys, tempfile +from galaxy import eggs +import pkg_resources; pkg_resources.require( "bx-python" ) +from bx.cookbook import doc_optparse + +def stop_err( msg ): + sys.stderr.write( msg ) + sys.exit() + +def check_seq_file( dbkey, GALAXY_DATA_INDEX_DIR ): + seq_file = "%s/sam_fa_indices.loc" % GALAXY_DATA_INDEX_DIR + seq_path = '' + for line in open( seq_file ): + line = line.rstrip( '\r\n' ) + if line and not line.startswith( "#" ) and line.startswith( 'index' ): + fields = line.split( '\t' ) + if len( fields ) < 3: + continue + if fields[1] == dbkey: + seq_path = fields[2].strip() + break + return seq_path + +def __main__(): + #Parse Command Line + options, args = doc_optparse.parse( __doc__ ) + seq_path = check_seq_file( options.dbkey, options.indexDir ) + tmp_dir = tempfile.gettempdir() + os.chdir(tmp_dir) + tmpf0 = tempfile.NamedTemporaryFile(dir=tmp_dir) + tmpf0bam = '%s.bam' % tmpf0.name + tmpf0bambai = '%s.bam.bai' % tmpf0.name + tmpf1 = tempfile.NamedTemporaryFile(dir=tmp_dir) + tmpf1fai = '%s.fai' % tmpf1.name + cmd1 = None + cmd2 = 'cp %s %s; cp %s %s' % (options.input1, tmpf0bam, options.bamIndex, tmpf0bambai) + cmd3 = 'samtools pileup -f %s %s > %s 2> /dev/null' + if options.ref =='indexed': + full_path = "%s.fai" % seq_path + if not os.path.exists( full_path ): + stop_err( "No sequences are available for '%s', request them by reporting this error." % options.dbkey ) + cmd3 = cmd3 % (seq_path, tmpf0bam, options.output1) + elif options.ref == 'history': + cmd1 = 'cp %s %s; cp %s.fai %s' % (options.ownFile, tmpf1.name, options.ownFile, tmpf1fai) + cmd3 = cmd3 % (tmpf1.name, tmpf0bam, options.output1) + # index reference if necessary + if cmd1: + try: + os.system(cmd1) + except Exception, eq: + stop_err('Error moving reference sequence\n' + str(eq)) + # copy bam index to working directory + try: + os.system(cmd2) + except Exception, eq: + stop_err('Error moving files to temp directory\n' + str(eq)) + # perform pileup command + try: + os.system(cmd3) + except Exception, eq: + stop_err('Error running SAMtools merge tool\n' + str(eq)) + # clean up temp files + tmpf1.close() + tmpf0.close() + if os.path.exists(tmpf0bam): + os.remove(tmpf0bam) + if os.path.exists(tmpf0bambai): + os.remove(tmpf0bambai) + if os.path.exists(tmpf1fai): + os.remove(tmpf0bambai) + +if __name__ == "__main__" : __main__() diff --git a/tools/samtools/sam_pileup.xml b/tools/samtools/sam_pileup.xml new file mode 100644 index 00000000000..4054d1f1d56 --- /dev/null +++ b/tools/samtools/sam_pileup.xml @@ -0,0 +1,50 @@ + + generates the pileup format for a provided BAM file + + sam_pileup.py + --input1=$input1 + --output=$output1 + --ref=$refOrHistory.reference + #if $refOrHistory.reference == "history": + --ownFile=$refOrHistory.ownFile + #else: + --ownFile="None" + #end if + --dbkey=${input1.metadata.dbkey} + --indexDir=${GALAXY_DATA_INDEX_DIR} + --bamIndex=${input1.metadata.bam_index} + + + + + + + + + + + + + + + + + + + + + + + + + +**What it does** + +Uses SAMTools_' pileup command to produce a file in the pileup format based on the provided BAM file. + +.. _SAMTools: http://samtools.sourceforge.net/samtools.shtml + + + + + diff --git a/tools/samtools/sam_to_bam.py b/tools/samtools/sam_to_bam.py new file mode 100644 index 00000000000..7f7458282ce --- /dev/null +++ b/tools/samtools/sam_to_bam.py @@ -0,0 +1,85 @@ +#! /usr/bin/python + +""" +Converts SAM data to BAM format. + +usage: %prog [options] + -i, --input1=i: SAM file to be converted + -d, --dbkey=d: dbkey value + -r, --ref_file=r: Reference file if choosing from history + -o, --output1=o: BAM output + -x, --index_dir=x: Index directory + +usage: %prog input_file dbkey ref_list output_file +""" + +import os, sys, tempfile +from galaxy import eggs +import pkg_resources; pkg_resources.require( "bx-python" ) +from bx.cookbook import doc_optparse + +def stop_err( msg ): + sys.stderr.write( "%s\n" % msg ) + sys.exit() + +def check_seq_file( dbkey, GALAXY_DATA_INDEX_DIR ): + seq_file = "%s/sam_fa_indices.loc" % GALAXY_DATA_INDEX_DIR + seq_path = '' + for line in open( seq_file ): + line = line.rstrip( '\r\n' ) + if line and not line.startswith( "#" ) and line.startswith( 'index' ): + fields = line.split( '\t' ) + if len( fields ) < 3: + continue + if fields[1] == dbkey: + seq_path = fields[2].strip() + break + return seq_path + +def __main__(): + #Parse Command Line + options, args = doc_optparse.parse( __doc__ ) + seq_path = check_seq_file( options.dbkey, options.index_dir ) + tmp_dir = tempfile.gettempdir() + os.chdir(tmp_dir) + tmpf1 = tempfile.NamedTemporaryFile(dir=tmp_dir) + tmpf1fai = '%s.fai' % tmpf1.name + tmpf2 = tempfile.NamedTemporaryFile(dir=tmp_dir) + tmpf3 = tempfile.NamedTemporaryFile(dir=tmp_dir) + tmpf3bam = '%s.bam' % tmpf3.name + if options.ref_file == "None": + full_path = "%s.fai" % seq_path + if not os.path.exists( full_path ): + stop_err( "No sequences are available for '%s', request them by reporting this error." % options.dbkey ) + cmd1 = "cp %s %s; cp %s %s" % (seq_path, tmpf1.name, full_path, tmpf1fai) + else: + cmd1 = "cp %s %s; samtools faidx %s 2>/dev/null" % (options.ref_file, tmpf1.name, tmpf1.name) + cmd2 = "samtools view -bt %s -o %s %s 2>/dev/null" % (tmpf1fai, tmpf2.name, options.input1) + cmd3 = "samtools sort %s %s 2>/dev/null" % (tmpf2.name, tmpf3.name) + cmd4 = "cp %s %s" % (tmpf3bam, options.output1) + # either create index based on fa file or copy provided index to temp directory + try: + os.system(cmd1) + except Exception, eq: + stop_err("Error creating the reference list index.\n" + str(eq)) + # create original bam file + try: + os.system(cmd2) + except Exception, eq: + stop_err("Error running view command.\n" + str(eq)) + # sort original bam file to produce sorted output bam file + try: + os.system(cmd3) + os.system(cmd4) + except Exception, eq: + stop_err("Error sorting data and creating output file.\n" + str(eq)) + # cleanup temp files + tmpf1.close() + tmpf2.close() + tmpf3.close() + if os.path.exists(tmpf1fai): + os.remove(tmpf1fai) + if os.path.exists(tmpf3bam): + os.remove(tmpf3bam) + +if __name__=="__main__": __main__() diff --git a/tools/samtools/sam_to_bam.xml b/tools/samtools/sam_to_bam.xml new file mode 100644 index 00000000000..e3f7186496b --- /dev/null +++ b/tools/samtools/sam_to_bam.xml @@ -0,0 +1,59 @@ + + converts SAM format to BAM format + + sam_to_bam.py + --input1=$source.input1 + --dbkey=${input1.metadata.dbkey} + #if $source.indexSource == "history": + --ref_file=$ref_file + #else + --ref_file="None" + #end if + --output1=$output1 + --index_dir=${GALAXY_DATA_INDEX_DIR} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +**What it does** + +This tool uses the SAMTools_ toolkit to produce a BAM file based on a sorted input SAM file. + +.. _SAMTools: http://samtools.sourceforge.net/samtools.shtml + + +