<reponame>StephenRicher/pyFastQTools
#!/usr/bin/env python3

""" Check sequence duplication levels in FASTQ file. """

import pyCommonTools as pct
import contextlib
import subprocess
from collections import defaultdict
import sys


def duplicates(in_fastq: str = '-', out_fastq: str = '-',
               buffer_size: float = 0.1, parallel: int = 1):

    ''' Check FASTQ duplication level. '''

    log = pct.create_logger()

    with contextlib.ExitStack() as cm:
        out_fobj = cm.enter_context(pct.open_smart(out_fastq, mode='w'))
        in_fobj = cm.enter_context(pct.open_smart(in_fastq))
        try:
            p1 = cm.enter_context(subprocess.Popen(
                ['awk', 'NR%4 == 2'],
                stdin=in_fobj, stdout=subprocess.PIPE))
            p2 = cm.enter_context(subprocess.Popen(
                ['sort', '--parallel', f'{parallel}',
                '--buffer-size', f'{int(buffer_size*100)}%'],
                stdin=p1.stdout, stdout=subprocess.PIPE, encoding='utf8'))
            p1.stdout.close()
        except FileNotFoundError as e:
            log.exception(f'{e}\nPlease install awk and sort.')
            sys.exit(1)

        duplicates = defaultdict(int)

        for index, line in enumerate(p2.stdout):
            line = line.rstrip('\n')
            if index == 0:
                copies = 1
            elif line == previous_line:
                copies += 1
            else:
                duplicates[copies] += 1
                copies = 1
            previous_line = line
        duplicates[copies] += 1

        for duplicate_level, ncopies in sorted(duplicates.items()):
            out_fobj.write(f'{duplicate_level}\t{ncopies}\n')

        exit_codes = [p.wait() for p in [p1, p2]]
        log.debug(f'Exit_codes for p1, p2: {exit_codes}.')
        if not all(ec is 0 for ec in exit_codes):
            log.error('A sub-process returned a non-zero exit code.')


#!/usr/bin/env python3

""" Check sequence duplication levels in FASTQ file. """

import pyCommonTools as pct
import contextlib
import subprocess
from collections import defaultdict
import sys


def duplicates(in_fastq: str = '-', out_fastq: str = '-',
               buffer_size: float = 0.1, parallel: int = 1):

    ''' Check FASTQ duplication level. '''

    log = pct.create_logger()

    with contextlib.ExitStack() as cm:
        out_fobj = cm.enter_context(pct.open_smart(out_fastq, mode='w'))
        in_fobj = cm.enter_context(pct.open_smart(in_fastq))
        try:
            p1 = cm.enter_context(subprocess.Popen(
                ['awk', 'NR%4 == 2'],
                stdin=in_fobj, stdout=subprocess.PIPE))
            p2 = cm.enter_context(subprocess.Popen(
                ['sort', '--parallel', f'{parallel}',
                '--buffer-size', f'{int(buffer_size*100)}%'],
                stdin=p1.stdout, stdout=subprocess.PIPE, encoding='utf8'))
            p1.stdout.close()
        except FileNotFoundError as e:
            log.exception(f'{e}\nPlease install awk and sort.')
            sys.exit(1)

        duplicates = defaultdict(int)

        for index, line in enumerate(p2.stdout):
            line = line.rstrip('\n')
            if index == 0:
                copies = 1
            elif line == previous_line:
                copies += 1
            else:
                duplicates[copies] += 1
                copies = 1
            previous_line = line
        duplicates[copies] += 1

        for duplicate_level, ncopies in sorted(duplicates.items()):
            out_fobj.write(f'{duplicate_level}\t{ncopies}\n')

        exit_codes = [p.wait() for p in [p1, p2]]
        log.debug(f'Exit_codes for p1, p2: {exit_codes}.')
        if not all(ec is 0 for ec in exit_codes):
            log.error('A sub-process returned a non-zero exit code.')
#!/usr/bin/env python3 Check sequence duplication levels in FASTQ file. Check FASTQ duplication level.