<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="author" content="Joe Brown - Base2 Genomics" />
    <title>covviz - Base2 Genomics</title>
    <script type="text/javascript" src="https://code.jquery.com/jquery-3.3.1.js"></script>
    <script type="text/javascript" src="https://cdn.datatables.net/v/bs4/dt-1.10.18/sl-1.3.0/datatables.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/selectize.js/0.12.6/js/standalone/selectize.min.js"></script>
    <script type="text/javascript" src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>
    <script type="text/javascript" src="https://cdn.plot.ly/plotly-latest.min.js"></script>
    <link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/v/bs4/dt-1.10.18/sl-1.3.0/datatables.min.css"/>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/selectize.js/0.12.6/css/selectize.bootstrap3.min.css">
    <link rel="stylesheet" type="text/css" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
    <style type="text/css">
    .disabled_div {pointer-events: none; opacity: 0.4}
    tr.selected {background-color: rgba(161,234,247,0.5) !important; color: black !important}
    .tab-content > .tab-pane:not(.active),
    .pill-content > .pill-pane:not(.active) {display: block; height: 0; overflow-y: hidden;}
    .nav-pills .nav-link.active, .nav-pills .show > .nav-link {background-color: #6c757d !important;}
    .form-control.selectize-control {padding: 0px 0px 0px;}
    .selectize-input {min-height: 38px !important; padding: 7px 12px !important;}
    .remove-single {color: gray !important; top: -1px !important; font-size: 20px !important;}    </style>
</head>
<body>
    <nav class="navbar navbar-dark navbar-expand-md p-0" style="background-color: #3C444C;">
        <a class="navbar-brand m-0 p-1 text-light"><img class="pr-4" src='data:image/png;base64, ' alt="" height="58">
        </a>
        <div class="collapse navbar-collapse">
            <ul class="nav nav-pills" role="tablist">
                <li class="nav-item">
                    <a class="nav-link text-white active" data-toggle="tab" role="tab" href="#chrom_coverage" aria-controls="chrom_coverage" aria-selected="true">Chromosome Coverage</a>
                </li>
                <li class="nav-item" id="global_qc_nav" hidden>
                    <a class="nav-link text-white" data-toggle="tab" role="tab" href="#global_qc" aria-controls="global_qc" aria-selected="false">Global QC</a>
                </li>
            </ul>
        </div>
        <span class="navbar-brand mb-0 h1">covviz report</span>
    </nav>
    <div class="container-fluid w-90 pt-3">
        <div class="tab-content border-bottom">
            <div class="tab-pane fade show active" id="chrom_coverage" role="tabpanel" aria-labelledby="scaled_tab">
                <div class="row">
                    <div class="col-12" id="chrom_selector_div">
                        <div id="chrom_selector" class="btn-group btn-group-toggle d-flex justify-content-center flex-wrap" data-toggle="buttons">
                            <div class="input-group-prepend">
                                <span class="input-group-text">Chromosome:</span>
                            </div>
                        </div>
                    </div>
                    <div class="col-2" id="gene_search_div" hidden>
                        <div class="input-group">
                            <input type="text" class="form-control" id="gene-search" aria-label="gene-search">
                        </div>
                    </div>
                </div>
                <ul class="nav nav-tabs pt-3" role="tablist">
                    <li class="nav-item">
                        <a class="nav-link active text-secondary" id="scaled_tab" data-toggle="tab" href="#scaled" role="tab" aria-controls="scaled" aria-selected="true">Scaled chromosome coverage</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link text-secondary" id="cov_tab" data-toggle="tab" href="#cov" role="tab" aria-controls="cov" aria-selected="false">Proportions covered</a>
                    </li>
                </ul>
                <div class="tab-content border-bottom">
                    <div class="tab-pane fade show active mb-3" id="scaled" role="tabpanel" aria-labelledby="scaled_tab">
                        <div style="height:600px" id="scaled_plot_placeholder">
                            <div class="mt-3 d-flex justify-content-center align-items-center bg-light text-muted h-100">
                                <div class="d-flex flex-column">
                                    <div>
                                        Loading...
                                    </div>
                                </div>
                            </div>
                        </div>
                        <div class="row pt-3 mb-3" id="scaled_plot" hidden></div>
                    </div>
                    <div class="tab-pane fade mb-3" id="cov" role="tabpanel" aria-labelledby="cov_tab">
                        <div style="height:600px" id="cov_plot_placeholder">
                            <div class="mt-3 d-flex justify-content-center align-items-center bg-light text-muted h-100">
                                <div class="d-flex flex-column">
                                    <div>
                                        Loading...
                                    </div>
                                </div>
                            </div>
                        </div>
                        <div class="row pt-3 mb-3" id="cov_plot" hidden></div>
                    </div>
                </div>
            </div>
            <div class="tab-pane fade" id="global_qc" role="tabpanel" aria-labelledby="global_qc">
                <div id="global_qc_plots" class="container-fluid w-90">
                    <div class="row border-bottom">
                        <div class="col-6">
                            <h4>Inferred sex</h4>
                        </div>
                        <div class="col-6">
                            <h4>Problematic low and non-uniform coverage bins</h4>
                        </div>
                    </div>
                    <div class="row">
                        <div id="inferred_sex" class="col-6"></div>
                        <div id="bin_counts" class="col-6"></div>
                    </div>
                </div>
            </div>
        </div>
        <div class="row pt-3 pb-3">
            <div class="col-12">
                <table id="ped_table" class="table table-hover pb-3 display nowrap" width="100%"></table>
            </div>
        </div>
    </div>
</body>

<script>
// MIT License

// Copyright (c) 2013 pieroxy

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
var LZString=function(){function o(o,r){if(!t[o]){t[o]={};for(var n=0;n<o.length;n++)t[o][o.charAt(n)]=n}return t[o][r]}var r=String.fromCharCode,n="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",e="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-$",t={},i={compressToBase64:function(o){if(null==o)return"";var r=i._compress(o,6,function(o){return n.charAt(o)});switch(r.length%4){default:case 0:return r;case 1:return r+"===";case 2:return r+"==";case 3:return r+"="}},decompressFromBase64:function(r){return null==r?"":""==r?null:i._decompress(r.length,32,function(e){return o(n,r.charAt(e))})},compressToUTF16:function(o){return null==o?"":i._compress(o,15,function(o){return r(o+32)})+" "},decompressFromUTF16:function(o){return null==o?"":""==o?null:i._decompress(o.length,16384,function(r){return o.charCodeAt(r)-32})},compressToUint8Array:function(o){for(var r=i.compress(o),n=new Uint8Array(2*r.length),e=0,t=r.length;t>e;e++){var s=r.charCodeAt(e);n[2*e]=s>>>8,n[2*e+1]=s%256}return n},decompressFromUint8Array:function(o){if(null===o||void 0===o)return i.decompress(o);for(var n=new Array(o.length/2),e=0,t=n.length;t>e;e++)n[e]=256*o[2*e]+o[2*e+1];var s=[];return n.forEach(function(o){s.push(r(o))}),i.decompress(s.join(""))},compressToEncodedURIComponent:function(o){return null==o?"":i._compress(o,6,function(o){return e.charAt(o)})},decompressFromEncodedURIComponent:function(r){return null==r?"":""==r?null:(r=r.replace(/ /g,"+"),i._decompress(r.length,32,function(n){return o(e,r.charAt(n))}))},compress:function(o){return i._compress(o,16,function(o){return r(o)})},_compress:function(o,r,n){if(null==o)return"";var e,t,i,s={},p={},u="",c="",a="",l=2,f=3,h=2,d=[],m=0,v=0;for(i=0;i<o.length;i+=1)if(u=o.charAt(i),Object.prototype.hasOwnProperty.call(s,u)||(s[u]=f++,p[u]=!0),c=a+u,Object.prototype.hasOwnProperty.call(s,c))a=c;else{if(Object.prototype.hasOwnProperty.call(p,a)){if(a.charCodeAt(0)<256){for(e=0;h>e;e++)m<<=1,v==r-1?(v=0,d.push(n(m)),m=0):v++;for(t=a.charCodeAt(0),e=0;8>e;e++)m=m<<1|1&t,v==r-1?(v=0,d.push(n(m)),m=0):v++,t>>=1}else{for(t=1,e=0;h>e;e++)m=m<<1|t,v==r-1?(v=0,d.push(n(m)),m=0):v++,t=0;for(t=a.charCodeAt(0),e=0;16>e;e++)m=m<<1|1&t,v==r-1?(v=0,d.push(n(m)),m=0):v++,t>>=1}l--,0==l&&(l=Math.pow(2,h),h++),delete p[a]}else for(t=s[a],e=0;h>e;e++)m=m<<1|1&t,v==r-1?(v=0,d.push(n(m)),m=0):v++,t>>=1;l--,0==l&&(l=Math.pow(2,h),h++),s[c]=f++,a=String(u)}if(""!==a){if(Object.prototype.hasOwnProperty.call(p,a)){if(a.charCodeAt(0)<256){for(e=0;h>e;e++)m<<=1,v==r-1?(v=0,d.push(n(m)),m=0):v++;for(t=a.charCodeAt(0),e=0;8>e;e++)m=m<<1|1&t,v==r-1?(v=0,d.push(n(m)),m=0):v++,t>>=1}else{for(t=1,e=0;h>e;e++)m=m<<1|t,v==r-1?(v=0,d.push(n(m)),m=0):v++,t=0;for(t=a.charCodeAt(0),e=0;16>e;e++)m=m<<1|1&t,v==r-1?(v=0,d.push(n(m)),m=0):v++,t>>=1}l--,0==l&&(l=Math.pow(2,h),h++),delete p[a]}else for(t=s[a],e=0;h>e;e++)m=m<<1|1&t,v==r-1?(v=0,d.push(n(m)),m=0):v++,t>>=1;l--,0==l&&(l=Math.pow(2,h),h++)}for(t=2,e=0;h>e;e++)m=m<<1|1&t,v==r-1?(v=0,d.push(n(m)),m=0):v++,t>>=1;for(;;){if(m<<=1,v==r-1){d.push(n(m));break}v++}return d.join("")},decompress:function(o){return null==o?"":""==o?null:i._decompress(o.length,32768,function(r){return o.charCodeAt(r)})},_decompress:function(o,n,e){var t,i,s,p,u,c,a,l,f=[],h=4,d=4,m=3,v="",w=[],A={val:e(0),position:n,index:1};for(i=0;3>i;i+=1)f[i]=i;for(p=0,c=Math.pow(2,2),a=1;a!=c;)u=A.val&A.position,A.position>>=1,0==A.position&&(A.position=n,A.val=e(A.index++)),p|=(u>0?1:0)*a,a<<=1;switch(t=p){case 0:for(p=0,c=Math.pow(2,8),a=1;a!=c;)u=A.val&A.position,A.position>>=1,0==A.position&&(A.position=n,A.val=e(A.index++)),p|=(u>0?1:0)*a,a<<=1;l=r(p);break;case 1:for(p=0,c=Math.pow(2,16),a=1;a!=c;)u=A.val&A.position,A.position>>=1,0==A.position&&(A.position=n,A.val=e(A.index++)),p|=(u>0?1:0)*a,a<<=1;l=r(p);break;case 2:return""}for(f[3]=l,s=l,w.push(l);;){if(A.index>o)return"";for(p=0,c=Math.pow(2,m),a=1;a!=c;)u=A.val&A.position,A.position>>=1,0==A.position&&(A.position=n,A.val=e(A.index++)),p|=(u>0?1:0)*a,a<<=1;switch(l=p){case 0:for(p=0,c=Math.pow(2,8),a=1;a!=c;)u=A.val&A.position,A.position>>=1,0==A.position&&(A.position=n,A.val=e(A.index++)),p|=(u>0?1:0)*a,a<<=1;f[d++]=r(p),l=d-1,h--;break;case 1:for(p=0,c=Math.pow(2,16),a=1;a!=c;)u=A.val&A.position,A.position>>=1,0==A.position&&(A.position=n,A.val=e(A.index++)),p|=(u>0?1:0)*a,a<<=1;f[d++]=r(p),l=d-1,h--;break;case 2:return w.join("")}if(0==h&&(h=Math.pow(2,m),m++),f[l])v=f[l];else{if(l!==d)return null;v=s+s.charAt(0)}w.push(v),f[d++]=s+v.charAt(0),h--,s=v,0==h&&(h=Math.pow(2,m),m++)}}};return i}();"function"==typeof define&&define.amd?define(function(){return LZString}):"undefined"!=typeof module&&null!=module&&(module.exports=LZString);
</script>

<script>
const compressed_data = "{{data}}"
const data = JSON.parse(LZString.decompressFromBase64(compressed_data))
const sample_column = data.sample_column
const cov_color = 'rgba(108,117,125,0.2)'
// const highlight_color = 'rgb(255,147,0)'
const cov_layout = {
    title: "",
    margin: {t: 10, b: 40},
    height: 600,
    xaxis: {title: "Scaled Coverage", showgrid: false, range: [0, 1.5]},
    yaxis: {title: "Proportion of Regions Covered", range: [0, 1.]},
    hovermode: "closest",
    showlegend: false,
}
const scaled_layout = {
    title: "",
    margin: {t: 10, b: 40},
    height: 600,
    xaxis: {title: "Position", rangeslider: {}, autorange: true, showgrid: false, showlines: false, zeroline: false},
    yaxis: {title: "Scaled Coverage", fixedrange: true, domain: [0, 3], showgrid: true, showticklabels: true, tickvals: [0, 1, 2, 3], zeroline: false},
    hovermode: "closest",
    showlegend: false,
}
var ped = false
var cov_traces = []
var scaled_traces = []
var scatter_point_color = 'rgba(31,120,180,0.5)'
var scatter_point_color_light = 'rgba(255,255,255,0.1)'
var gene_search_obj

const load_buttons = (arr) => {
    var btngrp = document.getElementById("chrom_selector");
    for (var i = 0; i < arr.length; i++) {
        if (i == 0) {
            btngrp.insertAdjacentHTML('beforeend', '<label class="btn btn-secondary active" id="chrbtn' + arr[i] + '"><input type="radio" name="options" data-name="' + arr[i] + '" autocomplete="off" id="chrinp' + arr[i] + '" checked="true"> ' + arr[i] + ' </label>')
        } else {
            btngrp.insertAdjacentHTML('beforeend', '<label class="btn btn-secondary" id="chrbtn' + arr[i] + '"><input type="radio" name="options" data-name="' + arr[i] + '" autocomplete="off" id="chrinp' + arr[i] + '"> ' + arr[i] + ' </label>')
        }
    }
    let chr = $('#chrom_selector input:radio:checked').data('name')
    build_gene_search()
    build_cov(chr)
    build_scaled(chr)
}

const build_cov = (chr) => {
    // hide the placeholder
    $('#cov_plot_placeholder').prop('hidden', true)
    // show the plot
    $('#cov_plot').prop('hidden', false)
    cov_layout.xaxis.range = [0, 1.5]
    cov_layout.yaxis.range = [0, 1.]
    cov_traces = data["roc"][chr]

    let cov_plot = document.getElementById("cov_plot")
    Plotly.react(cov_plot, cov_traces, cov_layout)
    cov_plot.removeAllListeners("plotly_click")
    cov_plot.removeAllListeners("plotly_doubleclick")
    cov_plot.on("plotly_click", handle_plot_click)
    cov_plot.on("plotly_doubleclick", handle_plot_doubleclick)
}

const build_scaled = (chr, range=false) => {
    // hide the placeholder
    $('#scaled_plot_placeholder').prop('hidden', true)
    // show the plot
    $('#scaled_plot').prop('hidden', false)
    scaled_layout.xaxis.autorange = true
    if (range) {
        scaled_layout.xaxis.autorange = false
        scaled_layout.xaxis.range = range
    }
    scaled_traces = data[chr]

    let scaled_plot = document.getElementById("scaled_plot")
    Plotly.react(scaled_plot, scaled_traces, scaled_layout)
    scaled_plot.removeAllListeners("plotly_click")
    scaled_plot.removeAllListeners("plotly_doubleclick")
    scaled_plot.on("plotly_click", handle_plot_click)
    scaled_plot.on("plotly_doubleclick", handle_plot_doubleclick)
    $("#scaled_plot").removeClass("disabled_div")
}

const build_table = () => {
    if ("ped" in data) {
        var ped_table = $("#ped_table").DataTable({
            data: data.ped.slice(1),
            columns: data.ped[0],
            // scrollY: '600px',
            scrollX: true,
            scrollCollapse: true,
            paging: true,
            pagingType: "simple",
            info: true,
            bSortClasses: false,
        })

        // track if we actually have a table rendered
        if ("sample_column" in data) {
            ped = true
            // register table clicks on sample_column
            ped_table.on('click', 'tr', function () {
                if ( $(this).hasClass('selected') ) {
                    ped_table.$('tr.selected').removeClass('selected')
                    reset_line_plots()
                }
                else {
                    ped_table.$('tr.selected').removeClass('selected')
                    $(this).addClass('selected')
                    let sample_id = ped_table.rows('.selected').data()[0][sample_column]
                    highlight_plot_traces(sample_id)
                }
            })
        }
    }
}

const get_sex_data = (x, y, text, hover, colors) => {
    return {
        x: x,
        y: y,
        mode: 'markers',
        type: 'scatter',
        text: text,
        hovertext: hover,
        marker: { size: 12, color: colors, line: { color: 'rgb(40,40,40)', width: 1, } },
    }
}

const get_bin_data = (x, y, text, color='rgba(31,120,180,0.5)') => {
    return {
        x: x,
        y: y,
        mode: 'markers',
        type: 'scatter',
        text: text,
        hoverinfo: 'text',
        marker: { size: 12, color: color, line: {color: 'rgb(40,40,40)', width: 1,} },
    }
}

const get_pca_data = (x, y, text, color='rgba(31,120,180,0.5)') => {
    return {
        x: x,
        y: y,
        mode: 'markers',
        type: 'scatter',
        text: text,
        hoverinfo: 'text',
        marker: { size: 12, color: color, line: { color: 'rgb(40,40,40)', width: 1, } },
    }
}

const build_inferred_sex_plot = () => {
    var sex_p = document.getElementById("inferred_sex")
    Plotly.react(sex_p,
        [get_sex_data(data.depth.inferred.x, data.depth.inferred.y, data.depth.bins.samples, data.depth.inferred.hover, data.depth.inferred.color)],
        {
            margin: {t: 15,},
            height: 400,
            xaxis: {title: "X Copy Number"},
            yaxis: {title: "Y Copy Number"},
            hovermode: "closest",
            legend: { orientation: "h", x: 0, y: 1.125, },
            dragmode: "lasso",
        }
    )
    sex_p.removeAllListeners("plotly_selected")
    sex_p.removeAllListeners("plotly_deselect")
    sex_p.on("plotly_selected", handle_scatter_selection)
    sex_p.on("plotly_deselect", handle_scatter_deselect)
}

const build_global_qc = () => {

    if (!("depth" in data)) {
        return
    }

    $("#global_qc_nav").prop('hidden', false)

    // inferred sex
    build_inferred_sex_plot()

    // bin counts
    var bin_p = document.getElementById("bin_counts")
    Plotly.react(bin_p, [get_bin_data(data.depth.bins.x, data.depth.bins.y, data.depth.bins.samples)], {
        margin: {t: 15,},
        height: 400,
        xaxis: {title: "Proportion of bins with depth < 0.15"},
        yaxis: {title: "Proportion of bins with depth<br>outside of (0.85, 1.15)"},
        hovermode: "closest",
        legend: { orientation: "h", x: 0, y: 1.125, },
        dragmode: "lasso",
    })
    bin_p.on("plotly_selected", handle_scatter_selection)
    bin_p.on("plotly_deselect", handle_scatter_deselect)

    // PCAs
    if ("pca_1" in data.depth.pca) {
        // insert HTML into plot area
        let pa = document.getElementById("global_qc_plots")
        pa.insertAdjacentHTML('beforeend', '<div class="row border-bottom"><div class="col-6"><h4>PCA 1 vs 2</h4></div><div class="col-6"><h4>PCA 1 vs 3</h4></div></div><div class="row"><div id="pca_1" class="col-6"></div><div id="pca_2" class="col-6"></div></div>')
        let pca1_p = document.getElementById("pca_1")
          pca2_p = document.getElementById("pca_2")
        Plotly.react(pca1_p, [get_pca_data(data.depth.pca.pca_1, data.depth.pca.pca_2, data.depth.bins.samples)], {
            margin: {t: 15,},
            height: 400,
            xaxis: {title: "PC1"},
            yaxis: {title: "PC2"},
            hovermode: "closest",
            legend: { orientation: "h", x: 0, y: 1.125, },
            dragmode: "lasso",
        })
        pca1_p.on("plotly_selected", handle_scatter_selection)
        pca1_p.on("plotly_deselect", handle_scatter_deselect)

        Plotly.react(pca2_p, [get_pca_data(data.depth.pca.pca_1, data.depth.pca.pca_3, data.depth.bins.samples)], {
            margin: {t: 15,},
            height: 400,
            xaxis: {title: "PC1"},
            yaxis: {title: "PC3"},
            hovermode: "closest",
            legend: { orientation: "h", x: 0, y: 1.125, },
            dragmode: "lasso",
        })
        pca2_p.on("plotly_selected", handle_scatter_selection)
        pca2_p.on("plotly_deselect", handle_scatter_deselect)
    }
}

$('#chrom_selector').on("change", () => {
    // $('#tab_names a[href="#scaled"]').tab('show')
    let chr = $('#chrom_selector input:radio:checked').data('name')
    if ("genes" in data) {
        gene_search_obj.clear()
    }
    $("#scaled_plot").addClass("disabled_div")
    if (ped) {
        let tables = $('.dataTable').DataTable()
        let table = tables.table('#ped_table')
        // remove all filters and reset table
        // table.search('').columns().search('').draw()
        // de-select all rows
        table.$('tr.selected').removeClass('selected')
    }
    build_cov(chr)
    build_scaled(chr)
})

const search_datatable = (sample_id) => {
    let tables = $('.dataTable').DataTable()
    let table = tables.table('#ped_table')
    // remove selection
    table.$('tr.selected').removeClass('selected')
    // run the search
    table.search(sample_id).draw()
    // highlight the selected sample within the search results
    table.rows().every(function(row_index, table_loop, row_loop) {
        if (sample_id == this.data()[sample_column]) {
            table.rows([row_index]).nodes().to$().addClass('selected')
        }
    })
}

const reset_datatable = () => {
    let tables = $('.dataTable').DataTable()
    let table = tables.table('#ped_table')
    table.$('tr.selected').removeClass('selected')
    table.search('').columns().search('').draw()
}

const handle_plot_click = (click_data) => {
    if (click_data.points[0].data.name == 'genes') {
        let genes = click_data.points[0].text.split(";")
        for (var i = 0; i < genes.length; i++) {
            window.open("https://www.genecards.org/cgi-bin/carddisp.pl?gene=" + genes[i], "_blank")
        }
    } else {
        let sample_id = click_data.points[0].data.text
        if (sample_id) {
            highlight_plot_traces(sample_id)
            if (ped) {
    search_datatable(sample_id)
            }
        }
    }
}

const handle_scatter_deselect = (event) => {
    build_inferred_sex_plot()
    Plotly.restyle('bin_counts', 'marker.color', scatter_point_color, [0])
    if ("pca_1" in data.depth.pca) {
        Plotly.restyle('pca_1', 'marker.color', scatter_point_color, [0])
        Plotly.restyle('pca_2', 'marker.color', scatter_point_color, [0])
    }
}

const handle_scatter_selection = (event) => {
    var sample_ids = event.points.map(point => point.text)
    var colors = []
    for (var i = 0; i < data.depth.bins.samples.length; i++) {
        colors.push(scatter_point_color_light)
    }
    event.points.forEach((pt) => {
        colors[pt.pointNumber] = scatter_point_color
    })

    Plotly.restyle('inferred_sex', 'marker.color', [colors])
    Plotly.restyle('bin_counts', 'marker.color', [colors])
    if ("pca_1" in data.depth.pca) {
        Plotly.restyle('pca_1', 'marker.color', [colors])
        Plotly.restyle('pca_2', 'marker.color', [colors])
    }
}

const reset_line_plots = () => {
    scaled_layout.xaxis.autorange = true
    // de-select scaled plot
    Plotly.react("scaled_plot", scaled_traces, scaled_layout)
    cov_layout.xaxis.range = [0, 1.5]
    cov_layout.yaxis.range = [0, 1.]
    // de-select cov plot
    Plotly.react("cov_plot", cov_traces, cov_layout)
}

const handle_plot_doubleclick = () => {
    reset_line_plots()
    // de-select in table
    if ("ped" in data) {
        reset_datatable()
    }
}

const highlight_plot_traces = (sample_id) => {
    let s_traces = []
    let c_traces = []
    let k_traces = []
    let highlight_color;
    for (var i = 0; i < scaled_traces.length; i++) {
        // let trace = scaled_traces[i]
        let trace = $.extend(true, {}, scaled_traces[i])
        // limit to significant sample traces
        if (trace.name == "significant") {
            // de-prioritize; gray
            if (trace.text != sample_id) {
                trace.marker.color = cov_color
            }
            else {
                highlight_color = scaled_traces[i].marker.color
            }
        }
        s_traces.push(trace)
    }
    for (var i = 0; i < cov_traces.length; i++) {
        let trace = $.extend(true, {}, cov_traces[i])
        if (trace.text != sample_id) {
            trace.marker.color = cov_color
        } else {
            trace.marker.color = highlight_color
        }
        c_traces.push(trace)
    }
    Plotly.react("cov_plot", c_traces, cov_layout)
    Plotly.react("scaled_plot", s_traces, scaled_layout)
}

const build_gene_search = () => {
    if ("genes" in data) {

        // re-organize the buttons and show the search field
        $('#chrom_selector_div').removeClass('col-12').addClass('col-10')
        $("#gene_search_div").prop('hidden', false)

        // n = name, v = [chrom, start, end]
        let gene_search = $('#gene-search').selectize({
            plugins: ['remove_button'],
            valueField: 'v',
            labelField: 'n',
            searchField: 'n',
            options: data['genes'],
            placeholder: 'Gene ID',
            mode: 'single',
            closeAfterSelect: false,
            maxItems: 1,
            maxOptions: 20,
        })
        gene_search_obj = gene_search[0].selectize
        // register handler
        $('#gene-search').on('change', function() {
            update_scaled_range(gene_search_obj.items[0])
        })
    }
}

const update_scaled_range = (coords) => {
    if (!coords) {
        return
    }

    coords = coords.split(',')
    let chrom = coords[0]
    let padding = 100000
    let start = parseInt(coords[1]) - padding
    let end = parseInt(coords[2]) + padding

    let current_chr = $('#chrom_selector input:radio:checked').data('name')

    if (current_chr != chrom) {
        // change the button
        $("#chrbtn" + current_chr).removeClass('active')
        $("#chrinp" + current_chr).prop('checked', false)
        $("#chrbtn" + chrom).addClass('active')
        $("#chrinp" + chrom).prop('checked', true)

        // temp disable
        $("#scaled_plot").addClass("disabled_div")

        // change both plots to currently selected chromosome
        build_cov(chrom)
    }

    // zoom the scaled plot
    build_scaled(chrom, [start, end])
}

$(document).ready(function() {
    load_buttons(data.chromosomes)
    build_table()
    build_global_qc()
})

</script>
</html>
