diff --git a/config/datatypes_conf.xml.sample b/config/datatypes_conf.xml.sample
index 9c80d81ddbb..2a1cc9f846c 100644
--- a/config/datatypes_conf.xml.sample
+++ b/config/datatypes_conf.xml.sample
@@ -691,6 +691,9 @@
+
+
+
diff --git a/lib/galaxy/datatypes/registry.py b/lib/galaxy/datatypes/registry.py
index fcb1884d970..4be4249130e 100644
--- a/lib/galaxy/datatypes/registry.py
+++ b/lib/galaxy/datatypes/registry.py
@@ -776,6 +776,7 @@ class Registry( object ):
qualityscore.QualityScoreSOLiD(),
qualityscore.QualityScore454(),
sequence.Fasta(),
+ sequence.FastqSanger(),
sequence.Fastq(),
interval.Wiggle(),
text.Html(),
diff --git a/lib/galaxy/datatypes/sequence.py b/lib/galaxy/datatypes/sequence.py
index 7dc6feaa6eb..0c4cde56a13 100644
--- a/lib/galaxy/datatypes/sequence.py
+++ b/lib/galaxy/datatypes/sequence.py
@@ -603,16 +603,27 @@ class BaseFastq ( Sequence ):
>>> from galaxy.datatypes.sniff import get_test_fname
>>> fname = get_test_fname( '1.fastqsanger' )
- >>> Fastq().sniff( fname )
+ >>> FastqSanger().sniff( fname )
True
>>> fname = get_test_fname( '2.fastqsanger' )
+ >>> FastqSanger().sniff( fname )
+ True
+ >>> fname = get_test_fname( '2.fastq' )
>>> Fastq().sniff( fname )
True
+ >>> FastqSanger().sniff( fname )
+ False
"""
compressed = is_gzip(filename) or is_bz2(filename)
if compressed and not isinstance(self, Binary):
return False
- headers = get_headers( filename, None )
+ headers = get_headers( filename, None, count=1000 )
+
+ # If this is a FastqSanger-derived class, then check to see if the base qualities match
+ if isinstance(self, FastqSanger) or isinstance(self, FastqSangerGz) or isinstance(self, FastqSangerBz2):
+ if not self.sangerQualities(headers):
+ return False
+
bases_regexp = re.compile( "^[NGTAC]*" )
# check that first block looks like a fastq block
try:
@@ -687,6 +698,14 @@ class BaseFastq ( Sequence ):
return True
process_split_file = staticmethod(process_split_file)
+ @staticmethod
+ def sangerQualities( lines ):
+ """Presuming lines are lines from a fastq file, return True if the qualities are compatible with sanger encoding"""
+ for line in lines[3::4]:
+ if not all(_ >= '!' and _ <= 'M' for _ in line[0]):
+ return False
+ return True
+
class Fastq( BaseFastq ):
"""Class representing a generic FASTQ sequence"""
@@ -730,10 +749,6 @@ class FastqGz ( BaseFastq, Binary ):
return BaseFastq.sniff( self, filename )
-if SNIFF_COMPRESSED_FASTQS:
- Binary.register_sniffable_binary_format("fastq.gz", "fastq.gz", FastqGz)
-
-
class FastqSangerGz( FastqGz ):
"""Class representing a compressed FASTQ sequence ( the Sanger variant )"""
edam_format = "format_1932"
@@ -746,6 +761,11 @@ class FastqSolexaGz( FastqGz ):
file_ext = "fastqsolexa.gz"
+if SNIFF_COMPRESSED_FASTQS:
+ Binary.register_sniffable_binary_format("fastqsanger.gz", "fastqsanger.gz", FastqSangerGz)
+ Binary.register_sniffable_binary_format("fastq.gz", "fastq.gz", FastqGz)
+
+
class FastqIlluminaGz( FastqGz ):
"""Class representing a compressed FASTQ sequence ( the Illumina 1.3+ variant )"""
edam_format = "format_1931"
@@ -770,16 +790,17 @@ class FastqBz2 ( BaseFastq, Binary ):
return BaseFastq.sniff( self, filename )
-if SNIFF_COMPRESSED_FASTQS:
- Binary.register_sniffable_binary_format("fastq.bz2", "fastq.bz2", FastqBz2)
-
-
class FastqSangerBz2( FastqBz2 ):
"""Class representing a compressed FASTQ sequence ( the Sanger variant )"""
edam_format = "format_1932"
file_ext = "fastqsanger.bz2"
+if SNIFF_COMPRESSED_FASTQS:
+ Binary.register_sniffable_binary_format("fastqsanger.bz2", "fastqsanger.bz2", FastqSangerBz2)
+ Binary.register_sniffable_binary_format("fastq.bz2", "fastq.bz2", FastqBz2)
+
+
class FastqSolexaBz2( FastqBz2 ):
"""Class representing a compressed FASTQ sequence ( the Solexa variant )"""
edam_format = "format_1933"