<commit_before>import {addCopy, logToGoogle, triggerDownloadModal, stringTitleize} from "./utils.js";
import {showInfoModal} from "./modal.js";
import {AmountTable} from "./components/amounttable.js";
import ECNumbers from "./components/ecnumbers.js";
import "unipept-visualizations/src/treeview/treeview.js";

/* eslint require-jsdoc: off */
/* TODO: make  class */

/**
 * @typedef {Object} FACounts
 * @property {number} value count
 * @property {string} name  The name of the GO/EC nummber
 * @property {string} code  The code of the GO/EC nummber
 */

/**
 * @param {Object} data descriptio of the data
 * @param {Object.<string, FACounts>} data.fa.go - GO data inforamtion
 * @param {FACounts} data.fa.uniprotEntries - EC data inforamtion
 */
function initSequenceShow(data) {
    // set up the fancy tree
    initLineageTree(data.tree);

    // set up the fullscreen stuff
    setUpFullScreen();

    // set up save image stuff
    setUpImageSave();

    // enable the external link popovers
    addExternalLinks();

    // enable the open in UniProt and clipboard buttons
    setUpUniprotButtons(data.uniprotEntries);

    setUpFA(data.fa);

    // add the tab help
    initHelp();


    /** ***************** Functions ***********************/

    /**
     * Initializes the help popups
     */
    function initHelp() {
        // tab help
        $(".nav-tabs li a span.help").click(function (e) {
            let title,
                content;
            e.stopPropagation();
            e.preventDefault();
            if ($(this).parent().attr("id") === "lineage-tree-tab") {
                title = "Lineage tree";
                content = "This interactive tree bundles the complete taxonomic lineages of all UniProt entries whose protein sequence contains " + data.peptide + ". You can click on nodes to expand them, scroll to zoom and drag to move the tree.";
            } else {
                title = "Lineage table";
                content = "This table shows the complete taxonomic lineages of all taxa associated with the UniProt entries whose protein sequence contains " + data.peptide + ". The first column contains the taxon name extracted from the UniProt entry, followed by columns representing taxonomic ranks ordered from superkingdom on the left to forma on the right.";
            }
            showInfoModal(title, content);
        });
    }

    function addExternalLinks() {
        // Add handler to the external links buttons
        $(".externalLinks-button").parent().mouseenter(function () {
            if (!$(this).hasClass("open")) {
                $(this).find(".externalLinks-button").dropdown("toggle");
            }
        });
        $(".externalLinks-button").parent().mouseleave(function () {
            if ($(this).hasClass("open")) {
                $(this).find(".externalLinks-button").dropdown("toggle");
            }
        });
    }

    function setUpUniprotButtons(entries) {
        $("#open-uniprot").click(function () {
            let url = "http://www.uniprot.org/uniprot/?query=accession%3A";
            url += entries.join("+OR+accession%3A");
            window.open(url, "_blank");
        });
        addCopy("#clipboard-uniprot", () => entries.join("\n"), "Copy UniProt IDs to clipboard");
    }

    /**
     * Sets up the image save stuff
     */
    function setUpImageSave() {
        $("#buttons-single").prepend("<button id='save-btn-lineage' class='btn btn-default btn-xs btn-animate'><span class='glyphicon glyphicon-download down'></span> Save tree as image</button>");
        $("#save-btn-lineage").click(function () {
            logToGoogle("Single Peptide", "Save Image");
            triggerDownloadModal("#lineageTree svg", null, "unipept_treeview");
        });
    }

    /**
     * Sets up the full screen stuff
     */
    function setUpFullScreen() {
        if (fullScreenApi.supportsFullScreen) {
            $("#buttons-single").prepend("<button id='zoom-btn-lineage' class='btn btn-default btn-xs btn-animate'><span class='glyphicon glyphicon-resize-full grow'></span> Enter full screen</button>");
            $("#zoom-btn-lineage").click(function () {
                logToGoogle("Single Peptide", "Full Screen");
                window.fullScreenApi.requestFullScreen($("#lineageTree").get(0));
            });
            $(document).bind(fullScreenApi.fullScreenEventName, resizeFullScreen);
        }

        function resizeFullScreen() {
            setTimeout(function () {
                let width = 916,
                    height = 600;
                if (window.fullScreenApi.isFullScreen()) {
                    width = $(window).width();
                    height = $(window).height();
                }
                $("#lineageTree svg").attr("width", width);
                $("#lineageTree svg").attr("height", height);
            }, 1000);
        }
    }

    function setUpFA(fa) {
        setUpGO(fa.go);
        setUpEC(fa.ec);
    }

    function setUpEC(ec) {
        if (ec.numAnnotatedPeptides > 0) {
            setUPECTree(ec);
            setUpEcTable(ec);
        } else {
            $("#ec-table").html("<span>No EC code annotations found.</span>");
            $("#ec-treeview").remove();
        }
    }

    /**
     * Create the EC treeview
     * @todo move to somewhere else
     * @param {number}   numAnnotatedPeptides number of anotate peptides
     * @param {FACounts} data                 EC data
     * @return {TreeView} The created treeview
     */
    function setUPECTree({numAnnotatedPeptides, data}) {
        let ecOrganiser = new ECNumbers(data);
        let tree = ecOrganiser.createTree("#ec-treeview", {
            width: 916,
            height: 600,
            levelsToExpand: 1,
            getTooltip: d => {
                let fullcode = (d.name + ".-.-.-.-").split(".").splice(0, 4).join(".");
                let tip = `<strong>EC ${fullcode}</strong>`;
                tip += `<br>${ECNumbers.nameOf(fullcode)}`;
                tip += `<br>Ocurrences: ${d.data.count} (${(100*d.data.count/numAnnotatedPeptides).toFixed(1)}%) <br>`;
                if (d.data.count == d.data.self_count) {
                    tip += "All specific";
                } else {
                    tip += `Specific ocurrences: ${d.data.self_count} (${(100*d.data.self_count/numAnnotatedPeptides).toFixed(1)}%)`;
                }
                return tip;
            },
        });
        // save tree
        $("#save-btn-ec").click(() => {
            logToGoogle("Single Peptide", "Save EC Image");
            triggerDownloadModal("#ec-treeview svg", null, "unipept_treeview");
        });

        return tree;
    }

    function setUpEcTable({numAnnotatedPeptides, data: ecdata}) {
        const sortedNumbers = Array.from(ecdata.values()).sort((a, b) => (b.value - a.value));
        new AmountTable({
            title: "EC numbers - " + data.peptide,
            el: d3.select("#ec-table"),
            header: ["Count", "EC-Number", "Name"],
            data: sortedNumbers,
            limit: 5,<commit_msg>fix(sequences ec): remove the "Pleas wait..." messsage when done<commit_after>import {addCopy, logToGoogle, triggerDownloadModal, stringTitleize} from "./utils.js";
import {showInfoModal} from "./modal.js";
import {AmountTable} from "./components/amounttable.js";
import ECNumbers from "./components/ecnumbers.js";
import "unipept-visualizations/src/treeview/treeview.js";

/* eslint require-jsdoc: off */
/* TODO: make  class */

/**
 * @typedef {Object} FACounts
 * @property {number} value count
 * @property {string} name  The name of the GO/EC nummber
 * @property {string} code  The code of the GO/EC nummber
 */

/**
 * @param {Object} data descriptio of the data
 * @param {Object.<string, FACounts>} data.fa.go - GO data inforamtion
 * @param {FACounts} data.fa.uniprotEntries - EC data inforamtion
 */
function initSequenceShow(data) {
    // set up the fancy tree
    initLineageTree(data.tree);

    // set up the fullscreen stuff
    setUpFullScreen();

    // set up save image stuff
    setUpImageSave();

    // enable the external link popovers
    addExternalLinks();

    // enable the open in UniProt and clipboard buttons
    setUpUniprotButtons(data.uniprotEntries);

    setUpFA(data.fa);

    // add the tab help
    initHelp();


    /** ***************** Functions ***********************/

    /**
     * Initializes the help popups
     */
    function initHelp() {
        // tab help
        $(".nav-tabs li a span.help").click(function (e) {
            let title,
                content;
            e.stopPropagation();
            e.preventDefault();
            if ($(this).parent().attr("id") === "lineage-tree-tab") {
                title = "Lineage tree";
                content = "This interactive tree bundles the complete taxonomic lineages of all UniProt entries whose protein sequence contains " + data.peptide + ". You can click on nodes to expand them, scroll to zoom and drag to move the tree.";
            } else {
                title = "Lineage table";
                content = "This table shows the complete taxonomic lineages of all taxa associated with the UniProt entries whose protein sequence contains " + data.peptide + ". The first column contains the taxon name extracted from the UniProt entry, followed by columns representing taxonomic ranks ordered from superkingdom on the left to forma on the right.";
            }
            showInfoModal(title, content);
        });
    }

    function addExternalLinks() {
        // Add handler to the external links buttons
        $(".externalLinks-button").parent().mouseenter(function () {
            if (!$(this).hasClass("open")) {
                $(this).find(".externalLinks-button").dropdown("toggle");
            }
        });
        $(".externalLinks-button").parent().mouseleave(function () {
            if ($(this).hasClass("open")) {
                $(this).find(".externalLinks-button").dropdown("toggle");
            }
        });
    }

    function setUpUniprotButtons(entries) {
        $("#open-uniprot").click(function () {
            let url = "http://www.uniprot.org/uniprot/?query=accession%3A";
            url += entries.join("+OR+accession%3A");
            window.open(url, "_blank");
        });
        addCopy("#clipboard-uniprot", () => entries.join("\n"), "Copy UniProt IDs to clipboard");
    }

    /**
     * Sets up the image save stuff
     */
    function setUpImageSave() {
        $("#buttons-single").prepend("<button id='save-btn-lineage' class='btn btn-default btn-xs btn-animate'><span class='glyphicon glyphicon-download down'></span> Save tree as image</button>");
        $("#save-btn-lineage").click(function () {
            logToGoogle("Single Peptide", "Save Image");
            triggerDownloadModal("#lineageTree svg", null, "unipept_treeview");
        });
    }

    /**
     * Sets up the full screen stuff
     */
    function setUpFullScreen() {
        if (fullScreenApi.supportsFullScreen) {
            $("#buttons-single").prepend("<button id='zoom-btn-lineage' class='btn btn-default btn-xs btn-animate'><span class='glyphicon glyphicon-resize-full grow'></span> Enter full screen</button>");
            $("#zoom-btn-lineage").click(function () {
                logToGoogle("Single Peptide", "Full Screen");
                window.fullScreenApi.requestFullScreen($("#lineageTree").get(0));
            });
            $(document).bind(fullScreenApi.fullScreenEventName, resizeFullScreen);
        }

        function resizeFullScreen() {
            setTimeout(function () {
                let width = 916,
                    height = 600;
                if (window.fullScreenApi.isFullScreen()) {
                    width = $(window).width();
                    height = $(window).height();
                }
                $("#lineageTree svg").attr("width", width);
                $("#lineageTree svg").attr("height", height);
            }, 1000);
        }
    }

    function setUpFA(fa) {
        setUpGO(fa.go);
        setUpEC(fa.ec);
    }

    function setUpEC(ec) {
        if (ec.numAnnotatedPeptides > 0) {
            setUPECTree(ec);
            setUpEcTable(ec);
        } else {
            $("#ec-table").html("<span>No EC code annotations found.</span>");
            $("#ec-treeview").remove();
        }
    }

    /**
     * Create the EC treeview
     * @todo move to somewhere else
     * @param {number}   numAnnotatedPeptides number of anotate peptides
     * @param {FACounts} data                 EC data
     * @return {TreeView} The created treeview
     */
    function setUPECTree({numAnnotatedPeptides, data}) {
        let ecOrganiser = new ECNumbers(data);
        let tree = ecOrganiser.createTree("#ec-treeview", {
            width: 916,
            height: 600,
            levelsToExpand: 1,
            getTooltip: d => {
                let fullcode = (d.name + ".-.-.-.-").split(".").splice(0, 4).join(".");
                let tip = `<strong>EC ${fullcode}</strong>`;
                tip += `<br>${ECNumbers.nameOf(fullcode)}`;
                tip += `<br>Ocurrences: ${d.data.count} (${(100*d.data.count/numAnnotatedPeptides).toFixed(1)}%) <br>`;
                if (d.data.count == d.data.self_count) {
                    tip += "All specific";
                } else {
                    tip += `Specific ocurrences: ${d.data.self_count} (${(100*d.data.self_count/numAnnotatedPeptides).toFixed(1)}%)`;
                }
                return tip;
            },
        });
        // save tree
        $("#save-btn-ec").click(() => {
            logToGoogle("Single Peptide", "Save EC Image");
            triggerDownloadModal("#ec-treeview svg", null, "unipept_treeview");
        });

        return tree;
    }

    function setUpEcTable({numAnnotatedPeptides, data: ecdata}) {
        const sortedNumbers = Array.from(ecdata.values()).sort((a, b) => (b.value - a.value));
        const target = d3.select("#ec-table");
        target.html("");
        new AmountTable({
            title: "EC numbers - " + data.peptide,
            el: target,
            header: ["Count", "EC-Number", "Name"],
            data: sortedNumbers,
            limit: 5,
{'fraction_non_alphanumeric': 0.14910745537276865, 'fraction_numerical': 0.004620231011550577, 'mean_word_length': 2.1453104359313078, 'pattern_counts': {'":': 0, '<': 35, '<?xml version=': 0, '>': 45, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1545238', 'n_tokens_mistral': 4188, 'n_tokens_neox': 3941, 'n_words': 963}