template = OrderedDict([<EOL>("<STR_LIT>", <NUM_LIT:0>),<EOL>("<STR_LIT>", <NUM_LIT:0>),<EOL>("<STR_LIT>", <NUM_LIT:0>),<EOL>("<STR_LIT>", <NUM_LIT:0>),<EOL>("<STR_LIT>", <NUM_LIT:0>),<EOL>("<STR_LIT>", <NUM_LIT:0>)<EOL>])<EOL>with open(log_file) as fh:<EOL><INDENT>for line in fh:<EOL><INDENT>fields = [int(x) for x in line.strip().split()[-<NUM_LIT:4>:]]<EOL>if not fields[<NUM_LIT:0>]:<EOL><INDENT>template["<STR_LIT>"] += <NUM_LIT:1><EOL><DEDENT>template["<STR_LIT>"] += fields[<NUM_LIT:1>]<EOL>template["<STR_LIT>"] += fields[<NUM_LIT:3>]<EOL>template["<STR_LIT>"] += fields[<NUM_LIT:1>] + fields[<NUM_LIT:3>]<EOL>template["<STR_LIT>"] += fields[<NUM_LIT:0>]<EOL><DEDENT>total_len = template["<STR_LIT>"] + template["<STR_LIT>"]<EOL>if total_len:<EOL><INDENT>template["<STR_LIT>"] = round(<EOL>(template["<STR_LIT>"] / total_len) * <NUM_LIT:100>, <NUM_LIT:2>)<EOL><DEDENT>else:<EOL><INDENT>template["<STR_LIT>"] = <NUM_LIT:0><EOL><DEDENT><DEDENT>return template<EOL>

Retrieves some statistics from a single Trimmomatic log file.

    This function parses Trimmomatic's log file and stores some trimming
    statistics in an :py:class:`OrderedDict` object. This object contains
    the following keys:

        - ``clean_len``: Total length after trimming.
        - ``total_trim``: Total trimmed base pairs.
        - ``total_trim_perc``: Total trimmed base pairs in percentage.
        - ``5trim``: Total base pairs trimmed at 5' end.
        - ``3trim``: Total base pairs trimmed at 3' end.

    Parameters
    ----------
    log_file : str
        Path to trimmomatic log file.

    Returns
    -------
    x : :py:class:`OrderedDict`
        Object storing the trimming statistics.


def write_report(storage_dic, output_file, sample_id):

