# Path: crumbs/seq/sff_extract.py
# class SffExtractor(object):
#     'This class extracts the reads from an SFF file'
#     def __init__(self, sff_fhands, trim=False, min_left_clip=0,
#                  nucls_to_check=50, max_nucl_freq_threshold=0.5):
#         'It inits the class'
#         self.fhands = sff_fhands
#         self.trim = trim
#         self.min_left_clip = min_left_clip
# 
#         # checking
#         self.nucls_to_check = nucls_to_check
#         self.max_nucl_freq_threshold = max_nucl_freq_threshold
#         self.nucl_counts = {}
# 
#     @property
#     def seqs(self):
#         'It yields all sequences'
#         for fhand in self.fhands:
#             self._prepare_nucl_counts(fhand.name)
#             if not self.min_left_clip:
#                 seqs = SffIterator(fhand, trim=self.trim)
#             else:
#                 seqs = _min_left_clipped_seqs(fhand, self.trim,
#                                               self.min_left_clip)
#             for record in seqs:
#                 self._update_nucl_counts(str(record.seq), fhand.name)
#                 yield record
# 
#     def _prepare_nucl_counts(self, fpath):
#         'It prepares the structure to store the nucleotide counts'
#         counts = {'A': array('L', [0] * self.nucls_to_check),
#                   'T': array('L', [0] * self.nucls_to_check),
#                   'C': array('L', [0] * self.nucls_to_check),
#                   'G': array('L', [0] * self.nucls_to_check)}
#         self.nucl_counts[fpath] = counts
# 
#     def _update_nucl_counts(self, seq, fpath):
#         'Given a seq (as a string) it updates the nucleotide counts'
#         seq = seq[:self.nucls_to_check]
#         counts = self.nucl_counts
#         for index, nucl in enumerate(seq):
#             try:
#                 counts[fpath][nucl][index] += 1
#             except KeyError:
#                 pass  # we do not count the lowercase letters
# 
#     @property
#     def clip_advice(self):
#         'It checks how many positions have a high max nucl freq.'
#         advices = {}
#         for fhand in self.fhands:
#             fpath = fhand.name
#             counts = self.nucl_counts[fpath]
#             treshold = self.max_nucl_freq_threshold
#             pos_above_threshold = 0
#             seq_above_threshold = ''
#             index = 0
#             for index in range(self.nucls_to_check):
#                 num_nucls = [counts['A'][index], counts['T'][index],
#                              counts['C'][index], counts['G'][index]]
#                 tot_nucls = sum(num_nucls)
#                 if not tot_nucls:
#                     continue
#                 freq_nucls = [i / tot_nucls for i in num_nucls]
#                 above_threshold = [i >= treshold for i in freq_nucls]
#                 if any(above_threshold):
#                     pos_above_threshold += 1
#                     seq_above_threshold += _get_nucl_with_max_freq('ATCG',
#                                                                    freq_nucls)
#                 else:
#                     break
#             if pos_above_threshold:
#                 if self.trim:
#                     # number of nucleotides to remove next time, the ones
#                     # that we have detected plus the ones already removed
#                     advice = index + self.min_left_clip, seq_above_threshold
#                 else:
#                     advice = index, seq_above_threshold
#             else:
#                 advice = None
#             advices[fpath] = advice
#         return advices
# 
# Path: crumbs/utils/test_utils.py
# TEST_DATA_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), '..',
#                                              '..', 'test', 'test_data'))
# 
# Path: crumbs/utils/bin_utils.py
# SEQ_BIN_DIR = os.path.join(BIN_DIR, 'seq')


import unittest
import os.path
from tempfile import NamedTemporaryFile
from subprocess import check_output, CalledProcessError
from crumbs.seq.sff_extract import SffExtractor
from crumbs.utils.test_utils import TEST_DATA_DIR
from crumbs.utils.bin_utils import SEQ_BIN_DIR

        # empty file
        empty_fhand = NamedTemporaryFile()
        try:
            seqs = SffExtractor([open(empty_fhand.name, 'rb')]).seqs
            list(seqs)
            self.fail('ValueError expected.')
        except ValueError:
            pass

        # Wrong file type
        fasta_fhand = NamedTemporaryFile()
        fasta_fhand.write('>a_seq\n' + 'ACTG' * 30 + '\n')
        fasta_fhand.flush()
        try:
            seqs = SffExtractor([open(fasta_fhand.name, 'rb')]).seqs
            list(seqs)
        except ValueError:
            pass

    def test_check_nucl_counts(self):
        'It checks that the nucleotide freqs are all below the given threshold'
        sff_fpath = os.path.join(TEST_DATA_DIR, '10_454_reads.sff')

        extractor = SffExtractor([open(sff_fpath, 'rb')])
        seqs = extractor.seqs
        seqs = list(seqs)
        assert len(seqs) == 10
        assert extractor.clip_advice[sff_fpath] == (5, 'A')


