changeset 8:9bfe38410155 draft

planemo upload for repository https://github.com/bgruening/galaxytools/tree/master/tools/bismark commit 51299fa62f0566a4a897b1c149db564631282fff
author bgruening
date Wed, 22 Aug 2018 08:09:42 -0400
parents fcadce4d9a06
children 1a88b0f2669f
files bismark2report_wrapper.py bismark2report_wrapper.xml bismark_bowtie2_wrapper.xml bismark_deduplicate/bismark_deduplicate_wrapper.py bismark_deduplicate/bismark_deduplicate_wrapper.xml bismark_deduplicate/deduplicate_bismark bismark_deduplicate_wrapper.py bismark_deduplicate_wrapper.xml bismark_mapping/bismark bismark_mapping/bismark_bowtie2_wrapper.xml bismark_mapping/bismark_genome_preparation bismark_mapping/bismark_wrapper.py bismark_methyl_extractor/bismark2bedGraph bismark_methyl_extractor/bismark_methylation_extractor bismark_methyl_extractor/bismark_methylation_extractor.py bismark_methyl_extractor/bismark_methylation_extractor.xml bismark_methyl_extractor/coverage2cytosine bismark_methylation_extractor.py bismark_methylation_extractor.xml bismark_pretty_report/bismark2report bismark_pretty_report/bismark2report_wrapper.py bismark_pretty_report/bismark2report_wrapper.xml bismark_pretty_report/bismark_sitrep.tpl bismark_wrapper.py documentation/Bismark_User_Guide.pdf documentation/readme.rst macros.xml new/bismark new/bismark_genome_preparation new/bismark_methylation_extractor old/bismark old/bismark_genome_preparation old/bismark_methylation_extractor test-data/bowtie1_singles_output_result1.bam test-data/bowtie1_singles_output_result2.bam test-data/bowtie1_singles_report_result1.txt test-data/bowtie1_singles_report_result2.txt test-data/bowtie1_singles_stdout_result1.txt test-data/bowtie1_singles_stdout_result2.txt test-data/bowtie1_singles_suppressed_reads_l_result2.txt test-data/bowtie1_singles_suppressed_reads_r_result2.txt test-data/bowtie1_singles_unmapped_reads_l_result2.txt test-data/bowtie1_singles_unmapped_reads_r_result2.txt test-data/bwa-mem-fastq1.fq test-data/bwa-mem-fastq2.fq test-data/bwa-mem-mt-genome.fa test-data/dedup_reads.bam test-data/dedup_report.txt test-data/input1.fq.gz test-data/mapped_reads.bam test-data/mapping_report.txt test-data/mm10.tiny.fa.gz test-data/output_html_report.html test-data/output_mbias_report.txt test-data/output_splitting_report.txt test-data/summary.txt tool_dependencies.xml
diffstat 47 files changed, 3642 insertions(+), 54267 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bismark2report_wrapper.py	Wed Aug 22 08:09:42 2018 -0400
@@ -0,0 +1,71 @@
+#!/usr/bin/python
+
+import argparse
+import logging
+import subprocess
+import sys
+
+
+def stop_err(logger, msg):
+    logger.critical(msg)
+    sys.exit()
+
+
+def log_subprocess_output(logger, pipe):
+    for line in iter(pipe.readline, b''):
+        logger.debug(line.decode().rstrip())
+
+
+def get_arg():
+    parser = argparse.ArgumentParser()
+    parser.add_argument('--alignment_report', dest='alignment_report', action='store', metavar='alignment_report',
+                        type=str)
+    parser.add_argument('--dedup_report', dest='dedup_report', action='store', metavar='dedup_report', type=str)
+    parser.add_argument('--splitting_report', dest='splitting_report', action='store', metavar='splitting_report',
+                        type=str)
+    parser.add_argument('--mbias_report', dest='mbias_report', action='store', metavar='mbias_report', type=str)
+    parser.add_argument('--nucleotide_report', dest='nucleotide_report', action='store', metavar='nucleotide_report',
+                        type=str)
+    parser.add_argument('--output_html_report', dest='output_html_report', action='store', metavar='output_html_report',
+                        type=str)
+    parser.add_argument('--log_report', dest='log_report', action='store', metavar='log_report', type=str)
+    args = parser.parse_args()
+    return args
+
+
+def __main__():
+    args = get_arg()
+    logger = logging.getLogger('bismark_deduplicate_wrapper')
+    logger.setLevel(logging.DEBUG)
+    ch = logging.StreamHandler(sys.stdout)
+    if args.log_report:
+        ch.setLevel(logging.WARNING)
+        handler = logging.FileHandler(args.log_report)
+        handler.setLevel(logging.DEBUG)
+        logger.addHandler(handler)
+    else:
+        ch.setLevel(logging.DEBUG)
+    logger.addHandler(ch)
+
+    cmd = ['bismark2report', '--verbose', '--alignment_report', args.alignment_report,
+           '--output', args.output_html_report]
+
+    if args.dedup_report:
+        cmd.extend(['--dedup_report', args.dedup_report])
+    if args.splitting_report:
+        cmd.extend(['--splitting_report', args.splitting_report])
+    if args.mbias_report:
+        cmd.extend(['--mbias_report', args.mbias_report])
+    if args.nucleotide_report:
+        cmd.extend(['--nucleotide_report', args.nucleotide_report])
+
+    logger.info("Generating report with: '%s'", " ".join(cmd))
+    process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+    with process.stdout:
+        log_subprocess_output(logger, process.stdout)
+    exitcode = process.wait()
+    if exitcode != 0:
+        stop_err(logger, "Bismark pretty report error (also check the log file if any)!\n%s" % process.stderr)
+
+
+if __name__ == "__main__": __main__()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bismark2report_wrapper.xml	Wed Aug 22 08:09:42 2018 -0400
@@ -0,0 +1,81 @@
+<tool id="bismark_pretty_report" name="Bismark Pretty Report" version="0.20.0" profile="17.01">
+    <description>Generates a graphical HTML report page from report outputs of Bismark</description>
+    <requirements>
+        <requirement type="package" version="0.20.0">bismark</requirement>
+        <requirement type="package" version="1.8">samtools</requirement>
+        <requirement type="package" version="2.3.4.2">bowtie2</requirement>
+    </requirements>
+    <command><![CDATA[
+        python '$__tool_directory__/bismark2report_wrapper.py'
+
+        --alignment_report '$alignment'
+
+        #if $additional_reports['dedup']:
+        	--dedup_report '$additional_reports["dedup"]'
+        #end if
+        #if $additional_reports['splitting']:
+            --splitting_report '$additional_reports["splitting"]'
+        #end if
+        #if $additional_reports['mbias']:
+            --mbias_report '$additional_reports["mbias"]'
+        #end if
+        #if $additional_reports['nucleotide']:
+            --nucleotide_report '$additional_reports["nucleotide"]'
+        #end if
+
+        --output_html_report '$output_html_report'
+
+        #if $separate_logfile:
+            --log_report '$log_report'
+        #end if
+]]>
+    </command>
+
+    <inputs>
+        <param name="alignment" type="data" format="txt" label="Submit a Bismark mapping report" optional="False"/>
+        <section name="additional_reports" title="Additional reports to include in the HTML page (optional)"
+                 expanded="True">
+            <param name="dedup" type="data" format="txt" label="Submit the corresponding Bismark deduplication report"
+                   optional="True" help="Optional output of the module *Bismark Deduplicate*"/>
+            <param name="splitting" type="data" format="txt" label="Submit the corresponding Bismark splitting report"
+                   optional="True" help="Optional output of the module *Bismark Methylation Extractor*"/>
+            <param name="mbias" type="data" format="txt" label="Submit the corresponding Bismark M-bias report"
+                   optional="True" help="Optional output of the module *Bismark Methylation Extractor*"/>
+            <param name="nucleotide" type="data" format="txt" label="Submit the corresponding Bismark nucleotide report"
+                   optional="True" help="Optional output of the module *Bismark Mapping*"/>
+        </section>
+        <param name="separate_logfile" type="boolean" truevalue="true" falsevalue="false" checked="False"
+               label="Create a separate logfile, otherwise logs are added to the dataset info."/>
+    </inputs>
+
+    <outputs>
+        <data name="output_html_report" format="html"
+              label="${tool.name} on ${on_string}: Download pretty html report"/>
+        <data name="log_report" format="txt" label="${tool.name} on ${on_string}: log report (tool stdout)">
+            <filter>( separate_logfile is True )</filter>
+        </data>
+    </outputs>
+
+    <tests>
+        <test>
+            <param name="alignment" value="mapping_report.txt" ftype="txt"/>
+            <param name="dedup" value="dedup_report.txt" ftype="txt"/>
+            <param name="splitting" value="output_splitting_report.txt" ftype="txt"/>
+            <param name="mbias" value="output_mbias_report.txt" ftype="txt"/>
+            <output name="output_html_report" file="output_html_report.html" ftype="html" lines_diff="8"/>
+        </test>
+    </tests>
+
+    <help>
+        <![CDATA[
+**What it does**
+
+    | This tool uses a Bismark alignment report to generate a graphical HTML report page.
+    | Optionally, further reports of the Bismark suite such as deduplication, methylation extractor splitting or M-bias reports can be specified as well.
+
+]]>
+    </help>
+    <citations>
+        <citation type="doi">10.1093/bioinformatics/btr167</citation>
+    </citations>
+</tool>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bismark_bowtie2_wrapper.xml	Wed Aug 22 08:09:42 2018 -0400
@@ -0,0 +1,606 @@
+<tool id="bismark_bowtie2" name="Bismark Mapper" version="0.20.0" profile="18.01">
+    <description>Bisulfite reads mapper</description>
+    <requirements>
+        <requirement type="package" version="0.20.0">bismark</requirement>
+        <requirement type="package" version="1.8">samtools</requirement>
+        <requirement type="package" version="2.3.4.2">bowtie2</requirement>
+    </requirements>
+    <command><![CDATA[
+        python '$__tool_directory__/bismark_wrapper.py'
+
+        ## Change this to accommodate the number of threads you have available.
+        --num-threads "\${GALAXY_SLOTS:-4}"
+
+        ##
+        ## Bismark Genome Preparation, if desired.
+        ##
+
+        ## Handle reference file.
+        #if $refGenomeSource.genomeSource == "built_in_fasta":
+            --own-file '${refGenomeSource.built_in_fasta.fields.path}'
+        #else if $refGenomeSource.genomeSource == "history":
+            --own-file '$refGenomeSource["own_file"]'
+        #else:
+            --indexes-path '${refGenomeSource.built_in_indexes.fields.path}'
+        #end if
+
+        ##
+        ##  Input parameters
+        ##
+
+        #if $singlePaired.sPaired == "single":
+            --single-paired '$singlePaired.input_singles'
+
+            #if $singlePaired.input_singles.ext in ["fastq", "fastq.gz", "fastqillumina"]:
+                --phred64-quals
+                --fastq
+            #elif $singlePaired.input_singles.ext in ["fastqsanger", "fastqsanger.gz"]:
+                --fastq
+            #elif $singlePaired.input_singles.ext == "fasta":
+                --fasta
+            #end if
+        #else:
+            --mate-paired
+            #set $mate1 = list()
+            #set $mate2 = list()
+            #for $mate_pair in $singlePaired.mate_list
+                $mate1.append( str($mate_pair.input_mate1) )
+                $mate2.append( str($mate_pair.input_mate2) )
+            #end for
+
+            --mate1 #echo ','.join($mate1)
+            --mate2 #echo ','.join($mate2)
+
+            #for $mate_pair in $singlePaired.mate_list:
+                #if $mate_pair.input_mate1.ext == "fastqillumina":
+                    --phred64-quals
+                    --fastq
+                #elif $mate_pair.input_mate1.ext in "fastqsanger,fastqsanger.gz":
+                    --fastq
+                #elif $mate_pair.input_mate1.ext == "fasta":
+                    --fasta
+                #end if
+                #break
+            #end for
+
+            -I $singlePaired.minInsert
+            -X $singlePaired.maxInsert
+        #end if
+
+        #if $sort_bam:
+            --sort-bam
+        #end if
+
+        ## for now hardcode the value for the required memory per thread in --best mode
+        --chunkmbs 512
+
+
+        #if $params.settingsType == "custom":
+
+            ## default 20
+            --seed-len $params.seed_len
+            ## default 0
+            --seed-mismatches $params.seed_mismatches
+            ## default 15
+            --seed-extention-attempts $params.seed_extention_attempts
+            ## default 2
+            --max-reseed $params.max_reseed
+
+            ## default 70
+            ##--maqerr $params.maqerr
+
+            ## default unlimited
+            #if $params.qupto != 0:
+                --qupto $params.qupto
+            #end if
+            #if $params.skip_reads != 0:
+                --skip-reads $params.skip_reads
+            #end if
+
+            ## if set, disable the original behaviour
+            $params.no_mixed
+            ## if set, disable the original behaviour
+            $params.no_discordant
+
+            #if $params.bismark_stdout:
+                --stdout '$output_stdout'
+            #end if
+
+            #if $params.isReportOutput:
+                --output-report-file '$report_file'
+            #end if
+
+        #else:
+          --output-report-file '$report_file'
+        #end if
+
+      ##
+      ## Output parameters.
+      ##
+      --output '$output'
+      ##$suppress_header
+
+      #if str( $singlePaired.sPaired ) == "single"
+        #if $output_unmapped_reads_l
+          --output-unmapped-reads '$output_unmapped_reads_l'
+        #end if
+        #if $output_suppressed_reads_l
+          --output-suppressed-reads '$output_suppressed_reads_l'
+        #end if
+      #else
+        #if $output_unmapped_reads_l and $output_unmapped_reads_r
+          --output-unmapped-reads-l '$output_unmapped_reads_l'
+          --output-unmapped-reads-r '$output_unmapped_reads_r'
+        #end if
+        #if $output_suppressed_reads_l and $output_suppressed_reads_l
+          --output-suppressed-reads-l '$output_suppressed_reads_l'
+          --output-suppressed-reads-r '$output_suppressed_reads_r'
+        #end if
+      #end if
+
+]]>
+    </command>
+    <inputs>
+        <conditional name="refGenomeSource">
+            <param name="genomeSource" type="select"
+                   label="Will you select a reference genome from your history or use a built-in index?"
+                   help="Built-ins were indexed using default options">
+                <option value="built_in_indexes" selected="true">Use built-in Bismark indexes</option>
+                <option value="built_in_fasta">Generate Bismark indexes from built-in Reference Genome (fasta)</option>
+                <option value="history">Generate Bismark indexes from Genome (fasta) in your Galaxy history</option>
+            </param>
+            <when value="built_in_indexes">
+                <param name="built_in_indexes" type="select" label="Select Reference Genome (bismark indexes)"
+                       help="If your genome of interest is not listed, contact your Galaxy admin">
+                    <options from_data_table="bismark_indexes">
+                        <filter type="sort_by" column="name"/>
+                        <validator type="no_options" message="No indexes are available for the selected input dataset"/>
+                    </options>
+                </param>
+            </when>
+            <when value="built_in_fasta">
+                <param name="built_in_fasta" type="select" label="Select Reference Genome (fasta)">
+                    <options from_data_table="all_fasta">
+                        <filter type="sort_by" column="name"/>
+                        <validator type="no_options"
+                                   message="No genomes in fasta are available for the selected input dataset"/>
+                    </options>
+                </param>
+            </when>
+            <when value="history">
+                <param name="own_file" type="data" format="fasta" label="Select the reference genome"/>
+            </when>
+        </conditional>
+
+        <!-- Input Parameters -->
+        <conditional name="singlePaired">
+            <param name="sPaired" type="select" label="Is this library mate-paired?">
+                <option value="single">Single-end</option>
+                <option value="paired">Paired-end</option>
+            </param>
+            <when value="single">
+                <param name="input_singles" type="data"
+                       format="fastqsanger,fastqillumina,fastq,fasta,fastq.gz,fastqsanger.gz" label="FASTQ/FASTA file"
+                       help="FASTQ or FASTA files."/>
+            </when>
+            <when value="paired">
+                <repeat name="mate_list" title="Paired End Pairs" min="1">
+                    <param name="input_mate1" type="data"
+                           format="fastqsanger,fastqillumina,fastq,fasta,fastq.gz,fastqsanger.gz" label="Mate pair 1"
+                           help="FASTQ or FASTA files."/>
+                    <param name="input_mate2" type="data"
+                           format="fastqsanger,fastqillumina,fastq,fasta,fastq.gz,fastqsanger.gz" label="Mate pair 2"
+                           help="FASTQ or FASTA files."/>
+                </repeat>
+                <param name="minInsert" type="integer" value="0"
+                       label="Minimum insert size for valid paired-end alignments"/>
+                <param name="maxInsert" type="integer" value="500"
+                       label="Maximum insert size for valid paired-end alignments"/>
+            </when>
+        </conditional>
+
+        <param name="sort_bam" type="boolean" truevalue="true" falsevalue="false" checked="False"
+               label="Sort BAM file by chromosomal position (not compatibile with methylation extractor)"/>
+
+        <conditional name="params">
+            <param name="settingsType" type="select" label="Bismark settings to use"
+                   help="You can use the default settings or set custom values for any of Bismark's parameters.">
+                <option value="default">Use Defaults</option>
+                <option value="custom">Full parameter list</option>
+            </param>
+            <!-- Full/advanced params. -->
+            <when value="dafault"></when>
+            <when value="custom">
+                <!-- -N -->
+                <param name="seed_mismatches" type="integer" value="0"
+                       label="Number of mismatches to be allowed in a seed alignment during multiseed alignment"/>
+                <!-- -L -->
+                <param name="seed_len" type="integer" value="20"
+                       label="Length of the seed substrings to align during multiseed alignment"/>
+                <!--
+                <param name="maqerr" type="integer" value="70" label="Maximum permitted total of quality values at all mismatched read positions throughout the entire alignment, not just in the 'seed'." />
+                -->
+                <!-- -D -->
+                <param name="seed_extention_attempts" type="integer" value="15"
+                       label="How many consecutive seed extension attempts can fail before Bowtie 2 moves on"/>
+                <!-- -R -->
+                <param name="max_reseed" type="integer" value="2"
+                       label="Maximum number of times Bowtie 2 will re-seed reads with repetitive seeds"/>
+
+                <param name="qupto" type="integer" value="0"
+                       label="Only aligns the first N reads or read pairs from the input"
+                       help="Default is 0 and means 'no-limit'."/>
+                <param name="skip_reads" type="integer" value="0"
+                       label="Skip (i.e. do not align) the first N reads or read pairs from the input"/>
+
+                <param name="no_discordant" type="boolean" truevalue="--no-discordant" falsevalue="" checked="false"
+                       label="Disable looking for discordant alignments if it cannot find any concordant alignments (only for paired-end reads)"
+                       help=""/>
+                <param name="no_mixed" type="boolean" truevalue="--no-mixed" falsevalue="" checked="false"
+                       label="Disable Bowtie 2's behaviour to try to find alignments for the individual mates (only for paired-end reads"
+                       help=""/>
+
+                <param name="suppressed_read_file" type="boolean" truevalue="true" falsevalue="false" checked="false"
+                       label="Write ambiguous reads to an extra output file"
+                       help="Write all reads which produce more than one valid alignment with the same number of lowest mismatches or other reads that fail to align uniquely."/>
+                <param name="unmapped_read_file" type="boolean" truevalue="true" falsevalue="false" checked="false"
+                       label="Write all reads that could not be aligned to a file"/>
+                <!-- output Options -->
+                <param name="bismark_stdout" type="boolean" truevalue="true" falsevalue="false" checked="false"
+                       label="Write the bismark output and summary information to an extra file"/>
+                <param name="isReportOutput" type="boolean" truevalue="true" falsevalue="false" checked="true"
+                       label="Offer all report files concatenated in one file (Mapping Report)"/>
+
+                <!--end output options -->
+            </when>  <!-- full -->
+        </conditional>  <!-- params -->
+        <!--
+        <param name="suppress_header" type="boolean" truevalue="..suppress-header" falsevalue="" checked="false" label="Suppress the header in the output SAM file" help="Bowtie produces SAM with several lines of header information by default." />
+          -->
+    </inputs>
+
+
+    <outputs>
+        <data format="txt" name="report_file" label="${tool.name} on ${on_string}: mapping report">
+            <filter>
+                ((
+                params['settingsType'] == "default" or
+                ( params['settingsType'] == "custom" and
+                params['isReportOutput'] is True )
+                ))
+            </filter>
+        </data>
+        <data format="txt" name="output_stdout" label="${tool.name} on ${on_string}: Summary">
+            <filter>
+                ((
+                params['settingsType'] == "custom" and
+                params['bismark_stdout'] is True
+                ))
+            </filter>
+        </data>
+
+        <data format="qname_input_sorted.bam" name="output" label="${tool.name} on ${on_string}: mapped reads">
+            <actions>
+                <conditional name="refGenomeSource.genomeSource">
+                    <when value="built_in_indexes">
+                        <action type="metadata" name="dbkey">
+                            <option type="from_data_table" name="bismark_indexes" column="1" offset="0">
+                                <filter type="param_value" column="0" value="#" compare="startswith" keep="False"/>
+                                <filter type="param_value" ref="refGenomeSource.built_in_indexes" column="0"/>
+                            </option>
+                        </action>
+                    </when>
+                    <when value="generate_indexes">
+                        <action type="metadata" name="dbkey">
+                            <option type="from_data_table" name="all_fasta" column="1" offset="0">
+                                <filter type="param_value" column="0" value="#" compare="startswith" keep="False"/>
+                                <filter type="param_value" ref="refGenomeSource.generate_indexes" column="0"/>
+                            </option>
+                        </action>
+                    </when>
+                </conditional>
+            </actions>
+            <change_format>
+                <when input="sort_bam" value="true" format="bam"/>
+                <when input="sort_bam" value="false" format="qname_input_sorted.bam"/>
+            </change_format>
+        </data>
+
+        <data format="fastq" name="output_suppressed_reads_l"
+              label="${tool.name} on ${on_string}: suppressed reads (L)">
+            <filter>
+                ((
+                params['settingsType'] == "custom" and
+                params['suppressed_read_file'] is True
+                ))
+            </filter>
+            <actions>
+                <conditional name="singlePaired.sPaired">
+                    <when value="single">
+                        <action type="format">
+                            <option type="from_param" name="singlePaired.input_singles" param_attribute="ext"/>
+                        </action>
+                    </when>
+                </conditional>
+            </actions>
+        </data>
+
+        <data format="fastq" name="output_suppressed_reads_r"
+              label="${tool.name} on ${on_string}: suppressed reads (R)">
+            <filter>
+                ((
+                singlePaired['sPaired'] == "paired" and
+                params['settingsType'] == "custom" and
+                params['suppressed_read_file'] is True
+                ))
+            </filter>
+            <actions>
+                <conditional name="singlePaired.sPaired">
+                    <when value="single">
+                        <action type="format">
+                            <option type="from_param" name="singlePaired.input_singles" param_attribute="ext"/>
+                        </action>
+                    </when>
+                    <!--when value="paired">
+                        <action type="format">
+                          <option type="from_param" name="singlePaired.mate_list[0].input_mate1" param_attribute="ext" />
+                        </action>
+                    </when-->
+                </conditional>
+            </actions>
+        </data>
+
+        <!-- Outout unmapped reads -->
+        <data format="fastq" name="output_unmapped_reads_l" label="${tool.name} on ${on_string}: unmapped reads (L)">
+            <filter>
+                ((
+                params['settingsType'] == "custom" and
+                params['unmapped_read_file'] is True
+                ))
+            </filter>
+            <actions>
+                <conditional name="singlePaired.sPaired">
+                    <when value="single">
+                        <action type="format">
+                            <option type="from_param" name="singlePaired.input_singles" param_attribute="ext"/>
+                        </action>
+                    </when>
+                    <!--when value="paired">
+                        <action type="format">
+                          <option type="from_param" name="singlePaired.mate_list[0].input_mate1" param_attribute="ext" />
+                        </action>
+                    </when-->
+                </conditional>
+            </actions>
+        </data>
+        <data format="fastq" name="output_unmapped_reads_r" label="${tool.name} on ${on_string}: unmapped reads (R)">
+            <filter>
+                ((
+                singlePaired['sPaired'] == "paired" and
+                params['settingsType'] == "custom" and
+                params['unmapped_read_file'] is True
+                ))
+            </filter>
+            <actions>
+                <conditional name="singlePaired.sPaired">
+                    <when value="single">
+                        <action type="format">
+                            <option type="from_param" name="singlePaired.input_singles" param_attribute="ext"/>
+                        </action>
+                    </when>
+                    <!--when value="paired">
+                        <action type="format">
+                          <option type="from_param" name="singlePaired.mate_list[0].input_mate1" param_attribute="ext" />
+                        </action>
+                    </when-->
+                </conditional>
+            </actions>
+        </data>
+    </outputs>
+    <tests>
+        <test>
+            <param name="genomeSource" value="history"/>
+            <param name="own_file" value="mm10.tiny.fa.gz" />
+            <param name="sPaired" value="single"/>
+            <param name="input_singles" value="input1.fq.gz" ftype="fastqsanger"/>
+            <param name="sort_bam" value="false"/>
+            <param name="settingsType" value="custom"/>
+            <param name="suppressed_read_file" value="true"/>
+            <param name="unmapped_read_file" value="true"/>
+            <param name="bismark_stdout" value="true"/>
+            <param name="isReportOutput" value="true"/>
+
+            <output name="output_stdout" file="summary.txt" ftype="txt" lines_diff="80">
+                 <assert_contents>
+                     <has_text text="Sequences analysed in total:" />
+                     <has_text text="44115" />
+                     <has_text text="Mapping efficiency:" />
+                     <has_text text="1.3%" />
+                     <has_text text="Bismark run complete" />
+                 </assert_contents>
+            </output>
+            <output name="report_file" file="mapping_report.txt" ftype="txt" lines_diff="6"/>
+            <output name="output" file="mapped_reads.bam" ftype="qname_input_sorted.bam" lines_diff="14"/>
+        </test>
+    </tests>
+
+    <help>
+        <![CDATA[
+
+**What it does**
+
+  | Bismark_ is a bisulfite mapper and methylation caller. Bismark takes in FastA or FastQ files and aligns the reads to a specified bisulfite genome.
+  | Sequence reads are transformed into a bisulfite converted forward strand version (C->T conversion) or into a bisulfite treated reverse strand (G->A conversion of the forward strand).
+  | Each of these reads are then aligned to bisulfite treated forward strand index of a reference genome (C->T converted) and a bisulfite treated reverse strand index of the genome (G->A conversion of the forward strand, by doing this alignments will produce the same positions).
+  | These instances of Bowtie 2 are run in parallel. The sequence file(s) are then read in again sequence by sequence to pull out the original sequence from the genome and determine if there were any protected C's present or not.
+  |
+  | As of version 0.7.0 Bismark will only run 2 alignment threads for OT and OB in parallel, the 4 strand mode can be re-enabled by using non_directional mode.
+  |
+  | It is developed by Krueger F and Andrews SR. at the Babraham Institute. Krueger F, Andrews SR. (2011) Bismark: a flexible aligner and methylation caller for Bisulfite-Seq applications. Bioinformatics, 27, 1571-2.
+
+.. _Bismark: http://www.bioinformatics.babraham.ac.uk/projects/bismark/
+
+----
+
+**Know what you are doing**
+
+  .. class:: warningmark
+
+  | There is no such thing (yet) as an automated gearshift in short read mapping. It is all like stick-shift driving in San Francisco.
+  | In other words = running this tool with default parameters will probably not give you meaningful results.
+  | A way to deal with this is to **understand** the parameters by carefully reading the `documentation`__ and experimenting. Fortunately, Galaxy makes experimenting easy.
+  |
+
+  .. class:: warningmark
+
+  | Make sure all your input reads are in the correct and same format. If thats not the case please adjust/convert the filetype with galaxy's build-in converters.
+
+.. __: http://www.bioinformatics.babraham.ac.uk/projects/bismark/
+
+----
+
+**Input formats**
+
+  | Bismark accepts files in either Sanger FASTQ format (galaxy type *fastqsanger*), Illumina FASTQ format (galaxy type *fastqillumina*) or FASTA format (galaxy type *fasta*). Use the FASTQ Groomer to prepare your files.
+
+----
+
+**A Note on Built-in Reference Genomes**
+
+  | The default variant for all genomes is "Full", defined as all primary chromosomes (or scaffolds/contigs) including mitochondrial plus associated unmapped, plasmid, and other segments.
+  | When only one version of a genome is available in this tool, it represents the default "Full" variant. Some genomes will have more than one variant available.
+  | The "Canonical Male" or sometimes simply "Canonical" variant contains the primary chromosomes for a genome. For example a human "Canonical" variant contains chr1-chr22, chrX, chrY, and chrM. The "Canonical Female" variant contains the primary chromosomes excluding chrY.
+
+----
+
+**Outputs**
+
+* The final output of Bismark is in SAM format by default, and has the following columns::
+
+      Column  Description
+    --------  --------------------------------------------------------
+    1  QNAME  seq-ID
+    2  FLAG   this flag tries to take the strand a bisulfite read
+              originated from into account
+              (this is different from ordinary DNA alignment flags!)
+    3  RNAME  chromosome
+    4  POS    start position
+    5  MAPQ   always 255
+    6  CIGAR  extended CIGAR string
+    7  MRNM   Mate Reference sequence NaMe ('=' if same as RNAME)
+    8  MPOS   1-based Mate POSition
+    9  ISIZE  Inferred insert SIZE
+    10 SEQ    query SEQuence on the same strand as the reference
+    11 QUAL   Phred33 scale
+    12 NM-tag edit distance to the reference)
+    13 XX-tag base-by-base mismatches to the reference.
+              This does not include indels.
+    14 XM-tag methylation call string
+    15 XR-tag read conversion state for the alignment
+    16 XG-tag genome conversion state for the alignment
+
+
+  | Each read of paired-end alignments is written out in a separate line in the above format.
+  |
+
+* It looks like this (scroll sideways to see the entire example)::
+
+    QNAME	FLAG	RNAME	POS	MAPQ	CIAGR	MRNM	MPOS	ISIZE	SEQ	QUAL	OPT
+    HWI-EAS91_1_30788AAXX:1:1:1761:343	4	*	0	0	*	*	0	0	AAAAAAANNAAAAAAAAAAAAAAAAAAAAAAAAAAACNNANNGAGTNGNNNNNNNGCTTCCCACAGNNCTGG	hhhhhhh;;hhhhhhhhhhh^hOhhhhghhhfhhhgh;;h;;hhhh;h;;;;;;;hhhhhhghhhh;;Phhh
+    HWI-EAS91_1_30788AAXX:1:1:1578:331	4	*	0	0	*	*	0	0	GTATAGANNAATAAGAAAAAAAAAAATGAAGACTTTCNNANNTCTGNANNNNNNNTCTTTTTTCAGNNGTAG	hhhhhhh;;hhhhhhhhhhhhhhhhhhhhhhhhhhhh;;h;;hhhh;h;;;;;;;hhhhhhhhhhh;;hhVh
+
+----
+
+**Note on Bismark settings**
+
+  | All of the options have a default value. You can change any of them. If any Bismark function is missing please contact the tool author or your Galaxy admin.
+
+----
+
+**Bismark settings**
+
+* **If Paired-End Reads**
+
+  * **Minimum insert size for valid paired-end alignments**
+
+      | The minimum insert size for valid paired-end alignments. E.g. if -I 60 is specified and a paired-end alignment consists of two 20-bp alignments in the appropriate orientation with a 20-bp gap between them, that alignment is considered valid (as long as -X is also satisfied). A 19-bp gap would not be valid in that case. Default: 0.
+      |
+      | Alignment option *-I/--minins <INT>*
+
+
+  * **Maximum insert size for valid paired-end alignments**
+
+      |  The maximum insert size for valid paired-end alignments. E.g. if -X 100 is specified and a paired-end alignment consists of two 20-bp alignments in the proper orientation with a 60-bp gap between them, that alignment is considered valid (as long as -I is also satisfied). A 61-bp gap would not be valid in that case. Default: 500.
+      |
+      | Alignment option *-X/--maxins <INT>*
+
+
+* **Number of mismatches to be allowed in a seed alignment during multiseed alignment**
+
+    | Sets the number of mismatches to allowed in a seed alignment during multiseed alignment. Can be set to 0 or 1. Setting this higher makes alignment slower (often much slower) but increases sensitivity. Default: 0. This option is only available for Bowtie 2 (for Bowtie 1 see -n).
+    |
+    | Bowtie 2 Specific option *-N <INT>*
+
+* **Length of the seed substrings to align during multiseed alignment**
+
+    | Sets the length of the seed substrings to align during multiseed alignment. Smaller values make alignment slower but more senstive. Default: the --sensitive preset of Bowtie 2 is used by default, which sets -L to 20. This option is only available for Bowtie 2 (for Bowtie 1 see -l).
+    |
+    | Bowtie 2 Specific option *-L <INT>*
+
+
+* **How many consecutive seed extension attempts can fail before Bowtie 2 moves on**
+
+    | Up to <int> consecutive seed extension attempts can "fail" before Bowtie 2 moves on, using the alignments found so far. A seed extension "fails" if it does not yield a new best or a new second-best alignment. Default: 15.
+    |
+    | Bowtie 2 Effort option *-D <INT>*
+
+* **Maximum number of times Bowtie 2 will re-seed reads with repetitive seeds**
+
+    | <int> is the maximum number of times Bowtie 2 will "re-seed" reads with repetitive seeds. When "re-seeding," Bowtie 2 simply chooses a new set of reads (same length, same number of mismatches allowed) at different offsets and searches for more alignments. A read is considered to have repetitive seeds if the total number of seed hits divided by the number of seeds that aligned at least once is greater than 300. Default: 2.
+    |
+    | Bowtie 2 Effort option *-R <INT>*
+
+* **Only aligns the first N reads or read pairs from the input**
+
+    | Only aligns the first <int> reads or read pairs from the input. Default: no limit.
+    |
+    | Input option *-u/--upto <INT>*
+
+* **Skip (i.e. do not align) the first N reads or read pairs from the input**
+
+    | Input option *-s/--skip*
+
+* **Disable looking for discordant alignments if it cannot find any concordant alignments**
+
+    | Normally, Bowtie 2 looks for discordant alignments if it cannot find any concordant alignments. A discordant alignment is an alignment where both mates align uniquely, but that does not satisfy the paired-end constraints (--fr/--rf/--ff, -I, -X). This option disables that behavior and it is on by default.
+    |
+    | Bowtie 2 Paired-End option *--no-discordant*
+
+* **Disable Bowtie 2's behaviour to try to find alignments for the individual mates**
+
+    | This option disables Bowtie 2's behavior to try to find alignments for the individual mates if it cannot find a concordant or discordant alignment for a pair. This option is invariable and on by default.
+    |
+    | Bowtie 2 Paired-End option *--no-mixed*
+
+* **Write ambiguous reads to an extra output file**
+
+    | Write all reads which produce more than one valid alignment with the same number of lowest mismatches or other reads that fail to align uniquely to a file in the output directory. Written reads will appear as they did in the input, without any of the translation of quality values that may have taken place within Bowtie or Bismark. Paired-end reads will be written to two parallel files with _1 and _2 inserted in theit filenames, i.e. _ambiguous_reads_1.txt and _ambiguous_reads_2.txt. These reads are not written to the file specified with --un.
+    |
+    | Output option *--ambiguous*
+
+* **Write all reads that could not be aligned to a file**
+
+    | Write all reads that could not be aligned to a file in the output directory. Written reads will appear as they did in the input, without any translation of quality values that may have taken place within Bowtie or Bismark. Paired-end reads will be written to two parallel files with _1 and _2 inserted in their filenames, i.e. _unmapped_reads_1.txt and unmapped_reads_2.txt. Reads with more than one valid alignment with the same number of lowest mismatches (ambiguous mapping) are also written to _unmapped_reads.txt unless the option --ambiguous is specified as well.
+    |
+    | Output option *-un/--unmapped*
+
+* **Offer all report files concatenated in one file**
+
+    | Prints out a Bismark mapping report
+
+]]>
+    </help>
+    <citations>
+        <citation type="doi">10.1093/bioinformatics/btr167</citation>
+    </citations>
+</tool>
--- a/bismark_deduplicate/bismark_deduplicate_wrapper.py	Sat May 06 13:18:09 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-#!/usr/bin/python
-
-import argparse
-import os
-import re
-import shutil
-import subprocess
-import sys
-import tempfile
-import logging
-from glob import glob
-
-def cleanup_before_exit(tmp_dir):
-    if tmp_dir and os.path.exists(tmp_dir):
-        shutil.rmtree(tmp_dir)
-
-def get_arg():
-    parser = argparse.ArgumentParser()
-    parser.add_argument('--tool_dir', dest='tool_dir', action='store', nargs=1, metavar='tool_dir', type=str)
-    parser.add_argument('-p', action='store_true')
-    parser.add_argument('-s', action='store_true')
-    parser.add_argument('--input', dest='input', action='store', nargs=1, metavar='input', type=str)
-    parser.add_argument('--output_report', dest='output_report', action='store', nargs=1, metavar='output_report', type=str)
-    parser.add_argument('--output_bam', dest='output_bam', action='store', nargs=1, metavar='output_report', type=str)
-    parser.add_argument('--log_report', dest='log_report', action='store', nargs=1, metavar='log_filename', type=str)
-    args = parser.parse_args()
-    return args
-
-def __main__():
-    args = get_arg()
-
-    tmp_dir = tempfile.mkdtemp(prefix='tmp', suffix='')
-    os.chdir(tmp_dir)
-
-    if args.log_report:
-        logging.basicConfig(level=logging.INFO, filename=args.log_report[0], filemode="a+", format='%(message)s')
-    else:
-        logging.basicConfig(level=logging.INFO, filename=os.path.join(tmp_dir, 'log_report.txt'), filemode="a+", format='%(message)s')
-
-    default_reads_name = 'submitted_reads.bam'
-    os.symlink(args.input[0], default_reads_name)
-
-    if args.p is True:
-        sPaired = '-p'
-    if args.s is True:
-        sPaired = '-s'
-
-    cmd = 'perl %s %s duplicated_reads.bam --bam' % (os.path.join(args.tool_dir[0], 'deduplicate_bismark'), sPaired)
-    logging.info('COMMAND LINE:\n\n%s' % cmd)
-
-    proc = subprocess.Popen(['perl', os.path.join(args.tool_dir[0], 'deduplicate_bismark'), sPaired, default_reads_name, '--bam'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
-    proc_out, proc_err = proc.communicate()
-
-    logging.info("__________________________________________________________________\n")
-    logging.info("BISMARK DEDUPLICATE STDOUT:\n\n%s" % proc_out)
-    if proc_err:
-        logging.critical("__________________________________________________________________\n")
-        logging.critical("BISMARK DEDUPLICATE WARNING:\n\n%s" % proc_err)
-        sys.exit("Dedpulicate Bismark crashed with the folowing error message:\n%s" % proc_err)
-
-    shutil.move( glob('*deduplicated.bam')[0], args.output_bam[0] )
-    shutil.move( glob('*deduplication_report.txt')[0], args.output_report[0])
-
-    cleanup_before_exit(tmp_dir)
-
-if __name__=="__main__": __main__()
\ No newline at end of file
--- a/bismark_deduplicate/bismark_deduplicate_wrapper.xml	Sat May 06 13:18:09 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +0,0 @@
-<tool id="bismark_deduplicate" name="Bismark Deduplicate" version="0.16.3">
-
-    <description>Deduplicates reads mapped by Bismark</description>
-    <!--<version_command>bismark version</version_command>-->
-
-    <requirements>
-        <requirement type="package" version="0.1.19">samtools</requirement>
-        <requirement type="package" version="2.1.0">bowtie2</requirement>
-    </requirements>
-
-    <stdio>
-        <exit_code range="1:" />
-        <exit_code range=":-1" />
-        <regex match="Error:" />
-        <regex match="Exception:" />
-    </stdio>
-
-    <command interpreter="python">
-<![CDATA[
-        bismark_deduplicate_wrapper.py
-
-        --tool_dir "$__tool_directory__"
-
-        #if str ( $sPaired ) == "single":
-        	-s
-        #else
-        	-p
-        #end if
-
-        --input "$mapping_output"
-
-        --output_report "$output_report"
-        --output_bam "$output_bam"
-
-        ##--log_report "$log_report"
-]]>
-    </command>
-
-    <inputs>
-        <param name="sPaired" type="select" label="Is this library mate-paired?" format="bam">
-            <option value="single">Single-end</option>
-            <option value="paired">Paired-end</option>
-        </param>
-        <param name="mapping_output" type="data" format="bam, sam" label="Submit the resulting bam/sam file from Bismark bisulfite mapper" />
-    </inputs>
-
-    <outputs>
-        <data name="output_bam" format="bam" label="${tool.name} on ${on_string}: deduplicated mapped reads" />
-        <data name="output_report" format="txt" label="${tool.name} on ${on_string}: deduplication report"/>
-        <!--<data name="log_report" format="txt" label="${tool.name} on ${on_string}: log report (tool stdout)"/>-->
-    </outputs>
-
-    <help>
-<![CDATA[
-**What it does**
-
-	| This tool is supposed to remove alignments to the same position in the genome from the Bismark mapping output (both single and paired-end SAM files), which can arise by e.g. excessive PCR amplification. If sequences align to the same genomic position but on different strands they will be scored individually.
-	|
-	| Note that deduplication is not recommended for RRBS-type experiments!
-	|
-	| For single-end alignments only use the start-coordinate of a read will be used for deduplication.
-	| For paired-end alignments the start-coordinate of the first read and the end coordinate of the second read will be used for deduplication. 
-
-]]>
-  </help>
-  <citations>
-      <citation type="doi">10.1093/bioinformatics/btr167</citation>
-  </citations>
-</tool>
\ No newline at end of file
--- a/bismark_deduplicate/deduplicate_bismark	Sat May 06 13:18:09 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1272 +0,0 @@
-#!/usr/bin/env perl
-use strict;
-use warnings;
-use Getopt::Long;
-
-
-### This script is supposed to remove alignments to the same position in the genome which can arise by e.g. PCR amplification
-### Paired-end alignments are considered a duplicate if both partner reasd start and end at the exact same position
-
-### May 13, 2013
-### Changed the single-end trimming behavior so that only the start coordinate will be used. This avoids duplicate reads that have been trimmed to a varying extent
-### Changed the way of determining the end of reads in SAM format to using the CIGAR string if the read contains InDels
-
-### 16 July 2013
-### Adding a new deduplication mode for barcoded RRBS-Seq
-
-### 27 Sept 2013
-### Added close statement for all output filehandles (which should probably have been there from the start...)
-
-### 8 Jan 2015
-### to detect paired-end command from the @PG line we are no requiring spaces before and after the -1 or -2
-
-### 09 Mar 2015
-### Removing newline characters also from the read conversion flag in case the tags had been reordered and are now present in the very last column
-
-### 19 08 2015
-### Hiding the option --representative from view to discourage people from using it (it was nearly always not what they wanted to do anyway). It should still work 
-### for alignments that do not contain any indels
-### Just for reference, here is the the text:
-### print "--representative\twill browse through all sequences and print out the sequence with the most representative (as in most frequent) methylation call for any given position. Note that this is very likely the most highly amplified PCR product for a given sequence\n\n";
-
-
-my $dedup_version = 'v0.16.3';
-
-my $help;
-my $representative;
-my $single;
-my $paired;
-my $global_single;
-my $global_paired;
-my $vanilla;
-my $samtools_path;
-my $bam;
-my $rrbs;
-my $version;
-
-my $command_line = GetOptions ('help' => \$help,
-			       'representative' => \$representative,
-			       's|single' => \$global_single,
-			       'p|paired' => \$global_paired,
-			       'vanilla' => \$vanilla,
-			       'samtools_path=s' => \$samtools_path,
-			       'bam' => \$bam,
-			       'barcode' => \$rrbs,
-			       'version' => \$version,
-			      );
-
-die "Please respecify command line options\n\n" unless ($command_line);
-
-if ($help){
-  print_helpfile();
-  exit;
-}
-
-if ($version){
-  print << "VERSION";
-
-                           Bismark Deduplication Module
-
-                          Deduplicator Version: $dedup_version
-              Copyright 2010-16 Felix Krueger, Babraham Bioinformatics
-                www.bioinformatics.babraham.ac.uk/projects/bismark/
-
-
-VERSION
-    exit;
-  }
-
-
-
-my @filenames = @ARGV;
-
-unless (@filenames){
-  print "Please provide one or more Bismark output files for deduplication\n\n";
-  sleep (2);
-  print_helpfile();
-  exit;
-}
-
-
-### OPTIONS
-unless ($global_single or $global_paired){
-  if ($vanilla){
-    die "Please specify either -s (single-end) or -p (paired-end) for deduplication. Reading this information from the \@PG header line only works for SAM/BAM files\n\n";
-  }
-  warn "\nNeither -s (single-end) nor -p (paired-end) selected for deduplication. Trying to extract this information for each file separately from the \@PG line of the SAM/BAM file\n";
-}
-
-if ($global_paired){
-  if ($global_single){
-    die "Please select either -s for single-end files or -p for paired-end files, but not both at the same time!\n\n";
-  }
-  if ($vanilla){
-
-    if ($rrbs){
-      die "Barcode deduplication only works with Bismark SAM (or BAM) output (in attempt to phase out the vanilla format)\n";
-    }
-
-    warn "Processing paired-end custom Bismark output file(s):\n";
-    warn join ("\t",@filenames),"\n\n";
-  }
-  else{
-    warn "Processing paired-end Bismark output file(s) (SAM format):\n";
-    warn join ("\t",@filenames),"\n\n";
-  }
-}
-else{
-  if ($vanilla){
-    warn "Processing single-end custom Bismark output file(s):\n";
-    warn join ("\t",@filenames),"\n\n";
-  }
-  else{
-    warn "Processing single-end Bismark output file(s) (SAM format):\n";
-    warn join ("\t",@filenames),"\n\n";
-  }
-}
-
-### PATH TO SAMTOOLS
-if (defined $samtools_path){
-  # if Samtools was specified as full command
-  if ($samtools_path =~ /samtools$/){
-    if (-e $samtools_path){
-      # Samtools executable found
-    }
-    else{
-      die "Could not find an installation of Samtools at the location $samtools_path. Please respecify\n";
-    }
-  }
-  else{
-    unless ($samtools_path =~ /\/$/){
-      $samtools_path =~ s/$/\//;
-    }
-    $samtools_path .= 'samtools';
-    if (-e $samtools_path){
-      # Samtools executable found
-    }
-    else{
-      die "Could not find an installation of Samtools at the location $samtools_path. Please respecify\n";
-    }
-  }
-}
-# Check whether Samtools is in the PATH if no path was supplied by the user
-else{
-  if (!system "which samtools >/dev/null 2>&1"){ # STDOUT is binned, STDERR is redirected to STDOUT. Returns 0 if Samtools is in the PATH
-    $samtools_path = `which samtools`;
-    chomp $samtools_path;
-  }
-}
-
-if ($bam){
-  if (defined $samtools_path){
-    $bam = 1;
-  }
-  else{
-    warn "No Samtools found on your system, writing out a gzipped SAM file instead\n";
-    $bam = 2;
-  }
-}
-else{
-  $bam = 0;
-}
-
-
-if ($representative){
-  warn "\nIf there are several alignments to a single position in the genome the alignment with the most representative methylation call will be chosen (this might be the most highly amplified PCR product...)\n\n";
-  sleep (1);
-}
-elsif($rrbs){
-  warn "\nIf the input is a multiplexed sample with several alignments to a single position in the genome, only alignments with a unique barcode will be chosen)\n\n";
-  sleep (1);
-}
-else{ # default; random (=first) alignment
-  warn "\nIf there are several alignments to a single position in the genome the first alignment will be chosen. Since the input files are not in any way sorted this is a near-enough random selection of reads.\n\n";
-  sleep (1);
-}
-
-foreach my $file (@filenames){
-
-  if ($global_single){
-    $paired = 0;
-    $single = 1;
-  }
-  elsif($global_paired){
-    $paired = 1;
-    $single = 0;
-  }
-
-  unless($global_single or $global_paired){
-
-    warn "Trying to determine the type of mapping from the SAM header line\n"; sleep(1);
-
-    ### if the user did not specify whether the alignment file was single-end or paired-end we are trying to get this information from the @PG header line in the SAM/BAM file
-    if ($file =~ /\.gz$/){
-      open (DETERMINE,"gunzip -c $file |") or die "Unable to read from gzipped file $file: $!\n";
-    }
-    elsif ($file =~ /\.bam$/){
-      open (DETERMINE,"$samtools_path view -h $file |") or die "Unable to read from BAM file $file: $!\n";
-    }
-    else{
-      open (DETERMINE,$file) or die "Unable to read from $file: $!\n";
-    }
-    while (<DETERMINE>){
-      last unless (/^\@/);
-      if ($_ =~ /^\@PG/){
-	# warn "found the \@PG line:\n";
-	# warn "$_";
-	
-	if ($_ =~ /\s+-1\s+/ and $_ =~ /\s+-2\s+/){
-	  warn "Treating file as paired-end data (extracted from \@PG line)\n"; sleep(1);
-	  $paired = 1;
-	  $single = 0;
-	}
-	else{
-	  warn "Treating file as single-end data (extracted from \@PG line)\n"; sleep(1);
-	  $paired = 0;
-	  $single = 1;
-	}
-      }
-    }
-    close DETERMINE or warn "$!\n";
-  }
-
-  if ($file =~ /(\.bam$|\.sam$)/){
-      bam_isEmpty($file);
-  }
-  
-
-  ### OPTIONS
-  unless ($single or $paired){
-    die "Please specify either -s (single-end) or -p (paired-end) for deduplication, or provide a SAM/BAM file that contains the \@PG header line\n\n";
-  }
-
-  ### 
-  unless ($vanilla){
-    if ($paired){
-      test_positional_sorting($file);
-    }
-  }
-
-
-  ### writing to a report file
-  my $report = $file;
-
-  $report =~ s/\.gz$//;
-  $report =~ s/\.sam$//;
-  $report =~ s/\.bam$//;
-  $report =~ s/\.txt$//;
-  $report =~ s/$/.deduplication_report.txt/;
-
-  open (REPORT,'>',$report) or die "Failed to write to report file to $report: $!\n\n";
-
-
-  ### for representative methylation calls we need to discriminate between single-end and paired-end files as the latter have 2 methylation call strings
-  if($representative){
-    deduplicate_representative($file);
-  }
-
-  elsif($rrbs){
-    deduplicate_barcoded_rrbs($file);
-  }
-
-  ### as the default option we simply write out the first read for a position and discard all others. This is the fastest option
-  else{
-
-    my %unique_seqs;
-    my %positions;
-
-    if ($file =~ /\.gz$/){
-      open (IN,"gunzip -c $file |") or die "Unable to read from gzipped file $file: $!\n";
-    }
-    elsif ($file =~ /\.bam$/){
-      open (IN,"$samtools_path view -h $file |") or die "Unable to read from BAM file $file: $!\n";
-    }
-    else{
-      open (IN,$file) or die "Unable to read from $file: $!\n";
-    }
-
-    my $outfile = $file;
-    $outfile =~ s/\.gz$//;
-    $outfile =~ s/\.sam$//;
-    $outfile =~ s/\.bam$//;
-    $outfile =~ s/\.txt$//;
-
-    if ($vanilla){
-      $outfile =~ s/$/_deduplicated.txt/;
-    }
-    else{
-      if ($bam == 1){
-	$outfile =~ s/$/.deduplicated.bam/;
-      }
-      elsif ($bam == 2){
-	$outfile =~ s/$/.deduplicated.sam.gz/;
-      }
-      else{
-	$outfile =~ s/$/.deduplicated.sam/;
-      }
-    }
-    if ($bam == 1){
-      open (OUT,"| $samtools_path view -bSh 2>/dev/null - > $outfile") or die "Failed to write to $outfile: $!\n";
-    }
-    elsif($bam == 2){ ### no Samtools found on system. Using GZIP compression instead
-      open (OUT,"| gzip -c - > $outfile") or die "Failed to write to $outfile: $!\n";
-    }
-
-    else{
-      open (OUT,'>',$outfile) or die "Unable to write to $outfile: $!\n";
-    }
-
-    ### need to proceed slightly differently for the custom Bismark and Bismark SAM output
-    if ($vanilla){
-      $_ = <IN>; # Bismark version header
-      print OUT; # Printing the Bismark version to the de-duplicated file again
-    }
-    my $count = 0;
-    my $unique_seqs = 0;
-    my $removed = 0;
-
-    while (<IN>){
-
-      if ($count == 0){
-	if ($_ =~ /^Bismark version:/){
-	  warn "The file appears to be in the custom Bismark and not SAM format. Please see option --vanilla!\n";
-	  sleep (2);
-	  print_helpfile();
-	  exit;
-	}
-      }
-
-      ### if this was a SAM file we ignore header lines
-      unless ($vanilla){
-	if (/^\@\w{2}\t/){
-	  print "skipping header line:\t$_";
-	  print OUT "$_"; # Printing the header lines again into the de-duplicated file
-	  next;
-	}
-      }
-
-      ++$count;
-      my $composite; # storing positional data. For single end data we are only using the start coordinate since the end might have been trimmed to different lengths
-
-      my ($strand,$chr,$start,$end,$cigar);
-      my $line1;
-
-      if ($vanilla){
-	($strand,$chr,$start,$end) = (split (/\t/))[1,2,3,4];
-      }
-      else{ # SAM format
-	($strand,$chr,$start,$cigar) = (split (/\t/))[1,2,3,5]; # we are assigning the FLAG value to $strand
-
-	### SAM single-end
-	if ($single){
-
-	  if ($strand == 0 ){
-	    ### read aligned to the forward strand. No action needed
-	  }
-	  elsif ($strand == 16){
-	    ### read is on reverse strand
-	
-	    $start -= 1; # only need to adjust this once
-	
-	    # for InDel free matches we can simply use the M number in the CIGAR string
-	    if ($cigar =~ /^(\d+)M$/){ # linear match
-	      $start += $1;
-	    }
-
-	    else{
-	      # parsing CIGAR string
-	      my @len = split (/\D+/,$cigar); # storing the length per operation
-	      my @ops = split (/\d+/,$cigar); # storing the operation
-	      shift @ops; # remove the empty first element
-	      die "CIGAR string contained a non-matching number of lengths and operations\n" unless (scalar @len == scalar @ops);
-
-	      # warn "CIGAR string; $cigar\n";
-	      ### determining end position of a read
-	      foreach my $index(0..$#len){
-		if ($ops[$index] eq 'M'){  # standard matching bases
-		  $start += $len[$index];
-		  # warn "Operation is 'M', adding $len[$index] bp\n";
-		}
-		elsif($ops[$index] eq 'I'){ # insertions do not affect the end position
-		  # warn "Operation is 'I', next\n";
-		}
-		elsif($ops[$index] eq 'D'){ # deletions do affect the end position
-		  #  warn "Operation is 'D',adding $len[$index] bp\n";
-		  $start += $len[$index];
-		}
-		else{
-		  die "Found CIGAR operations other than M, I or D: '$ops[$index]'. Not allowed at the moment\n";
-		}
-	      }
-	    }
-	  }
-	  $composite = join (":",$strand,$chr,$start);
-	}
-	elsif($paired){
-
-	  ### storing the current line
-	  $line1 = $_;
-
-	  my $read_conversion;
-	  my $genome_conversion;
-
-	  while ( /(XR|XG):Z:([^\t]+)/g ) {
-	    my $tag = $1;
-	    my $value = $2;
-
-	    if ($tag eq "XR") {
-	      $read_conversion = $value;
-	      $read_conversion =~ s/\r//;
-	      chomp $read_conversion;
-	    } elsif ($tag eq "XG") {
-	      $genome_conversion = $value;
-	      $genome_conversion =~ s/\r//;
-	      chomp $genome_conversion;
-	    }
-	  }
-	  die "Failed to determine read and genome conversion from line: $line1\n\n" unless ($read_conversion and $read_conversion);
-
-	
-	  my $index;
-	  if ($read_conversion eq 'CT' and $genome_conversion eq 'CT') { ## original top strand
-	    $index = 0;
-	    $strand = '+';
-	  } elsif ($read_conversion eq 'GA' and $genome_conversion eq 'CT') { ## complementary to original top strand
-	    $index = 1;
-	    $strand = '-';
-	  } elsif ($read_conversion eq 'GA' and $genome_conversion eq 'GA') { ## complementary to original bottom strand
-	    $index = 2;
-	    $strand = '+';
-	  } elsif ($read_conversion eq 'CT' and $genome_conversion eq 'GA') { ## original bottom strand
-	    $index = 3;
-	    $strand = '-';
-	  } else {
-	    die "Unexpected combination of read and genome conversion: '$read_conversion' / '$genome_conversion'\n";
-	  }
-	
-	  # if the read aligns in forward orientation we can certainly use the start position of read 1, and only need to work out the end position of read 2	
-	  if ($index == 0 or $index == 2){
-	
-	    ### reading in the next line
-	    $_ = <IN>;
-	    # the only thing we need is the end position
-	    ($end,my $cigar_2) = (split (/\t/))[3,5];
-
-	    $end -= 1; # only need to adjust this once
-	
-	    # for InDel free matches we can simply use the M number in the CIGAR string
-	    if ($cigar_2 =~ /^(\d+)M$/){ # linear match
-	      $end += $1;
-	    }
-	    else{
-	      # parsing CIGAR string
-	      my @len = split (/\D+/,$cigar_2); # storing the length per operation
-	      my @ops = split (/\d+/,$cigar_2); # storing the operation
-	      shift @ops; # remove the empty first element
-	      die "CIGAR string contained a non-matching number of lengths and operations ($cigar_2)\n" unless (scalar @len == scalar @ops);
-	
-	      # warn "CIGAR string; $cigar_2\n";
-	      ### determining end position of the read
-	      foreach my $index(0..$#len){
-		if ($ops[$index] eq 'M'){  # standard matching bases
-		  $end += $len[$index];
-		  # warn "Operation is 'M', adding $len[$index] bp\n";
-		}
-		elsif($ops[$index] eq 'I'){ # insertions do not affect the end position
-		  # warn "Operation is 'I', next\n";
-		}
-		elsif($ops[$index] eq 'D'){ # deletions do affect the end position
-		  #  warn "Operation is 'D',adding $len[$index] bp\n";
-		  $end += $len[$index];
-		}
-		else{
-		  die "Found CIGAR operations other than M, I or D: '$ops[$index]'. Not allowed at the moment\n";
-		}
-	      }
-	    }
-	  }
-	  else{
-	    # else read 1 aligns in reverse orientation and we need to work out the end of the fragment first, and use the start of the next line
-
-	    $end = $start - 1; # need to adjust this only once
-	
-	    # for InDel free matches we can simply use the M number in the CIGAR string
-	    if ($cigar =~ /^(\d+)M$/){ # linear match
-	      $end += $1;
-	    }
-	    else{
-	      # parsing CIGAR string
-	      my @len = split (/\D+/,$cigar); # storing the length per operation
-	      my @ops = split (/\d+/,$cigar); # storing the operation
-	      shift @ops; # remove the empty first element
-	      die "CIGAR string contained a non-matching number of lengths and operations ($cigar)\n" unless (scalar @len == scalar @ops);
-	
-	      # warn "CIGAR string; $cigar\n";
-	      ### determining end position of the read
-	      foreach my $index(0..$#len){
-		if ($ops[$index] eq 'M'){  # standard matching bases
-		  $end += $len[$index];
-		  # warn "Operation is 'M', adding $len[$index] bp\n";
-		}
-		elsif($ops[$index] eq 'I'){ # insertions do not affect the end position
-		  # warn "Operation is 'I', next\n";
-		}
-		elsif($ops[$index] eq 'D'){ # deletions do affect the end position
-		  # warn "Operation is 'D',adding $len[$index] bp\n";
-		  $end += $len[$index];
-		}
-		else{
-		  die "Found CIGAR operations other than M, I or D: '$ops[$index]'. Not allowed at the moment\n";
-		}
-	      }
-	    }
-	
-	    ### reading in the next line
-	    $_ = <IN>;
-	    # the only thing we need is the start position
-	    ($start) = (split (/\t/))[3];
-	  }
-	  $composite = join (":",$strand,$chr,$start,$end);
-	}
-	
-	else{
-	  die "Input must be single or paired-end\n";
-	}
-      }
-
-      if (exists $unique_seqs{$composite}){
-	++$removed;
-	unless (exists $positions{$composite}){
-	  $positions{$composite}++;
-	}
-      }
-      else{
-	if ($paired){
-	  unless ($vanilla){
-	    print OUT "$line1"; # printing first paired-end line for SAM output
-	  }
-	}
-	print OUT "$_"; # printing single-end SAM alignment or second paired-end line
-	$unique_seqs{$composite}++;
-      }
-    }
-
-    my $percentage;
-    my $percentage_leftover;
-    my $leftover = $count - $removed;
-
-    unless ($count == 0){
-      $percentage = sprintf("%.2f",$removed/$count*100);
-      $percentage_leftover = sprintf("%.2f",$leftover/$count*100);
-    }
-    else{
-      $percentage = 'N/A';
-      $percentage_leftover = 'N/A';
-    }
-
-    warn "\nTotal number of alignments analysed in $file:\t$count\n";
-    warn "Total number duplicated alignments removed:\t$removed ($percentage%)\n";
-    warn "Duplicated alignments were found at:\t",scalar keys %positions," different position(s)\n\n";
-    warn "Total count of deduplicated leftover sequences: $leftover ($percentage_leftover% of total)\n\n";
-
-    print REPORT "\nTotal number of alignments analysed in $file:\t$count\n";
-    print REPORT "Total number duplicated alignments removed:\t$removed ($percentage%)\n";
-    print REPORT "Duplicated alignments were found at:\t",scalar keys %positions," different position(s)\n\n";
-    print REPORT "Total count of deduplicated leftover sequences: $leftover ($percentage_leftover% of total)\n\n";
-  }
-
-  close OUT or warn "Failed to close output filehandle: $!\n";
-  close REPORT or warn "Failed to close report filehandle: $!\n";
-
-}
-
-
-sub deduplicate_barcoded_rrbs{
-
-  my $file = shift;
-
-  my %unique_seqs;
-  my %positions;
-
-  if ($file =~ /\.gz$/){
-    open (IN,"gunzip -c $file |") or die "Unable to read from gzipped file $file: $!\n";
-  }
-  elsif ($file =~ /\.bam$/){
-    open (IN,"$samtools_path view -h $file |") or die "Unable to read from BAM file $file: $!\n";
-  }
-  else{
-    open (IN,$file) or die "Unable to read from $file: $!\n";
-  }
-
-  my $outfile = $file;
-  $outfile =~ s/\.gz$//;
-  $outfile =~ s/\.sam$//;
-  $outfile =~ s/\.bam$//;
-  $outfile =~ s/\.txt$//;
-
-  if ($vanilla){
-    $outfile =~ s/$/_dedup_RRBS.txt/;
-  }
-  else{
-    if ($bam == 1){
-      $outfile =~ s/$/.dedup_RRBS.bam/;
-    }
-    elsif ($bam == 2){
-      $outfile =~ s/$/.dedupRRBS.sam.gz/;
-    }
-    else{
-      $outfile =~ s/$/.dedup_RRBS.sam/;
-    }
-  }
-  if ($bam == 1){
-    open (OUT,"| $samtools_path view -bSh 2>/dev/null - > $outfile") or die "Failed to write to $outfile: $!\n";
-  }
-  elsif($bam == 2){ ### no Samtools found on system. Using GZIP compression instead
-    open (OUT,"| gzip -c - > $outfile") or die "Failed to write to $outfile: $!\n";
-  }
-  else{
-    open (OUT,'>',$outfile) or die "Unable to write to $outfile: $!\n";
-  }
-
-  ### This mode only supports Bismark SAM output
-  my $count = 0;
-  my $unique_seqs = 0;
-  my $removed = 0;
-
-  while (<IN>){
-
-    if ($count == 0){
-      if ($_ =~ /^Bismark version:/){
-	warn "The file appears to be in the custom Bismark and not SAM format. Please see option --vanilla!\n";
-	sleep (2);
-	print_helpfile();
-	exit;
-      }
-    }
-
-    ### if this was a SAM file we ignore header lines
-    if (/^\@\w{2}\t/){
-      warn "skipping SAM header line:\t$_";
-      print OUT; # Printing the header lines again into the de-duplicated file
-      next;
-    }
-
-    ++$count;
-    my $composite; # storing positional data. For single end data we are only using the start coordinate since the end might have been trimmed to different lengths
-    ### in this barcoded mode we also store the read barcode as additional means of assisting the deduplication
-    ### in effect the $composite string looks like this (separated by ':'):
-
-    ### FLAG:chromosome:start:barcode
-
-    my $end;
-    my $line1;
-
-    # SAM format
-    my ($id,$strand,$chr,$start,$cigar) = (split (/\t/))[0,1,2,3,5]; # we are assigning the FLAG value to $strand
-
-    $id =~ /:(\w+)$/;
-    my $barcode = $1;
-    unless ($barcode){
-      die "Failed to extract a barcode from the read ID (last element of each read ID needs to be the barcode sequence, e.g. ':CATG'\n\n";
-    }
-
-    ### SAM single-end
-    if ($single){
-
-      if ($strand == 0 ){
-	### read aligned to the forward strand. No action needed
-      }
-      elsif ($strand == 16){
-	### read is on reverse strand
-	
-	$start -= 1; # only need to adjust this once
-	
-	# for InDel free matches we can simply use the M number in the CIGAR string
-	if ($cigar =~ /^(\d+)M$/){ # linear match
-	  $start += $1;
-	}
-	else{
-	  # parsing CIGAR string
-	  my @len = split (/\D+/,$cigar); # storing the length per operation
-	  my @ops = split (/\d+/,$cigar); # storing the operation
-	  shift @ops; # remove the empty first element
-	  die "CIGAR string contained a non-matching number of lengths and operations\n" unless (scalar @len == scalar @ops);
-
-	  # warn "CIGAR string; $cigar\n";
-	  ### determining end position of a read
-	  foreach my $index(0..$#len){
-	    if ($ops[$index] eq 'M'){  # standard matching bases
-	      $start += $len[$index];
-	      # warn "Operation is 'M', adding $len[$index] bp\n";
-	    }
-	    elsif($ops[$index] eq 'I'){ # insertions do not affect the end position
-	      # warn "Operation is 'I', next\n";
-	    }
-	    elsif($ops[$index] eq 'D'){ # deletions do affect the end position
-	      #  warn "Operation is 'D',adding $len[$index] bp\n";
-	      $start += $len[$index];
-	    }
-	    else{
-	      die "Found CIGAR operations other than M, I or D: '$ops[$index]'. Not allowed at the moment\n";
-	    }
-	  }
-	}
-      }
-
-      ### Here we take the barcode sequence into consideration
-      $composite = join (":",$strand,$chr,$start,$barcode);
-      # warn "$composite\n\n";
-      # sleep(1);
-    }
-    elsif($paired){
-
-      ### storing the current line
-      $line1 = $_;
-
-      my $read_conversion;
-      my $genome_conversion;
-
-      while ( /(XR|XG):Z:([^\t]+)/g ) {
-	my $tag = $1;
-	my $value = $2;
-	
-	if ($tag eq "XR") {
-	  $read_conversion = $value;
-	  $read_conversion =~ s/\r//;
-	  chomp $read_conversion;
-	}
-	elsif ($tag eq "XG") {
-	  $genome_conversion = $value;
-	  $genome_conversion =~ s/\r//;
-	  chomp $genome_conversion;
-	}
-      }
-      die "Failed to determine read and genome conversion from line: $line1\n\n" unless ($read_conversion and $read_conversion);
-
-	
-      my $index;
-      if ($read_conversion eq 'CT' and $genome_conversion eq 'CT') { ## original top strand
-	$index = 0;
-	$strand = '+';
-      } elsif ($read_conversion eq 'GA' and $genome_conversion eq 'CT') { ## complementary to original top strand
-	$index = 1;
-	$strand = '-';
-      } elsif ($read_conversion eq 'GA' and $genome_conversion eq 'GA') { ## complementary to original bottom strand
-	$index = 2;
-	$strand = '+';
-      } elsif ($read_conversion eq 'CT' and $genome_conversion eq 'GA') { ## original bottom strand
-	$index = 3;
-	$strand = '-';
-      } else {
-	die "Unexpected combination of read and genome conversion: '$read_conversion' / '$genome_conversion'\n";
-      }
-	
-      # if the read aligns in forward orientation we can certainly use the start position of read 1, and only need to work out the end position of read 2	
-      if ($index == 0 or $index == 2){
-	
-	### reading in the next line
-	$_ = <IN>;
-	# the only thing we need is the end position
-	($end,my $cigar_2) = (split (/\t/))[3,5];
-
-	$end -= 1; # only need to adjust this once
-	
-	# for InDel free matches we can simply use the M number in the CIGAR string
-	if ($cigar_2 =~ /^(\d+)M$/){ # linear match
-	  $end += $1;
-	}
-	else{
-	  # parsing CIGAR string
-	  my @len = split (/\D+/,$cigar_2); # storing the length per operation
-	  my @ops = split (/\d+/,$cigar_2); # storing the operation
-	  shift @ops; # remove the empty first element
-	  die "CIGAR string contained a non-matching number of lengths and operations ($cigar_2)\n" unless (scalar @len == scalar @ops);
-	
-	  # warn "CIGAR string; $cigar_2\n";
-	  ### determining end position of the read
-	  foreach my $index(0..$#len){
-	    if ($ops[$index] eq 'M'){  # standard matching bases
-	      $end += $len[$index];
-	      # warn "Operation is 'M', adding $len[$index] bp\n";
-	    }
-	    elsif($ops[$index] eq 'I'){ # insertions do not affect the end position
-	      # warn "Operation is 'I', next\n";
-	    }
-	    elsif($ops[$index] eq 'D'){ # deletions do affect the end position
-	      #  warn "Operation is 'D',adding $len[$index] bp\n";
-	      $end += $len[$index];
-	    }
-	    else{
-	      die "Found CIGAR operations other than M, I or D: '$ops[$index]'. Not allowed at the moment\n";
-	    }
-	  }
-	}
-      }
-      else{
-	# else read 1 aligns in reverse orientation and we need to work out the end of the fragment first, and use the start of the next line
-	
-	$end = $start - 1; # need to adjust this only once
-	
-	# for InDel free matches we can simply use the M number in the CIGAR string
-	if ($cigar =~ /^(\d+)M$/){ # linear match
-	  $end += $1;
-	}
-	else{
-	  # parsing CIGAR string
-	  my @len = split (/\D+/,$cigar); # storing the length per operation
-	  my @ops = split (/\d+/,$cigar); # storing the operation
-	  shift @ops; # remove the empty first element
-	  die "CIGAR string contained a non-matching number of lengths and operations ($cigar)\n" unless (scalar @len == scalar @ops);
-	
-	  # warn "CIGAR string; $cigar\n";
-	  ### determining end position of the read
-	  foreach my $index(0..$#len){
-	    if ($ops[$index] eq 'M'){  # standard matching bases
-	      $end += $len[$index];
-	      # warn "Operation is 'M', adding $len[$index] bp\n";
-	    }
-	    elsif($ops[$index] eq 'I'){ # insertions do not affect the end position
-	      # warn "Operation is 'I', next\n";
-	    }
-	    elsif($ops[$index] eq 'D'){ # deletions do affect the end position
-	      # warn "Operation is 'D',adding $len[$index] bp\n";
-	      $end += $len[$index];
-	    }
-	    else{
-	      die "Found CIGAR operations other than M, I or D: '$ops[$index]'. Not allowed at the moment\n";
-	    }
-	  }
-	}
-	
-	### reading in the next line
-	$_ = <IN>;
-	# the only thing we need is the start position
-	($start) = (split (/\t/))[3];
-      }
-
-      ### Here we take the barcode sequence into consideration
-      $composite = join (":",$strand,$chr,$start,$end,$barcode);
-    }
-    else{
-      die "Input must be single or paired-end\n";
-    }
-
-    if (exists $unique_seqs{$composite}){
-      ++$removed;
-      unless (exists $positions{$composite}){
-	$positions{$composite}++;
-      }
-    }
-    else{
-      if ($paired){
-	print OUT $line1; # printing first paired-end line for SAM output
-      }
-      print OUT; # printing single-end SAM alignment or second paired-end line
-      $unique_seqs{$composite}++;
-    }
-  }
-
-  my $percentage;
-  my $percentage_leftover;
-  my $leftover = $count - $removed;
-
-  unless ($count == 0){
-    $percentage = sprintf("%.2f",$removed/$count*100);
-    $percentage_leftover = sprintf("%.2f",$leftover/$count*100);
-  }
-  else{
-    $percentage = 'N/A';
-    $percentage_leftover = 'N/A';
-  }
-
-
-  warn "\nTotal number of alignments analysed in $file:\t$count\n";
-  warn "Total number duplicated alignments removed:\t$removed ($percentage%)\n";
-  warn "Duplicated alignments were found at:\t",scalar keys %positions," different position(s)\n\n";
-  warn "Total count of deduplicated leftover sequences: $leftover ($percentage_leftover% of total)\n\n";
-
-  print REPORT "\nTotal number of alignments analysed in $file:\t$count\n";
-  print REPORT "Total number duplicated alignments removed:\t$removed ($percentage%)\n";
-  print REPORT "Duplicated alignments were found at:\t",scalar keys %positions," different position(s)\n\n";
-  print REPORT "Total count of deduplicated leftover sequences: $leftover ($percentage_leftover% of total)\n\n";
-
-}
-
-sub bam_isEmpty{
-      
-    my $file = shift;
-
-    if ($file =~ /\.bam$/){
-	open (EMPTY,"$samtools_path view $file |") or die "Unable to read from BAM file $file: $!\n";
-    }
-    else{
-	open (EMPTY,$file) or die "Unable to read from $file: $!\n";
-    }
-    my $count = 0;
-    while (<EMPTY>){
-	if ($_){
-	    $count++;  # file contains data, fine.
-	}
-	last; # one line is enough
-    }
-
-    if ($count == 0){
-	die "\n### File appears to be empty, terminating deduplication process. Please make sure the input file has not been truncated. ###\n\n";
-    }
-    close EMPTY or warn "$!\n";
-}
-
-
-sub print_helpfile{
-  print "\n",'='x111,"\n";
-  print "\nThis script is supposed to remove alignments to the same position in the genome from the Bismark mapping output\n(both single and paired-end SAM files), which can arise by e.g. excessive PCR amplification. If sequences align\nto the same genomic position but on different strands they will be scored individually.\n\nNote that deduplication is not recommended for RRBS-type experiments!\n\nIn the default mode, the first alignment to a given position will be used irrespective of its methylation call\n(this is the fastest option, and as the alignments are not ordered in any way this is also near enough random).\n\n";
-  print "For single-end alignments only use the start coordinate of a read will be used for deduplication.\n\n";
-  print "For paired-end alignments the start-coordinate of the first read and the end coordinate of the second\nread will be used for deduplication. ";
-  print "This script expects the Bismark output to be in SAM format\n(Bismark v0.6.x or higher). To deduplicate the old custom Bismark output please specify '--vanilla'.\n\n";
-  print "*** Please note that for paired-end BAM files the deduplication script expects Read1 and Read2 to\nfollow each other in consecutive lines! If the file has been sorted by position make sure that you resort it\nby read name first (e.g. using samtools sort -n)  ***\n\n";
-
-  print '='x111,"\n\n";
-  print ">>> USAGE: ./deduplicate_bismark_alignment_output.pl [options] filename(s) <<<\n\n";
-
-  print "-s/--single\t\tdeduplicate single-end Bismark files (default format: SAM)\n";
-  print "-p/--paired\t\tdeduplicate paired-end Bismark files (default format: SAM)\n\n";
-  print "--vanilla\t\tThe input file is in the old custom Bismark format and not in SAM format\n\n";
-  print "--barcode\t\tIn addition to chromosome, start position and orientation this will also take a potential barcode into\n                        consideration while deduplicating. The barcode needs to be the last element of the read ID and separated\n                        by a ':', e.g.: MISEQ:14:000000000-A55D0:1:1101:18024:2858_1:N:0:CTCCT\n\n";
-  print "--bam\t\t\tThe output will be written out in BAM format instead of the default SAM format. This script will\n\t\t\tattempt to use the path to Samtools that was specified with '--samtools_path', or, if it hasn't\n\t\t\tbeen specified, attempt to find Samtools in the PATH. If no installation of Samtools can be found,\n\t\t\tthe SAM output will be compressed with GZIP instead (yielding a .sam.gz output file)\n\n";
-  print "--samtools_path\t\tThe path to your Samtools installation, e.g. /home/user/samtools/. Does not need to be specified\n\t\t\texplicitly if Samtools is in the PATH already\n\n";
-  print "--version\t\tPrint version information and exit\n";
-
-  print '='x111,"\n\n";
-
-  print "This script was last modified on November 04, 2015\n\n";
-}
-
-
-
-
-sub test_positional_sorting{
-
-  my $filename = shift;
-
-  print "\nNow testing Bismark result file $filename for positional sorting (which would be bad...)\t";
-  sleep(1);
-
-  if ($filename =~ /\.gz$/) {
-    open (TEST,"gunzip -c $filename |") or die "Can't open gzipped file $filename: $!\n";
-  }
-  elsif ($filename =~ /bam$/ ||  isBam($filename) ){ ### this would allow to read BAM files that do not end in *.bam
-    if ($samtools_path){
-      open (TEST,"$samtools_path view -h $filename |") or die "Can't open BAM file $filename: $!\n";
-    }
-    else{
-      die "Sorry couldn't find an installation of Samtools. Either specifiy an alternative path using the option '--samtools_path /your/path/', or use a SAM file instead\n\n";
-    }
-  }
-  else {
-    open (TEST,$filename) or die "Can't open file $filename: $!\n";
-  }
-
-  my $count = 0;
-
-  while (<TEST>) {
-    if (/^\@/) {	     # testing header lines if they contain the @SO flag (for being sorted)
-      if (/^\@SO/) {
-	die "SAM/BAM header line '$_' indicates that the Bismark aligment file has been sorted by chromosomal positions which is is incompatible with correct methylation extraction. Please use an unsorted file instead (e.g. use samtools sort -n)\n\n";
-      }
-      next;
-    }
-    $count++;
-
-    last if ($count > 100000); # else we test the first 100000 sequences if they start with the same read ID
-
-    my ($id_1) = (split (/\t/));
-
-    ### reading the next line which should be read 2
-    $_ = <TEST>;
-    my ($id_2) = (split (/\t/));
-    last unless ($id_2);
-    ++$count;
-
-    if ($id_1 eq $id_2){
-      ### ids are the same
-      next;
-    }
-    else{ ### in previous versions of Bismark we appended /1 and /2 to the read IDs for easier eyeballing which read is which. These tags need to be removed first
-      my $id_1_trunc = $id_1;
-      $id_1_trunc =~ s/\/1$//;
-      my $id_2_trunc = $id_2;
-      $id_2_trunc =~ s/\/2$//;
-
-      unless ($id_1_trunc eq $id_2_trunc){
-	die "\nThe IDs of Read 1 ($id_1) and Read 2 ($id_2) are not the same. This might be a result of sorting the paired-end SAM/BAM files by chromosomal position which is not compatible with correct methylation extraction. Please use an unsorted file instead (e.g. use samtools sort -n)\n\n";
-      }
-    }
-  }
-  #  close TEST or die $!; somehow fails on our cluster...
-  ### If it hasen't died so far then it seems the file is in the correct Bismark format (read 1 and read 2 of a pair directly following each other)
-  warn "...passed!\n";
-  sleep(1);
-
-}
-
-sub isBam{
-
-  my $filename = shift;
-
-  # reading the first line of the input file to see if it is a BAM file in disguise (i.e. a BAM file that does not end in *.bam which may be produced by Galaxy)
-  open (DISGUISE,"gunzip -c $filename |") or die "Failed to open filehandle DISGUISE for $filename\n\n";
-
-  ### when BAM files read through a gunzip -c stream they start with BAM...
-  my $bam_in_disguise = <DISGUISE>;
-  # warn "BAM in disguise: $bam_in_disguise\n\n";
-
-  if ($bam_in_disguise){
-    if ($bam_in_disguise =~ /^BAM/){
-      close (DISGUISE) or warn "Had trouble closing filehandle BAM in disguise: $!\n";
-      return 1;
-    }
-    else{
-      close (DISGUISE) or warn "Had trouble closing filehandle BAM in disguise: $!\n";
-     return 0;
-    }
-  }
-  else{
-    close (DISGUISE) or warn "Had trouble closing filehandle BAM in disguise: $!\n";
-    return 0;
-  }
-}
-
-
-
-
-
-#####################################
-
-### The following subroutine "deduplicate_representative" only works correctly for reads that do not contain any indels (as in only Bowtie1-based alignments). 
-### Please refrain from using it unless you want to test something out.
-
-#####################################
-
-sub deduplicate_representative {
-  my $file = shift;
-
-  my %positions;
-  my %unique_seqs;
-
-  my $count = 0;
-  my $unique_seqs = 0;
-  my $removed = 0;
-
-  ### going through the file first and storing all positions as well as their methylation call strings in a hash
-  if ($file =~ /\.gz$/){
-    open (IN,"gunzip -c $file |") or die "Unable to read from gzipped file $file: $!\n";
-  }
-  elsif ($file =~ /\.bam$/){
-    open (IN,"$samtools_path view -h $file |") or die "Unable to read from BAM file $file: $!\n";
-  }
-  else{
-    open (IN,$file) or die "Unable to read from $file: $!\n";
-  }
-
-  if ($single){
-
-    my $outfile = $file;
-    $outfile =~ s/\.gz$//;
-    $outfile =~ s/\.sam$//;
-    $outfile =~ s/\.bam$//;
-    $outfile =~ s/\.txt$//;
-
-    if ($vanilla){
-      $outfile =~ s/$/.deduplicated_to_representative_sequences.txt/;
-    }
-    else{
-      if ($bam == 1){
-	$outfile =~ s/$/.deduplicated_to_representative_sequences.bam/;
-      }
-      elsif ($bam == 2){
-	$outfile =~ s/$/.deduplicated_to_representative_sequences.sam.gz/;
-      }
-      else{
-	$outfile =~ s/$/.deduplicated_to_representative_sequences.sam/;
-      }
-    }
-
-    if ($bam == 1){
-      open (OUT,"| $samtools_path view -bSh 2>/dev/null - > $outfile") or die "Failed to write to $outfile: $!\n";
-    }
-    elsif($bam == 2){ ### no Samtools found on system. Using GZIP compression instead
-      open (OUT,"| gzip -c - > $outfile") or die "Failed to write to $outfile: $!\n";
-    }
-    else{
-      open (OUT,'>',$outfile) or die "Unable to write to $outfile: $!\n";
-    }
-
-    warn "Reading and storing all alignment positions\n";
-
-    ### need to proceed slightly differently for the custom Bismark and Bismark SAM output
-    if ($vanilla){
-      $_ = <IN>; # Bismark version header
-      print OUT; # Printing the Bismark version to the de-duplicated file again
-    }
-
-    while (<IN>){
-
-      if ($count == 0){
-	if ($_ =~ /^Bismark version:/){
-	  warn "The file appears to be in the custom Bismark and not SAM format. Please see option --vanilla!\n";
-	  sleep (2);
-	  print_helpfile();
-	  exit;
-	}
-      }
-
-      ### if this was a SAM file we ignore header lines
-      unless ($vanilla){
-	if (/^\@\w{2}\t/){
-	  warn "skipping SAM header line:\t$_";
-	  print OUT; # Printing the header lines again into the de-duplicated file
-	  next;
-	}
-      }
-
-      my ($strand,$chr,$start,$end,$meth_call);
-
-      if ($vanilla){
-	($strand,$chr,$start,$end,$meth_call) = (split (/\t/))[1,2,3,4,7];
-      }
-      else{ # SAM format
-
-	($strand,$chr,$start,my $seq,$meth_call) = (split (/\t/))[1,2,3,9,13]; # we are assigning the FLAG value to $strand
-	### SAM single-end
-	$end = $start + length($seq) - 1;
-      }
-
-      my $composite = join (":",$strand,$chr,$start,$end);
-
-      $count++;
-      $positions{$composite}->{$meth_call}->{count}++;
-      $positions{$composite}->{$meth_call}->{alignment} = $_;
-    }
-    warn "Stored ",scalar keys %positions," different positions for $count sequences in total (+ and - alignments to the same position are scored individually)\n\n";
-    close IN or warn $!;
-  }
-
-  elsif ($paired){
-
-    ### we are going to concatenate both methylation call strings from the paired end file to form a joint methylation call string
-
-    my $outfile = $file;
-    if ($vanilla){
-      $outfile =~ s/$/_deduplicated_to_representative_sequences_pe.txt/;
-    }
-    else{
-      $outfile =~ s/$/_deduplicated_to_representative_sequences_pe.sam/;
-    }
-
-    open (OUT,'>',$outfile) or die "Unable to write to $outfile: $!\n";
-    warn "Reading and storing all alignment positions\n";
-
-    ### need to proceed slightly differently for the custom Bismark and Bismark SAM output
-    if ($vanilla){
-      $_ = <IN>; # Bismark version header
-      print OUT; # Printing the Bismark version to the de-duplicated file again
-    }
-
-    while (<IN>){
-
-      if ($count == 0){
-	if ($_ =~ /^Bismark version:/){
-	  warn "The file appears to be in the custom Bismark and not SAM format. Please see option --vanilla!\n";
-	  sleep (2);
-	  print_helpfile();
-	  exit;
-	}
-      }
-
-      ### if this was a SAM file we ignore header lines
-      unless ($vanilla){
-	if (/^\@\w{2}\t/){
-	  warn "skipping SAM header line:\t$_";
-	  print OUT; # Printing the header lines again into the de-duplicated file
-	  next;
-	}
-      }
-
-      my ($strand,$chr,$start,$end,$meth_call_1,$meth_call_2);
-      my $line1;
-
-      if ($vanilla){
-	($strand,$chr,$start,$end,$meth_call_1,$meth_call_2) = (split (/\t/))[1,2,3,4,7,10];
-      }
-      else{ # SAM paired-end format
-	
-	($strand,$chr,$start,$meth_call_1) = (split (/\t/))[1,2,3,13]; # we are assigning the FLAG value to $strand
-	
-	### storing the first line (= read 1 alignment)	
-	$line1 = $_;
-	
-	### reading in the next line
-	$_ = <IN>;
-	# we only need the end position and the methylation call
-	(my $pos,my $seq_2,$meth_call_2) = (split (/\t/))[3,9,13];
-	$end = $pos + length($seq_2) - 1;
-      }
-
-      my $composite = join (":",$strand,$chr,$start,$end);
-      $count++;
-      my $meth_call = $meth_call_1.$meth_call_2;
-
-      $positions{$composite}->{$meth_call}->{count}++;
-      if ($vanilla){
-	$positions{$composite}->{$meth_call}->{alignment} = $_;
-      }
-      else{ # SAM PAIRED-END
-	$positions{$composite}->{$meth_call}->{alignment_1} = $line1;
-	$positions{$composite}->{$meth_call}->{alignment_2} = $_;
-      }
-    }
-    warn "Stored ",scalar keys %positions," different positions for $count sequences in total (+ and - alignments to the same position are scored individually)\n\n";
-    close IN or warn $!;
-  }
-
-  ### PRINTING RESULTS
-
-  ### Now going through all stored positions and printing out the methylation call which is most representative, i.e. the one which occurred most often
-  warn "Now printing out alignments with the most representative methylation call(s)\n";
-
-  foreach my $pos (keys %positions){
-    foreach my $meth_call (sort { $positions{$pos}->{$b}->{count} <=> $positions{$pos}->{$a}->{count} }keys %{$positions{$pos}}){
-      if ($paired){
-	if ($vanilla){
-	  print OUT $positions{$pos}->{$meth_call}->{alignment};
-	}
-	else{
-	  print OUT $positions{$pos}->{$meth_call}->{alignment_1}; # SAM read 1
-	  print OUT $positions{$pos}->{$meth_call}->{alignment_2}; # SAM read 2
-	}
-      }
-      else{ # single-end
-	print OUT $positions{$pos}->{$meth_call}->{alignment};
-      }
-      $unique_seqs++;
-      last; ### exiting once we printed a sequence with the most frequent methylation call for a position
-    }
-  }
-
-  my $percentage;
-  unless ($count == 0){
-    $percentage = sprintf ("%.2f",$unique_seqs*100/$count);
-  }
-  else{
-    $percentage = 'N/A';
-  }
-
-  warn "\nTotal number of alignments analysed in $file:\t$count\n";
-  warn "Total number of representative alignments printed from $file in total:\t$unique_seqs ($percentage%)\n\n";
-  print REPORT "\nTotal number of alignments analysed in $file:\t$count\n";
-  print REPORT "Total number of representative alignments printed from $file in total:\t$unique_seqs ($percentage%)\n\n";
-
-}
-
-
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bismark_deduplicate_wrapper.py	Wed Aug 22 08:09:42 2018 -0400
@@ -0,0 +1,81 @@
+#!/usr/bin/python
+
+import argparse
+import logging
+import os
+import shutil
+import subprocess
+import sys
+import signal
+import tempfile
+from glob import glob
+
+
+def stop_err(logger, msg):
+    logger.critical(msg)
+    sys.exit(1)
+
+
+def restore_sigpipe():
+    """
+    Needed to handle samtools view
+    """
+    signal.signal(signal.SIGPIPE, signal.SIG_DFL)
+
+
+def log_subprocess_output(logger, pipe):
+    for line in iter(pipe.readline, b''):
+        logger.debug(line.decode().rstrip())
+
+
+def get_arg():
+    parser = argparse.ArgumentParser()
+    parser.add_argument('--single_or_paired',  dest='single_or_paired')
+    parser.add_argument('--input', dest='input', metavar='input')
+    parser.add_argument('--output_report', dest='output_report', metavar='output_report')
+    parser.add_argument('--output_bam', dest='output_bam', metavar='output_report')
+    parser.add_argument('--log_report', dest='log_report', metavar='log_filename', type=str)
+    args = parser.parse_args()
+    return args
+
+
+def __main__():
+    args = get_arg()
+
+    logger = logging.getLogger('bismark_deduplicate_wrapper')
+    logger.setLevel(logging.DEBUG)
+    ch = logging.StreamHandler(sys.stdout)
+    if args.log_report:
+        ch.setLevel(logging.WARNING)
+        handler = logging.FileHandler(args.log_report)
+        handler.setLevel(logging.DEBUG)
+        logger.addHandler(handler)
+    else:
+        ch.setLevel(logging.DEBUG)
+    logger.addHandler(ch)
+
+    # ensure the input has a .bam suffix
+    tmp_dir = tempfile.mkdtemp(prefix='tmp', suffix='')
+    os.chdir(tmp_dir)
+    default_reads_name = 'submitted_reads.bam'
+    os.symlink(args.input, default_reads_name)
+
+    single_or_paired = '-s' if args.single_or_paired == 'single' else '-p'
+    cmd = ['deduplicate_bismark', single_or_paired, default_reads_name, '--bam']
+    logger.info("Deduplicating with: '%s'", " ".join(cmd))
+    process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
+                               preexec_fn=restore_sigpipe)
+    proc_out, proc_err = process.communicate()
+    logger.info(proc_out)
+    if process.returncode != 0:
+        stop_err(logger, "Bismark deduplication error (also check the log file if any)!\n%s" % proc_err)
+
+    deduplicated_out_name = 'submitted_reads.deduplicated.bam'
+    deduplicated_report_name = 'submitted_reads.deduplication_report.txt'
+    logger.debug("Moving '%s' to galaxy: '%s'.", deduplicated_out_name, args.output_bam)
+    shutil.move(deduplicated_out_name, args.output_bam )
+    logger.debug("Moving '%s' to galaxy: '%s'.", deduplicated_report_name, args.output_report)
+    shutil.move('submitted_reads.deduplication_report.txt', args.output_report)
+    logger.debug("Done.")
+
+if __name__=="__main__": __main__()
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bismark_deduplicate_wrapper.xml	Wed Aug 22 08:09:42 2018 -0400
@@ -0,0 +1,66 @@
+<tool id="bismark_deduplicate" name="Bismark Deduplicate" version="0.20.0" profile="18.01">
+    <description>Deduplicates reads mapped by Bismark</description>
+    <requirements>
+        <requirement type="package" version="0.20.0">bismark</requirement>
+        <requirement type="package" version="1.8">samtools</requirement>
+        <requirement type="package" version="2.3.4.2">bowtie2</requirement>
+    </requirements>
+    <command><![CDATA[
+        python '$__tool_directory__/bismark_deduplicate_wrapper.py'
+
+        --single_or_paired $sPaired
+
+        --input '$mapping_output'
+        --output_report '$output_report'
+        --output_bam '$output_bam'
+        #if $separate_logfile:
+           --log_report '$log_report'
+        #end if
+]]>
+    </command>
+    <inputs>
+        <param name="sPaired" type="select" label="Is this library mate-paired?">
+            <option value="single">Single-end</option>
+            <option value="paired">Paired-end</option>
+        </param>
+        <param name="mapping_output" type="data" format="qname_input_sorted.bam,bam"
+               label="Submit the resulting bam/sam file from Bismark bisulfite mapper"/>
+        <param name="separate_logfile" type="boolean" truevalue="true" falsevalue="false" checked="False"
+               label="Create a separate logfile, otherwise logs are added to the dataset info."/>
+    </inputs>
+
+    <outputs>
+        <data name="output_bam" format="qname_sorted.bam"
+              label="${tool.name} on ${on_string}: deduplicated mapped reads"/>
+        <data name="output_report" format="txt" label="${tool.name} on ${on_string}: deduplication report"/>
+        <data name="log_report" format="txt" label="${tool.name} on ${on_string}: log report (tool stdout)">
+            <filter>( separate_logfile is True )</filter>
+        </data>
+    </outputs>
+
+    <tests>
+        <test>
+            <param name="sPaired" value="single"/>
+            <param name="mapping_output" value="mapped_reads.bam" ftype="qname_sorted.bam"/>
+            <output name="output_bam" file="dedup_reads.bam" ftype="qname_sorted.bam"/>
+            <output name="output_report" file="dedup_report.txt" ftype="txt"/>
+        </test>
+    </tests>
+
+    <help>
+        <![CDATA[
+**What it does**
+
+	| This tool is supposed to remove alignments to the same position in the genome from the Bismark mapping output (both single and paired-end SAM files), which can arise by e.g. excessive PCR amplification. If sequences align to the same genomic position but on different strands they will be scored individually.
+	|
+	| Note that deduplication is not recommended for RRBS-type experiments!
+	|
+	| For single-end alignments only use the start-coordinate of a read will be used for deduplication.
+	| For paired-end alignments the start-coordinate of the first read and the end coordinate of the second read will be used for deduplication.
+
+]]>
+    </help>
+    <citations>
+        <citation type="doi">10.1093/bioinformatics/btr167</citation>
+    </citations>
+</tool>
--- a/bismark_mapping/bismark	Sat May 06 13:18:09 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,10220 +0,0 @@
-#!/usr/bin/env perl
-use strict;
-use warnings;
-use IO::Handle;
-use Cwd;
-$|++;
-use Getopt::Long;
-use FindBin qw($Bin);
-use lib "$Bin/../lib";
-
-## This program is Copyright (C) 2010-16, Felix Krueger (felix.krueger@babraham.ac.uk)
-
-## This program is free software: you can redistribute it and/or modify
-## it under the terms of the GNU General Public License as published by
-## the Free Software Foundation, either version 3 of the License, or
-## (at your option) any later version.
-
-## This program is distributed in the hope that it will be useful,
-## but WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-## GNU General Public License for more details.
-
-## You should have received a copy of the GNU General Public License
-## along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-
-my $parent_dir = getcwd;
-my $bismark_version = 'v0.16.3';
-my $command_line = join (" ",@ARGV);
-
-
-### before processing the command line we will replace --solexa1.3-quals with --phred64-quals as the '.' in the option name will cause Getopt::Long to fail
-foreach my $arg (@ARGV){
-  if ($arg eq '--solexa1.3-quals'){
-    $arg = '--phred64-quals';
-  }
-}
-my @filenames;   # will be populated by processing the command line
-
-my ($genome_folder,$CT_index_basename,$GA_index_basename,$path_to_bowtie,$sequence_file_format,$bowtie_options,$directional,$unmapped,$ambiguous,$phred64,$solexa,$output_dir,$bowtie2,$vanilla,$sam_no_hd,$skip,$upto,$temp_dir,$non_bs_mm,$insertion_open,$insertion_extend,$deletion_open,$deletion_extend,$gzip,$bam,$samtools_path,$pbat,$prefix,$old_flag,$basename,$score_min_intercept,$score_min_slope,$bt2_large_index,$multicore,$rg_tag,$rg_id,$rg_sample,$ambig_bam,$cram,$cram_ref,$nucleotide_coverage,$dovetail) = process_command_line();
-
-my @fhs;         # stores alignment process names, bisulfite index location, bowtie filehandles and the number of times sequences produced an alignment
-my %chromosomes; # stores the chromosome sequences of the mouse genome
-my %SQ_order;    # stores the order of sequences in the reference. This is to produce SAM/BAM files with a known order of chromosomes
-my %counting;    # counting various events
-my $final_output_filename; # required for the nucleotide coverage report 
-my @pids; # storing the process IDs of child processes in parallel mode
-
-
-my $seqID_contains_tabs;
-my $verbose = 0;
-
-if ($multicore > 1){
-  warn "Running Bismark Parallel version. Number of parallel instances to be spawned: $multicore\n\n";
-}
-
-
-sub multi_process_handling{
-
-  my $offset = 1;
-  my $process_id;
-  if ($multicore > 1){
-
-    until ($offset == $multicore){
-      # warn "multicore: $multicore\noffset: $offset\n";
-      my $fork = fork;
-
-      if (defined $fork){
-	if ($fork != 0){
-	  $process_id = $fork;
-	  push @pids, $process_id;
-	  if ($offset < $multicore){
-	    ++$offset;
-	    # warn "I am the parent process, child pid: $fork\nIncrementing offset counter to: $offset\n\n";
-	  }
-	  else{
-	    # warn "Reached the number of maximum multicores. Proceeeding to processing...\n";
-	  }
-	}
-	elsif ($fork == 0){
-	  # warn "I am a child process, pid: $fork\nOffset counter is: $offset\nProceeding to processing...\n";
-	  $process_id = $fork;
-	  last;
-	}
-      }
-      else{
-	die "Forking unsuccessful. Proceeding using a single thread only\n";
-      }
-    }
-
-    # warn "\nThe Thread Identity\n===================\n";
-    if ($process_id){
-      # print "I am the parent process. My children are called:\n";
-      # print join ("\t",@pids),"\n";
-      # print "I am going to process the following line count: $offset\n\n";
-    }
-    elsif($process_id == 0){
-      # warn "I am a child process: Process ID: $process_id\n";
-      # warn "I am going to process the following line count: $offset\n\n";
-    }
-    else{
-      die "Process ID was: '$process_id'\n";
-    }
-  }
-  else{
-    warn "Single-core mode: setting pid to 1\n";
-    $process_id = 1;
-  }
-
-  return ($process_id,$offset);
-}
-
-
-sub subset_input_file_FastQ{
-
-  my ($filename,$process_id,$offset) = @_;
-
-  if ($filename =~ /gz$/){
-    open (OFFSET,"gunzip -c $filename |") or die "Couldn't read from file '$filename': $!\n";
-  }
-  else{
-    open (OFFSET,$filename) or die "Couldn't read from file '$filename': $!\n";
-  }
-
-  # warn "offset is $offset\n";
-  my $temp = $filename;
-  $temp .= ".temp.$offset";
-  $temp =~ s/^.*\///; # replacing everything upto and including the last /, i.e. removing file path information
-
-  if ($gzip){
-    $temp .= '.gz';
-    open (TEMPFQ,"| gzip -c - > ${temp_dir}${temp}") or die "Can't write to file ${temp_dir}${temp}: $!\n";
-  }
-  else{
-    open (TEMPFQ,'>',"${temp_dir}${temp}") or die "Failed to write output ${temp_dir}${temp}: $!\n";
-  }
-
-  my $line_count = 0;
-
-  while (1){
-    my $l1 = <OFFSET>;
-    my $l2 = <OFFSET>;
-    my $l3 = <OFFSET>;
-    my $l4 = <OFFSET>;
-
-    last unless ($l4);
-    ++$line_count;
-
-    if ( ($line_count - $offset)%$multicore == 0){
-      # warn "line count: $line_count\noffset: $offset\n";
-      # warn "Modulus: ",($line_count - $offset)%$multicore,"\n";
-      # warn "processing this line $line_count (processID: $process_id with \$offset $offset)\n";
-      print TEMPFQ "$l1$l2$l3$l4";
-    }
-    else{
-      # warn "skipping line $line_count for processID: $process_id with \$offset $offset)\n";
-      next;
-    }
-  }
-
-  close OFFSET or warn $!;
-  close TEMPFQ or warn "Failed to close file handle TEMPFQ: $!\n";
-
-  warn "Finished subdividing $filename for PID: $process_id and offset $offset\n\n";
-
-  return ($temp); # returning the subset filename
-
-}
-
-sub subset_input_file_FastA{
-
-  my ($filename,$process_id,$offset) = @_;
-
-  if ($filename =~ /gz$/){
-    open (OFFSET,"gunzip -c $filename |") or die "Couldn't read from file '$filename': $!\n";
-  }
-  else{
-    open (OFFSET,$filename) or die "Couldn't read from file '$filename': $!\n";
-  }
-
-  # warn "offset is $offset\n";
-  my $temp = $filename;
-  $temp .= ".temp.$offset";
-  $temp =~ s/^.*\///; # replacing everything upto and including the last /, i.e. removing file path information
-
-  if ($gzip){
-    $temp .= '.gz';
-    open (TEMPFA,"| gzip -c - > ${temp_dir}${temp}") or die "Can't write to file ${temp_dir}${temp}: $!\n";
-  }
-  else{
-    open (TEMPFA,'>',"${temp_dir}${temp}") or die "Failed to write output ${temp_dir}${temp}: $!\n";
-  }
-
-  warn "Writing temporary infile to $temp\n";
-
-  my $line_count = 0;
-
-  while (1){
-    my $l1 = <OFFSET>;
-    my $l2 = <OFFSET>;
-
-    last unless ($l2);
-    ++$line_count;
-
-    if ( ($line_count - $offset)%$multicore == 0){
-      # warn "line count: $line_count\noffset: $offset\n";
-      # warn "Modulus: ",($line_count - $offset)%$multicore,"\n";
-      # warn "processing this line $line_count (processID: $process_id with \$offset $offset)\n";
-      print TEMPFA "$l1$l2";
-    }
-    else{
-      # warn "skipping line $line_count for processID: $process_id with \$offset $offset)\n";
-      next;
-    }
-  }
-
-  close OFFSET or warn $!;
-  close TEMPFA or warn "Failed to close file handle TEMPFQ: $!\n";
-
-  warn "Finished subdividing $filename for PID: $process_id and offset $offset\n\n";
-
-  return ($temp); # returning the subset filename
-
-}
-
-#####
-#####
-
-foreach my $filename (@filenames){
-
-  my $original_filename = $filename;
-  my $original_filename_1;
-  my $original_filename_2;
-
-  chdir $parent_dir or die "Unable to move to initial working directory'$parent_dir' $!\n";
-  ### resetting the counting hash and fhs
-  reset_counters_and_fhs($filename);
-  @pids = ();
-  $seqID_contains_tabs = 0;
-
-  ### if 2 or more files are provided we can hold the genome in memory and don't need to read it in a second time
-  unless (%chromosomes){
-      my $cwd = getcwd; # storing the path of the current working directory
-      warn "Current working directory is: $cwd\n\n";
-      read_genome_into_memory($cwd);
-  }
-
-  ### As of version 0.14.0 we support multi-threading. In a first instance we accomplish this by
-  ### splitting the input file(s) into several smaller subfiles and merging the results back at
-  ### the end.
-
-  # get general settings (also for single-threaded use)
-  my ($pid,$offset) = multi_process_handling ();
-
-  my ($single_end,$paired_end);
-  ### PAIRED-END ALIGNMENTS
-  if ($filename =~ ','){
-      
-    $single_end = 0;
-    $paired_end = 1;
-
-    my ($C_to_T_infile_1,$G_to_A_infile_1); # to be made from mate1 file
-
-    $fhs[0]->{name} = 'CTread1GAread2CTgenome';
-    $fhs[1]->{name} = 'GAread1CTread2GAgenome';
-    $fhs[2]->{name} = 'GAread1CTread2CTgenome';
-    $fhs[3]->{name} = 'CTread1GAread2GAgenome';
-    warn "\nPaired-end alignments will be performed\n",'='x39,"\n\n";
-
-    my ($filename_1,$filename_2) = (split (/,/,$filename));
-    $original_filename_1 = $filename_1;
-    $original_filename_2 = $filename_2;
-
-    warn "The provided filenames for paired-end alignments are $filename_1 and $filename_2\n";
-
-    ### subsetting the input file(s)
-    unless ($multicore == 1){ # not needed in single-core mode
-      # warn "My PID: $pid\nMy offset: $offset\n";
-      if ($sequence_file_format eq 'FASTA'){
-	my $temp_filename_1 = subset_input_file_FastA($filename_1,$pid,$offset);
-	warn "Using the subset file >${temp_dir}$temp_filename_1< as new in-file 1 (instead of >$filename_1<)\n";
-	$filename_1 = "${temp_dir}$temp_filename_1";
-	
-	my $temp_filename_2 = subset_input_file_FastA($filename_2,$pid,$offset);
-	warn "Using the subset file >${temp_dir}$temp_filename_2< as new in-file 2 (instead of >$filename_2<)\n";
-	$filename_2 = "${temp_dir}$temp_filename_2";
-      }
-      else{ # FastQ format, default
-	my $temp_filename_1 = subset_input_file_FastQ($filename_1,$pid,$offset);
-	warn "Using the subset file >${temp_dir}$temp_filename_1< as new in-file 1 (instead of >$filename_1<)\n";
-	$filename_1 = "${temp_dir}$temp_filename_1";
-
-	my $temp_filename_2 = subset_input_file_FastQ($filename_2,$pid,$offset);
-	warn "Using the subset file >${temp_dir}$temp_filename_2< as new in-file 2 (instead of >$filename_2<)\n";
-	$filename_2 = "${temp_dir}$temp_filename_2";
-      }
-    }
-
-    ### additional variables only for paired-end alignments
-    my ($C_to_T_infile_2,$G_to_A_infile_2); # to be made from mate2 file
-
-    ### FastA format
-    if ($sequence_file_format eq 'FASTA'){
-      warn "Input files are in FastA format\n";
-
-      if ($directional){
-	($C_to_T_infile_1) = biTransformFastAFiles_paired_end ($filename_1,1); # also passing the read number
-	($G_to_A_infile_2) = biTransformFastAFiles_paired_end ($filename_2,2);
-
-	$fhs[0]->{inputfile_1} = $C_to_T_infile_1;
-	$fhs[0]->{inputfile_2} = $G_to_A_infile_2;
-	$fhs[1]->{inputfile_1} = undef;
-	$fhs[1]->{inputfile_2} = undef;
-	$fhs[2]->{inputfile_1} = undef;
-	$fhs[2]->{inputfile_2} = undef;
-	$fhs[3]->{inputfile_1} = $C_to_T_infile_1;
-	$fhs[3]->{inputfile_2} = $G_to_A_infile_2;
-      }
-      else{
-	($C_to_T_infile_1,$G_to_A_infile_1) = biTransformFastAFiles_paired_end ($filename_1,1); # also passing the read number
-	($C_to_T_infile_2,$G_to_A_infile_2) = biTransformFastAFiles_paired_end ($filename_2,2);
-
-	$fhs[0]->{inputfile_1} = $C_to_T_infile_1;
-	$fhs[0]->{inputfile_2} = $G_to_A_infile_2;
-	$fhs[1]->{inputfile_1} = $G_to_A_infile_1;
-	$fhs[1]->{inputfile_2} = $C_to_T_infile_2;
-	$fhs[2]->{inputfile_1} = $G_to_A_infile_1;
-	$fhs[2]->{inputfile_2} = $C_to_T_infile_2;
-	$fhs[3]->{inputfile_1} = $C_to_T_infile_1;
-	$fhs[3]->{inputfile_2} = $G_to_A_infile_2;
-      }
-
-      if ($bowtie2){
-	paired_end_align_fragments_to_bisulfite_genome_fastA_bowtie2 ($C_to_T_infile_1,$G_to_A_infile_1,$C_to_T_infile_2,$G_to_A_infile_2);
-      }
-      else{
-	paired_end_align_fragments_to_bisulfite_genome_fastA ($C_to_T_infile_1,$G_to_A_infile_1,$C_to_T_infile_2,$G_to_A_infile_2);
-      }
-    }
-
-    ### FastQ format
-    else{
-      warn "Input files are in FastQ format\n";
-      if ($directional){
-	if ($bowtie2){
-	  ($C_to_T_infile_1) = biTransformFastQFiles_paired_end ($filename_1,1); # also passing the read number
-	  ($G_to_A_infile_2) = biTransformFastQFiles_paired_end ($filename_2,2);
-	
-	  $fhs[0]->{inputfile_1} = $C_to_T_infile_1;
-	  $fhs[0]->{inputfile_2} = $G_to_A_infile_2;
-	  $fhs[1]->{inputfile_1} = undef;
-	  $fhs[1]->{inputfile_2} = undef;
-	  $fhs[2]->{inputfile_1} = undef;
-	  $fhs[2]->{inputfile_2} = undef;
-	  $fhs[3]->{inputfile_1} = $C_to_T_infile_1;
-	  $fhs[3]->{inputfile_2} = $G_to_A_infile_2;
-	}
-	else{ # Bowtie 1 alignments
-	  if ($gzip){
-	    ($C_to_T_infile_1) = biTransformFastQFiles_paired_end_bowtie1_gzip ($filename_1,$filename_2); # passing both reads at the same time
-	
-	    $fhs[0]->{inputfile_1} = $C_to_T_infile_1; # this file contains both read 1 and read 2 in tab delimited format
-	    $fhs[0]->{inputfile_2} = undef; # no longer needed
-	    $fhs[1]->{inputfile_1} = undef;
-	    $fhs[1]->{inputfile_2} = undef;
-	    $fhs[2]->{inputfile_1} = undef;
-	    $fhs[2]->{inputfile_2} = undef;
-	    $fhs[3]->{inputfile_1} = $C_to_T_infile_1; # this file contains both read 1 and read 2 in tab delimited format
-	    $fhs[3]->{inputfile_2} = undef; # no longer needed
-	  }
-	  else{
-	    ($C_to_T_infile_1) = biTransformFastQFiles_paired_end ($filename_1,1); # also passing the read number
-	    ($G_to_A_infile_2) = biTransformFastQFiles_paired_end ($filename_2,2);
-	
-	    $fhs[0]->{inputfile_1} = $C_to_T_infile_1;
-	    $fhs[0]->{inputfile_2} = $G_to_A_infile_2;
-	    $fhs[1]->{inputfile_1} = undef;
-	    $fhs[1]->{inputfile_2} = undef;
-	    $fhs[2]->{inputfile_1} = undef;
-	    $fhs[2]->{inputfile_2} = undef;
-	    $fhs[3]->{inputfile_1} = $C_to_T_infile_1;
-	    $fhs[3]->{inputfile_2} = $G_to_A_infile_2;
-	  }
-	}
-      }
-      elsif($pbat){ # PBAT-Seq. This works for both Bowtie and Bowtie 2
-	### At the moment we are only performing alignments only with uncompressed FastQ files
-	($C_to_T_infile_1,$G_to_A_infile_1) = biTransformFastQFiles_paired_end ($filename_1,1); # also passing the read number
-	($C_to_T_infile_2,$G_to_A_infile_2) = biTransformFastQFiles_paired_end ($filename_2,2);
-	
-	$fhs[0]->{inputfile_1} = undef;
-	$fhs[0]->{inputfile_2} = undef;
-	$fhs[1]->{inputfile_1} = $G_to_A_infile_1;
-	$fhs[1]->{inputfile_2} = $C_to_T_infile_2;
-	$fhs[2]->{inputfile_1} = $G_to_A_infile_1;
-	$fhs[2]->{inputfile_2} = $C_to_T_infile_2;
-	$fhs[3]->{inputfile_1} = undef;
-	$fhs[3]->{inputfile_2} = undef;
-      }
-      else{
-	if ($bowtie2){
-	  ($C_to_T_infile_1,$G_to_A_infile_1) = biTransformFastQFiles_paired_end ($filename_1,1); # also passing the read number
-	  ($C_to_T_infile_2,$G_to_A_infile_2) = biTransformFastQFiles_paired_end ($filename_2,2);
-	
-	  $fhs[0]->{inputfile_1} = $C_to_T_infile_1;
-	  $fhs[0]->{inputfile_2} = $G_to_A_infile_2;
-	  $fhs[1]->{inputfile_1} = $G_to_A_infile_1;
-	  $fhs[1]->{inputfile_2} = $C_to_T_infile_2;
-	  $fhs[2]->{inputfile_1} = $G_to_A_infile_1;
-	  $fhs[2]->{inputfile_2} = $C_to_T_infile_2;
-	  $fhs[3]->{inputfile_1} = $C_to_T_infile_1;
-	  $fhs[3]->{inputfile_2} = $G_to_A_infile_2;
-	}
-	else{ # Bowtie 1 alignments
-	  if ($gzip){
-	    ($C_to_T_infile_1,$G_to_A_infile_1) = biTransformFastQFiles_paired_end_bowtie1_gzip ($filename_1,$filename_2); # passing both reads at the same time
-	
-	    $fhs[0]->{inputfile_1} = $C_to_T_infile_1;
-	    $fhs[0]->{inputfile_2} = undef; # not needed for compressed temp files
-	    $fhs[1]->{inputfile_1} = $G_to_A_infile_1;
-	    $fhs[1]->{inputfile_2} = undef;
-	    $fhs[2]->{inputfile_1} = $G_to_A_infile_1;
-	    $fhs[2]->{inputfile_2} = undef;
-	    $fhs[3]->{inputfile_1} = $C_to_T_infile_1;
-	    $fhs[3]->{inputfile_2} = undef; # not needed for compressed temp files
-	  }
-	  else{ # uncompressed temp files
-	    ($C_to_T_infile_1,$G_to_A_infile_1) = biTransformFastQFiles_paired_end ($filename_1,1); # also passing the read number
-	    ($C_to_T_infile_2,$G_to_A_infile_2) = biTransformFastQFiles_paired_end ($filename_2,2);
-	
-	    $fhs[0]->{inputfile_1} = $C_to_T_infile_1;
-	    $fhs[0]->{inputfile_2} = $G_to_A_infile_2;
-	    $fhs[1]->{inputfile_1} = $G_to_A_infile_1;
-	    $fhs[1]->{inputfile_2} = $C_to_T_infile_2;
-	    $fhs[2]->{inputfile_1} = $G_to_A_infile_1;
-	    $fhs[2]->{inputfile_2} = $C_to_T_infile_2;
-	    $fhs[3]->{inputfile_1} = $C_to_T_infile_1;
-	    $fhs[3]->{inputfile_2} = $G_to_A_infile_2;
-	  }
-	}
-      }
-      if ($bowtie2){
-	paired_end_align_fragments_to_bisulfite_genome_fastQ_bowtie2 ($C_to_T_infile_1,$G_to_A_infile_1,$C_to_T_infile_2,$G_to_A_infile_2);
-      }
-      else{
-       	paired_end_align_fragments_to_bisulfite_genome_fastQ ($C_to_T_infile_1,$G_to_A_infile_1,$C_to_T_infile_2,$G_to_A_infile_2);	
-      }
-    }
-    start_methylation_call_procedure_paired_ends($filename_1,$filename_2,$C_to_T_infile_1,$G_to_A_infile_1,$C_to_T_infile_2,$G_to_A_infile_2,$pid);
-  }
-
-  ### Else we are performing SINGLE-END ALIGNMENTS
-  else{
-    warn "\nSingle-end alignments will be performed\n",'='x39,"\n\n";
-
-    $single_end = 1;
-    $paired_end = 0;
-
-    ### subsetting the input file(s)
-    unless ($multicore == 1){ # not needed in single-core mode
-      # warn "My PID: $pid\nMy offset: $offset\n";
-      if ($sequence_file_format eq 'FASTA'){
-	my $temp_filename = subset_input_file_FastA($filename,$pid,$offset);
-	warn "Using the subset file >${temp_dir}$temp_filename< as new in-file (instead of >$filename<)\n";
-	$filename = "${temp_dir}$temp_filename";
-      }
-      else{ # FastQ format, default
-	my $temp_filename = subset_input_file_FastQ($filename,$pid,$offset);
-	warn "Using the subset file >${temp_dir}$temp_filename< as new in-file (instead of >$filename<)\n";
-	$filename = "${temp_dir}$temp_filename";
-      }
-    }
-
-    ### Initialising bisulfite conversion filenames
-    my ($C_to_T_infile,$G_to_A_infile);
-
-    ### FastA format
-    if ($sequence_file_format eq 'FASTA'){
-      warn "Input file is in FastA format\n";
-      if ($directional){
-	($C_to_T_infile) = biTransformFastAFiles ($filename);
-	$fhs[0]->{inputfile} = $fhs[1]->{inputfile} = $C_to_T_infile;
-      }
-      else{
-	($C_to_T_infile,$G_to_A_infile) = biTransformFastAFiles ($filename);
-	$fhs[0]->{inputfile} = $fhs[1]->{inputfile} = $C_to_T_infile;
-	$fhs[2]->{inputfile} = $fhs[3]->{inputfile} = $G_to_A_infile;
-      }
-
-      ### Creating 4 different bowtie filehandles and storing the first entry
-      if ($bowtie2){
-	single_end_align_fragments_to_bisulfite_genome_fastA_bowtie2 ($C_to_T_infile,$G_to_A_infile);
-      }
-      else{
-	single_end_align_fragments_to_bisulfite_genome_fastA ($C_to_T_infile,$G_to_A_infile);
-      }
-    }
-
-    ## FastQ format
-    else{
-      warn "Input file is in FastQ format\n";
-      if ($directional){
-	($C_to_T_infile) = biTransformFastQFiles ($filename);
-	$fhs[0]->{inputfile} = $fhs[1]->{inputfile} = $C_to_T_infile;
-      }
-      elsif($pbat){
-	($G_to_A_infile) = biTransformFastQFiles ($filename);
-	$fhs[0]->{inputfile} = $fhs[1]->{inputfile} = $G_to_A_infile; # PBAT-Seq only uses the G to A converted files
-      }
-      else{
-	($C_to_T_infile,$G_to_A_infile) = biTransformFastQFiles ($filename);
-	$fhs[0]->{inputfile} = $fhs[1]->{inputfile} = $C_to_T_infile;
-	$fhs[2]->{inputfile} = $fhs[3]->{inputfile} = $G_to_A_infile;
-      }
-
-      ### Creating up to 4 different bowtie filehandles and storing the first entry
-      if ($pbat){
-	if ($bowtie2){ # as of version 0.10.2 we also support PBAT alignments for Bowtie 2
-	  single_end_align_fragments_to_bisulfite_genome_fastQ_bowtie2 (undef,$G_to_A_infile);
-	}
-	else{
-	  single_end_align_fragments_to_bisulfite_genome_fastQ (undef,$G_to_A_infile);
-	}
-      }
-      elsif ($bowtie2){
-	single_end_align_fragments_to_bisulfite_genome_fastQ_bowtie2 ($C_to_T_infile,$G_to_A_infile);
-      }
-      else{
-	single_end_align_fragments_to_bisulfite_genome_fastQ ($C_to_T_infile,$G_to_A_infile);
-      }
-    }
-
-    start_methylation_call_procedure_single_ends($filename,$C_to_T_infile,$G_to_A_infile,$pid);
-
-  }
-
-  ### MERGING AND DELETING TEMP FILES // TIDYING UP AFTER A MULTICORE PROCESS
-
-  if ($pid){ # only performing this for the parent process
-
-    if ($multicore > 1){
-
-      warn "Now waiting for all child processes to complete\n";
-
-      ### we need to ensure that we wait for all child processes to be finished before continuing
-      # warn "here are the child IDs: @pids\n";
-      # warn "Looping through the child process IDs:\n";
-
-      foreach my $id (@pids){
-	# print "$id\t";
-	my $kid = waitpid ($id,0);
-	# print "Returned: $kid\nExit status: $?\n";
-	unless ($? == 0){
-	  warn "\nChild process terminated with exit signal: '$?'\n\n";
-	}
-      }
-
-      # regenerating names for temporary files
-      my @temp_input;
-      my @temp_output;
-      my @temp_reports;
-      my @temp_unmapped_1;  # will store single end reads or R1 of paired-end
-      my @temp_unmapped_2;
-      my @temp_ambiguous_1; # will store single end reads or R1 of paired-end
-      my @temp_ambiguous_2;
-      my @temp_ambig_bam; 
-
-      for (1..$offset){
-
-	# Temp Input Files
-	if ($single_end){
-	  if ($gzip){
-	    push @temp_input, "${original_filename}.temp.${_}.gz";
-	  }
-	  else{
-	    push @temp_input, "${original_filename}.temp.${_}";
-	  }
-
-	}
-	elsif($paired_end){
-	  if ($gzip){
-	    push @temp_input, "${original_filename_1}.temp.${_}.gz";
-	    push @temp_input, "${original_filename_2}.temp.${_}.gz";
-	  }
-	  else{
-	    push @temp_input, "${original_filename_1}.temp.${_}";
-	    push @temp_input, "${original_filename_2}.temp.${_}";
-	  }
-	}
-
-	# if files had a prefix we need to specify it
-	my $add_prefix;
-	if (defined $prefix){
-	  $add_prefix = "${prefix}.";
-	}
-	else{
-	  $add_prefix = '';
-	}
-
-	# Temp Output Files
-	if ($single_end){
-	
-	  if ($bowtie2){
-	    if ($gzip){
-		push @temp_output,     "${output_dir}${add_prefix}${original_filename}.temp.${_}.gz_bismark_bt2.bam";
-		push @temp_reports,    "${output_dir}${add_prefix}${original_filename}.temp.${_}.gz_bismark_bt2_SE_report.txt";
-		push @temp_ambig_bam,  "${output_dir}${add_prefix}${original_filename}.temp.${_}.gz_bismark_bt2.ambig.bam";   # only for Bowtie 2 
-	    }
-	    else{
-		push @temp_output,     "${output_dir}${add_prefix}${original_filename}.temp.${_}_bismark_bt2.bam";
-		push @temp_reports,    "${output_dir}${add_prefix}${original_filename}.temp.${_}_bismark_bt2_SE_report.txt";
-		push @temp_ambig_bam,  "${output_dir}${add_prefix}${original_filename}.temp.${_}_bismark_bt2.ambig.bam";      # only for Bowtie 2 
-	    }
-	  }
-	  else{
-	    if ($gzip){
-	      push @temp_output,     "${output_dir}${add_prefix}${original_filename}.temp.${_}.gz_bismark.bam";
-	      push @temp_reports,    "${output_dir}${add_prefix}${original_filename}.temp.${_}.gz_bismark_SE_report.txt";
-	    }
-	    else{
-	      push @temp_output,     "${output_dir}${add_prefix}${original_filename}.temp.${_}_bismark.bam";
-	      push @temp_reports,    "${output_dir}${add_prefix}${original_filename}.temp.${_}_bismark_SE_report.txt";
-	    }
-	  }
-	
-	  if ($unmapped){
-	    if ($gzip){
-	      push @temp_unmapped_1,   "${output_dir}${add_prefix}${original_filename}.temp.${_}.gz_unmapped_reads.fq";
-	    }
-	    else{
-	      push @temp_unmapped_1,   "${output_dir}${add_prefix}${original_filename}.temp.${_}_unmapped_reads.fq";
-  	    }
-	  }
-
-	  if ($ambiguous){
-	    if ($gzip){
-	      push @temp_ambiguous_1,  "${output_dir}${add_prefix}${original_filename}.temp.${_}.gz_ambiguous_reads.fq";
-	    }
-	    else{
-	      push @temp_ambiguous_1,  "${output_dir}${add_prefix}${original_filename}.temp.${_}_ambiguous_reads.fq";
-	    }
-	  }
-	
-	}
-	elsif($paired_end){
-	  if ($bowtie2){
-	    if ($gzip){
-	      push @temp_output,     "${output_dir}${add_prefix}${original_filename_1}.temp.${_}.gz_bismark_bt2_pe.bam";
-	      push @temp_reports,    "${output_dir}${add_prefix}${original_filename_1}.temp.${_}.gz_bismark_bt2_PE_report.txt";
-	      push @temp_ambig_bam,  "${output_dir}${add_prefix}${original_filename_1}.temp.${_}.gz_bismark_bt2_pe.ambig.bam";      # only for Bowtie 2 
-	    }
-	    else{
-	      push @temp_output,     "${output_dir}${add_prefix}${original_filename_1}.temp.${_}_bismark_bt2_pe.bam";
-	      push @temp_reports,    "${output_dir}${add_prefix}${original_filename_1}.temp.${_}_bismark_bt2_PE_report.txt";
-	      push @temp_ambig_bam,  "${output_dir}${add_prefix}${original_filename_1}.temp.${_}_bismark_bt2_pe.ambig.bam";         # only for Bowtie 2 
-	    }
-	  }
-	  else{
-	    if ($gzip){
-	      push @temp_output,     "${output_dir}${add_prefix}${original_filename_1}.temp.${_}.gz_bismark_pe.bam";
-	      push @temp_reports,    "${output_dir}${add_prefix}${original_filename_1}.temp.${_}.gz_bismark_PE_report.txt";
-	    }
-	    else{
-	      push @temp_output,     "${output_dir}${add_prefix}${original_filename_1}.temp.${_}_bismark_pe.bam";
-	      push @temp_reports,    "${output_dir}${add_prefix}${original_filename_1}.temp.${_}_bismark_PE_report.txt";
-	    }
-	  }
-
-	  if ($unmapped){
-	    if ($gzip){
-	      push @temp_unmapped_1,   "${output_dir}${add_prefix}${original_filename_1}.temp.${_}.gz_unmapped_reads_1.fq";
-	      push @temp_unmapped_2,   "${output_dir}${add_prefix}${original_filename_2}.temp.${_}.gz_unmapped_reads_2.fq";
-	    }
-	    else{
-	      push @temp_unmapped_1,   "${output_dir}${add_prefix}${original_filename_1}.temp.${_}_unmapped_reads_1.fq";
-	      push @temp_unmapped_2,   "${output_dir}${add_prefix}${original_filename_2}.temp.${_}_unmapped_reads_2.fq";
-	    }
-	  }
-
-	  if ($ambiguous){
-	    if ($gzip){
-	      push @temp_ambiguous_1,   "${output_dir}${add_prefix}${original_filename_1}.temp.${_}.gz_ambiguous_reads_1.fq";
-	      push @temp_ambiguous_2,   "${output_dir}${add_prefix}${original_filename_2}.temp.${_}.gz_ambiguous_reads_2.fq";
-	    }
-	    else{
-	      push @temp_ambiguous_1,   "${output_dir}${add_prefix}${original_filename_1}.temp.${_}_ambiguous_reads_1.fq";
-	      push @temp_ambiguous_2,   "${output_dir}${add_prefix}${original_filename_2}.temp.${_}_ambiguous_reads_2.fq";
-	    }
-	  }
-	
-	}
-      }
-
-      warn "\n\nRight, cleaning up now...\n\n";
-
-      # deleting temp files;
-      warn "Deleting temporary sequence files...\n";
-      foreach my $temp (@temp_input){
-	#print "$temp\t";
-	$temp =~ s/.*\///; # deleting path information
-	print "${temp_dir}${temp}\t";
-	unlink "${temp_dir}${temp}" or warn "Failed to delete temporary FastQ file ${temp_dir}$temp: $!\n";
-      }
-      print "\n\n";
-
-      # merging temp BAM files
-      if ($single_end){
-	merge_individual_BAM_files(\@temp_output,$original_filename,$single_end);
-      }
-      else{
-	merge_individual_BAM_files(\@temp_output,$original_filename_1,$single_end);
-      }
-      
-      # deleting temp BAM files
-      warn "Deleting temporary BAM files...\n";
-      foreach my $temp (@temp_output){
-	  # print "$temp\t";
-	  $temp =~ s/.*\///; # deleting path information
-	  print "${output_dir}${temp}\t";
-	  unlink "${output_dir}${temp}" or warn "Failed to delete temporary BAM file ${output_dir}${temp}: $!\n";
-      }
-      print "\n\n";
-      
-      ### AMBIGUOUS BAM files
-      if ($ambig_bam){
-
-	  # merging temp AMBIG BAM files
-	  if ($single_end){
-	      merge_individual_ambig_BAM_files(\@temp_ambig_bam,$original_filename,$single_end);
-	  }
-	  else{
-	      merge_individual_ambig_BAM_files(\@temp_ambig_bam,$original_filename_1,$single_end);
-	  }
-	  
-	  # deleting temp BAM files
-	  warn "Deleting temporary ambiguous BAM files...\n";
-	  foreach my $temp (@temp_ambig_bam){
-	      # print "$temp\t";
-	      $temp =~ s/.*\///; # deleting path information
-	      print "${output_dir}${temp}\t";
-	      unlink "${output_dir}${temp}" or warn "Failed to delete temporary ambiguous BAM file ${output_dir}${temp}: $!\n";
-	  }
-	  print "\n\n";
-      }
-
-      if ($unmapped){
-	if ($single_end){
-	  merge_individual_unmapped_files(\@temp_unmapped_1,$original_filename,$single_end);
-	}
-	else{
-	  merge_individual_unmapped_files(\@temp_unmapped_1,$original_filename_1,$single_end,'_1');
-	  merge_individual_unmapped_files(\@temp_unmapped_2,$original_filename_2,$single_end,'_2');
-	}
-
-	# deleting temp unmapped files
-	warn "Deleting temporary unmapped files...\n";
-	foreach my $temp (@temp_unmapped_1){
-	  print "$temp\t";
-	  unlink "${output_dir}${temp}" or warn "Failed to delete temporary unmapped FastQ file ${output_dir}$temp: $!\n";
-	}
-	if ($paired_end){
-	  foreach my $temp (@temp_unmapped_2){
-	    print "$temp\t";
-	    unlink "${output_dir}${temp}" or warn "Failed to delete temporary unmapped FastQ file ${output_dir}$temp: $!\n";
-	  }
-	}
-	print "\n\n";
-
-      }
-
-      if ($ambiguous){
-	if ($single_end){
-	  merge_individual_ambiguous_files(\@temp_ambiguous_1,$original_filename,$single_end);
-	}
-	else{
-	  merge_individual_ambiguous_files(\@temp_ambiguous_1,$original_filename_1,$single_end,'_1');
-	  merge_individual_ambiguous_files(\@temp_ambiguous_2,$original_filename_2,$single_end,'_2');
-	}
-
-	# deleting temp ambiguous files
-	warn "Deleting temporary ambiguous files...\n";
-	foreach my $temp (@temp_ambiguous_1){
-	  print "$temp\t";
-	  unlink "${output_dir}${temp}" or warn "Failed to delete temporary ambiguous FastQ file ${output_dir}$temp: $!\n";
-	}
-
-	if ($paired_end){
-	  foreach my $temp (@temp_ambiguous_2){
-	    print "$temp\t";
-	    unlink "${output_dir}${temp}" or warn "Failed to delete temporary ambiguous FastQ file ${output_dir}$temp: $!\n";
-	  }
-	}
-	print "\n\n";
-      }
-
-      # resetting the counters once more so we can add all data from all temporary reports
-      reset_counters_and_fhs($original_filename);
-
-      ### Merging the Bismark mapping report files
-      if ($single_end){
-	merge_individual_mapping_reports(\@temp_reports,$original_filename,$single_end);
-	print_final_analysis_report_single_end('mock_file1','mock_file_2','mock_pid','mergeThis');
-      }
-      else{
-	merge_individual_mapping_reports(\@temp_reports,$original_filename_1,$single_end,$original_filename_2);
-	print_final_analysis_report_paired_ends('mock_file1','mock_file_2','mock_file3','mock_file_4','mock_pid','mergeThis');
-      }
-
-      # deleting temp report files
-      warn "Deleting temporary report files...\n";
-      foreach my $temp (@temp_reports){
-	print "$temp\t";
-	unlink "${output_dir}${temp}" or warn "Failed to delete temporary report file $output_dir$temp: $!\n";
-      }
-      print "\n\n";
-
-    }
-
-  }
-
-  if ($pid){ # only for the Parent
-    warn "\n====================\nBismark run complete\n====================\n\n";
-
-    if ($nucleotide_coverage){
-	warn "Now calculating observed and expected nucleotide coverage statistics... \n\n";
-	if ($final_output_filename =~ /(bam|cram)|/){
-	    my @args;
-	    push @args, "--genome $genome_folder";
-	    push @args, "--dir '$output_dir'";
-	    push @args, "--samtools_path $samtools_path";
-	    push @args, $final_output_filename;
-	    print "@args","\n"; sleep(3);
-	    
-	    system ("$Bin/bam2nuc @args");
-	    warn "Finished bam2nuc calculation ...\n\n";
-	   
-	}
-	else{
-	    warn "Nucleotide coverage statistics are currently only available for BAM or CRAM files\n\n";
-	}
-    }
-    
-  }
-
-}
-
-sub merge_individual_mapping_reports{
-
-  my ($temp_reports,$original_filename_1,$single_end,$original_filename_2) = @_;
-  my $report_file = $original_filename_1;
-  $report_file =~ s/.*\///; # removing path information
-  $report_file =~ s/(\.fastq\.gz|\.fq\.gz|\.fastq|\.fq)$//; # attempting to remove fastq.gz etc to make filename a little shorter
- 
-  if ($prefix){
-    $report_file = "${prefix}.${report_file}";
-  }
-
-  if ($basename){ # Output file basename is set using the -B argument
-    $report_file = ${basename};
-  }
-
-  if ($single_end){
-    if ($bowtie2){
-      $report_file .= '_bismark_bt2_SE_report.txt';
-    }
-    else{
-      $report_file .= '_bismark_SE_report.txt';
-    }
-  }
-  else{
-    if ($bowtie2){
-      $report_file .= '_bismark_bt2_PE_report.txt';
-    }
-    else{
-      $report_file .= '_bismark_PE_report.txt';
-    }
-  }
-  warn "Writing report to ${output_dir}${report_file}\n";
-  open (REPORT,'>',"$output_dir$report_file") or die "Failed to write to ${output_dir}${report_file}: $!\n";
-
-  foreach my $temp(@$temp_reports){
-    $temp =~ s/.*\///; # removing path information
-  }
-
-  warn "Now merging temporary reports @$temp_reports into >>> ${output_dir}${report_file} <<<\n";
-
-  if ($single_end){
-    print REPORT "Bismark report for: $original_filename_1 (version: $bismark_version)\n";
-  }
-  else{ # paired-end
-    print REPORT "Bismark report for: $original_filename_1 and $original_filename_2 (version: $bismark_version)\n";
-  }
-
-
-  my $first = 0;
-
-  foreach my $temp(@$temp_reports){
-    # $temp =~ s/.*\///; # removing path information
-
-    warn "Merging from file >> $temp <<\n";
-    open (IN,"${output_dir}${temp}") or die "Failed to read from temporary mapping report '${output_dir}${temp}'\n";
-
-    ### this is printing the first couple of lines
-    while (<IN>){
-      chomp;
-      if ($_ =~ /^Bismark report/){
-	next;
-      }
-
-      unless ($first){ # only happens for the first run we are processing
-	if ($_ =~ /^Final Alignment/){
-	  ++$first;
-	  last;
-	}
-	else{
-	  print REPORT "$_\n";
-	}
-      }
-    }
-    close IN or warn "Failed to close filehandle\n";
-
-    ### Simon says: You are going to regret this in the future. Just for the record. He might be right...
-    read_alignment_report($temp,$single_end);
-
-  }
-  warn "\n";
-
-}
-
-sub read_alignment_report{
-  my ($report,$single_end) = @_;
-
-  my $unique;
-  my $no_aln;
-  my $multiple;
-  my $no_genomic;
-  my $total_seqs;
-  my $bismark_version;
-  my $input_filename;
-
-  my $unique_text;
-  my $no_aln_text;
-  my $multiple_text;
-  my $total_seq_text;
-
-  my $total_C_count;
-  my ($meth_CpG,$meth_CHG,$meth_CHH,$meth_unknown);
-  my ($unmeth_CpG,$unmeth_CHG,$unmeth_CHH,$unmeth_unknown);
-
-  my $number_OT;
-  my $number_CTOT;
-  my $number_CTOB;
-  my $number_OB;
-
-  open (ALN,"${output_dir}${report}") or die "Failed to read from temporary mapping report '$output_dir$report'\n";
-
-  while (<ALN>){
-    chomp;
-
-    ### General Alignment stats
-    if ($_ =~ /^Sequence pairs analysed in total:/ ){ ## Paired-end
-      (undef,$total_seqs) = split /\t/;
-      # warn "Total paired seqs: >> $total_seqs <<\n";
-    }
-    elsif ($_ =~ /^Sequences analysed in total:/ ){   ## Single-end
-      (undef,$total_seqs) = split /\t/;
-      # warn "total single-end seqs >> $total_seqs <<\n";
-    }
-
-    elsif($_ =~ /^Number of paired-end alignments with a unique best hit:/){ ## Paired-end
-      (undef,$unique) = split /\t/;
-      # warn "Unique PE>> $unique <<\n";
-    }
-    elsif($_ =~ /^Number of alignments with a unique best hit from/){        ## Single-end
-      (undef,$unique) = split /\t/;
-      # warn "Unique SE>> $unique <<\n";
-    }
-
-    elsif($_ =~ /^Sequence pairs with no alignments under any condition:/){  ## Paired-end
-      (undef,$no_aln) = split /\t/;
-      # warn "No alignment PE >> $no_aln <<\n";
-    }
-    elsif($_ =~ /^Sequences with no alignments under any condition:/){  ## Single-end
-      (undef,$no_aln) = split /\t/;
-      # warn "No alignments SE>> $no_aln <<\n";
-    }
-
-    elsif($_ =~ /^Sequence pairs did not map uniquely:/){ ## Paired-end
-      (undef,$multiple) = split /\t/;
-      # warn "Multiple alignments PE >> $multiple <<\n";
-    }
-    elsif($_ =~ /^Sequences did not map uniquely:/){ ## Single-end
-      (undef,$multiple) = split /\t/;
-      # warn "Multiple alignments SE >> $multiple <<\n";
-    }
-
-    elsif($_ =~ /^Sequence pairs which were discarded because genomic sequence could not be extracted:/){ ## Paired-end
-      (undef,$no_genomic) = split /\t/;
-      # warn "No genomic sequence PE >> $no_genomic <<\n";
-    }
-    elsif($_ =~ /^Sequences which were discarded because genomic sequence could not be extracted:/){ ## Single-end
-      (undef,$no_genomic) = split /\t/;
-      # warn "No genomic sequence SE>> $no_genomic <<\n";
-    }
-
-    ### Context Methylation
-    elsif($_ =~ /^Total number of C/ ){
-      (undef,$total_C_count) = split /\t/;
-      # warn "Total number C >> $total_C_count <<\n";
-    }
-
-    elsif($_ =~ /^Total methylated C\'s in CpG context:/ ){
-      (undef,$meth_CpG) = split /\t/;
-      # warn "meth CpG >> $meth_CpG <<\n" ;
-    }
-    elsif($_ =~ /^Total methylated C\'s in CHG context:/ ){
-      (undef,$meth_CHG) = split /\t/;
-      # warn "meth CHG >> $meth_CHG <<\n" ;
-    }
-    elsif($_ =~ /^Total methylated C\'s in CHH context:/ ){
-      (undef,$meth_CHH) = split /\t/;
-      # warn "meth CHH >> $meth_CHH <<\n" ;
-    }
-    elsif($_ =~ /^Total methylated C\'s in Unknown context:/ ){
-      (undef,$meth_unknown) = split /\t/;
-      # warn "meth Unknown >> $meth_unknown <<\n" ;
-    }
-
-    elsif($_ =~ /^Total unmethylated C\'s in CpG context:/ or $_ =~ /^Total C to T conversions in CpG context:/){
-      (undef,$unmeth_CpG) = split /\t/;
-      # warn "unmeth CpG >> $unmeth_CpG <<\n" ;
-    }
-    elsif($_ =~ /^Total unmethylated C\'s in CHG context:/ or $_ =~ /^Total C to T conversions in CHG context:/){
-      (undef,$unmeth_CHG) = split /\t/;
-      # warn "unmeth CHG >> $unmeth_CHG <<\n" ;
-    }
-    elsif($_ =~ /^Total unmethylated C\'s in CHH context:/ or $_ =~ /^Total C to T conversions in CHH context:/){
-      (undef,$unmeth_CHH) = split /\t/;
-      # warn "unmeth CHH >> $unmeth_CHH <<\n";
-    }
-    elsif($_ =~ /^Total unmethylated C\'s in Unknown context:/ or $_ =~ /^Total C to T conversions in Unknown context:/){
-      (undef,$unmeth_unknown) = split /\t/;
-      # warn "unmeth Unknown >> $unmeth_unknown <<\n" ;
-    }
-
-    ### Strand Origin
-
-    elsif($_ =~ /^CT\/GA\/CT:/ ){             ## Paired-end
-      (undef,$number_OT) = split /\t/;
-      # warn "Number OT PE>> $number_OT <<\n" ;
-    }
-    elsif($_ =~ /^CT\/CT:/ ){                 ## Single-end
-      (undef,$number_OT) = split /\t/;
-      # warn "Number OT SE>> $number_OT <<\n" ;
-    }
-
-    elsif($_ =~ /^GA\/CT\/CT:/ ){             ## Paired-end
-      (undef,$number_CTOT) = split /\t/;
-      # warn "Number CTOT PE >> $number_CTOT <<\n" ;
-    }
-    elsif($_ =~ /^GA\/CT:/ ){                 ## Single-end
-      (undef,$number_CTOT) = split /\t/;
-      # warn "Number CTOT SE >> $number_CTOT <<\n" ;
-    }
-
-    elsif($_ =~ /^GA\/CT\/GA:/ ){             ## Paired-end
-      (undef,$number_CTOB) = split /\t/;
-      # warn "Number CTOB PE >> $number_CTOB <<\n" ;
-    }
-    elsif($_ =~ /^GA\/GA:/ ){                 ## Single-end
-      (undef,$number_CTOB) = split /\t/;
-      # warn "Number CTOB SE >> $number_CTOB <<\n";
-    }
-
-    elsif($_ =~ /^CT\/GA\/GA:/ ){             ## Paired-end
-      (undef,$number_OB) = split /\t/;
-      # warn "Number OB PE >> $number_OB <<\n";
-    }
-    elsif($_ =~ /^CT\/GA:/ ){                 ## Single-end
-      (undef,$number_OB) = split /\t/;
-      # warn "Number OB SE >> $number_OB <<\n";
-    }
-  }
-
-  $counting{sequences_count}                               += $total_seqs;
-  $counting{unique_best_alignment_count}                   += $unique;
-  $counting{no_single_alignment_found}                     += $no_aln;
-  $counting{unsuitable_sequence_count}                     += $multiple;
-  $counting{genomic_sequence_could_not_be_extracted_count} += $no_genomic;
-
-  $counting{total_meCHH_count}                             += $meth_CHH;
-  $counting{total_meCHG_count}                             += $meth_CHG;
-  $counting{total_meCpG_count}                             += $meth_CpG;
-  if ($bowtie2){
-    $counting{total_meC_unknown_count}                     += $meth_unknown;
-  }
-
-  $counting{total_unmethylated_CHH_count}                  += $unmeth_CHH;
-  $counting{total_unmethylated_CHG_count}                  += $unmeth_CHG;
-  $counting{total_unmethylated_CpG_count}                  += $unmeth_CpG;
-  if ($bowtie2){
-    $counting{total_unmethylated_C_unknown_count}          += $unmeth_unknown;
-  }
-
-  if ($single_end){
-    $counting{CT_CT_count}    += $number_OT;
-    $counting{CT_GA_count}    += $number_OB;
-    $counting{GA_CT_count}    += $number_CTOT;
-    $counting{GA_GA_count}    += $number_CTOB;
-  }
-  else{
-    # paired-end
-    $counting{GA_CT_CT_count} += $number_CTOT;
-    $counting{CT_GA_CT_count} += $number_OT;
-    $counting{GA_CT_GA_count} += $number_CTOB;
-    $counting{CT_GA_GA_count} += $number_OB;
-  }
-}
-
-sub merge_individual_ambiguous_files{
-
-  my ($temp_ambiguous,$original_filename,$single_end,$paired_information) = @_;
-  my $ambiguous_file = $original_filename;
-  $ambiguous_file =~ s/.*\///; # removing path information
-
-  if ($prefix){
-    $ambiguous_file = "${prefix}.${ambiguous_file}";
-  }
-
-  if ($single_end){
-
-    if ($basename){ # Output file basename is set using the -B argument
-      if ($sequence_file_format eq 'FASTQ'){
-	$ambiguous_file = "${basename}_ambiguous_reads.fq.gz";
-      }
-      else{
-	$ambiguous_file = "${basename}_ambiguous_reads.fa.gz";
-      }
-    }
-    else{
-      if ($sequence_file_format eq 'FASTQ'){
-	$ambiguous_file =~ s/$/_ambiguous_reads.fq.gz/;
-      }
-      else{
-	$ambiguous_file =~ s/$/_ambiguous_reads.fa.gz/;
-      }
-    }
-  }
-  else{ # paired-end
-
-    if ($basename){ # Output file basename is set using the -B argument
-      if ($sequence_file_format eq 'FASTQ'){
-	$ambiguous_file = "${basename}_ambiguous_reads${paired_information}.fq.gz";
-      }
-      else{
-	$ambiguous_file = "${basename}_ambiguous_reads${paired_information}.fa.gz";
-      }
-    }
-    else{
-      if ($sequence_file_format eq 'FASTQ'){
-	$ambiguous_file =~ s/$/_ambiguous_reads${paired_information}.fq.gz/;
-      }
-      else{
-	$ambiguous_file =~ s/$/_ambiguous_reads${paired_information}.fa.gz/;
-      }
-    }
-  }
-
-  foreach my $temp(@$temp_ambiguous){
-    $temp =~ s/.*\///; # removing path information
-  }
-
-  open (AMBIGUOUS,"| gzip -c - > $output_dir$ambiguous_file") or die "Failed to write to $ambiguous_file: $!\n";
-  warn "Now merging ambiguous sequences @$temp_ambiguous into >>> $output_dir$ambiguous_file <<<\n";
-
-  foreach my $temp(@$temp_ambiguous){
-    warn "Merging from file >> $temp <<\n";
-    if ($temp =~ /gz$/){
-      open (IN,"gunzip -c ${output_dir}$temp |") or die "Failed to read from ambiguous temp file '${output_dir}$temp'\n";
-    }
-    else{
-      open (IN,"${output_dir}$temp") or die "Failed to read from ambiguous temp file '${output_dir}$temp'\n";
-    }
-
-    while (<IN>){
-      print AMBIGUOUS;
-    }
-    close IN or warn "Failed to close filehandle\n";
-  }
-  warn "\n";
-
-  close AMBIGUOUS or warn "Failed to close output filehandle AMBIGUOUS\n\n";
-}
-
-
-sub merge_individual_unmapped_files{
-
-  my ($temp_unmapped,$original_filename,$single_end,$paired_information) = @_;
-  my $unmapped_file = $original_filename;
-  $unmapped_file =~ s/.*\///; # removing path information
-
-  if ($prefix){
-    $unmapped_file = "${prefix}.${unmapped_file}";
-  }
-
-  if ($single_end){
-
-    if ($basename){ # Output file basename is set using the -B argument
-      if ($sequence_file_format eq 'FASTQ'){
-	$unmapped_file = "${basename}_unmapped_reads.fq.gz";
-      }
-      else{
-	$unmapped_file = "${basename}_unmapped_reads.fa.gz";
-      }
-    }
-    else{
-      if ($sequence_file_format eq 'FASTQ'){
-	$unmapped_file =~ s/$/_unmapped_reads.fq.gz/;
-      }
-      else{
-	$unmapped_file =~ s/$/_unmapped_reads.fa.gz/;
-      }
-    }
-  }
-  else{ # paired-end
-
-    if ($basename){ # Output file basename is set using the -B argument
-      if ($sequence_file_format eq 'FASTQ'){
-	$unmapped_file = "${basename}_unmapped_reads${paired_information}.fq.gz";
-      }
-      else{
-	$unmapped_file = "${basename}_unmapped_reads${paired_information}.fa.gz";
-      }
-    }
-    else{
-      if ($sequence_file_format eq 'FASTQ'){
-	$unmapped_file =~ s/$/_unmapped_reads${paired_information}.fq.gz/;
-      }
-      else{
-	$unmapped_file =~ s/$/_unmapped_reads${paired_information}.fa.gz/;
-      }
-    }
-  }
-
-  foreach my $temp(@$temp_unmapped){
-    $temp =~ s/.*\///; # removing path information
-  }
-
-  open (UNMAPPED,"| gzip -c - > ${output_dir}${unmapped_file}") or die "Failed to write to ${output_dir}${unmapped_file}: $!\n";
-  warn "Now merging unmapped sequences @$temp_unmapped into >>> ${output_dir}${unmapped_file} <<<\n";
-
-  foreach my $temp(@$temp_unmapped){
-    warn "Merging from file >> $temp <<\n";
-    if ($temp =~ /gz$/){
-      open (IN,"gunzip -c ${output_dir}${temp} |") or die "Failed to read from unmapped temp file '${output_dir}$temp'\n";
-    }
-    else{
-      open (IN,"${output_dir}${temp}") or die "Failed to read from unmapped temp file '${output_dir}${temp}'\n";
-    }
-
-    while (<IN>){
-      print UNMAPPED;
-    }
-    close IN or warn "Failed to close filehandle\n";
-  }
-  warn "\n";
-
-  close UNMAPPED or warn "Failed to close output filehandle UNMAPPED\n\n";
-}
-
-
-sub merge_individual_BAM_files{
-
-  my ($tempbam,$original_filename,$single_end) = @_;
-  my $merged_name = $original_filename;
-  
-  #warn "merged name is: $merged_name\n";
-  $merged_name =~ s/.*\///; # deleting path information
-  # warn "merged name is: $merged_name\n";
-  $merged_name =~ s/(\.fastq\.gz|\.fq\.gz|\.fastq|\.fq)$//; # attempting to remove fastq.gz etc to make filename a little shorter
-  # warn "merged name is: $merged_name\n"; sleep(5);
-  
-  foreach my $temp_bam(@$tempbam){
-    $temp_bam =~ s/.*\///; # deleting path information
-  }
-
-  if ($prefix){
-    $merged_name = "$prefix.$merged_name";
-  }
-
-  if ($single_end){
-    if ($bowtie2){ # BAM format is the default for Bowtie 2
-      $merged_name .= '_bismark_bt2.bam';
-    }
-    else{          # BAM is the default output
-      $merged_name .= '_bismark.bam';
-    }
-
-    if ($basename){ # Output file basename is set using the -B argument
-      $merged_name = "${basename}.bam";
-    }
-  }
-  else{
-    if ($bowtie2){ # BAM format is the default for Bowtie 2
-      $merged_name .= '_bismark_bt2_pe.bam';
-    }
-    else{          # BAM is the default output
-      $merged_name .= '_bismark_pe.bam';
-    }
-
-    if ($basename){ # Output file basename is set using the -B argument
-      $merged_name = "${basename}_pe.bam";
-    }
-  }
-  
-
-  if ($cram){
-      $merged_name =~ s/bam$/cram/;
-      warn "At this stage we write out a single CRAM file and delete all temporary BAM files\n";
-      warn "Now merging BAM files @$tempbam into >>> $merged_name <<<\n";
-      $final_output_filename = "${output_dir}${merged_name}";
-      
-      open (OUT,"| $samtools_path view -h -C -T $cram_ref 2>/dev/null - > ${output_dir}${merged_name}") or die "Failed to write to CRAM file $merged_name: $!\nPlease note that this option requires Samtools version 1.2 or higher!\n\n";
-  }
-  else{
-      $final_output_filename = "${output_dir}${merged_name}";
-      warn "Now merging BAM files @$tempbam into >>> $merged_name <<<\n";
-      open (OUT,"| $samtools_path view -bSh 2>/dev/null - > ${output_dir}${merged_name}") or die "Failed to write to $merged_name: $!\n";
-  }  
-
-  my $first = 0;
-  
-  foreach my $temp_bam(@$tempbam){
-    # $temp_bam =~ s/.*\///; # deleting path information
-
-    warn "Merging from file >> $temp_bam <<\n";
-
-    if ($first > 0){
-      open (IN,"$samtools_path view ${output_dir}${temp_bam} |") or die "Failed to read from BAM file ${output_dir}${temp_bam}\n";
-    }
-    else{ # only for the first file we print the header as well
-      open (IN,"$samtools_path view -h ${output_dir}${temp_bam} |") or die "Failed to read from BAM file ${output_dir}${temp_bam}\n";
-    }
-
-    while (<IN>){
-      print OUT;
-    }
-    close IN or warn "Failed to close filehandle\n";
-    ++$first;
-  }
-  warn "\n";
-
-  close OUT or warn "Failed to close output filehandle\n\n";
-  
-}
-
-
-sub merge_individual_ambig_BAM_files{
-    
-    my ($tempbam,$original_filename,$single_end) = @_;
-    my $merged_name = $original_filename;
-    
-    # warn "merged name is: $merged_name\n";
-    $merged_name =~ s/.*\///; # deleting path information
-    # warn "merged name is: $merged_name\n"; sleep(1);
-
-    foreach my $temp_bam(@$tempbam){
-	$temp_bam =~ s/.*\///; # deleting path information
-    }
-    
-    if ($prefix){
-	$merged_name = "$prefix.$merged_name";
-    }
-    
-    if ($single_end){
-	if ($bowtie2){ # BAM format is the default for Bowtie 2
-	    $merged_name .= '_bismark_bt2.ambig.bam';
-	}
-	
-	if ($basename){ # Output file basename is set using the -B argument
-	    $merged_name = "${basename}.ambig.bam";
-	}
-    }
-    else{
-	if ($bowtie2){ # BAM format is the default for Bowtie 2
-	    $merged_name .= '_bismark_bt2_pe.ambig.bam';
-	}
-	
-	if ($basename){ # Output file basename is set using the -B argument
-	    $merged_name = "${basename}_pe.ambig.bam";
-	}
-    }
-
-    warn "Now merging ambiguous BAM files @$tempbam into >>> $merged_name <<<\n";
-    open (OUT,"| $samtools_path view -bSh 2>/dev/null - > ${output_dir}${merged_name}") or die "Failed to write to $merged_name: $!\n";
-    my $first = 0;
-    
-    foreach my $temp_bam(@$tempbam){
-	# $temp_bam =~ s/.*\///; # deleting path information
-	
-	warn "Merging from file >> $temp_bam <<\n";
-	
-	if ($first > 0){
-	    open (IN,"$samtools_path view ${output_dir}${temp_bam} |") or die "Failed to read from BAM file ${output_dir}${temp_bam}\n";
-	}
-	else{ # only for the first file we print the header as well
-	    open (IN,"$samtools_path view -h ${output_dir}${temp_bam} |") or die "Failed to read from BAM file ${output_dir}${temp_bam}\n";
-	}
-
-	while (<IN>){
-	    print OUT;
-	}
-	close IN or warn "Failed to close filehandle\n";
-	++$first;
-    }
-    warn "\n";
-    
-    close OUT or warn "Failed to close output filehandle\n\n";
-}
-
-sub start_methylation_call_procedure_single_ends {
-  my ($sequence_file,$C_to_T_infile,$G_to_A_infile,$pid) = @_;
-  my ($dir,$filename);
-
-  if ($sequence_file =~ /\//){
-    ($dir,$filename) = $sequence_file =~ m/(.*\/)(.*)$/;
-  }
-  else{
-    $filename = $sequence_file;
-  }
-
-  ### printing all alignments to a results file
-  my $outfile = $filename;
-  # warn "Outfile: $outfile\n";
-  $outfile =~ s/(\.fastq\.gz|\.fq\.gz|\.fastq|\.fq)$//; # attempting to remove fastq.gz etc to make filename a little shorter
-  # warn "Outfile: $outfile\n";sleep(5);
-  
-  if ($prefix){
-    $outfile = "$prefix.$outfile";
-  }
-  if ($bowtie2){ # SAM format is the default for Bowtie 2
-    $outfile =~ s/$/_bismark_bt2.sam/;
-  }
-  elsif ($vanilla){ # vanilla custom Bismark output single-end output (like Bismark versions 0.5.X)
-    $outfile =~ s/$/_bismark.txt/;
-  }
-  else{ # SAM is the default output
-    $outfile =~ s/$/_bismark.sam/;
-  }
-
-  if ($basename){ # Output file basename is set using the -B argument
-    $outfile = "${basename}.sam";
-  }
-
-  $bam = 0 unless (defined $bam);
-  
-  if ($ambig_bam){
-      my $ambig_bam_out = $outfile;
-      $ambig_bam_out =~ s/sam$/ambig.bam/;
-      warn "Ambiguous BAM output: $ambig_bam_out\n";
-      open (AMBIBAM,"| $samtools_path view -bSh 2>/dev/null - > $output_dir$ambig_bam_out") or die "Failed to write to $ambig_bam_out: $!\n";
-  }
-
-  if ($cram){ ### Samtools is installed, writing out CRAM directly. This qill require Samtools version 1.2 or higher!
-      ### for multicore processing we write out BAM files by default and merge them together as a single CRAM file in the merging step later on.
-      ### This avoids having to change all the the file endings on the way
-      if($multicore > 1){
-	  $outfile =~ s/sam$/bam/;
-	  open (OUT,"| $samtools_path view -bSh 2>/dev/null - > $output_dir$outfile") or die "Failed to write to $outfile: $!\n";
-      }
-      else{ # single-core mode
-	  $outfile =~ s/sam$/cram/;
-	  $final_output_filename = "${output_dir}${outfile}";
-	  open (OUT,"| $samtools_path view -h -C -T $cram_ref 2>/dev/null - > $output_dir$outfile") or die "Failed to write to CRAM file $outfile: $!\nPlease note that this option requires Samtools version 1.2 or higher!\n\n";
-      }
-  }
-  elsif($bam == 1){ ### Samtools is installed, writing out BAM directly
-      $outfile =~ s/sam$/bam/;
-      $final_output_filename = "${output_dir}${outfile}";
-      open (OUT,"| $samtools_path view -bSh 2>/dev/null - > $output_dir$outfile") or die "Failed to write to $outfile: $!\n";
-  }
-  elsif($bam == 2){ ### no Samtools found on system. Using GZIP compression instead
-      $outfile .= '.gz';
-      open (OUT,"| gzip -c - > $output_dir$outfile") or die "Failed to write to $outfile: $!\n";
-  }
-  else{ # uncompressed ouput, default
-      open (OUT,'>',"$output_dir$outfile") or die "Failed to write to $outfile: $!\n";
-  }
-  warn "\n>>> Writing bisulfite mapping results to $output_dir$outfile <<<\n\n";
-
- 
-  sleep(1);
-  
-  if ($vanilla){
-    print OUT "Bismark version: $bismark_version\n";
-  }
-
-  ### printing alignment and methylation call summary to a report file
-  my $reportfile = $filename;
-  $reportfile =~ s/(\.fastq\.gz|\.fq\.gz|\.fastq|\.fq)$//; # attempting to remove fastq.gz etc to make filename a little shorter
-
-  if ($prefix){
-    $reportfile = "$prefix.$reportfile";
-  }
-  if ($bowtie2){
-    $reportfile =~ s/$/_bismark_bt2_SE_report.txt/;
-  }
-  else{
-    $reportfile =~ s/$/_bismark_SE_report.txt/;
-  }
-
-  if ($basename){ # Output file basename is set using the -B argument
-    $reportfile = "${basename}_SE_report.txt";
-  }
-
-  open (REPORT,'>',"$output_dir$reportfile") or die "Failed to write to $reportfile: $!\n";
-  print REPORT "Bismark report for: $sequence_file (version: $bismark_version)\n";
-
-  if ($unmapped){
-    my $unmapped_file = $filename;
-    if ($prefix){
-      $unmapped_file = "$prefix.$unmapped_file";
-    }
-
-    if ($basename){ # Output file basename is set using the -B argument
-      if ($sequence_file_format eq 'FASTQ'){
-	$unmapped_file = "${basename}_unmapped_reads.fq";
-      }
-      else{
-	$unmapped_file = "${basename}_unmapped_reads.fa";
-      }
-    }
-    else{
-      if ($sequence_file_format eq 'FASTQ'){
-	$unmapped_file =~ s/$/_unmapped_reads.fq/;
-      }
-      else{
-	$unmapped_file =~ s/$/_unmapped_reads.fa/;
-      }
-    }
-
-    if ($multicore > 1){ # multicore runs already output gzipped unmapped files
-      open (UNMAPPED,'>',"$output_dir$unmapped_file") or die "Failed to write to $unmapped_file: $!\n";
-    }
-    else{
-      $unmapped_file .= '.gz';
-      open (UNMAPPED,"| gzip -c - > $output_dir$unmapped_file") or die "Failed to write to $unmapped_file: $!\n";
-    }
-    warn "Unmapped sequences will be written to $output_dir$unmapped_file\n";
-  }
-
-  if ($ambiguous){
-    my $ambiguous_file = $filename;
-
-    if ($prefix){
-      $ambiguous_file = "$prefix.$ambiguous_file";
-    }
-
-    if ($basename){ # Output file basename is set using the -B argument
-      if ($sequence_file_format eq 'FASTQ'){
-	$ambiguous_file =  "${basename}_ambiguous_reads.fq";
-      }
-      else{
-	$ambiguous_file =  "${basename}_ambiguous_reads.fa";
-      }
-    }
-    else{
-      if ($sequence_file_format eq 'FASTQ'){
-	$ambiguous_file =~ s/$/_ambiguous_reads.fq/;
-      }
-      else{
-	$ambiguous_file =~ s/$/_ambiguous_reads.fa/;
-      }
-    }
-
-    if ($multicore > 1){ # multicore runs already output gzipped amobiguous files
-      open (AMBIG,'>',"$output_dir$ambiguous_file") or die "Failed to write to $ambiguous_file: $!\n";
-    }
-    else{
-      $ambiguous_file .= '.gz';
-      open (AMBIG,"| gzip -c - > $output_dir$ambiguous_file") or die "Failed to write to $ambiguous_file: $!\n";
-    }
-    warn "Ambiguously mapping sequences will be written to $output_dir$ambiguous_file\n";
-  }
-
-  if ($directional){
-      print REPORT "Option '--directional' specified (default mode): alignments to complementary strands (CTOT, CTOB) were ignored (i.e. not performed)\n";
-  }
-  elsif ($pbat){
-      print REPORT "Option '--pbat' specified: alignments to original strands (OT and OB) strands were ignored (i.e. not performed)\n";
-  }
-  else{
-      print REPORT "Option '--non_directional' specified: alignments to all strands were being performed (OT, OB, CTOT, CTOB)\n";
-  }
-  
-  if ($bowtie2){
-      print REPORT "Bismark was run with Bowtie 2 against the bisulfite genome of $genome_folder with the specified options: $bowtie_options\n\n";
-  }
-  else{
-      print REPORT "Bismark was run with Bowtie against the bisulfite genome of $genome_folder with the specified options: $bowtie_options\n\n";
-  }
-
-  
-  unless ($vanilla or $sam_no_hd){
-      generate_SAM_header();
-  }
-  
-  ### Input file is in FastA format
-  if ($sequence_file_format eq 'FASTA'){
-    process_single_end_fastA_file_for_methylation_call($sequence_file,$C_to_T_infile,$G_to_A_infile,$pid);
-  }
-  ### Input file is in FastQ format
-  else{
-    process_single_end_fastQ_file_for_methylation_call($sequence_file,$C_to_T_infile,$G_to_A_infile,$pid);
-  }
-}
-
-sub start_methylation_call_procedure_paired_ends {
-  my ($sequence_file_1,$sequence_file_2,$C_to_T_infile_1,$G_to_A_infile_1,$C_to_T_infile_2,$G_to_A_infile_2,$pid) = @_;
-  my ($dir_1,$filename_1);
-    
-  if ($sequence_file_1 =~ /\//){
-      ($dir_1,$filename_1) = $sequence_file_1 =~ m/(.*\/)(.*)$/;
-  }
-  else{
-      $filename_1 = $sequence_file_1;
-  }
-  
-  my ($dir_2,$filename_2);
-
-  if  ($sequence_file_2 =~ /\//){
-    ($dir_2,$filename_2) = $sequence_file_2 =~ m/(.*\/)(.*)$/;
-  }
-  else{
-    $filename_2 = $sequence_file_2;
-  }
-
-  ### printing all alignments to a results file
-  my $outfile = $filename_1;
-  # warn "Outfile: $outfile\n";
-  $outfile =~ s/(\.fastq\.gz|\.fq\.gz|\.fastq|\.fq)$//; # attempting to remove fastq.gz etc to make filename a little shorter
-  # warn "Outfile: $outfile\n";sleep(5);
-
-  if ($prefix){
-    $outfile = "$prefix.$outfile";
-  }
-  if ($bowtie2){ # SAM format is the default Bowtie 2 output
-    $outfile =~ s/$/_bismark_bt2_pe.sam/;
-  }
-  elsif ($vanilla){ # vanilla custom Bismark paired-end output (like Bismark versions 0.5.X)
-    $outfile =~ s/$/_bismark_pe.txt/;
-  }
-  else{ # SAM format is the default Bowtie 1 output
-    $outfile =~ s/$/_bismark_pe.sam/;
-  }
-
-
-  if ($basename){ # Output file basename is set using the -B argument
-    $outfile = "${basename}_pe.sam";
-  }
-  
-  if ($ambig_bam){
-      my $ambig_bam_out = $outfile;
-      $ambig_bam_out =~ s/sam$/ambig.bam/;
-      warn "Ambiguous BAM output: $ambig_bam_out\n";
-      open (AMBIBAM,"| $samtools_path view -bSh 2>/dev/null - > $output_dir$ambig_bam_out") or die "Failed to write to $ambig_bam_out: $!\n";
-  }
-  
-  $bam = 0 unless (defined $bam);
-  
-  if ($cram){ ### Samtools is installed, writing out CRAM directly. This qill require Samtools version 1.2 or higher!
-      if ($multicore > 1){
-	  $outfile =~ s/sam$/bam/;
-	  open (OUT,"| $samtools_path view -bSh 2>/dev/null - > $output_dir$outfile") or die "Failed to write to $outfile: $!\n";
-      }
-      else{ # single-core mode
-	  $outfile =~ s/sam$/cram/;
-	  $final_output_filename = "${output_dir}${outfile}";	  
-	  open (OUT,"| $samtools_path view -h -C -T $cram_ref 2>/dev/null - > $output_dir$outfile") or die "Failed to write to CRAM file $outfile: $!\nPlease note that this option requires Samtools version 1.2 or higher!\n\n";
-      }
-  }
-  elsif ($bam == 1){ ### Samtools is installed, writing out BAM directly
-      $outfile =~ s/sam$/bam/;
-      $final_output_filename = "${output_dir}${outfile}";	  
-      open (OUT,"| $samtools_path view -bSh 2>/dev/null - > $output_dir$outfile") or die "Failed to write to $outfile: $!\n";
-  }
-  elsif($bam == 2){ ### no Samtools found on system. Using GZIP compression instead
-      $outfile .= '.gz';
-      open (OUT,"| gzip -c - > $output_dir$outfile") or die "Failed to write to $outfile: $!\n";
-  }
-  else{ # uncompressed ouput, default
-      open (OUT,'>',"$output_dir$outfile") or die "Failed to write to $outfile: $!\n";
-  }
-
-  warn "\n>>> Writing bisulfite mapping results to $outfile <<<\n\n";
-  sleep(1);
-
-  if ($vanilla){
-    print OUT "Bismark version: $bismark_version\n";
-  }
-
-  ### printing alignment and methylation call summary to a report file
-  my $reportfile = $filename_1;
-  $reportfile =~ s/(\.fastq\.gz|\.fq\.gz|\.fastq|\.fq)$//; # attempting to remove fastq.gz etc to make filename a little shorter
-
-  if ($prefix){
-    $reportfile = "$prefix.$reportfile";
-  }
-
-  if ($bowtie2){
-    $reportfile =~ s/$/_bismark_bt2_PE_report.txt/;
-  }
-  else{
-    $reportfile =~ s/$/_bismark_PE_report.txt/;
-  }
-
-  if ($basename){ # Output file basename is set using the -B argument
-    $reportfile = "${basename}_PE_report.txt";
-  }
-
-  open (REPORT,'>',"$output_dir$reportfile") or die "Failed to write to $reportfile: $!\n";
-  print REPORT "Bismark report for: $sequence_file_1 and $sequence_file_2 (version: $bismark_version)\n";
-
-  if ($bowtie2){
-    print REPORT "Bismark was run with Bowtie 2 against the bisulfite genome of $genome_folder with the specified options: $bowtie_options\n";
-  }
-  else{
-    print REPORT "Bismark was run with Bowtie against the bisulfite genome of $genome_folder with the specified options: $bowtie_options\n";
-  }
-
-
-  ### Unmapped read output
-  if ($unmapped){
-    my $unmapped_1 = $filename_1;
-    my $unmapped_2 = $filename_2;
-
-    if ($prefix){
-      $unmapped_1 = "$prefix.$unmapped_1";
-      $unmapped_2 = "$prefix.$unmapped_2";
-    }
-
-    if ($basename){ # Output file basename is set using the -B argument
-      if ($sequence_file_format eq 'FASTQ'){
-	$unmapped_1 = "${basename}_unmapped_reads_1.fq";
-	$unmapped_2 = "${basename}_unmapped_reads_2.fq";
-      }
-      else{
-	$unmapped_1 = "${basename}_unmapped_reads_1.fa";
-	$unmapped_2 = "${basename}_unmapped_reads_2.fa";
-      }
-    }
-    else{
-      if ($sequence_file_format eq 'FASTQ'){
-	$unmapped_1 =~ s/$/_unmapped_reads_1.fq/;
-	$unmapped_2 =~ s/$/_unmapped_reads_2.fq/;
-      }
-      else{
-	$unmapped_1 =~ s/$/_unmapped_reads_1.fa/;
-	$unmapped_2 =~ s/$/_unmapped_reads_2.fa/;
-      }
-    }
-
-    if ($multicore > 1){ # unmapped files are merged into .gz files in multicore runs anyway
-      open (UNMAPPED_1,'>',"$output_dir$unmapped_1") or die "Failed to write to $unmapped_1: $!\n";
-      open (UNMAPPED_2,'>',"$output_dir$unmapped_2") or die "Failed to write to $unmapped_2: $!\n";
-    }
-    else{
-      $unmapped_1 .= '.gz';
-      $unmapped_2 .= '.gz';
-      open (UNMAPPED_1,"| gzip -c - > $output_dir$unmapped_1") or die "Failed to write to $unmapped_1: $!\n";
-      open (UNMAPPED_2,"| gzip -c - > $output_dir$unmapped_2") or die "Failed to write to $unmapped_2: $!\n";
-    }
-    warn "Unmapped sequences will be written to $unmapped_1 and $unmapped_2\n";
-  }
-
-  if ($ambiguous){
-    my $amb_1 = $filename_1;
-    my $amb_2 = $filename_2;
-
-    if ($prefix){
-      $amb_1 = "$prefix.$amb_1";
-      $amb_2 = "$prefix.$amb_2";
-    }
-
-    if ($basename){ # Output file basename is set using the -B argument
-      if ($sequence_file_format eq 'FASTQ'){
-	$amb_1 = "${basename}_ambiguous_reads_1.fq";
-	$amb_2 = "${basename}_ambiguous_reads_2.fq";
-      }
-      else{
-	$amb_1 = "${basename}_ambiguous_reads_1.fa";
-	$amb_2 = "${basename}_ambiguous_reads_2.fa";
-      }
-    }
-    else{
-      if ($sequence_file_format eq 'FASTQ'){
-	$amb_1 =~ s/$/_ambiguous_reads_1.fq/;
-	$amb_2 =~ s/$/_ambiguous_reads_2.fq/;
-      }
-      else{
-	$amb_1 =~ s/$/_ambiguous_reads_1.fa/;
-	$amb_2 =~ s/$/_ambiguous_reads_2.fa/;
-      }
-    }
-
-    if ($multicore > 1){ # ambiguous files are merged into .gz files in multicore runs anyway
-      open (AMBIG_1,'>',"$output_dir$amb_1") or die "Failed to write to $amb_1: $!\n";
-      open (AMBIG_2,'>',"$output_dir$amb_2") or die "Failed to write to $amb_2: $!\n";
-    }
-    else{
-      $amb_1 .= '.gz';
-      $amb_2 .= '.gz';
-      open (AMBIG_1,"| gzip -c - > $output_dir$amb_1") or die "Failed to write to $amb_1: $!\n";
-      open (AMBIG_2,"| gzip -c - > $output_dir$amb_2") or die "Failed to write to $amb_2: $!\n";
-    }
-    warn "Ambiguously mapping sequences will be written to $amb_1 and $amb_2\n";
-  }
-
-  if ($directional){
-    print REPORT "Option '--directional' specified (default mode): alignments to complementary strands (CTOT, CTOB) were ignored (i.e. not performed)\n\n";
-  }
-  elsif ($pbat){
-    print REPORT "Option '--pbat' specified: alignments to original strands (OT, OB) were ignored (i.e. not performed)\n\n";
-  }
-  else{
-    print REPORT "Option '--non_directional' specified: alignments to all strands were being performed (OT, OB, CTOT, CTOB)\n\n";
-  }
-
-
-
-  unless ($vanilla or $sam_no_hd){
-    generate_SAM_header();
-  }
-
-  ### Input files are in FastA format
-  if ($sequence_file_format eq 'FASTA'){
-    process_fastA_files_for_paired_end_methylation_calls($sequence_file_1,$sequence_file_2,$C_to_T_infile_1,$G_to_A_infile_1,$C_to_T_infile_2,$G_to_A_infile_2,$pid);
-  }
-  ### Input files are in FastQ format
-  else{
-    process_fastQ_files_for_paired_end_methylation_calls($sequence_file_1,$sequence_file_2,$C_to_T_infile_1,$G_to_A_infile_1,$C_to_T_infile_2,$G_to_A_infile_2,$pid);
-  }
-}
-
-sub print_final_analysis_report_single_end{
-  my ($C_to_T_infile,$G_to_A_infile,$pid,$merge_multi) = @_;
-
-  if ($merge_multi){
-    warn "Printing a final merged alignment report for all individual sub-reports\n\n";
-  }
-  else{
-    ### All sequences from the original sequence file have been analysed now
-    ### deleting temporary C->T or G->A infiles
-
-    if ($directional){
-      my $deletion_successful =  unlink "$temp_dir$C_to_T_infile";
-      if ($deletion_successful == 1){
-	warn "\nSuccessfully deleted the temporary file $temp_dir$C_to_T_infile\n\n";
-      }
-      else{
-	warn "Could not delete temporary file $C_to_T_infile properly $!\n";
-      }
-    }
-    elsif ($pbat){
-      my $deletion_successful =  unlink "$temp_dir$G_to_A_infile";
-      if ($deletion_successful == 1){
-	warn "\nSuccessfully deleted the temporary file $temp_dir$G_to_A_infile\n\n";
-      }
-      else{
-	warn "Could not delete temporary file $G_to_A_infile properly $!\n";
-      }
-    }
-    else{
-      my $deletion_successful =  unlink "$temp_dir$C_to_T_infile","$temp_dir$G_to_A_infile";
-      if ($deletion_successful == 2){
-	warn "\nSuccessfully deleted the temporary files $temp_dir$C_to_T_infile and $temp_dir$G_to_A_infile\n\n";
-      }
-      else{
-	warn "Could not delete temporary files properly $!\n";
-      }
-    }
-  }
-
-  ### printing a final report for the alignment procedure
-  print REPORT "Final Alignment report\n",'='x22,"\n";
-  warn "Final Alignment report\n",'='x22,"\n";
-  #  foreach my $index (0..$#fhs){
-  #    print "$fhs[$index]->{name}\n";
-  #    print "$fhs[$index]->{seen}\talignments on the correct strand in total\n";
-  #    print "$fhs[$index]->{wrong_strand}\talignments were discarded (nonsensical alignments)\n\n";
-  #  }
-
-  ### printing a final report for the methylation call procedure
-  warn "Sequences analysed in total:\t$counting{sequences_count}\n";
-  print REPORT "Sequences analysed in total:\t$counting{sequences_count}\n";
-  my $percent_alignable_sequences;
-
-  if ($counting{sequences_count} == 0){
-    $percent_alignable_sequences = 0;
-  }
-  else{
-    $percent_alignable_sequences = sprintf ("%.1f",$counting{unique_best_alignment_count}*100/$counting{sequences_count});
-  }
-
-  warn "Number of alignments with a unique best hit from the different alignments:\t$counting{unique_best_alignment_count}\nMapping efficiency:\t${percent_alignable_sequences}%\n\n";
-  print REPORT "Number of alignments with a unique best hit from the different alignments:\t$counting{unique_best_alignment_count}\nMapping efficiency:\t${percent_alignable_sequences}%\n";
-
-  ### percentage of low complexity reads overruled because of low complexity (thereby creating a bias for highly methylated reads),
-  ### only calculating the percentage if there were any overruled alignments
-  if ($counting{low_complexity_alignments_overruled_count}){
-    my $percent_overruled_low_complexity_alignments = sprintf ("%.1f",$counting{low_complexity_alignments_overruled_count}*100/$counting{sequences_count});
-    #   print REPORT "Number of low complexity alignments which were overruled to have a unique best hit rather than discarding them:\t$counting{low_complexity_alignments_overruled_count}\t(${percent_overruled_low_complexity_alignments}%)\n";
-  }
-
-  print "Sequences with no alignments under any condition:\t$counting{no_single_alignment_found}\n";
-  print "Sequences did not map uniquely:\t$counting{unsuitable_sequence_count}\n";
-  print "Sequences which were discarded because genomic sequence could not be extracted:\t$counting{genomic_sequence_could_not_be_extracted_count}\n\n";
-  print "Number of sequences with unique best (first) alignment came from the bowtie output:\n";
-  print join ("\n","CT/CT:\t$counting{CT_CT_count}\t((converted) top strand)","CT/GA:\t$counting{CT_GA_count}\t((converted) bottom strand)","GA/CT:\t$counting{GA_CT_count}\t(complementary to (converted) top strand)","GA/GA:\t$counting{GA_GA_count}\t(complementary to (converted) bottom strand)"),"\n\n";
-
-  print REPORT "Sequences with no alignments under any condition:\t$counting{no_single_alignment_found}\n";
-  print REPORT "Sequences did not map uniquely:\t$counting{unsuitable_sequence_count}\n";
-  print REPORT "Sequences which were discarded because genomic sequence could not be extracted:\t$counting{genomic_sequence_could_not_be_extracted_count}\n\n";
-  print REPORT "Number of sequences with unique best (first) alignment came from the bowtie output:\n";
-  print REPORT join ("\n","CT/CT:\t$counting{CT_CT_count}\t((converted) top strand)","CT/GA:\t$counting{CT_GA_count}\t((converted) bottom strand)","GA/CT:\t$counting{GA_CT_count}\t(complementary to (converted) top strand)","GA/GA:\t$counting{GA_GA_count}\t(complementary to (converted) bottom strand)"),"\n\n";
-
-  if ($directional){
-    print "Number of alignments to (merely theoretical) complementary strands being rejected in total:\t$counting{alignments_rejected_count}\n\n";
-    print REPORT "Number of alignments to (merely theoretical) complementary strands being rejected in total:\t$counting{alignments_rejected_count}\n\n";
-  }
-
-  ### detailed information about Cs analysed
-  warn "Final Cytosine Methylation Report\n",'='x33,"\n";
-  my $total_number_of_C = $counting{total_meCHH_count}+$counting{total_meCHG_count}+$counting{total_meCpG_count}+$counting{total_unmethylated_CHH_count}+$counting{total_unmethylated_CHG_count}+$counting{total_unmethylated_CpG_count};
-  warn "Total number of C's analysed:\t$total_number_of_C\n\n";
-  warn "Total methylated C's in CpG context:\t$counting{total_meCpG_count}\n";
-  warn "Total methylated C's in CHG context:\t$counting{total_meCHG_count}\n";
-  warn "Total methylated C's in CHH context:\t$counting{total_meCHH_count}\n";
-  if ($bowtie2){
-    warn "Total methylated C's in Unknown context:\t$counting{total_meC_unknown_count}\n";
-  }
-  warn "\n";
-
-  warn "Total unmethylated C's in CpG context:\t$counting{total_unmethylated_CpG_count}\n";
-  warn "Total unmethylated C's in CHG context:\t$counting{total_unmethylated_CHG_count}\n";
-  warn "Total unmethylated C's in CHH context:\t$counting{total_unmethylated_CHH_count}\n";
-  if ($bowtie2){
-    warn "Total unmethylated C's in Unknown context:\t$counting{total_unmethylated_C_unknown_count}\n";
-  }
-  warn "\n";
-
-  print REPORT "Final Cytosine Methylation Report\n",'='x33,"\n";
-  print REPORT "Total number of C's analysed:\t$total_number_of_C\n\n";
-
-  print REPORT "Total methylated C's in CpG context:\t$counting{total_meCpG_count}\n";
-  print REPORT "Total methylated C's in CHG context:\t$counting{total_meCHG_count}\n";
-  print REPORT "Total methylated C's in CHH context:\t$counting{total_meCHH_count}\n";
-  if ($bowtie2){
-    print REPORT "Total methylated C's in Unknown context:\t$counting{total_meC_unknown_count}\n";
-  }
-  print REPORT "\n";
-
-  print REPORT "Total unmethylated C's in CpG context:\t$counting{total_unmethylated_CpG_count}\n";
-  print REPORT "Total unmethylated C's in CHG context:\t$counting{total_unmethylated_CHG_count}\n";
-  print REPORT "Total unmethylated C's in CHH context:\t$counting{total_unmethylated_CHH_count}\n";
-  if ($bowtie2){
-    print REPORT "Total unmethylated C's in Unknown context:\t$counting{total_unmethylated_C_unknown_count}\n";
-  }
-  print REPORT "\n";
-
-  my $percent_meCHG;
-  if (($counting{total_meCHG_count}+$counting{total_unmethylated_CHG_count}) > 0){
-    $percent_meCHG = sprintf("%.1f",100*$counting{total_meCHG_count}/($counting{total_meCHG_count}+$counting{total_unmethylated_CHG_count}));
-  }
-
-  my $percent_meCHH;
-  if (($counting{total_meCHH_count}+$counting{total_unmethylated_CHH_count}) > 0){
-    $percent_meCHH = sprintf("%.1f",100*$counting{total_meCHH_count}/($counting{total_meCHH_count}+$counting{total_unmethylated_CHH_count}));
-  }
-
-  my $percent_meCpG;
-  if (($counting{total_meCpG_count}+$counting{total_unmethylated_CpG_count}) > 0){
-    $percent_meCpG = sprintf("%.1f",100*$counting{total_meCpG_count}/($counting{total_meCpG_count}+$counting{total_unmethylated_CpG_count}));
-  }
-
-  my $percent_meC_unknown;
-  if (($counting{total_meC_unknown_count}+$counting{total_unmethylated_C_unknown_count}) > 0){
-    $percent_meC_unknown = sprintf("%.1f",100*$counting{total_meC_unknown_count}/($counting{total_meC_unknown_count}+$counting{total_unmethylated_C_unknown_count}));
-  }
-
-
-  ### printing methylated CpG percentage if applicable
-  if ($percent_meCpG){
-    warn "C methylated in CpG context:\t${percent_meCpG}%\n";
-    print REPORT "C methylated in CpG context:\t${percent_meCpG}%\n";
-  }
-  else{
-    warn "Can't determine percentage of methylated Cs in CpG context if value was 0\n";
-    print REPORT "Can't determine percentage of methylated Cs in CpG context if value was 0\n";
-  }
-
-  ### printing methylated C percentage (CHG context) if applicable
-  if ($percent_meCHG){
-    warn "C methylated in CHG context:\t${percent_meCHG}%\n";
-    print REPORT "C methylated in CHG context:\t${percent_meCHG}%\n";
-  }
-  else{
-    warn "Can't determine percentage of methylated Cs in CHG context if value was 0\n";
-    print REPORT "Can't determine percentage of methylated Cs in CHG context if value was 0\n";
-  }
-
-  ### printing methylated C percentage (CHH context) if applicable
-  if ($percent_meCHH){
-    warn "C methylated in CHH context:\t${percent_meCHH}%\n";
-    print REPORT "C methylated in CHH context:\t${percent_meCHH}%\n";
-  }
-  else{
-    warn "Can't determine percentage of methylated Cs in CHH context if value was 0\n";
-    print REPORT "Can't determine percentage of methylated Cs in CHH context if value was 0\n";
-  }
-
-  ### printing methylated C percentage (Unknown C context) if applicable
-  if ($bowtie2){
-    if ($percent_meC_unknown){
-      warn "C methylated in Unknown context (CN or CHN):\t${percent_meC_unknown}%\n";
-      print REPORT "C methylated in Unknown context (CN or CHN):\t${percent_meC_unknown}%\n";
-    }
-    else{
-      warn "Can't determine percentage of methylated Cs in Unknown context (CN or CHN) if value was 0\n";
-      print REPORT "Can't determine percentage of methylated Cs in Unknown context (CN or CHN) if value was 0\n";
-    }
-  }
-  print REPORT "\n\n";
-  warn "\n\n";
-
-  if ($seqID_contains_tabs){
-    warn "The sequence IDs in the provided file contain tab-stops which might prevent sequence alignments. If this happened, please replace all tab characters within the seqID field with spaces before running Bismark.\n\n";
-    print REPORT "The sequence IDs in the provided file contain tab-stops which might prevent sequence alignments. If this happened, please replace all tab characters within the seqID field with spaces before running Bismark.\n\n";
-  }
-}
-
-
-sub print_final_analysis_report_paired_ends{
-  my ($C_to_T_infile_1,$G_to_A_infile_1,$C_to_T_infile_2,$G_to_A_infile_2,$pid,$merge_multi) = @_;
-
-  if ($merge_multi){
-    warn "Printing a final merged alignment report for all individual sub-reports\n\n";
-  }
-  else{
-    ### All sequences from the original sequence file have been analysed now, therefore deleting temporary C->T or G->A infiles
-    if ($directional){
-      if ($G_to_A_infile_2){
-	my $deletion_successful =  unlink "$temp_dir$C_to_T_infile_1","$temp_dir$G_to_A_infile_2";
-	if ($deletion_successful == 2){
-	  warn "\nSuccessfully deleted the temporary files $temp_dir$C_to_T_infile_1 and $temp_dir$G_to_A_infile_2\n\n";
-	}
-	else{
-	  warn "Could not delete temporary files $temp_dir$C_to_T_infile_1 and $temp_dir$G_to_A_infile_2 properly: $!\n";
-	}
-      }
-      else{ # for paired-end FastQ infiles with Bowtie1 there is only one file to delete
-	my $deletion_successful =  unlink "$temp_dir$C_to_T_infile_1";
-	if ($deletion_successful == 1){
-	  warn "\nSuccessfully deleted the temporary file $temp_dir$C_to_T_infile_1\n\n";
-	}
-	else{
-	  warn "Could not delete temporary file $temp_dir$C_to_T_infile_1 properly: $!\n";
-	}
-      }
-    }
-    else{
-      if ($G_to_A_infile_2 and $C_to_T_infile_2){
-	my $deletion_successful =  unlink "$temp_dir$C_to_T_infile_1","$temp_dir$G_to_A_infile_1","$temp_dir$C_to_T_infile_2","$temp_dir$G_to_A_infile_2";
-	if ($deletion_successful == 4){
-	  warn "\nSuccessfully deleted the temporary files $temp_dir$C_to_T_infile_1, $temp_dir$G_to_A_infile_1, $temp_dir$C_to_T_infile_2 and $temp_dir$G_to_A_infile_2\n\n";
-	}
-	else{
-	  warn "Could not delete temporary files properly: $!\n";
-	}
-      }
-      else{ # for paired-end FastQ infiles with Bowtie1 there are only two files to delete
-	my $deletion_successful =  unlink "$temp_dir$C_to_T_infile_1","$temp_dir$G_to_A_infile_1";
-	if ($deletion_successful == 2){
-	  warn "\nSuccessfully deleted the temporary files $temp_dir$C_to_T_infile_1 and $temp_dir$G_to_A_infile_1\n\n";
-	}
-	else{
-	  warn "Could not delete temporary files properly: $!\n";
-	}
-      }
-    }
-  }
-
-  ### printing a final report for the alignment procedure
-  warn "Final Alignment report\n",'='x22,"\n";
-  print REPORT "Final Alignment report\n",'='x22,"\n";
-  #  foreach my $index (0..$#fhs){
-  #    print "$fhs[$index]->{name}\n";
-  #    print "$fhs[$index]->{seen}\talignments on the correct strand in total\n";
-  #    print "$fhs[$index]->{wrong_strand}\talignments were discarded (nonsensical alignments)\n\n";
-  #  }
-
-  ### printing a final report for the methylation call procedure
-  warn "Sequence pairs analysed in total:\t$counting{sequences_count}\n";
-  print REPORT "Sequence pairs analysed in total:\t$counting{sequences_count}\n";
-
-  my $percent_alignable_sequence_pairs;
-  if ($counting{sequences_count} == 0){
-    $percent_alignable_sequence_pairs = 0;
-  }
-  else{
-    $percent_alignable_sequence_pairs = sprintf ("%.1f",$counting{unique_best_alignment_count}*100/$counting{sequences_count});
-  }
-  print "Number of paired-end alignments with a unique best hit:\t$counting{unique_best_alignment_count}\nMapping efficiency:\t${percent_alignable_sequence_pairs}%\n\n";
-  print REPORT "Number of paired-end alignments with a unique best hit:\t$counting{unique_best_alignment_count}\nMapping efficiency:\t${percent_alignable_sequence_pairs}% \n";
-
-  print "Sequence pairs with no alignments under any condition:\t$counting{no_single_alignment_found}\n";
-  print "Sequence pairs did not map uniquely:\t$counting{unsuitable_sequence_count}\n";
-  print "Sequence pairs which were discarded because genomic sequence could not be extracted:\t$counting{genomic_sequence_could_not_be_extracted_count}\n\n";
-  print "Number of sequence pairs with unique best (first) alignment came from the bowtie output:\n";
-  print join ("\n","CT/GA/CT:\t$counting{CT_GA_CT_count}\t((converted) top strand)","GA/CT/CT:\t$counting{GA_CT_CT_count}\t(complementary to (converted) top strand)","GA/CT/GA:\t$counting{GA_CT_GA_count}\t(complementary to (converted) bottom strand)","CT/GA/GA:\t$counting{CT_GA_GA_count}\t((converted) bottom strand)"),"\n\n";
-
-
-  print REPORT "Sequence pairs with no alignments under any condition:\t$counting{no_single_alignment_found}\n";
-  print REPORT "Sequence pairs did not map uniquely:\t$counting{unsuitable_sequence_count}\n";
-  print REPORT "Sequence pairs which were discarded because genomic sequence could not be extracted:\t$counting{genomic_sequence_could_not_be_extracted_count}\n\n";
-  print REPORT "Number of sequence pairs with unique best (first) alignment came from the bowtie output:\n";
-  print REPORT join ("\n","CT/GA/CT:\t$counting{CT_GA_CT_count}\t((converted) top strand)","GA/CT/CT:\t$counting{GA_CT_CT_count}\t(complementary to (converted) top strand)","GA/CT/GA:\t$counting{GA_CT_GA_count}\t(complementary to (converted) bottom strand)","CT/GA/GA:\t$counting{CT_GA_GA_count}\t((converted) bottom strand)"),"\n\n";
-  ### detailed information about Cs analysed
-
-  if ($directional){
-    print "Number of alignments to (merely theoretical) complementary strands being rejected in total:\t$counting{alignments_rejected_count}\n\n";
-    print REPORT "Number of alignments to (merely theoretical) complementary strands being rejected in total:\t$counting{alignments_rejected_count}\n\n";
-  }
-
-  warn "Final Cytosine Methylation Report\n",'='x33,"\n";
-  print REPORT "Final Cytosine Methylation Report\n",'='x33,"\n";
-
-  my $total_number_of_C = $counting{total_meCHG_count}+ $counting{total_meCHH_count}+$counting{total_meCpG_count}+$counting{total_unmethylated_CHG_count}+$counting{total_unmethylated_CHH_count}+$counting{total_unmethylated_CpG_count};
-  warn "Total number of C's analysed:\t$total_number_of_C\n\n";
-  warn "Total methylated C's in CpG context:\t$counting{total_meCpG_count}\n";
-  warn "Total methylated C's in CHG context:\t$counting{total_meCHG_count}\n";
-  warn "Total methylated C's in CHH context:\t$counting{total_meCHH_count}\n";
-  if ($bowtie2){
-    warn "Total methylated C's in Unknown context:\t$counting{total_meC_unknown_count}\n";
-  }
-  warn "\n";
-
-  warn "Total unmethylated C's in CpG context:\t$counting{total_unmethylated_CpG_count}\n";
-  warn "Total unmethylated C's in CHG context:\t$counting{total_unmethylated_CHG_count}\n";
-  warn "Total unmethylated C's in CHH context:\t$counting{total_unmethylated_CHH_count}\n";
-  if ($bowtie2){
-    warn "Total unmethylated C's in Unknown context:\t$counting{total_unmethylated_C_unknown_count}\n";
-  }
-  warn "\n";
-
-  print REPORT "Total number of C's analysed:\t$total_number_of_C\n\n";
-  print REPORT "Total methylated C's in CpG context:\t$counting{total_meCpG_count}\n";
-  print REPORT "Total methylated C's in CHG context:\t$counting{total_meCHG_count}\n";
-  print REPORT "Total methylated C's in CHH context:\t$counting{total_meCHH_count}\n";
-  if ($bowtie2){
-    print REPORT "Total methylated C's in Unknown context:\t$counting{total_meC_unknown_count}\n\n";
-  }
-  print REPORT "\n";
-
-  print REPORT "Total unmethylated C's in CpG context:\t$counting{total_unmethylated_CpG_count}\n";
-  print REPORT "Total unmethylated C's in CHG context:\t$counting{total_unmethylated_CHG_count}\n";
-  print REPORT "Total unmethylated C's in CHH context:\t$counting{total_unmethylated_CHH_count}\n";
-  if ($bowtie2){
-    print REPORT "Total unmethylated C's in Unknown context:\t$counting{total_unmethylated_C_unknown_count}\n\n";
-  }
-  print REPORT "\n";
-
-  my $percent_meCHG;
-  if (($counting{total_meCHG_count}+$counting{total_unmethylated_CHG_count}) > 0){
-    $percent_meCHG = sprintf("%.1f",100*$counting{total_meCHG_count}/($counting{total_meCHG_count}+$counting{total_unmethylated_CHG_count}));
-  }
-
-  my $percent_meCHH;
-  if (($counting{total_meCHH_count}+$counting{total_unmethylated_CHH_count}) > 0){
-    $percent_meCHH = sprintf("%.1f",100*$counting{total_meCHH_count}/($counting{total_meCHH_count}+$counting{total_unmethylated_CHH_count}));
-  }
-
-  my $percent_meCpG;
-  if (($counting{total_meCpG_count}+$counting{total_unmethylated_CpG_count}) > 0){
-    $percent_meCpG = sprintf("%.1f",100*$counting{total_meCpG_count}/($counting{total_meCpG_count}+$counting{total_unmethylated_CpG_count}));
-  }
-
-  my $percent_meC_unknown;
-  if (($counting{total_meC_unknown_count}+$counting{total_unmethylated_C_unknown_count}) > 0){
-    $percent_meC_unknown = sprintf("%.1f",100*$counting{total_meC_unknown_count}/($counting{total_meC_unknown_count}+$counting{total_unmethylated_C_unknown_count}));
-  }
-
-
-  ### printing methylated CpG percentage if applicable
-  if ($percent_meCpG){
-    warn "C methylated in CpG context:\t${percent_meCpG}%\n";
-    print REPORT "C methylated in CpG context:\t${percent_meCpG}%\n";
-  }
-  else{
-    warn "Can't determine percentage of methylated Cs in CpG context if value was 0\n";
-    print REPORT "Can't determine percentage of methylated Cs in CpG context if value was 0\n";
-  }
-
-  ### printing methylated C percentage in CHG context if applicable
-  if ($percent_meCHG){
-    warn "C methylated in CHG context:\t${percent_meCHG}%\n";
-    print REPORT "C methylated in CHG context:\t${percent_meCHG}%\n";
-  }
-  else{
-    warn "Can't determine percentage of methylated Cs in CHG context if value was 0\n";
-    print REPORT "Can't determine percentage of methylated Cs in CHG context if value was 0\n";
-  }
-
-  ### printing methylated C percentage in CHH context if applicable
-  if ($percent_meCHH){
-    warn "C methylated in CHH context:\t${percent_meCHH}%\n";
-    print REPORT "C methylated in CHH context:\t${percent_meCHH}%\n";
-  }
-  else{
-    warn "Can't determine percentage of methylated Cs in CHH context if value was 0\n";
-    print REPORT "Can't determine percentage of methylated Cs in CHH context if value was 0\n";
-  }
-
-  ### printing methylated C percentage (Unknown C context) if applicable
-  if ($bowtie2){
-    if ($percent_meC_unknown){
-      warn "C methylated in unknown context (CN or CHN):\t${percent_meC_unknown}%\n";
-      print REPORT "C methylated in unknown context (CN or CHN):\t${percent_meC_unknown}%\n";
-    }
-    else{
-      warn "Can't determine percentage of methylated Cs in unknown context (CN or CHN) if value was 0\n";
-      print REPORT "Can't determine percentage of methylated Cs in unknown context (CN or CHN) if value was 0\n";
-    }
-  }
-  print REPORT "\n\n";
-  warn "\n\n";
-
-}
-
-sub process_single_end_fastA_file_for_methylation_call{
-  my ($sequence_file,$C_to_T_infile,$G_to_A_infile,$pid) = @_;
-  ### this is a FastA sequence file; we need the actual sequence to compare it against the genomic sequence in order to make a methylation call.
-  ### Now reading in the sequence file sequence by sequence and see if the current sequence was mapped to one (or both) of the converted genomes in either
-  ### the C->T or G->A version
-
-  ### gzipped version of the infile
-  if ($sequence_file =~ /\.gz$/){
-    open (IN,"gunzip -c $sequence_file |") or die $!;
-  }
-  else{
-    open (IN,$sequence_file) or die $!;
-  }
-
-  my $count = 0;
-
-  warn "\nReading in the sequence file $sequence_file\n";
-  while (1) {
-    # last if ($counting{sequences_count} > 100);
-    my $identifier = <IN>;
-    my $sequence = <IN>;
-    last unless ($identifier and $sequence);
-
-    $identifier = fix_IDs($identifier); # this is to avoid problems with truncated read ID when they contain white spaces
-
-    ++$count;
-
-    if ($skip){
-      next unless ($count > $skip);
-    }
-    if ($upto){
-      last if ($count > $upto);
-    }
-
-    $counting{sequences_count}++;
-    if ($counting{sequences_count}%1000000==0) {
-      warn "Processed $counting{sequences_count} sequences so far\n";
-    }
-    chomp $sequence;
-    chomp $identifier;
-
-    $identifier =~ s/^>//; # deletes the > at the beginning of FastA headers
-
-    my $return;
-    if ($bowtie2){
-      $return = check_bowtie_results_single_end_bowtie2 (uc$sequence,$identifier);
-    }
-    else{
-      $return = check_bowtie_results_single_end(uc$sequence,$identifier); # default Bowtie 1
-    }
-
-    unless ($return){
-      $return = 0;
-    }
-
-    # print the sequence to ambiguous.out if --ambiguous was specified
-    if ($ambiguous and $return == 2){
-      print AMBIG ">$identifier\n";	
-      print AMBIG "$sequence\n";
-    }
-
-    # print the sequence to <unmapped.out> file if --un was specified
-    elsif ($unmapped and $return == 1){
-      print UNMAPPED ">$identifier\n";	
-      print UNMAPPED "$sequence\n";
-    }
-  }
-  print "Processed $counting{sequences_count} sequences in total\n\n";
- 
-  close OUT or warn "Failed to close filehandle OUT: $!\n";
-  
-  print_final_analysis_report_single_end($C_to_T_infile,$G_to_A_infile,$pid);
-
-}
-
-sub process_single_end_fastQ_file_for_methylation_call{
-
-  my ($sequence_file,$C_to_T_infile,$G_to_A_infile,$pid) = @_;
-
-  ### this is the Illumina sequence file; we need the actual sequence to compare it against the genomic sequence in order to make a methylation call.
-  ### Now reading in the sequence file sequence by sequence and see if the current sequence was mapped to one (or both) of the converted genomes in either
-  ### the C->T or G->A version
-
-  ### gzipped version of the infile
-  if ($sequence_file =~ /\.gz$/){
-    open (IN,"gunzip -c $sequence_file |") or die $!;
-  }
-  else{
-    open (IN,$sequence_file) or die $!;
-  }
-
-  my $count = 0;
-
-  warn "\nReading in the sequence file $sequence_file\n";
-  while (1) {
-    my $identifier = <IN>;
-    my $sequence = <IN>;
-    my $identifier_2 = <IN>;
-    my $quality_value = <IN>;
-    last unless ($identifier and $sequence and $identifier_2 and $quality_value);
-
-    $identifier = fix_IDs($identifier); # this is to avoid problems with truncated read ID when they contain white spaces
-
-    ++$count;
-
-    if ($skip){
-      next unless ($count > $skip);
-    }
-    if ($upto){
-      last if ($count > $upto);
-    }
-
-    $counting{sequences_count}++;
-
-    if ($counting{sequences_count}%1000000==0) {
-      warn "Processed $counting{sequences_count} sequences so far\n";
-    }
-    chomp $sequence;
-    chomp $identifier;
-    chomp $quality_value;
-
-    $identifier =~ s/^\@//;  # deletes the @ at the beginning of Illumin FastQ headers
-
-    my $return;
-    if ($bowtie2){
-      $return = check_bowtie_results_single_end_bowtie2 (uc$sequence,$identifier,$quality_value);
-    }
-    else{
-      $return = check_bowtie_results_single_end(uc$sequence,$identifier,$quality_value); # default Bowtie 1
-    }
-
-    unless ($return){
-      $return = 0;
-    }
-
-    # print the sequence to ambiguous.out if --ambiguous was specified
-    if ($ambiguous and $return == 2){
-      print AMBIG "\@$identifier\n";	
-      print AMBIG "$sequence\n";
-      print AMBIG $identifier_2;	
-      print AMBIG "$quality_value\n";
-    }
-
-    # print the sequence to <unmapped.out> file if --un was specified
-    elsif ($unmapped and $return == 1){
-      print UNMAPPED "\@$identifier\n";	
-      print UNMAPPED "$sequence\n";
-      print UNMAPPED $identifier_2;	
-      print UNMAPPED "$quality_value\n";
-    }
-  }
-  print "Processed $counting{sequences_count} sequences in total\n\n";
-
-  close OUT or warn "Failed to close filehandle OUT: $!\n";
-
-  print_final_analysis_report_single_end($C_to_T_infile,$G_to_A_infile,$pid);
-  if ($ambig_bam){
-      close AMBIBAM or warn "Had trouble closing filehandle AMBIBAM: $!\n";
-  }
-}
-
-sub process_fastA_files_for_paired_end_methylation_calls{
-  my ($sequence_file_1,$sequence_file_2,$C_to_T_infile_1,$G_to_A_infile_1,$C_to_T_infile_2,$G_to_A_infile_2,$pid) = @_;
-  ### Processing the two FastA sequence files; we need the actual sequences of both reads to compare them against the genomic sequence in order to
-  ### make a methylation call. The sequence idetifier per definition needs to be the same for a sequence pair used for paired-end mapping.
-  ### Now reading in the sequence files sequence by sequence and see if the current sequences produced an alignment to one (or both) of the
-  ### converted genomes (either the C->T or G->A version)
-
-  ### gzipped version of the infiles
-  if ($sequence_file_1 =~ /\.gz$/ and $sequence_file_2 =~ /\.gz$/){
-    open (IN1,"gunzip -c $sequence_file_1 |") or die "Failed to open gunzip -c pipe to $sequence_file_1 $!\n";
-    open (IN2,"gunzip -c $sequence_file_2 |") or die "Failed to open gunzip -c pipe to $sequence_file_2 $!\n";
-  }
-  else{
-    open (IN1,$sequence_file_1) or die $!;
-    open (IN2,$sequence_file_2) or die $!;
-  }
-
-  warn "\nReading in the sequence files $sequence_file_1 and $sequence_file_2\n";
-  ### Both files are required to have the exact same number of sequences, therefore we can process the sequences jointly one by one
-
-  my $count = 0;
-
-  while (1) {
-    # reading from the first input file
-    my $identifier_1 = <IN1>;
-    my $sequence_1 = <IN1>;
-    # reading from the second input file
-    my $identifier_2 = <IN2>;
-    my $sequence_2 = <IN2>;
-    last unless ($identifier_1 and $sequence_1 and $identifier_2 and $sequence_2);
-
-    $identifier_1 = fix_IDs($identifier_1); # this is to avoid problems with truncated read ID when they contain white spaces
-    $identifier_2 = fix_IDs($identifier_2);
-
-    ++$count;
-
-    if ($skip){
-      next unless ($count > $skip);
-    }
-    if ($upto){
-      last if ($count > $upto);
-    }
-
-    $counting{sequences_count}++;
-    if ($counting{sequences_count}%1000000==0) {
-      warn "Processed $counting{sequences_count} sequence pairs so far\n";
-    }
-    my $orig_identifier_1 = $identifier_1;
-    my $orig_identifier_2 = $identifier_2;
-
-    chomp $sequence_1;
-    chomp $identifier_1;
-    chomp $sequence_2;
-    chomp $identifier_2;
-
-    $identifier_1 =~ s/^>//; # deletes the > at the beginning of FastA headers
-
-    my $return;
-    if ($bowtie2){
-      $return = check_bowtie_results_paired_ends_bowtie2 (uc$sequence_1,uc$sequence_2,$identifier_1);
-    }
-    else{
-      $return = check_bowtie_results_paired_ends (uc$sequence_1,uc$sequence_2,$identifier_1);
-    }
-
-    unless ($return){
-      $return = 0;
-    }
-
-    # print the sequences to ambiguous_1 and _2 if --ambiguous was specified
-    if ($ambiguous and $return == 2){
-      print AMBIG_1 $orig_identifier_1;	
-      print AMBIG_1 "$sequence_1\n";
-      print AMBIG_2 $orig_identifier_2;	
-      print AMBIG_2 "$sequence_2\n";
-    }
-
-    # print the sequences to unmapped_1.out and unmapped_2.out if --un was specified
-    elsif ($unmapped and $return == 1){
-      print UNMAPPED_1 $orig_identifier_1;	
-      print UNMAPPED_1 "$sequence_1\n";
-      print UNMAPPED_2 $orig_identifier_2;	
-      print UNMAPPED_2 "$sequence_2\n";
-    }
-  }
-
-  warn "Processed $counting{sequences_count} sequences in total\n\n";
-
-  close OUT or die $!;
-
-  print_final_analysis_report_paired_ends($C_to_T_infile_1,$G_to_A_infile_1,$C_to_T_infile_2,$G_to_A_infile_2,$pid);
-
-}
-
-sub process_fastQ_files_for_paired_end_methylation_calls{
-  my ($sequence_file_1,$sequence_file_2,$C_to_T_infile_1,$G_to_A_infile_1,$C_to_T_infile_2,$G_to_A_infile_2,$pid) = @_;
-  ### Processing the two Illumina sequence files; we need the actual sequence of both reads to compare them against the genomic sequence in order to
-  ### make a methylation call. The sequence identifier per definition needs to be same for a sequence pair used for paired-end alignments.
-  ### Now reading in the sequence files sequence by sequence and see if the current sequences produced a paired-end alignment to one (or both)
-  ### of the converted genomes (either C->T or G->A version)
-
-  ### gzipped version of the infiles
-  if ($sequence_file_1 =~ /\.gz$/ and $sequence_file_2 =~ /\.gz$/){
-    open (IN1,"gunzip -c $sequence_file_1 |") or die "Failed to open gunzip -c pipe to $sequence_file_1 $!\n";
-    open (IN2,"gunzip -c $sequence_file_2 |") or die "Failed to open gunzip -c pipe to $sequence_file_2 $!\n";
-  }
-  else{
-    open (IN1,$sequence_file_1) or die $!;
-    open (IN2,$sequence_file_2) or die $!;
-  }
-
-  my $count = 0;
-
-  warn "\nReading in the sequence files $sequence_file_1 and $sequence_file_2\n";
-  ### Both files are required to have the exact same number of sequences, therefore we can process the sequences jointly one by one
-  while (1) {
-    # reading from the first input file
-    my $identifier_1 = <IN1>;
-    my $sequence_1 = <IN1>;
-    my $ident_1 = <IN1>;         # not needed
-    my $quality_value_1 = <IN1>; # not needed
-    # reading from the second input file
-    my $identifier_2 = <IN2>;
-    my $sequence_2 = <IN2>;
-    my $ident_2 = <IN2>;         # not needed
-    my $quality_value_2 = <IN2>; # not needed
-    last unless ($identifier_1 and $sequence_1 and $quality_value_1 and $identifier_2 and $sequence_2 and $quality_value_2);
-    $identifier_1 = fix_IDs($identifier_1); # this is to avoid problems with truncated read ID when they contain white spaces
-    $identifier_2 = fix_IDs($identifier_2);
-
-    ++$count;
-
-    if ($skip){
-      next unless ($count > $skip);
-    }
-    if ($upto){
-      last if ($count > $upto);
-    }
-
-    $counting{sequences_count}++;
-    if ($counting{sequences_count}%1000000==0) {
-      warn "Processed $counting{sequences_count} sequence pairs so far\n";
-    }
-
-    my $orig_identifier_1 = $identifier_1;
-    my $orig_identifier_2 = $identifier_2;
-
-    chomp $sequence_1;
-    chomp $identifier_1;
-    chomp $sequence_2;
-    chomp $identifier_2;
-    chomp $quality_value_1;
-    chomp $quality_value_2;
-
-    $identifier_1 =~ s/^\@//;  # deletes the @ at the beginning of the FastQ ID
-
-    my $return;
-    if ($bowtie2){
-      $return = check_bowtie_results_paired_ends_bowtie2 (uc$sequence_1,uc$sequence_2,$identifier_1,$quality_value_1,$quality_value_2);
-    }
-    else{
-      $return = check_bowtie_results_paired_ends (uc$sequence_1,uc$sequence_2,$identifier_1,$quality_value_1,$quality_value_2);
-    }
-
-    unless ($return){
-      $return = 0;
-    }
-
-    # print the sequences to ambiguous_1 and _2 if --ambiguous was specified
-    if ($ambiguous and $return == 2){
-      # seq_1
-      print AMBIG_1 $orig_identifier_1;	
-      print AMBIG_1 "$sequence_1\n";
-      print AMBIG_1 $ident_1;	
-      print AMBIG_1 "$quality_value_1\n";
-	# seq_2
-      print AMBIG_2 $orig_identifier_2;	
-      print AMBIG_2 "$sequence_2\n";
-      print AMBIG_2 $ident_2;	
-      print AMBIG_2 "$quality_value_2\n";
-    }
-
-    # print the sequences to unmapped_1.out and unmapped_2.out if --un was specified
-    elsif ($unmapped and $return == 1){
-      # seq_1
-      print UNMAPPED_1 $orig_identifier_1;	
-      print UNMAPPED_1 "$sequence_1\n";
-      print UNMAPPED_1 $ident_1;	
-      print UNMAPPED_1 "$quality_value_1\n";
-      # seq_2
-      print UNMAPPED_2 $orig_identifier_2;	
-      print UNMAPPED_2 "$sequence_2\n";
-      print UNMAPPED_2 $ident_2;	
-      print UNMAPPED_2 "$quality_value_2\n";
-    }
-  }
-
-  warn "Processed $counting{sequences_count} sequences in total\n\n";
-
-  close OUT or warn "Failed to close filehandle OUT: $!\n\n";
-  if ($ambig_bam){
-      close AMBIBAM or warn "Had trouble closing filehandle AMBIBAM: $!\n\n";
-  }
-
-  print_final_analysis_report_paired_ends($C_to_T_infile_1,$G_to_A_infile_1,$C_to_T_infile_2,$G_to_A_infile_2,$pid);
-
-}
-
-sub check_bowtie_results_single_end{
-  my ($sequence,$identifier,$quality_value) = @_;
-
-  unless ($quality_value){ # FastA sequences get assigned a quality value of Phred 40 throughout
-    $quality_value = 'I'x(length$sequence);
-  }
-
-  my %mismatches = ();
-  ### reading from the bowtie output files to see if this sequence aligned to a bisulfite converted genome
-  foreach my $index (0..$#fhs){
-
-    ### skipping this index if the last alignment has been set to undefined already (i.e. end of bowtie output)
-    next unless ($fhs[$index]->{last_line} and defined $fhs[$index]->{last_seq_id});
-    ### if the sequence we are currently looking at produced an alignment we are doing various things with it
-    if ($fhs[$index]->{last_seq_id} eq $identifier) {
-      ###############################################################
-      ### STEP I Now processing the alignment stored in last_line ###
-      ###############################################################
-      my $valid_alignment_found_1 = decide_whether_single_end_alignment_is_valid($index,$identifier);
-      ### sequences can fail at this point if there was only 1 seq in the wrong orientation, or if there were 2 seqs, both in the wrong orientation
-      ### we only continue to extract useful information about this alignment if 1 was returned
-      if ($valid_alignment_found_1 == 1){
-	### Bowtie outputs which made it this far are in the correct orientation, so we can continue to analyse the alignment itself
-	### need to extract the chromosome number from the bowtie output (which is either XY_cf (complete forward) or XY_cr (complete reverse)
-	my ($id,$strand,$mapped_chromosome,$position,$bowtie_sequence,$mismatch_info) = (split (/\t/,$fhs[$index]->{last_line},-1))[0,1,2,3,4,7];
-
-	unless($mismatch_info){
-	  $mismatch_info = '';
-	}
-
-	chomp $mismatch_info;
-	my $chromosome;
-	if ($mapped_chromosome =~ s/_(CT|GA)_converted$//){
-	  $chromosome = $mapped_chromosome;
-	}
-	else{
-	  die "Chromosome number extraction failed for $mapped_chromosome\n";
-	}
-	### Now extracting the number of mismatches to the converted genome
-	my $number_of_mismatches;
-	if ($mismatch_info eq ''){
-	  $number_of_mismatches = 0;
-	}
-	elsif ($mismatch_info =~ /^\d/){
-	  my @mismatches = split (/,/,$mismatch_info);
-	  $number_of_mismatches = scalar @mismatches;
-	}
-	else{
-	  die "Something weird is going on with the mismatch field:\t>>> $mismatch_info <<<\n";
-	}
-	### creating a composite location variable from $chromosome and $position and storing the alignment information in a temporary hash table
-	my $alignment_location = join (":",$chromosome,$position);
-	### If a sequence aligns to exactly the same location twice the sequence does either not contain any C or G, or all the Cs (or Gs on the reverse
-	### strand) were methylated and therefore protected. It is not needed to overwrite the same positional entry with a second entry for the same
-	### location (the genomic sequence extraction and methylation would not be affected by this, only the thing which would change is the index
-	### number for the found alignment)
-	unless (exists $mismatches{$number_of_mismatches}->{$alignment_location}){
-	  $mismatches{$number_of_mismatches}->{$alignment_location}->{seq_id}=$id;
-	  $mismatches{$number_of_mismatches}->{$alignment_location}->{bowtie_sequence}=$bowtie_sequence;
-	  $mismatches{$number_of_mismatches}->{$alignment_location}->{index}=$index;
-	  $mismatches{$number_of_mismatches}->{$alignment_location}->{chromosome}=$chromosome;
-	  $mismatches{$number_of_mismatches}->{$alignment_location}->{position}=$position;
-	}
-	$number_of_mismatches = undef;
-	##################################################################################################################################################
-	### STEP II Now reading in the next line from the bowtie filehandle. The next alignment can either be a second alignment of the same sequence or a
-	### a new sequence. In either case we will store the next line in @fhs ->{last_line}. In case the alignment is already the next entry, a 0 will
-	### be returned as $valid_alignment_found and it will then be processed in the next round only.
-	##################################################################################################################################################
-	my $newline = $fhs[$index]->{fh}-> getline();
-	if ($newline){
-	  my ($seq_id) = split (/\t/,$newline);
-	  $fhs[$index]->{last_seq_id} = $seq_id;
-	  $fhs[$index]->{last_line} = $newline;
-	}
-	else {
-	  # assigning undef to last_seq_id and last_line and jumping to the next index (end of bowtie output)
-	  $fhs[$index]->{last_seq_id} = undef;
-	  $fhs[$index]->{last_line} = undef;
-	  next;
-	}	
-	my $valid_alignment_found_2 = decide_whether_single_end_alignment_is_valid($index,$identifier);
-	### we only continue to extract useful information about this second alignment if 1 was returned
-	if ($valid_alignment_found_2 == 1){
-	  ### If the second Bowtie output made it this far it is in the correct orientation, so we can continue to analyse the alignment itself
-	  ### need to extract the chromosome number from the bowtie output (which is either XY_cf (complete forward) or XY_cr (complete reverse)
-	  my ($id,$strand,$mapped_chromosome,$position,$bowtie_sequence,$mismatch_info) = (split (/\t/,$fhs[$index]->{last_line},-1))[0,1,2,3,4,7];
-	  unless($mismatch_info){
-	    $mismatch_info = '';
-	  }	
-	  chomp $mismatch_info;
-
-	  my $chromosome;	
-	  if ($mapped_chromosome =~ s/_(CT|GA)_converted$//){
-	    $chromosome = $mapped_chromosome;
-	  }
-	  else{
-	    die "Chromosome number extraction failed for $mapped_chromosome\n";
-	  }
-
-	  ### Now extracting the number of mismatches to the converted genome
-	  my $number_of_mismatches;
-	  if ($mismatch_info eq ''){
-	    $number_of_mismatches = 0;
-	  }
-	  elsif ($mismatch_info =~ /^\d/){
-	    my @mismatches = split (/,/,$mismatch_info);
-	    $number_of_mismatches = scalar @mismatches;
-	  }
-	  else{
-	    die "Something weird is going on with the mismatch field\n";
-	  }
-	  ### creating a composite location variable from $chromosome and $position and storing the alignment information in a temporary hash table
-	  ### extracting the chromosome number from the bowtie output (see above)
-	  my $alignment_location = join (":",$chromosome,$position);
-	  ### In the special case that two differently converted sequences align against differently converted genomes, but to the same position
-	  ### with the same number of mismatches (or perfect matches), the chromosome, position and number of mismatches are the same. In this
-	  ### case we are not writing the same entry out a second time.
-	  unless (exists $mismatches{$number_of_mismatches}->{$alignment_location}){
-	    $mismatches{$number_of_mismatches}->{$alignment_location}->{seq_id}=$id;
-	    $mismatches{$number_of_mismatches}->{$alignment_location}->{bowtie_sequence}=$bowtie_sequence;
-	    $mismatches{$number_of_mismatches}->{$alignment_location}->{index}=$index;
-	    $mismatches{$number_of_mismatches}->{$alignment_location}->{chromosome}=$chromosome;
-	    $mismatches{$number_of_mismatches}->{$alignment_location}->{position}=$position;
-	  }
-	  ####################################################################################################################################
-	  #### STEP III Now reading in one more line which has to be the next alignment to be analysed. Adding it to @fhs ->{last_line}    ###
-	  ####################################################################################################################################
-	  $newline = $fhs[$index]->{fh}-> getline();
-	  if ($newline){
-	    my ($seq_id) = split (/\t/,$newline);
-	    die "The same seq ID occurred more than twice in a row\n" if ($seq_id eq $identifier);
-	    $fhs[$index]->{last_seq_id} = $seq_id;
-	    $fhs[$index]->{last_line} = $newline;
-	    next;
-	  }	
-	  else {
-	    # assigning undef to last_seq_id and last_line and jumping to the next index (end of bowtie output)
-	    $fhs[$index]->{last_seq_id} = undef;
-	    $fhs[$index]->{last_line} = undef;
-	    next;
-	  }
-	  ### still within the 2nd sequence in correct orientation found	
-	}
-	### still withing the 1st sequence in correct orientation found
-      }
-      ### still within the if (last_seq_id eq identifier) condition
-    }
-    ### still within foreach index loop
-  }
-  ### if there was not a single alignment found for a certain sequence we will continue with the next sequence in the sequence file
-  unless(%mismatches){
-    $counting{no_single_alignment_found}++;
-    if ($unmapped){
-      return 1; ### We will print this sequence out as unmapped sequence if --un unmapped.out has been specified
-    }
-    else{
-      return;
-    }
-  }
-  #######################################################################################################################################################
-  #######################################################################################################################################################
-  ### We are now looking if there is a unique best alignment for a certain sequence. This means we are sorting in ascending order and look at the     ###
-  ### sequence with the lowest amount of mismatches. If there is only one single best position we are going to store the alignment information in the ###
-  ### meth_call variables, if there are multiple hits with the same amount of (lowest) mismatches we are discarding the sequence altogether           ###
-  #######################################################################################################################################################
-  #######################################################################################################################################################
-  ### Going to use the variable $sequence_fails as a memory if a sequence could not be aligned uniquely (set to 1 then)
-  my $sequence_fails = 0;
-  ### Declaring an empty hash reference which will store all information we need for the methylation call
-  my $methylation_call_params; # hash reference!
-  ### sorting in ascending order
-  foreach my $mismatch_number (sort {$a<=>$b} keys %mismatches){
-
-    ### if there is only 1 entry in the hash with the lowest number of mismatches we accept it as the best alignment
-    if (scalar keys %{$mismatches{$mismatch_number}} == 1){
-      for my $unique_best_alignment (keys %{$mismatches{$mismatch_number}}){
-	$methylation_call_params->{$identifier}->{bowtie_sequence} = $mismatches{$mismatch_number}->{$unique_best_alignment}->{bowtie_sequence};
-	$methylation_call_params->{$identifier}->{chromosome} = $mismatches{$mismatch_number}->{$unique_best_alignment}->{chromosome};
-	$methylation_call_params->{$identifier}->{position} = $mismatches{$mismatch_number}->{$unique_best_alignment}->{position};
-	$methylation_call_params->{$identifier}->{index} = $mismatches{$mismatch_number}->{$unique_best_alignment}->{index};
-    	$methylation_call_params->{$identifier}->{number_of_mismatches} = $mismatch_number;
-      }
-    }
-    elsif (scalar keys %{$mismatches{$mismatch_number}} == 3){
-      ### If there are 3 sequences with the same number of lowest mismatches we can discriminate 2 cases: (i) all 3 alignments are unique best hits and
-      ### come from different alignments processes (== indices) or (ii) one sequence alignment (== index) will give a unique best alignment, whereas a
-      ### second one will produce 2 (or potentially many) alignments for the same sequence but in a different conversion state or against a different genome
-      ### version (or both). This becomes especially relevant for highly converted sequences in which all Cs have been converted to Ts in the bisulfite
-      ### reaction. E.g.
-      ### CAGTCACGCGCGCGCG will become
-      ### TAGTTATGTGTGTGTG in the CT transformed version, which will ideally still give the correct alignment in the CT->CT alignment condition.
-      ### If the same read will then become G->A transformed as well however, the resulting sequence will look differently and potentially behave
-      ### differently in a GA->GA alignment and this depends on the methylation state of the original sequence!:
-      ### G->A conversion:
-      ### highly methylated: CAATCACACACACACA
-      ### highly converted : TAATTATATATATATA <== this sequence has a reduced complexity (only 2 bases left and not 3), and it is more likely to produce
-      ### an alignment with a low complexity genomic region than the one above. This would normally lead to the entire sequence being kicked out as the
-      ### there will be 3 alignments with the same number of lowest mismatches!! This in turn means that highly methylated and thereby not converted
-      ### sequences are more likely to pass the alignment step, thereby creating a bias for methylated reads compared to their non-methylated counterparts.
-      ### We do not want any bias, whatsover. Therefore if we have 1 sequence producing a unique best alignment and the second and third conditions
-      ### producing alignments only after performing an additional (theoretical) conversion we want to keep the best alignment with the lowest number of
-      ### additional transliterations performed. Thus we want to have a look at the level of complexity of the sequences producing the alignment.
-      ### In the above example the number of transliterations required to transform the actual sequence
-      ### to the C->T version would be TAGTTATGTGTGTGTG -> TAGTTATGTGTGTGTG = 0; (assuming this gives the correct alignment)
-      ### in the G->A case it would be TAGTTATGTGTGTGTG -> TAATTATATATATATA = 6; (assuming this gives multiple wrong alignments)
-      ### if the sequence giving a unique best alignment required a lower number of transliterations than the second best sequence yielding alignments
-      ### while requiring a much higher number of transliterations, we are going to accept the unique best alignment with the lowest number of performed
-      ### transliterations. As a threshold which does scale we will start with the number of tranliterations of the lowest best match x 2 must still be
-      ### smaller than the number of tranliterations of the second best sequence. Everything will be flagged with $sequence_fails = 1 and discarded.
-      my @three_candidate_seqs;
-      foreach my $composite_location (keys (%{$mismatches{$mismatch_number}}) ){
-	my $transliterations_performed;
-	if ($mismatches{$mismatch_number}->{$composite_location}->{index} == 0 or $mismatches{$mismatch_number}->{$composite_location}->{index} == 1){
-	  $transliterations_performed = determine_number_of_transliterations_performed($sequence,'CT');
-	}
-	elsif ($mismatches{$mismatch_number}->{$composite_location}->{index} == 2 or $mismatches{$mismatch_number}->{$composite_location}->{index} == 3){
-	  $transliterations_performed = determine_number_of_transliterations_performed($sequence,'GA');
-	}
-	else{
-	  die "unexpected index number range $!\n";
-	}
-	push @three_candidate_seqs,{
-				    index =>$mismatches{$mismatch_number}->{$composite_location}->{index},
-				    bowtie_sequence => $mismatches{$mismatch_number}->{$composite_location}->{bowtie_sequence},
-				    mismatch_number => $mismatch_number,
-				    chromosome => $mismatches{$mismatch_number}->{$composite_location}->{chromosome},
-				    position => $mismatches{$mismatch_number}->{$composite_location}->{position},
-				    seq_id => $mismatches{$mismatch_number}->{$composite_location}->{seq_id},
-				    transliterations_performed => $transliterations_performed,
-				   };
-      }
-      ### sorting in ascending order for the lowest number of transliterations performed
-      @three_candidate_seqs = sort {$a->{transliterations_performed} <=> $b->{transliterations_performed}} @three_candidate_seqs;
-      my $first_array_element = $three_candidate_seqs[0]->{transliterations_performed};
-      my $second_array_element = $three_candidate_seqs[1]->{transliterations_performed};
-      my $third_array_element = $three_candidate_seqs[2]->{transliterations_performed};
-      # print "$first_array_element\t$second_array_element\t$third_array_element\n";
-      if (($first_array_element*2) < $second_array_element){
-	$counting{low_complexity_alignments_overruled_count}++;
-	### taking the index with the unique best hit and over ruling low complexity alignments with 2 hits
-	$methylation_call_params->{$identifier}->{bowtie_sequence} = $three_candidate_seqs[0]->{bowtie_sequence};
-	$methylation_call_params->{$identifier}->{chromosome} = $three_candidate_seqs[0]->{chromosome};
-	$methylation_call_params->{$identifier}->{position} = $three_candidate_seqs[0]->{position};
-	$methylation_call_params->{$identifier}->{index} = $three_candidate_seqs[0]->{index};
-	$methylation_call_params->{$identifier}->{number_of_mismatches} = $mismatch_number;
-	# print "Overruled low complexity alignments! Using $first_array_element and disregarding $second_array_element and $third_array_element\n";
-      }
-      else{
-	$sequence_fails = 1;
-      }
-    }
-    else{
-      $sequence_fails = 1;
-    }
-    ### after processing the alignment with the lowest number of mismatches we exit
-    last;
-  }
-  ### skipping the sequence completely if there were multiple alignments with the same amount of lowest mismatches found at different positions
-  if ($sequence_fails == 1){
-    $counting{unsuitable_sequence_count}++;
-    if ($ambiguous){
-      return 2; # => exits to next sequence, and prints it out to multiple_alignments.out if --ambiguous has been specified
-    }
-    if ($unmapped){
-      return 1; # => exits to next sequence, and prints it out to unmapped.out if --un has been specified
-    }
-    else{
-      return 0; # => exits to next sequence (default)
-    }
-  }
-
-  ### --DIRECTIONAL
-  ### If the option --directional has been specified the user wants to consider only alignments to the original top strand or the original bottom strand. We will therefore
-  ### discard all alignments to strands complementary to the original strands, as they should not exist in reality due to the library preparation protocol
-  if ($directional){
-    if ( ($methylation_call_params->{$identifier}->{index} == 2) or ($methylation_call_params->{$identifier}->{index} == 3) ){
-      #    warn "Alignment rejected! (index was: $methylation_call_params->{$identifier}->{index})\n";
-      $counting{alignments_rejected_count}++;
-      return 0;
-    }
-  }
-
-  ### If the sequence has not been rejected so far it will have a unique best alignment
-  $counting{unique_best_alignment_count}++;
-  extract_corresponding_genomic_sequence_single_end($identifier,$methylation_call_params);
-
-  ### check test to see if the genomic sequence we extracted has the same length as the observed sequence+2, and only then we perform the methylation call
-  if (length($methylation_call_params->{$identifier}->{unmodified_genomic_sequence}) != length($sequence)+2){
-    warn "Chromosomal sequence could not be extracted for\t$identifier\t$methylation_call_params->{$identifier}->{chromosome}\t$methylation_call_params->{$identifier}->{position}\n";
-    $counting{genomic_sequence_could_not_be_extracted_count}++;
-    return 0;
-  }
-
-  ### otherwise we are set to perform the actual methylation call
-  $methylation_call_params->{$identifier}->{methylation_call} = methylation_call($identifier,$sequence,$methylation_call_params->{$identifier}->{unmodified_genomic_sequence},$methylation_call_params->{$identifier}->{read_conversion});
-
-  print_bisulfite_mapping_result_single_end($identifier,$sequence,$methylation_call_params,$quality_value);
-  return 0; ## otherwise 1 will be returned by default, which would print the sequence to unmapped.out
-}
-
-sub check_bowtie_results_single_end_bowtie2{
-  my ($sequence,$identifier,$quality_value) = @_;
-
-  unless ($quality_value){ # FastA sequences get assigned a quality value of Phred 40 throughout
-    $quality_value = 'I'x(length$sequence);
-  }
-
-  # as of version Bowtie 2 2.0.0 beta7, when input reads are unpaired, Bowtie 2 no longer removes the trailing /1 or /2 from the read name.
-  # $identifier =~ s/\/[1234567890]+$//; # some sequencers don't just have /1 or /2 at the end of read IDs
-  # print "sequence $sequence\nid $identifier\nquality: '$quality_value'\n";
-  
-  my $alignment_ambiguous = 0;
-  my $first_ambig_alignment; # storing the first ambiguous alignment so it can be written out in case '--ambig_bam' was specified
-  my $best_AS_so_far;   ## we need to keep a memory of the best alignment score so far
-  my $amb_same_thread = 0;   ## if a reads primary and secondary alignments have the same alignment score we set this to true.
-
-  my %alignments = ();
-
-  ### reading from the Bowtie 2 output filehandles
-  foreach my $index (0..$#fhs){
-    #  print "Index: $index\n";
-    #   print "$fhs[$index]->{last_line}\n";
-    #   print "$fhs[$index]->{last_seq_id}\n";
-    # sleep (1);
-    ### skipping this index if the last alignment has been set to undefined already (i.e. end of bowtie output)
-    next unless ($fhs[$index]->{last_line} and defined $fhs[$index]->{last_seq_id});
-
-    ### if the sequence we are currently looking at produced an alignment we are doing various things with it
-    # print "last seq id: $fhs[$index]->{last_seq_id} and identifier: $identifier\n";
-
-    if ($fhs[$index]->{last_seq_id} eq $identifier) {
-      #  SAM format specifications for Bowtie 2
-      #  (1) Name of read that aligned
-      #  (2) Sum of all applicable flags. Flags relevant to Bowtie are:
-      #        1 The read is one of a pair
-      #        2 The alignment is one end of a proper paired-end alignment
-      #        4 The read has no reported alignments
-      #        8 The read is one of a pair and has no reported alignments
-      #       16 The alignment is to the reverse reference strand
-      #       32 The other mate in the paired-end alignment is aligned to the reverse reference strand
-      #       64 The read is mate 1 in a pair
-      #      128 The read is mate 2 in a pair
-      #      256 The read has multiple mapping states
-      #  (3) Name of reference sequence where alignment occurs (unmapped reads have a *)
-      #  (4) 1-based offset into the forward reference strand where leftmost character of the alignment occurs (0 for unmapped reads)
-      #  (5) Mapping quality (255 means MAPQ is not available)
-      #  (6) CIGAR string representation of alignment (* if unavailable)
-      #  (7) Name of reference sequence where mate's alignment occurs. Set to = if the mate's reference sequence is the same as this alignment's, or * if there is no mate.
-      #  (8) 1-based offset into the forward reference strand where leftmost character of the mate's alignment occurs. Offset is 0 if there is no mate.
-      #  (9) Inferred fragment size. Size is negative if the mate's alignment occurs upstream of this alignment. Size is 0 if there is no mate.
-      # (10) Read sequence (reverse-complemented if aligned to the reverse strand)
-      # (11) ASCII-encoded read qualities (reverse-complemented if the read aligned to the reverse strand). The encoded quality values are on the Phred quality scale and the encoding is ASCII-offset by 33 (ASCII char !), similarly to a FASTQ file.
-      # (12) Optional fields. Fields are tab-separated. bowtie2 outputs zero or more of these optional fields for each alignment, depending on the type of the alignment:
-      # AS:i:<N> Alignment score. Can be negative. Can be greater than 0 in --local mode (but not in --end-to-end mode). Only present if SAM record is for an aligned read.
-      # XS:i:<N> Alignment score for second-best alignment. Can be negative. Can be greater than 0 in --local mode (but not in --end-to-end mode). Only present if the SAM record is for an aligned read and more than one alignment was found for the read.
-      # YS:i:<N> Alignment score for opposite mate in the paired-end alignment. Only present if the SAM record is for a read that aligned as part of a paired-end alignment.
-      # XN:i:<N> The number of ambiguous bases in the reference covering this alignment. Only present if SAM record is for an aligned read.
-      # XM:i:<N> The number of mismatches in the alignment. Only present if SAM record is for an aligned read.
-      # XO:i:<N> The number of gap opens, for both read and reference gaps, in the alignment. Only present if SAM record is for an aligned read.
-      # XG:i:<N> The number of gap extensions, for both read and reference gaps, in the alignment. Only present if SAM record is for an aligned read.
-      # NM:i:<N> The edit distance; that is, the minimal number of one-nucleotide edits (substitutions, insertions and deletions) needed to transform the read string into the reference string. Only present if SAM record is for an aligned read.
-      # YF:Z:<N> String indicating reason why the read was filtered out. See also: Filtering. Only appears for reads that were filtered out.
-      # MD:Z:<S> A string representation of the mismatched reference bases in the alignment. See SAM format specification for details. Only present if SAM record is for an aligned read.
-
-      my ($id,$flag,$mapped_chromosome,$position,$mapping_quality,$cigar,$bowtie_sequence,$qual) = (split (/\t/,$fhs[$index]->{last_line}))[0,1,2,3,4,5,9,10];
-
-      ### If a sequence has no reported alignments there will be a single output line with a bit-wise flag value of 4. We can store the next alignment and move on to the next Bowtie 2 instance
-      if ($flag == 4){
-	## reading in the next alignment, which must be the next sequence
-	my $newline = $fhs[$index]->{fh}-> getline();
-	if ($newline){
-	  chomp $newline;
-	  my ($seq_id) = split (/\t/,$newline);
-	  $fhs[$index]->{last_seq_id} = $seq_id;
-	  $fhs[$index]->{last_line} = $newline;
-	  if ($seq_id eq $identifier){
-	    die "Sequence with ID $identifier did not produce any alignment, but next seq-ID was also $fhs[$index]->{last_seq_id}!\n";
-	  }
-	  next; # next instance
-	}
-	else{
-	  # assigning undef to last_seq_id and last_line and jumping to the next index (end of Bowtie 2 output)
-	  $fhs[$index]->{last_seq_id} = undef;
-	  $fhs[$index]->{last_line} = undef;
-	  next;
-	}
-      }
-
-      # if there are one or more proper alignments we can extract the chromosome number
-      my $chromosome;
-      if ($mapped_chromosome =~ s/_(CT|GA)_converted$//){
-	$chromosome = $mapped_chromosome;
-      }
-      else{
-	die "Chromosome number extraction failed for $mapped_chromosome\n";
-      }
-
-      ### We will use the optional field to determine the best alignment. Later on we extract the number of mismatches and/or indels from the CIGAR string
-      my ($alignment_score,$second_best,$MD_tag);
-      my @fields = split (/\t/,$fhs[$index]->{last_line});
-
-      foreach (11..$#fields){
-	  if ($fields[$_] =~ /AS:i:(.*)/){
-	      $alignment_score = $1;
-	  }
-	  elsif ($fields[$_] =~ /XS:i:(.*)/){
-	      $second_best = $1;
-	  }
-	  elsif ($fields[$_] =~ /MD:Z:(.*)/){
-	      $MD_tag = $1;
-	  }
-      }
-      
-      my $overwrite = 0; # If we get 2 alignments to the very same position, e.g. to OT with and AS of -156 and to CTOB with and AS of 0 we need the latter to trump the former, else
-      # the read will be assigned to the wrong strand which may result in incorrect methylation calls.
-      # this was brought to our attention by Sylvain Foret (ANU Canberra), 13 April 2016
-      
-      if (!defined $best_AS_so_far){
-	  $best_AS_so_far = $alignment_score;
-	  $overwrite++;
-	  # warn "First alignment score, setting \$best_AS_so_far to $best_AS_so_far\n";
-	  if ($ambig_bam){ # also setting the first_ambig_alignment
-	      $first_ambig_alignment = $fhs[$index]->{last_line};
-	      $first_ambig_alignment =~ s/_(CT|GA)_converted//;
-	      # warn "$first_ambig_alignment\n"; sleep(1);
-	  }	
-      }
-      else{
-	  if ($alignment_score >= $best_AS_so_far){ # AS are generally negative with a maximum of 0;
-	      # 19 07 2016: changed this to >= so that equally good alignments are also added. Ambiguous alignments from different threads will be identified later on
-	      $best_AS_so_far = $alignment_score;
-	      $overwrite++;
-	      # warn "Found better or equal alignment score ($alignment_score), setting \$best_AS_so_far to $best_AS_so_far\n";
-	      
-	      # 22 07 2016: resetting the ambiguous score within same thread only if the current alignment is really better than the previous one
-	      if ($alignment_score > $best_AS_so_far){
-		  # warn "Resetting amb within thread value to 0\n";
-		  $amb_same_thread = 0;
-		  
-		  if ($ambig_bam){ # also setting a new first_ambig_alignment
-		      $first_ambig_alignment = $fhs[$index]->{last_line};
-		      $first_ambig_alignment =~ s/_(CT|GA)_converted//;
-		      # warn "$first_ambig_alignment\n"; sleep(1);
-		  }
-	      }
-	  }
-	  else{
-	      # warn "Current alignment (AS $alignment_score) isn't better than the best so far ($best_AS_so_far). Not changing anything\n";
-	  }
-      }
-      
-      # warn "First  best alignment_score is: '$alignment_score'\n";
-      # warn "MD tag is: '$MD_tag'\n";
-      die "Failed to extract alignment score ($alignment_score) and MD tag ($MD_tag) from line $fhs[$index]->{last_line}!\n" unless (defined $alignment_score and defined $MD_tag);
-      
-      if (defined $second_best){
-	  # warn "second best alignment_score is: '$second_best'\n\n";
-	  
-	  # If the first alignment score is the same as the alignment score of the second best hit we keep a memory of this
-	  if ($alignment_score == $second_best){
-	      
-	      # checking to see if this read produced the best alignment
-	      if ($alignment_score == $best_AS_so_far){  # yes this read is the best one so far, however it is ambiguous
-		  # warn "Read is ambiguous within the same thread, or otherwise as good as the best one so far. Setting \$amb_same_thread to 1 for currently best AS: $best_AS_so_far\n";
-		  $amb_same_thread = 1;
-	      }
-	      else{
-		  # warn "This read has a worse alignments score than the best alignment so far and will be ignored even though it is ambiguous in itself\n";
-	      }
-	      
-	      ### if there is a better alignment later on -> fine. If not, the read will get booted altogether
-	      
-	      ## need to read and discard all additional ambiguous reads until we reach the next sequence
-	      until ($fhs[$index]->{last_seq_id} ne $identifier){
-		  my $newline = $fhs[$index]->{fh}-> getline();
-		  if ($newline){
-		      chomp $newline;
-		      my ($seq_id) = split (/\t/,$newline);
-		      $fhs[$index]->{last_seq_id} = $seq_id;
-		      $fhs[$index]->{last_line} = $newline;
-		  }
-		  else{
-		      # assigning undef to last_seq_id and last_line and jumping to the next index (end of Bowtie 2 output)
-		      $fhs[$index]->{last_seq_id} = undef;
-		      $fhs[$index]->{last_line} = undef;
-		      last; # break free in case we have reached the end of the alignment output
-		  }
-	      }
-	      #  warn "Index: $index\tThe current Seq-ID is $identifier, skipped all ambiguous sequences until the next ID which is: $fhs[$index]->{last_seq_id}\n";
-	  }
-	  else{ # the next best alignment has a lower alignment score than the current read, so we can safely store the current alignment
-	      
-	      my $alignment_location = join (":",$chromosome,$position);
-	      
-	      ### If a sequence aligns to exactly the same location with a perfect match twice the sequence does either not contain any C or G, or all the Cs (or Gs on the reverse
-	      ### strand) were methylated and therefore protected. Alternatively it will align better in one condition than in the other. In any case, it is not needed to overwrite
-	      ### the same positional entry with a second entry for the same location, as the genomic sequence extraction and methylation call would not be affected by this. The only
-	      ### thing which would change is the index number for the found alignment). We will continue to assign these alignments to the first indexes 0 and 1, i.e. OT and OB 
-	      
-	      if ($overwrite){
-		  $alignments{$alignment_location}->{seq_id} = $id; 
-		  $alignments{$alignment_location}->{alignment_score} = $alignment_score;
-		  $alignments{$alignment_location}->{alignment_score_second_best} = $second_best;
-		  $alignments{$alignment_location}->{bowtie_sequence} = $bowtie_sequence;
-		  $alignments{$alignment_location}->{index} = $index;
-		  $alignments{$alignment_location}->{chromosome} = $chromosome;
-		  $alignments{$alignment_location}->{position} = $position;
-		  $alignments{$alignment_location}->{CIGAR} = $cigar;
-		  $alignments{$alignment_location}->{MD_tag} = $MD_tag;
-	      }
-	      
-	      ### now reading and discarding all (inferior) alignments of this sequencing read until we hit the next sequence
-	      until ($fhs[$index]->{last_seq_id} ne $identifier){
-		  my $newline = $fhs[$index]->{fh}-> getline();
-		  if ($newline){
-		      chomp $newline;
-		      my ($seq_id) = split (/\t/,$newline);
-		      $fhs[$index]->{last_seq_id} = $seq_id;
-		      $fhs[$index]->{last_line} = $newline;
-		  }
-		  else{
-		      # assigning undef to last_seq_id and last_line and jumping to the next index (end of Bowtie 2 output)
-		      $fhs[$index]->{last_seq_id} = undef;
-		      $fhs[$index]->{last_line} = undef;
-		      last; # break free in case we have reached the end of the alignment output
-		  }
-	      }
-	      #  warn "Index: $index\tThe current Seq-ID is $identifier, skipped all ambiguous sequences until the next ID which is: $fhs[$index]->{last_seq_id}\n";
-	  }
-      }
-      else{ # there is no second best hit, so we can just store this one and read in the next sequence
-
-	  my $alignment_location = join (":",$chromosome,$position);
-	  # warn "There is no second best hit. Overwrite status: $overwrite\n";
-	  ### If a sequence aligns to exactly the same location with a perfect match twice the sequence does either not contain any C or G, or all the Cs (or Gs on the reverse
-	  ### strand) were methylated and therefore protected. Alternatively it will align better in one condition than in the other. In any case, it is not needed to overwrite
-	  ### the same positional entry with a second entry for the same location, as the genomic sequence extraction and methylation call would not be affected by this. The only
-	  ### thing which would change is the index number for the found alignment). We will continue to assign these alignments to the first indexes 0 and 1, i.e. OT and OB 
-	  
-	  if ($overwrite){
-	      $alignments{$alignment_location}->{seq_id} = $id; 
-	      $alignments{$alignment_location}->{alignment_score} = $alignment_score;
-	      $alignments{$alignment_location}->{alignment_score_second_best} = undef;
-	      $alignments{$alignment_location}->{bowtie_sequence} = $bowtie_sequence;
-	      $alignments{$alignment_location}->{index} = $index;
-	      $alignments{$alignment_location}->{chromosome} = $chromosome;
-	      $alignments{$alignment_location}->{position} = $position;
-	      $alignments{$alignment_location}->{MD_tag} = $MD_tag;
-	      $alignments{$alignment_location}->{CIGAR} = $cigar;
-	  }
-	  
-	  my $newline = $fhs[$index]->{fh}-> getline();
-	  if ($newline){
-	      chomp $newline;
-	      my ($seq_id) = split (/\t/,$newline);
-	      $fhs[$index]->{last_seq_id} = $seq_id;
-	      $fhs[$index]->{last_line} = $newline;
-	      if ($seq_id eq $identifier){
-		  die "Sequence with ID $identifier did not have a second best alignment, but next seq-ID was also $fhs[$index]->{last_seq_id}!\n";
-	      }
-	  }
-	  else{
-	      # assigning undef to last_seq_id and last_line and jumping to the next index (end of Bowtie 2 output)
-	      $fhs[$index]->{last_seq_id} = undef;
-	      $fhs[$index]->{last_line} = undef;
-	  }
-      }
-    }
-  }
-  
-  ### If there were several equally good alignments for the best alignment score we will boot the read
-  if ($amb_same_thread){
-      $alignment_ambiguous = 1;
-      # warn "\$alignment_ambiguous now: $alignment_ambiguous\n";
-  }
-  else{
-      # warn "alignment won't be considered ambiguous. This time....\n";
-  }
-
-  ### if the read produced several ambiguous alignments already now can returning already now. If --ambiguous or --unmapped was specified the read sequence will be printed out.
-  if ($alignment_ambiguous == 1){
-      $counting{unsuitable_sequence_count}++;
-      ### report that the sequence has multiple hits with bitwise flag 256. We can print the sequence to the result file straight away and skip everything else
-      # my $ambiguous_read_output = join("\t",$identifier,'256','*','0','0','*','*','0','0',$sequence,$quality_value);
-      # print "$ambiguous_read_output\n";
-
-      if ($ambig_bam){ 
-	  # warn "Sequence is ambiguous, printing out BAM file:\n";
-	  print AMBIBAM "$first_ambig_alignment\n";
-      }  
-
-      if ($ambiguous){
-	  return 2; # => exits to next sequence, and prints it out to _ambiguous_reads.txt if '--ambiguous' was specified
-      }
-      elsif ($unmapped){
-	  return 1; # => exits to next sequence, and prints it out to _unmapped_reads.txt if '--unmapped' but not '--ambiguous' was specified
-      }
-      else{
-	  return 0;
-      }
-  }
-
-  ### if there was no alignment found for a certain sequence at all we continue with the next sequence in the sequence file
-  unless(%alignments){
-    $counting{no_single_alignment_found}++;
-    # my $unmapped_read_output = join("\t",$identifier,'4','*','0','0','*','*','0','0',$sequence,$quality_value);
-    # print  "$unmapped_read_output\n";
-    if ($unmapped){
-      return 1; # => exits to next sequence, and prints it out to _unmapped_reads.txt if '--unmapped' was specified
-    }
-    else{
-      return 0; # default
-    }
-  }
-
-  #######################################################################################################################################################
-
-  ### If the sequence was not rejected so far we are now looking if there is a unique best alignment among all alignment instances. If there is only one
-  ### single best position we are going to store the alignment information in the $meth_call variable. If there are multiple hits with the same (highest)
-  ### alignment score we are discarding the sequence altogether.
-  ### For end-to-end alignments the maximum alignment score can be 0, each mismatch can receive penalties up to 6, and each gap receives penalties for
-  ### opening (5) and extending (3 per bp) the gap.
-
-  #######################################################################################################################################################
-
-  my $methylation_call_params; # hash reference which will store all information we need for the methylation call
-  my $sequence_fails = 0; # Going to use $sequence_fails as a 'memory' if a sequence could not be aligned uniquely (set to 1 then)
-
-  ### print contents of %alignments for debugging
-  #   if (scalar keys %alignments > 1){
-  #     print "\n******\n";
-  #     foreach my $alignment_location (sort {$a cmp $b} keys %alignments){
-  #       print "Loc:  $alignment_location\n";
-  #       print "ID:   $alignments{$alignment_location}->{seq_id}\n";
-  #       print "AS:   $alignments{$alignment_location}->{alignment_score}\n";
-  #       print "Seq:  $alignments{$alignment_location}->{bowtie_sequence}\n";
-  #       print "Index $alignments{$alignment_location}->{index}\n";
-  #       print "Chr:  $alignments{$alignment_location}->{chromosome}\n";
-  #       print "pos:  $alignments{$alignment_location}->{position}\n";
-  #       print "MD:   $alignments{$alignment_location}->{MD_tag}\n\n";
-  #     }
-  #     print "\n******\n";
-  #   }
-
-  ### if there is only 1 entry in the hash with we accept it as the best alignment
-  if (scalar keys %alignments == 1){
-    for my $unique_best_alignment (keys %alignments){
-      $methylation_call_params->{$identifier}->{bowtie_sequence} = $alignments{$unique_best_alignment}->{bowtie_sequence};
-      $methylation_call_params->{$identifier}->{chromosome}      = $alignments{$unique_best_alignment}->{chromosome};
-      $methylation_call_params->{$identifier}->{position}        = $alignments{$unique_best_alignment}->{position};
-      $methylation_call_params->{$identifier}->{index}           = $alignments{$unique_best_alignment}->{index};
-      $methylation_call_params->{$identifier}->{alignment_score} = $alignments{$unique_best_alignment}->{alignment_score};
-      $methylation_call_params->{$identifier}->{alignment_score_second_best} = $alignments{$unique_best_alignment}->{alignment_score_second_best};
-      $methylation_call_params->{$identifier}->{MD_tag}          = $alignments{$unique_best_alignment}->{MD_tag};
-      $methylation_call_params->{$identifier}->{CIGAR}           = $alignments{$unique_best_alignment}->{CIGAR};
-    }
-  }
-
-  ### otherwise we are going to find out if there is a best match among the multiple alignments, or whether there are 2 or more equally good alignments (in which case
-  ### we boot the sequence altogether
-  elsif (scalar keys %alignments >= 2  and scalar keys %alignments <= 4){
-    my $best_alignment_score;
-    my $best_alignment_location;
-    foreach my $alignment_location (sort {$alignments{$b}->{alignment_score} <=> $alignments{$a}->{alignment_score}} keys %alignments){
-      # print "$alignments{$alignment_location}->{alignment_score}\n";
-      unless (defined $best_alignment_score){
-	$best_alignment_score = $alignments{$alignment_location}->{alignment_score};
-	$best_alignment_location = $alignment_location;
-	# print "setting best alignment score: $best_alignment_score\n";
-      }
-      else{
-	### if the second best alignment has the same alignment score as the first one, the sequence will get booted
-	if ($alignments{$alignment_location}->{alignment_score} == $best_alignment_score){
-	  # warn "Same alignment score, the sequence will get booted!\n";
-	  $sequence_fails = 1;
-	  last; # exiting after the second alignment since we know that the sequence has ambiguous alignments
-	}
-	### else we are going to store the best alignment for further processing
-	else{
-	  $methylation_call_params->{$identifier}->{bowtie_sequence} = $alignments{$best_alignment_location}->{bowtie_sequence};
-	  $methylation_call_params->{$identifier}->{chromosome}      = $alignments{$best_alignment_location}->{chromosome};
-	  $methylation_call_params->{$identifier}->{position}        = $alignments{$best_alignment_location}->{position};
-	  $methylation_call_params->{$identifier}->{index}           = $alignments{$best_alignment_location}->{index};
-	  $methylation_call_params->{$identifier}->{alignment_score} = $alignments{$best_alignment_location}->{alignment_score};
-	  $methylation_call_params->{$identifier}->{MD_tag}          = $alignments{$best_alignment_location}->{MD_tag};
-	  $methylation_call_params->{$identifier}->{CIGAR}           = $alignments{$best_alignment_location}->{CIGAR};
-	  if (defined $alignments{$best_alignment_location}->{alignment_score_second_best} and $alignments{$best_alignment_location}-> {alignment_score_second_best} > $alignments{$alignment_location}->{alignment_score}) {
-	    $methylation_call_params->{$identifier}->{alignment_score_second_best} = $alignments{$best_alignment_location}->{alignment_score_second_best};
-	  }
-	  else {
-	    $methylation_call_params->{$identifier}->{alignment_score_second_best} = $alignments{$alignment_location}->{alignment_score};
-	  }
-	  last; # exiting after processing the second alignment since the sequence produced a unique best alignment
-	}
-      }
-    }
-  }
-  else{
-    die "There are too many potential hits for this sequence (1-4 expected, but found: ",scalar keys %alignments,")\n";;
-  }
-
-  ### skipping the sequence completely if there were multiple alignments with the same best alignment score at different positions
-  if ($sequence_fails == 1){
-    $counting{unsuitable_sequence_count}++;
-
-    ### report that the sequence has multiple hits with bitwise flag 256. We can print the sequence to the result file straight away and skip everything else
-    # my $ambiguous_read_output = join("\t",$identifier,'256','*','0','0','*','*','0','0',$sequence,$quality_value);
-    # print OUT "$ambiguous_read_output\n";
-
-    if ($ambiguous){
-      return 2; # => exits to next sequence, and prints it out (in FastQ format) to _ambiguous_reads.txt if '--ambiguous' was specified
-    }
-    elsif ($unmapped){
-      return 1; # => exits to next sequence, and prints it out (in FastQ format) to _unmapped_reads.txt if '--unmapped' but not '--ambiguous' was specified
-    }
-    else{
-      return 0; # => exits to next sequence (default)
-    }
-  }
-
-  ### --DIRECTIONAL
-  ### If the option --directional has been specified the user wants to consider only alignments to the original top strand or the original bottom strand. We will therefore
-  ### discard all alignments to strands complementary to the original strands, as they should not exist in reality due to the library preparation protocol
-  if ($directional){
-    if ( ($methylation_call_params->{$identifier}->{index} == 2) or ($methylation_call_params->{$identifier}->{index} == 3) ){
-      # warn "Alignment rejected! (index was: $methylation_call_params->{$identifier}->{index})\n";
-      $counting{alignments_rejected_count}++;
-      return 0;
-    }
-  }
-
-  ### If the sequence has not been rejected so far it has a unique best alignment
-  $counting{unique_best_alignment_count}++;
-
-  ### Now we need to extract a genomic sequence that exactly corresponds to the reported alignment. This potentially means that we need to deal with insertions or deletions as well
-  extract_corresponding_genomic_sequence_single_end_bowtie2 ($identifier,$methylation_call_params);
-
-  ### check test to see if the genomic sequence we extracted has the same length as the observed sequence+2, and only then we perform the methylation call
-  if (length($methylation_call_params->{$identifier}->{unmodified_genomic_sequence}) != length($sequence)+2){
-    warn "Chromosomal sequence could not be extracted for\t$identifier\t$methylation_call_params->{$identifier}->{chromosome}\t$methylation_call_params->{$identifier}->{position}\n";
-    $counting{genomic_sequence_could_not_be_extracted_count}++;
-    return 0;
-  }
-
-  # Compute MAPQ value
-  $methylation_call_params->{$identifier}->{mapq} = calc_mapq (length($sequence), undef,
-							       $methylation_call_params->{$identifier}->{alignment_score},
-							       $methylation_call_params->{$identifier}->{alignment_score_second_best});
-
-
-
-  ### otherwise we are set to perform the actual methylation call
-  $methylation_call_params->{$identifier}->{methylation_call} = methylation_call($identifier,$sequence,$methylation_call_params->{$identifier}->{unmodified_genomic_sequence},$methylation_call_params->{$identifier}->{read_conversion});
-  print_bisulfite_mapping_result_single_end_bowtie2 ($identifier,$sequence,$methylation_call_params,$quality_value);
-  return 0; ## if a sequence got this far we do not want to print it to unmapped or ambiguous.out
-}
-
-
-sub determine_number_of_transliterations_performed{
-  my ($sequence,$read_conversion) = @_;
-  my $number_of_transliterations;
-  if ($read_conversion eq 'CT'){
-    $number_of_transliterations = $sequence =~ tr/C/T/;
-  }
-  elsif ($read_conversion eq 'GA'){
-    $number_of_transliterations = $sequence =~ tr/G/A/;
-  }
-  else{
-    die "Read conversion mode of the read was not specified $!\n";
-  }
-  return $number_of_transliterations;
-}
-
-sub decide_whether_single_end_alignment_is_valid{
-  my ($index,$identifier) = @_;
-
-  # extracting from Bowtie 1 format
-  my ($id,$strand) = (split (/\t/,$fhs[$index]->{last_line}))[0,1];
-
-  ### ensuring that the entry is the correct sequence
-  if (($id eq $fhs[$index]->{last_seq_id}) and ($id eq $identifier)){
-    ### checking the orientation of the alignment. We need to discriminate between 8 different conditions, however only 4 of them are theoretically
-    ### sensible alignments
-    my $orientation = ensure_sensical_alignment_orientation_single_end ($index,$strand);
-    ### If the orientation was correct can we move on
-    if ($orientation == 1){
-      return 1; ### 1st possibility for a sequence to pass
-    }
-    ### If the alignment was in the wrong orientation we need to read in a new line
-    elsif($orientation == 0){
-      my $newline = $fhs[$index]->{fh}->getline();
-      if ($newline){
-		($id,$strand) = (split (/\t/,$newline))[0,1];
-		
-	### ensuring that the next entry is still the correct sequence
-	if ($id eq $identifier){
-	  ### checking orientation again
-	  $orientation = ensure_sensical_alignment_orientation_single_end ($index,$strand);
-	  ### If the orientation was correct can we move on
-	  if ($orientation == 1){
-	    $fhs[$index]->{last_seq_id} = $id;
-	    $fhs[$index]->{last_line} = $newline;
-	    return 1; ### 2nd possibility for a sequence to pass
-	  }
-	  ### If the alignment was in the wrong orientation again we need to read in yet another new line and store it in @fhs
-	  elsif ($orientation == 0){
-	    $newline = $fhs[$index]->{fh}->getline();
-	    if ($newline){
-	      my ($seq_id) = split (/\t/,$newline);
-	      ### check if the next line still has the same seq ID (must not happen), and if not overwrite the current seq-ID and bowtie output with
-	      ### the same fields of the just read next entry
-	      die "Same seq ID 3 or more times in a row!(should be 2 max) $!" if ($seq_id eq $identifier);
-	      $fhs[$index]->{last_seq_id} = $seq_id;
-	      $fhs[$index]->{last_line} = $newline;
-	      return 0; # not processing anything this round as the alignment currently stored in last_line was in the wrong orientation
-	    }
-	    else{
-	      # assigning undef to last_seq_id and last_line (end of bowtie output)
-	      $fhs[$index]->{last_seq_id} = undef;
-	      $fhs[$index]->{last_line} = undef;
-	      return 0; # not processing anything as the alignment currently stored in last_line was in the wrong orientation
-	    }
-	  }
-	  else{
-	    die "The orientation of the alignment must be either correct or incorrect\n";
-	  }
-	}
-	### the sequence we just read in is already the next sequence to be analysed -> store it in @fhs
-	else{
-	  $fhs[$index]->{last_seq_id} = $id;
-	  $fhs[$index]->{last_line} = $newline;
-	  return 0; # processing the new alignment result only in the next round
-	}
-      }
-      else {
-	# assigning undef to last_seq_id and last_line (end of bowtie output)
-	$fhs[$index]->{last_seq_id} = undef;
-	$fhs[$index]->{last_line} = undef;
-	return 0; # not processing anything as the alignment currently stored in last_line was in the wrong orientation
-      }
-    }
-    else{
-      die "The orientation of the alignment must be either correct or incorrect\n";
-    }
-  }
-  ### the sequence stored in @fhs as last_line is already the next sequence to be analysed -> analyse next round
-  else{
-    return 0;
-  }
-}
-#########################
-### BOWTIE 1 | PAIRED-END
-#########################
-
-sub check_bowtie_results_paired_ends{
-  my ($sequence_1,$sequence_2,$identifier,$quality_value_1,$quality_value_2) = @_;
-
-  ### quality values are not given for FastA files, so they are initialised with a Phred quality of 40
-  unless ($quality_value_1){
-    $quality_value_1 = 'I'x(length$sequence_1);
-  }
-  unless ($quality_value_2){
-    $quality_value_2 = 'I'x(length$sequence_2);
-  }
-
-  #  warn "$identifier\n$fhs[0]->{last_seq_id}\n$fhs[1]->{last_seq_id}\n$fhs[2]->{last_seq_id}\n$fhs[3]->{last_seq_id}\n\n";
-  #  sleep (1);
-  my %mismatches = ();
-  ### reading from the bowtie output files to see if this sequence pair aligned to a bisulfite converted genome
-
-
-  ### for paired end reads we are reporting alignments to the OT strand first (index 0), then the OB strand (index 3!!), similiar to the single end way.
-  ### alignments to the complementary strands are reported afterwards (CTOT got index 1, and CTOB got index 2).
-  ### This is needed so that alignments which either contain no single C or G or reads which contain only protected Cs are reported to the original strands (OT and OB)
-  ### Before the complementary strands. Remember that it does not make any difference for the methylation calls, but it will matter if alignment to the complementary
-  ### strands are not being reported by specifying --directional
-
-  foreach my $index (0,3,1,2){
-    ### skipping this index if the last alignment has been set to undefined already (i.e. end of bowtie output)
-    next unless ($fhs[$index]->{last_line_1} and $fhs[$index]->{last_line_2} and defined $fhs[$index]->{last_seq_id});
-    ### if the sequence pair we are currently looking at produced an alignment we are doing various things with it
-    if ($fhs[$index]->{last_seq_id} eq $identifier) {
-      # print "$identifier\n$fhs[$index]->{last_seq_id}\n\n";
-
-      ##################################################################################
-      ### STEP I Processing the entry which is stored in last_line_1 and last_line_2 ###
-      ##################################################################################
-      my $valid_alignment_found = decide_whether_paired_end_alignment_is_valid($index,$identifier);
-      ### sequences can fail at this point if there was only 1 alignment in the wrong orientation, or if there were 2 aligments both in the wrong
-      ### orientation. We only continue to extract useful information about this alignment if 1 was returned
-      if ($valid_alignment_found == 1){
-	### Bowtie outputs which made it this far are in the correct orientation, so we can continue to analyse the alignment itself.
-	### we store the useful information in %mismatches
-	my ($id_1,$strand_1,$mapped_chromosome_1,$position_1,$bowtie_sequence_1,$mismatch_info_1) = (split (/\t/,$fhs[$index]->{last_line_1},-1))[0,1,2,3,4,7];
-	my ($id_2,$strand_2,$mapped_chromosome_2,$position_2,$bowtie_sequence_2,$mismatch_info_2) = (split (/\t/,$fhs[$index]->{last_line_2},-1))[0,1,2,3,4,7];
-	chomp $mismatch_info_1;
-	chomp $mismatch_info_2;
-	
-	### need to extract the chromosome number from the bowtie output (which is either XY_CT_converted or XY_GA_converted
-	my ($chromosome_1,$chromosome_2);
-	if ($mapped_chromosome_1 =~ s/_(CT|GA)_converted$//){
-	  $chromosome_1 = $mapped_chromosome_1;
-	}	
-	else{
-	  die "Chromosome number extraction failed for $mapped_chromosome_1\n";
-	}
-	if ($mapped_chromosome_2 =~ s/_(CT|GA)_converted$//){
-	  $chromosome_2 = $mapped_chromosome_2;
-	}
-	else{
-	  die "Chromosome number extraction failed for $mapped_chromosome_2\n";
-	}
-	
-	### Now extracting the number of mismatches to the converted genome
-	my $number_of_mismatches_1;
-	my $number_of_mismatches_2;
-	if ($mismatch_info_1 eq ''){
-	  $number_of_mismatches_1 = 0;
-	}
-	elsif ($mismatch_info_1 =~ /^\d/){
-	  my @mismatches = split (/,/,$mismatch_info_1);
-	  $number_of_mismatches_1 = scalar @mismatches;
-	}
-	else{
-	  die "Something weird is going on with the mismatch field\n";
-	}
-	if ($mismatch_info_2 eq ''){
-	  $number_of_mismatches_2 = 0;
-	}
-	elsif ($mismatch_info_2 =~ /^\d/){
-	  my @mismatches = split (/,/,$mismatch_info_2);
-	  $number_of_mismatches_2 = scalar @mismatches;
-	}
-	else{
-	  die "Something weird is going on with the mismatch field\n";
-	}
-	### To decide whether a sequence pair has a unique best alignment we will look at the lowest sum of mismatches from both alignments
-	my $sum_of_mismatches = $number_of_mismatches_1+$number_of_mismatches_2;
-	### creating a composite location variable from $chromosome and $position and storing the alignment information in a temporary hash table
-	die "Position 1 is higher than position 2" if ($position_1 > $position_2);
-	die "Paired-end alignments need to be on the same chromosome\n" unless ($chromosome_1 eq $chromosome_2);
-	my $alignment_location = join(":",$chromosome_1,$position_1,$position_2);
-	### If a sequence aligns to exactly the same location twice the sequence does either not contain any C or G, or all the Cs (or Gs on the reverse
-	### strand) were methylated and therefore protected. It is not needed to overwrite the same positional entry with a second entry for the same
-	### location (the genomic sequence extraction and methylation would not be affected by this, only the thing which would change is the index
-	### number for the found alignment)
-	unless (exists $mismatches{$sum_of_mismatches}->{$alignment_location}){
-	  $mismatches{$sum_of_mismatches}->{$alignment_location}->{seq_id}=$id_1; # either is fine
-	  $mismatches{$sum_of_mismatches}->{$alignment_location}->{bowtie_sequence_1}=$bowtie_sequence_1;
-	  $mismatches{$sum_of_mismatches}->{$alignment_location}->{bowtie_sequence_2}=$bowtie_sequence_2;
-	  $mismatches{$sum_of_mismatches}->{$alignment_location}->{index}=$index;
-	  $mismatches{$sum_of_mismatches}->{$alignment_location}->{chromosome}=$chromosome_1; # either is fine
-	  $mismatches{$sum_of_mismatches}->{$alignment_location}->{start_seq_1}=$position_1;
-	  $mismatches{$sum_of_mismatches}->{$alignment_location}->{start_seq_2}=$position_2;
-	  $mismatches{$sum_of_mismatches}->{$alignment_location}->{number_of_mismatches_1} = $number_of_mismatches_1;
-	  $mismatches{$sum_of_mismatches}->{$alignment_location}->{number_of_mismatches_2} = $number_of_mismatches_2;
-	}
-	###################################################################################################################################################
-	### STEP II Now reading in the next 2 lines from the bowtie filehandle. If there are 2 next lines in the alignments filehandle it can either    ###
-	### be a second alignment of the same sequence pair or a new sequence pair. In any case we will just add it to last_line_1 and last_line _2.    ###
-	### If it is the alignment of the next sequence pair, 0 will be returned as $valid_alignment_found, so it will not be processed any further in  ###
-	### this round                                                                                                                                  ###
-	###################################################################################################################################################
-	my $newline_1 = $fhs[$index]->{fh}-> getline();
-	my $newline_2 = $fhs[$index]->{fh}-> getline();
-
-	if ($newline_1 and $newline_2){
-	  my ($seq_id_1) = split (/\t/,$newline_1);
-	  my ($seq_id_2) = split (/\t/,$newline_2);
-	
-	  if ($seq_id_1 =~ s/\/1$//){ # removing the read /1 tag
-	    $fhs[$index]->{last_seq_id} = $seq_id_1;
-	  }
-	  elsif ($seq_id_2 =~ s/\/1$//){ # removing the read /1 tag
-	    $fhs[$index]->{last_seq_id} = $seq_id_2;
-	  }
-	  else{
-	    die "Either read 1 or read 2 needs to end on '/1'\n";
-	  }
-	
-	  $fhs[$index]->{last_line_1} = $newline_1;
-	  $fhs[$index]->{last_line_2} = $newline_2;
-	}
-	else {
-	  # assigning undef to last_seq_id and both last_lines and jumping to the next index (end of bowtie output)
-	  $fhs[$index]->{last_seq_id} = undef;
-	  $fhs[$index]->{last_line_1} = undef;
-	  $fhs[$index]->{last_line_2} = undef;
-	  next; # jumping to the next index
-	}
-	### Now processing the entry we just stored in last_line_1 and last_line_2
-	$valid_alignment_found = decide_whether_paired_end_alignment_is_valid($index,$identifier);
-	### only processing the alignment further if 1 was returned. 0 will be returned either if the alignment is already the next sequence pair to
-	### be analysed or if it was a second alignment of the current sequence pair but in the wrong orientation
-	if ($valid_alignment_found == 1){
-	  ### we store the useful information in %mismatches
-	  ($id_1,$strand_1,$mapped_chromosome_1,$position_1,$bowtie_sequence_1,$mismatch_info_1) = (split (/\t/,$fhs[$index]->{last_line_1}))[0,1,2,3,4,7];
-	  ($id_2,$strand_2,$mapped_chromosome_2,$position_2,$bowtie_sequence_2,$mismatch_info_2) = (split (/\t/,$fhs[$index]->{last_line_2}))[0,1,2,3,4,7];
-	  chomp $mismatch_info_1;
-	  chomp $mismatch_info_2;
-	  ### need to extract the chromosome number from the bowtie output (which is either _CT_converted or _GA_converted)
-	  if ($mapped_chromosome_1 =~ s/_(CT|GA)_converted$//){
-	    $chromosome_1 = $mapped_chromosome_1;
-	  }	
-	  else{
-	    die "Chromosome number extraction failed for $mapped_chromosome_1\n";
-	  }
-	  if ($mapped_chromosome_2 =~ s/_(CT|GA)_converted$//){
-	    $chromosome_2 = $mapped_chromosome_2;
-	  }
-	  else{
-	    die "Chromosome number extraction failed for $mapped_chromosome_2\n";
-	  }
-	
-	  $number_of_mismatches_1='';
-	  $number_of_mismatches_2='';
-	  ### Now extracting the number of mismatches to the converted genome
-	  if ($mismatch_info_1 eq ''){
-	    $number_of_mismatches_1 = 0;
-	  }
-	  elsif ($mismatch_info_1 =~ /^\d/){
-	    my @mismatches = split (/,/,$mismatch_info_1);
-	    $number_of_mismatches_1 = scalar @mismatches;
-	  }
-	  else{
-	    die "Something weird is going on with the mismatch field\n";
-	  }
-	  if ($mismatch_info_2 eq ''){
-	    $number_of_mismatches_2 = 0;
-	  }
-	  elsif ($mismatch_info_2 =~ /^\d/){
-	    my @mismatches = split (/,/,$mismatch_info_2);
-	    $number_of_mismatches_2 = scalar @mismatches;
-	  }
-	  else{
-	    die "Something weird is going on with the mismatch field\n";
-	  }
-	  ### To decide whether a sequence pair has a unique best alignment we will look at the lowest sum of mismatches from both alignments
-	  $sum_of_mismatches = $number_of_mismatches_1+$number_of_mismatches_2;
-	  ### creating a composite location variable from $chromosome and $position and storing the alignment information in a temporary hash table
-	  die "position 1 is greater than position 2" if ($position_1 > $position_2);
-	  die "Paired-end alignments need to be on the same chromosome\n" unless ($chromosome_1 eq $chromosome_2);
-	  $alignment_location = join(":",$chromosome_1,$position_1,$position_2);
-	  ### If a sequence aligns to exactly the same location twice the sequence does either not contain any C or G, or all the Cs (or Gs on the reverse
-	  ### strand) were methylated and therefore protected. It is not needed to overwrite the same positional entry with a second entry for the same
-	  ### location (the genomic sequence extraction and methylation would not be affected by this, only the thing which would change is the index
-	  ### number for the found alignment)
-	  unless (exists $mismatches{$sum_of_mismatches}->{$alignment_location}){
-	    $mismatches{$sum_of_mismatches}->{$alignment_location}->{seq_id}=$id_1; # either is fine
-	    $mismatches{$sum_of_mismatches}->{$alignment_location}->{bowtie_sequence_1}=$bowtie_sequence_1;
-	    $mismatches{$sum_of_mismatches}->{$alignment_location}->{bowtie_sequence_2}=$bowtie_sequence_2;
-	    $mismatches{$sum_of_mismatches}->{$alignment_location}->{index}=$index;
-	    $mismatches{$sum_of_mismatches}->{$alignment_location}->{chromosome}=$chromosome_1; # either is fine
-	    $mismatches{$sum_of_mismatches}->{$alignment_location}->{start_seq_1}=$position_1;
-	    $mismatches{$sum_of_mismatches}->{$alignment_location}->{start_seq_2}=$position_2;
-	    $mismatches{$sum_of_mismatches}->{$alignment_location}->{number_of_mismatches_1} = $number_of_mismatches_1;
-	    $mismatches{$sum_of_mismatches}->{$alignment_location}->{number_of_mismatches_2} = $number_of_mismatches_2;
-	  }
-	  ###############################################################################################################################################
-	  ### STEP III Now reading in two more lines. These have to be the next entry and we will just add assign them to last_line_1 and last_line_2 ###
-	  ###############################################################################################################################################
-	  $newline_1 = $fhs[$index]->{fh}-> getline();
-	  $newline_2 = $fhs[$index]->{fh}-> getline();
-
-	  if ($newline_1 and $newline_2){
-	    my ($seq_id_1) = split (/\t/,$newline_1);
-	    my ($seq_id_2) = split (/\t/,$newline_2);
-
-	    if ($seq_id_1 =~ s/\/1$//){ # removing the read /1 tag
-	      $fhs[$index]->{last_seq_id} = $seq_id_1;
-	    }
-	    if ($seq_id_2 =~ s/\/1$//){ # removing the read /1 tag
-	      $fhs[$index]->{last_seq_id} = $seq_id_2;
-	    }
-	    $fhs[$index]->{last_line_1} = $newline_1;
-	    $fhs[$index]->{last_line_2} = $newline_2;
-	  }
-	  else {
-	    # assigning undef to last_seq_id and both last_lines and jumping to the next index (end of bowtie output)
-	    $fhs[$index]->{last_seq_id} = undef;
-	    $fhs[$index]->{last_line_1} = undef;
-	    $fhs[$index]->{last_line_2} = undef;
-	    next; # jumping to the next index
-	  }
-	  ### within the 2nd sequence pair alignment in correct orientation found
-	}
-	### within the 1st sequence pair alignment in correct orientation found
-      }
-      ### still within the (last_seq_id eq identifier) condition
-    }
-    ### still within foreach index loop
-  }
-  ### if there was no single alignment found for a certain sequence we will continue with the next sequence in the sequence file
-  unless(%mismatches){
-    $counting{no_single_alignment_found}++;
-    return 1; ### We will print this sequence out as unmapped sequence if --un unmapped.out has been specified
-  }
-  ### Going to use the variable $sequence_pair_fails as a 'memory' if a sequence could not be aligned uniquely (set to 1 then)
-  my $sequence_pair_fails = 0;
-  ### Declaring an empty hash reference which will store all information we need for the methylation call
-  my $methylation_call_params; # hash reference!
-  ### We are now looking if there is a unique best alignment for a certain sequence. This means we are sorting in ascending order and look at the
-  ### sequence with the lowest amount of mismatches. If there is only one single best position we are going to store the alignment information in the
-  ### meth_call variables, if there are multiple hits with the same amount of (lowest) mismatches we are discarding the sequence altogether
-  foreach my $mismatch_number (sort {$a<=>$b} keys %mismatches){
-    #dev print "Number of mismatches: $mismatch_number\t$identifier\t$sequence_1\t$sequence_2\n";
-    foreach my $entry (keys (%{$mismatches{$mismatch_number}}) ){
-      #dev print "$mismatch_number\t$entry\t$mismatches{$mismatch_number}->{$entry}->{index}\n";
-      # print join("\t",$mismatch_number,$mismatches{$mismatch_number}->{$entry}->{seq_id},$sequence,$mismatches{$mismatch_number}->{$entry}->{bowtie_sequence},$mismatches{$mismatch_number}->{$entry}->{chromosome},$mismatches{$mismatch_number}->{$entry}->{position},$mismatches{$mismatch_number}->{$entry}->{index}),"\n";
-    }
-    if (scalar keys %{$mismatches{$mismatch_number}} == 1){
-      #  print "Unique best alignment for sequence pair $sequence_1\t$sequence_1\n";
-      for my $unique_best_alignment (keys %{$mismatches{$mismatch_number}}){
-	$methylation_call_params->{$identifier}->{seq_id} = $identifier;
- 	$methylation_call_params->{$identifier}->{bowtie_sequence_1} = $mismatches{$mismatch_number}->{$unique_best_alignment}->{bowtie_sequence_1};
-	$methylation_call_params->{$identifier}->{bowtie_sequence_2} = $mismatches{$mismatch_number}->{$unique_best_alignment}->{bowtie_sequence_2};
-       	$methylation_call_params->{$identifier}->{chromosome} = $mismatches{$mismatch_number}->{$unique_best_alignment}->{chromosome};
-      	$methylation_call_params->{$identifier}->{start_seq_1} = $mismatches{$mismatch_number}->{$unique_best_alignment}->{start_seq_1};
-	$methylation_call_params->{$identifier}->{start_seq_2} = $mismatches{$mismatch_number}->{$unique_best_alignment}->{start_seq_2};
-	$methylation_call_params->{$identifier}->{alignment_end} = ($mismatches{$mismatch_number}->{$unique_best_alignment}->{start_seq_2}+length($mismatches{$mismatch_number}->{$unique_best_alignment}->{bowtie_sequence_2}));
-	$methylation_call_params->{$identifier}->{index} = $mismatches{$mismatch_number}->{$unique_best_alignment}->{index};
-     	$methylation_call_params->{$identifier}->{number_of_mismatches_1} = $mismatches{$mismatch_number}->{$unique_best_alignment}->{number_of_mismatches_1};
-	$methylation_call_params->{$identifier}->{number_of_mismatches_2} = $mismatches{$mismatch_number}->{$unique_best_alignment}->{number_of_mismatches_2};
-      }
-    }
-    else{
-      $sequence_pair_fails = 1;
-    }
-    ### after processing the alignment with the lowest number of mismatches we exit
-    last;
-  }
-  ### skipping the sequence completely if there were multiple alignments with the same amount of lowest mismatches found at different positions
-  if ($sequence_pair_fails == 1){
-    $counting{unsuitable_sequence_count}++;
-    if ($ambiguous){
-      return 2; # => exits to next sequence pair, and prints both seqs out to multiple_alignments_1 and -2 if --ambiguous has been specified
-    }
-    if ($unmapped){
-      return 1; # => exits to next sequence pair, and prints both seqs out to unmapped_1 and _2  if --un has been specified
-    }
-    else{
-      return 0; # => exits to next sequence (default)
-    }
-  }
-
-  ### --DIRECTIONAL
-  ### If the option --directional has been specified the user wants to consider only alignments to the original top strand or the original bottom strand. We will therefore
-  ### discard all alignments to strands complementary to the original strands, as they should not exist in reality due to the library preparation protocol
-  if ($directional){
-    if ( ($methylation_call_params->{$identifier}->{index} == 1) or ($methylation_call_params->{$identifier}->{index} == 2) ){
-      #    warn "Alignment rejected! (index was: $methylation_call_params->{$identifier}->{index})\n";
-      $counting{alignments_rejected_count}++;
-      return 0;
-    }
-  }
-
-  ### If the sequence has not been rejected so far it does have a unique best alignment
-  $counting{unique_best_alignment_count}++;
-  extract_corresponding_genomic_sequence_paired_ends($identifier,$methylation_call_params);
-
-  ### check test to see if the genomic sequences we extracted has the same length as the observed sequences +2, and only then we perform the methylation call
-  if (length($methylation_call_params->{$identifier}->{unmodified_genomic_sequence_1}) != length($sequence_1)+2){
-    warn "Chromosomal sequence could not be extracted for\t$identifier\t$methylation_call_params->{$identifier}->{chromosome}\t$methylation_call_params->{$identifier}->{start_seq_1}\n";
-    $counting{genomic_sequence_could_not_be_extracted_count}++;
-    return 0;
-  }
-  if (length($methylation_call_params->{$identifier}->{unmodified_genomic_sequence_2}) != length($sequence_2)+2){
-    warn "Chromosomal sequence could not be extracted for\t$identifier\t$methylation_call_params->{$identifier}->{chromosome}\t$methylation_call_params->{$identifier}->{start_seq_2}\n";
-    $counting{genomic_sequence_could_not_be_extracted_count}++;
-    return 0;
-  }
-
-  ### otherwise we are set to perform the actual methylation call
-  $methylation_call_params->{$identifier}->{methylation_call_1} = methylation_call($identifier,$sequence_1,$methylation_call_params->{$identifier}->{unmodified_genomic_sequence_1},$methylation_call_params->{$identifier}->{read_conversion_1});
-  $methylation_call_params->{$identifier}->{methylation_call_2} = methylation_call($identifier,$sequence_2,$methylation_call_params->{$identifier}->{unmodified_genomic_sequence_2},$methylation_call_params->{$identifier}->{read_conversion_2});
-
-  print_bisulfite_mapping_results_paired_ends($identifier,$sequence_1,$sequence_2,$methylation_call_params,$quality_value_1,$quality_value_2);
-  return 0; ## otherwise 1 will be returned by default, which would print the sequence pair to unmapped_1 and _2
-}
-
-#########################
-### BOWTIE 2 | PAIRED-END
-#########################
-
-sub check_bowtie_results_paired_ends_bowtie2{
-  my ($sequence_1,$sequence_2,$identifier,$quality_value_1,$quality_value_2) = @_;
-
-  ### quality values are not given for FastA files, so they are initialised with a Phred quality of 40
-  unless ($quality_value_1){
-    $quality_value_1 = 'I'x(length$sequence_1);
-  }
-
-  unless ($quality_value_2){
-    $quality_value_2 = 'I'x(length$sequence_2);
-  }
-  # print "$identifier\n$fhs[0]->{last_seq_id}\n$fhs[1]->{last_seq_id}\n$fhs[2]->{last_seq_id}\n$fhs[3]->{last_seq_id}\n\n";
-
-  my %alignments;
-  my $alignment_ambiguous = 0;
-
-  my $first_ambig_alignment_line1; # storing the first ambiguous alignment so it can be written out in case '--ambig_bam' was specified R1
-  my $first_ambig_alignment_line2; # R2
-
-  my $best_AS_so_far;   ## we need to keep a memory of the best alignment score so far
-  my $amb_same_thread = 0;   ## if a read's primary and secondary alignments have the same alignment score we set this to true.
-
-  ### reading from the Bowtie 2 output filehandles
-
-  ### for paired end reads we are reporting alignments to the OT strand first (index 0), then the OB strand (index 3!!), similiar to the single end way.
-  ### alignments to the complementary strands are reported afterwards (CTOT got index 1, and CTOB got index 2).
-  ### This is needed so that alignments which either contain no single C or G or reads which contain only protected Cs are reported to the original strands (OT and OB)
-  ### Before the complementary strands. Remember that it does not make any difference for the methylation calls, but it will matter if alignments to the complementary
-  ### strands are not being reported when '--directional' is specified
-
-  foreach my $index (0,3,1,2){
-    ### skipping this index if the last alignment has been set to undefined already (i.e. end of bowtie output)
-    next unless ($fhs[$index]->{last_line_1} and $fhs[$index]->{last_line_2} and defined $fhs[$index]->{last_seq_id});
-
-    ### if the sequence pair we are currently looking at produced an alignment we are doing various things with it
-    if ($fhs[$index]->{last_seq_id} eq $identifier) {
-	
-	my ($id_1,$flag_1,$mapped_chromosome_1,$position_1,$mapping_quality_1,$cigar_1,$bowtie_sequence_1,$qual_1) = (split (/\t/,$fhs[$index]->{last_line_1}))[0,1,2,3,4,5,9,10];
-	my ($id_2,$flag_2,$mapped_chromosome_2,$position_2,$mapping_quality_2,$cigar_2,$bowtie_sequence_2,$qual_2) = (split (/\t/,$fhs[$index]->{last_line_2}))[0,1,2,3,4,5,9,10];
-      #  print "Index: $index\t$fhs[$index]->{last_line_1}\n";
-      #  print "Index: $index\t$fhs[$index]->{last_line_2}\n";	
-      #  print join ("\t",$id_1,$flag_1,$mapped_chromosome_1,$position_1,$mapping_quality_1,$cigar_1,$bowtie_sequence_1,$qual_1),"\n";
-      #  print join ("\t",$id_2,$flag_2,$mapped_chromosome_2,$position_2,$mapping_quality_2,$cigar_2,$bowtie_sequence_2,$qual_2),"\n";
-      $id_1 =~ s/\/1$//;
-      $id_2 =~ s/\/2$//;
-
-      #  SAM format specifications for Bowtie 2
-      #  (1) Name of read that aligned
-      #  (2) Sum of all applicable flags. Flags relevant to Bowtie are:
-      #        1 The read is one of a pair
-      #        2 The alignment is one end of a proper paired-end alignment
-      #        4 The read has no reported alignments
-      #        8 The read is one of a pair and has no reported alignments
-      #       16 The alignment is to the reverse reference strand
-      #       32 The other mate in the paired-end alignment is aligned to the reverse reference strand
-      #       64 The read is mate 1 in a pair
-      #      128 The read is mate 2 in a pair
-      #      256 The read has multiple mapping states
-      #  (3) Name of reference sequence where alignment occurs (unmapped reads have a *)
-      #  (4) 1-based offset into the forward reference strand where leftmost character of the alignment occurs (0 for unmapped reads)
-      #  (5) Mapping quality (255 means MAPQ is not available)
-      #  (6) CIGAR string representation of alignment (* if unavailable)
-      #  (7) Name of reference sequence where mate's alignment occurs. Set to = if the mate's reference sequence is the same as this alignment's, or * if there is no mate.
-      #  (8) 1-based offset into the forward reference strand where leftmost character of the mate's alignment occurs. Offset is 0 if there is no mate.
-      #  (9) Inferred fragment size. Size is negative if the mate's alignment occurs upstream of this alignment. Size is 0 if there is no mate.
-      # (10) Read sequence (reverse-complemented if aligned to the reverse strand)
-      # (11) ASCII-encoded read qualities (reverse-complemented if the read aligned to the reverse strand). The encoded quality values are on the Phred quality scale and the encoding is ASCII-offset by 33 (ASCII char !), similarly to a FASTQ file.
-      # (12) Optional fields. Fields are tab-separated. bowtie2 outputs zero or more of these optional fields for each alignment, depending on the type of the alignment:
-      # AS:i:<N> Alignment score. Can be negative. Can be greater than 0 in --local mode (but not in --end-to-end mode). Only present if SAM record is for an aligned read.
-      # XS:i:<N> Alignment score for second-best alignment. Can be negative. Can be greater than 0 in --local mode (but not in --end-to-end mode). Only present if the SAM record is for an aligned read and more than one alignment was found for the read.
-      # YS:i:<N> Alignment score for opposite mate in the paired-end alignment. Only present if the SAM record is for a read that aligned as part of a paired-end alignment.
-      # XN:i:<N> The number of ambiguous bases in the reference covering this alignment. Only present if SAM record is for an aligned read.
-      # XM:i:<N> The number of mismatches in the alignment. Only present if SAM record is for an aligned read.
-      # XO:i:<N> The number of gap opens, for both read and reference gaps, in the alignment. Only present if SAM record is for an aligned read.
-      # XG:i:<N> The number of gap extensions, for both read and reference gaps, in the alignment. Only present if SAM record is for an aligned read.
-      # NM:i:<N> The edit distance; that is, the minimal number of one-nucleotide edits (substitutions, insertions and deletions) needed to transform the read string into the reference string. Only present if SAM record is for an aligned read.
-      # YF:Z:<N> String indicating reason why the read was filtered out. See also: Filtering. Only appears for reads that were filtered out.
-      # MD:Z:<S> A string representation of the mismatched reference bases in the alignment. See SAM format specification for details. Only present if SAM record is for an aligned read.
-
-      ### If a sequence has no reported alignments there will be a single output line per sequence with a bit-wise flag value of 77 for read 1 (1+4+8+64), or 141 for read 2 (1+4+8+128).
-      ### We can store the next alignment and move on to the next Bowtie 2 instance
-      if ($flag_1 == 77 and $flag_2 == 141){
-	## reading in the next alignment, which must be the next sequence
-	my $newline_1 = $fhs[$index]->{fh}-> getline();
-	my $newline_2 = $fhs[$index]->{fh}-> getline();
-	
-	if ($newline_1 and $newline_2){
-	  chomp $newline_1;
-	  chomp $newline_2;
-	  my ($seq_id_1) = split (/\t/,$newline_1);
-	  my ($seq_id_2) = split (/\t/,$newline_2);
-	  $seq_id_1 =~ s/\/1$//;
-	  $seq_id_2 =~ s/\/2$//;
-	  $fhs[$index]->{last_seq_id} = $seq_id_1;
-	  $fhs[$index]->{last_line_1} = $newline_1;
-	  $fhs[$index]->{last_line_2} = $newline_2;
-
-	  #  print "current sequence ($identifier) did not map, reading in next sequence\n";
-	  #  print "$index\t$fhs[$index]->{last_seq_id}\n";
-	  #  print "$index\t$fhs[$index]->{last_line_1}\n";
-	  #  print "$index\t$fhs[$index]->{last_line_2}\n";
-	  next; # next instance
-	}
-	else{
-	  # assigning undef to last_seq_id and last_line and jumping to the next index (end of Bowtie 2 output)
-	  $fhs[$index]->{last_seq_id} = undef;
-	  $fhs[$index]->{last_line_1} = undef;
-	  $fhs[$index]->{last_line_2} = undef;
-	  next;
-	}
-      }
-
-	### If there are one or more proper alignments we can extract the chromosome number
-	my ($chromosome_1,$chromosome_2);
-	if ($mapped_chromosome_1 =~ s/_(CT|GA)_converted$//){
-	    $chromosome_1 = $mapped_chromosome_1;
-	}	
-	else{
-	    die "Chromosome number extraction failed for $mapped_chromosome_1\n";
-	}
-	if ($mapped_chromosome_2 =~ s/_(CT|GA)_converted$//){
-	    $chromosome_2 = $mapped_chromosome_2;
-	}
-	else{
-	    die "Chromosome number extraction failed for $mapped_chromosome_2\n";
-	}
-
-	die "Paired-end alignments need to be on the same chromosome\n" unless ($chromosome_1 eq $chromosome_2);
-
-	### We will use the optional fields to determine the best alignments. Later on we extract the number of mismatches and/or indels from the CIGAR string
-	my ($alignment_score_1,$alignment_score_2,$second_best_1,$second_best_2,$MD_tag_1,$MD_tag_2);
-	
-	my @fields_1 = split (/\t/,$fhs[$index]->{last_line_1});
-	my @fields_2 = split (/\t/,$fhs[$index]->{last_line_2});
-	
-	foreach (11..$#fields_1){
-	    if ($fields_1[$_] =~ /AS:i:(.*)/){
-		$alignment_score_1 = $1;
-	    }
-	    elsif ($fields_1[$_] =~ /XS:i:(.*)/){
-		$second_best_1 = $1;
-	    }
-	    elsif ($fields_1[$_] =~ /MD:Z:(.*)/){
-		$MD_tag_1 = $1;
-	    }
-	}
-	
-	foreach (11..$#fields_2){
-	    if ($fields_2[$_] =~ /AS:i:(.*)/){
-		$alignment_score_2 = $1;
-	    }
-	    elsif ($fields_2[$_] =~ /XS:i:(.*)/){
-		$second_best_2 = $1;
-	    }
-	    elsif ($fields_2[$_] =~ /MD:Z:(.*)/){
-		$MD_tag_2 = $1;
-	    }
-	}
-	
-	die "Failed to extract alignment score 1 ($alignment_score_1) and MD tag ($MD_tag_1)!\nlast alignment 1: $fhs[$index]->{last_line_1}\nlast alignment 2: $fhs[$index]->{last_line_2}\n" unless (defined $alignment_score_1 and defined $MD_tag_1);
-	die "Failed to extract alignment score 2 ($alignment_score_2) and MD tag ($MD_tag_2)!\nlast alignment 1: $fhs[$index]->{last_line_1}\nlast alignment 2: $fhs[$index]->{last_line_2}\n" unless (defined $alignment_score_2 and defined $MD_tag_2);
-	
-	# warn "First read 1 alignment score is: '$alignment_score_1'\n";
-	# warn "First read 2 alignment score is: '$alignment_score_2'\n";
-	# warn "MD tag 1 is: '$MD_tag_1'\n";
-	# warn "MD tag 2 is: '$MD_tag_2'\n";
-	
-	### To decide whether a sequence pair has a unique best alignment we will look at the highest sum of alignment scores from both alignments
-	my $sum_of_alignment_scores_1 = $alignment_score_1 + $alignment_score_2 ;
-	# warn "sum of alignment scores: $sum_of_alignment_scores_1\n\n"; sleep(1);
-
-	my $overwrite = 0; # If there are 2 alternative alignments to the same position, e.g. OT with 50 mismatches and CTOB with 0 mismatches, the CTOB one trumps the OT one.
-	# introduced 13 April 2016 as a suggestion by Sylvain Foret, ANU Canberra
-	
-	if (!defined $best_AS_so_far){
-	    $overwrite = 1;
-	    $best_AS_so_far = $sum_of_alignment_scores_1;
-	    # warn "First alignment score, setting \$best_AS_so_far to $best_AS_so_far\n";
-	    if ($ambig_bam){ # also setting the first_ambig_alignment
-		# Read 1
-		$first_ambig_alignment_line1 = $fhs[$index]->{last_line_1};
-		$first_ambig_alignment_line1 =~ s/_(CT|GA)_converted//;
-		# Read 2
-		$first_ambig_alignment_line2 = $fhs[$index]->{last_line_2};
-		$first_ambig_alignment_line2 =~ s/_(CT|GA)_converted//;
-		# warn "$first_ambig_alignment_line1\n$first_ambig_alignment_line2\n\n"; sleep(1);
-	    }
-	}
-	else{
-	    if ($sum_of_alignment_scores_1 >= $best_AS_so_far){ # AS are generally negative with a maximum of 0
-		# 19 07 2016 Changed to >= so that equally good alignments to different positions get added as well. Ambiguous alignments are identified and removed later.
-		$best_AS_so_far = $sum_of_alignment_scores_1;
-		$overwrite = 1;
-		
-		# warn "Found better or equal sum of alignment scores ($sum_of_alignment_scores_1), setting \$best_AS_so_far to $best_AS_so_far\n";
-		# resetting the ambiguous within thread memory (if applicable at all) only if the current alignment is really better than the previous one.
-		# 22 07 2016: ambiguous score within same thread only resets if the current alignment is really better than the previous one
-		if ($sum_of_alignment_scores_1 > $best_AS_so_far){
-		    # warn "Resetting amb within thread value to 0\n";
-		    $amb_same_thread = 0;
-		    
-		    if ($ambig_bam){ # also setting a new first_ambig_alignment
-			# Read 1
-			$first_ambig_alignment_line1 = $fhs[$index]->{last_line_1};
-			$first_ambig_alignment_line1 =~ s/_(CT|GA)_converted//;
-			# Read 2
-			$first_ambig_alignment_line2 = $fhs[$index]->{last_line_2};
-			$first_ambig_alignment_line2 =~ s/_(CT|GA)_converted//;
-			# warn "$first_ambig_alignment_line1\n$first_ambig_alignment_line2\n\n"; sleep(1);
-		    }
-		}
-	    }
-	    else{
-		# warn "current alignment (AS $sum_of_alignment_scores) isn't better than the best so far ($best_AS_so_far). Not changing anything\n";
-	    }
-	}
-
-	if (defined $second_best_1 and defined $second_best_2){
-	    my $sum_of_alignment_scores_second_best = $second_best_1 + $second_best_2;
-	    # warn "Second best alignment_score_1 is: '$second_best_1'\n";
-	    # warn "Second best alignment_score_2 is: '$second_best_2'\n";
-	    # warn "Second best alignment sum of alignment scores is: '$sum_of_alignment_scores_second_best'\n";
-	    
-	    # If the first alignment score for the first read pair is the same as the alignment score of the second best hit we we keep a memory of this
-	    if ($sum_of_alignment_scores_1 == $sum_of_alignment_scores_second_best){
-		
-		# checking to see if this read pair produced the best alignment
-		if ($sum_of_alignment_scores_1 == $best_AS_so_far){  # yes this is the best read pair so far, either within the thread or between threads, however it is ambiguous
-		    # warn "Read pair is ambiguous within the same thread, or otherwise as good as the best one so far. Setting \$amb_same_thread to 1 for currently best AS: $best_AS_so_far\n";
-		    $amb_same_thread = 1;
-		}
-		else{
-		    # warn "This read pair has a worse alignment score than the best alignment so far and will be ignored even though it is ambiguous in itself\n";
-		}
-		
-		### if there is a better alignment later on -> fine. If not, the read will get booted altogether one way or another
-
-		## need to read and discard all additional ambiguous reads until we reach the next sequence
-		until ($fhs[$index]->{last_seq_id} ne $identifier){
-		    my $newline_1 = $fhs[$index]->{fh}-> getline();
-		    my $newline_2 = $fhs[$index]->{fh}-> getline();
-		    if ($newline_1 and $newline_2){
-			chomp $newline_1;
-			chomp $newline_2;
-			my ($seq_id_1) = split (/\t/,$newline_1);
-			my ($seq_id_2) = split (/\t/,$newline_2);
-			$seq_id_1 =~ s/\/1$//;
-			$seq_id_2 =~ s/\/2$//;
-			# print "New Seq IDs:\t$seq_id_1\t$seq_id_2\n";
-
-			$fhs[$index]->{last_seq_id} = $seq_id_1;
-			$fhs[$index]->{last_line_1} = $newline_1;
-			$fhs[$index]->{last_line_2} = $newline_2;
-		    }
-		    else{
-			# assigning undef to last_seq_id and last_line and jumping to the next index (end of Bowtie 2 output)
-			$fhs[$index]->{last_seq_id} = undef;
-			$fhs[$index]->{last_line_1} = undef;
-			$fhs[$index]->{last_line_2} = undef;
-			last; # break free if the end of the alignment output was reached
-		    }
-		}
-		#  if ($fhs[$index]->{last_seq_id}){
-		#    warn "Index: $index\tThis Seq-ID is $identifier, skipped all ambiguous sequences until the next ID which is: $fhs[$index]->{last_seq_id}\n";
-		#  }
-	    }
-	    else{ # the next best alignment has a lower alignment score than the current read, so we can safely store the current alignment
-		
-		my $alignment_location;
-		if ($position_1 <= $position_2){
-		    $alignment_location = join(":",$chromosome_1,$position_1,$position_2);
-		}
-		elsif($position_2 < $position_1){	
-		    $alignment_location = join(":",$chromosome_1,$position_2,$position_1);
-		}
-		
-		### If a sequence aligns to exactly the same location twice the sequence does either not contain any C or G, or all the Cs (or Gs on the reverse
-		### strand) were methylated and therefore protected. Alternatively it will align better in one condition than in the other. In any case, it is not needed to overwrite
-		### the same positional entry with a second entry for the same location, as the genomic sequence extraction and methylation call would not be affected by this. The only
-		### thing which would change is the index number for the found alignment). We will continue to assign these alignments to the first indexes 0 and 3, i.e. OT and OB 
-		
-		if ($overwrite){ # see comment above at "my $overwrite = ..."
-		    #unless (exists $alignments{$alignment_location}){
-		    $alignments{$alignment_location}->{seq_id} = $id_1;
-		    $alignments{$alignment_location}->{alignment_score_1} = $alignment_score_1;
-		    $alignments{$alignment_location}->{alignment_score_2} = $alignment_score_2;
-		    $alignments{$alignment_location}->{sum_of_alignment_scores} = $sum_of_alignment_scores_1;
-		    $alignments{$alignment_location}->{sum_of_alignment_scores_second_best} = $sum_of_alignment_scores_second_best;
-		    $alignments{$alignment_location}->{bowtie_sequence_1} = $bowtie_sequence_1;
-		    $alignments{$alignment_location}->{bowtie_sequence_2} = $bowtie_sequence_2;
-		    $alignments{$alignment_location}->{index} = $index;
-		    $alignments{$alignment_location}->{chromosome} = $chromosome_1; # either is fine
-		    $alignments{$alignment_location}->{position_1} = $position_1;
-		    $alignments{$alignment_location}->{position_2} = $position_2;
-		    $alignments{$alignment_location}->{mismatch_info_1} = $MD_tag_1;
-		    $alignments{$alignment_location}->{mismatch_info_2} = $MD_tag_2;
-		    $alignments{$alignment_location}->{CIGAR_1} = $cigar_1;
-		    $alignments{$alignment_location}->{CIGAR_2} = $cigar_2;
-		    $alignments{$alignment_location}->{flag_1} = $flag_1;
-		    $alignments{$alignment_location}->{flag_2} = $flag_2;
-		    # warn "added best of several alignments to \%alignments hash\n";
-		}
-		
-		### now reading and discarding all (inferior) alignments of this read pair until we hit the next sequence
-		until ($fhs[$index]->{last_seq_id} ne $identifier){
-		    my $newline_1 = $fhs[$index]->{fh}-> getline();
-		    my $newline_2 = $fhs[$index]->{fh}-> getline();
-		    if ($newline_1 and $newline_2){
-			chomp $newline_1;
-			chomp $newline_2;
-			my ($seq_id_1) = split (/\t/,$newline_1);
-			my ($seq_id_2) = split (/\t/,$newline_2);
-			$seq_id_1 =~ s/\/1$//;
-			$seq_id_2 =~ s/\/2$//;
-			# print "New Seq IDs:\t$seq_id_1\t$seq_id_2\n";
-			
-			$fhs[$index]->{last_seq_id} = $seq_id_1;
-			$fhs[$index]->{last_line_1} = $newline_1;
-			$fhs[$index]->{last_line_2} = $newline_2;
-		    }
-		    else{
-			# assigning undef to last_seq_id and last_line_1 and _2 and jumping to the next index (end of Bowtie 2 output)
-			$fhs[$index]->{last_seq_id} = undef;
-			$fhs[$index]->{last_line_1} = undef;
-			$fhs[$index]->{last_line_2} = undef;
-			last; # break free if the end of the alignment output was reached
-		    }
-		}
-		# if($fhs[$index]->{last_seq_id}){
-		#   warn "Index: $index\tThis Seq-ID is $identifier, skipped all other alignments until the next ID was reached which is: $fhs[$index]->{last_seq_id}\n";
-		# }
-	    }	
-	}
-	else{ # there is no second best hit, so we can just store this one and read in the next sequence
-	    
-	    my $alignment_location = join(":",$chromosome_1,$position_1,$position_2);
-	    # print "$alignment_location\n";
-	    ### If a sequence aligns to exactly the same location with a perfect match twice the sequence does either not contain any C or G, or all the Cs (or Gs on the reverse
-	    ### strand) were methylated and therefore protected. Alternatively it will align better in one condition than in the other. In any case, it is not needed to overwrite
-	    ### the same positional entry with a second entry for the same location, as the genomic sequence extraction and methylation call would not be affected by this. The only
-	    ### thing which would change is the index number for the found alignment). We will continue to assign these alignments to the first indexes 0 and 3, i.e. OT and OB
-	    
-	    #unless (exists $alignments{$alignment_location}){ # see comment above at my $overwrite = ...
-	    if ($overwrite){
-		$alignments{$alignment_location}->{seq_id} = $id_1;
-		$alignments{$alignment_location}->{alignment_score_1} = $alignment_score_1;
-		$alignments{$alignment_location}->{alignment_score_2} = $alignment_score_2;
-		$alignments{$alignment_location}->{sum_of_alignment_scores} = $sum_of_alignment_scores_1;
-		$alignments{$alignment_location}->{sum_of_alignment_scores_second_best} = undef;
-		$alignments{$alignment_location}->{bowtie_sequence_1} = $bowtie_sequence_1;
-		$alignments{$alignment_location}->{bowtie_sequence_2} = $bowtie_sequence_2;
-		$alignments{$alignment_location}->{index} = $index;
-		$alignments{$alignment_location}->{chromosome} = $chromosome_1; # either is fine
-		$alignments{$alignment_location}->{position_1} = $position_1;
-		$alignments{$alignment_location}->{position_2} = $position_2;
-		$alignments{$alignment_location}->{mismatch_info_1} = $MD_tag_1;
-		$alignments{$alignment_location}->{mismatch_info_2} = $MD_tag_2;
-		$alignments{$alignment_location}->{CIGAR_1} = $cigar_1;
-		$alignments{$alignment_location}->{CIGAR_2} = $cigar_2;
-		$alignments{$alignment_location}->{flag_1} = $flag_1;
-		$alignments{$alignment_location}->{flag_2} = $flag_2;
-		# warn "added unique alignment to \%alignments hash\n";
-	    }
-	    
-	    # Now reading and storing the next read pair
-	    my $newline_1 = $fhs[$index]->{fh}-> getline();
-	    my $newline_2 = $fhs[$index]->{fh}-> getline();
-	    if ($newline_1 and $newline_2){
-		chomp $newline_1;
-		chomp $newline_2;
-		# print "$newline_1\n";
-		# print "$newline_2\n";
-		my ($seq_id_1) = split (/\t/,$newline_1);
-		my ($seq_id_2) = split (/\t/,$newline_2);
-		$seq_id_1 =~ s/\/1$//;
-		$seq_id_2 =~ s/\/2$//;
-		# print "New Seq IDs:\t$seq_id_1\t$seq_id_2\n";
-		
-		$fhs[$index]->{last_seq_id} = $seq_id_1;
-		$fhs[$index]->{last_line_1} = $newline_1;
-		$fhs[$index]->{last_line_2} = $newline_2;
-		
-		if ($seq_id_1 eq $identifier){
-		    die "Sequence with ID $identifier did not have a second best alignment, but next seq-ID was also $fhs[$index]->{last_seq_id}!\n";
-		}
-	    }
-	    else{
-		# assigning undef to last_seq_id and last_line_1 and _2 and jumping to the next index (end of Bowtie 2 output)
-		$fhs[$index]->{last_seq_id} = undef;
-		$fhs[$index]->{last_line_1} = undef;
-		$fhs[$index]->{last_line_2} = undef;
-	    }
-	}
-    }
-  }
-
-  ### If there were several equally good alignments for the best alignment score we will boot the read
-  if ($amb_same_thread){
-      # warn "\$alignment_ambiguous now: $alignment_ambiguous\n";
-      $alignment_ambiguous = 1;
-      # warn "\$alignment_ambiguous now: $alignment_ambiguous\n";
-  }
-  else{
-      # warn "alignment won't be considered ambiguous. This time....\n";
-  }
-  
-
-  ### if the read produced several ambiguous alignments for a single instance of Bowtie 2 we can return already now. If --ambiguous was specified the read sequence will be printed out in FastQ format
-  if ($alignment_ambiguous == 1){
-      $counting{unsuitable_sequence_count}++;
-      ### report that the sequence pair has multiple hits with bitwise flag 256. We can print the sequence to the result file straight away and skip everything else
-      #  my $ambiguous_read_1 = join("\t",$identifier.'/1','256','*','0','0','*','*','0','0',$sequence_1,$quality_value_1);
-      #  my $ambiguous_read_2 = join("\t",$identifier.'/2','256','*','0','0','*','*','0','0',$sequence_2,$quality_value_2);
-      #  print "$ambiguous_read_1\n";
-      #  print "$ambiguous_read_2\n";
-      
-      if ($ambig_bam){ 
-	  # warn "Sequence is ambiguous, printing out to ambiguous BAM file:\n";
-	  # replacing the first /1\t in the ID of R1 
-	  # warn "Was\n$first_ambig_alignment_line1\n$first_ambig_alignment_line2\n";
-	  $first_ambig_alignment_line1 =~ s/\/1\t/\t/;
- 	  $first_ambig_alignment_line2 =~ s/\/2\t/\t/;
-	  # warn "Is:\n$first_ambig_alignment_line1\n$first_ambig_alignment_line2\n\n";
-	  
-	  print AMBIBAM "$first_ambig_alignment_line1\n$first_ambig_alignment_line2\n";
-   	  # print "$first_ambig_alignment_line1\n$first_ambig_alignment_line2\n";
-      }  
-      
-      if ($ambiguous){
-	  return 2; # => exits to next sequence pair, and prints it out to _ambiguous_reads_1.txt and _ambiguous_reads_2.txt if '--ambiguous' was specified
-      }
-      elsif ($unmapped){
-	  return 1; # => exits to next sequence pair, and prints it out to _unmapped_reads_1.txt and _unmapped_reads_2.txt if '--unmapped' but not '--ambiguous' was specified
-      }
-      else{
-	  return 0;
-      }
-  }
-
-  ### if no alignment was found for a certain sequence at all we continue with the next sequence in the sequence file
-  unless (%alignments){
-    $counting{no_single_alignment_found}++;
-
-    # my $unmapped_read_1 = join("\t",$identifier.'/1','77','*','0','0','*','*','0','0',$sequence_1,$quality_value_1);
-    # my $unmapped_read_2 = join("\t",$identifier.'/2','141','*','0','0','*','*','0','0',$sequence_2,$quality_value_2);
-    # print "$unmapped_read_1\n";
-    # print "$unmapped_read_2\n";
-    if ($unmapped){
-      return 1; # => exits to next sequence pair, and prints it out to _unmapped_reads_1.txt and _unmapped_read_2.txt if '--unmapped' was specified
-    }
-    else{
-      return 0;
-    }
-  }
-
-  #######################################################################################################################################################
-
-  ### If the sequence pair was not rejected so far we are now looking if there is a unique best alignment among all alignment instances. If there is only one
-  ### single best position we are going to store the alignment information in the $meth_call variable. If there are multiple hits with the same (highest)
-  ### alignment score we are discarding the sequence pair altogether.
-  ### For end-to-end alignments the maximum alignment score is 0, each mismatch receives a penalty of 6, and each gap receives penalties for opening (5)
-  ### and extending (3 per bp) the gap.
-
-  #######################################################################################################################################################
-
-  ### Declaring an empty hash reference which will store all information we need for the methylation call
-  my $methylation_call_params; # hash reference
-  my $sequence_pair_fails = 0; # using $sequence_pair_fails as a 'memory' if a sequence could not be aligned uniquely (set to 1 then)
-
-  ### print contents of %alignments for debugging
-  ##  if (scalar keys %alignments >= 1){
-  #     print "\n******\n";
-  #     foreach my $alignment_location (sort {$a cmp $b} keys %alignments){
-  #       print "Loc:  $alignment_location\n";
-  #       print "ID:      $alignments{$alignment_location}->{seq_id}\n";
-  #       print "AS_1:    $alignments{$alignment_location}->{alignment_score_1}\n";
-  #       print "AS_2:    $alignments{$alignment_location}->{alignment_score_2}\n";
-  #       print "Seq_1:   $alignments{$alignment_location}->{bowtie_sequence_1}\n";
-  #       print "Seq_2:   $alignments{$alignment_location}->{bowtie_sequence_2}\n";
-  #       print "Index    $alignments{$alignment_location}->{index}\n";
-  #       print "Chr:     $alignments{$alignment_location}->{chromosome}\n";
-  #       print "Pos_1:   $alignments{$alignment_location}->{position_1}\n";
-  #       print "Pos_2:   $alignments{$alignment_location}->{position_2}\n";
-  #       print "CIGAR_1: $alignments{$alignment_location}->{CIGAR_1}\n";
-  #       print "CIGAR_2: $alignments{$alignment_location}->{CIGAR_2}\n";
-  #       print "MD_1:    $alignments{$alignment_location}->{mismatch_info_1}\n";
-  #       print "MD_2:    $alignments{$alignment_location}->{mismatch_info_2}\n";
-  #       print "Flag 1:  $alignments{$alignment_location}->{flag_1}\n";
-  #       print "Flag 2:  $alignments{$alignment_location}->{flag_2}\n";
-  #    }
-  #    print "\n******\n";
-  #  }
-
-  ### if there is only 1 entry in the %alignments hash we accept it as the best alignment
-  if (scalar keys %alignments == 1){
-    for my $unique_best_alignment (keys %alignments){
-      $methylation_call_params->{$identifier}->{bowtie_sequence_1} = $alignments{$unique_best_alignment}->{bowtie_sequence_1};
-      $methylation_call_params->{$identifier}->{bowtie_sequence_2} = $alignments{$unique_best_alignment}->{bowtie_sequence_2};
-      $methylation_call_params->{$identifier}->{chromosome}        = $alignments{$unique_best_alignment}->{chromosome};
-      $methylation_call_params->{$identifier}->{position_1}        = $alignments{$unique_best_alignment}->{position_1};
-      $methylation_call_params->{$identifier}->{position_2}        = $alignments{$unique_best_alignment}->{position_2};
-      $methylation_call_params->{$identifier}->{index}             = $alignments{$unique_best_alignment}->{index};
-      $methylation_call_params->{$identifier}->{alignment_score_1} = $alignments{$unique_best_alignment}->{alignment_score_1};
-      $methylation_call_params->{$identifier}->{alignment_score_2} = $alignments{$unique_best_alignment}->{alignment_score_2};
-      $methylation_call_params->{$identifier}->{sum_of_alignment_scores} = $alignments{$unique_best_alignment}->{sum_of_alignment_scores};
-      $methylation_call_params->{$identifier}->{sum_of_alignment_scores_second_best} = $alignments{$unique_best_alignment}->{sum_of_alignment_scores_second_best};
-      $methylation_call_params->{$identifier}->{mismatch_info_1}   = $alignments{$unique_best_alignment}->{mismatch_info_1};
-      $methylation_call_params->{$identifier}->{mismatch_info_2}   = $alignments{$unique_best_alignment}->{mismatch_info_2};
-      $methylation_call_params->{$identifier}->{CIGAR_1}           = $alignments{$unique_best_alignment}->{CIGAR_1};
-      $methylation_call_params->{$identifier}->{CIGAR_2}           = $alignments{$unique_best_alignment}->{CIGAR_2};
-      $methylation_call_params->{$identifier}->{flag_1}            = $alignments{$unique_best_alignment}->{flag_1};
-      $methylation_call_params->{$identifier}->{flag_2}            = $alignments{$unique_best_alignment}->{flag_2};
-    }
-  }
-
-  ### otherwise we are going to find out if there is a best match among the multiple alignments, or whether there are 2 or more equally good alignments (in which case
-  ### we boot the sequence pair altogether)
-  elsif (scalar keys %alignments >= 2  and scalar keys %alignments <= 4){
-    my $best_sum_of_alignment_scores;
-    my $best_alignment_location;
-    foreach my $alignment_location (sort {$alignments{$b}->{sum_of_alignment_scores} <=> $alignments{$a}->{sum_of_alignment_scores}} keys %alignments){
-	
-	# warn "$alignments{$alignment_location}->{sum_of_alignment_scores}\n"; sleep(1);
-	
-	unless (defined $best_sum_of_alignment_scores){
-	    $best_sum_of_alignment_scores = $alignments{$alignment_location}->{sum_of_alignment_scores};
-	    $best_alignment_location = $alignment_location;
-	    # print "setting best alignment score to: $best_sum_of_alignment_scores\n";
-	}
-	else{
-	    ### if the second best alignment has the same sum of alignment scores as the first one, the sequence pair will get booted
-	    if ($alignments{$alignment_location}->{sum_of_alignment_scores} == $best_sum_of_alignment_scores){
-		# warn "Same sum of alignment scores for 2 different alignments, the sequence pair will get booted!\n";
-		$sequence_pair_fails = 1;
-		last; # exiting since we know that the sequence has ambiguous alignments
-	    }
-	    ### else we are going to store the best alignment for further processing
-	    else{
-		$methylation_call_params->{$identifier}->{bowtie_sequence_1} = $alignments{$best_alignment_location}->{bowtie_sequence_1};
-		$methylation_call_params->{$identifier}->{bowtie_sequence_2} = $alignments{$best_alignment_location}->{bowtie_sequence_2};
-		$methylation_call_params->{$identifier}->{chromosome}        = $alignments{$best_alignment_location}->{chromosome};
-		$methylation_call_params->{$identifier}->{position_1}        = $alignments{$best_alignment_location}->{position_1};
-		$methylation_call_params->{$identifier}->{position_2}        = $alignments{$best_alignment_location}->{position_2};
-		$methylation_call_params->{$identifier}->{index}             = $alignments{$best_alignment_location}->{index};
-		$methylation_call_params->{$identifier}->{alignment_score_1} = $alignments{$best_alignment_location}->{alignment_score_1};
-		$methylation_call_params->{$identifier}->{alignment_score_2} = $alignments{$best_alignment_location}->{alignment_score_2};
-		$methylation_call_params->{$identifier}->{sum_of_alignment_scores} = $alignments{$best_alignment_location}->{sum_of_alignment_scores};
-		$methylation_call_params->{$identifier}->{mismatch_info_1}   = $alignments{$best_alignment_location}->{mismatch_info_1};
-		$methylation_call_params->{$identifier}->{mismatch_info_2}   = $alignments{$best_alignment_location}->{mismatch_info_2};
-		$methylation_call_params->{$identifier}->{CIGAR_1}           = $alignments{$best_alignment_location}->{CIGAR_1};
-		$methylation_call_params->{$identifier}->{CIGAR_2}           = $alignments{$best_alignment_location}->{CIGAR_2};
-		$methylation_call_params->{$identifier}->{flag_1}            = $alignments{$best_alignment_location}->{flag_1};
-		$methylation_call_params->{$identifier}->{flag_2}            = $alignments{$best_alignment_location}->{flag_2};
-
-		if (defined $alignments{$best_alignment_location}->{sum_of_alignment_scores_second_best} and ( $alignments{$best_alignment_location}->{sum_of_alignment_scores_second_best} > $alignments{$alignment_location}->{sum_of_alignment_scores} )) {
-		    $methylation_call_params->{$identifier}->{sum_of_alignment_scores_second_best} = $alignments{$best_alignment_location}->{sum_of_alignment_scores_second_best};
-		}
-		else {
-		    $methylation_call_params->{$identifier}->{sum_of_alignment_scores_second_best} = $alignments{$alignment_location}->{sum_of_alignment_scores};
-		}
-		
-		last; # exiting since the sequence produced a unique best alignment
-	    }
-	}
-    }
-  }
-  else{
-      die "There are too many potential hits for this sequence pair (1-4 expected, but found: '",scalar keys %alignments,"')\n";;
-  }
-
-  ### skipping the sequence completely if there were multiple alignments with the same best sum of alignment scores at different positions
-  if ($sequence_pair_fails == 1){
-    $counting{unsuitable_sequence_count}++;
-
-    ### report that the sequence has multiple hits with bitwise flag 256. We can print the sequence to the result file straight away and skip everything else
-    # my $ambiguous_read_1 = join("\t",$identifier.'/1','256','*','0','0','*','*','0','0',$sequence_1,$quality_value_1);
-    # my $ambiguous_read_2 = join("\t",$identifier.'/2','256','*','0','0','*','*','0','0',$sequence_2,$quality_value_2);
-    # warn "$ambiguous_read_1\n";
-    # warn "$ambiguous_read_2\n";
-
-    if ($ambiguous){
-      return 2; # => exits to next sequence pair, and prints it out (in FastQ format) to _ambiguous_reads_1.txt and _ambiguous_reads_2.txt if '--ambiguous' was specified
-      }
-    elsif ($unmapped){
-      return 1; # => exits to next sequence pair, and prints it out (in FastQ format) to _unmapped_reads_1.txt and _unmapped_reads_2.txt if '--unmapped' but not '--ambiguous' was specified
-    }
-    else{
-      return 0; # => exits to next sequence pair (default)
-    }
-  }
-
-  ### --DIRECTIONAL
-  ### If the option --directional has been specified the user wants to consider only alignments to the original top strand or the original bottom strand. We will therefore
-  ### discard all alignments to strands complementary to the original strands, as they should not exist in reality due to the library preparation protocol
-  if ($directional){
-    if ( ($methylation_call_params->{$identifier}->{index} == 1) or ($methylation_call_params->{$identifier}->{index} == 2) ){
-      #    warn "Alignment rejected! (index was: $methylation_call_params->{$identifier}->{index})\n";
-      $counting{alignments_rejected_count}++;
-      return 0;
-    }
-  }
-
-  ### If the sequence pair has not been rejected so far it does have a unique best alignment
-  $counting{unique_best_alignment_count}++;
-  extract_corresponding_genomic_sequence_paired_ends_bowtie2($identifier,$methylation_call_params);
-
-  ### check to see if the genomic sequences we extracted has the same length as the observed sequences +2, and only then we perform the methylation call
-  if (length($methylation_call_params->{$identifier}->{unmodified_genomic_sequence_1}) != length($sequence_1)+2){
-    warn "Chromosomal sequence could not be extracted for\t$identifier\t$methylation_call_params->{$identifier}->{chromosome}\t$methylation_call_params->{$identifier}->{position_1}\n";
-    $counting{genomic_sequence_could_not_be_extracted_count}++;
-    return 0;
-  }
-  if (length($methylation_call_params->{$identifier}->{unmodified_genomic_sequence_2}) != length($sequence_2)+2){
-    warn "Chromosomal sequence could not be extracted for\t$identifier\t$methylation_call_params->{$identifier}->{chromosome}\t$methylation_call_params->{$identifier}->{position_2}\n";
-    $counting{genomic_sequence_could_not_be_extracted_count}++;
-    return 0;
-  }
-
-  ### Compute MAPQ value
-  $methylation_call_params->{$identifier}->{mapq} = calc_mapq (length($sequence_1), length($sequence_2),
-                                                                           $methylation_call_params->{$identifier}->{sum_of_alignment_scores},
-                                                                           $methylation_call_params->{$identifier}->{sum_of_alignment_scores_second_best});
-
-
-  ### now we are set to perform the actual methylation call
-  $methylation_call_params->{$identifier}->{methylation_call_1} = methylation_call($identifier,$sequence_1,$methylation_call_params->{$identifier}->{unmodified_genomic_sequence_1},$methylation_call_params->{$identifier}->{read_conversion_1});
-  $methylation_call_params->{$identifier}->{methylation_call_2} = methylation_call($identifier,$sequence_2,$methylation_call_params->{$identifier}->{unmodified_genomic_sequence_2},$methylation_call_params->{$identifier}->{read_conversion_2});
-  # warn "$methylation_call_params->{$identifier}->{read_conversion_2}\n";
-  # warn "  $sequence_2\n";
-  # warn "$methylation_call_params->{$identifier}->{unmodified_genomic_sequence_2}\n";
-  # warn "  $methylation_call_params->{$identifier}->{methylation_call_2}\n";
-
-  print_bisulfite_mapping_results_paired_ends_bowtie2($identifier,$sequence_1,$sequence_2,$methylation_call_params,$quality_value_1,$quality_value_2);
-  return 0; ## otherwise 1 will be returned by default, which would print the sequence pair to unmapped_1 and _2
-}
-
-###
-
-# Compute MAPQ value for a read or read pair as in Bowtie2-2.2.2 (specifically, V2 of the MAPQ calculator: "class BowtieMapq2")
-# assuming end-to-end alignment with the default calculation of the minimum alignment score
-
-sub calc_mapq {
-  my ($read1Len, $read2Len, $AS_best, $AS_secBest) = @_;
-
-  my $scMin = $score_min_intercept + $score_min_slope * $read1Len;
-  ### read2Len is only defined for paired-end reads, so for single-end mode we can just a score min value for read 1
-  if (defined $read2Len){
-    $scMin   += $score_min_intercept + $score_min_slope * $read2Len;
-  }
-
-  my $diff = abs$scMin; # scores can vary by up to this much (since max AS is 0 for end-to-end alignment)
-  my $bestOver = $AS_best - $scMin;
-
-  if (!defined $AS_secBest) {
-    if    ($bestOver >= $diff * 0.8) { return 42; }
-    elsif ($bestOver >= $diff * 0.7) { return 40; }
-    elsif ($bestOver >= $diff * 0.6) { return 24; }
-    elsif ($bestOver >= $diff * 0.5) { return 23; }
-    elsif ($bestOver >= $diff * 0.4) { return  8; }
-    elsif ($bestOver >= $diff * 0.3) { return  3; }
-    else                             { return  0; }
-  } else {
-    my $bestDiff = abs(abs($AS_best) - abs($AS_secBest));
-    if ($bestDiff >= $diff * 0.9) {
-      if ($bestOver == $diff) {
-	return 39;
-      } else {
-	return 33;
-      }
-    } elsif ($bestDiff >= $diff * 0.8) {
-      if ($bestOver == $diff) {
-	return 38;
-      } else {
-	return 27;
-      }
-    } elsif ($bestDiff >= $diff * 0.7) {
-      if ($bestOver == $diff) {
-	return 37;
-      } else {
-	return 26;
-      }
-    } elsif ($bestDiff >= $diff * 0.6) {
-      if ($bestOver == $diff) {
-	return 36;
-      } else {
-	return 22;
-      }
-    } elsif ($bestDiff >= $diff * 0.5) {
-      if ($bestOver == $diff) {
-	return 35;
-      } elsif ($bestOver >= $diff * 0.84) {
-	return 25;
-      } elsif ($bestOver >= $diff * 0.68) {
-	return 16;
-      } else {
-	return 5;
-      }
-    } elsif ($bestDiff >= $diff * 0.4) {
-      if ($bestOver == $diff) {
-	return 34;
-      } elsif ($bestOver >= $diff * 0.84) {
-	return 21;
-      } elsif ($bestOver >= $diff * 0.68) {
-	return 14;
-      } else {
-	return 4;
-      }
-    } elsif ($bestDiff >= $diff * 0.3) {
-      if ($bestOver == $diff) {
-	return 32;
-      } elsif ($bestOver >= $diff * 0.88) {
-	return 18;
-      } elsif ($bestOver >= $diff * 0.67) {
-	return 15;
-      } else {
-	return 3;
-      }
-    } elsif ($bestDiff >= $diff * 0.2) {
-      if ($bestOver == $diff) {
-	return 31;
-      } elsif ($bestOver >= $diff * 0.88) {
-	return 17;
-      } elsif ($bestOver >= $diff * 0.67) {
-	return 11;
-      } else {
-	return 0;
-      }
-    } elsif ($bestDiff >= $diff * 0.1) {
-      if ($bestOver == $diff) {
-	return 30;
-      } elsif ($bestOver >= $diff * 0.88) {
-	return 12;
-      } elsif ($bestOver >= $diff * 0.67) {
-	return 7;
-      } else {
-	return 0;
-      }
-    } elsif ($bestDiff > 0) {
-      if ($bestOver >= $diff * 0.67) {
-	return 6;
-      } else {
-	return 2;
-      }
-    } else {
-      if ($bestOver >= $diff * 0.67) {
-	return 1;
-      } else {
-	return 0;
-      }
-    }
-  }
-}
-
-
-###
-
-sub decide_whether_paired_end_alignment_is_valid{
-  my ($index,$identifier) = @_;
-  my ($id_1,$strand_1,$mapped_chromosome_1,$position_1,$bowtie_sequence_1,$mismatch_info_1) = (split (/\t/,$fhs[$index]->{last_line_1},-1))[0,1,2,3,4,7];
-  my ($id_2,$strand_2,$mapped_chromosome_2,$position_2,$bowtie_sequence_2,$mismatch_info_2) = (split (/\t/,$fhs[$index]->{last_line_2},-1))[0,1,2,3,4,7];
-  chomp $mismatch_info_1;
-  chomp $mismatch_info_2;
-  my $seq_id_1 = $id_1;
-  my $seq_id_2 = $id_2;
-  $seq_id_1 =~ s/\/1$//; # removing the read /1
-  $seq_id_2 =~ s/\/1$//; # removing the read /1
-
-  ### ensuring that the current entry is the correct sequence
-  if ($seq_id_1 eq $identifier or $seq_id_2 eq $identifier){
-    ### checking the orientation of the alignment. We need to discriminate between 8 different conditions, however only 4 of them are theoretically
-    ### sensible alignments
-    my $orientation = ensure_sensical_alignment_orientation_paired_ends ($index,$id_1,$strand_1,$id_2,$strand_2);
-    ### If the orientation was correct can we move on
-    if ($orientation == 1){
-      return 1; ### 1st possibility for A SEQUENCE-PAIR TO PASS
-    }
-    ### If the alignment was in the wrong orientation we need to read in two new lines
-    elsif($orientation == 0){
-      my $newline_1 = $fhs[$index]->{fh}->getline();
-      my $newline_2 = $fhs[$index]->{fh}->getline();
-      if ($newline_1 and $newline_2){
-	### extract detailed information about the alignment again (from $newline_1 and $newline_2 this time)
-	($id_1,$strand_1) = (split (/\t/,$newline_1))[0,1];
-	($id_2,$strand_2) = (split (/\t/,$newline_2))[0,1];
-
-	my $seqid;
-	$seq_id_1 = $id_1;
-	$seq_id_2 = $id_2;
-	# we need to capture the first read (ending on /1)
-	if ($seq_id_1 =~ s/\/1$//){ # removing the read /1 tag
-	  $seqid = $seq_id_1;
-	}
-	elsif ($seq_id_2 =~ s/\/1$//){ # removing the read /1 tag
-	  $seqid = $seq_id_2;
-	}
-	else{
-	  die "One of the two reads needs to end on /1!!";
-	}
-	
-	### ensuring that the next entry is still the correct sequence
-	if ($seq_id_1 eq $identifier or  $seq_id_2 eq $identifier){
-	  ### checking orientation again
-	  $orientation = ensure_sensical_alignment_orientation_paired_ends ($index,$id_1,$strand_1,$id_2,$strand_2);
-	  ### If the orientation was correct can we move on
-	  if ($orientation == 1){
-	    ### Writing the current sequence to last_line_1 and last_line_2
-	    $fhs[$index]->{last_seq_id} = $seqid;
-	    $fhs[$index]->{last_line_1} = $newline_1;
-	    $fhs[$index]->{last_line_2} = $newline_2;
-	    return 1; ### 2nd possibility for a SEQUENCE-PAIR TO PASS
-	  }
-	  ### If the alignment was in the wrong orientation again we need to read in yet another 2 new lines and store them in @fhs (this must be
-	  ### the next entry)
-	  elsif ($orientation == 0){
-	    $newline_1 = $fhs[$index]->{fh}->getline();
-	    $newline_2 = $fhs[$index]->{fh}->getline();
-	    if ($newline_1 and $newline_2){
-	      ($seq_id_1) = split (/\t/,$newline_1);
-	      ($seq_id_2) = split (/\t/,$newline_2);
-	
-	      $seqid = '';
-	      if ($seq_id_1 =~ s/\/1$//){ # removing the read /1 tag
-		$seqid = $seq_id_1;
-	      }
-	      elsif ($seq_id_2 =~ s/\/1$//){ # removing the read /1 tag
-		$seqid = $seq_id_2;
-	      }
-	      else{
-		die "One of the two reads needs to end on /1!!";
-	      }
-	
-	      ### check if the next 2 lines still have the same seq ID (must not happen), and if not overwrite the current seq-ID and bowtie output with
-	      ### the same fields of the just read next entry
-	      die "Same seq ID 3 or more times in a row!(should be 2 max)" if ($seqid eq $identifier);
-	      $fhs[$index]->{last_seq_id} = $seqid;
-	      $fhs[$index]->{last_line_1} = $newline_1;
-	      $fhs[$index]->{last_line_2} = $newline_2;
-	      return 0; # not processing anything this round as the alignment currently stored in last_line_1 and _2 was in the wrong orientation
-	    }
-	    else {
-	      ### assigning undef to last_seq_id and last_line (end of bowtie output)
-	      $fhs[$index]->{last_seq_id} = undef;
-	      $fhs[$index]->{last_line_1} = undef;
-	      $fhs[$index]->{last_line_2} = undef;
-	      return 0; # not processing anything as the alignment currently stored in last_line_1 and _2 was in the wrong orientation
-	    }
-	  }
-	  else{
-	    die "The orientation of the alignment must be either correct or incorrect\n";
-	  }
-	}
-	### the sequence pair we just read in is already the next sequence pair to be analysed -> store it in @fhs
-	else{
-	  $fhs[$index]->{last_seq_id} = $seqid;
-	  $fhs[$index]->{last_line_1} = $newline_1;
-	  $fhs[$index]->{last_line_2} = $newline_2;
-	  return 0; # processing the new alignment result only in the next round
-	}
-      }
-      else {
-	# assigning undef to last_seq_id and both last_lines (end of bowtie output)
-	$fhs[$index]->{last_seq_id} = undef;
-	$fhs[$index]->{last_line_1} = undef;
-	$fhs[$index]->{last_line_2} = undef;
-	return 0; # not processing anything as the alignment currently stored in last_line_1 and _2 was in the wrong orientation
-      }
-    }
-    else{
-      die "The orientation of the alignment must be either correct or incorrect\n";
-    }
-  }
-  ### the sequence pair stored in @fhs as last_line_1 and last_line_2 is already the next sequence pair to be analysed -> analyse next round
-  else{
-    return 0;
-  }
-}
-
-### EXTRACT GENOMIC SEQUENCE | BOWTIE 1 | PAIRED-END
-
-sub extract_corresponding_genomic_sequence_paired_ends {
-  my ($sequence_identifier,$methylation_call_params) = @_;
-  ### A bisulfite sequence pair for 1 location in the genome can theoretically be on any of the 4 possible converted strands. We are also giving the
-  ### sequence a 'memory' of the conversion we are expecting which we will need later for the methylation call
-  my $alignment_read_1;
-  my $alignment_read_2;
-  my $read_conversion_info_1;
-  my $read_conversion_info_2;
-  my $genome_conversion;
-
-  ### Now extracting the same sequence from the mouse genomic sequence, +2 extra bases at oone of the ends so that we can also make a CpG, CHG or CHH methylation call
-  ### if the C happens to be at the first or last position of the actually observed sequence
-  my $non_bisulfite_sequence_1;
-  my $non_bisulfite_sequence_2;
-
-  ### all alignments reported by bowtie have the + alignment first and the - alignment as the second one irrespective of whether read 1 or read 2 was
-  ### the + alignment. We however always read in sequences read 1 then read 2, so if read 2 is the + alignment we need to swap the extracted genomic
-  ### sequences around!
-  ### results from CT converted read 1 plus GA converted read 2 vs. CT converted genome (+/- orientation alignments are reported only)
-  if ($methylation_call_params->{$sequence_identifier}->{index} == 0){
-    ### [Index 0, sequence originated from (converted) forward strand]
-    $counting{CT_GA_CT_count}++;
-    $alignment_read_1 = '+';
-    $alignment_read_2 = '-';
-    $read_conversion_info_1 = 'CT';
-    $read_conversion_info_2 = 'GA';
-    $genome_conversion = 'CT';
-    ### SEQUENCE 1 (this is always the forward hit, in this case it is read 1)
-    ### for hits on the forward strand we need to capture 2 extra bases at the 3' end
-
-    $non_bisulfite_sequence_1 = substr ($chromosomes{$methylation_call_params->{$sequence_identifier}->{chromosome}},$methylation_call_params->{$sequence_identifier}->{start_seq_1},length($methylation_call_params->{$sequence_identifier}->{bowtie_sequence_1})+2); ##CHH change
-
-    ### SEQUENCE 2 (this will always be on the reverse strand, in this case it is read 2)
-    ### As the second conversion is GA we need to capture 1 base 3', so that it is a 5' base after reverse complementation
-    if (length($chromosomes{$methylation_call_params->{$sequence_identifier}->{chromosome}}) > $methylation_call_params->{$sequence_identifier}->{start_seq_2}+length($methylation_call_params->{$sequence_identifier}->{bowtie_sequence_2})+1){ ## CHH change to +1
-
-      $non_bisulfite_sequence_2 = substr ($chromosomes{$methylation_call_params->{$sequence_identifier}->{chromosome}},($methylation_call_params->{$sequence_identifier}->{start_seq_2}),length($methylation_call_params->{$sequence_identifier}->{bowtie_sequence_2})+2);
-      ### the reverse strand sequence needs to be reverse complemented
-      $non_bisulfite_sequence_2 = reverse_complement($non_bisulfite_sequence_2);
-    }
-    else{
-       $non_bisulfite_sequence_2 = '';
-     }
-   }
-
-   ### results from GA converted read 1 plus CT converted read 2 vs. GA converted genome (+/- orientation alignments are reported only)
-  elsif ($methylation_call_params->{$sequence_identifier}->{index} == 1){
-    ### [Index 1, sequence originated from complementary to (converted) reverse strand]
-    $counting{GA_CT_GA_count}++;
-    $alignment_read_1 = '+';
-    $alignment_read_2 = '-';
-    $read_conversion_info_1 = 'GA';
-    $read_conversion_info_2 = 'CT';
-    $genome_conversion = 'GA';
-
-    ### SEQUENCE 1 (this is always the forward hit, in this case it is read 1)
-    ### as we need to make the methylation call for the base 5' of the first base (GA conversion!) we need to capture 2 extra bases at the 5' end
-    if ($methylation_call_params->{$sequence_identifier}->{start_seq_1}-1 > 0){ ## CHH change to -1
-      $non_bisulfite_sequence_1 = substr ($chromosomes{$methylation_call_params->{$sequence_identifier}->{chromosome}},$methylation_call_params->{$sequence_identifier}->{start_seq_1}-2,length($methylation_call_params->{$sequence_identifier}->{bowtie_sequence_1})+2); ### CHH change to -2/+2
-    }
-    else{
-      $non_bisulfite_sequence_1 = '';
-    }
-
-    ### SEQUENCE 2 (this will always be on the reverse strand, in this case it is read 2)
-    ### As we are doing a CT comparison for the reverse strand we are taking 2 bases extra at the 5' end, so it is a 3' base after reverse complementation
-    $non_bisulfite_sequence_2 = substr ($chromosomes{$methylation_call_params->{$sequence_identifier}->{chromosome}},($methylation_call_params->{$sequence_identifier}->{start_seq_2})-2,length($methylation_call_params->{$sequence_identifier}->{bowtie_sequence_2})+2); ### CHH change to -2/+2
-    ### the reverse strand sequence needs to be reverse complemented
-    $non_bisulfite_sequence_2 = reverse_complement($non_bisulfite_sequence_2);
-  }
-
-  ### results from GA converted read 1 plus CT converted read 2 vs. CT converted genome (-/+ orientation alignments are reported only)
-  elsif ($methylation_call_params->{$sequence_identifier}->{index} == 2){
-    ### [Index 2, sequence originated from the complementary to (converted) forward strand]
-    $counting{GA_CT_CT_count}++;
-    $alignment_read_1 = '-';
-    $alignment_read_2 = '+';
-    $read_conversion_info_1 = 'GA';
-    $read_conversion_info_2 = 'CT';
-    $genome_conversion = 'CT';
-
-    ### Here we switch the sequence information round!!  non_bisulfite_sequence_1 will later correspond to the read 1!!!!
-    ### SEQUENCE 1 (this is always the forward hit, in this case it is READ 2), read 1 is in - orientation on the reverse strand
-    ### As read 1 is GA converted we need to capture 2 extra 3' bases which will be 2 extra 5' base after reverse complementation
-    $non_bisulfite_sequence_1 = substr ($chromosomes{$methylation_call_params->{$sequence_identifier}->{chromosome}},($methylation_call_params->{$sequence_identifier}->{start_seq_2}),length($methylation_call_params->{$sequence_identifier}->{bowtie_sequence_2})+2); ### CHH change to +2
-    ### the reverse strand sequence needs to be reverse complemented
-    $non_bisulfite_sequence_1 = reverse_complement($non_bisulfite_sequence_1);
-
-    ### SEQUENCE 2 (this will always be on the reverse strand, in this case it is READ 1)
-    ### non_bisulfite_sequence_2 will later correspond to the read 2!!!!
-    ### Read 2 is CT converted so we need to capture 2 extra 3' bases
-    if (length($chromosomes{$methylation_call_params->{$sequence_identifier}->{chromosome}}) > ($methylation_call_params->{$sequence_identifier}->{start_seq_1})+length($methylation_call_params->{$sequence_identifier}->{bowtie_sequence_1})+1){ ## CHH change to +1
-      $non_bisulfite_sequence_2 = substr ($chromosomes{$methylation_call_params->{$sequence_identifier}->{chromosome}},($methylation_call_params->{$sequence_identifier}->{start_seq_1}),length($methylation_call_params->{$sequence_identifier}->{bowtie_sequence_1})+2); ## CHH changed from +1 to +2
-    }
-    else{
-      $non_bisulfite_sequence_2 = '';
-    }
-  }
-
-  ### results from CT converted read 1 plus GA converted read 2 vs. GA converted genome (-/+ orientation alignments are reported only)
-  elsif ($methylation_call_params->{$sequence_identifier}->{index} == 3){
-    ### [Index 3, sequence originated from the (converted) reverse strand]
-    $counting{CT_GA_GA_count}++;
-    $alignment_read_1 = '-';
-    $alignment_read_2 = '+';
-    $read_conversion_info_1 = 'CT';
-    $read_conversion_info_2 = 'GA';
-    $genome_conversion = 'GA';
-
-    ### Here we switch the sequence information round!!  non_bisulfite_sequence_1 will later correspond to the read 1!!!!
-    ### SEQUENCE 1 (this is always the forward hit, in this case it is READ 2), read 1 is in - orientation on the reverse strand
-    ### As read 1 is CT converted we need to capture 2 extra 5' bases which will be 2 extra 3' base after reverse complementation
-    if ( ($methylation_call_params->{$sequence_identifier}->{start_seq_2}-1) > 0){ ## CHH changed to -1
-      $non_bisulfite_sequence_1 = substr ($chromosomes{$methylation_call_params->{$sequence_identifier}->{chromosome}},($methylation_call_params->{$sequence_identifier}->{start_seq_2})-2,length($methylation_call_params->{$sequence_identifier}->{bowtie_sequence_2})+2); ### CHH changed to -2/+2
-      ### the reverse strand sequence needs to be reverse complemented
-      $non_bisulfite_sequence_1 = reverse_complement($non_bisulfite_sequence_1);
-    }
-    else{
-      $non_bisulfite_sequence_1 = '';
-    }
-
-    ### SEQUENCE 2 (this will always be on the reverse strand, in this case it is READ 1)
-    ### non_bisulfite_sequence_2 will later correspond to the read 2!!!!
-    ### Read 2 is GA converted so we need to capture 2 extra 5' bases
-    $non_bisulfite_sequence_2 = substr ($chromosomes{$methylation_call_params->{$sequence_identifier}->{chromosome}},($methylation_call_params->{$sequence_identifier}->{start_seq_1})-2,length($methylation_call_params->{$sequence_identifier}->{bowtie_sequence_1})+2); ### CHH changed to -2/+2
-  }
-  else{
-    die "Too many bowtie result filehandles\n";
-  }
-  ### the alignment_strand information is needed to determine which strand of the genomic sequence we are comparing the read against,
-  ### the read_conversion information is needed to know whether we are looking for C->T or G->A substitutions
-
-  $methylation_call_params->{$sequence_identifier}->{alignment_read_1} = $alignment_read_1;
-  $methylation_call_params->{$sequence_identifier}->{alignment_read_2} = $alignment_read_2;
-  $methylation_call_params->{$sequence_identifier}->{genome_conversion} = $genome_conversion;
-  $methylation_call_params->{$sequence_identifier}->{read_conversion_1} = $read_conversion_info_1;
-  $methylation_call_params->{$sequence_identifier}->{read_conversion_2} = $read_conversion_info_2;
-  $methylation_call_params->{$sequence_identifier}->{unmodified_genomic_sequence_1} = $non_bisulfite_sequence_1;
-  $methylation_call_params->{$sequence_identifier}->{unmodified_genomic_sequence_2} = $non_bisulfite_sequence_2;
-}
-
-### EXTRACT GENOMIC SEQUENCE BOWTIE 2 | PAIRED-END
-
-sub extract_corresponding_genomic_sequence_paired_ends_bowtie2{
-  my ($sequence_identifier,$methylation_call_params) = @_;
-  ### A bisulfite sequence pair for 1 location in the genome can theoretically be on any of the 4 possible converted strands. We are also giving the
-  ### sequence a 'memory' of the conversion we are expecting which we will need later for the methylation call
-
-  my $cigar_1 = $methylation_call_params->{$sequence_identifier}->{CIGAR_1};
-  my $cigar_2 = $methylation_call_params->{$sequence_identifier}->{CIGAR_2};
-  my $flag_1 =  $methylation_call_params->{$sequence_identifier}->{flag_1};
-  my $flag_2 =  $methylation_call_params->{$sequence_identifier}->{flag_2};
-
-  my $contains_deletion_1 = 0;
-  my $contains_deletion_2 = 0;
-  if ($cigar_1 =~ /D/){
-    $contains_deletion_1 = 1;
-    if ($verbose){ warn "$cigar_1\n$methylation_call_params->{$sequence_identifier}->{mismatch_info_1}\n";}
-  }
-  if ($cigar_2 =~ /D/){
-    $contains_deletion_2 = 1;
-    if ($verbose){ warn "$cigar_2\n$methylation_call_params->{$sequence_identifier}->{mismatch_info_2}\n";}
-  }
-
-  # warn "$cigar_1\t$cigar_2\t$flag_1\t$flag_2\n";
-  ### We are now extracting the corresponding genomic sequence, +2 extra bases at the end (or start) so that we can also make a CpG methylation call and
-  ### in addition make differential calls for Cs in CHG or CHH context if the C happens to be at the last (or first)  position of the actually observed sequence
-
-  ### the alignment_strand information is needed to determine which strand of the genomic sequence we are comparing the read against,
-  ### the read_conversion information is needed to know whether we are looking for C->T or G->A substitutions
-  my $alignment_read_1;
-  my $alignment_read_2;
-  my $read_conversion_info_1;
-  my $read_conversion_info_2;
-  my $genome_conversion;
-
-  ### Now extracting the same sequence from the mouse genomic sequence, +2 extra bases at one of the ends so that we can also make a CpG, CHG or CHH methylation call
-  ### if the C happens to be at the last position of the actually observed sequence
-  my $non_bisulfite_sequence_1 = '';
-  my $non_bisulfite_sequence_2 = '';
-  my $genomic_seq_for_MD_tag_1 = ''; # this sequence contains potential deletions in the genome as well so that we can generate a proper MD tag for the SAM output
-  my $genomic_seq_for_MD_tag_2 = '';
-
-  ### Positions in SAM format are 1 based, so we need to subract 1 when getting substrings
-  my $pos_1 = $methylation_call_params->{$sequence_identifier}->{position_1}-1;
-  my $pos_2 = $methylation_call_params->{$sequence_identifier}->{position_2}-1;
-
-  # parsing CIGAR 1 string
-  my @len_1 = split (/\D+/,$cigar_1); # storing the length per operation
-  my @ops_1 = split (/\d+/,$cigar_1); # storing the operation
-  shift @ops_1; # remove the empty first element
-  die "CIGAR 1 string contained a non-matching number of lengths and operations\n" unless (scalar @len_1 == scalar @ops_1);
-  # parsing CIGAR 2 string
-  my @len_2 = split (/\D+/,$cigar_2); # storing the length per operation
-  my @ops_2 = split (/\d+/,$cigar_2); # storing the operation
-  shift @ops_2; # remove the empty first element
-  die "CIGAR 2 string contained a non-matching number of lengths and operations\n" unless (scalar @len_2 == scalar @ops_2);
-
-  my $indels_1 = 0; # adding these to the hemming distance value (needed for the NM field in the final SAM output
-  my $indels_2 = 0;
-
-  ### Extracting read 1 genomic sequence ###
-
-  # extracting 2 additional bp at the 5' end (read 1)
-  if ( ($methylation_call_params->{$sequence_identifier}->{index} == 1) or ($methylation_call_params->{$sequence_identifier}->{index} == 3) ){
-    # checking if the substring will be valid or if we can't extract the sequence because we are right at the edge of a chromosome
-    unless ( ($pos_1-2) > 0){# exiting with en empty genomic sequence otherwise
-      $methylation_call_params->{$sequence_identifier}->{unmodified_genomic_sequence_1} = $non_bisulfite_sequence_1;
-      $methylation_call_params->{$sequence_identifier}->{genomic_seq_for_MD_tag_1} = $genomic_seq_for_MD_tag_1;
-      return;
-    }
-    $non_bisulfite_sequence_1 .= substr ($chromosomes{$methylation_call_params->{$sequence_identifier}->{chromosome}},$pos_1-2,2);
-  }
-
-  foreach (0..$#len_1){
-    if ($ops_1[$_] eq 'M'){
-      # extracting genomic sequence
-      $non_bisulfite_sequence_1 .= substr ($chromosomes{$methylation_call_params->{$sequence_identifier}->{chromosome}},$pos_1,$len_1[$_]);
-      if ($contains_deletion_1){
-	$genomic_seq_for_MD_tag_1 .= substr ($chromosomes{$methylation_call_params->{$sequence_identifier}->{chromosome}},$pos_1,$len_1[$_]);
-      }
-      #   warn "$non_bisulfite_sequence_1\n";
-      # adjusting position
-      $pos_1 += $len_1[$_];
-    }
-    elsif ($ops_1[$_] eq 'I'){ # insertion in the read sequence
-      # we simply add padding Xs instead of finding genomic sequence. This will not be used to infer methylation calls, and we can later ignore it for the generation of the MD;Z: tag
-      $non_bisulfite_sequence_1 .= 'X' x $len_1[$_];
-      if ($contains_deletion_1){
-	$genomic_seq_for_MD_tag_1 .= 'X' x $len_1[$_];
-      }
-      # warn "$non_bisulfite_sequence_1\n";
-      # position doesn't need adjusting
-
-      ### 03 06 2014: In fact we don't need to add anything to the hemming distance for insertions since we use padding Xs which will fail a base by base comparison in hemming_dist()
-      # indels_1 += $len_1[$_]; # adding to $indels_1 to determine the hemming distance (= single base mismatches, insertions or deletions) for the SAM output
-    }
-    elsif ($ops_1[$_] eq 'D'){ # deletion in the read sequence
-      # we do not add any genomic sequence but only adjust the position
-      # we do however need to add the genomic sequence to $genomic_seq_for_MD-tag so we can create a proper MD tag later
-      if ($contains_deletion_1){
-	$genomic_seq_for_MD_tag_1 .= substr ($chromosomes{$methylation_call_params->{$sequence_identifier}->{chromosome}},$pos_1,$len_1[$_]);
-      }
-      #     warn "Just adjusting the position by: ",$len_1[$_],"bp\n";
-      $pos_1 += $len_1[$_];
-      $indels_1 += $len_1[$_]; # adding to $indels_1 to determine the hemming distance (= single base mismatches, insertions or deletions) for the SAM output
-    }
-    elsif($cigar_1 =~ tr/[NSHPX=]//){ # if these (for standard mapping) illegal characters exist we die
-      die "The CIGAR 1 string contained illegal CIGAR operations in addition to 'M', 'I' and 'D': $cigar_1\n";
-    }
-    else{
-      die "The CIGAR 1 string contained undefined CIGAR operations in addition to 'M', 'I' and 'D': $cigar_1\n";
-    }
-  }
-
-  ### 3' end of read 1
-  if ( ($methylation_call_params->{$sequence_identifier}->{index} == 0) or ($methylation_call_params->{$sequence_identifier}->{index} == 2) ){
-    ## checking if the substring will be valid or if we can't extract the sequence because we are right at the edge of a chromosome
-    unless (length($chromosomes{$methylation_call_params->{$sequence_identifier}->{chromosome}}) >= $pos_1+2){# exiting with en empty genomic sequence otherwise
-      $methylation_call_params->{$sequence_identifier}->{unmodified_genomic_sequence_1} = $non_bisulfite_sequence_1;
-      return;
-    }
-
-    $non_bisulfite_sequence_1 .= substr ($chromosomes{$methylation_call_params->{$sequence_identifier}->{chromosome}},$pos_1,2);
-  }
-
-
-  ### Extracting read 2 genomic sequence ###
-
-  ### 5' end of read 2
-  if ( ($methylation_call_params->{$sequence_identifier}->{index} == 1) or ($methylation_call_params->{$sequence_identifier}->{index} == 3) ){
-    ## checking if the substring will be valid or if we can't extract the sequence because we are right at the edge of a chromosome
-    unless ( ($pos_2-2) >= 0){# exiting with en empty genomic sequence otherwise
-      $methylation_call_params->{$sequence_identifier}->{unmodified_genomic_sequence_1} = $non_bisulfite_sequence_1;
-      $methylation_call_params->{$sequence_identifier}->{unmodified_genomic_sequence_2} = $non_bisulfite_sequence_2;
-      $methylation_call_params->{$sequence_identifier}->{genomic_seq_for_MD_tag_2} = $genomic_seq_for_MD_tag_2;
-      return;
-    }
-    $non_bisulfite_sequence_2 .= substr ($chromosomes{$methylation_call_params->{$sequence_identifier}->{chromosome}},$pos_2-2,2);
-  }
-
-  foreach (0..$#len_2){
-    if ($ops_2[$_] eq 'M'){
-      # extracting genomic sequence
-      $non_bisulfite_sequence_2 .= substr ($chromosomes{$methylation_call_params->{$sequence_identifier}->{chromosome}},$pos_2,$len_2[$_]);
-      if ($contains_deletion_2){
-	$genomic_seq_for_MD_tag_2 .= substr ($chromosomes{$methylation_call_params->{$sequence_identifier}->{chromosome}},$pos_2,$len_2[$_]);
-      }
-      # warn "$non_bisulfite_sequence_2\n";
-      # adjusting position
-      $pos_2 += $len_2[$_];
-    }
-    elsif ($ops_2[$_] eq 'I'){ # insertion in the read sequence
-      # we simply add padding Xs instead of finding genomic sequence. This will not be used to infer methylation calls and we can ignore this later during the generation of the MD:Z: tag
-      $non_bisulfite_sequence_2 .= 'X' x $len_2[$_];
-      if ($contains_deletion_2){
-	$genomic_seq_for_MD_tag_2 .= 'X' x $len_2[$_];
-      }
-      # warn "$non_bisulfite_sequence_2\n";
-      # position doesn't need adjusting
-
-      ### 03 06 2014: In fact we don't need to add anything to the hemming distance for insertions since we use padding Xs which will fail a base by base comparison in hemming_dist()
-      # $indels_2 += $len_2[$_]; # adding to $indels_1 to determine the hemming distance (= single base mismatches, insertions or deletions) for the SAM output
-    }
-    elsif ($ops_2[$_] eq 'D'){ # deletion in the read sequence
-      # we do not add any genomic sequence but only adjust the position
-      # we do however need to add the genomic sequence to $genomic_seq_for_MD-tag so we can create a proper MD tag later
-      if ($contains_deletion_2){
-	$genomic_seq_for_MD_tag_2 .= substr ($chromosomes{$methylation_call_params->{$sequence_identifier}->{chromosome}},$pos_2,$len_2[$_]);
-      }
-      # warn "Just adjusting the position by: ",$len_2[$_],"bp\n";
-      $pos_2 += $len_2[$_];
-      $indels_2 += $len_2[$_]; # adding to $indels_1 to determine the hemming distance (= single base mismatches, insertions or deletions) for the SAM output
-    }
-    elsif($cigar_2 =~ tr/[NSHPX=]//){ # if these (for standard mapping) illegal characters exist we die
-      die "The CIGAR 2 string contained illegal CIGAR operations in addition to 'M', 'I' and 'D': $cigar_2\n";
-    }
-    else{
-      die "The CIGAR 2 string contained undefined CIGAR operations in addition to 'M', 'I' and 'D': $cigar_2\n";
-    }
-  }
-
-  ### 3' end of read 2
-  if ( ($methylation_call_params->{$sequence_identifier}->{index} == 0) or ($methylation_call_params->{$sequence_identifier}->{index} == 2) ){
-    ## checking if the substring will be valid or if we can't extract the sequence because we are right at the edge of a chromosome
-    unless (length($chromosomes{$methylation_call_params->{$sequence_identifier}->{chromosome}}) >= $pos_2+2){# exiting with en empty genomic sequence otherwise
-      # need to set read 1 as well now to prevent warning
-      #  warn "'$non_bisulfite_sequence_1'\n'$non_bisulfite_sequence_2'\n\n";
-      #  sleep(5);
-      $methylation_call_params->{$sequence_identifier}->{unmodified_genomic_sequence_1} = $non_bisulfite_sequence_1;
-      $methylation_call_params->{$sequence_identifier}->{unmodified_genomic_sequence_2} = $non_bisulfite_sequence_2;
-      return;
-    }
-    $non_bisulfite_sequence_2 .= substr ($chromosomes{$methylation_call_params->{$sequence_identifier}->{chromosome}},$pos_2,2);
-  }
-
-  ### all paired-end alignments reported by Bowtie 2 have the Read 1 alignment first and the Read 2 alignment as the second one irrespective of whether read 1 or read 2 was
-  ### the + alignment. We also read in sequences read 1 then read 2 so they should correspond perfectly
-
-  ### results from CT converted read 1 plus GA converted read 2 vs. CT converted genome (+/- orientation alignments are reported only)
-  if ($methylation_call_params->{$sequence_identifier}->{index} == 0){
-    ### [Index 0, sequence originated from (converted) forward strand]
-    $counting{CT_GA_CT_count}++;
-    $alignment_read_1 = '+';
-    $alignment_read_2 = '-';
-    $read_conversion_info_1 = 'CT';
-    $read_conversion_info_2 = 'GA';
-    $genome_conversion = 'CT';
-    ### Read 1 is always the forward hit
-    ### Read 2 is will always on the reverse strand, so it needs to be reverse complemented
-    $non_bisulfite_sequence_2 = reverse_complement($non_bisulfite_sequence_2);
-    if ($contains_deletion_2){
-      $genomic_seq_for_MD_tag_2 = reverse_complement($genomic_seq_for_MD_tag_2);
-    }
-  }
-
-  ### results from GA converted read 1 plus CT converted read 2 vs. GA converted genome (+/- orientation alignments are reported only)
-  elsif ($methylation_call_params->{$sequence_identifier}->{index} == 1){
-    ### [Index 1, sequence originated from complementary to (converted) bottom strand]
-    $counting{GA_CT_GA_count}++;
-    $alignment_read_1 = '+';
-    $alignment_read_2 = '-';
-    $read_conversion_info_1 = 'GA';
-    $read_conversion_info_2 = 'CT';
-    $genome_conversion = 'GA';
-    ### Read 1 is always the forward hit
-    ### Read 2 is will always on the reverse strand, so it needs to be reverse complemented
-    $non_bisulfite_sequence_2 = reverse_complement($non_bisulfite_sequence_2);
-    if ($contains_deletion_2){
-      $genomic_seq_for_MD_tag_2 = reverse_complement($genomic_seq_for_MD_tag_2);
-    }
-  }
-
-  ### results from GA converted read 1 plus CT converted read 2 vs. CT converted genome (-/+ orientation alignments are reported only)
-  elsif ($methylation_call_params->{$sequence_identifier}->{index} == 2){
-    ### [Index 2, sequence originated from the complementary to (converted) top strand]
-    $counting{GA_CT_CT_count}++;
-    $alignment_read_1 = '-';
-    $alignment_read_2 = '+';
-    $read_conversion_info_1 = 'GA';
-    $read_conversion_info_2 = 'CT';
-    $genome_conversion = 'CT';
-
-    ### Read 1 (the reverse strand) genomic sequence needs to be reverse complemented
-    $non_bisulfite_sequence_1 = reverse_complement($non_bisulfite_sequence_1);
-    if ($contains_deletion_1){
-      $genomic_seq_for_MD_tag_1 = reverse_complement($genomic_seq_for_MD_tag_1);
-    }
-  }
-
-  ### results from CT converted read 1 plus GA converted read 2 vs. GA converted genome (-/+ orientation alignments are reported only)
-  elsif ($methylation_call_params->{$sequence_identifier}->{index} == 3){
-    ### [Index 3, sequence originated from the (converted) reverse strand]
-    $counting{CT_GA_GA_count}++;
-    $alignment_read_1 = '-';
-    $alignment_read_2 = '+';
-    $read_conversion_info_1 = 'CT';
-    $read_conversion_info_2 = 'GA';
-    $genome_conversion = 'GA';
-    ### Read 1 (the reverse strand) genomic sequence needs to be reverse complemented
-    $non_bisulfite_sequence_1 = reverse_complement($non_bisulfite_sequence_1);
-    if ($contains_deletion_1){
-      $genomic_seq_for_MD_tag_1 = reverse_complement($genomic_seq_for_MD_tag_1);
-    }
-  }
-  else{
-    die "Too many bowtie result filehandles\n";
-  }
-  ### the alignment_strand information is needed to determine which strand of the genomic sequence we are comparing the read against,
-  ### the read_conversion information is needed to know whether we are looking for C->T or G->A substitutions
-
-  $methylation_call_params->{$sequence_identifier}->{alignment_read_1} = $alignment_read_1;
-  $methylation_call_params->{$sequence_identifier}->{alignment_read_2} = $alignment_read_2;
-  $methylation_call_params->{$sequence_identifier}->{genome_conversion} = $genome_conversion;
-  $methylation_call_params->{$sequence_identifier}->{read_conversion_1} = $read_conversion_info_1;
-  $methylation_call_params->{$sequence_identifier}->{read_conversion_2} = $read_conversion_info_2;
-  $methylation_call_params->{$sequence_identifier}->{unmodified_genomic_sequence_1} = $non_bisulfite_sequence_1;
-  $methylation_call_params->{$sequence_identifier}->{unmodified_genomic_sequence_2} = $non_bisulfite_sequence_2;
-  $methylation_call_params->{$sequence_identifier}->{genomic_seq_for_MD_tag_1} = $genomic_seq_for_MD_tag_1;
-  $methylation_call_params->{$sequence_identifier}->{genomic_seq_for_MD_tag_2} = $genomic_seq_for_MD_tag_2;
-  
-  ## the end position of a read is stored in $pos
-  $methylation_call_params->{$sequence_identifier}->{end_position_1} = $pos_1;
-  $methylation_call_params->{$sequence_identifier}->{end_position_2} = $pos_2;
-  $methylation_call_params->{$sequence_identifier}->{indels_1} = $indels_1;
-  $methylation_call_params->{$sequence_identifier}->{indels_2} = $indels_2;
-}
-
-##########################################
-### PRINT SINGLE END RESULTS: Bowtie 1 ###
-##########################################
-
-sub print_bisulfite_mapping_result_single_end{
-  my ($identifier,$sequence,$methylation_call_params,$quality_value)= @_;
-
-  ### we will output the FastQ quality in Sanger encoding (Phred 33 scale)
-  if ($phred64){
-    $quality_value = convert_phred64_quals_to_phred33($quality_value);
-  }
-  elsif ($solexa){
-    $quality_value = convert_solexa_quals_to_phred33($quality_value);
-  }
-
-  ### We will add +1 bp to the starting position of single-end reads, as Bowtie 1 reports the index and not the bp position. 
-  $methylation_call_params->{$identifier}->{position} += 1;
-	
-  ### writing every uniquely mapped read and its methylation call to the output file
-  if ($vanilla){
-    my $bowtie1_output = join("\t",$identifier,$methylation_call_params->{$identifier}->{alignment_strand},$methylation_call_params->{$identifier}->{chromosome},$methylation_call_params->{$identifier}->{position},$methylation_call_params->{$identifier}->{end_position},$sequence,$methylation_call_params->{$identifier}->{unmodified_genomic_sequence},$methylation_call_params->{$identifier}->{methylation_call},$methylation_call_params->{$identifier}->{read_conversion},$methylation_call_params->{$identifier}->{genome_conversion},$quality_value);
-    print OUT "$bowtie1_output\n";
-  }
-  else{ # SAM output, default since Bismark v1.0.0
-    single_end_SAM_output($identifier,$sequence,$methylation_call_params,$quality_value); # at the end of the script
-  }
-}
-
-##########################################
-### PRINT SINGLE END RESULTS: Bowtie 2 ###
-##########################################
-
-sub print_bisulfite_mapping_result_single_end_bowtie2{
-  my ($identifier,$sequence,$methylation_call_params,$quality_value)= @_;
-
-  ### we will output the FastQ quality in Sanger encoding (Phred 33 scale)
-  if ($phred64){
-    $quality_value = convert_phred64_quals_to_phred33($quality_value);
-  }
-  elsif ($solexa){
-    $quality_value = convert_solexa_quals_to_phred33($quality_value);
-  }
-
-  ### writing every mapped read and its methylation call to the SAM output file (unmapped and ambiguous reads were already printed)
-	single_end_SAM_output($identifier,$sequence,$methylation_call_params,$quality_value); # at the end of the script
-}
-
-##########################################
-### PRINT PAIRED END ESULTS: Bowtie 1  ###
-##########################################
-
-sub print_bisulfite_mapping_results_paired_ends{
-  my ($identifier,$sequence_1,$sequence_2,$methylation_call_params,$quality_value_1,$quality_value_2)= @_;
-
-  ### we will output the FastQ quality in Sanger encoding (Phred 33 scale)
-  if ($phred64){
-    $quality_value_1 = convert_phred64_quals_to_phred33($quality_value_1);
-    $quality_value_2 = convert_phred64_quals_to_phred33($quality_value_2);
-  }
-  elsif ($solexa){
-    $quality_value_1 = convert_solexa_quals_to_phred33($quality_value_1);
-    $quality_value_2 = convert_solexa_quals_to_phred33($quality_value_2);
-  }
-
-  ### We will add +1 bp to the start position of paired-end reads, as Bowtie 1 reports the index and not the bp position. (End position is already 1-based)
-  $methylation_call_params->{$identifier}->{start_seq_1} += 1;
-
-  ### writing every single aligned read and its methylation call to the output file
-  if ($vanilla){	
-    my $bowtie1_output_paired_end = join("\t",$identifier,$methylation_call_params->{$identifier}->{alignment_read_1},$methylation_call_params->{$identifier}->{chromosome},$methylation_call_params->{$identifier}->{start_seq_1},$methylation_call_params->{$identifier}->{alignment_end},$sequence_1,$methylation_call_params->{$identifier}->{unmodified_genomic_sequence_1},$methylation_call_params->{$identifier}->{methylation_call_1},$sequence_2,$methylation_call_params->{$identifier}->{unmodified_genomic_sequence_2},$methylation_call_params->{$identifier}->{methylation_call_2},$methylation_call_params->{$identifier}->{read_conversion_1},$methylation_call_params->{$identifier}->{genome_conversion},$quality_value_1,$quality_value_2);
-    print OUT "$bowtie1_output_paired_end\n";
-  }
-  else{ # SAM output, default since Bismark v1.0.0
-    paired_end_SAM_output($identifier,$sequence_1,$sequence_2,$methylation_call_params,$quality_value_1,$quality_value_2); # at the end of the script
-  }
-
-}
-
-##########################################
-### PRINT PAIRED END ESULTS: Bowtie 2  ###
-##########################################
-
-sub print_bisulfite_mapping_results_paired_ends_bowtie2{
-  my ($identifier,$sequence_1,$sequence_2,$methylation_call_params,$quality_value_1,$quality_value_2)= @_;
-
-  ### we will output the FastQ quality in Sanger encoding (Phred 33 scale)
-  if ($phred64){
-    $quality_value_1 = convert_phred64_quals_to_phred33($quality_value_1);
-    $quality_value_2 = convert_phred64_quals_to_phred33($quality_value_2);
-  }
-  elsif ($solexa){
-    $quality_value_1 = convert_solexa_quals_to_phred33($quality_value_1);
-    $quality_value_2 = convert_solexa_quals_to_phred33($quality_value_2);
-  }
-
-  ### writing every single aligned read and its methylation call to the output file  (unmapped and ambiguous reads were already printed)
-  paired_end_SAM_output($identifier,$sequence_1,$sequence_2,$methylation_call_params,$quality_value_1,$quality_value_2); # at the end of the script
-
-}
-	
-	
-sub convert_phred64_quals_to_phred33{
-
-  my $qual = shift;
-  my @quals = split (//,$qual);
-  my @new_quals;
-
-  foreach my $index (0..$#quals){
-    my $phred_score = convert_phred64_quality_string_into_phred_score ($quals[$index]);
-    my $phred33_quality_string = convert_phred_score_into_phred33_quality_string ($phred_score);
-    $new_quals[$index] = $phred33_quality_string;
-  }
-
-  my $phred33_quality = join ("",@new_quals);
-  return $phred33_quality;
-}
-
-sub convert_solexa_quals_to_phred33{
-
-  my $qual = shift;
-  my @quals = split (//,$qual);
-  my @new_quals;
-
-  foreach my $index (0..$#quals){
-    my $phred_score = convert_solexa_pre1_3_quality_string_into_phred_score ($quals[$index]);
-    my $phred33_quality_string = convert_phred_score_into_phred33_quality_string ($phred_score);
-    $new_quals[$index] = $phred33_quality_string;
-  }
-
-  my $phred33_quality = join ("",@new_quals);
-  return $phred33_quality;
-}
-
-sub convert_phred_score_into_phred33_quality_string{
-  my $qual = shift;
-  $qual = chr($qual+33);
-  return $qual;
-}
-
-sub convert_phred64_quality_string_into_phred_score{
-  my $string = shift;
-  my $qual = ord($string)-64;
-  return $qual;
-}
-
-sub convert_solexa_pre1_3_quality_string_into_phred_score{
-  ### We will just use 59 as the offset here as all Phred Scores between 10 and 40 look exactly the same, there is only a minute difference for values between 0 and 10
-  my $string = shift;
-  my $qual = ord($string)-59;
-  return $qual;
-}
-
-
-sub extract_corresponding_genomic_sequence_single_end {
-  my ($sequence_identifier,$methylation_call_params) = @_;
-  ### A bisulfite sequence for 1 location in the genome can theoretically be any of the 4 possible converted strands. We are also giving the
-  ### sequence a 'memory' of the conversion we are expecting which we will need later for the methylation call
-
-  ### the alignment_strand information is needed to determine which strand of the genomic sequence we are comparing the read against,
-  ### the read_conversion information is needed to know whether we are looking for C->T or G->A substitutions
-  my $alignment_strand;
-  my $read_conversion_info;
-  my $genome_conversion;
-  ### Also extracting the corresponding genomic sequence, +2 extra bases at the end so that we can also make a CpG methylation call and
-  ### in addition make differential calls for Cs non-CpG context, which will now be divided into CHG and CHH methylation,
-  ### if the C happens to be at the last position of the actually observed sequence
-  my $non_bisulfite_sequence;
-  ### depending on the conversion we want to make need to capture 1 extra base at the 3' end
-
-  my $pbat_index_modifier = 0;
-
-  if ($pbat){
-    $pbat_index_modifier += 2; # (we are simply not running indexes 0 or 1!
-  }
-
-  ### results from CT converted read vs. CT converted genome (+ orientation alignments are reported only)
-  if ( ($methylation_call_params->{$sequence_identifier}->{index} + $pbat_index_modifier) == 0){
-    ### [Index 0, sequence originated from (converted) forward strand]
-    $counting{CT_CT_count}++;
-    $alignment_strand = '+';
-    $read_conversion_info = 'CT';
-    $genome_conversion = 'CT';
-
-    ## checking if the substring will be valid or if we can't extract the sequence because we are right at the edge of a chromosome
-    if (length($chromosomes{$methylation_call_params->{$sequence_identifier}->{chromosome}}) > $methylation_call_params->{$sequence_identifier}->{position}+length($methylation_call_params->{$sequence_identifier}->{bowtie_sequence})+1){ ## CHH changed to +1
-      ### + 2 extra base at the 3' end
-      $non_bisulfite_sequence = substr ($chromosomes{$methylation_call_params->{$sequence_identifier}->{chromosome}},$methylation_call_params->{$sequence_identifier}->{position},length($methylation_call_params->{$sequence_identifier}->{bowtie_sequence})+2); ## CHH changed to +2
-    }
-    else{
-      $non_bisulfite_sequence = '';
-    }
-  }
-
-  ### results from CT converted reads vs. GA converted genome (- orientation alignments are reported only)
-  elsif ( ($methylation_call_params->{$sequence_identifier}->{index} + $pbat_index_modifier) == 1){
-    ### [Index 1, sequence originated from (converted) reverse strand]
-    $counting{CT_GA_count}++;
-    $alignment_strand = '-';
-    $read_conversion_info = 'CT';
-    $genome_conversion = 'GA';
-
-    ## checking if the substring will be valid or if we can't extract the sequence because we are right at the edge of a chromosome
-    if ($methylation_call_params->{$sequence_identifier}->{position}-2 >= 0){ ## CHH changed to -2 # 02 02 2012 Changed this to >= from >
-      ### Extracting 2 extra 5' bases on forward strand which will become 2 extra 3' bases after reverse complementation
-      $non_bisulfite_sequence = substr ($chromosomes{$methylation_call_params->{$sequence_identifier}->{chromosome}},$methylation_call_params->{$sequence_identifier}->{position}-2,length($methylation_call_params->{$sequence_identifier}->{bowtie_sequence})+2); ## CHH changed to -2/+2
-      ## reverse complement!
-      $non_bisulfite_sequence = reverse_complement($non_bisulfite_sequence);
-    }
-    else{
-      $non_bisulfite_sequence = '';
-    }
-  }
-
-  ### results from GA converted reads vs. CT converted genome (- orientation alignments are reported only)
-  elsif ( ($methylation_call_params->{$sequence_identifier}->{index} + $pbat_index_modifier) == 2){
-    ### [Index 2, sequence originated from complementary to (converted) forward strand]
-    $counting{GA_CT_count}++;
-    $alignment_strand = '-';
-    $read_conversion_info = 'GA';
-    $genome_conversion = 'CT';
-
-    ### +2 extra bases on the forward strand 3', which will become 2 extra 5' bases after reverse complementation
-    ## checking if the substring will be valid or if we can't extract the sequence because we are right at the edge of a chromosome
-    if (length($chromosomes{$methylation_call_params->{$sequence_identifier}->{chromosome}}) > $methylation_call_params->{$sequence_identifier}->{position}+length($methylation_call_params->{$sequence_identifier}->{bowtie_sequence})+1){ ## changed to +1 on 02 02 2012
-      $non_bisulfite_sequence = substr ($chromosomes{$methylation_call_params->{$sequence_identifier}->{chromosome}},$methylation_call_params->{$sequence_identifier}->{position},length($methylation_call_params->{$sequence_identifier}->{bowtie_sequence})+2); ## CHH changed to +2
-      ## reverse complement!
-      $non_bisulfite_sequence = reverse_complement($non_bisulfite_sequence);
-    }
-    else{
-      $non_bisulfite_sequence = '';
-    }
-  }
-
-  ### results from GA converted reads vs. GA converted genome (+ orientation alignments are reported only)
-  elsif ( ($methylation_call_params->{$sequence_identifier}->{index} + $pbat_index_modifier) == 3){
-    ### [Index 3, sequence originated from complementary to (converted) reverse strand]
-    $counting{GA_GA_count}++;
-    $alignment_strand = '+';
-    $read_conversion_info = 'GA';
-    $genome_conversion = 'GA';
-
-    ## checking if the substring will be valid or if we can't extract the sequence because we are right at the edge of a chromosome
-    if ($methylation_call_params->{$sequence_identifier}->{position}-2 >= 0){ ## CHH changed to +2 # 02 02 2012 Changed this to >= from >
-      ### +2 extra base at the 5' end as we are nominally checking the converted reverse strand
-      $non_bisulfite_sequence = substr ($chromosomes{$methylation_call_params->{$sequence_identifier}->{chromosome}},$methylation_call_params->{$sequence_identifier}->{position}-2,length($methylation_call_params->{$sequence_identifier}->{bowtie_sequence})+2); ## CHH changed to -2/+2
-    }
-    else{
-      $non_bisulfite_sequence = '';
-    }
-  }
-  else{
-    die "Too many bowtie result filehandles\n";
-  }
-
-  $methylation_call_params->{$sequence_identifier}->{alignment_strand} = $alignment_strand;
-  $methylation_call_params->{$sequence_identifier}->{read_conversion} = $read_conversion_info;
-  $methylation_call_params->{$sequence_identifier}->{genome_conversion} = $genome_conversion;
-  $methylation_call_params->{$sequence_identifier}->{unmodified_genomic_sequence} = $non_bisulfite_sequence;
-
-  ### at this point we can also determine the end position of a read
-  $methylation_call_params->{$sequence_identifier}->{end_position} = $methylation_call_params->{$sequence_identifier}->{position}+length($methylation_call_params->{$sequence_identifier}->{bowtie_sequence});
-}
-
-
-sub extract_corresponding_genomic_sequence_single_end_bowtie2{
-  my ($sequence_identifier,$methylation_call_params) = @_;
-
-  my $MD_tag = $methylation_call_params->{$sequence_identifier}->{MD_tag};
-  my $cigar  = $methylation_call_params->{$sequence_identifier}->{CIGAR};
-
-  my $contains_deletion = 0;
-  if ($cigar =~ /D/){
-    $contains_deletion = 1;
-    # warn "$cigar\n$MD_tag\n";
-  }
-  ### A bisulfite sequence for 1 location in the genome can theoretically be any of the 4 possible converted strands. We are also giving the
-  ### sequence a 'memory' of the conversion we are expecting which we will need later for the methylation call
-
-  ### the alignment_strand information is needed to determine which strand of the genomic sequence we are comparing the read against,
-  ### the read_conversion information is needed to know whether we are looking for C->T or G->A substitutions
-  my $alignment_strand;
-  my $read_conversion_info;
-  my $genome_conversion;
-
-  ### We are now extracting the corresponding genomic sequence, +2 extra bases at the end (or start) so that we can also make a CpG methylation call and
-  ### in addition make differential calls for Cs in CHG or CHH context if the C happens to be at the last (or first)  position of the actually observed sequence
-  my $non_bisulfite_sequence = '';
-  my $genomic_seq_for_MD_tag = ''; # this sequence contains potential deletions in the genome as well so that we can generate a proper MD tag for the SAM output
-
-  ### Positions in SAM format are 1 based, so we need to subract 1 when getting substrings
-  my $pos = $methylation_call_params->{$sequence_identifier}->{position}-1;
-
-  # parsing CIGAR string
-  my @len = split (/\D+/,$cigar); # storing the length per operation
-  my @ops = split (/\d+/,$cigar); # storing the operation
-  shift @ops; # remove the empty first element
-  die "CIGAR string contained a non-matching number of lengths and operations\n" unless (scalar @len == scalar @ops);
-
-  my $pbat_index_modifier = 0;
-
-  if ($pbat){
-    $pbat_index_modifier += 2; # (we are simply not running indexes 0 or 1!
-  }
-
-  ### If the sequence aligns best as CT converted reads vs. GA converted genome (OB, index 1) or GA converted reads vs. GA converted genome (CTOB, index 3)
-  if ( (($methylation_call_params->{$sequence_identifier}->{index} + $pbat_index_modifier) == 1) or (($methylation_call_params->{$sequence_identifier}->{index}  + $pbat_index_modifier) == 3) ){
-    ## checking if the substring will be valid or if we can't extract the sequence because we are right at the edge of a chromosome
-    unless ( ($pos-2) >= 0){ # exiting with en empty genomic sequence otherwise
-      $methylation_call_params->{$sequence_identifier}->{unmodified_genomic_sequence} = $non_bisulfite_sequence;
-      $methylation_call_params->{$sequence_identifier}->{genomic_seq_for_MD_tag} = $genomic_seq_for_MD_tag;
-      return;
-    }
-    $non_bisulfite_sequence .= substr ($chromosomes{$methylation_call_params->{$sequence_identifier}->{chromosome}},$pos-2,2);
-  }
-
-  my $indels = 0;	
-
-  foreach (0..$#len){
-    if ($ops[$_] eq 'M'){
-      #extracting genomic sequence
-      $non_bisulfite_sequence .= substr ($chromosomes{$methylation_call_params->{$sequence_identifier}->{chromosome}},$pos,$len[$_]);
-      if ($contains_deletion){
-	$genomic_seq_for_MD_tag .= substr ($chromosomes{$methylation_call_params->{$sequence_identifier}->{chromosome}},$pos,$len[$_]);
-      }
-      # adjusting position
-      $pos += $len[$_];
-    }
-    elsif ($ops[$_] eq 'I'){ # insertion in the read sequence
-      # we simply add padding Xs instead of finding genomic sequence. This will not be used to infer methylation calls and we can later ignore it better during the generation of the MD:Z-tag
-      $non_bisulfite_sequence .= 'X' x $len[$_];
-      if ($contains_deletion){
-	$genomic_seq_for_MD_tag .= 'X' x $len[$_];
-      }
-      # warn "$non_bisulfite_sequence\n";
-      # position doesn't need to be adjusting
-
-      ### 03 06 2014: In fact we don't need to add anything to the hemming distance for insertions since we use padding Xs which will fail the base by base comparison in hemming_dist()
-      # $indels += $len[$_]; # adding this to $indels so we can determine the hemming distance for the SAM output (= single-base substitutions (mismatches, insertions, deletions)
-    }
-    elsif ($ops[$_] eq 'D'){ # deletion in the read sequence
-      # we do not add any genomic sequence but only adjust the position
-
-      # we do however add the genomic sequence to the $genomic_sequence for MD-tag determination if the CIGAR string contained a deletion
-      if ($contains_deletion){
-	$genomic_seq_for_MD_tag .= substr ($chromosomes{$methylation_call_params->{$sequence_identifier}->{chromosome}},$pos,$len[$_]);
-      }
-      $pos += $len[$_];
-      $indels += $len[$_]; # adding this to $indels so we can determine the hemming distance for the SAM output (= single-base substitutions (mismatches, insertions, deletions)
-    }
-    elsif($cigar =~ tr/[NSHPX=]//){ # if these (for standard mapping) illegal characters exist we die
-      die "The CIGAR string contained illegal CIGAR operations in addition to 'M', 'I' and 'D': $cigar\n";
-    }
-    else{
-      die "The CIGAR string contained undefined CIGAR operations in addition to 'M', 'I' and 'D': $cigar\n";
-    }
-  }
-
-  ### If the sequence aligns best as CT converted reads vs. CT converted genome (OT, index 0) or GA converted reads vs. CT converted genome (CTOT, index 2)
-  if ( ( ($methylation_call_params->{$sequence_identifier}->{index} + $pbat_index_modifier) == 0) or ( ($methylation_call_params->{$sequence_identifier}->{index} + $pbat_index_modifier) == 2) ){
-    ## checking if the substring will be valid or if we can't extract the sequence because we are right at the edge of a chromosome
-    unless (length($chromosomes{$methylation_call_params->{$sequence_identifier}->{chromosome}}) >= $pos+2){ # exiting with en empty genomic sequence otherwise
-      $methylation_call_params->{$sequence_identifier}->{unmodified_genomic_sequence} = $non_bisulfite_sequence;
-      $methylation_call_params->{$sequence_identifier}->{genomic_seq_for_MD_tag} = $genomic_seq_for_MD_tag;
-      return;
-    }
-    $non_bisulfite_sequence .= substr ($chromosomes{$methylation_call_params->{$sequence_identifier}->{chromosome}},$pos,2);
-    # print "$methylation_call_params->{$sequence_identifier}->{bowtie_sequence}\n$non_bisulfite_sequence\n";
-  }
-
-
-  ### results from CT converted read vs. CT converted genome (+ orientation alignments are reported only)
-  if ( ($methylation_call_params->{$sequence_identifier}->{index} + $pbat_index_modifier) == 0){
-    ### [Index 0, sequence originated from (converted) forward strand]
-    $counting{CT_CT_count}++;
-    $alignment_strand = '+';
-    $read_conversion_info = 'CT';
-    $genome_conversion = 'CT';
-  }
-
-  ### results from CT converted reads vs. GA converted genome (- orientation alignments are reported only)
-  elsif ( ($methylation_call_params->{$sequence_identifier}->{index} + $pbat_index_modifier) == 1){
-    ### [Index 1, sequence originated from (converted) reverse strand]
-    $counting{CT_GA_count}++;
-    $alignment_strand = '-';
-    $read_conversion_info = 'CT';
-    $genome_conversion = 'GA';
-
-    ### reverse complement!
-    $non_bisulfite_sequence = reverse_complement($non_bisulfite_sequence);
-    if ($contains_deletion){
-      $genomic_seq_for_MD_tag = reverse_complement($genomic_seq_for_MD_tag);
-    }
-  }
-
-  ### results from GA converted reads vs. CT converted genome (- orientation alignments are reported only)
-  elsif ( ($methylation_call_params->{$sequence_identifier}->{index} + $pbat_index_modifier) == 2){
-    ### [Index 2, sequence originated from complementary to (converted) forward strand]
-    $counting{GA_CT_count}++;
-    $alignment_strand = '-';
-    $read_conversion_info = 'GA';
-    $genome_conversion = 'CT';
-
-    ### reverse complement!
-    $non_bisulfite_sequence = reverse_complement($non_bisulfite_sequence);
-    if ($contains_deletion){
-      $genomic_seq_for_MD_tag = reverse_complement($genomic_seq_for_MD_tag);
-    }
-  }
-
-  ### results from GA converted reads vs. GA converted genome (+ orientation alignments are reported only)
-  elsif ( ($methylation_call_params->{$sequence_identifier}->{index} + $pbat_index_modifier) == 3){
-    ### [Index 3, sequence originated from complementary to (converted) reverse strand]
-    $counting{GA_GA_count}++;
-    $alignment_strand = '+';
-    $read_conversion_info = 'GA';
-    $genome_conversion = 'GA';
-
-  }
-  else{
-    die "Too many Bowtie 2 result filehandles\n";
-  }
-
-  $methylation_call_params->{$sequence_identifier}->{alignment_strand} = $alignment_strand;
-  $methylation_call_params->{$sequence_identifier}->{read_conversion} = $read_conversion_info;
-  $methylation_call_params->{$sequence_identifier}->{genome_conversion} = $genome_conversion;
-  $methylation_call_params->{$sequence_identifier}->{unmodified_genomic_sequence} = $non_bisulfite_sequence;
-  $methylation_call_params->{$sequence_identifier}->{genomic_seq_for_MD_tag} = $genomic_seq_for_MD_tag;
-
-  # if ($contains_deletion){
-  #   warn "non-bis: $methylation_call_params->{$sequence_identifier}->{unmodified_genomic_sequence}\n";
-  #   warn "MD-seq:  $methylation_call_params->{$sequence_identifier}->{genomic_seq_for_MD_tag}\n";
-  # }
-
-  ### the end position of a read is stored in $pos
-  $methylation_call_params->{$sequence_identifier}->{end_position} = $pos;
-  $methylation_call_params->{$sequence_identifier}->{indels} = $indels;
-}
-
-### METHYLATION CALL
-
-sub methylation_call{
-  my ($identifier,$sequence_actually_observed,$genomic_sequence,$read_conversion) = @_;
-  ### splitting both the actually observed sequence and the genomic sequence up into single bases so we can compare them one by one
-  my @seq = split(//,$sequence_actually_observed);
-  my @genomic = split(//,$genomic_sequence);
-  #  print join ("\n",$identifier,$sequence_actually_observed,$genomic_sequence,$read_conversion),"\n";
-  ### Creating a match-string with different characters for non-cytosine bases (disregarding mismatches here), methyl-Cs or non-methyl Cs in either
-  ### CpG, CHH or CHG context
-
-  #################################################################
-  ### . for bases not involving cytosines                       ###
-  ### X for methylated C in CHG context (was protected)         ###
-  ### x for not methylated C in CHG context (was converted)     ###
-  ### H for methylated C in CHH context (was protected)         ###
-  ### h for not methylated C in CHH context (was converted)     ###
-  ### Z for methylated C in CpG context (was protected)         ###
-  ### z for not methylated C in CpG context (was converted)     ###
-  ### U for methylated C in unknown context (was protected)     ###
-  ### u for not methylated C in unknwon context (was converted) ###
-  #################################################################
-
-  my @match =();
-  warn "length of \@seq: ",scalar @seq,"\tlength of \@genomic: ",scalar @genomic,"\n" unless (scalar @seq eq (scalar@genomic-2)); ## CHH changed to -2
-  my $methyl_CHH_count = 0;
-  my $methyl_CHG_count = 0;
-  my $methyl_CpG_count = 0;
-  my $methyl_C_unknown_count = 0;
-  my $unmethylated_CHH_count = 0;
-  my $unmethylated_CHG_count = 0;
-  my $unmethylated_CpG_count = 0;
-  my $unmethylated_C_unknown_count = 0;
-
-  if ($read_conversion eq 'CT'){
-    for my $index (0..$#seq) {
-      if ($seq[$index] eq $genomic[$index]) {
-	### The residue can only be a C if it was not converted to T, i.e. protected my methylation
-	if ($genomic[$index] eq 'C') {
-	  ### If the residue is a C we want to know if it was in CpG context or in any other context
-	  my $downstream_base = $genomic[$index+1];
-	
-	  if ($downstream_base eq 'G'){
-	    ++$methyl_CpG_count;
-	    push @match,'Z'; # protected C, methylated, in CpG context
-	  }
-	  elsif ($downstream_base eq 'N'){ # if the downstream base was an N we cannot really be sure about the sequence context (as it might have been a CG)
-	    ++$methyl_C_unknown_count;
-	    push @match,'U'; # protected C, methylated, in Unknown context
-	  }	
-	  else {
-	    ### C in not in CpG-context, determining the second downstream base context
-	    my $second_downstream_base = $genomic[$index+2];
-	
-	    if ($second_downstream_base eq 'G'){
-	      ++$methyl_CHG_count;
-	      push @match,'X'; # protected C, methylated, in CHG context
-	    }
-	    elsif ($second_downstream_base eq 'N'){
-	      ++$methyl_C_unknown_count; # if the second downstream base was an N we cannot really be sure about the sequence context (as it might have been a CHH or CHG)
-	      push @match,'U'; # protected C, methylated, in Unknown context
-	    }
-	    else{
-	      ++$methyl_CHH_count;
-	      push @match,'H'; # protected C, methylated, in CHH context
-	    }
-	  }
-	}
-	else {
-	  push @match, '.';
-	}
-      }
-      elsif ($seq[$index] ne $genomic[$index]) {
-	### for the methylation call we are only interested in mismatches involving cytosines (in the genomic sequence) which were converted into Ts
-	### in the actually observed sequence
-	if ($genomic[$index] eq 'C' and $seq[$index] eq 'T') {
-	  ### If the residue was converted to T we want to know if it was in CpG, CHG or CHH  context
-	  my $downstream_base = $genomic[$index+1];
-	
-	  if ($downstream_base eq 'G'){
-	    ++$unmethylated_CpG_count;
-	    push @match,'z'; # converted C, not methylated, in CpG context
-	  }
-	  elsif ($downstream_base eq 'N'){ # if the downstream base was an N we cannot really be sure about the sequence context (as it might have been a CG)
-	    ++$unmethylated_C_unknown_count;
-	    push @match,'u'; # converted C, not methylated, in Unknown context
-	  }
-	  else{
-	    ### C in not in CpG-context, determining the second downstream base context
-	    my $second_downstream_base = $genomic[$index+2];
-	
-	    if ($second_downstream_base eq 'G'){
-	      ++$unmethylated_CHG_count;
-	      push @match,'x'; # converted C, not methylated, in CHG context
-	    }
-	    elsif ($second_downstream_base eq 'N'){
-	      ++$unmethylated_C_unknown_count; # if the second downstream base was an N we cannot really be sure about the sequence context (as it might have been a CHH or CHG)
-	      push @match,'u'; # converted C, not methylated, in Unknown context
-	    }
-	    else{
-	      ++$unmethylated_CHH_count;
-	      push @match,'h'; # converted C, not methylated, in CHH context
-	    }
-	  }
-	}
-	### all other mismatches are not of interest for a methylation call
-	else {
-	  push @match,'.';
-	}
-      }
-      else{
-	die "There can be only 2 possibilities\n";
-      }
-    }
-  }
-  elsif ($read_conversion eq 'GA'){
-    # print join ("\n",'***',$identifier,$sequence_actually_observed,$genomic_sequence,$read_conversion,'***'),"\n";
-
-    for my $index (0..$#seq) {
-      if ($seq[$index] eq $genomic[$index+2]) {
-	### The residue can only be a G if the C on the other strand was not converted to T, i.e. protected my methylation
-	if ($genomic[$index+2] eq 'G') {
-	  ### If the residue is a G we want to know if the C on the other strand was in CpG, CHG or CHH context, therefore we need
-	  ### to look if the base upstream is a C
-
-	  my $upstream_base = $genomic[$index+1];
-	
-	  if ($upstream_base eq 'C'){
-	    ++$methyl_CpG_count;
-	    push @match,'Z'; # protected C on opposing strand, methylated, in CpG context
-	  }
-	  elsif ($upstream_base eq 'N'){ # if the upstream base was an N we cannot really be sure about the sequence context (as it might have been a CG)
-	    ++$methyl_C_unknown_count;
-	    push @match,'U'; # protected C on opposing strand, methylated, in Unknown context
-	  }
-	  else{
-	    ### C in not in CpG-context, determining the second upstream base context
-	    my $second_upstream_base = $genomic[$index];
-	
-	    if ($second_upstream_base eq 'C'){
-	      ++$methyl_CHG_count;
-	      push @match,'X'; # protected C on opposing strand, methylated, in CHG context
-	    }
-	    elsif ($second_upstream_base eq 'N'){
-	      ++$methyl_C_unknown_count; # if the second upstream base was an N we cannot really be sure about the sequence context (as it might have been a CHH or CHG)
-	      push @match,'U'; # protected C, methylated, in Unknown context
-	    }
-	    else{
-	      ++$methyl_CHH_count;
-	      push @match,'H'; # protected C on opposing strand, methylated, in CHH context
-	    }
-	  }
-	}
-	else{
-	  push @match, '.';
-	}
-      }
-      elsif ($seq[$index] ne $genomic[$index+2]) {
-	### for the methylation call we are only interested in mismatches involving cytosines (in the genomic sequence) which were converted to Ts
-	### on the opposing strand, so G to A conversions in the actually observed sequence
-	if ($genomic[$index+2] eq 'G' and $seq[$index] eq 'A') {
-	  ### If the C residue on the opposing strand was converted to T then we will see an A in the currently observed sequence. We want to know if
-	  ### the C on the opposing strand was it was in CpG, CHG or CHH context, therefore we need to look one (or two) bases upstream!
-
-	  my $upstream_base = $genomic[$index+1];
-
-	  if ($upstream_base eq 'C'){
-	    ++$unmethylated_CpG_count;
-	    push @match,'z'; # converted C on opposing strand, not methylated, in CpG context
-	  }
-	  elsif ($upstream_base eq 'N'){ # if the upstream base was an N we cannot really be sure about the sequence context (as it might have been a CG)
-	    ++$unmethylated_C_unknown_count;
-	    push @match,'u'; # converted C on opposing strand, not methylated, in Unknown context
-	  }
-	  else{
-	    ### C in not in CpG-context, determining the second upstream base context
-	    my $second_upstream_base = $genomic[$index];
-	
-	    if ($second_upstream_base eq 'C'){
-	      ++$unmethylated_CHG_count;
-	      push @match,'x'; # converted C on opposing strand, not methylated, in CHG context
-	    }
-	    elsif ($second_upstream_base eq 'N'){
-	      ++$unmethylated_C_unknown_count; # if the second upstream base was an N we cannot really be sure about the sequence context (as it might have been a CHH or CHG)
-	      push @match,'u'; # converted C on opposing strand, not methylated, in Unknown context
-	    }
-	    else{
-	      ++$unmethylated_CHH_count;
-	      push @match,'h'; # converted C on opposing strand, not methylated, in CHH context
-	    }
-	  }
-	}
-	### all other mismatches are not of interest for a methylation call
-	else {
-	  push @match,'.';
-	}
-      }
-      else{
-	die "There can be only 2 possibilities\n";
-      }
-    }
-  }
-  else{
-    die "Strand conversion info is required to perform a methylation call\n";
-  }
-
-  my $methylation_call = join ("",@match);
-
-  $counting{total_meCHH_count} += $methyl_CHH_count;
-  $counting{total_meCHG_count} += $methyl_CHG_count;
-  $counting{total_meCpG_count} += $methyl_CpG_count;
-  $counting{total_meC_unknown_count} += $methyl_C_unknown_count;
-  $counting{total_unmethylated_CHH_count} += $unmethylated_CHH_count;
-  $counting{total_unmethylated_CHG_count} += $unmethylated_CHG_count;
-  $counting{total_unmethylated_CpG_count} += $unmethylated_CpG_count;
-  $counting{total_unmethylated_C_unknown_count} += $unmethylated_C_unknown_count;
-
-  # print "\n$sequence_actually_observed\n$genomic_sequence\n",@match,"\n$read_conversion\n\n";
-
-  return $methylation_call;
-}
-
-sub read_genome_into_memory{
-
-    ## working directoy
-    my $cwd = shift;
-    
-    ## reading in and storing the specified genome in the %chromosomes hash
-    chdir ($genome_folder) or die "Can't move to $genome_folder: $!";
-    warn "Now reading in and storing sequence information of the genome specified in: $genome_folder\n\n";
-
-    my @chromosome_filenames =  <*.fa>;
-
-    ### if there aren't any genomic files with the extension .fa we will look for files with the extension .fasta
-    unless (@chromosome_filenames){
-      @chromosome_filenames =  <*.fasta>;
-    }
-
-    unless (@chromosome_filenames){
-      die "The specified genome folder $genome_folder does not contain any sequence files in FastA format (with .fa or .fasta file extensions)\n";
-    }
-
-    my $SQ_count = 0;
-
-    foreach my $chromosome_filename (@chromosome_filenames){
-
-	open (CHR_IN,$chromosome_filename) or die "Failed to read from sequence file $chromosome_filename $!\n";
-	### first line needs to be a fastA header
-	my $first_line = <CHR_IN>;
-	chomp $first_line;
-	$first_line =~ s/\r//;
-	### Extracting chromosome name from the FastA header
-	my $chromosome_name = extract_chromosome_name($first_line);
-	my $sequence;
-
-	while (<CHR_IN>){
-	  chomp;
-	  $_ =~ s/\r//; # removing carriage returns if present
-	  if ($_ =~ /^>/){
-	
-	    ### storing the previous chromosome in the %chromosomes hash, only relevant for Multi-Fasta-Files (MFA)
-	    if (exists $chromosomes{$chromosome_name}){
-	      print "chr $chromosome_name (",length $sequence ," bp)\n";
-	      die "Exiting because chromosome name already exists. Please make sure all chromosomes have a unique name!\n";
-	    }
-	    else {
-	      if (length($sequence) == 0){
-		warn "Chromosome $chromosome_name in the multi-fasta file $chromosome_filename did not contain any sequence information!\n";
-	      }
-	      print "chr $chromosome_name (",length $sequence ," bp)\n";
-	      $chromosomes{$chromosome_name} = $sequence;
-	      $SQ_order{$SQ_count} = $chromosome_name;
-
-	      ++$SQ_count;
-
-	    }
-	    ### resetting the sequence variable
-	    $sequence = '';
-	    ### setting new chromosome name
-	    $chromosome_name = extract_chromosome_name($_);
-	  }
-	  else{
-	    $sequence .= uc$_;
-	  }
-	}
-	
- 	### Processing last chromosome of a multi Fasta File or the only entry in case of single entry FastA files
-
-	if (exists $chromosomes{$chromosome_name}){
-	    print "chr $chromosome_name (",length $sequence ," bp)\t";
-	    die "Exiting because chromosome name already exists. Please make sure all chromosomes have a unique name.\n";
-	}
-	else{
-	    if (length($sequence) == 0){
-		warn "Chromosome $chromosome_name in the file $chromosome_filename did not contain any sequence information!\n";
-	    }
-
-	    ++$SQ_count;
-
-	    print "chr $chromosome_name (",length $sequence ," bp)\n";
-	    $chromosomes{$chromosome_name} = $sequence;
-	    $SQ_order{$SQ_count} = $chromosome_name;
-	}
-    }
-    print "\n";
-    chdir $cwd or die "Failed to move to directory $cwd\n";
-
-    ### If no single multi-FastA genome file was specified explicitely we will generate one here and write it to the output directory
-    if ($cram){
-	unless (defined $cram_ref){
-	    warn "Reconstituting a single multi-FastA genome file as CRAM reference (you may specify such a file using --cram_ref <file> explicitely to prevent this behaviour)\n";	
-
-	    $cram_ref = "${output_dir}Bismark_genome_CRAM_reference.mfa";
-	    warn "Writing multi-FastA file to $cram_ref\n";
-	    open (REF,'>',"$cram_ref") or die "Failed to write to file $cram_ref\n";
-	    foreach my $chr(keys %chromosomes){
-		print REF ">$chr\n$chromosomes{$chr}\n";
-	    }
-	    warn "Complete\n";
-	    close REF or warn "Failed to close filehandle REF: $!\n";
-	}
-	
-    }
-    
-
-
-}
-
-sub extract_chromosome_name {
-    ## Bowtie seems to extract the first string after the inition > in the FASTA file, so we are doing this as well
-    my $fasta_header = shift;
-    if ($fasta_header =~ s/^>//){
-	my ($chromosome_name) = split (/\s+/,$fasta_header);
-	return $chromosome_name;
-    }
-    else{
-	die "The specified chromosome ($fasta_header) file doesn't seem to be in FASTA format as required!\n";
-    }
-}
-
-sub reverse_complement{
-  my $sequence = shift;
-  $sequence =~ tr/CATG/GTAC/;
-  $sequence = reverse($sequence);
-  return $sequence;
-}
-
-sub biTransformFastAFiles {
-  my $file = shift;
-  my ($dir,$filename);
-  if ($file =~ /\//){
-    ($dir,$filename) = $file =~ m/(.*\/)(.*)$/;
-  }
-  else{
-    $filename = $file;
-  }
-
-  ### gzipped version of the infile
-  if ($file =~ /\.gz$/){
-    open (IN,"gunzip -c $file |") or die "Couldn't read from file $file: $!\n";
-  }
-  else{
-    open (IN,$file) or die "Couldn't read from file $file: $!\n";
-  }
-
-  if ($skip){
-    warn "Skipping the first $skip reads from $file\n";
-    sleep (1);
-  }
-  if ($upto){
-    warn "Processing reads up to sequence no. $upto from $file\n";
-    sleep (1);
-  }
-
-  my $C_to_T_infile = my $G_to_A_infile = $filename;
-
-  if ($gzip){
-    $C_to_T_infile =~ s/$/_C_to_T.fa.gz/;
-    $G_to_A_infile =~ s/$/_G_to_A.fa.gz/;
-  }
-  else{
-    $C_to_T_infile =~ s/$/_C_to_T.fa/;
-    $G_to_A_infile =~ s/$/_G_to_A.fa/;
-  }
-
-  if ($prefix){
-    #  warn "Prefixing $prefix:\nold: $C_to_T_infile\nold: $G_to_A_infile\n\n";
-    $C_to_T_infile = "$prefix.$C_to_T_infile";
-    $G_to_A_infile = "$prefix.$G_to_A_infile";
-    #  warn "Prefixing $prefix:\nnew: $C_to_T_infile\nnew: $G_to_A_infile\n\n";
-  }
-
-  warn "Writing a C -> T converted version of the input file $filename to $temp_dir$C_to_T_infile\n";
-
-  if ($gzip){
-    open (CTOT,"| gzip -c - > ${temp_dir}${C_to_T_infile}") or die "Can't write to file: $!\n";
-  }
-  else{
-    open (CTOT,'>',"$temp_dir$C_to_T_infile") or die "Couldn't write to file $!\n";
-  }
-
-  unless ($directional){
-    warn "Writing a G -> A converted version of the input file $filename to $temp_dir$G_to_A_infile\n";
-    if ($gzip){
-      open (GTOA,"| gzip -c - > ${temp_dir}${G_to_A_infile}") or die "Can't write to file: $!\n";
-    }
-    else{
-      open (GTOA,'>',"$temp_dir$G_to_A_infile") or die "Couldn't write to file $!\n";
-    }
-  }
-
-  my $count = 0;
-
-  while (1){
-    my $header = <IN>;
-    my $sequence= <IN>;
-    last unless ($header and $sequence);
-
-    $header = fix_IDs($header); # this is to avoid problems with truncated read ID when they contain white spaces
-
-    ++$count;
-
-    if ($skip){
-      next unless ($count > $skip);
-    }
-    if ($upto){
-      last if ($count > $upto);
-    }
-
-    $sequence = uc$sequence; # make input file case insensitive
-
-    # detecting if the input file contains tab stops, as this is likely to result in no alignments
-    if (index($header,"\t") != -1){
-      $seqID_contains_tabs++;
-    }
-
-    ### small check if the sequence seems to be in FastA format
-    die "Input file doesn't seem to be in FastA format at sequence $count: $!\n" unless ($header =~ /^>.*/);
-
-    my $sequence_C_to_T = $sequence;
-    $sequence_C_to_T =~ tr/C/T/;
-    print CTOT "$header$sequence_C_to_T";
-
-    unless ($directional){
-      my $sequence_G_to_A = $sequence;
-      $sequence_G_to_A =~ tr/G/A/;
-      print GTOA "$header$sequence_G_to_A";
-    }
-  }
-  close CTOT or die "Failed to close filehandle $!\n";
-
-  if ($directional){
-    warn "\nCreated C -> T converted versions of the FastA file $filename ($count sequences in total)\n\n";
-  }
-  else{
-    close GTOA or die "Failed to close filehandle $!\n";
-    warn "\nCreated C -> T as well as G -> A converted versions of the FastA file $filename ($count sequences in total)\n\n";
-  }
-  return ($C_to_T_infile,$G_to_A_infile);
-}
-
-sub biTransformFastAFiles_paired_end {
-  my ($file,$read_number) = @_;
-
-  if ($gzip){
-    warn "GZIP compression of temporary files is not supported for paired-end FastA data. Continuing to write uncompressed files\n";
-    sleep (2);
-  }
-
-  my ($dir,$filename);
-  if ($file =~ /\//){
-    ($dir,$filename) = $file =~ m/(.*\/)(.*)$/;
-  }
-  else{
-    $filename = $file;
-  }
-
-  ### gzipped version of the infile
-  if ($file =~ /\.gz$/){
-    open (IN,"gunzip -c $file |") or die "Couldn't read from file $file: $!\n";
-  }
-  else{
-    open (IN,$file) or die "Couldn't read from file $file: $!\n";
-  }
-
-  if ($skip){
-    warn "Skipping the first $skip reads from $file\n";
-    sleep (1);
-  }
-  if ($upto){
-    warn "Processing reads up to sequence no. $upto from $file\n";
-    sleep (1);
-  }
-
-  my $C_to_T_infile = my $G_to_A_infile = $filename;
-
-  $C_to_T_infile =~ s/$/_C_to_T.fa/;
-  $G_to_A_infile =~ s/$/_G_to_A.fa/;
-
-  if ($prefix){
-    #  warn "Prefixing $prefix:\nold: $C_to_T_infile\nold: $G_to_A_infile\n\n";
-    $C_to_T_infile = "$prefix.$C_to_T_infile";
-    $G_to_A_infile = "$prefix.$G_to_A_infile";
-    #  warn "Prefixing $prefix:\nnew: $C_to_T_infile\nnew: $G_to_A_infile\n\n";
-  }
-
-  if ($directional){
-    if ($read_number == 1){
-      warn "Writing a C -> T converted version of the input file $filename to $temp_dir$C_to_T_infile\n";
-      open (CTOT,'>',"$temp_dir$C_to_T_infile") or die "Couldn't write to file $!\n";
-    }
-    elsif ($read_number == 2){
-      warn "Writing a G -> A converted version of the input file $filename to $temp_dir$G_to_A_infile\n";
-      open (GTOA,'>',"$temp_dir$G_to_A_infile") or die "Couldn't write to file $!\n";
-    }
-    else{
-      die "Read number needs to be 1 or 2, but was: $read_number\n\n";
-    }
-  }
-  else{ # all four strand output
-    warn "Writing a C -> T converted version of the input file $filename to $temp_dir$C_to_T_infile\n";
-    warn "Writing a G -> A converted version of the input file $filename to $temp_dir$G_to_A_infile\n";
-    open (CTOT,'>',"$temp_dir$C_to_T_infile") or die "Couldn't write to file $!\n";
-    open (GTOA,'>',"$temp_dir$G_to_A_infile") or die "Couldn't write to file $!\n";
-  }
-
-  my $count = 0;
-
-  while (1){
-    my $header = <IN>;
-    my $sequence= <IN>;
-    last unless ($header and $sequence);
-
-    $header = fix_IDs($header); # this is to avoid problems with truncated read ID when they contain white spaces
-
-    ++$count;
-
-    if ($skip){
-      next unless ($count > $skip);
-    }
-    if ($upto){
-      last if ($count > $upto);
-    }
-
-    $sequence = uc$sequence; # make input file case insensitive
-
-    # detecting if the input file contains tab stops, as this is likely to result in no alignments
-    if (index($header,"\t") != -1){
-      $seqID_contains_tabs++;
-    }
-
-    ## small check if the sequence seems to be in FastA format
-    die "Input file doesn't seem to be in FastA format at sequence $count: $!\n" unless ($header =~ /^>/);
-
-    if ($read_number == 1){
-      if ($bowtie2){
-	$header =~ s/$/\/1\/1/;
-      }
-      else{	
-	$header =~ s/$/\/1/;
-      }
-    }
-    elsif ($read_number == 2){
-      if ($bowtie2){
-	$header =~ s/$/\/2\/2/;
-      }
-      else{
-	$header =~ s/$/\/2/;
-      }
-    }
-    else{
-      die "Read number needs to be 1 or 2, but was: $read_number\n\n";
-    }
-    my $sequence_C_to_T = my $sequence_G_to_A = $sequence;
-
-    $sequence_C_to_T =~ tr/C/T/;
-    $sequence_G_to_A =~ tr/G/A/;
-
-    if ($directional){
-
-      if ($read_number == 1){
-	print CTOT "$header$sequence_C_to_T";
-      }
-      elsif ($read_number == 2){
-	print GTOA "$header$sequence_G_to_A";
-      }
-    }
-    else{
-      print CTOT "$header$sequence_C_to_T";
-      print GTOA "$header$sequence_G_to_A";
-    }
-  }
-
-  if ($directional){
-    if ($read_number == 1){
-      warn "\nCreated C -> T converted version of the FastA file $filename ($count sequences in total)\n\n";
-    }
-    else{
-      warn "\nCreated G -> A converted version of the FastA file $filename ($count sequences in total)\n\n";
-    }
-  }
-  else{
-    warn "\nCreated C -> T as well as G -> A converted versions of the FastA file $filename ($count sequences in total)\n\n";
-  }
-
-  if ($directional){
-    if ($read_number == 1){
-      return ($C_to_T_infile);
-    }
-    else{
-      return ($G_to_A_infile);
-    }
-  }
-  else{
-    return ($C_to_T_infile,$G_to_A_infile);
-  }
-}
-
-
-sub biTransformFastQFiles {
-  my $file = shift;
-  my ($dir,$filename);
-  if ($file =~ /\//){
-    ($dir,$filename) = $file =~ m/(.*\/)(.*)$/;
-  }
-  else{
-    $filename = $file;
-  }
-
-  ### gzipped version of the infile
-  if ($file =~ /\.gz$/){
-    open (IN,"gunzip -c $file |") or die "Couldn't read from file $file: $!\n";
-  }
-  else{
-    open (IN,$file) or die "Couldn't read from file $file: $!\n";
-  }
-
-  if ($skip){
-    warn "Skipping the first $skip reads from $file\n";
-    sleep (1);
-  }
-  if ($upto){
-    warn "Processing reads up to sequence no. $upto from $file\n";
-    sleep (1);
-  }
-
-  my $C_to_T_infile = my $G_to_A_infile = $filename;
-
-  if ($prefix){
-    # warn "Prefixing $prefix:\nold: $C_to_T_infile\nold: $G_to_A_infile\n\n";
-    $C_to_T_infile = "$prefix.$C_to_T_infile";
-    $G_to_A_infile = "$prefix.$G_to_A_infile";
-    # warn "Prefixing $prefix:\nnew: $C_to_T_infile\nnew: $G_to_A_infile\n\n";
-  }
-
-  if ($pbat){ # PBAT-Seq
-    if ($gzip){
-      $G_to_A_infile =~ s/$/_G_to_A.fastq.gz/;
-    }
-    else{
-      $G_to_A_infile =~ s/$/_G_to_A.fastq/;
-    }
-
-    warn "Writing a G -> A converted version of the input file $filename to $temp_dir$G_to_A_infile\n";
-
-    if ($gzip){
-      open (GTOA,"| gzip -c - > ${temp_dir}${G_to_A_infile}") or die "Can't write to file: $!\n";
-    }
-    else{
-      open (GTOA,'>',"$temp_dir$G_to_A_infile") or die "Couldn't write to file $!\n";
-    }
-  }
-  else{ # directional or non-directional
-    if ($gzip){
-      $C_to_T_infile =~ s/$/_C_to_T.fastq.gz/;
-    }
-    else{
-      $C_to_T_infile =~ s/$/_C_to_T.fastq/;
-    }
-
-    warn "Writing a C -> T converted version of the input file $filename to $temp_dir$C_to_T_infile\n";
-
-    if ($gzip){
-      open (CTOT,"| gzip -c - > ${temp_dir}${C_to_T_infile}") or die "Can't write to file: $!\n";
-    }
-    else{
-      open (CTOT,'>',"$temp_dir$C_to_T_infile") or die "Couldn't write to file $!\n"; # uncompressed option
-    }
-
-    unless ($directional){
-      if ($gzip){
-	$G_to_A_infile =~ s/$/_G_to_A.fastq.gz/;
-      }
-      else{
-	$G_to_A_infile =~ s/$/_G_to_A.fastq/;
-      }
-
-      warn "Writing a G -> A converted version of the input file $filename to $temp_dir$G_to_A_infile\n";
-
-      if ($gzip){
-	open (GTOA,"| gzip -c - > ${temp_dir}${G_to_A_infile}") or die "Can't write to file: $!\n";
-      }
-      else{
-	open (GTOA,'>',"$temp_dir$G_to_A_infile") or die "Couldn't write to file $!\n";
-      }
-    }
-  }
-
-  my $count = 0;
-  while (1){
-    my $identifier = <IN>;
-    my $sequence = <IN>;
-    my $identifier2 = <IN>;
-    my $quality_score = <IN>;
-    last unless ($identifier and $sequence and $identifier2 and $quality_score);
-
-    $identifier = fix_IDs($identifier); # this is to avoid problems with truncated read ID when they contain white spaces
-
-    ++$count;
-
-    if ($skip){
-      next unless ($count > $skip);
-    }
-    if ($upto){
-      last if ($count > $upto);
-    }
-
-    $sequence = uc$sequence; # make input file case insensitive
-
-    # detecting if the input file contains tab stops, as this is likely to result in no alignments
-    if (index($identifier,"\t") != -1){
-      $seqID_contains_tabs++;
-    }
-
-    ## small check if the sequence file appears to be a FastQ file
-    if ($count == 1){
-      if ($identifier !~ /^\@/ or $identifier2 !~ /^\+/){
-	die "Input file doesn't seem to be in FastQ format at sequence $count: $!\n";
-      }
-    }
-
-    if ($pbat){
-      my $sequence_G_to_A = $sequence;
-      $sequence_G_to_A =~ tr/G/A/;
-      print GTOA join ('',$identifier,$sequence_G_to_A,$identifier2,$quality_score);
-    }
-    else{ # directional or non-directional
-      my $sequence_C_to_T = $sequence;
-      $sequence_C_to_T =~ tr/C/T/;
-      print CTOT join ('',$identifier,$sequence_C_to_T,$identifier2,$quality_score);
-
-      unless ($directional){
-	my $sequence_G_to_A = $sequence;
-	$sequence_G_to_A =~ tr/G/A/;
-	print GTOA join ('',$identifier,$sequence_G_to_A,$identifier2,$quality_score);
-      }
-    }
-  }
-
-  if ($directional){
-    close CTOT or die "Failed to close filehandle $!\n";
-    warn "\nCreated C -> T converted version of the FastQ file $filename ($count sequences in total)\n\n";
-  }
-  elsif($pbat){
-    warn "\nCreated G -> A converted version of the FastQ file $filename ($count sequences in total)\n\n";
-    close GTOA or die "Failed to close filehandle $!\n";
-    return ($G_to_A_infile);
-  }
-  else{
-    close CTOT or die "Failed to close filehandle $!\n";
-    close GTOA or die "Failed to close filehandle $!\n";
-    warn "\nCreated C -> T as well as G -> A converted versions of the FastQ file $filename ($count sequences in total)\n\n";
-  }
-
-  return ($C_to_T_infile,$G_to_A_infile);
-}
-
-sub biTransformFastQFiles_paired_end {
-  my ($file,$read_number) = @_;
-  my ($dir,$filename);
-
-  if ($file =~ /\//){
-    ($dir,$filename) = $file =~ m/(.*\/)(.*)$/;
-  }
-  else{
-    $filename = $file;
-  }
-
-  ### gzipped version of the infile
-  if ($file =~ /\.gz$/){
-    open (IN,"gunzip -c $file |") or die "Couldn't read from file $file: $!\n";
-  }
-  else{
-    open (IN,$file) or die "Couldn't read from file $file: $!\n";
-  }
-
-  if ($skip){
-    warn "Skipping the first $skip reads from $file\n";
-    sleep (1);
-  }
-  if ($upto){
-    warn "Processing reads up to sequence no. $upto from $file\n";
-    sleep (1);
-  }
-
-  my $C_to_T_infile = my $G_to_A_infile = $filename;
-
-  if ($gzip){
-    $C_to_T_infile =~ s/$/_C_to_T.fastq.gz/;
-    $G_to_A_infile =~ s/$/_G_to_A.fastq.gz/;
-  }
-  else{
-    $C_to_T_infile =~ s/$/_C_to_T.fastq/;
-    $G_to_A_infile =~ s/$/_G_to_A.fastq/;
-  }
-
-  if ($prefix){
-    #  warn "Prefixing $prefix:\nold: $C_to_T_infile\nold: $G_to_A_infile\n\n";
-    $C_to_T_infile = "$prefix.$C_to_T_infile";
-    $G_to_A_infile = "$prefix.$G_to_A_infile";
-    #  warn "Prefixing $prefix:\nnew: $C_to_T_infile\nnew: $G_to_A_infile\n\n";
-  }
-
-  if ($directional){
-    if ($read_number == 1){
-      warn "Writing a C -> T converted version of the input file $filename to $temp_dir$C_to_T_infile\n";
-      if ($gzip){
-	open (CTOT,"| gzip -c - > ${temp_dir}${C_to_T_infile}") or die "Can't write to file: $!\n";
-      }
-      else{
-	open (CTOT,'>',"$temp_dir$C_to_T_infile") or die "Couldn't write to file $!\n";
-      }
-    }
-    elsif ($read_number == 2){
-      warn "Writing a G -> A converted version of the input file $filename to $temp_dir$G_to_A_infile\n";
-      if ($gzip){
-	open (GTOA,"| gzip -c - > ${temp_dir}${G_to_A_infile}") or die "Can't write to file: $!\n";
-      }
-      else{
-	open (GTOA,'>',"$temp_dir$G_to_A_infile") or die "Couldn't write to file $!\n";
-      }
-    }
-    else{
-      die "Read number needs to be 1 or 2, but was $read_number!\n\n";
-    }
-  }
-  else{
-    warn "Writing a C -> T converted version of the input file $filename to $temp_dir$C_to_T_infile\n";
-    warn "Writing a G -> A converted version of the input file $filename to $temp_dir$G_to_A_infile\n";
-    if ($gzip){
-      open (CTOT,"| gzip -c - > ${temp_dir}${C_to_T_infile}") or die "Can't write to file: $!\n";
-      open (GTOA,"| gzip -c - > ${temp_dir}${G_to_A_infile}") or die "Can't write to file: $!\n";
-    }
-    else{
-      open (CTOT,'>',"$temp_dir$C_to_T_infile") or die "Couldn't write to file $!\n";
-      open (GTOA,'>',"$temp_dir$G_to_A_infile") or die "Couldn't write to file $!\n";
-    }
-  }
-
-  my $count = 0;
-  while (1){
-    my $identifier = <IN>;
-    my $sequence = <IN>;
-    my $identifier2 = <IN>;
-    my $quality_score = <IN>;
-    last unless ($identifier and $sequence and $identifier2 and $quality_score);
-    ++$count;
-
-    $identifier = fix_IDs($identifier); # this is to avoid problems with truncated read ID when they contain white spaces
-
-    if ($skip){
-      next unless ($count > $skip);
-    }
-    if ($upto){
-      last if ($count > $upto);
-    }
-
-    $sequence= uc$sequence; # make input file case insensitive
-
-    ## small check if the sequence file appears to be a FastQ file
-    if ($count == 1){
-      if ($identifier !~ /^\@/ or $identifier2 !~ /^\+/){
-	die "Input file doesn't seem to be in FastQ format at sequence $count: $!\n";
-      }
-    }
-    my $sequence_C_to_T = my $sequence_G_to_A = $sequence;
-
-    if ($read_number == 1){
-      if ($bowtie2){
-	$identifier =~ s/$/\/1\/1/;
-      }
-      else{
-	$identifier =~ s/$/\/1/;
-      }
-    }
-    elsif ($read_number == 2){
-      if ($bowtie2){
-	$identifier =~ s/$/\/2\/2/;
-      }
-      else{
-	$identifier =~ s/$/\/2/;
-      }
-    }
-    else{
-      die "Read number needs to be 1 or 2\n";
-    }
-
-    $sequence_C_to_T =~ tr/C/T/;
-    $sequence_G_to_A =~ tr/G/A/;
-
-    if ($directional){
-      if ($read_number == 1){
-	print CTOT join ('',$identifier,$sequence_C_to_T,$identifier2,$quality_score);
-      }
-      else{
-	print GTOA join ('',$identifier,$sequence_G_to_A,$identifier2,$quality_score);
-      }
-    }
-    else{
-      print CTOT join ('',$identifier,$sequence_C_to_T,$identifier2,$quality_score);
-      print GTOA join ('',$identifier,$sequence_G_to_A,$identifier2,$quality_score);
-    }
-  }
-
-  if ($directional){
-    if ($read_number == 1){
-      warn "\nCreated C -> T converted version of the FastQ file $filename ($count sequences in total)\n\n";
-    }
-    else{
-      warn "\nCreated G -> A converted version of the FastQ file $filename ($count sequences in total)\n\n";
-    }
-  }
-  else{
-    warn "\nCreated C -> T as well as G -> A converted versions of the FastQ file $filename ($count sequences in total)\n\n";
-  }
-  if ($directional){
-    if ($read_number == 1){
-      close CTOT or die "Failed to close filehandle $!\n";
-      return ($C_to_T_infile);
-    }
-    else{
-      close GTOA or die "Failed to close filehandle $!\n";
-      return ($G_to_A_infile);
-    }
-  }
-  else{
-    close CTOT or die "Failed to close filehandle $!\n";
-    close GTOA or die "Failed to close filehandle $!\n";
-    return ($C_to_T_infile,$G_to_A_infile);
-  }
-}
-
-
-### SPECIAL BOWTIE 1 PAIRED-END FORMAT FOR GZIPPED OUTPUT FILES
-
-sub biTransformFastQFiles_paired_end_bowtie1_gzip {
-  my ($file_1,$file_2) = @_;
-  my ($dir,$filename);
-
-  if ($file_1 =~ /\//){
-    ($dir,$filename) = $file_1 =~ m/(.*\/)(.*)$/;
-  }
-  else{
-    $filename = $file_1;
-  }
-
-  ### gzipped version of infile 1
-  if ($file_1 =~ /\.gz$/){
-    open (IN_1,"gunzip -c $file_1 |") or die "Couldn't read from file $file_1: $!\n";
-  }
-  else{
-    open (IN_1,$file_1) or die "Couldn't read from file $file_1: $!\n";
-  }
-  ### gzipped version of infile 2
-  if ($file_2 =~ /\.gz$/){
-    open (IN_2,"gunzip -c $file_2 |") or die "Couldn't read from file $file_2: $!\n";
-  }
-  else{
-    open (IN_2,$file_2) or die "Couldn't read from file $file_2: $!\n";
-  }
-
-
-  if ($skip){
-    warn "Skipping the first $skip reads from $file_1 and $file_2\n";
-    sleep (1);
-  }
-  if ($upto){
-    warn "Processing reads up to sequence no. $upto from $file_1 and $file_2\n";
-    sleep (1);
-  }
-
-  my $CT_plus_GA_infile = my $GA_plus_CT_infile = $filename;
-
-  if ($prefix){
-    # warn "Prefixing $prefix:\nold: $CT_plus_GA_infile\nold: $GA_plus_CT_infile\n\n";
-    $CT_plus_GA_infile = "$prefix.$CT_plus_GA_infile";
-    $GA_plus_CT_infile = "$prefix.$GA_plus_CT_infile";
-    # warn "Prefixing $prefix:\nnew: $CT_plus_GA_infile\nnew: $GA_plus_CT_infile\n\n";
-  }
-
-  $CT_plus_GA_infile =~ s/$/.CT_plus_GA.fastq.gz/;
-  $GA_plus_CT_infile =~ s/$/.GA_plus_CT.fastq.gz/;
-  # warn "Prefixing $prefix:\nnew: $CT_plus_GA_infile\nnew: $GA_plus_CT_infile\n\n";
-
-  warn "Writing a C -> T converted version of $file_1 and a G -> A converted version of $file_2 to $temp_dir$CT_plus_GA_infile\n";
-  open (CTPLUSGA,"| gzip -c - > ${temp_dir}${CT_plus_GA_infile}") or die "Can't write to file: $!\n";
-  # open (CTPLUSGA,'>',"$temp_dir$CT_plus_GA_infile") or die "Couldn't write to file $!\n";
-
-  unless ($directional){
-    print "Writing a G -> A converted version of $file_1 and a C -> T converted version of $file_2 to $temp_dir$GA_plus_CT_infile\n";
-    open (GAPLUSCT,"| gzip -c - > ${temp_dir}${GA_plus_CT_infile}") or die "Can't write to file: $!\n";
-  }
-
-  ### for Bowtie 1 we need to write a single gzipped file with 1 line per pair of sequences in the the following format:
-  ### <seq-ID>     <sequence #1 mate>     <quality #1 mate>     <sequence #2 mate>     <quality #2 mate>
-
-  my $count = 0;
-  while (1){
-    my $identifier_1 = <IN_1>;
-    my $sequence_1 = <IN_1>;
-    my $identifier2_1 = <IN_1>;
-    my $quality_score_1 = <IN_1>;
-
-    my $identifier_2 = <IN_2>;
-    my $sequence_2 = <IN_2>;
-    my $identifier2_2 = <IN_2>;
-    my $quality_score_2 = <IN_2>;
-
-    last unless ($identifier_1 and $sequence_1 and $identifier2_1 and $quality_score_1 and $identifier_2 and $sequence_2 and $identifier2_2 and $quality_score_2);
-
-    ++$count;
-
-    ## small check if the sequence file appears to be a FastQ file
-    if ($count == 1){
-      if ($identifier_1 !~ /^\@/ or $identifier2_1 !~ /^\+/){
-	die "Input file 1 doesn't seem to be in FastQ format at sequence $count: $!\n";
-      }
-      if ($identifier_2 !~ /^\@/ or $identifier2_2 !~ /^\+/){
-	die "Input file 2 doesn't seem to be in FastQ format at sequence $count: $!\n";
-      }
-    }
-
-    $identifier_1 = fix_IDs($identifier_1); # this is to avoid problems with truncated read ID when they contain white spaces
-    chomp $identifier_1;
-    chomp $sequence_1;
-    chomp $sequence_2;
-    chomp $quality_score_1;
-    chomp $quality_score_2;
-
-    $identifier_1 =~ s/^\@//;
-    $identifier_1 =~ s/$/\/1/; #adding an extra /1 to the end which is being removed by Bowtie otherwise (which leads to no sequences alignments whatsoever)
-
-    if ($skip){
-      next unless ($count > $skip);
-    }
-    if ($upto){
-      last if ($count > $upto);
-    }
-
-    $sequence_1 = uc$sequence_1; # make input file 1 case insensitive
-    $sequence_2 = uc$sequence_2; # make input file 2 case insensitive
-
-    # print "$identifier_1\t$sequence_1\t$quality_score_1\t$sequence_2\t$quality_score_2\n";
-    my $sequence_1_C_to_T = $sequence_1;
-    my $sequence_2_G_to_A = $sequence_2;
-    $sequence_1_C_to_T =~ tr/C/T/;
-    $sequence_2_G_to_A =~ tr/G/A/;
-
-    print CTPLUSGA "$identifier_1\t$sequence_1_C_to_T\t$quality_score_1\t$sequence_2_G_to_A\t$quality_score_2\n";
-
-    unless ($directional){
-      my $sequence_1_G_to_A = $sequence_1;
-      my $sequence_2_C_to_T = $sequence_2;
-      $sequence_1_G_to_A =~ tr/G/A/;
-      $sequence_2_C_to_T =~ tr/C/T/;
-      print GAPLUSCT "$identifier_1\t$sequence_1_G_to_A\t$quality_score_1\t$sequence_2_C_to_T\t$quality_score_2\n";
-    }
-  }
-
-  close CTPLUSGA or die "Couldn't close filehandle\n";
-  warn "\nCreated C -> T converted version of FastQ file '$file_1' and G -> A converted version of FastQ file '$file_2' ($count sequences in total)\n";
-
-  if ($directional){
-    warn "\n";
-    return ($CT_plus_GA_infile);
-  }
-  else{
-    close GAPLUSCT or die "Couldn't close filehandle\n";
-    warn "Created G -> A converted version of FastQ file '$file_1' and C -> T converted version of FastQ file '$file_2' ($count sequences in total)\n\n";
-    return ($CT_plus_GA_infile,$GA_plus_CT_infile);
-  }
-}
-
-
-sub fix_IDs{
-  my $id = shift;
-  $id =~ s/[ \t]+/_/g; # replace spaces or tabs with underscores
-  return $id;
-}
-
-sub ensure_sensical_alignment_orientation_single_end{
-  my $index = shift; # index number if the sequence produced an alignment
-  my $strand = shift;
-  ###  setting $orientation to 1 if it is in the correct orientation, and leave it 0 if it is the nonsensical wrong one
-  my $orientation = 0;
-  ##############################################################################################################
-  ## FORWARD converted read against FORWARD converted genome (read: C->T.....C->T..      genome:C->T.......C->T)
-  ## here we only want reads in the forward (+) orientation
-  if ($fhs[$index]->{name} eq 'CTreadCTgenome') {
-    ### if the alignment is (+) we count it, and return 1 for a correct orientation
-    if ($strand eq '+') {
-      $fhs[$index]->{seen}++;