rule digital_normalisation:
    """
    Digital normalisation is a method to normalise coverage of a sample in
    fixed, low memory and without any reference.
    The assembly with normalised data provides as good or better results than
    assembling the unnormalised data.
    Furthermore, SPAdes with normalised data is notably speeder and cost less
    memory than without digital normalisation.

    Required input:
        - __digital_normalisation__input: List of paired FASTQ files

    Required output:
        - __digital_normalisation__output: List of paired FASTQ files

    Required log:
        - __digital_normalisation__log: Log with stdout and sterr of Khmer.

    Required parameters:
        - __digital_normalisation__prefix: Prefix for intermediary outputs.

    Required configuration:
        .. code-block:: yaml

            digital_normalisation:
                ksize: 20 # Kmer size used to normalised the coverage.
                cutoff: 20 # When the median k-mer coverage level is above this number the read is not kept.
                max_memory_usage: 16e9 # Maximum amount of memory to use for data structure.
                threads: 4 # Number of threads to be used.
                options: # any options recognised by normalize-by-median.py.

    Reference:
        - https://github.com/dib-lab/khmer
    """
    input:
        fastq = __digital_normalisation__input
    output:
        fastq_dn = __digital_normalisation__output,
        graph = temp(__digital_normalisation__prefix + "/graph.ct")
    log:
        __digital_normalisation__log
    params:
        prefix = __digital_normalisation__prefix,
        ksize = config['digital_normalisation']['ksize'],
        cutoff = config['digital_normalisation']['cutoff'],
        m = config['digital_normalisation']['max_memory_usage'],
        options = config['digital_normalisation']['options']
    threads:
        config['digital_normalisation']['threads']
    shell:
        """
        # Files name without .gz extension
        fastq="{input.fastq}"

        # Check if FASTQ are compressed
        if [[ $fastq == *.gz ]]
        then
            compressed="yes"
            fastq=$(echo ${{fastq%*.gz}} | sed -e "s/.gz\s/ /g")
            # Uncompress fastq file
            unpigz -fk {input.fastq} -p {threads}
        fi

        # Concatenate R1 and R2
        interleave-reads.py $fastq --output {params.prefix}.pe > {log} 2>&1

        # Digital normalisation
        normalize-by-median.py --paired --ksize {params.ksize} \
            --cutoff {params.cutoff} -M {params.m} {params.options} \
            --savegraph {output.graph} {params.prefix}.pe \
            --output {params.prefix}.pe.keep >> {log} 2>&1

        # Filter abundance
        filter-abund.py --threads {threads} -V {output.graph} \
            {params.prefix}.pe.keep --output {params.prefix}.pe.filter \
            >> {log} 2>&1

        # Extract paired reads
        extract-paired-reads.py {params.prefix}.pe.filter \
            --output-paired {params.prefix}.dn.pe \
            --output-single {params.prefix}.dn.se >> {log} 2>&1

        # Split paired reads
        split-paired-reads.py {params.prefix}.dn.pe \
            -1 {output.fastq_dn[0]} -2 {output.fastq_dn[1]} >> {log} 2>&1

        # Remove fastq file if fastq files were compressed
        if [[ -n $compressed ]]
        then
            rm $fastq
        fi
        """
