<commit_before>//# sourceURL=d3Heatmap.js

'use strict';

window.smartRApp.directive('heatmapPlot', [
    'smartRUtils',
    'controlElements',
    function(smartRUtils, controlElements) {

        return {
            restrict: 'E',
            scope: {
                data: '=',
                width: '@',
                height: '@',
                params: '='
            },
            link: function(scope, element) {

                /**
                 * Watch data model (which is only changed by ajax calls when we want to (re)draw everything)
                 */
                scope.$watch('data', function(newValue) {
                    $(element[0]).empty();
                    if (angular.isArray(newValue.fields)) {
                        createHeatmap(scope.data, element[0], scope.params);
                    }
                }, true);
            }
        };

        function createHeatmap(data, root, params) {
            var animationDuration = 1500;
            var extraFields = data.extraFields === undefined ? [] : data.extraFields;
            var features = data.features === undefined ? [] : data.features;
            var fields = data.fields;
            var significanceValues = data.significanceValues;
            var logfoldValues = data.logfoldValues;
            var ttestValues = data.ttestValues;
            var pvalValues = data.pvalValues;
            var adjpvalValues = data.adjpvalValues;
            var bvalValues = data.bvalValues;
            var ranking = data.ranking[0];
            var patientIDs = data.patientIDs;
            var uids = data.uids;
            var numberOfClusteredColumns = data.numberOfClusteredColumns[0];
            var numberOfClusteredRows = data.numberOfClusteredRows[0];
            // var warning = data.warnings === undefined ? '' : data.warnings;
            var maxRows = data.maxRows[0];
            var geneCardsAllowed = JSON.parse(params.geneCardsAllowed);
            var rowClustering = true;
            var colClustering = true;

            var originalPatientIDs = patientIDs.slice();
            var originalUIDs = uids.slice();

            var tmpAnimationDuration = animationDuration;
            function switchAnimation(checked) {
                if (! checked) {
                    tmpAnimationDuration = animationDuration;
                    animationDuration = 0;
                } else {
                    animationDuration = tmpAnimationDuration;
                }
            }

            var gridFieldWidth = 20;
            var gridFieldHeight = 20;
            var dendrogramHeight = 300;
            var histogramHeight = 200;
            var legendWidth = 200;
            var legendHeight = 40;
            var buttonWidth = 200;
            var buttonHeight = 40;
            var buttonPadding = 20;

            var margin = {
                top: gridFieldHeight * 2 + 100 + features.length * gridFieldHeight / 2 + dendrogramHeight,
                right: gridFieldWidth + 300 + dendrogramHeight,
                bottom: 10,
                left: histogramHeight + 250
            };

            var width = gridFieldWidth * patientIDs.length;
            var height = gridFieldHeight * uids.length;

            // FIXME: This is here because the sizing of the whole heatmap is kind of messed up
            // At one point in the future we need to fix this
            smartRUtils.prepareWindowSize(width * 2 + margin.left + margin.right, height * 2 + margin.top + margin.right);

            var selectedPatientIDs = [];

            var scale = null;
            var histogramScale = null;

            function setScales() {
                scale = d3.scale.linear()
                    .domain(d3.extent(significanceValues))
                    .range((ranking === 'pval' || ranking === 'adjpval') ? [histogramHeight, 0] : [0, histogramHeight]);

                histogramScale = function (value) {
                    return (ranking === 'ttest' || ranking === 'logfold') ? scale(Math.abs(value)) : scale(value);
                };
            }
            setScales();

            function getInternalSortValue(value) {
                switch (ranking) {
                    case 'pval':
                    case 'adjpval':
                        return 1 - value;
                    default:
                        return value;
                }
            }

            var heatmap = d3.select(root).append('svg')
                .attr('width', (width + margin.left + margin.right) * 4)
                .attr('height', (height + margin.top + margin.bottom) * 4)
                .attr('class', 'visualization')
                .append('g')
                .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');

            function adjustDimensions() {
                // gridFieldWidth/gridFieldHeight are adjusted outside as the zoom changes
                $(heatmap[0]).closest('svg')
                    .attr('width', margin.left + margin.right + (gridFieldWidth * patientIDs.length))
                    .attr('height', margin.top + margin.bottom + (gridFieldHeight * uids.length));
            }

            adjustDimensions();

            var tip = d3.tip()
                .attr('class', 'd3-tip')
                .offset([-10, 0])
                .html(function(d) { return d; });

            heatmap.call(tip);

            var featureItems = heatmap.append('g');
            var squareItems = heatmap.append('g');
            var colSortItems = heatmap.append('g');
            var selectItems = heatmap.append('g');
            var patientIDItems = heatmap.append('g');
            var rowSortItems = heatmap.append('g');
            var significanceSortItems = heatmap.append('g');
            var labelItems = heatmap.append('g');
            var barItems = heatmap.append('g');
            var legendItems = heatmap.append('g');
            // var warningDiv = $('#heim-heatmap-warnings').append('strong')
            //     .text(warning);

            // this code is needed for the legend generation
            var zScores = fields.map(function(d) { return d.ZSCORE; });
            var maxZScore = Math.max.apply(null, zScores);
            var minZScore = Math.min.apply(null, zScores);
            var steps = [];
            for (var i = minZScore; i < maxZScore; i+= (maxZScore - minZScore) / 200) {
                steps.push(i);
            }

            function updateHeatmap() {
                var square = squareItems.selectAll('.square')
                    .data(fields, function (d) {
                        return 'patientID-' + d.PATIENTID + '-uid-' + d.UID;
                    });

                square.enter()
                    .append('rect')
                    .attr('class', function (d) {
                        return 'square patientID-' + smartRUtils.makeSafeForCSS(d.PATIENTID) +
                            ' uid-' + smartRUtils.makeSafeForCSS(d.UID);
                    })
                    .attr('x', function (d) {
                        return patientIDs.indexOf(d.PATIENTID) * gridFieldWidth;
                    })
                    .attr('y', function (d) {
                        return uids.indexOf(d.UID) * gridFieldHeight;
                    })
                    .attr('width', gridFieldWidth)
                    .attr('height', gridFieldHeight)
                    .attr('rx', 0)
                    .attr('ry', 0)
                    .style('fill', 'white')
                    .on('mouseover', function (d) {
                        d3.select('.patientID.patientID-' + smartRUtils.makeSafeForCSS(d.PATIENTID))
                            .classed('highlight', true);
                        d3.select('.uid.uid-' + smartRUtils.makeSafeForCSS(d.UID))
                            .classed('highlight', true);

                        var html = '';
                        for (var key in d) {
                            if (d.hasOwnProperty(key)) {
                                html += key + ': ' + d[key] + '<br/>';
                            }
                        }
                        tip.show(html);
                    })
                    .on('mouseout', function () {
                        d3.selectAll('.patientID').classed('highlight', false);
                        d3.selectAll('.uid').classed('highlight', false);
                        tip.hide();
                    });


                square.transition()
                    .duration(animationDuration)
                    .attr('x', function (d) {
                        return patientIDs.indexOf(d.PATIENTID) * gridFieldWidth;
                    })
                    .attr('y', function (d) {
                        return uids.indexOf(d.UID) * gridFieldHeight;
                    })
                    .attr('width', gridFieldWidth)
                    .attr('height', gridFieldHeight);

                var colSortText = colSortItems.selectAll('.colSortText')
                    .data(patientIDs, function (d) {
                        return d;
                    });

                colSortText.enter()
                    .append('text')
                    .attr('class', 'text colSortText')
                    .attr('x', function (d, i) {
                        return i * gridFieldWidth + 0.5 * gridFieldWidth;
                    })
                    .attr('y', -2 - gridFieldHeight + 0.5 * gridFieldHeight)
                    .attr('dy', '0.35em')
                    .attr('text-anchor', 'middle')
                    .text('↑↓');

                colSortText.transition()
                    .duration(animationDuration)
                    .attr('x', function (d, i) {
                        return i * gridFieldWidth + 0.5 * gridFieldWidth;
                    })
                    .attr('y', -2 - gridFieldHeight + 0.5 * gridFieldHeight);

                var colSortBox = colSortItems.selectAll('.colSortBox')
                    .data(patientIDs, function (d) {
                        return d;
                    });

                function getValueForSquareSorting(patientID, uid) {
                    var square = d3.select('.square' + '.patientID-' + smartRUtils.makeSafeForCSS(patientID) +
                        '.uid-' + smartRUtils.makeSafeForCSS(uid));
                    return square[0][0] ? square.property('__data__').ZSCORE : Number.NEGATIVE_INFINITY;
                }

                function isSorted(arr) {
                    return arr.every(function (d, i) {
                        return i === arr.length - 1 || arr[i][1] >= arr[i + 1][1];
                    });
                }

                colSortBox.enter()
                    .append('rect')
                    .attr('class', 'box colSortBox')
                    .attr('x', function (d, i) {
                        return i * gridFieldWidth;
                    })
                    .attr('y', -2 - gridFieldHeight)
                    .attr('width', gridFieldWidth)
                    .attr('height', gridFieldHeight)
                    .on('click', function (patientID) {
                        d3.selectAll('.box').classed('sortedBy', false);
                        d3.select(this).classed('sortedBy', true);

                        var rowValues = uids.map(function (uid, idx) {
                            return [idx, getValueForSquareSorting(patientID, uid)];
                        });
                        if (isSorted(rowValues)) {
                            rowValues.sort(function (a, b) {
                                return a[1] - b[1];
                            });
                        } else {
                            rowValues.sort(function (a, b) {
                                return b[1] - a[1];
                            });
                        }
                        var sortValues = rowValues.map(function (rowValue) {
                            return rowValue[0];
                        });
                        updateRowOrder(sortValues);
                    });

                colSortBox.transition()
                    .duration(animationDuration)
                    .attr('x', function (d, i) {
                        return i * gridFieldWidth;
                    })
                    .attr('y', -2 - gridFieldHeight)
                    .attr('width', gridFieldWidth)
                    .attr('height', gridFieldHeight);

                var rowSortText = rowSortItems.selectAll('.rowSortText')
                    .data(uids, function (d) {
                        return d;
                    });

                rowSortText.enter()
                    .append('text')
                    .attr('class', 'text rowSortText')
                    .attr('transform', function (d, i) {
                        return 'translate(' + (width + 2 + 0.5 * gridFieldWidth) + ',0)' + 'translate(0,' +
                            (i * gridFieldHeight + 0.5 * gridFieldHeight) + ')rotate(-90)';
                    })
                    .attr('dy', '0.35em')
                    .attr('text-anchor', 'middle')
                    .text('↑↓');

                rowSortText.transition()
                    .duration(animationDuration)
                    .attr('transform', function (d, i) {
                        return 'translate(' + (width + 2 + 0.5 * gridFieldWidth) + ',0)' + 'translate(0,' +
                            (i * gridFieldHeight + 0.5 * gridFieldHeight) + ')rotate(-90)';
                    });

                var rowSortBox = rowSortItems.selectAll('.rowSortBox')
                    .data(uids, function (d) {
                        return d;
                    });

                rowSortBox.enter()
                    .append('rect')
                    .attr('class', 'box rowSortBox')
                    .attr('x', width + 2)
                    .attr('y', function (d, i) {
                        return i * gridFieldHeight;
                    })
                    .attr('width', gridFieldWidth)
                    .attr('height', gridFieldHeight)
                    .on('click', function (uid) {
                        d3.selectAll('.box').classed('sortedBy', false);
                        d3.select(this).classed('sortedBy', true);

                        var colValues = patientIDs.map(function (patientID, idx) {
                            return [idx, getValueForSquareSorting(patientID, uid)];
                        });<commit_msg>(SH-87) Indicate graphically on which basis a heatmap rows and columns are ordered.<commit_after>//# sourceURL=d3Heatmap.js

'use strict';

window.smartRApp.directive('heatmapPlot', [
    'smartRUtils',
    'controlElements',
    function(smartRUtils, controlElements) {

        return {
            restrict: 'E',
            scope: {
                data: '=',
                width: '@',
                height: '@',
                params: '='
            },
            link: function(scope, element) {

                /**
                 * Watch data model (which is only changed by ajax calls when we want to (re)draw everything)
                 */
                scope.$watch('data', function(newValue) {
                    $(element[0]).empty();
                    if (angular.isArray(newValue.fields)) {
                        createHeatmap(scope.data, element[0], scope.params);
                    }
                }, true);
            }
        };

        function createHeatmap(data, root, params) {
            var animationDuration = 1500;
            var extraFields = data.extraFields === undefined ? [] : data.extraFields;
            var features = data.features === undefined ? [] : data.features;
            var fields = data.fields;
            var significanceValues = data.significanceValues;
            var logfoldValues = data.logfoldValues;
            var ttestValues = data.ttestValues;
            var pvalValues = data.pvalValues;
            var adjpvalValues = data.adjpvalValues;
            var bvalValues = data.bvalValues;
            var ranking = data.ranking[0];
            var patientIDs = data.patientIDs;
            var uids = data.uids;
            var numberOfClusteredColumns = data.numberOfClusteredColumns[0];
            var numberOfClusteredRows = data.numberOfClusteredRows[0];
            // var warning = data.warnings === undefined ? '' : data.warnings;
            var maxRows = data.maxRows[0];
            var geneCardsAllowed = JSON.parse(params.geneCardsAllowed);
            var rowClustering = true;
            var colClustering = true;

            var originalPatientIDs = patientIDs.slice();
            var originalUIDs = uids.slice();

            var tmpAnimationDuration = animationDuration;
            function switchAnimation(checked) {
                if (! checked) {
                    tmpAnimationDuration = animationDuration;
                    animationDuration = 0;
                } else {
                    animationDuration = tmpAnimationDuration;
                }
            }

            var gridFieldWidth = 20;
            var gridFieldHeight = 20;
            var dendrogramHeight = 300;
            var histogramHeight = 200;
            var legendWidth = 200;
            var legendHeight = 40;
            var buttonWidth = 200;
            var buttonHeight = 40;
            var buttonPadding = 20;

            var margin = {
                top: gridFieldHeight * 2 + 100 + features.length * gridFieldHeight / 2 + dendrogramHeight,
                right: gridFieldWidth + 300 + dendrogramHeight,
                bottom: 10,
                left: histogramHeight + 250
            };

            var width = gridFieldWidth * patientIDs.length;
            var height = gridFieldHeight * uids.length;

            // FIXME: This is here because the sizing of the whole heatmap is kind of messed up
            // At one point in the future we need to fix this
            smartRUtils.prepareWindowSize(width * 2 + margin.left + margin.right, height * 2 + margin.top + margin.right);

            var selectedPatientIDs = [];

            var scale = null;
            var histogramScale = null;

            function setScales() {
                scale = d3.scale.linear()
                    .domain(d3.extent(significanceValues))
                    .range((ranking === 'pval' || ranking === 'adjpval') ? [histogramHeight, 0] : [0, histogramHeight]);

                histogramScale = function (value) {
                    return (ranking === 'ttest' || ranking === 'logfold') ? scale(Math.abs(value)) : scale(value);
                };
            }
            setScales();

            function getInternalSortValue(value) {
                switch (ranking) {
                    case 'pval':
                    case 'adjpval':
                        return 1 - value;
                    default:
                        return value;
                }
            }

            var heatmap = d3.select(root).append('svg')
                .attr('width', (width + margin.left + margin.right) * 4)
                .attr('height', (height + margin.top + margin.bottom) * 4)
                .attr('class', 'visualization')
                .append('g')
                .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');

            function adjustDimensions() {
                // gridFieldWidth/gridFieldHeight are adjusted outside as the zoom changes
                $(heatmap[0]).closest('svg')
                    .attr('width', margin.left + margin.right + (gridFieldWidth * patientIDs.length))
                    .attr('height', margin.top + margin.bottom + (gridFieldHeight * uids.length));
            }

            adjustDimensions();

            var tip = d3.tip()
                .attr('class', 'd3-tip')
                .offset([-10, 0])
                .html(function(d) { return d; });

            heatmap.call(tip);

            var featureItems = heatmap.append('g');
            var squareItems = heatmap.append('g');
            var colSortItems = heatmap.append('g');
            var selectItems = heatmap.append('g');
            var patientIDItems = heatmap.append('g');
            var rowSortItems = heatmap.append('g');
            var significanceSortItems = heatmap.append('g');
            var labelItems = heatmap.append('g');
            var barItems = heatmap.append('g');
            var legendItems = heatmap.append('g');
            // var warningDiv = $('#heim-heatmap-warnings').append('strong')
            //     .text(warning);

            // this code is needed for the legend generation
            var zScores = fields.map(function(d) { return d.ZSCORE; });
            var maxZScore = Math.max.apply(null, zScores);
            var minZScore = Math.min.apply(null, zScores);
            var steps = [];
            for (var i = minZScore; i < maxZScore; i+= (maxZScore - minZScore) / 200) {
                steps.push(i);
            }

            function updateHeatmap() {
                var square = squareItems.selectAll('.square')
                    .data(fields, function (d) {
                        return 'patientID-' + d.PATIENTID + '-uid-' + d.UID;
                    });

                square.enter()
                    .append('rect')
                    .attr('class', function (d) {
                        return 'square patientID-' + smartRUtils.makeSafeForCSS(d.PATIENTID) +
                            ' uid-' + smartRUtils.makeSafeForCSS(d.UID);
                    })
                    .attr('x', function (d) {
                        return patientIDs.indexOf(d.PATIENTID) * gridFieldWidth;
                    })
                    .attr('y', function (d) {
                        return uids.indexOf(d.UID) * gridFieldHeight;
                    })
                    .attr('width', gridFieldWidth)
                    .attr('height', gridFieldHeight)
                    .attr('rx', 0)
                    .attr('ry', 0)
                    .style('fill', 'white')
                    .on('mouseover', function (d) {
                        d3.select('.patientID.patientID-' + smartRUtils.makeSafeForCSS(d.PATIENTID))
                            .classed('highlight', true);
                        d3.select('.uid.uid-' + smartRUtils.makeSafeForCSS(d.UID))
                            .classed('highlight', true);

                        var html = '';
                        for (var key in d) {
                            if (d.hasOwnProperty(key)) {
                                html += key + ': ' + d[key] + '<br/>';
                            }
                        }
                        tip.show(html);
                    })
                    .on('mouseout', function () {
                        d3.selectAll('.patientID').classed('highlight', false);
                        d3.selectAll('.uid').classed('highlight', false);
                        tip.hide();
                    });


                square.transition()
                    .duration(animationDuration)
                    .attr('x', function (d) {
                        return patientIDs.indexOf(d.PATIENTID) * gridFieldWidth;
                    })
                    .attr('y', function (d) {
                        return uids.indexOf(d.UID) * gridFieldHeight;
                    })
                    .attr('width', gridFieldWidth)
                    .attr('height', gridFieldHeight);

                var colSortText = colSortItems.selectAll('.colSortText')
                    .data(patientIDs, function (d) {
                        return d;
                    });

                colSortText.enter()
                    .append('text')
                    .attr('class', 'text colSortText')
                    .attr('x', function (d, i) {
                        return i * gridFieldWidth + 0.5 * gridFieldWidth;
                    })
                    .attr('y', -2 - gridFieldHeight + 0.5 * gridFieldHeight)
                    .attr('dy', '0.35em')
                    .attr('text-anchor', 'middle')
                    .text('↑↓');

                colSortText.transition()
                    .duration(animationDuration)
                    .attr('x', function (d, i) {
                        return i * gridFieldWidth + 0.5 * gridFieldWidth;
                    })
                    .attr('y', -2 - gridFieldHeight + 0.5 * gridFieldHeight);

                var colSortBox = colSortItems.selectAll('.colSortBox')
                    .data(patientIDs, function (d) {
                        return d;
                    });

                function getValueForSquareSorting(patientID, uid) {
                    var square = d3.select('.square' + '.patientID-' + smartRUtils.makeSafeForCSS(patientID) +
                        '.uid-' + smartRUtils.makeSafeForCSS(uid));
                    return square[0][0] ? square.property('__data__').ZSCORE : Number.NEGATIVE_INFINITY;
                }

                function isSorted(arr) {
                    return arr.every(function (d, i) {
                        return i === arr.length - 1 || arr[i][1] >= arr[i + 1][1];
                    });
                }

                colSortBox.enter()
                    .append('rect')
                    .attr('class', 'box colSortBox')
                    .attr('x', function (d, i) {
                        return i * gridFieldWidth;
                    })
                    .attr('y', -2 - gridFieldHeight)
                    .attr('width', gridFieldWidth)
                    .attr('height', gridFieldHeight)
                    .on('click', function (patientID) {
                        d3.selectAll('.colSortBox').classed('sortedBy', false);
                        d3.select(this).classed('sortedBy', true);

                        var rowValues = uids.map(function (uid, idx) {
                            return [idx, getValueForSquareSorting(patientID, uid)];
                        });
                        if (isSorted(rowValues)) {
                            rowValues.sort(function (a, b) {
                                return a[1] - b[1];
                            });
                        } else {
                            rowValues.sort(function (a, b) {
                                return b[1] - a[1];
                            });
                        }
                        var sortValues = rowValues.map(function (rowValue) {
                            return rowValue[0];
                        });
                        updateRowOrder(sortValues);
                    });

                colSortBox.transition()
                    .duration(animationDuration)
                    .attr('x', function (d, i) {
                        return i * gridFieldWidth;
                    })
                    .attr('y', -2 - gridFieldHeight)
                    .attr('width', gridFieldWidth)
                    .attr('height', gridFieldHeight);

                var rowSortText = rowSortItems.selectAll('.rowSortText')
                    .data(uids, function (d) {
                        return d;
                    });

                rowSortText.enter()
                    .append('text')
                    .attr('class', 'text rowSortText')
                    .attr('transform', function (d, i) {
                        return 'translate(' + (width + 2 + 0.5 * gridFieldWidth) + ',0)' + 'translate(0,' +
                            (i * gridFieldHeight + 0.5 * gridFieldHeight) + ')rotate(-90)';
                    })
                    .attr('dy', '0.35em')
                    .attr('text-anchor', 'middle')
                    .text('↑↓');

                rowSortText.transition()
                    .duration(animationDuration)
                    .attr('transform', function (d, i) {
                        return 'translate(' + (width + 2 + 0.5 * gridFieldWidth) + ',0)' + 'translate(0,' +
                            (i * gridFieldHeight + 0.5 * gridFieldHeight) + ')rotate(-90)';
                    });

                var rowSortBox = rowSortItems.selectAll('.rowSortBox')
                    .data(uids, function (d) {
                        return d;
                    });

                rowSortBox.enter()
                    .append('rect')
                    .attr('class', 'box rowSortBox')
                    .attr('x', width + 2)
                    .attr('y', function (d, i) {
                        return i * gridFieldHeight;
                    })
                    .attr('width', gridFieldWidth)
                    .attr('height', gridFieldHeight)
                    .on('click', function (uid) {
                        d3.selectAll('.rowSortBox').classed('sortedBy', false);
                        d3.select(this).classed('sortedBy', true);

                        var colValues = patientIDs.map(function (patientID, idx) {
                            return [idx, getValueForSquareSorting(patientID, uid)];
                        });
{'fraction_non_alphanumeric': 0.1159678858162355, 'fraction_numerical': 0.008646126398133535, 'mean_word_length': 1.175961179544606, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5206722', 'n_tokens_mistral': 7578, 'n_tokens_neox': 6884, 'n_words': 1492}