# Path: crumbs/seq/sff_extract.py
# class SffExtractor(object):
#     'This class extracts the reads from an SFF file'
#     def __init__(self, sff_fhands, trim=False, min_left_clip=0,
#                  nucls_to_check=50, max_nucl_freq_threshold=0.5):
#         'It inits the class'
#         self.fhands = sff_fhands
#         self.trim = trim
#         self.min_left_clip = min_left_clip
# 
#         # checking
#         self.nucls_to_check = nucls_to_check
#         self.max_nucl_freq_threshold = max_nucl_freq_threshold
#         self.nucl_counts = {}
# 
#     @property
#     def seqs(self):
#         'It yields all sequences'
#         for fhand in self.fhands:
#             self._prepare_nucl_counts(fhand.name)
#             if not self.min_left_clip:
#                 seqs = SffIterator(fhand, trim=self.trim)
#             else:
#                 seqs = _min_left_clipped_seqs(fhand, self.trim,
#                                               self.min_left_clip)
#             for record in seqs:
#                 self._update_nucl_counts(str(record.seq), fhand.name)
#                 yield record
# 
#     def _prepare_nucl_counts(self, fpath):
#         'It prepares the structure to store the nucleotide counts'
#         counts = {'A': array('L', [0] * self.nucls_to_check),
#                   'T': array('L', [0] * self.nucls_to_check),
#                   'C': array('L', [0] * self.nucls_to_check),
#                   'G': array('L', [0] * self.nucls_to_check)}
#         self.nucl_counts[fpath] = counts
# 
#     def _update_nucl_counts(self, seq, fpath):
#         'Given a seq (as a string) it updates the nucleotide counts'
#         seq = seq[:self.nucls_to_check]
#         counts = self.nucl_counts
#         for index, nucl in enumerate(seq):
#             try:
#                 counts[fpath][nucl][index] += 1
#             except KeyError:
#                 pass  # we do not count the lowercase letters
# 
#     @property
#     def clip_advice(self):
#         'It checks how many positions have a high max nucl freq.'
#         advices = {}
#         for fhand in self.fhands:
#             fpath = fhand.name
#             counts = self.nucl_counts[fpath]
#             treshold = self.max_nucl_freq_threshold
#             pos_above_threshold = 0
#             seq_above_threshold = ''
#             index = 0
#             for index in range(self.nucls_to_check):
#                 num_nucls = [counts['A'][index], counts['T'][index],
#                              counts['C'][index], counts['G'][index]]
#                 tot_nucls = sum(num_nucls)
#                 if not tot_nucls:
#                     continue
#                 freq_nucls = [i / tot_nucls for i in num_nucls]
#                 above_threshold = [i >= treshold for i in freq_nucls]
#                 if any(above_threshold):
#                     pos_above_threshold += 1
#                     seq_above_threshold += _get_nucl_with_max_freq('ATCG',
#                                                                    freq_nucls)
#                 else:
#                     break
#             if pos_above_threshold:
#                 if self.trim:
#                     # number of nucleotides to remove next time, the ones
#                     # that we have detected plus the ones already removed
#                     advice = index + self.min_left_clip, seq_above_threshold
#                 else:
#                     advice = index, seq_above_threshold
#             else:
#                 advice = None
#             advices[fpath] = advice
#         return advices
# 
# Path: crumbs/utils/test_utils.py
# TEST_DATA_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), '..',
#                                              '..', 'test', 'test_data'))
# 
# Path: crumbs/utils/bin_utils.py
# SEQ_BIN_DIR = os.path.join(BIN_DIR, 'seq')


# Path: test/seq/test_sff_extract.py
import unittest
import os.path
from tempfile import NamedTemporaryFile
from subprocess import check_output, CalledProcessError
from crumbs.seq.sff_extract import SffExtractor
from crumbs.utils.test_utils import TEST_DATA_DIR
from crumbs.utils.bin_utils import SEQ_BIN_DIR


        # empty file
        empty_fhand = NamedTemporaryFile()
        try:
            seqs = SffExtractor([open(empty_fhand.name, 'rb')]).seqs
            list(seqs)
            self.fail('ValueError expected.')
        except ValueError:
            pass

        # Wrong file type
        fasta_fhand = NamedTemporaryFile()
        fasta_fhand.write('>a_seq\n' + 'ACTG' * 30 + '\n')
        fasta_fhand.flush()
        try:
            seqs = SffExtractor([open(fasta_fhand.name, 'rb')]).seqs
            list(seqs)
        except ValueError:
            pass

    def test_check_nucl_counts(self):
        'It checks that the nucleotide freqs are all below the given threshold'
        sff_fpath = os.path.join(TEST_DATA_DIR, '10_454_reads.sff')

        extractor = SffExtractor([open(sff_fpath, 'rb')])
        seqs = extractor.seqs
        seqs = list(seqs)
        assert len(seqs) == 10
        assert extractor.clip_advice[sff_fpath] == (5, 'A')


        extractor = SffExtractor([open(sff_fpath, 'rb')], min_left_clip=4,