<!DOCTYPE html>
<html>
    <head>
        <title>MicroHapulator Report</title>
        <link rel="stylesheet" href="assets/bootstrap.min.css" media="screen">
        <script src="assets/jquery.min.js"></script>
        <script src="assets/jquery-ui.min.js"></script>
        <script src="assets/fancyTable.js"></script>
        <style type="text/css">
            h2 {
                margin-top: 50px;
            }
            .container {
                max-width: 750px;
                padding-top: 100px;
            }
            .alnrt {
                text-align: right;
            }
            p.caption {
                color: #666666;
                font-size: small;
                margin: 0 auto 30px auto;
                text-align: center;
                width: 85%;
            }
            p.title {
                color: #666666;
                font-size: small;
                margin: 30px auto -10px auto;
                text-align: center;
                width: 85%;
            }
            img {
                margin: 10px auto;
                width: 48%;
            }
            img.small {
                width: 24.5%;
            }
            img.center {
                display: block;
                margin-left: auto;
                margin-right: auto;
            }
            .fullwidth {
                width: 100%;
            }
            table {
                margin: 12pt auto;
                width: 100%;
            }
            .scrollwrapper {
                overflow-x: auto;
                margin-bottom: 30px;
            }
            table.half {
                margin: 12pt auto 12pt auto;
                width: 50%;
            }
            td, th {
                padding-right: 10px;
                white-space: nowrap;
            }

            blockquote p {
                font-size: small;
            }

            blockquote h3 {
                margin-top: 0;
            }

            ::-webkit-scrollbar {
                width: 5px;
                height: 5px;
            }

            ::-webkit-scrollbar-thumb {
                background: gray;
                border-radius: 10px;
            }
            ::-webkit-scrollbar-track{
                -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.3);
                border-radius: 10px;
                background-color: #F5F5F5;
            }
        </style>
    </head>
    <body>
        <div class="container">
            <h1>MicroHapulator Report</h1>
            <p>
                Report generated at {{date}},<br />
                using <a href="https://microhapulator.readthedocs.io" target="_blank">MicroHapulator</a> version {{mhpl8rversion}}.
            </p>

            <h2>Table of Contents</h2>
            <ol>
                {% block table_of_contents %}
                {% endblock %}
            </ol>
            <p>
                The data and statistics from which this report is populated are available in their entirety in the MicroHapulator working directory.
                Per-sample results and full-resolution graphics are available in each <code>analysis/{samplename}</code> subdirectory in the working directory.
                The entire working directory is large and not convenient for sharing.
                Accordingly, graphics, JavaScript, and CSS assets are copied to the <code>report/</code> directory, which can then be compressed in a ZIP archive that should be better suited for e.g. email transfer.
            </p>

            <a name="readqc"></a>
            <h2>Read QA/QC</h2>
            <p>
                QC reports for the input reads are generated using <a href="https://www.bioinformatics.babraham.ac.uk/projects/fastqc/" target="_blank">FastQC</a> and compiled into a single report with <a href="https://multiqc.info/" target="_blank">MultiQC</a>.
                A link to the MultiQC report is provided below.
            </p>
            <blockquote>
                <p>
                    <strong>NOTE</strong>: FastQC was designed for QC of whole-genome shotgun NGS reads prior to genome asssembly.
                    A QC warning or failure for some modules (such as per-base sequence content or sequence duplication levels) may or may not be a concern with MH reads.
                    Interpret results with care!
                </p>
            </blockquote>
            <p><a href="analysis/multiqc_report.html",  target="_blank">Click here to open MultiQC report in a new tab</a></p>

            {% if read_length_table is none %}
                {% block read_len_fig %}
                {% endblock %}
            {% else %}
                {% block read_len_table %}
                {% endblock %}
            {% endif %}

            {% block read_filter_stats %}
            {% endblock %}

            {% block read_merge_stats %}
            {% endblock %}

            <a name="readmapping"></a>
            <h2>Read Mapping</h2>
            {% block read_map_header %}
            {% endblock %}
            <p class="title"><strong>Table 3.1</strong>: Read mapping metrics.</p>
            <table>
                <tr>
                    <th>Sample</th>
                    <th class="alnrt">Filtered Reads</th>
                    <th class="alnrt">Mapped Reads</th>
                    <th class="alnrt">Mapping Rate</th>
                    <th class="alnrt">Chi-square</th>
                </tr>
                {% for sample, stats in mapping_summary.items() %}
                <tr>
                    <td>{{ sample }}</td>
                    <td class="alnrt">{{ stats.total_reads }}</td>
                    <td class="alnrt">{{ stats.mapped_reads }}</td>
                    <td class="alnrt">{{ stats.mapping_rate }}</td>
                    <td class="alnrt">{{ stats.chi_square }}</td>
                </tr>
                {% endfor %}
            </table>
            <br />
            <p>
                The reported chi-square statistic is a measure of read coverage imbalance between markers, and can be compared among samples sequenced using the sample panel:
                the minimum value of 0 represents perfectly uniform coverage across markers, while the maximum value of D occurs when all reads map to a single marker (D represents the degrees of freedom, or the number of markers minus 1).
                A visual representation of interlocus balance is shown in <strong>Figure 3.4</strong>.
            </p>
            <p>Using mapping information, each read is assigned to one of four categories as follows.</p>
            <ul>
                <li><strong>On-target</strong>: read maps only to the expected MH loci</li>
                <li><strong>Off-target</strong>: read maps to the human reference genome, but not to any expected MH loci</li>
                <li><strong>Contaminant</strong>: read does not map to the human reference genome</li>
                <li><strong>Repetitive</strong>: read maps to the expected MH loci, but also (preferentially) to other locations in the human reference genome</li>
            </ul>
            <img class="fullwidth" src="img/read-mapping-qc.png" />
            <p class="caption"><strong>Figure 3.2</strong>: Bar graph showing the number of reads for each sample, broken down into four categories: on-target, off-target, contaminant, and repetitive.</p>
            <p class="title">
                <strong>Table 3.3</strong>: The total number of reads mapped to each marker, and the subset of those reads marked as repetitive, broken down by sample.
                Table columns are sortable, and marker names link to a marker detail page.
            </p>
            <div class="scrollwrapper">
                <table id="mapping_rates_table" class="pagination_table">
                    <thead>
                        <tr>
                            <td></td>
                            {% for sample in samples %}
                            <td style="visibility: collapse;">{{sample}}</td>
                            <td style="font-weight:bold">{{sample}}</td>
                            {% endfor %}
                        </tr>
                        <tr>
                            <th>Marker</th>
                            {% for sample in samples %}
                            <th class="alnrt" style="font-weight:bold" data-sortas="numeric">Reads</th>
                            <th class="alnrt" style="font-weight:bold" data-sortas="numeric">Repetitive</th>
                            {% endfor %}
                            <td></td>
                        </tr>
                    </thead>
                    <tbody>
                        {% for marker, marker_data in repetitive_reads_by_marker.items() %}
                        <tr>
                            <td><a href="marker-detail-report.html?marker={{marker}}" target="_blank">{{marker}}</a></td>
                            {% for sample in samples %}
                            <td class="alnrt" data-sortvalue="{{ marker_data[sample].mapped }}">{{ "{:,d}".format(marker_data[sample].mapped) }}</td>
                            <td class="alnrt" data-sortvalue="{{ marker_data[sample].repetitive }}">{{ "{:,d}".format(marker_data[sample].repetitive) }}</td>
                            {% endfor %}
                        </tr>
                        {% endfor %}
                    </tbody>
                </table>
            </div>

            {% for sample in samples %}
            <img src="img/{{sample}}-interlocus-balance.png" />
            {% endfor %}
            <p class="caption"><strong>Figure 3.4</strong>: Histograms showing the interlocus balance for each sample.</p>

            <a name="typing"></a>
            <h2>Haplotype Calling</h2>
            <p>
                Haplotypes are called empirically using <code>mhpl8r type</code> as follows.
                MicroHapulator examines each aligned read to determine its suitability for haplotype calling: this is a <em>typing event</em>.
                If the read alignment spans all SNPs of interest, the typing event is successful and a haplotype call is made.
                If not, the typing event is failed and no haplotype call is made.
                (<em>Note that if more than one marker is defined at a given locus, MicroHapulator can attempt multiple typing events per read.
                In this case the number of <strong>Attempted Typing Events</strong> will exceed the number of <strong>Mapped Reads</strong>.</em>)
                Collectively, the tallies of each observed haplotype represent a typing result for each sample.
                The typing rate is calculated as the number of successful typing events divided by the total number of attempted typing events.
            </p>
            <p class="title"><strong>Table 4.1</strong>: Read typing metrics.</p>
            <table>
                <tr>
                    <th>Sample</th>
                    <th class="alnrt">Mapped Reads</th>
                    <th class="alnrt">Attempted Typing Events</th>
                    <th class="alnrt">Successful Typing Events</th>
                    <th class="alnrt">Typing Success Rate</th>
                </tr>
                {% for sample, stats in typing_summary.items() %}
                <tr>
                    <td>{{ sample }}</td>
                    <td class="alnrt">{{ mapping_summary[sample].mapped_reads }}</td>
                    <td class="alnrt">{{ stats.attempted }}</td>
                    <td class="alnrt">{{ stats.successful }}</td>
                    <td class="alnrt">{{ stats.typing_rate }}</td>
                </tr>
                {% endfor %}
            </table>
            <p class="title">
                <strong>Table 4.2</strong>: Typing rate of each individual marker, broken down by sample.
                Table columns are sortable, and marker names link to a marker detail page.
            </p>
            <div class="scrollwrapper">
                <table id="typing_rates_table" class="pagination_table">
                    <thead>
                        <tr>
                            <th>Marker</th>
                            {% for sample in typing_summary.keys() %}
                            <th class=alnrt style="font-weight:bold">{{sample}}</th>
                            {% endfor %}
                        </tr>
                    </thead>
                    <tbody>
                        {% for markername in markernames %}
                        <tr>
                            <td><a href="marker-detail-report.html?marker={{markername}}" target="_blank">{{ markername }}</a></td>
                            {% for summary in typing_summary.values() %}
                            <td class="alnrt" data-sortvalue="{{ summary.marker_typing_rate(markername) }}">{{ summary.marker_typing_rate(markername) }}%</td>
                            {% endfor %}
                        </tr>
                        {% endfor %}
                    </tbody>
                </table>
            </div>
            {% if typing_summary.has_high_discard_markers %}
            <p class="title">
                <strong>Table 4.3</strong>: The following markers contain a large proportion of discarded reads (untyped reads that do not span all SNPs at the locus).
                Markers with &gt;{{ "{:.1f}".format(discard_alert_threshold * 100) }}% discarded reads are shown here—this behavior can be configured with the <code>--discard-alert</code> option (e.g. <code>--discard-alert={{ discard_alert_threshold }}</code>).
            </p>
            <div class="scrollwrapper">
                <table id="discard_rates_table" class="pagination_table">
                    <thead>
                        <tr>
                            <th>Marker</th>
                            <th>Sample</th>
                            <th class="alnrt">Discarded Reads</th>
                            <th class="alnrt">Total Reads</th>
                            <th class="alnrt">% Reads Discarded</th>
                        </tr>
                    </thead>
                    <tbody>
                        {% for n, row in typing_summary.high_discard_markers.iterrows() %}
                        <tr>
                            <td><a href="marker-detail-report.html?marker={{marker}}" target="_blank">{{ row.Marker }}</a></td>
                            <td>{{ row.Sample }}</td>
                            <td class="alnrt">{{ "{:,d}".format(row.TotalReads - row.TypedReads) }}</td>
                            <td class="alnrt">{{ "{:,d}".format(row.TotalReads) }}</td>
                            <td class="alnrt">{{ "{:.1f}".format(row.DiscardRate * 100) }}%</td>
                        </tr>
                        {% endfor %}
                    </tbody>
                </table>
            </div>
            {% endif %}
            {% if typing_summary.has_high_gap_markers %}
            <p class="title">
                <strong>Table 4.4</strong>: The following markers contain a large proportion of reads with gap alleles (reads with alignment gaps spanning one or more SNPs at the locus).
                Markers with &gt;{{ "{:.1f}".format(gap_alert_threshold * 100) }}% discarded reads are shown here—this behavior can be configured with the <code>--gap-alert</code> option (e.g. <code>--gap-alert={{ gap_alert_threshold }}</code>).
            </p>
            <div class="scrollwrapper">
                <table id="gap_rates_table" class="pagination_table">
                    <thead>
                        <tr>
                            <th>Marker</th>
                            <th>Sample</th>
                            <th class="alnrt">Reads Containing Gaps</th>
                            <th class="alnrt">Typed Reads</th>
                            <th class="alnrt">% Gapped Reads</th>
                        </tr>
                    </thead>
                    <tbody>
                        {% for n, row in typing_summary.high_gap_markers.iterrows() %}
                        <tr>
                            <td><a href="marker-detail-report.html?marker={{marker}}" target="_blank">{{ row.Marker }}</a></td>
                            <td>{{ row.Sample }}</td>
                            <td class="alnrt">{{ "{:,d}".format(row.GappedReads) }}</td>
                            <td class="alnrt">{{ "{:,d}".format(row.TypedReads) }}</td>
                            <td class="alnrt">{{ "{:.1f}".format(row.GappedRate * 100) }}%</td>
                        </tr>
                        {% endfor %}
                    </tbody>
                </table>
            </div>
            {% endif %}

            <a name="filters"></a>
            <h2>Genotype Calling</h2>
            <p>
                Two types of thresholds are applied to each typing result using <code>mhpl8r filter</code> to discriminate between true MH alleles (haplotypes) and false alleles resulting from sequencing error or other artifacts.
                A static detection threshold, based on a fixed number of reads, is used to filter out low-level noise.
                A dynamic analytical threshold, based on a percentage of the total reads at the locus (after removing alleles that fail the detection threshold), accounts for fluctuations in the depth of coverage between loci, samples, and runs, and can filter out higher-level noise in most cases.
                The haplotype tallies, after all filters have been applied, represents the <em>genotype call</em> for that sample.
            </p>
            <p class="title">
                <strong>Table 5.1</strong>: Detection thresholds and analytical thresholds for each marker.
                Table columns are sortable, and marker names link to a marker detail page.
            </p>
            <table class="half pagination_table">
                <thead>
                    <tr>
                        <th>Marker</th>
                        <th class="alnrt">Detection</th>
                        <th class="alnrt">Analytical</th>
                    </tr>
                </thead>
                <tbody>
                    {% for marker in markernames %}
                    <tr>
                        <td><a href="marker-detail-report.html?marker={{marker}}" target="_blank">{{ marker }}</a></td>
                        <td class="alnrt" data-sortvalue="{{ thresholds.get(marker)[0] }}">{{ thresholds.get(marker)[0] }}</td>
                        <td class="alnrt" data-sortvalue="{{ thresholds.get(marker)[1] }}">{{ "{:.1f}".format(thresholds.get(marker)[1] * 100) }}%</td>
                    </tr>
                    {% endfor %}
                </tbody>
            </table>
            <hr />
            <p>
                For single-source samples, we expect the two alleles at heterozygous loci to have roughly even abundance.
                The following plots show the <em>relative</em> abundance of the major and minor allele for each marker with a heterozygous genotype (markers are sorted by absolute combined abundance, which is printed above each pair of allele counts).
                For known DNA mixtures, these plots can be safely ignored.
                But for suspected single-source samples, if there is substantial imbalance between major and minor allele counts at numerous loci, the sample should be examined more closely for the presence of a minor DNA contributor.
            </p>
            {% for sample in samples %}
            <img src="img/{{sample}}-heterozygote-balance.png" class="fullwidth" />
            {% endfor %}
            <p class="caption"><strong>Figure 5.2</strong>: Bar graphs showing heterozygote balance for all samples.</p>
        </div>
    </body>
    <script type="text/javascript">
        $(".pagination_table").fancyTable({
            sortColumn: 0,
            pagination: true,
            perPage: 15,
            globalSearch: true,
            sortable: true,
            globalSearchExcludeColumns: [2, 3, 4, 5, 6, 7, 8, 9],
        });
    </script>
</html>
