add a short read tool for showing histogram of lengths of high quality scores.

remove the old histogram tool, same function can be done by other galaxy tools.
This commit is contained in:
Wen-Yu Chung
2008-03-25 22:35:26 +00:00
parent 5ba3755ad6
commit 35a07c8b43
4 changed files with 247 additions and 274 deletions
@@ -0,0 +1,188 @@
#! /usr/bin/python
import os, sys, math, tempfile, zipfile, re
from rpy import *
def stop_err(msg):
sys.stderr.write(msg)
sys.stderr.write("\n")
sys.exit()
def unzip(zip_file):
zip_inst = zipfile.ZipFile(zip_file, 'r')
tmpfilename = tempfile.NamedTemporaryFile().name
for name in zip_inst.namelist():
file(tmpfilename,'a').write(zip_inst.read(name))
zip_inst.close()
return tmpfilename
def __main__():
# I/O
infile_score_name = sys.argv[1].strip()
outfile_R_name = sys.argv[2].strip()
try:
score_threshold = int(sys.argv[3].strip())
except:
stop_err('Please enter a threshold for quality score.')
# unzip infile
if (zipfile.is_zipfile(infile_score_name)):
unzip_infile = unzip(infile_score_name)
else: unzip_infile = infile_score_name
# detect whether it's tabular or fasta format
seq_method = None
score_file = unzip_infile
test_fh = open(score_file,'r')
while seq_method is None:
read_scorefile = test_fh.readline()
if read_scorefile.startswith('#'):
continue
if not read_scorefile:
continue
elif read_scorefile.startswith(">"):
read_next_line = test_fh.readline()
fields = read_next_line.split()
for score in fields:
try:
x = int(score)
seq_method = '454'
except:
seq_method = 'Failed'
break
elif len(read_scorefile.split('\t')) > 0:
fields = read_scorefile.split()
for score in fields:
try:
x = int(score)
seq_method = 'solexa'
except:
seq_method = 'Failed'
break
else:
stop_err('Your input file format does not fit the requirement. Please use either fasta format or tabular format')
if seq_method == 'Failed':
stop_err('Unable to determine the file format. Please use either fasta-like format (except title lines, the file contains only numeric values) or tabular format')
test_fh.close()
# R
cont_high_quality = []
invalid_lines = 0
invalid_scores = 0
if (seq_method == 'solexa'):
for i, line in enumerate(open(score_file)):
line = line.rstrip('\r\n')
if line.startswith('#'):
continue
if not line:
continue
try:
each_loc = line.split('\t')
except:
invalid_lines += 1
continue
for j, each_base in enumerate(each_loc):
each_nuc_error = each_base.split()
try:
each_nuc_error[0] = int(each_nuc_error[0])
each_nuc_error[1] = int(each_nuc_error[1])
each_nuc_error[2] = int(each_nuc_error[2])
each_nuc_error[3] = int(each_nuc_error[3])
big = max(each_nuc_error)
except:
invalid_scores += 1
big = 0
if j == 0:
cont_high_quality.append(1)
else:
if big >= score_threshold:
cont_high_quality[len(cont_high_quality)-1] += 1
else:
cont_high_quality.append(1)
else:
tmp_score = ''
for i, line in enumerate(open(score_file)):
if line.startswith('#'):
continue
if not line:
continue
if line.startswith('>'):
if len(tmp_score) > 0:
each_loc = tmp_score.split()
for j, each_base in enumerate(each_loc):
try:
each_base = int(each_base)
except:
invalid_scores += 1
each_base = 0
if j == 0:
cont_high_quality.append(1)
else:
if each_base >= score_threshold:
cont_high_quality[len(cont_high_quality)-1] += 1
else:
cont_high_quality.append(1)
tmp_score = ''
else:
tmp_score = tmp_score + ' ' + line
if len(tmp_score) > 0:
each_loc = tmp_score.split()
for j, each_base in enumerate(each_loc):
try:
each_base = int(each_base)
except:
invalid_scores += 1
each_base = 0
if j == 0:
cont_high_quality.append(1)
else:
if each_base >= score_threshold:
cont_high_quality[len(cont_high_quality)-1] += 1
else:
cont_high_quality.append(1)
# throw messages of invalid values
if invalid_lines > 0:
print >> sys.stdout, 'Skipped %d lines due to invalid format' %(invalid_lines)
if invalid_scores > 0:
print >> sys.stdout, 'Skipped %d scores due to invalid values' %(invalid_scores)
# generate pdf figures
cont_high_quality = array (cont_high_quality)
outfile_R_pdf = outfile_R_name
r.pdf(outfile_R_pdf)
title = "histogram of continueous high quality scores"
xlim_range = [1,max(cont_high_quality)]
nclass = max(cont_high_quality)
if nclass > 100: nclass = 100
r.hist(cont_high_quality,probability=True, xlab="Continueous High Quality Score length (bp)", ylab="Frequency (%)", xlim=xlim_range, main=title, nclass=nclass)
if zipfile.is_zipfile(infile_score_name) and os.path.exists(unzip_infile):
os.remove(unzip_infile)
r.dev_off()
r.quit(save = "no")
if __name__=="__main__":__main__()
@@ -0,0 +1,59 @@
<tool id="hist_high_quality_score" name="Histogram">
<description> of high quality score reads </description>
<command interpreter="python">short_reads_figure_high_quality_length.py $input1 $output1 $input2</command>
<inputs>
<page>
<param name="input1" type="data" format="qualityscore,txtseq.zip" label="Sequence file" />
<param name="input2" type="integer" size="5" value="20" label="Quality Score Threshold" />
</page>
</inputs>
<outputs>
<data name="output1" format="pdf" />
</outputs>
<help>
.. class:: warningmark
**TIP**. To use this tool your dataset needs to be in *Quality Score* format. Click pencil icon next to your dataset to set datatype to *Quality Score*.
-----
**What it does**
This tool takes Quality Files generated by Roche (454), Illumina (Solexa), or ABI SOLiD machines and builds a histogram of lengths of high quality reads.
-----
**Examples of Quality Data**
Roche (454) or ABI SOLiD data::
&gt;seq1
23 33 34 25 28 28 28 32 23 34 27 4 28 28 31 21 28
Illumina (Solexa) data::
-40 -40 40 -40 -40 -40 -40 40
-----
**Note**
- Quality score data::
&gt;seq1
23 33 34 25 28 28 28 32 23 34 27 4 28 28 31 21 28
- If the threshold was set to 20::
lengths of continuous quality scores that are higher than 20 is 11, 5 (a low quality score 4 in the middle)
The histogram will be built based on the numbers (11, 5).
- For Illumina (Solexa) data, only the maximal of 4 values will be considered.
</help>
</tool>
@@ -1,206 +0,0 @@
#! /usr/bin/python
"""
Galaxy
Input:
sequence file(s): zip or text file --> for 454 and Solexa
Output:
an array of lengths of the reads
----
Wen-Yu Chung
"""
import os, sys, math, tempfile, zipfile, re
from rpy import *
# default and initialize values
number_of_points = 20
read_seqfile = []
read_scorefile = []
title_keys = []
seq_hash = {}
score_hash = {}
trim_seq_hash = {}
tmp_seq = ''
tmp_score = [] # change variables here
length_before_trim = []
length_after_trim = []
score_points = []
database_tmp = "/tmp/" # default dir: current directory
if (not os.path.isdir(database_tmp)):
os.mkdir(database_tmp)
# functions
def stop_err(msg):
sys.stderr.write(msg)
sys.stderr.write("\n")
sys.exit()
def read_input_files(file_list):
read_file = []
for file_name in file_list:
infile = open(file_name,'r')
read_file = infile.readlines()
infile.close()
return read_file
def unzip_files(file_name):
read_file = []
temp_dir_name = tempfile.mkdtemp() + '/' #dir=database_tmp
temp_new_dest = temp_dir_name + file_name.split('/')[-1]
command_line = 'cp ' + file_name + ' ' + temp_dir_name + '\nunzip ' + temp_new_dest + ' -d ' + temp_dir_name
os.system(command_line)
os.remove(temp_new_dest)
dest = os.listdir(temp_dir_name)
if ((len(dest) == 1) and (os.path.isdir(dest[0]))):
new_file_dir = temp_dir_name + dest[0] + '/'
dest = os.listdir(new_file_dir)
else:
new_file_dir = temp_dir_name
for filex in dest:
filex = new_file_dir + filex
read_file.append(filex)
return new_file_dir, read_file
def parse_solexa_files(result, type):
# parse solexa seq and probability files only
# not fasta format
# assign numeric id
tmp_hash = {}
tmp_title = ''
tmp_seq = ''
tmp_id = 0
if (type == 'seq'):
for each_line in result:
tmp_seq = ''
each_line.strip('\r\n')
tmp_id += 1
fasta_id = '>' + str(tmp_id)
(run_id, file_id, read_x, read_y, read) = each_line.split()
tmp_hash[(fasta_id)] = read
else: # type == score
for each_line in result:
tmp_seq = []
each_line.strip('\r\n')
tmp_id += 1
fasta_id = '>' + str(tmp_id)
each_loc = each_line.split('\t')
for each_base in each_loc:
each_nuc_error = each_base.split()
each_nuc_error[0] = int(each_nuc_error[0])
each_nuc_error[1] = int(each_nuc_error[1])
each_nuc_error[2] = int(each_nuc_error[2])
each_nuc_error[3] = int(each_nuc_error[3])
big = max(each_nuc_error)
#baseIndex = each_nuc_error.index(big)
tmp_seq.append(big)
tmp_hash[(fasta_id)] = tmp_seq
return tmp_hash
def parse_fasta_format(result):
# detect whether it's score or seq files
# return a hash: key = title and value = seq
tmp_hash = {}
tmp_title = ''
tmp_seq = ''
for each_line in result:
each_line = each_line.strip('\r\n')
if (each_line[0] == '>'):
if (len(tmp_seq) > 0):
tmp_hash[(tmp_title)] = tmp_seq
tmp_title = each_line
tmp_seq = ''
else:
tmp_seq = tmp_seq + each_line
if (each_line.split()[0].isdigit()):
tmp_seq = tmp_seq + ' '
if (len(tmp_seq) > 0):
tmp_hash[(tmp_title)] = tmp_seq
return tmp_hash
def generate_hist_figure():
# R module and code
tmp_array = []
# data for R hist
# write the length only!
outfile = open(outfile_R_name,'w')
title_keys = seq_hash.keys()
i = 0
for read_title in title_keys:
i += 1
tmp_seq = seq_hash[(read_title)]
length_before_trim.append(len(tmp_seq))
print >> outfile,"%d\t%d" %(i, len(tmp_seq))
outfile.close()
max_length_before_trim = max(length_before_trim)
# generate pdf figures
"""
outfile_R_pdf = outfile_R_name
r.pdf(outfile_R_pdf)
title = infile_seq_name.split('/')[-1]
xlim_range = [1,max_length_before_trim]
r.hist(length_before_trim,prob=1, xlab="Read length (bp)", ylab="Frequency (%)", xlim=xlim_range, main=title, nclass=100)
r.dev_off()
"""
return 0
# I/O
infile_seq_name = sys.argv[1].strip()
outfile_R_name = sys.argv[2].strip()
# to unzip or not unzip file
tmp_seq_dir = ''
seq_file_list = []
if (zipfile.is_zipfile(infile_seq_name)): (tmp_seq_dir, seq_file_list) = unzip_files(infile_seq_name)
else: seq_file_list = [infile_seq_name]
read_seqfile = read_input_files(seq_file_list)
if (os.path.isdir(tmp_seq_dir)):
for file_name in seq_file_list:
os.remove(file_name)
os.removedirs(tmp_seq_dir)
# detect whether it's tabular or fasta format
if read_seqfile[0].startswith(">"):
seq_method = '454'
else:
seq_method = 'solexa'
# parse files
if (seq_method == 'solexa'):
seq_hash = parse_solexa_files(read_seqfile, 'seq')
else: # the other two are both fasta format
seq_hash = parse_fasta_format(read_seqfile)
# R
status = generate_hist_figure()
# close and remove temporary files
r.quit(save = "no")
@@ -1,68 +0,0 @@
<tool id="array_of_reads_length" name="Array of Reads Length">
<description>on sequence file</description>
<command interpreter="python">short_reads_figure_length.py $input1 $output1</command>
<inputs>
<page>
<param name="input1" type="data" format="fasta,tabular,txtseq.zip" label="Sequence file" />
</page>
</inputs>
<outputs>
<data name="output1" format="tabular" />
</outputs>
<tests>
<test>
<param name="input1" value="solexa.fna" />
<output name="output1" file="solexaLength.txt" />
</test>
<test>
<param name="input1" value="454.fna" />
<output name="output1" file="454Length.txt" />
</test>
</tests>
<help>
**What it does**
This tool outputs an array of lengths of reads.
Currently, the tool accepts two file formats:
- fasta: for **454** data
- tabular: for **Solexa** data. Only take the maximal value from each 4 quality scores.
You can also upload your files in a zip file format and use this tool.
To see the distribution, please use the Histogram tool in Graph/Display data.
-----
**Example**
454 data::
&gt;EYKX4VC01B65GS length=54 xy=0784_1754 region=1 run=R_2007_11_07_16_15_57_
CCGGTATCCGGGTGCCGTGATGAGCGCCACCGGAACGAATTCGACTATGCCGAA
&gt;EYKX4VC01BNCSP length=187 xy=0558_3831 region=1 run=R_2007_11_07_16_15_57_
CTTACCGGTCACCACCGTGCCTTCAGGATTGATCGCCAGATCGGTCGGTGCGTCAGGCGG
GGTGACATCGCCCACCACGGTACTCACTGGCTGGCTCTGGTTCCCGGCGGCATCGGAGGC
CACCACGTTGAGGGTATTCCCCTCGGTTTGTGGCTCGGTGAGAACCACGTTGTAGTCGCC
ATTGGTC
Solexa data::
5 300 902 419 GACTCATGATTTCTTACCTATTAGTGGTTGAACATC
5 300 880 431 GTGATATGTATGTTGACGGCCATAAGGCTGCTTCTT
5 300 896 461 GTTGTCGATAGAACTTCATGTGCCTGTAAAACAAGT
5 300 890 751 ACCAACCAGAACGTGAAAAAGCGTCCTGCGTGTAGC
5 300 897 443 GTTTATGTTGGTTTCATGGTTTTGTCTAACTTTATC
5 300 906 879 GCTTTACCGTCTTTCCAGAAATTGTTCCAAGTATCG
An array of lengths of the reads::
Please see Graph/Display Data --> Histogram.
</help>
</tool>