with open(output_file, "<STR_LIT:w>") as fh, open("<STR_LIT>", "<STR_LIT:w>") as json_rep:<EOL><INDENT>fh.write("<STR_LIT>"<EOL>"<STR_LIT>")<EOL>for sample, vals in storage_dic.items():<EOL><INDENT>fh.write("<STR_LIT>".format(<EOL>sample, "<STR_LIT:U+002C>".join([str(x) for x in vals.values()])))<EOL>json_dic = {<EOL>"<STR_LIT>": [{<EOL>"<STR_LIT>": sample_id,<EOL>"<STR_LIT:data>": [<EOL>{"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT:value>": vals["<STR_LIT>"],<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT>": True},<EOL>]<EOL>}],<EOL>"<STR_LIT>": [{<EOL>"<STR_LIT>": sample_id,<EOL>"<STR_LIT:data>": {<EOL>"<STR_LIT>": vals["<STR_LIT>"]<EOL>}<EOL>}],<EOL>"<STR_LIT>": vals["<STR_LIT>"]<EOL>}<EOL>json_rep.write(json.dumps(json_dic, separators=("<STR_LIT:U+002C>", "<STR_LIT::>")))<EOL><DEDENT><DEDENT>

Writes a report from multiple samples.

    Parameters
    ----------
    storage_dic : dict or :py:class:`OrderedDict`
        Storage containing the trimming statistics. See :py:func:`parse_log`
        for its generation.
    output_file : str
        Path where the output file will be generated.
    sample_id : str
        Id or name of the current sample.


log_storage = OrderedDict()<EOL>for log in log_files:<EOL><INDENT>log_id = log.rstrip("<STR_LIT>")<EOL>log_storage[log_id] = parse_log(log)<EOL>os.remove(log)<EOL><DEDENT>write_report(log_storage, "<STR_LIT>", log_id)<EOL>

Main executor of the trimmomatic_report template.

    Parameters
    ----------
    log_files : list
        List of paths to the trimmomatic log files.


@MainWrapper<EOL>def main(sample_id, assembly_file, minsize):

logger.info("<STR_LIT>")<EOL>warnings = []<EOL>fails = "<STR_LIT>"<EOL>logger.info("<STR_LIT>")<EOL>assembly_obj = Assembly(assembly_file, <NUM_LIT:0>, <NUM_LIT:0>,<EOL>sample_id, minsize)<EOL>if '<STR_LIT>' in assembly_file:<EOL><INDENT>assembler = "<STR_LIT>"<EOL><DEDENT>else:<EOL><INDENT>assembler = "<STR_LIT>"<EOL><DEDENT>with open("<STR_LIT>", "<STR_LIT:w>") as warn_fh:<EOL><INDENT>t_80 = int(minsize) * <NUM_LIT><EOL>t_150 = int(minsize) * <NUM_LIT><EOL>assembly_len = assembly_obj.get_assembly_length()<EOL>logger.debug("<STR_LIT>".format(assembly_len))<EOL>if assembly_obj.nORFs < <NUM_LIT:1>:<EOL><INDENT>warn_msg = "<STR_LIT>"<EOL>warn_fh.write(warn_msg)<EOL>fails = warn_msg<EOL><DEDENT>if assembly_len < t_80:<EOL><INDENT>logger.warning("<STR_LIT>"<EOL>"<STR_LIT>"<EOL>"<STR_LIT>"<EOL>"<STR_LIT>".format(assembly_len))<EOL>assembly_len = assembly_obj.get_assembly_length()<EOL>logger.debug("<STR_LIT>"<EOL>"<STR_LIT:{}>".format(assembly_len))<EOL>if assembly_len < t_80:<EOL><INDENT>warn_msg = "<STR_LIT>""<STR_LIT>".format(<EOL>assembly_len)<EOL>logger.warning(warn_msg)<EOL>warn_fh.write(warn_msg)<EOL>fails = warn_msg<EOL><DEDENT><DEDENT>if assembly_len > t_150:<EOL><INDENT>warn_msg = "<STR_LIT>""<STR_LIT>".format(<EOL>assembly_len)<EOL>logger.warning(warn_msg)<EOL>warn_fh.write(warn_msg)<EOL>fails = warn_msg<EOL><DEDENT><DEDENT>with open("<STR_LIT>", "<STR_LIT:w>") as json_report:<EOL><INDENT>json_dic = {<EOL>"<STR_LIT>": [{<EOL>"<STR_LIT>": sample_id,<EOL>"<STR_LIT:data>": [<EOL>{"<STR_LIT>": "<STR_LIT>".format(assembler),<EOL>"<STR_LIT:value>": len(assembly_obj.contigs),<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT>": True},<EOL>{"<STR_LIT>": "<STR_LIT>".format(assembler),<EOL>"<STR_LIT:value>": assembly_len,<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT>": True},<EOL>{"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT:value>": assembly_obj.nORFs,<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT>":False}<EOL>]<EOL>}],<EOL>}<EOL>if warnings:<EOL><INDENT>json_dic["<STR_LIT>"] = [{<EOL>"<STR_LIT>": sample_id,<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT:value>": warnings<EOL>}]<EOL><DEDENT>if fails:<EOL><INDENT>json_dic["<STR_LIT>"] = [{<EOL>"<STR_LIT>": sample_id,<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT:value>": [fails]<EOL>}]<EOL><DEDENT>json_report.write(json.dumps(json_dic, separators=("<STR_LIT:U+002C>", "<STR_LIT::>")))<EOL><DEDENT>with open("<STR_LIT>", "<STR_LIT:w>") as status_fh:<EOL><INDENT>status_fh.write("<STR_LIT>")<EOL><DEDENT>

Main executor of the process_mapping template.

    Parameters
    ----------
    sample_id : str
        Sample Identification string.
    assembly: str
        Path to the fatsa file generated by the assembler.
    minsize: str
        Min contig size to be considered a complete ORF


cov = None<EOL>for i in header_str.split("<STR_LIT:_>")[::-<NUM_LIT:1>]:<EOL><INDENT>try:<EOL><INDENT>cov = float(i)<EOL>break<EOL><DEDENT>except ValueError:<EOL><INDENT>continue<EOL><DEDENT><DEDENT>return cov<EOL>

Attempts to retrieve the coverage value from the header string.

        It splits the header by "_" and then screens the list backwards in
        search of the first float value. This will be interpreted as the
        coverage value. If it cannot find a float value, it returns None.
        This search methodology is based on the strings of assemblers
        like spades and skesa that put the mean kmer coverage for each
        contig in its corresponding fasta header.

        Parameters
        ----------
        header_str : str
            String

        Returns
        -------
        float or None
            The coverage value for the contig. None if it cannot find the
            value in the provide string.


<EOL>seq_temp = []<EOL>contig_id = <NUM_LIT:0><EOL>cov, header = None, None<EOL>with open(assembly_file) as fh:<EOL><INDENT>logger.debug("<STR_LIT>".format(<EOL>assembly_file))<EOL>for line in fh:<EOL><INDENT>if not line.strip():<EOL><INDENT>continue<EOL><DEDENT>else:<EOL><INDENT>line = line.strip()<EOL><DEDENT>if line.startswith("<STR_LIT:>>"):<EOL><INDENT>if seq_temp:<EOL><INDENT>seq = "<STR_LIT>".join(seq_temp)<EOL>logger.debug("<STR_LIT>"<EOL>"<STR_LIT>".format(<EOL>contig_id, header, cov))<EOL>self._populate_contigs(contig_id, header, cov, seq)<EOL>seq_temp = []<EOL>contig_id += <NUM_LIT:1><EOL><DEDENT>header = line[<NUM_LIT:1>:]<EOL>cov = self._parse_coverage(line)<EOL><DEDENT>else:<EOL><INDENT>seq_temp.append(line)<EOL><DEDENT><DEDENT>logger.debug("<STR_LIT>"<EOL>"<STR_LIT>".format(<EOL>contig_id, header, cov))<EOL>seq = "<STR_LIT>".join(seq_temp)<EOL>self._populate_contigs(contig_id, header, cov, seq)<EOL><DEDENT>

Parse an assembly fasta file.

        This is a Fasta parsing method that populates the
        :py:attr:`~Assembly.contigs` attribute with data for each contig in the
        assembly.

        The insertion of data on the self.contigs is done by the
        :py:meth:`Assembly._populate_contigs` method, which also calculates
        GC content and proportions.

        Parameters
        ----------
        assembly_file : str
            Path to the assembly fasta file.


def _populate_contigs(self, contig_id, header, cov, sequence):

<EOL>gc_kwargs = self._get_gc_content(sequence, len(sequence))<EOL>logger.debug("<STR_LIT>".format(gc_kwargs))<EOL>self.contigs[contig_id] = {<EOL>"<STR_LIT>": header,<EOL>"<STR_LIT>": sequence,<EOL>"<STR_LIT>": len(sequence),<EOL>"<STR_LIT>": cov,<EOL>**gc_kwargs<EOL>}<EOL>

Inserts data from a single contig into\
         :py:attr:`~Assembly.contigs`.

        By providing a contig id, the original header, the coverage that
        is parsed from the header and the sequence, this method will
        populate the :py:attr:`~Assembly.contigs` attribute.

        Parameters
        ----------
        contig_id : int
            Arbitrary unique contig identifier.
        header : str
            Original header of the current contig.
        cov : float
            The contig coverage, parsed from the fasta header
        sequence : str
            The complete sequence of the contig.


<EOL>at = sum(map(sequence.count, ["<STR_LIT:A>", "<STR_LIT:T>"]))<EOL>gc = sum(map(sequence.count, ["<STR_LIT>", "<STR_LIT:C>"]))<EOL>n = length - (at + gc)<EOL>at_prop = at / length<EOL>gc_prop = gc / length<EOL>n_prop = n / length<EOL>return {"<STR_LIT>": at, "<STR_LIT>": gc, "<STR_LIT:n>": n,<EOL>"<STR_LIT>": at_prop, "<STR_LIT>": gc_prop, "<STR_LIT>": n_prop}<EOL>

Get GC content and proportions.

        Parameters
        ----------
        sequence : str
            The complete sequence of the contig.
        length : int
            The length of the sequence contig.

        Returns
        -------
        x : dict
            Dictionary with the at/gc/n counts and proportions


<EOL>self.filtered_ids = []<EOL>self.report = {}<EOL>gc_filters = [<EOL>["<STR_LIT>", "<STR_LIT>", self.min_gc],<EOL>["<STR_LIT>", "<STR_LIT>", <NUM_LIT:1> - self.min_gc]<EOL>]<EOL>self.filters = list(comparisons) + gc_filters<EOL>logger.debug("<STR_LIT>".format(<EOL>self.filters))<EOL>for contig_id, contig in self.contigs.items():<EOL><INDENT>for key, op, value in list(comparisons) + gc_filters:<EOL><INDENT>if not self._test_truth(contig[key], op, value):<EOL><INDENT>self.filtered_ids.append(contig_id)<EOL>self.report[contig_id] = "<STR_LIT>".format(key,<EOL>contig[key],<EOL>value)<EOL>break<EOL><DEDENT>else:<EOL><INDENT>self.report[contig_id] = "<STR_LIT>"<EOL><DEDENT><DEDENT><DEDENT>

Filters the contigs of the assembly according to user provided\
        comparisons.

        The comparisons must be a list of three elements with the
        :py:attr:`~Assembly.contigs` key, operator and test value. For
        example, to filter contigs with a minimum length of 250, a comparison
        would be::

            self.filter_contigs(["length", ">=", 250])

        The filtered contig ids will be stored in the
        :py:attr:`~Assembly.filtered_ids` list.

        The result of the test for all contigs will be stored in the
        :py:attr:`~Assembly.report` dictionary.

        Parameters
        ----------
        comparisons : list
            List with contig key, operator and value to test.


return sum(<EOL>[vals["<STR_LIT>"] for contig_id, vals in self.contigs.items()<EOL>if contig_id not in self.filtered_ids])<EOL>

Returns the length of the assembly, without the filtered contigs.

        Returns
        -------
        x : int
            Total length of the assembly.


def write_assembly(self, output_file, filtered=True):

logger.debug("<STR_LIT>".format(<EOL>output_file))<EOL>with open(output_file, "<STR_LIT:w>") as fh:<EOL><INDENT>for contig_id, contig in self.contigs.items():<EOL><INDENT>if contig_id not in self.filtered_ids and filtered:<EOL><INDENT>fh.write("<STR_LIT>".format(self.sample,<EOL>contig["<STR_LIT>"],<EOL>contig["<STR_LIT>"]))<EOL><DEDENT><DEDENT><DEDENT>

Writes the assembly to a new file.

        The ``filtered`` option controls whether the new assembly will be
        filtered or not.

        Parameters
        ----------
        output_file : str
            Name of the output assembly file.
        filtered : bool
            If ``True``, does not include filtered ids.


logger.debug("<STR_LIT>".format(<EOL>output_file))<EOL>with open(output_file, "<STR_LIT:w>") as fh:<EOL><INDENT>for contig_id, vals in self.report.items():<EOL><INDENT>fh.write("<STR_LIT>".format(contig_id, vals))<EOL><DEDENT><DEDENT>

Writes a report with the test results for the current assembly

        Parameters
        ----------
        output_file : str
            Name of the output assembly file.


def _get_quality_stats(d, start_str, field_start=<NUM_LIT:1>, field_end=<NUM_LIT:2>):

min_parsed = False<EOL>parse = False<EOL>report = []<EOL>start_str = start_str<EOL>end_str = "<STR_LIT>"<EOL>with open(d) as fh:<EOL><INDENT>for line in fh:<EOL><INDENT>if line.startswith(start_str):<EOL><INDENT>next(fh)<EOL>parse = True<EOL>status = line.strip().split()[-<NUM_LIT:1>]<EOL><DEDENT>elif parse and line.startswith(end_str):<EOL><INDENT>return report, status<EOL><DEDENT>elif parse:<EOL><INDENT>fields = line.strip().split()<EOL>if not min_parsed:<EOL><INDENT>if fields[<NUM_LIT:0>] != "<STR_LIT:1>":<EOL><INDENT>try:<EOL><INDENT>blank_points = int(fields[<NUM_LIT:0>]) - <NUM_LIT:1><EOL>report.extend([<NUM_LIT:0>] * blank_points)<EOL><DEDENT>except ValueError:<EOL><INDENT>pass<EOL><DEDENT><DEDENT>min_parsed = True<EOL><DEDENT>report.append("<STR_LIT:;>".join([<EOL>str(round(float(x), <NUM_LIT:2>)) for x in<EOL>fields[field_start: field_end]<EOL>]))<EOL><DEDENT><DEDENT><DEDENT>

Parameters
----------
d

Returns
-------


def write_json_report(sample_id, data1, data2):

parser_map = {<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT>": "<STR_LIT>"<EOL>}<EOL>json_dic = {<EOL>"<STR_LIT>": [{<EOL>"<STR_LIT>": sample_id,<EOL>"<STR_LIT:data>": {<EOL>"<STR_LIT>": {"<STR_LIT:status>": None, "<STR_LIT:data>": []},<EOL>"<STR_LIT>": {"<STR_LIT:status>": None, "<STR_LIT:data>": []},<EOL>"<STR_LIT>": {"<STR_LIT:status>": None, "<STR_LIT:data>": []},<EOL>"<STR_LIT>": {"<STR_LIT:status>": None, "<STR_LIT:data>": []},<EOL>"<STR_LIT>": {"<STR_LIT:status>": None, "<STR_LIT:data>": []},<EOL>"<STR_LIT>": {"<STR_LIT:status>": None, "<STR_LIT:data>": []}<EOL>}<EOL>}]<EOL>}<EOL>for cat, start_str in parser_map.items():<EOL><INDENT>if cat == "<STR_LIT>":<EOL><INDENT>fs = <NUM_LIT:1><EOL>fe = <NUM_LIT:5><EOL><DEDENT>else:<EOL><INDENT>fs = <NUM_LIT:1><EOL>fe = <NUM_LIT:2><EOL><DEDENT>report1, status1 = _get_quality_stats(data1, start_str,<EOL>field_start=fs, field_end=fe)<EOL>report2, status2 = _get_quality_stats(data2, start_str,<EOL>field_start=fs, field_end=fe)<EOL>status = None<EOL>for i in ["<STR_LIT>", "<STR_LIT>", "<STR_LIT>"]:<EOL><INDENT>if i in [status1, status2]:<EOL><INDENT>status = i<EOL><DEDENT><DEDENT>json_dic["<STR_LIT>"][<NUM_LIT:0>]["<STR_LIT:data>"][cat]["<STR_LIT:data>"] = [report1, report2]<EOL>json_dic["<STR_LIT>"][<NUM_LIT:0>]["<STR_LIT:data>"][cat]["<STR_LIT:status>"] = status<EOL><DEDENT>return json_dic<EOL>

Writes the report

    Parameters
    ----------
    data1
    data2

    Returns
    -------


<EOL>if set(biased_list) == {False}:<EOL><INDENT>return <NUM_LIT:0><EOL><DEDENT>if set(biased_list[:<NUM_LIT:5>]) == {False}:<EOL><INDENT>return <NUM_LIT:0><EOL><DEDENT>for i, val in enumerate(biased_list):<EOL><INDENT>if val and set(biased_list[i+<NUM_LIT:1>:i+<NUM_LIT:3>]) == {False}:<EOL><INDENT>return i + <NUM_LIT:1><EOL><DEDENT><DEDENT>return len(biased_list)<EOL>

Returns the trim index from a ``bool`` list

    Provided with a list of ``bool`` elements (``[False, False, True, True]``),
    this function will assess the index of the list that minimizes the number
    of True elements (biased positions) at the extremities. To do so,
    it will iterate over the boolean list and find an index position where
    there are two consecutive ``False`` elements after a ``True`` element. This
    will be considered as an optimal trim position. For example, in the
    following list::

        [True, True, False, True, True, False, False, False, False, ...]

    The optimal trim index will be the 4th position, since it is the first
    occurrence of a ``True`` element with two False elements after it.

    If the provided ``bool`` list has no ``True`` elements, then the 0 index is
    returned.

    Parameters
    ----------
    biased_list: list
        List of ``bool`` elements, where ``True`` means a biased site.

    Returns
    -------
        x : index position of the biased list for the optimal trim.


logger.debug("<STR_LIT>")<EOL>target_nuc_bias = "<STR_LIT>"<EOL>logger.debug("<STR_LIT>"<EOL>"<STR_LIT:{}>".format(target_nuc_bias))<EOL>gather = False<EOL>biased = []<EOL>with open(data_file) as fh:<EOL><INDENT>for line in fh:<EOL><INDENT>if line.startswith(target_nuc_bias):<EOL><INDENT>logger.debug("<STR_LIT>".format(line))<EOL>next(fh)<EOL>gather = True<EOL><DEDENT>elif line.startswith("<STR_LIT>") and gather:<EOL><INDENT>logger.debug("<STR_LIT>".format(line))<EOL>break<EOL><DEDENT>elif gather:<EOL><INDENT>g, a, t, c = [float(x) for x in line.strip().split()[<NUM_LIT:1>:]]<EOL>gc = (g + <NUM_LIT:0.1>) / (c + <NUM_LIT:0.1>)<EOL>at = (a + <NUM_LIT:0.1>) / (t + <NUM_LIT:0.1>)<EOL>if <NUM_LIT> <= gc <= <NUM_LIT> and <NUM_LIT> <= at <= <NUM_LIT>:<EOL><INDENT>biased.append(False)<EOL><DEDENT>else:<EOL><INDENT>biased.append(True)<EOL><DEDENT><DEDENT><DEDENT><DEDENT>logger.debug("<STR_LIT>".format(biased))<EOL>biased_5end, biased_3end = biased[:int(len(biased)/<NUM_LIT:2>)],biased[int(len(biased)/<NUM_LIT:2>):][::-<NUM_LIT:1>]<EOL>logger.debug("<STR_LIT>")<EOL>trim_nt = [<NUM_LIT:0>, <NUM_LIT:0>]<EOL>trim_nt[<NUM_LIT:0>] = get_trim_index(biased_5end)<EOL>logger.debug("<STR_LIT>".format(trim_nt[<NUM_LIT:0>]))<EOL>trim_nt[<NUM_LIT:1>] = len(biased) - get_trim_index(biased_3end)<EOL>logger.debug("<STR_LIT>".format(trim_nt[<NUM_LIT:1>]))<EOL>return trim_nt<EOL>

Assess the optimal trim range for a given FastQC data file.

    This function will parse a single FastQC data file, namely the
    *'Per base sequence content'* category. It will retrieve the A/T and G/C
    content for each nucleotide position in the reads, and check whether the
    G/C and A/T proportions are between 80% and 120%. If they are, that
    nucleotide position is marked as biased for future removal.

    Parameters
    ----------
    data_file: str
        Path to FastQC data file.

    Returns
    -------
    trim_nt: list
        List containing the range with the best trimming positions for the
        corresponding FastQ file. The first element is the 5' end trim index
        and the second element is the 3' end trim index.


sample_ranges = [trim_range(x) for x in [p1_data, p2_data]]<EOL>optimal_5trim = max([x[<NUM_LIT:0>] for x in sample_ranges])<EOL>optimal_3trim = min([x[<NUM_LIT:1>] for x in sample_ranges])<EOL>return optimal_5trim, optimal_3trim<EOL>

Get the optimal read trim range from data files of paired FastQ reads.

    Given the FastQC data report files for paired-end FastQ reads, this
    function will assess the optimal trim range for the 3' and 5' ends of
    the paired-end reads. This assessment will be based on the *'Per sequence
    GC content'*.

    Parameters
    ----------
    p1_data: str
        Path to FastQC data report file from pair 1
    p2_data: str
        Path to FastQC data report file from pair 2

    Returns
    -------
    optimal_5trim: int
        Optimal trim index for the 5' end of the reads
    optima_3trim: int
        Optimal trim index for the 3' end of the reads

    See Also
    --------
    trim_range


summary_info = OrderedDict()<EOL>logger.debug("<STR_LIT>".format(<EOL>summary_file))<EOL>with open(summary_file) as fh:<EOL><INDENT>for line in fh:<EOL><INDENT>if not line.strip():<EOL><INDENT>continue<EOL><DEDENT>fields = [x.strip() for x in line.split("<STR_LIT:\t>")]<EOL>summary_info[fields[<NUM_LIT:1>]] = fields[<NUM_LIT:0>]<EOL><DEDENT><DEDENT>logger.debug("<STR_LIT>".format(<EOL>summary_info))<EOL>return summary_info<EOL>

Parses a FastQC summary report file and returns it as a dictionary.

    This function parses a typical FastQC summary report file, retrieving
    only the information on the first two columns. For instance, a line could
    be::

        'PASS	Basic Statistics	SH10762A_1.fastq.gz'

    This parser will build a dictionary with the string in the second column
    as a key and the QC result as the value. In this case, the returned
    ``dict`` would be something like::

        {"Basic Statistics": "PASS"}

    Parameters
    ----------
    summary_file: str
        Path to FastQC summary report.

    Returns
    -------
    summary_info: :py:data:`OrderedDict`
        Returns the information of the FastQC summary report as an ordered
        dictionary, with the categories as strings and the QC result as values.


<EOL>fail_sensitive = kwargs.get("<STR_LIT>", [<EOL>"<STR_LIT>",<EOL>"<STR_LIT>",<EOL>"<STR_LIT>",<EOL>"<STR_LIT>"<EOL>])<EOL>logger.debug("<STR_LIT>".format(fail_sensitive))<EOL>must_pass = kwargs.get("<STR_LIT>", [<EOL>"<STR_LIT>",<EOL>"<STR_LIT>"<EOL>])<EOL>logger.debug("<STR_LIT>".format(must_pass))<EOL>warning_fail_sensitive = kwargs.get("<STR_LIT>", [<EOL>"<STR_LIT>",<EOL>"<STR_LIT>",<EOL>])<EOL>warning_must_pass = kwargs.get("<STR_LIT>", [<EOL>"<STR_LIT>"<EOL>])<EOL>summary_info = get_summary(summary_file)<EOL>health = True<EOL>failed = []<EOL>warning = []<EOL>for cat, test in summary_info.items():<EOL><INDENT>logger.debug("<STR_LIT>".format(cat, test))<EOL>if cat in fail_sensitive and test == "<STR_LIT>":<EOL><INDENT>health = False<EOL>failed.append("<STR_LIT>".format(cat, test))<EOL>logger.error("<STR_LIT>"<EOL>"<STR_LIT>".format(cat))<EOL><DEDENT>if cat in must_pass and test != "<STR_LIT>":<EOL><INDENT>health = False<EOL>failed.append("<STR_LIT>".format(cat, test))<EOL>logger.error("<STR_LIT>".format(<EOL>cat))<EOL><DEDENT>if cat in warning_fail_sensitive and test == "<STR_LIT>":<EOL><INDENT>warning.append("<STR_LIT>".format(cat))<EOL>logger.warning("<STR_LIT>"<EOL>"<STR_LIT>".format(cat))<EOL><DEDENT>if cat in warning_must_pass and test != "<STR_LIT>":<EOL><INDENT>warning.append("<STR_LIT>".format(cat))<EOL>logger.warning("<STR_LIT>"<EOL>"<STR_LIT>".format(cat))<EOL><DEDENT><DEDENT>return health, failed, warning<EOL>

Checks the health of a sample from the FastQC summary file.

    Parses the FastQC summary file and tests whether the sample is good
    or not. There are four categories that cannot fail, and two that
    must pass in order for the sample pass this check. If the sample fails
    the quality checks, a list with the failing categories is also returned.

    Categories that cannot fail::

        fail_sensitive = [
            "Per base sequence quality",
            "Overrepresented sequences",
            "Sequence Length Distribution",
            "Per sequence GC content"
        ]

    Categories that must pass::

        must_pass = [
            "Per base N content",
            "Adapter Content"
        ]

    Parameters
    ----------
    summary_file: str
        Path to FastQC summary file.

    Returns
    -------
    x : bool
        Returns ``True`` if the sample passes all tests. ``False`` if not.
    summary_info : list
        A list with the FastQC categories that failed the tests. Is empty
        if the sample passes all tests.


@MainWrapper<EOL>def main(sample_id, result_p1, result_p2, opts):

logger.info("<STR_LIT>")<EOL>json_dic = {}<EOL>with open("<STR_LIT>".format(sample_id), "<STR_LIT:w>") as trep_fh,open("<STR_LIT>", "<STR_LIT:w>") as trim_fh,open("<STR_LIT>".format(sample_id), "<STR_LIT:w>") as rep_fh,open("<STR_LIT>", "<STR_LIT:w>") as status_fh,open("<STR_LIT>", "<STR_LIT:w>") as warn_fh,open("<STR_LIT>", "<STR_LIT:w>") as fail_fh,open("<STR_LIT>", "<STR_LIT:w>") as report_fh:<EOL><INDENT>if "<STR_LIT>" not in opts:<EOL><INDENT>json_dic = write_json_report(sample_id, result_p1[<NUM_LIT:0>],<EOL>result_p2[<NUM_LIT:0>])<EOL>logger.info("<STR_LIT>")<EOL>for p, fastqc_summary in enumerate([result_p1[<NUM_LIT:1>], result_p2[<NUM_LIT:1>]]):<EOL><INDENT>logger.debug("<STR_LIT>".format(fastqc_summary))<EOL>health, f_cat, warnings = check_summary_health(fastqc_summary)<EOL>logger.debug("<STR_LIT>".format(health))<EOL>logger.debug("<STR_LIT>".format(f_cat))<EOL>if warnings:<EOL><INDENT>json_dic["<STR_LIT>"] = [{<EOL>"<STR_LIT>": sample_id,<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT:value>": []<EOL>}]<EOL>for w in warnings:<EOL><INDENT>warn_fh.write("<STR_LIT>".format(w))<EOL>json_dic["<STR_LIT>"][<NUM_LIT:0>]["<STR_LIT:value>"].append(w)<EOL><DEDENT><DEDENT>output_file = "<STR_LIT>".format(sample_id, p)<EOL>os.rename(fastqc_summary, output_file)<EOL>logger.debug("<STR_LIT>".format(<EOL>output_file))<EOL>if not health:<EOL><INDENT>fail_msg = "<STR_LIT>""<STR_LIT>".format("<STR_LIT:U+002C>".join(f_cat))<EOL>logger.warning(fail_msg)<EOL>fail_fh.write(fail_msg)<EOL>json_dic["<STR_LIT>"] = [{<EOL>"<STR_LIT>": sample_id,<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT:value>": [fail_msg]<EOL>}]<EOL>report_fh.write(<EOL>json.dumps(json_dic, separators=("<STR_LIT:U+002C>", "<STR_LIT::>")))<EOL>status_fh.write("<STR_LIT>")<EOL>trim_fh.write("<STR_LIT>")<EOL>rep_fh.write("<STR_LIT>".format(sample_id, "<STR_LIT:U+002C>".join(f_cat)))<EOL>trep_fh.write("<STR_LIT>".format(sample_id))<EOL>return<EOL><DEDENT><DEDENT>logger.info("<STR_LIT>")<EOL><DEDENT>status_fh.write("<STR_LIT>")<EOL>rep_fh.write("<STR_LIT>".format(sample_id))<EOL>logger.info("<STR_LIT>")<EOL>optimal_trim = get_sample_trim(result_p1[<NUM_LIT:0>], result_p2[<NUM_LIT:0>])<EOL>logger.info("<STR_LIT>".format(optimal_trim))<EOL>trim_fh.write("<STR_LIT:{}>".format("<STR_LIT:U+0020>".join([str(x) for x in optimal_trim])))<EOL>trep_fh.write("<STR_LIT>".format(sample_id, optimal_trim[<NUM_LIT:0>],<EOL>optimal_trim[<NUM_LIT:1>]))<EOL>if json_dic:<EOL><INDENT>report_fh.write(json.dumps(json_dic, separators=("<STR_LIT:U+002C>", "<STR_LIT::>")))<EOL><DEDENT><DEDENT>

Main executor of the fastqc_report template.

    If the "--ignore-tests" option is present in the ``opts`` argument,
    the health check of the sample will be bypassed, and it will pass the
    check. This option is used in the first run of FastQC. In the second
    run (after filtering with trimmomatic) this option is not provided and
    the samples are submitted to a health check before proceeding in the
    pipeline.

    Parameters
    ----------
    sample_id : str
        Sample Identification string.
    result_p1 : list
        Two element list containing the path to the FastQC report files to
        the first FastQ pair.
        The first must be the nucleotide level report and the second the
        categorical report.
    result_p2: list
        Two element list containing the path to the FastQC report files to
        the second FastQ pair.
        The first must be the nucleotide level report and the second the
        categorical report.
    opts : list
        List of arbitrary options. See `Expected input`_.


@MainWrapper<EOL>def main(sample_id, assembly_file, coverage_bp_file=None):

logger.info("<STR_LIT>")<EOL>assembly_obj = Assembly(assembly_file, sample_id)<EOL>logger.info("<STR_LIT>")<EOL>assembly_obj.get_summary_stats("<STR_LIT>".format(sample_id))<EOL>size_dist = [len(x) for x in assembly_obj.contigs.values()]<EOL>json_dic = {<EOL>"<STR_LIT>": [{<EOL>"<STR_LIT>": sample_id,<EOL>"<STR_LIT:data>": [<EOL>{"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT:value>": assembly_obj.summary_info["<STR_LIT>"],<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT>": True},<EOL>{"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT:value>": assembly_obj.summary_info["<STR_LIT>"],<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT>": True},<EOL>]<EOL>}],<EOL>"<STR_LIT>": [{<EOL>"<STR_LIT>": sample_id,<EOL>"<STR_LIT:data>": {<EOL>"<STR_LIT>": size_dist<EOL>}<EOL>}]<EOL>}<EOL>if coverage_bp_file:<EOL><INDENT>try:<EOL><INDENT>window = <NUM_LIT><EOL>gc_sliding_data = assembly_obj.get_gc_sliding(window=window)<EOL>cov_sliding_data =assembly_obj.get_coverage_sliding(coverage_bp_file,<EOL>window=window)<EOL>total_bp = sum(<EOL>[sum(x) for x in assembly_obj.contig_coverage.values()]<EOL>)<EOL>json_dic["<STR_LIT>"][<NUM_LIT:0>]["<STR_LIT:data>"]["<STR_LIT>"] = {<EOL>"<STR_LIT>": gc_sliding_data,<EOL>"<STR_LIT>": cov_sliding_data,<EOL>"<STR_LIT>": window,<EOL>"<STR_LIT>": assembly_obj._get_window_labels(window),<EOL>"<STR_LIT>": os.path.basename(assembly_file)<EOL>}<EOL>json_dic["<STR_LIT>"][<NUM_LIT:0>]["<STR_LIT:data>"]["<STR_LIT>"] = total_bp<EOL><DEDENT>except:<EOL><INDENT>logger.error("<STR_LIT>"<EOL>"<STR_LIT:{}>".format(traceback.format_exc()))<EOL><DEDENT><DEDENT>with open("<STR_LIT>", "<STR_LIT:w>") as json_report:<EOL><INDENT>json_report.write(json.dumps(json_dic, separators=("<STR_LIT:U+002C>", "<STR_LIT::>")))<EOL><DEDENT>with open("<STR_LIT>", "<STR_LIT:w>") as status_fh:<EOL><INDENT>status_fh.write("<STR_LIT>")<EOL><DEDENT>

Main executor of the assembly_report template.

    Parameters
    ----------
    sample_id : str
        Sample Identification string.
    assembly_file : str
        Path to assembly file in Fasta format.


with open(assembly_file) as fh:<EOL><INDENT>header = None<EOL>logger.debug("<STR_LIT>".format(<EOL>assembly_file))<EOL>for line in fh:<EOL><INDENT>if not line.strip():<EOL><INDENT>continue<EOL><DEDENT>if line.startswith("<STR_LIT:>>"):<EOL><INDENT>header = line[<NUM_LIT:1>:].strip()<EOL>self.contigs[header] = []<EOL><DEDENT>else:<EOL><INDENT>self.contigs[header].append(line.strip())<EOL><DEDENT><DEDENT>self.contigs = OrderedDict(<EOL>(header, "<STR_LIT>".join(seq)) for header, seq in self.contigs.items())<EOL><DEDENT>

Parse an assembly file in fasta format.

        This is a Fasta parsing method that populates the
        :py:attr:`Assembly.contigs` attribute with data for each contig in the
         assembly.

        Parameters
        ----------
        assembly_file : str
            Path to the assembly fasta file.


contig_id = contig_str<EOL>try:<EOL><INDENT>contig_id = re.search("<STR_LIT>", contig_str).group(<NUM_LIT:1>)<EOL><DEDENT>except AttributeError:<EOL><INDENT>pass<EOL><DEDENT>try:<EOL><INDENT>contig_id = re.search("<STR_LIT>", contig_str).group(<NUM_LIT:1>)<EOL><DEDENT>except AttributeError:<EOL><INDENT>pass<EOL><DEDENT>return contig_id<EOL>

Tries to retrieve contig id. Returns the original string if it
        is unable to retrieve the id.

        Parameters
        ----------
        contig_str : str
            Full contig string (fasta header)

        Returns
        -------
        str
            Contig id


contig_size_list = []<EOL>self.summary_info["<STR_LIT>"] = len(self.contigs)<EOL>for contig_id, sequence in self.contigs.items():<EOL><INDENT>logger.debug("<STR_LIT>".format(contig_id))<EOL>contig_len = len(sequence)<EOL>contig_size_list.append(contig_len)<EOL>self.summary_info["<STR_LIT>"] += contig_len<EOL>self.summary_info["<STR_LIT>"].append(<EOL>sum(map(sequence.count, ["<STR_LIT>", "<STR_LIT:C>"])) / contig_len<EOL>)<EOL>self.summary_info["<STR_LIT>"] += sequence.count("<STR_LIT:N>")<EOL><DEDENT>logger.debug("<STR_LIT>")<EOL>self.summary_info["<STR_LIT>"] =sum(contig_size_list) / len(contig_size_list)<EOL>logger.debug("<STR_LIT>")<EOL>self.summary_info["<STR_LIT>"] =sum(self.summary_info["<STR_LIT>"]) / len(self.summary_info["<STR_LIT>"])<EOL>logger.debug("<STR_LIT>")<EOL>cum_size = <NUM_LIT:0><EOL>for l in sorted(contig_size_list, reverse=True):<EOL><INDENT>cum_size += l<EOL>if cum_size >= self.summary_info["<STR_LIT>"] / <NUM_LIT:2>:<EOL><INDENT>self.summary_info["<STR_LIT>"] = l<EOL>break<EOL><DEDENT><DEDENT>if output_csv:<EOL><INDENT>logger.debug("<STR_LIT>")<EOL>with open(output_csv, "<STR_LIT:w>") as fh:<EOL><INDENT>summary_line = "<STR_LIT>".format(<EOL>self.sample, "<STR_LIT:U+002C>".join(<EOL>[str(x) for x in self.summary_info.values()]))<EOL>fh.write(summary_line)<EOL><DEDENT><DEDENT>

Generates a CSV report with summary statistics about the assembly

        The calculated statistics are:

            - Number of contigs
            - Average contig size
            - N50
            - Total assembly length
            - Average GC content
            - Amount of missing data

        Parameters
        ----------
        output_csv: str
            Name of the output CSV file.


<EOL>if not self.summary_info:<EOL><INDENT>self.get_summary_stats()<EOL><DEDENT>c = <NUM_LIT:0><EOL>xbars = []<EOL>for contig, seq in self.contigs.items():<EOL><INDENT>contig_id = self._get_contig_id(contig)<EOL>self.contig_boundaries[contig_id] = [c, c + len(seq)]<EOL>c += len(seq)<EOL>xbars.append((contig_id, c, contig))<EOL><DEDENT>return xbars<EOL>

Returns the mapping between sliding window points and their contigs,
        and the x-axis position of contig

        Parameters
        ----------
        window : int
            Size of the window.

        Returns
        -------
        xbars : list
            The x-axis position of the ending for each contig.
        labels : list
            The x-axis labels for each data point in the sliding window


gc = sum(map(s.count, ["<STR_LIT:c>", "<STR_LIT:g>"]))<EOL>return gc / length<EOL>

Get proportion of GC from a string

        Parameters
        ----------
        s : str
            Arbitrary string

        Returns
        -------
        x : float
            GC proportion.


gc_res = []<EOL>complete_seq = "<STR_LIT>".join(self.contigs.values()).lower()<EOL>for i in range(<NUM_LIT:0>, len(complete_seq), window):<EOL><INDENT>seq_window = complete_seq[i:i + window]<EOL>gc_res.append(round(self._gc_prop(seq_window, len(seq_window)), <NUM_LIT:2>))<EOL><DEDENT>return gc_res<EOL>

Calculates a sliding window of the GC content for the assembly

        Returns
        -------
        gc_res : list
            List of GC proportion floats for each data point in the sliding
            window


with open(coverage_file) as fh:<EOL><INDENT>for line in fh:<EOL><INDENT>fields = line.strip().split()<EOL>header = fields[<NUM_LIT:0>]<EOL>coverage = int(fields[<NUM_LIT:2>])<EOL>if header not in self.contig_coverage:<EOL><INDENT>self.contig_coverage[header] = [coverage]<EOL><DEDENT>else:<EOL><INDENT>self.contig_coverage[header].append(coverage)<EOL><DEDENT><DEDENT><DEDENT>

Parameters
----------
coverage_file

Returns
-------


def get_coverage_sliding(self, coverage_file, window=<NUM_LIT>):

if not self.contig_coverage:<EOL><INDENT>self._get_coverage_from_file(coverage_file)<EOL><DEDENT>cov_res = []<EOL>complete_cov = [x for y in self.contig_coverage.values() for x in y]<EOL>for i in range(<NUM_LIT:0>, len(complete_cov), window):<EOL><INDENT>cov_window = complete_cov[i:i + window]<EOL>cov_res.append(int(sum(cov_window) / len(cov_window)))<EOL><DEDENT>return cov_res<EOL>

Parameters
----------
coverage_file : str
    Path to file containing the coverage info at the per-base level
    (as generated by samtools depth)
window : int
    Size of sliding window

Returns
-------


def send_to_output(master_dict, mash_output, sample_id, assembly_file):

plot_dict = {}<EOL>if master_dict:<EOL><INDENT>out_file = open("<STR_LIT>".format(<EOL>"<STR_LIT>".join(mash_output.split("<STR_LIT:.>")[<NUM_LIT:0>])), "<STR_LIT:w>")<EOL>out_file.write(json.dumps(master_dict))<EOL>out_file.close()<EOL>for k,v in master_dict.items():<EOL><INDENT>if not v[<NUM_LIT:2>] in plot_dict:<EOL><INDENT>plot_dict[v[<NUM_LIT:2>]] = [k]<EOL><DEDENT>else:<EOL><INDENT>plot_dict[v[<NUM_LIT:2>]].append(k)<EOL><DEDENT><DEDENT>number_hits = len(master_dict)<EOL><DEDENT>else:<EOL><INDENT>number_hits = <NUM_LIT:0><EOL><DEDENT>json_dic = {<EOL>"<STR_LIT>": [{<EOL>"<STR_LIT>": sample_id,<EOL>"<STR_LIT:data>": [{<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT>": master_dict,<EOL>"<STR_LIT:value>": number_hits<EOL>}]<EOL>}],<EOL>"<STR_LIT>": [{<EOL>"<STR_LIT>": sample_id,<EOL>"<STR_LIT:data>": {<EOL>"<STR_LIT>": plot_dict<EOL>},<EOL>"<STR_LIT>": assembly_file<EOL>}]<EOL>}<EOL>with open("<STR_LIT>", "<STR_LIT:w>") as json_report:<EOL><INDENT>json_report.write(json.dumps(json_dic, separators=("<STR_LIT:U+002C>", "<STR_LIT::>")))<EOL><DEDENT>

Send dictionary to output json file
    This function sends master_dict dictionary to a json file if master_dict is
    populated with entries, otherwise it won't create the file

    Parameters
    ----------
    master_dict: dict
        dictionary that stores all entries for a specific query sequence
        in multi-fasta given to mash dist as input against patlas database
    last_seq: str
        string that stores the last sequence that was parsed before writing to
        file and therefore after the change of query sequence between different
        rows on the input file
    mash_output: str
        the name/path of input file to main function, i.e., the name/path of
        the mash dist output txt file.
    sample_id: str
        The name of the sample being parse to .report.json file

    Returns
    -------


@MainWrapper<EOL>def main(mash_output, hash_cutoff, sample_id, assembly_file):

input_f = open(mash_output, "<STR_LIT:r>")<EOL>master_dict = {}<EOL>for line in input_f:<EOL><INDENT>tab_split = line.split("<STR_LIT:\t>")<EOL>current_seq = tab_split[<NUM_LIT:1>].strip()<EOL>ref_accession = "<STR_LIT:_>".join(tab_split[<NUM_LIT:0>].strip().split("<STR_LIT:_>")[<NUM_LIT:0>:<NUM_LIT:3>])<EOL>mash_dist = tab_split[<NUM_LIT:2>].strip()<EOL>hashes_list = tab_split[-<NUM_LIT:1>].strip().split("<STR_LIT:/>")<EOL>perc_hashes = float(hashes_list[<NUM_LIT:0>]) / float(hashes_list[<NUM_LIT:1>])<EOL>if ref_accession in master_dict.keys():<EOL><INDENT>current_seq += "<STR_LIT>".format(master_dict[ref_accession][-<NUM_LIT:1>])<EOL><DEDENT>if perc_hashes > float(hash_cutoff):<EOL><INDENT>master_dict[ref_accession] = [<EOL>round(<NUM_LIT:1> - float(mash_dist), <NUM_LIT:2>),<EOL>round(perc_hashes, <NUM_LIT:2>),<EOL>current_seq<EOL>]<EOL><DEDENT><DEDENT>send_to_output(master_dict, mash_output, sample_id, assembly_file)<EOL>

Main function that allows to dump a mash dist txt file to a json file

Parameters
----------
mash_output: str
    A string with the input file.
hash_cutoff: str
    the percentage cutoff for the percentage of shared hashes between query
    and plasmid in database that is allowed for the plasmid to be reported
    to the results outputs
sample_id: str
    The name of the sample.


logger.debug("<STR_LIT>".format(kmer_opt))<EOL>if kmer_opt == "<STR_LIT>":<EOL><INDENT>if max_read_len >= <NUM_LIT>:<EOL><INDENT>kmers = [<NUM_LIT>, <NUM_LIT>, <NUM_LIT>, <NUM_LIT>, <NUM_LIT>]<EOL><DEDENT>else:<EOL><INDENT>kmers = [<NUM_LIT>, <NUM_LIT>, <NUM_LIT>, <NUM_LIT>, <NUM_LIT>]<EOL><DEDENT>logger.debug("<STR_LIT>"<EOL>"<STR_LIT>".format(max_read_len, kmers))<EOL><DEDENT>elif len(kmer_opt.split()) > <NUM_LIT:1>:<EOL><INDENT>kmers = kmer_opt.split()<EOL>logger.debug("<STR_LIT>".format(kmers))<EOL><DEDENT>else:<EOL><INDENT>kmers = []<EOL>logger.debug("<STR_LIT>"<EOL>"<STR_LIT>")<EOL><DEDENT>return kmers<EOL>

Returns a kmer list based on the provided kmer option and max read len.

    Parameters
    ----------
    kmer_opt : str
        The k-mer option. Can be either ``'auto'``, ``'default'`` or a
        sequence of space separated integers, ``'23, 45, 67'``.
    max_read_len : int
        The maximum read length of the current sample.

    Returns
    -------
    kmers : list
        List of k-mer values that will be provided to Spades.


for fq in fastq:<EOL><INDENT>rp = os.path.realpath(fq)<EOL>logger.debug("<STR_LIT>".format(rp))<EOL>if re.match("<STR_LIT>", rp):<EOL><INDENT>os.remove(rp)<EOL><DEDENT><DEDENT>

Cleans the temporary fastq files. If they are symlinks, the link
source is removed

Parameters
----------
fastq : list
    List of fastq files.


@MainWrapper<EOL>def main(sample_id, fastq_pair, max_len, kmer, opts, clear, disable_rr):

logger.info("<STR_LIT>")<EOL>min_coverage, min_kmer_coverage = opts<EOL>logger.info("<STR_LIT>")<EOL>kmers = set_kmers(kmer, max_len)<EOL>logger.info("<STR_LIT>".format(kmers))<EOL>cli = [<EOL>"<STR_LIT>",<EOL>"<STR_LIT>",<EOL>"<STR_LIT>",<EOL>"<STR_LIT>",<EOL>"<STR_LIT>",<EOL>"<STR_LIT>",<EOL>min_coverage,<EOL>"<STR_LIT>",<EOL>"<STR_LIT:.>"<EOL>]<EOL>if kmers:<EOL><INDENT>cli += ["<STR_LIT>".format("<STR_LIT:U+002C>".join([str(x) for x in kmers]))]<EOL><DEDENT>cli += [<EOL>"<STR_LIT>",<EOL>fastq_pair[<NUM_LIT:0>],<EOL>"<STR_LIT>",<EOL>fastq_pair[<NUM_LIT:1>]<EOL>]<EOL>if disable_rr == '<STR_LIT:true>':<EOL><INDENT>cli += ['<STR_LIT>']<EOL><DEDENT>logger.debug("<STR_LIT>".format(cli))<EOL>p = subprocess.Popen(cli, stdout=PIPE, stderr=PIPE)<EOL>stdout, stderr = p.communicate()<EOL>try:<EOL><INDENT>stderr = stderr.decode("<STR_LIT:utf8>")<EOL>stdout = stdout.decode("<STR_LIT:utf8>")<EOL><DEDENT>except (UnicodeDecodeError, AttributeError):<EOL><INDENT>stderr = str(stderr)<EOL>stdout = str(stdout)<EOL><DEDENT>logger.info("<STR_LIT>"<EOL>"<STR_LIT>".format(stdout))<EOL>logger.info("<STR_LIT>"<EOL>"<STR_LIT>".format(stderr))<EOL>logger.info("<STR_LIT>".format(<EOL>p.returncode))<EOL>with open("<STR_LIT>", "<STR_LIT:w>") as fh:<EOL><INDENT>if p.returncode != <NUM_LIT:0>:<EOL><INDENT>fh.write("<STR_LIT:error>")<EOL>sys.exit(p.returncode)<EOL><DEDENT>else:<EOL><INDENT>fh.write("<STR_LIT>")<EOL><DEDENT><DEDENT>if "<STR_LIT>" in fastq_pair[<NUM_LIT:0>]:<EOL><INDENT>sample_id += "<STR_LIT>"<EOL><DEDENT>info = __get_version_spades()<EOL>assembly_file = "<STR_LIT>".format(<EOL>sample_id, info["<STR_LIT:version>"].replace("<STR_LIT:.>", "<STR_LIT>"))<EOL>os.rename("<STR_LIT>", assembly_file)<EOL>logger.info("<STR_LIT>".format(assembly_file))<EOL>if clear == "<STR_LIT:true>" and os.path.exists(assembly_file):<EOL><INDENT>clean_up(fastq_pair)<EOL><DEDENT>

Main executor of the spades template.

    Parameters
    ----------
    sample_id : str
        Sample Identification string.
    fastq_pair : list
        Two element list containing the paired FastQ files.
    max_len : int
        Maximum read length. This value is determined in
        :py:class:`templates.integrity_coverage`
    kmer : str
        Can be either ``'auto'``, ``'default'`` or a
        sequence of space separated integers, ``'23, 45, 67'``.
    opts : List of options for spades execution. See above.
    clear : str
        Can be either 'true' or 'false'. If 'true', the input fastq files will
        be removed at the end of the run, IF they are in the working directory
    disable_rr : str
        Can either be 'true' or 'false'. If 'true', disables repeat resolution
        stage of assembling


@MainWrapper<EOL>def main(sample_id, fastq_pair, max_len, kmer, clear):

logger.info("<STR_LIT>")<EOL>logger.info("<STR_LIT>")<EOL>kmers = set_kmers(kmer, max_len)<EOL>logger.info("<STR_LIT>".format(kmers))<EOL>cli = [<EOL>"<STR_LIT>",<EOL>"<STR_LIT>",<EOL>"<STR_LIT>",<EOL>"<STR_LIT>",<EOL>"<STR_LIT>",<EOL>"<STR_LIT:.>"<EOL>]<EOL>if kmers:<EOL><INDENT>cli += ["<STR_LIT>".format("<STR_LIT:U+002C>".join([str(x) for x in kmers]))]<EOL><DEDENT>cli += [<EOL>"<STR_LIT>",<EOL>fastq_pair[<NUM_LIT:0>],<EOL>"<STR_LIT>",<EOL>fastq_pair[<NUM_LIT:1>]<EOL>]<EOL>logger.debug("<STR_LIT>".format(cli))<EOL>p = subprocess.Popen(cli, stdout=PIPE, stderr=PIPE)<EOL>stdout, stderr = p.communicate()<EOL>try:<EOL><INDENT>stderr = stderr.decode("<STR_LIT:utf8>")<EOL>stdout = stdout.decode("<STR_LIT:utf8>")<EOL><DEDENT>except (UnicodeDecodeError, AttributeError):<EOL><INDENT>stderr = str(stderr)<EOL>stdout = str(stdout)<EOL><DEDENT>logger.info("<STR_LIT>"<EOL>"<STR_LIT>".format(stdout))<EOL>logger.info("<STR_LIT>"<EOL>"<STR_LIT>".format(stderr))<EOL>logger.info("<STR_LIT>".format(<EOL>p.returncode))<EOL>with open("<STR_LIT>", "<STR_LIT:w>") as fh:<EOL><INDENT>if p.returncode != <NUM_LIT:0>:<EOL><INDENT>fh.write("<STR_LIT:error>")<EOL>return<EOL><DEDENT>else:<EOL><INDENT>fh.write("<STR_LIT>")<EOL><DEDENT><DEDENT>if "<STR_LIT>" in fastq_pair[<NUM_LIT:0>]:<EOL><INDENT>sample_id += "<STR_LIT>"<EOL><DEDENT>assembly_file = "<STR_LIT>".format(<EOL>sample_id)<EOL>os.rename("<STR_LIT>", assembly_file)<EOL>logger.info("<STR_LIT>".format(assembly_file))<EOL>if clear == "<STR_LIT:true>" and os.path.exists(assembly_file):<EOL><INDENT>clean_up(fastq_pair)<EOL><DEDENT>

Main executor of the spades template.

    Parameters
    ----------
    sample_id : str
        Sample Identification string.
    fastq_pair : list
        Two element list containing the paired FastQ files.
    max_len : int
        Maximum read length. This value is determined in
        :py:class:`templates.integrity_coverage`
    kmer : str
        Can be either ``'auto'``, ``'default'`` or a
        sequence of space separated integers, ``'23, 45, 67'``.


<EOL>coverage_dict = OrderedDict()<EOL>total_cov = <NUM_LIT:0><EOL>with open(coverage_file) as fh:<EOL><INDENT>for line in fh:<EOL><INDENT>contig, cov = line.strip().split()<EOL>coverage_dict[contig] = {"<STR_LIT>": int(cov)}<EOL>total_cov += int(cov)<EOL>logger.debug("<STR_LIT>"<EOL>"<STR_LIT>".format(contig, cov))<EOL><DEDENT><DEDENT>return coverage_dict, total_cov<EOL>

Parses a file with coverage information into objects.

    This function parses a TSV file containing coverage results for
    all contigs in a given assembly and will build an ``OrderedDict``
    with the information about their coverage and length.  The length
    information is actually gathered from the contig header using a
    regular expression that assumes the usual header produced by Spades::

        contig_len = int(re.search("length_(.+?)_", line).group(1))

    Parameters
    ----------
    coverage_file : str
        Path to TSV file containing the coverage results.

    Returns
    -------
    coverage_dict : OrderedDict
        Contains the coverage and length information for each contig.
    total_size : int
        Total size of the assembly in base pairs.
    total_cov : int
        Sum of coverage values across all contigs.


def filter_assembly(assembly_file, minimum_coverage, coverage_info,<EOL>output_file):

<EOL>write_flag = False<EOL>with open(assembly_file) as fh, open(output_file, "<STR_LIT:w>") as out_fh:<EOL><INDENT>for line in fh:<EOL><INDENT>if line.startswith("<STR_LIT:>>"):<EOL><INDENT>write_flag = False<EOL>header = line.strip()[<NUM_LIT:1>:]<EOL>contig_cov = coverage_info[header]["<STR_LIT>"]<EOL>if contig_cov >= minimum_coverage:<EOL><INDENT>write_flag = True<EOL>out_fh.write(line)<EOL><DEDENT><DEDENT>elif write_flag:<EOL><INDENT>out_fh.write(line)<EOL><DEDENT><DEDENT><DEDENT>

Generates a filtered assembly file.

    This function generates a filtered assembly file based on an original
    assembly and a minimum coverage threshold.

    Parameters
    ----------
    assembly_file : str
        Path to original assembly file.
    minimum_coverage : int or float
        Minimum coverage required for a contig to pass the filter.
    coverage_info : OrderedDict or dict
        Dictionary containing the coverage information for each contig.
    output_file : str
        Path where the filtered assembly file will be generated.


def filter_bam(coverage_info, bam_file, min_coverage, output_bam):

<EOL>contig_list = [x for x, vals in coverage_info.items()<EOL>if vals["<STR_LIT>"] >= min_coverage]<EOL>cli = [<EOL>"<STR_LIT>",<EOL>"<STR_LIT>",<EOL>"<STR_LIT>",<EOL>"<STR_LIT>",<EOL>"<STR_LIT:4>",<EOL>"<STR_LIT>",<EOL>output_bam,<EOL>"<STR_LIT>",<EOL>"<STR_LIT:1>",<EOL>bam_file,<EOL>]<EOL>cli += contig_list<EOL>logger.debug("<STR_LIT>".format(<EOL>cli))<EOL>p = subprocess.Popen(cli, stdout=PIPE, stderr=PIPE)<EOL>stdout, stderr = p.communicate()<EOL>try:<EOL><INDENT>stderr = stderr.decode("<STR_LIT:utf8>")<EOL>stdout = stdout.decode("<STR_LIT:utf8>")<EOL><DEDENT>except (UnicodeDecodeError, AttributeError):<EOL><INDENT>stderr = str(stderr)<EOL>stdout = str(stdout)<EOL><DEDENT>logger.info("<STR_LIT>"<EOL>"<STR_LIT>".format(stdout))<EOL>logger.info("<STR_LIT>"<EOL>"<STR_LIT>".format(stderr))<EOL>logger.info("<STR_LIT>".format(<EOL>p.returncode))<EOL>if not p.returncode:<EOL><INDENT>cli = [<EOL>"<STR_LIT>",<EOL>"<STR_LIT:index>",<EOL>output_bam<EOL>]<EOL>logger.debug("<STR_LIT>"<EOL>"<STR_LIT:{}>".format(cli))<EOL>p = subprocess.Popen(cli, stdout=PIPE, stderr=PIPE)<EOL>stdout, stderr = p.communicate()<EOL>try:<EOL><INDENT>stderr = stderr.decode("<STR_LIT:utf8>")<EOL>stdout = stdout.decode("<STR_LIT:utf8>")<EOL><DEDENT>except (UnicodeDecodeError, AttributeError):<EOL><INDENT>stderr = str(stderr)<EOL>stdout = str(stdout)<EOL><DEDENT>logger.info("<STR_LIT>"<EOL>"<STR_LIT>".format(<EOL>stdout))<EOL>logger.info("<STR_LIT>"<EOL>"<STR_LIT>".format(<EOL>stderr))<EOL>logger.info("<STR_LIT>".format(<EOL>p.returncode))<EOL><DEDENT>

Uses Samtools to filter a BAM file according to minimum coverage

    Provided with a minimum coverage value, this function will use Samtools
    to filter a BAM file. This is performed to apply the same filter to
    the BAM file as the one applied to the assembly file in
    :py:func:`filter_assembly`.

    Parameters
    ----------
    coverage_info : OrderedDict or dict
        Dictionary containing the coverage information for each contig.
    bam_file : str
        Path to the BAM file.
    min_coverage : int
        Minimum coverage required for a contig to pass the filter.
    output_bam : str
        Path to the generated filtered BAM file.


def check_filtered_assembly(coverage_info, coverage_bp, minimum_coverage,<EOL>genome_size, contig_size, max_contigs,<EOL>sample_id):

<EOL>assembly_len = sum([v for k, v in contig_size.items()<EOL>if coverage_info[k]["<STR_LIT>"] >= minimum_coverage])<EOL>logger.debug("<STR_LIT>"<EOL>"<STR_LIT>".format(minimum_coverage, assembly_len))<EOL>ncontigs = len([x for x in coverage_info.values()<EOL>if x["<STR_LIT>"] >= minimum_coverage])<EOL>logger.debug("<STR_LIT>".format(ncontigs))<EOL>filtered_contigs = [k for k, v in coverage_info.items()<EOL>if v["<STR_LIT>"] >= minimum_coverage]<EOL>logger.debug("<STR_LIT>"<EOL>"<STR_LIT>".format(minimum_coverage, filtered_contigs))<EOL>total_assembled_bp = sum([sum(coverage_bp[x]) for x in filtered_contigs<EOL>if x in coverage_bp])<EOL>logger.debug("<STR_LIT>"<EOL>"<STR_LIT:{}>".format(total_assembled_bp))<EOL>warnings = []<EOL>fails = []<EOL>health = True<EOL>with open("<STR_LIT>", "<STR_LIT:w>") as warn_fh,open("<STR_LIT>", "<STR_LIT:w>") as json_report:<EOL><INDENT>logger.debug("<STR_LIT>".format(<EOL>assembly_len))<EOL>if assembly_len > genome_size * <NUM_LIT> * <NUM_LIT>:<EOL><INDENT>warn_msg = "<STR_LIT>""<STR_LIT>".format(<EOL>assembly_len)<EOL>logger.warning(warn_msg)<EOL>warn_fh.write(warn_msg)<EOL>fails.append("<STR_LIT>".format(assembly_len))<EOL><DEDENT>logger.debug("<STR_LIT>".format(<EOL>len(coverage_info)))<EOL>contig_threshold = max_contigs * genome_size / <NUM_LIT><EOL>if ncontigs > contig_threshold:<EOL><INDENT>warn_msg = "<STR_LIT>""<STR_LIT>".format(<EOL>ncontigs, round(contig_threshold, <NUM_LIT:1>))<EOL>logger.warning(warn_msg)<EOL>warn_fh.write(warn_msg)<EOL>warnings.append(warn_msg)<EOL><DEDENT>if assembly_len < genome_size * <NUM_LIT> * <NUM_LIT>:<EOL><INDENT>warn_msg = "<STR_LIT>""<STR_LIT>".format(<EOL>assembly_len)<EOL>logger.warning(warn_msg)<EOL>warn_fh.write(warn_msg)<EOL>fails.append("<STR_LIT>".format(assembly_len))<EOL>assembly_len = sum([v for v in contig_size.values()])<EOL>total_assembled_bp = sum(<EOL>[sum(coverage_bp[x]) for x in coverage_info if x in<EOL>coverage_bp])<EOL>logger.debug("<STR_LIT>"<EOL>"<STR_LIT:{}>".format(assembly_len))<EOL>logger.debug("<STR_LIT>"<EOL>"<STR_LIT>".format(total_assembled_bp))<EOL>health = False<EOL><DEDENT>json_dic = {<EOL>"<STR_LIT>": [{<EOL>"<STR_LIT>": sample_id,<EOL>"<STR_LIT:data>": {<EOL>"<STR_LIT>": total_assembled_bp<EOL>}<EOL>}]<EOL>}<EOL>if warnings:<EOL><INDENT>json_dic["<STR_LIT>"] = [{<EOL>"<STR_LIT>": sample_id,<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT:value>": warnings<EOL>}]<EOL><DEDENT>if fails:<EOL><INDENT>json_dic["<STR_LIT>"] = [{<EOL>"<STR_LIT>": sample_id,<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT:value>": [fails]<EOL>}]<EOL><DEDENT>json_report.write(json.dumps(json_dic, separators=("<STR_LIT:U+002C>", "<STR_LIT::>")))<EOL><DEDENT>return health<EOL>

Checks whether a filtered assembly passes a size threshold

    Given a minimum coverage threshold, this function evaluates whether an
    assembly will pass the minimum threshold of ``genome_size * 1e6 * 0.8``,
    which means 80% of the expected genome size or the maximum threshold
    of ``genome_size * 1e6 * 1.5``, which means 150% of the expected genome
    size. It will issue a warning if any of these thresholds is crossed.
    In the case of an expected genome size below 80% it will return False.

    Parameters
    ----------
    coverage_info : OrderedDict or dict
        Dictionary containing the coverage information for each contig.
    coverage_bp : dict
        Dictionary containing the per base coverage information for each
        contig. Used to determine the total number of base pairs in the
        final assembly.
    minimum_coverage : int
        Minimum coverage required for a contig to pass the filter.
    genome_size : int
        Expected genome size.
    contig_size : dict
        Dictionary with the len of each contig. Contig headers as keys and
        the corresponding lenght as values.
    max_contigs : int
        Maximum threshold for contig number. A warning is issued if this
        threshold is crossed.
    sample_id : str
        Id or name of the current sample

    Returns
    -------
    x : bool
        True if the filtered assembly size is higher than 80% of the
        expected genome size.


contig_coverage = {}<EOL>with open(coverage_file) as fh:<EOL><INDENT>for line in fh:<EOL><INDENT>fields = line.strip().split()<EOL>header = fields[<NUM_LIT:0>]<EOL>coverage = int(fields[<NUM_LIT:2>])<EOL>if header not in contig_coverage:<EOL><INDENT>contig_coverage[header] = [coverage]<EOL><DEDENT>else:<EOL><INDENT>contig_coverage[header].append(coverage)<EOL><DEDENT><DEDENT><DEDENT>return contig_coverage<EOL>


def evaluate_min_coverage(coverage_opt, assembly_coverage, assembly_size):

if coverage_opt == "<STR_LIT>":<EOL><INDENT>min_coverage = (assembly_coverage / assembly_size) * <NUM_LIT><EOL>logger.info("<STR_LIT>"<EOL>"<STR_LIT:{}>".format(min_coverage))<EOL>if min_coverage < <NUM_LIT:10>:<EOL><INDENT>logger.info("<STR_LIT>"<EOL>"<STR_LIT>")<EOL>min_coverage = <NUM_LIT:10><EOL><DEDENT><DEDENT>else:<EOL><INDENT>min_coverage = int(coverage_opt)<EOL>logger.info("<STR_LIT>".format(<EOL>min_coverage))<EOL><DEDENT>return min_coverage<EOL>

Evaluates the minimum coverage threshold from the value provided in
    the coverage_opt.

    Parameters
    ----------
    coverage_opt : str or int or float
        If set to "auto" it will try to automatically determine the coverage
        to 1/3 of the assembly size, to a minimum value of 10. If it set
        to a int or float, the specified value will be used.
    assembly_coverage : int or float
        The average assembly coverage for a genome assembly. This value
        is retrieved by the `:py:func:parse_coverage_table` function.
    assembly_size : int
        The size of the genome assembly. This value is retrieved by the
        `py:func:get_assembly_size` function.

    Returns
    -------
    x: int
        Minimum coverage threshold.


assembly_size = <NUM_LIT:0><EOL>contig_size = {}<EOL>header = "<STR_LIT>"<EOL>with open(assembly_file) as fh:<EOL><INDENT>for line in fh:<EOL><INDENT>if line.strip() == "<STR_LIT>":<EOL><INDENT>continue<EOL><DEDENT>if line.startswith("<STR_LIT:>>"):<EOL><INDENT>header = line.strip()[<NUM_LIT:1>:]<EOL>contig_size[header] = <NUM_LIT:0><EOL><DEDENT>else:<EOL><INDENT>line_len = len(line.strip())<EOL>assembly_size += line_len<EOL>contig_size[header] += line_len<EOL><DEDENT><DEDENT><DEDENT>return assembly_size, contig_size<EOL>

Returns the number of nucleotides and the size per contig for the
    provided assembly file path

    Parameters
    ----------
    assembly_file : str
        Path to assembly file.

    Returns
    -------
    assembly_size : int
        Size of the assembly in nucleotides
    contig_size : dict
        Length of each contig (contig name as key and length as value)


@MainWrapper<EOL>def main(sample_id, assembly_file, coverage_file, coverage_bp_file, bam_file,<EOL>opts, gsize):

min_assembly_coverage, max_contigs = opts<EOL>logger.info("<STR_LIT>")<EOL>logger.info("<STR_LIT>")<EOL>coverage_info, a_cov = parse_coverage_table(coverage_file)<EOL>a_size, contig_size = get_assembly_size(assembly_file)<EOL>logger.info("<STR_LIT>"<EOL>"<STR_LIT>".format(a_size, a_cov))<EOL>logger.info("<STR_LIT>")<EOL>coverage_bp_data = get_coverage_from_file(coverage_bp_file)<EOL>min_coverage = evaluate_min_coverage(min_assembly_coverage, a_cov, a_size)<EOL>filtered_assembly = "<STR_LIT>".format(<EOL>os.path.splitext(assembly_file)[<NUM_LIT:0>])<EOL>filtered_bam = "<STR_LIT>"<EOL>logger.info("<STR_LIT>")<EOL>if check_filtered_assembly(coverage_info, coverage_bp_data, min_coverage,<EOL>gsize, contig_size, int(max_contigs),<EOL>sample_id):<EOL><INDENT>logger.info("<STR_LIT>")<EOL>logger.info("<STR_LIT>")<EOL>filter_assembly(assembly_file, min_coverage, coverage_info,<EOL>filtered_assembly)<EOL>logger.info("<STR_LIT>")<EOL>filter_bam(coverage_info, bam_file, min_coverage, filtered_bam)<EOL><DEDENT>else:<EOL><INDENT>shutil.copy(assembly_file, filtered_assembly)<EOL>shutil.copy(bam_file, filtered_bam)<EOL>shutil.copy(bam_file + "<STR_LIT>", filtered_bam + "<STR_LIT>")<EOL><DEDENT>with open("<STR_LIT>", "<STR_LIT:w>") as status_fh:<EOL><INDENT>status_fh.write("<STR_LIT>")<EOL><DEDENT>

Main executor of the process_assembly_mapping template.

    Parameters
    ----------
    sample_id : str
        Sample Identification string.
    assembly_file : str
        Path to assembly file in Fasta format.
    coverage_file : str
        Path to TSV file with coverage information for each contig.
    coverage_bp_file : str
        Path to TSV file with coverage information for each base.
    bam_file : str
        Path to BAM file.
    opts : list
        List of options for processing assembly mapping.
    gsize : int
        Expected genome size


<EOL>file_correspondence = {}<EOL>for infile in list_of_jsons:<EOL><INDENT>file_dict = json.load(open(infile))<EOL>file_correspondence[infile] = file_dict<EOL><DEDENT>json_dict = {}<EOL>for accession in list(file_correspondence.values())[<NUM_LIT:0>]:<EOL><INDENT>if all([True if accession in f_dict else False<EOL>for f_dict in file_correspondence.values()]):<EOL><INDENT>accession_dict = {}<EOL>for infile in file_correspondence.keys():<EOL><INDENT>accession_dict[infile] = file_correspondence[infile][accession]<EOL><DEDENT>json_dict[accession] = accession_dict<EOL><DEDENT><DEDENT>out_file = open("<STR_LIT>".format(<EOL>list_of_jsons[<NUM_LIT:0>].split("<STR_LIT:.>")[<NUM_LIT:0>].split("<STR_LIT:_>")[-<NUM_LIT:1>]), "<STR_LIT:w>")<EOL>out_file.write(json.dumps(json_dict))<EOL>out_file.close()<EOL>json_dic = {<EOL>"<STR_LIT>": json_dict<EOL>}<EOL>with open("<STR_LIT>", "<STR_LIT:w>") as json_report:<EOL><INDENT>json_report.write(json.dumps(json_dic, separators=("<STR_LIT:U+002C>", "<STR_LIT::>")))<EOL><DEDENT>

Parameters
----------
list_of_jsons: list
    A list of files provided by fullConsensus process provided by nextflow


@MainWrapper<EOL>def main(sample_id, assembly_file, gsize, opts, assembler):

logger.info("<STR_LIT>")<EOL>warnings = []<EOL>fails = "<STR_LIT>"<EOL>min_contig_len, min_kmer_cov, max_contigs = [int(x) for x in opts]<EOL>logger.debug("<STR_LIT>".format(<EOL>min_contig_len))<EOL>logger.debug("<STR_LIT>".format(min_kmer_cov))<EOL>logger.info("<STR_LIT>")<EOL>assembly_obj = Assembly(assembly_file, min_contig_len, min_kmer_cov,<EOL>sample_id)<EOL>with open("<STR_LIT>", "<STR_LIT:w>") as warn_fh:<EOL><INDENT>t_80 = gsize * <NUM_LIT> * <NUM_LIT><EOL>t_150 = gsize * <NUM_LIT> * <NUM_LIT><EOL>assembly_len = assembly_obj.get_assembly_length()<EOL>logger.debug("<STR_LIT>".format(assembly_len))<EOL>if assembly_len < t_80:<EOL><INDENT>logger.warning("<STR_LIT>"<EOL>"<STR_LIT>"<EOL>"<STR_LIT>"<EOL>"<STR_LIT>".format(assembly_len))<EOL>assembly_obj.filter_contigs(*[<EOL>["<STR_LIT>", "<STR_LIT>", min_contig_len]<EOL>])<EOL>assembly_len = assembly_obj.get_assembly_length()<EOL>logger.debug("<STR_LIT>"<EOL>"<STR_LIT:{}>".format(assembly_len))<EOL>if assembly_len < t_80:<EOL><INDENT>warn_msg = "<STR_LIT>""<STR_LIT>".format(<EOL>assembly_len)<EOL>logger.warning(warn_msg)<EOL>warn_fh.write(warn_msg)<EOL>fails = warn_msg<EOL><DEDENT><DEDENT>if assembly_len > t_150:<EOL><INDENT>warn_msg = "<STR_LIT>""<STR_LIT>".format(<EOL>assembly_len)<EOL>logger.warning(warn_msg)<EOL>warn_fh.write(warn_msg)<EOL>fails = warn_msg<EOL><DEDENT>logger.debug("<STR_LIT>".format(<EOL>len(assembly_obj.contigs)))<EOL>contig_threshold = (max_contigs * gsize) / <NUM_LIT><EOL>if len(assembly_obj.contigs) > contig_threshold:<EOL><INDENT>warn_msg = "<STR_LIT>""<STR_LIT>".format(<EOL>len(assembly_obj.contigs),<EOL>max_contigs,<EOL>round(contig_threshold, <NUM_LIT:1>))<EOL>logger.warning(warn_msg)<EOL>warn_fh.write(warn_msg)<EOL>warnings.append(warn_msg)<EOL><DEDENT><DEDENT>logger.debug("<STR_LIT>".format(<EOL>"<STR_LIT>".format(assembly_file)))<EOL>assembly_obj.write_assembly("<STR_LIT>".format(<EOL>os.path.splitext(assembly_file)[<NUM_LIT:0>]))<EOL>output_report = "<STR_LIT>".format(sample_id)<EOL>assembly_obj.write_report(output_report)<EOL>with open("<STR_LIT>", "<STR_LIT:w>") as json_report:<EOL><INDENT>json_dic = {<EOL>"<STR_LIT>": [{<EOL>"<STR_LIT>": sample_id,<EOL>"<STR_LIT:data>": [<EOL>{"<STR_LIT>": "<STR_LIT>".format(assembler),<EOL>"<STR_LIT:value>": len(assembly_obj.contigs),<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT>": True},<EOL>{"<STR_LIT>": "<STR_LIT>".format(assembler),<EOL>"<STR_LIT:value>": assembly_len,<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT>": True}<EOL>]<EOL>}],<EOL>}<EOL>if warnings:<EOL><INDENT>json_dic["<STR_LIT>"] = [{<EOL>"<STR_LIT>": sample_id,<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT:value>": warnings<EOL>}]<EOL><DEDENT>if fails:<EOL><INDENT>json_dic["<STR_LIT>"] = [{<EOL>"<STR_LIT>": sample_id,<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT:value>": [fails]<EOL>}]<EOL><DEDENT>json_report.write(json.dumps(json_dic, separators=("<STR_LIT:U+002C>", "<STR_LIT::>")))<EOL><DEDENT>with open("<STR_LIT>", "<STR_LIT:w>") as status_fh:<EOL><INDENT>status_fh.write("<STR_LIT>")<EOL><DEDENT>

Main executor of the process_spades template.

    Parameters
    ----------
    sample_id : str
        Sample Identification string.
    assembly_file : str
        Path to the assembly file generated by Spades.
    gsize : int
        Estimate of genome size.
    opts : list
        List of options for processing spades assembly.
    assembler : str
        Name of the assembler, for logging purposes


cov = None<EOL>for i in header_str.split("<STR_LIT:_>")[::-<NUM_LIT:1>]:<EOL><INDENT>try:<EOL><INDENT>cov = float(i)<EOL>break<EOL><DEDENT>except ValueError:<EOL><INDENT>continue<EOL><DEDENT><DEDENT>return cov<EOL>

Attempts to retrieve the coverage value from the header string.

        It splits the header by "_" and then screens the list backwards in
        search of the first float value. This will be interpreted as the
        coverage value. If it cannot find a float value, it returns None.
        This search methodology is based on the strings of assemblers
        like spades and skesa that put the mean kmer coverage for each
        contig in its corresponding fasta header.

        Parameters
        ----------
        header_str : str
            String

        Returns
        -------
        float or None
            The coverage value for the contig. None if it cannot find the
            value in the provide string.


<EOL>seq_temp = []<EOL>contig_id = <NUM_LIT:0><EOL>cov, header = None, None<EOL>with open(assembly_file) as fh:<EOL><INDENT>logger.debug("<STR_LIT>".format(<EOL>assembly_file))<EOL>for line in fh:<EOL><INDENT>if not line.strip():<EOL><INDENT>continue<EOL><DEDENT>else:<EOL><INDENT>line = line.strip()<EOL><DEDENT>if line.startswith("<STR_LIT:>>"):<EOL><INDENT>if seq_temp:<EOL><INDENT>seq = "<STR_LIT>".join(seq_temp)<EOL>logger.debug("<STR_LIT>"<EOL>"<STR_LIT>".format(<EOL>contig_id, header, cov))<EOL>self._populate_contigs(contig_id, header, cov, seq)<EOL>seq_temp = []<EOL>contig_id += <NUM_LIT:1><EOL><DEDENT>header = line[<NUM_LIT:1>:]<EOL>cov = self._parse_coverage(line)<EOL><DEDENT>else:<EOL><INDENT>seq_temp.append(line)<EOL><DEDENT><DEDENT>logger.debug("<STR_LIT>"<EOL>"<STR_LIT>".format(<EOL>contig_id, header, cov))<EOL>seq = "<STR_LIT>".join(seq_temp)<EOL>self._populate_contigs(contig_id, header, cov, seq)<EOL><DEDENT>

Parse an assembly fasta file.

        This is a Fasta parsing method that populates the
        :py:attr:`~Assembly.contigs` attribute with data for each contig in the
        assembly.

        The insertion of data on the self.contigs is done by the
        :py:meth:`Assembly._populate_contigs` method, which also calculates
        GC content and proportions.

        Parameters
        ----------
        assembly_file : str
            Path to the assembly fasta file.


def _populate_contigs(self, contig_id, header, cov, sequence):

<EOL>gc_kwargs = self._get_gc_content(sequence, len(sequence))<EOL>logger.debug("<STR_LIT>".format(gc_kwargs))<EOL>self.contigs[contig_id] = {<EOL>"<STR_LIT>": header,<EOL>"<STR_LIT>": sequence,<EOL>"<STR_LIT>": len(sequence),<EOL>"<STR_LIT>": cov,<EOL>**gc_kwargs<EOL>}<EOL>

Inserts data from a single contig into\
         :py:attr:`~Assembly.contigs`.

        By providing a contig id, the original header, the coverage that
        is parsed from the header and the sequence, this method will
        populate the :py:attr:`~Assembly.contigs` attribute.

        Parameters
        ----------
        contig_id : int
            Arbitrary unique contig identifier.
        header : str
            Original header of the current contig.
        cov : float
            The contig coverage, parsed from the fasta header
        sequence : str
            The complete sequence of the contig.


<EOL>at = sum(map(sequence.count, ["<STR_LIT:A>", "<STR_LIT:T>"]))<EOL>gc = sum(map(sequence.count, ["<STR_LIT>", "<STR_LIT:C>"]))<EOL>n = length - (at + gc)<EOL>at_prop = at / length<EOL>gc_prop = gc / length<EOL>n_prop = n / length<EOL>return {"<STR_LIT>": at, "<STR_LIT>": gc, "<STR_LIT:n>": n,<EOL>"<STR_LIT>": at_prop, "<STR_LIT>": gc_prop, "<STR_LIT>": n_prop}<EOL>

Get GC content and proportions.

        Parameters
        ----------
        sequence : str
            The complete sequence of the contig.
        length : int
            The length of the sequence contig.

        Returns
        -------
        x : dict
            Dictionary with the at/gc/n counts and proportions


<EOL>self.filtered_ids = []<EOL>self.report = {}<EOL>gc_filters = [<EOL>["<STR_LIT>", "<STR_LIT>", self.min_gc],<EOL>["<STR_LIT>", "<STR_LIT>", <NUM_LIT:1> - self.min_gc]<EOL>]<EOL>self.filters = list(comparisons) + gc_filters<EOL>logger.debug("<STR_LIT>".format(<EOL>self.filters))<EOL>for contig_id, contig in self.contigs.items():<EOL><INDENT>for key, op, value in list(comparisons) + gc_filters:<EOL><INDENT>if not self._test_truth(contig[key], op, value):<EOL><INDENT>self.filtered_ids.append(contig_id)<EOL>self.report[contig_id] = "<STR_LIT>".format(key,<EOL>contig[key],<EOL>value)<EOL>break<EOL><DEDENT>else:<EOL><INDENT>self.report[contig_id] = "<STR_LIT>"<EOL><DEDENT><DEDENT><DEDENT>

Filters the contigs of the assembly according to user provided\
        comparisons.

        The comparisons must be a list of three elements with the
        :py:attr:`~Assembly.contigs` key, operator and test value. For
        example, to filter contigs with a minimum length of 250, a comparison
        would be::

            self.filter_contigs(["length", ">=", 250])

        The filtered contig ids will be stored in the
        :py:attr:`~Assembly.filtered_ids` list.

        The result of the test for all contigs will be stored in the
        :py:attr:`~Assembly.report` dictionary.

        Parameters
        ----------
        comparisons : list
            List with contig key, operator and value to test.


return sum(<EOL>[vals["<STR_LIT>"] for contig_id, vals in self.contigs.items()<EOL>if contig_id not in self.filtered_ids])<EOL>

Returns the length of the assembly, without the filtered contigs.

        Returns
        -------
        x : int
            Total length of the assembly.


def write_assembly(self, output_file, filtered=True):

logger.debug("<STR_LIT>".format(<EOL>output_file))<EOL>with open(output_file, "<STR_LIT:w>") as fh:<EOL><INDENT>for contig_id, contig in self.contigs.items():<EOL><INDENT>if contig_id not in self.filtered_ids and filtered:<EOL><INDENT>fh.write("<STR_LIT>".format(self.sample,<EOL>contig["<STR_LIT>"],<EOL>contig["<STR_LIT>"]))<EOL><DEDENT><DEDENT><DEDENT>

Writes the assembly to a new file.

        The ``filtered`` option controls whether the new assembly will be
        filtered or not.

        Parameters
        ----------
        output_file : str
            Name of the output assembly file.
        filtered : bool
            If ``True``, does not include filtered ids.


logger.debug("<STR_LIT>".format(<EOL>output_file))<EOL>with open(output_file, "<STR_LIT:w>") as fh:<EOL><INDENT>for contig_id, vals in self.report.items():<EOL><INDENT>fh.write("<STR_LIT>".format(contig_id, vals))<EOL><DEDENT><DEDENT>

Writes a report with the test results for the current assembly

        Parameters
        ----------
        output_file : str
            Name of the output assembly file.


json_dic = dict((x, y) for x, y in zip(header, fields))<EOL>return json_dic<EOL>

Parameters
----------
fields

Returns
-------


logger.debug("<STR_LIT>".format(stats_path))<EOL>if os.path.exists(stats_path):<EOL><INDENT>logger.debug("<STR_LIT>")<EOL>with open(stats_path) as fh:<EOL><INDENT>stats_json = json.load(fh)<EOL><DEDENT><DEDENT>else:<EOL><INDENT>logger.debug("<STR_LIT>")<EOL>stats_json = {}<EOL><DEDENT>return stats_json<EOL>

Parameters
----------
workdir

Returns
-------


@MainWrapper<EOL>def main(sample_id, trace_file, workdir):

<EOL>stats_suffix = "<STR_LIT>"<EOL>stats_path = join(workdir, sample_id + stats_suffix)<EOL>trace_path = join(workdir, trace_file)<EOL>logger.info("<STR_LIT>")<EOL>logger.debug("<STR_LIT>")<EOL>stats_array = get_previous_stats(stats_path)<EOL>logger.info("<STR_LIT>".format(stats_array))<EOL>tag = "<STR_LIT>"<EOL>logger.debug("<STR_LIT>".format(tag))<EOL>logger.info("<STR_LIT>".format(trace_path))<EOL>with open(trace_path) as fh:<EOL><INDENT>header = next(fh).strip().split()<EOL>logger.debug("<STR_LIT>".format(header))<EOL>for line in fh:<EOL><INDENT>fields = line.strip().split("<STR_LIT:\t>")<EOL>if tag in fields[<NUM_LIT:2>] and fields[<NUM_LIT:3>] == "<STR_LIT>":<EOL><INDENT>logger.debug(<EOL>"<STR_LIT>".format(<EOL>line))<EOL>current_json = get_json_info(fields, header)<EOL>stats_array[fields[<NUM_LIT:0>]] = current_json<EOL><DEDENT>else:<EOL><INDENT>logger.debug(<EOL>"<STR_LIT>"<EOL>"<STR_LIT>".format(<EOL>line))<EOL><DEDENT><DEDENT><DEDENT>with open(join(stats_path), "<STR_LIT:w>") as fh, open("<STR_LIT>", "<STR_LIT:w>") as rfh:<EOL><INDENT>fh.write(json.dumps(stats_array, separators=("<STR_LIT:U+002C>", "<STR_LIT::>")))<EOL>rfh.write(json.dumps(stats_array, separators=("<STR_LIT:U+002C>", "<STR_LIT::>")))<EOL><DEDENT>

Parses a nextflow trace file, searches for processes with a specific tag
and sends a JSON report with the relevant information

The expected fields for the trace file are::

    0. task_id
    1. process
    2. tag
    3. status
    4. exit code
    5. start timestamp
    6. container
    7. cpus
    8. duration
    9. realtime
    10. queue
    11. cpu percentage
    12. memory percentage
    13. real memory size of the process
    14. virtual memory size of the process

Parameters
----------
trace_file : str
    Path to the nextflow trace file


template = OrderedDict([<EOL>("<STR_LIT>", <NUM_LIT:0>),<EOL>("<STR_LIT>", <NUM_LIT:0>),<EOL>("<STR_LIT>", <NUM_LIT:0>),<EOL>("<STR_LIT>", <NUM_LIT:0>),<EOL>("<STR_LIT>", <NUM_LIT:0>),<EOL>("<STR_LIT>", <NUM_LIT:0>)<EOL>])<EOL>with open(log_file) as fh:<EOL><INDENT>for line in fh:<EOL><INDENT>fields = [int(x) for x in line.strip().split()[-<NUM_LIT:4>:]]<EOL>if not fields[<NUM_LIT:0>]:<EOL><INDENT>template["<STR_LIT>"] += <NUM_LIT:1><EOL><DEDENT>template["<STR_LIT>"] += fields[<NUM_LIT:1>]<EOL>template["<STR_LIT>"] += fields[<NUM_LIT:3>]<EOL>template["<STR_LIT>"] += fields[<NUM_LIT:1>] + fields[<NUM_LIT:3>]<EOL>template["<STR_LIT>"] += fields[<NUM_LIT:0>]<EOL><DEDENT>total_len = template["<STR_LIT>"] + template["<STR_LIT>"]<EOL>if total_len:<EOL><INDENT>template["<STR_LIT>"] = round(<EOL>(template["<STR_LIT>"] / total_len) * <NUM_LIT:100>, <NUM_LIT:2>)<EOL><DEDENT>else:<EOL><INDENT>template["<STR_LIT>"] = <NUM_LIT:0><EOL><DEDENT><DEDENT>return template<EOL>

Retrieves some statistics from a single Trimmomatic log file.

    This function parses Trimmomatic's log file and stores some trimming
    statistics in an :py:class:`OrderedDict` object. This object contains
    the following keys:

        - ``clean_len``: Total length after trimming.
        - ``total_trim``: Total trimmed base pairs.
        - ``total_trim_perc``: Total trimmed base pairs in percentage.
        - ``5trim``: Total base pairs trimmed at 5' end.
        - ``3trim``: Total base pairs trimmed at 3' end.

    Parameters
    ----------
    log_file : str
        Path to trimmomatic log file.

    Returns
    -------
    x : :py:class:`OrderedDict`
        Object storing the trimming statistics.


def write_report(storage_dic, output_file, sample_id):

with open(output_file, "<STR_LIT:w>") as fh, open("<STR_LIT>", "<STR_LIT:w>") as json_rep:<EOL><INDENT>fh.write("<STR_LIT>"<EOL>"<STR_LIT>")<EOL>for sample, vals in storage_dic.items():<EOL><INDENT>fh.write("<STR_LIT>".format(<EOL>sample, "<STR_LIT:U+002C>".join([str(x) for x in vals.values()])))<EOL>json_dic = {<EOL>"<STR_LIT>": [{<EOL>"<STR_LIT>": sample_id,<EOL>"<STR_LIT:data>": [<EOL>{"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT:value>": vals["<STR_LIT>"],<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT>": True},<EOL>]<EOL>}],<EOL>"<STR_LIT>": [{<EOL>"<STR_LIT>": sample_id,<EOL>"<STR_LIT:data>": {<EOL>"<STR_LIT>": vals["<STR_LIT>"]<EOL>}<EOL>}],<EOL>"<STR_LIT>": vals["<STR_LIT>"]<EOL>}<EOL>json_rep.write(json.dumps(json_dic, separators=("<STR_LIT:U+002C>", "<STR_LIT::>")))<EOL><DEDENT><DEDENT>

Writes a report from multiple samples.

    Parameters
    ----------
    storage_dic : dict or :py:class:`OrderedDict`
        Storage containing the trimming statistics. See :py:func:`parse_log`
        for its generation.
    output_file : str
        Path where the output file will be generated.


<EOL>unpaired_fastq = [f for f in os.listdir("<STR_LIT:.>")<EOL>if f.endswith("<STR_LIT>")]<EOL>for fpath in unpaired_fastq:<EOL><INDENT>os.remove(fpath)<EOL><DEDENT>expected_out = [f for f in os.listdir("<STR_LIT:.>") if f.endswith("<STR_LIT>")]<EOL>if clear == "<STR_LIT:true>" and len(expected_out) == <NUM_LIT:2>:<EOL><INDENT>for fq in fastq_pairs:<EOL><INDENT>rp = os.path.realpath(fq)<EOL>logger.debug("<STR_LIT>".format(rp))<EOL>if re.match("<STR_LIT>", rp):<EOL><INDENT>os.remove(rp)<EOL><DEDENT><DEDENT><DEDENT>

Cleans the working directory of unwanted temporary files


default_adapters = [os.path.join(ADAPTERS_PATH, x) for x in<EOL>os.listdir(ADAPTERS_PATH)]<EOL>filepath = os.path.join(os.getcwd(), "<STR_LIT>")<EOL>with open(filepath, "<STR_LIT:w>") as fh,fileinput.input(default_adapters) as in_fh:<EOL><INDENT>for line in in_fh:<EOL><INDENT>fh.write("<STR_LIT>".format(line, "<STR_LIT>"))<EOL><DEDENT><DEDENT>return filepath<EOL>

Merges the default adapters file in the trimmomatic adapters directory

    Returns
    -------
    str
        Path with the merged adapters file.


@MainWrapper<EOL>def main(sample_id, fastq_pair, trim_range, trim_opts, phred, adapters_file,<EOL>clear):

logger.info("<STR_LIT>")<EOL>cli = [<EOL>"<STR_LIT>",<EOL>"<STR_LIT>".format("<STR_LIT>"[:-<NUM_LIT:1>].lower().replace("<STR_LIT:U+0020>", "<STR_LIT>")),<EOL>"<STR_LIT>",<EOL>TRIM_PATH.strip(),<EOL>"<STR_LIT>",<EOL>"<STR_LIT>",<EOL>"<STR_LIT>"<EOL>]<EOL>try:<EOL><INDENT>phred = int(phred)<EOL>phred_flag = "<STR_LIT>".format(str(phred))<EOL>cli += [phred_flag]<EOL><DEDENT>except ValueError:<EOL><INDENT>pass<EOL><DEDENT>cli += fastq_pair<EOL>output_names = []<EOL>for i in range(len(fastq_pair)):<EOL><INDENT>output_names.append("<STR_LIT>".format(<EOL>SAMPLE_ID, str(i + <NUM_LIT:1>)))<EOL>output_names.append("<STR_LIT>".format(<EOL>SAMPLE_ID, str(i + <NUM_LIT:1>)))<EOL><DEDENT>cli += output_names<EOL>if trim_range != ["<STR_LIT:None>"]:<EOL><INDENT>cli += [<EOL>"<STR_LIT>".format(trim_range[<NUM_LIT:1>]),<EOL>"<STR_LIT>".format(trim_range[<NUM_LIT:0>]),<EOL>]<EOL><DEDENT>if os.path.exists(adapters_file):<EOL><INDENT>logger.debug("<STR_LIT>".format(<EOL>adapters_file))<EOL><DEDENT>else:<EOL><INDENT>logger.debug("<STR_LIT>"<EOL>"<STR_LIT>".format(adapters_file))<EOL>adapters_file = merge_default_adapters()<EOL><DEDENT>cli += [<EOL>"<STR_LIT>".format(adapters_file)<EOL>]<EOL>logfile = os.path.join(tempfile.mkdtemp(prefix='<STR_LIT>'), "<STR_LIT>".format(sample_id))<EOL>cli += [<EOL>"<STR_LIT>".format(trim_opts[<NUM_LIT:0>]),<EOL>"<STR_LIT>".format(trim_opts[<NUM_LIT:1>]),<EOL>"<STR_LIT>".format(trim_opts[<NUM_LIT:2>]),<EOL>"<STR_LIT>".format(trim_opts[<NUM_LIT:3>]),<EOL>"<STR_LIT>",<EOL>"<STR_LIT>",<EOL>logfile<EOL>]<EOL>logger.debug("<STR_LIT>".format(cli))<EOL>p = subprocess.Popen(cli, stdout=PIPE, stderr=PIPE)<EOL>stdout, stderr = p.communicate()<EOL>try:<EOL><INDENT>stderr = stderr.decode("<STR_LIT:utf8>")<EOL><DEDENT>except (UnicodeDecodeError, AttributeError):<EOL><INDENT>stderr = str(stderr)<EOL><DEDENT>logger.info("<STR_LIT>"<EOL>"<STR_LIT>".format(stdout))<EOL>logger.info("<STR_LIT>"<EOL>"<STR_LIT>".format(stderr))<EOL>logger.info("<STR_LIT>".format(<EOL>p.returncode))<EOL>trimmomatic_log(logfile, sample_id)<EOL>if p.returncode == <NUM_LIT:0> and os.path.exists("<STR_LIT>".format(<EOL>SAMPLE_ID)):<EOL><INDENT>clean_up(fastq_pair, clear)<EOL><DEDENT>with open("<STR_LIT>", "<STR_LIT:w>") as status_fh:<EOL><INDENT>if p.returncode != <NUM_LIT:0>:<EOL><INDENT>status_fh.write("<STR_LIT>")<EOL>return<EOL><DEDENT>else:<EOL><INDENT>status_fh.write("<STR_LIT>")<EOL><DEDENT><DEDENT>

Main executor of the trimmomatic template.

    Parameters
    ----------
    sample_id : str
        Sample Identification string.
    fastq_pair : list
        Two element list containing the paired FastQ files.
    trim_range : list
        Two element list containing the trimming range.
    trim_opts : list
        Four element list containing several trimmomatic options:
        [*SLIDINGWINDOW*; *LEADING*; *TRAILING*; *MINLEN*]
    phred : int
        Guessed phred score for the sample. The phred score is a generated
        output from :py:class:`templates.integrity_coverage`.
    adapters_file : str
        Path to adapters file. If not provided, or the path is not available,
        it will use the default adapters from Trimmomatic will be used
    clear : str
        Can be either 'true' or 'false'. If 'true', the input fastq files will
        be removed at the end of the run, IF they are in the working directory


logger.info("<STR_LIT>".format(mash_output))<EOL>read_mash_output = open(mash_output)<EOL>dic = {}<EOL>median_list = []<EOL>filtered_dic = {}<EOL>logger.info("<STR_LIT>")<EOL>for line in read_mash_output:<EOL><INDENT>tab_split = line.split("<STR_LIT:\t>")<EOL>identity = tab_split[<NUM_LIT:0>]<EOL>median_multiplicity = tab_split[<NUM_LIT:2>]<EOL>query_id = tab_split[<NUM_LIT:4>]<EOL>dic[query_id] = [identity, median_multiplicity]<EOL>median_list.append(float(median_multiplicity))<EOL><DEDENT>output_json = open("<STR_LIT:U+0020>".join(mash_output.split("<STR_LIT:.>")[:-<NUM_LIT:1>]) + "<STR_LIT>", "<STR_LIT:w>")<EOL>if len(median_list) > <NUM_LIT:0>:<EOL><INDENT>median_cutoff = median(median_list)<EOL>logger.info("<STR_LIT>")<EOL>for k, v in dic.items():<EOL><INDENT>copy_number = int(float(v[<NUM_LIT:1>]) / median_cutoff)<EOL>if float(v[<NUM_LIT:1>]) > median_cutoff:<EOL><INDENT>filtered_dic["<STR_LIT:_>".join(k.split("<STR_LIT:_>")[<NUM_LIT:0>:<NUM_LIT:3>])] = [<EOL>round(float(v[<NUM_LIT:0>]),<NUM_LIT:2>),<EOL>copy_number<EOL>]<EOL><DEDENT><DEDENT>logger.info(<EOL>"<STR_LIT>".format(len(filtered_dic)))<EOL><DEDENT>else:<EOL><INDENT>logger.error("<STR_LIT>")<EOL><DEDENT>output_json.write(json.dumps(filtered_dic))<EOL>output_json.close()<EOL>json_dic = {<EOL>"<STR_LIT>": [{<EOL>"<STR_LIT>": sample_id,<EOL>"<STR_LIT:data>": [{<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT>": filtered_dic,<EOL>"<STR_LIT:value>": len(filtered_dic)<EOL>}]<EOL>}],<EOL>}<EOL>with open("<STR_LIT>", "<STR_LIT:w>") as json_report:<EOL><INDENT>json_report.write(json.dumps(json_dic, separators=("<STR_LIT:U+002C>", "<STR_LIT::>")))<EOL><DEDENT>

converts top results from mash screen txt output to json format

Parameters
----------
mash_output: str
    this is a string that stores the path to this file, i.e, the name of
    the file
sample_id: str
    sample name


logger.debug("<STR_LIT>".format(kmer_opt))<EOL>if kmer_opt == "<STR_LIT>":<EOL><INDENT>if max_read_len >= <NUM_LIT>:<EOL><INDENT>kmers = [<NUM_LIT>, <NUM_LIT>, <NUM_LIT>, <NUM_LIT>, <NUM_LIT>]<EOL><DEDENT>else:<EOL><INDENT>kmers = [<NUM_LIT>, <NUM_LIT>, <NUM_LIT>, <NUM_LIT>, <NUM_LIT>]<EOL><DEDENT>logger.debug("<STR_LIT>"<EOL>"<STR_LIT>".format(max_read_len, kmers))<EOL><DEDENT>elif len(kmer_opt.split()) > <NUM_LIT:1>:<EOL><INDENT>kmers = kmer_opt.split()<EOL>if kmers[<NUM_LIT:0>]<<NUM_LIT:15> or kmers[-<NUM_LIT:1>]><NUM_LIT:255> or is_odd(kmers):<EOL><INDENT>kmers = []<EOL>logger.debug("<STR_LIT>"<EOL>"<STR_LIT>")<EOL><DEDENT>else:<EOL><INDENT>logger.debug("<STR_LIT>".format(kmers))<EOL><DEDENT><DEDENT>else:<EOL><INDENT>kmers = []<EOL>logger.debug("<STR_LIT>"<EOL>"<STR_LIT>")<EOL><DEDENT>return kmers<EOL>

Returns a kmer list based on the provided kmer option and max read len.

    Parameters
    ----------
    kmer_opt : str
        The k-mer option. Can be either ``'auto'``, ``'default'`` or a
        sequence of space separated integers, ``'23, 45, 67'``.
    max_read_len : int
        The maximum read length of the current sample.

    Returns
    -------
    kmers : list
        List of k-mer values that will be provided to megahit.


fixed_assembly = "<STR_LIT>"<EOL>with open(asseembly_path) as in_hf, open(fixed_assembly, "<STR_LIT:w>") as ou_fh:<EOL><INDENT>for line in in_hf:<EOL><INDENT>if line.startswith("<STR_LIT:>>"):<EOL><INDENT>fixed_line = line.replace("<STR_LIT:U+0020>", "<STR_LIT:_>")<EOL>ou_fh.write(fixed_line)<EOL><DEDENT>else:<EOL><INDENT>ou_fh.write(line)<EOL><DEDENT><DEDENT><DEDENT>return fixed_assembly<EOL>

Removes whitespace from the assembly contig names

    Parameters
    ----------
    asseembly_path : path to assembly file

    Returns
    -------
    str:
        Path to new assembly file with fixed contig names


for fq in fastq:<EOL><INDENT>rp = os.path.realpath(fq)<EOL>logger.debug("<STR_LIT>".format(rp))<EOL>if re.match("<STR_LIT>", rp):<EOL><INDENT>os.remove(rp)<EOL><DEDENT><DEDENT>

Cleans the temporary fastq files. If they are symlinks, the link
source is removed

Parameters
----------
fastq : list
    List of fastq files.


@MainWrapper<EOL>def main(sample_id, fastq_pair, max_len, kmer, mem, clear):

logger.info("<STR_LIT>")<EOL>logger.info("<STR_LIT>")<EOL>kmers = set_kmers(kmer, max_len)<EOL>logger.info("<STR_LIT>".format(kmers))<EOL>mem_bytes = int(mem.replace("<STR_LIT>", "<STR_LIT>")) * <NUM_LIT><EOL>cli = [<EOL>"<STR_LIT>",<EOL>"<STR_LIT>",<EOL>"<STR_LIT>",<EOL>"<STR_LIT>",<EOL>str(mem_bytes),<EOL>"<STR_LIT>",<EOL>"<STR_LIT>"<EOL>]<EOL>if kmers:<EOL><INDENT>cli += [<EOL>"<STR_LIT>",<EOL>"<STR_LIT:U+002C>".join([str(x) for x in kmers])<EOL>]<EOL><DEDENT>cli += [<EOL>"<STR_LIT>",<EOL>fastq_pair[<NUM_LIT:0>],<EOL>"<STR_LIT>",<EOL>fastq_pair[<NUM_LIT:1>]<EOL>]<EOL>logger.debug("<STR_LIT>".format(cli))<EOL>p = subprocess.Popen(cli, stdout=PIPE, stderr=PIPE)<EOL>stdout, stderr = p.communicate()<EOL>try:<EOL><INDENT>stderr = stderr.decode("<STR_LIT:utf8>")<EOL>stdout = stdout.decode("<STR_LIT:utf8>")<EOL><DEDENT>except (UnicodeDecodeError, AttributeError):<EOL><INDENT>stderr = str(stderr)<EOL>stdout = str(stdout)<EOL><DEDENT>logger.info("<STR_LIT>"<EOL>"<STR_LIT>".format(stdout))<EOL>logger.info("<STR_LIT>"<EOL>"<STR_LIT>".format(stderr))<EOL>logger.info("<STR_LIT>".format(<EOL>p.returncode))<EOL>with open("<STR_LIT>", "<STR_LIT:w>") as fh:<EOL><INDENT>if p.returncode != <NUM_LIT:0>:<EOL><INDENT>fh.write("<STR_LIT:error>")<EOL>return<EOL><DEDENT>else:<EOL><INDENT>fh.write("<STR_LIT>")<EOL><DEDENT><DEDENT>assembly_path = "<STR_LIT>"<EOL>fixed_assembly = fix_contig_names(assembly_path)<EOL>if "<STR_LIT>" in fastq_pair[<NUM_LIT:0>]:<EOL><INDENT>sample_id += "<STR_LIT>"<EOL><DEDENT>info = __get_version_megahit()<EOL>assembly_file = "<STR_LIT>".format(<EOL>sample_id, info["<STR_LIT:version>"].replace("<STR_LIT:.>", "<STR_LIT>"))<EOL>os.rename(fixed_assembly, assembly_file)<EOL>logger.info("<STR_LIT>".format(assembly_file))<EOL>if clear == "<STR_LIT:true>" and os.path.exists(assembly_file):<EOL><INDENT>clean_up(fastq_pair)<EOL><DEDENT>

Main executor of the megahit template.

    Parameters
    ----------
    sample_id : str
        Sample Identification string.
    fastq_pair : list
        Two element list containing the paired FastQ files.
    max_len : int
        Maximum read length. This value is determined in
        :py:class:`templates.integrity_coverage`
    kmer : str
        Can be either ``'auto'``, ``'default'`` or a
        sequence of space separated integers, ``'23, 45, 67'``.


adapter_out = "<STR_LIT>"<EOL>logger.debug("<STR_LIT>".format(adapter_out))<EOL>try:<EOL><INDENT>with open(adapter_fasta) as fh,open(adapter_out, "<STR_LIT:w>") as adap_fh:<EOL><INDENT>for line in fh:<EOL><INDENT>if line.startswith("<STR_LIT:>>"):<EOL><INDENT>head = line[<NUM_LIT:1>:].strip()<EOL>sequence = next(fh).strip()<EOL>adap_fh.write("<STR_LIT>".format(head, sequence))<EOL><DEDENT><DEDENT><DEDENT>logger.info("<STR_LIT>")<EOL>return adapter_out<EOL><DEDENT>except FileNotFoundError:<EOL><INDENT>logger.warning("<STR_LIT>".format(<EOL>adapter_fasta))<EOL>return<EOL><DEDENT>

Generates an adapter file for FastQC from a fasta file.

    The provided adapters file is assumed to be a simple fasta file with the
    adapter's name as header and the corresponding sequence::

        >TruSeq_Universal_Adapter
        AATGATACGGCGACCACCGAGATCTACACTCTTTCCCTACACGACGCTCTTCCGATCT
        >TruSeq_Adapter_Index 1
        GATCGGAAGAGCACACGTCTGAACTCCAGTCACATCACGATCTCGTATGCCGTCTTCTGCTTG

    Parameters
    ----------
    adapter_fasta : str
        Path to Fasta file with adapter sequences.

    Returns
    -------
    adapter_out : str or None
        The path to the reformatted adapter file. Returns ``None`` if the
        adapters file does not exist or the path is incorrect.


@MainWrapper<EOL>def main(fastq_pair, adapter_file, cpus):

logger.info("<STR_LIT>")<EOL>if os.path.exists(adapter_file):<EOL><INDENT>logger.info("<STR_LIT>".format(adapter_file))<EOL>adapters = convert_adatpers(adapter_file)<EOL><DEDENT>else:<EOL><INDENT>logger.info("<STR_LIT>"<EOL>"<STR_LIT>".format(adapter_file))<EOL>adapters = None<EOL><DEDENT>cli = [<EOL>"<STR_LIT>",<EOL>"<STR_LIT>",<EOL>"<STR_LIT>",<EOL>"<STR_LIT>",<EOL>"<STR_LIT>",<EOL>"<STR_LIT>",<EOL>str(cpus)<EOL>]<EOL>if adapters:<EOL><INDENT>cli += ["<STR_LIT>", "<STR_LIT:{}>".format(adapters)]<EOL><DEDENT>cli += fastq_pair<EOL>logger.debug("<STR_LIT>".format(cli))<EOL>p = subprocess.Popen(cli, stdout=PIPE, stderr=PIPE, shell=False)<EOL>stdout, stderr = p.communicate()<EOL>try:<EOL><INDENT>stderr = stderr.decode("<STR_LIT:utf8>")<EOL><DEDENT>except (UnicodeDecodeError, AttributeError):<EOL><INDENT>stderr = str(stderr)<EOL><DEDENT>logger.info("<STR_LIT>"<EOL>"<STR_LIT>".format(stdout))<EOL>logger.info("<STR_LIT>"<EOL>"<STR_LIT>".format(stderr))<EOL>logger.info("<STR_LIT>".format(<EOL>p.returncode))<EOL>logger.info("<STR_LIT>")<EOL>with open("<STR_LIT>", "<STR_LIT:w>") as status_fh:<EOL><INDENT>for fastq in fastq_pair:<EOL><INDENT>fpath = join(fastq.rsplit("<STR_LIT:.>", <NUM_LIT:2>)[<NUM_LIT:0>] + "<STR_LIT>",<EOL>"<STR_LIT>")<EOL>logger.debug("<STR_LIT>".format(fpath))<EOL>if not exists(fpath):<EOL><INDENT>logger.warning("<STR_LIT>".format(fpath))<EOL>status_fh.write("<STR_LIT>")<EOL>return<EOL><DEDENT>logger.debug("<STR_LIT>".format(fpath))<EOL>status_fh.write("<STR_LIT>")<EOL><DEDENT><DEDENT>logger.info("<STR_LIT>")<EOL>for i, fastq in enumerate(fastq_pair):<EOL><INDENT>fastqc_dir = fastq.rsplit("<STR_LIT:.>", <NUM_LIT:2>)[<NUM_LIT:0>] + "<STR_LIT>"<EOL>summary_file = join(fastqc_dir, "<STR_LIT>")<EOL>logger.debug("<STR_LIT>".format(summary_file))<EOL>fastqc_data_file = join(fastqc_dir, "<STR_LIT>")<EOL>logger.debug("<STR_LIT>".format(fastqc_data_file))<EOL>os.rename(fastqc_data_file, "<STR_LIT>".format(i + <NUM_LIT:1>))<EOL>os.rename(summary_file, "<STR_LIT>".format(i + <NUM_LIT:1>))<EOL><DEDENT>

Main executor of the fastq template.

    Parameters
    ----------
    fastq_pair : list
        Two element list containing the paired FastQ files.
    adapter_file : str
        Path to adapters file.
    cpus : int or str
        Number of cpu's that will be by FastQC.


@MainWrapper<EOL>def main(sample_id, assembly, min_size):

logger.info("<STR_LIT>")<EOL>f_open = open(assembly, "<STR_LIT>")<EOL>entry = (x[<NUM_LIT:1>] for x in groupby(f_open, lambda line: line[<NUM_LIT:0>] == "<STR_LIT:>>"))<EOL>success = <NUM_LIT:0><EOL>for header in entry:<EOL><INDENT>headerStr = header.__next__()[<NUM_LIT:1>:].strip()<EOL>seq = "<STR_LIT>".join(s.strip() for s in entry.__next__())<EOL>if len(seq) >= min_size:<EOL><INDENT>with open(sample_id + '<STR_LIT:_>' + headerStr.replace("<STR_LIT:U+0020>","<STR_LIT:_>").replace("<STR_LIT:=>","<STR_LIT:_>") + '<STR_LIT>', "<STR_LIT:w>") as output_file:<EOL><INDENT>output_file.write("<STR_LIT:>>" + sample_id + "<STR_LIT:_>" + headerStr.replace("<STR_LIT:U+0020>","<STR_LIT:_>").replace("<STR_LIT:=>","<STR_LIT:_>") + "<STR_LIT>" + seq + "<STR_LIT>")<EOL>success += <NUM_LIT:1><EOL><DEDENT><DEDENT><DEDENT>f_open.close()<EOL>logger.info("<STR_LIT>".format(success))<EOL>

Main executor of the split_fasta template.

    Parameters
    ----------
    sample_id : str
        Sample Identification string.
    assembly : list
        Assembly file.
    min_size : int
        Minimum contig size.


for f in fls:<EOL><INDENT>if os.path.exists(f):<EOL><INDENT>self._parser(f)<EOL><DEDENT>else:<EOL><INDENT>logger.warning("<STR_LIT>".format(f))<EOL><DEDENT><DEDENT>

Public method for parsing abricate output files.

        This method is called at at class instantiation for the provided
        output files. Additional abricate output files can be added using
        this method after the class instantiation.

        Parameters
        ----------
        fls : list
            List of paths to Abricate files


with open(fl) as fh:<EOL><INDENT>for line in fh:<EOL><INDENT>if line.startswith("<STR_LIT:#>") or line.strip() == "<STR_LIT>":<EOL><INDENT>continue<EOL><DEDENT>fields = line.strip().split("<STR_LIT:\t>")<EOL>try:<EOL><INDENT>coverage = float(fields[<NUM_LIT:8>])<EOL><DEDENT>except ValueError:<EOL><INDENT>coverage = None<EOL><DEDENT>try:<EOL><INDENT>identity = float(fields[<NUM_LIT:9>])<EOL><DEDENT>except ValueError:<EOL><INDENT>identity = None<EOL><DEDENT>try:<EOL><INDENT>accession = fields[<NUM_LIT:11>]<EOL><DEDENT>except IndexError:<EOL><INDENT>accession = None<EOL><DEDENT>self.storage[self._key] = {<EOL>"<STR_LIT>": os.path.basename(fl),<EOL>"<STR_LIT>": fields[<NUM_LIT:0>],<EOL>"<STR_LIT>": fields[<NUM_LIT:1>],<EOL>"<STR_LIT>": (int(fields[<NUM_LIT:2>]), int(fields[<NUM_LIT:3>])),<EOL>"<STR_LIT>": fields[<NUM_LIT:4>],<EOL>"<STR_LIT>": accession,<EOL>"<STR_LIT>": fields[<NUM_LIT:10>],<EOL>"<STR_LIT>": coverage,<EOL>"<STR_LIT>": identity<EOL>}<EOL>self._key += <NUM_LIT:1><EOL><DEDENT><DEDENT>

Parser for a single abricate output file.

        This parser will scan a single Abricate output file and populate
        the :py:attr:`Abricate.storage` attribute.

        Parameters
        ----------
        fl : str
            Path to abricate output file

        Notes
        -----
        This method will populate the :py:attr:`Abricate.storage` attribute
        with all compliant lines in the abricate output file. Entries are
        inserted using an arbitrary key that is set by the
        :py:attr:`Abricate._key` attribute.


def iter_filter(self, filters, databases=None, fields=None,<EOL>filter_behavior="<STR_LIT>"):

if filter_behavior not in ["<STR_LIT>", "<STR_LIT>"]:<EOL><INDENT>raise ValueError("<STR_LIT>")<EOL><DEDENT>for dic in self.storage.values():<EOL><INDENT>_pass = False<EOL>flag = []<EOL>if databases:<EOL><INDENT>if dic["<STR_LIT>"] not in databases:<EOL><INDENT>continue<EOL><DEDENT><DEDENT>for f in filters:<EOL><INDENT>val = dic[f[<NUM_LIT:0>]]<EOL>if not self._test_truth(val, f[<NUM_LIT:1>], f[<NUM_LIT:2>]):<EOL><INDENT>flag.append(False)<EOL><DEDENT>else:<EOL><INDENT>flag.append(True)<EOL><DEDENT><DEDENT>if filter_behavior == "<STR_LIT>":<EOL><INDENT>if all(flag):<EOL><INDENT>_pass = True<EOL><DEDENT><DEDENT>elif filter_behavior == "<STR_LIT>":<EOL><INDENT>if any(flag):<EOL><INDENT>_pass = True<EOL><DEDENT><DEDENT>if _pass:<EOL><INDENT>if fields:<EOL><INDENT>yield dict((x, y) for x, y in dic.items() if x in fields)<EOL><DEDENT>else:<EOL><INDENT>yield dic<EOL><DEDENT><DEDENT><DEDENT>

General purpose filter iterator.

        This general filter iterator allows the filtering of entries based
        on one or more custom filters. These filters must contain
        an entry of the `storage` attribute, a comparison operator, and the
        test value. For example, to filter out entries with coverage below 80::

            my_filter = ["coverage", ">=", 80]

        Filters should always be provide as a list of lists::

            iter_filter([["coverage", ">=", 80]])
            # or
            my_filters = [["coverage", ">=", 80],
                          ["identity", ">=", 50]]

            iter_filter(my_filters)

        As a convenience, a list of the desired databases can be directly
        specified using the `database` argument, which will only report
        entries for the specified databases::

            iter_filter(my_filters, databases=["plasmidfinder"])

        By default, this method will yield the complete entry record. However,
        the returned filters can be specified using the `fields` option::

            iter_filter(my_filters, fields=["reference", "coverage"])

        Parameters
        ----------
        filters : list
            List of lists with the custom filter. Each list should have three
            elements. (1) the key from the entry to be compared; (2) the
            comparison operator; (3) the test value. Example:
                ``[["identity", ">", 80]]``.
        databases : list
            List of databases that should be reported.
        fields : list
            List of fields from each individual entry that are yielded.
        filter_behavior : str
            options: ``'and'`` ``'or'``
            Sets the behaviour of the filters, if multiple filters have been
            provided. By default it is set to ``'and'``, which means that an
            entry has to pass all filters. It can be set to ``'or'``, in which
            case one one of the filters has to pass.

        yields
        ------
        dic : dict
            Dictionary object containing a :py:attr:`Abricate.storage` entry
            that passed the filters.


return list(self.iter_filter(*args, **kwargs))<EOL>

Wrapper of the iter_filter method that returns a list with results

        It should be called exactly as in the `iter_filter`

        Returns
        -------
        _ : list
            List of dictionary entries that passed the filters in the
            `iter_filter` method.

        See Also
        --------
        iter_filter


contig_id = contig_str<EOL>try:<EOL><INDENT>contig_id = re.search("<STR_LIT>", contig_str).group(<NUM_LIT:1>)<EOL><DEDENT>except AttributeError:<EOL><INDENT>pass<EOL><DEDENT>try:<EOL><INDENT>contig_id = re.search("<STR_LIT>", contig_str).group(<NUM_LIT:1>)<EOL><DEDENT>except AttributeError:<EOL><INDENT>pass<EOL><DEDENT>return contig_id<EOL>

Tries to retrieve contig id. Returns the original string if it
        is unable to retrieve the id.

        Parameters
        ----------
        contig_str : str
            Full contig string (fasta header)

        Returns
        -------
        str
            Contig id


json_dic = {"<STR_LIT>": []}<EOL>sample_dic = {}<EOL>sample_assembly_map = {}<EOL>for entry in self.storage.values():<EOL><INDENT>sample_id = re.match("<STR_LIT>", entry["<STR_LIT>"]).groups()[<NUM_LIT:0>]<EOL>if sample_id not in sample_dic:<EOL><INDENT>sample_dic[sample_id] = {}<EOL><DEDENT>contig_id = self._get_contig_id(entry["<STR_LIT>"])<EOL>database = entry["<STR_LIT>"]<EOL>if database not in sample_dic[sample_id]:<EOL><INDENT>sample_dic[sample_id][database] = []<EOL><DEDENT>if sample_id not in sample_assembly_map:<EOL><INDENT>sample_assembly_map[sample_id] = entry["<STR_LIT>"]<EOL><DEDENT>sample_dic[sample_id][database].append(<EOL>{"<STR_LIT>": contig_id,<EOL>"<STR_LIT>": entry["<STR_LIT>"],<EOL>"<STR_LIT>": entry["<STR_LIT>"].replace("<STR_LIT:'>", "<STR_LIT>"),<EOL>"<STR_LIT>": entry["<STR_LIT>"],<EOL>"<STR_LIT>": entry["<STR_LIT>"],<EOL>"<STR_LIT>": entry["<STR_LIT>"],<EOL>},<EOL>)<EOL><DEDENT>for sample, data in sample_dic.items():<EOL><INDENT>json_dic["<STR_LIT>"].append(<EOL>{<EOL>"<STR_LIT>": sample,<EOL>"<STR_LIT:data>": {"<STR_LIT>": data},<EOL>"<STR_LIT>": sample_assembly_map[sample]<EOL>}<EOL>)<EOL><DEDENT>return json_dic<EOL>

Generates the JSON report to plot the gene boxes

        Following the convention of the reports platform, this method returns
        a list of JSON/dict objects with the information about each entry in
        the abricate file. The information contained in this JSON is::

            {contig_id: <str>,
             seqRange: [<int>, <int>],
             gene: <str>,
             accession: <str>,
             coverage: <float>,
             identity: <float>
             }

        Note that the `seqRange` entry contains the position in the
        corresponding contig, not the absolute position in the whole assembly.

        Returns
        -------
        json_dic : list
            List of JSON/dict objects with the report data.