<gh_stars>1-10
import asyncio
import os
import sys

from srrTomat0 import HTSEQ_MODULE_NAME
from srrTomat0.processor.utils import file_path_abs

HTSEQ_COUNT_FILE_EXTENSION = ".count.out"
HTSEQ_EXECUTABLE_CALL = [str(sys.executable), "-m", HTSEQ_MODULE_NAME]


def htseq_count_aligned(srr_ids, sam_file_names, annotation_file, output_path, num_workers=5):
    """

    :param srr_ids: list(str)
        NCBI SRR ID string
    :param sam_file_names: list(list(str))
        A list of complete SAM file names that were aligned from the FASTQ
    :param annotation_file: str
        A path to the GTF/GFF annotation file
    :param output_path: str
        The path to put the output alignment files
    :param num_workers: int
        Number of separate simultaneous jobs to run
    :return:
    """

    sem = asyncio.Semaphore(num_workers)

    # Build HTseq.count tasks
    tasks = [_htseq_count(sid, samfn, annotation_file, output_path, sem)
             for sid, samfn in zip(srr_ids, sam_file_names)]

    # Run and return STAR tasks
    return asyncio.get_event_loop().run_until_complete(asyncio.gather(*tasks))


# TODO: test this
async def _htseq_count(srr_id, sam_file_name, annotation_file_name, output_path, semaphore):
    """
    :param srr_id: str
        NCBI SRR ID string
    :param sam_file_name: str
        Path to the aligned SAM file
    :param annotation_file_name: str
        A path to the GTF/GFF annotations
    :param output_path: str
        A path to the output
    :param semaphore: asyncio.Semaphore
        Semaphore for resource utilization
    :return output_file: str
        The path to the GeneCount file generated by HTCount
    """

    async with semaphore:

        if sam_file_name is None:
            return None

        try:
            os.makedirs(output_path)
        except FileExistsError:
            pass

        output_file = os.path.join(file_path_abs(output_path), srr_id + HTSEQ_COUNT_FILE_EXTENSION)

        if os.path.exists(output_file):
            print("{id} countfile exists ({path})".format(id=srr_id, path=output_path))
            return output_file

        # Call out to an external interpreter
        htseq_call = [*HTSEQ_EXECUTABLE_CALL, "--stranded=no", sam_file_name, annotation_file_name]

        print(" ".join(htseq_call))
        process = await asyncio.create_subprocess_exec(*htseq_call,
                                                       stdout=asyncio.subprocess.PIPE,
                                                       stderr=asyncio.subprocess.PIPE)

        (output_data, output_err) = await process.communicate()

        if int(process.returncode) != 0:
            print("HTSeq.count failed for {id} ({file})".format(id=srr_id, file=sam_file_name))
            return None

        with open(output_file, mode="w") as out_fh:
            print(output_data.decode('utf-8'), file=out_fh)

        return output_file

import asyncio
import os
import sys

from srrTomat0 import HTSEQ_MODULE_NAME
from srrTomat0.processor.utils import file_path_abs

HTSEQ_COUNT_FILE_EXTENSION = ".count.out"
HTSEQ_EXECUTABLE_CALL = [str(sys.executable), "-m", HTSEQ_MODULE_NAME]


def htseq_count_aligned(srr_ids, sam_file_names, annotation_file, output_path, num_workers=5):
    """

    :param srr_ids: list(str)
        NCBI SRR ID string
    :param sam_file_names: list(list(str))
        A list of complete SAM file names that were aligned from the FASTQ
    :param annotation_file: str
        A path to the GTF/GFF annotation file
    :param output_path: str
        The path to put the output alignment files
    :param num_workers: int
        Number of separate simultaneous jobs to run
    :return:
    """

    sem = asyncio.Semaphore(num_workers)

    # Build HTseq.count tasks
    tasks = [_htseq_count(sid, samfn, annotation_file, output_path, sem)
             for sid, samfn in zip(srr_ids, sam_file_names)]

    # Run and return STAR tasks
    return asyncio.get_event_loop().run_until_complete(asyncio.gather(*tasks))


# TODO: test this
async def _htseq_count(srr_id, sam_file_name, annotation_file_name, output_path, semaphore):
    """
    :param srr_id: str
        NCBI SRR ID string
    :param sam_file_name: str
        Path to the aligned SAM file
    :param annotation_file_name: str
        A path to the GTF/GFF annotations
    :param output_path: str
        A path to the output
    :param semaphore: asyncio.Semaphore
        Semaphore for resource utilization
    :return output_file: str
        The path to the GeneCount file generated by HTCount
    """

    async with semaphore:

        if sam_file_name is None:
            return None

        try:
            os.makedirs(output_path)
        except FileExistsError:
            pass

        output_file = os.path.join(file_path_abs(output_path), srr_id + HTSEQ_COUNT_FILE_EXTENSION)

        if os.path.exists(output_file):
            print("{id} countfile exists ({path})".format(id=srr_id, path=output_path))
            return output_file

        # Call out to an external interpreter
        htseq_call = [*HTSEQ_EXECUTABLE_CALL, "--stranded=no", sam_file_name, annotation_file_name]

        print(" ".join(htseq_call))
        process = await asyncio.create_subprocess_exec(*htseq_call,
                                                       stdout=asyncio.subprocess.PIPE,
                                                       stderr=asyncio.subprocess.PIPE)

        (output_data, output_err) = await process.communicate()

        if int(process.returncode) != 0:
            print("HTSeq.count failed for {id} ({file})".format(id=srr_id, file=sam_file_name))
            return None

        with open(output_file, mode="w") as out_fh:
            print(output_data.decode('utf-8'), file=out_fh)

        return output_file
:param srr_ids: list(str)         NCBI SRR ID string     :param sam_file_names: list(list(str))         A list of complete SAM file names that were aligned from the FASTQ     :param annotation_file: str         A path to the GTF/GFF annotation file     :param output_path: str         The path to put the output alignment files     :param num_workers: int         Number of separate simultaneous jobs to run     :return: # Build HTseq.count tasks # Run and return STAR tasks # TODO: test this :param srr_id: str         NCBI SRR ID string     :param sam_file_name: str         Path to the aligned SAM file     :param annotation_file_name: str         A path to the GTF/GFF annotations     :param output_path: str         A path to the output     :param semaphore: asyncio.Semaphore         Semaphore for resource utilization     :return output_file: str         The path to the GeneCount file generated by HTCount # Call out to an external interpreter