app/scripts/views/components/dataTable/tableView.js
/**
* Created by Karthik Kalletla on 6/20/16.
*/
'use strict';
(function(iViz, dc, _, React, ReactDOM, EnhancedFixedDataTableSpecial) {
// iViz pie chart component. It includes DC pie chart.
iViz.view.component.TableView = function() {
var content = this;
var chartId_;
var data_ = [];
var type_ = '';
var attr_ = [];
var attributes_ = [];
var geneData_ = [];
var selectedRows = [];
var selectedGenes = [];
var callbacks_ = {};
var sequencedSampleIds = [];
var selectedSamples = [];
var allSamplesIds = [];
var reactTableData = {};
var initialized = false;
var selectedRowData = [];
var selectedGeneData = [];
var displayName = '';
var categories_ = {};
var reactData_;
var isMutatedGeneCna = false;
var dimension = {};
var group = {};
var labelInitData = {};
var opts = {};
var genePanelMap = {};
var renderedReactTable;
// Category based color assignment. Avoid color changing
var assignedColors = {
NA: '#cccccc'
};
var colors = $.extend(true, [], iViz.util.getColors());
content.getCases = function() {
return iViz.util.intersection(selectedSamples, sequencedSampleIds);
};
content.getSelectedRowData = function() {
return selectedRowData;
};
content.clearSelectedRowData = function() {
selectedRowData = [];
};
content.init =
function(_attributes, _opts, _selectedSamples, _selectedGenes,
_data, _callbacks, _geneData, _dimension, _genePanelMap) {
initialized = false;
_selectedSamples.sort();
allSamplesIds = _selectedSamples;
selectedSamples = _selectedSamples;
sequencedSampleIds = _attributes.options.sequencedCases === undefined ? allSamplesIds : _attributes.options.sequencedCases;
sequencedSampleIds.sort();
selectedGenes = _selectedGenes;
chartId_ = _opts.chartId;
opts = _opts;
genePanelMap = _genePanelMap;
data_ = _data;
geneData_ = _geneData;
type_ = _attributes.type;
displayName = _attributes.display_name || 'Table';
attributes_ = _attributes;
callbacks_ = _callbacks;
isMutatedGeneCna = ['mutatedGene', 'cna'].indexOf(type_) !== -1;
if (!isMutatedGeneCna) {
dimension = _dimension;
group = dimension.group();
initPieTableData();
}
initReactTable(true, sequencedSampleIds);
initialized = true;
};
content.update = function(_selectedSampleUIDs, _selectedRows) {
var selectedMap_ = {};
var includeMutationCount = false;
if (_selectedRows !== undefined) {
selectedRows = _selectedRows;
}
if (selectedRows.length === 0) {
selectedRowData = [];
}
_selectedSampleUIDs.sort();
if ((!initialized) ||
(!iViz.util.compare(selectedSamples, _selectedSampleUIDs))) {
initialized = true;
selectedSamples = _selectedSampleUIDs;
if (iViz.util.compare(allSamplesIds, selectedSamples)) {
initReactTable(true, selectedSamples);
} else {
_.each(_selectedSampleUIDs, function(caseId) {
var caseData_ = data_[caseId];
if (_.isObject(caseData_)) {
var tempData_ = '';
switch (type_) {
case 'mutatedGene':
tempData_ = caseData_.mutated_genes;
includeMutationCount = true;
break;
case 'cna':
tempData_ = caseData_.cna_details;
includeMutationCount = false;
break;
default:
var category = caseData_[attributes_.attr_id];
if (!category) {
category = 'NA';
}
if (!selectedMap_.hasOwnProperty(category)) {
selectedMap_[category] = [];
}
selectedMap_[category].push(caseId);
break;
}
if (isMutatedGeneCna) {
_.each(tempData_, function(geneIndex) {
if (selectedMap_[geneIndex] === undefined) {
selectedMap_[geneIndex] = {};
if (includeMutationCount) {
selectedMap_[geneIndex].num_muts = 1;
}
selectedMap_[geneIndex].case_ids = [caseId];
} else {
if (includeMutationCount) {
selectedMap_[geneIndex].num_muts += 1;
}
selectedMap_[geneIndex].case_ids.push(caseId);
}
});
}
}
});
_.each(selectedMap_, function(content) {
content.case_uids = iViz.util.unique(content.case_ids);
});
initReactTable(true, selectedSamples, selectedMap_);
}
} else {
initReactTable(false);
}
};
content.updateGenes = function(genes) {
selectedGenes = genes;
initReactTable(false);
};
content.updateDataForDownload = function(fileType) {
if (fileType === 'tsv') {
initTsvDownloadData();
}
};
content.getCurrentCategories = function() {
return _.values(categories_);
};
function initReactTable(_reloadData, _selectedSampleUids, _selectedMap) {
if (_reloadData) {
reactTableData = initReactData(_selectedMap, _selectedSampleUids);
}
var _opts = {
input: reactTableData,
filter: 'ALL',
download: 'NONE',
downloadFileName: 'data.txt',
showHide: false,
hideFilter: true,
scroller: true,
resultInfo: false,
groupHeader: false,
fixedChoose: false,
uniqueId: 'uniqueId',
rowHeight: 25,
tableWidth: opts.width,
maxHeight: opts.height,
headerHeight: 26,
groupHeaderHeight: 40,
autoColumnWidth: false,
columnMaxWidth: 300,
columnSorting: false,
elementId: chartId_ + '-table',
sortBy: 'cases',
selectedRows: selectedRows,
rowClickFunc: function(data, selected) {
reactRowClickCallback(data, selected);
reactSubmitClickCallback();
},
// sortBy: 'name',
// sortDir: 'DESC',
tableType: type_
};
if (isMutatedGeneCna) {
_opts = _.extend(_opts, {
rowClickFunc: reactRowClickCallback,
selectedGene: selectedGenes,
geneClickFunc: reactGeneClickCallback,
selectButtonClickCallback: reactSubmitClickCallback
});
}
// Check whether the react table has been initialized
if (renderedReactTable) {
// Get sort settings from the initialized react table
var sort_ = renderedReactTable.getCurrentSort();
_opts = $.extend(_opts, sort_);
}
var testElement = React.createElement(EnhancedFixedDataTableSpecial,
_opts);
renderedReactTable = ReactDOM.render(testElement, document.getElementById(chartId_));
}
function initRegularTableData() {
var data = [];
_.each(categories_, function(category, name) {
for (var key in category) {
if (category.hasOwnProperty(key)) {
var datum = {
attr_id: key,
uniqueId: name,
attr_val: key === 'case_uids' ? category.case_uids.join(',') : category[key]
};
data.push(datum);
}
}
});
reactData_ = data;
}
function getColor(key) {
if (!assignedColors.hasOwnProperty(key)) {
var _color = colors.shift();
if (!_color) {
_color = iViz.util.getRandomColorOutOfLib();
}
assignedColors[key] = _color;
}
return assignedColors[key];
}
function initPieTableData() {
_.each(group.all(), function(attr, index) {
labelInitData[attr.key] = {
attr: attr,
color: getColor(attr.key),
id: attr.key,
index: index
};
});
}
function updateCategories() {
var _labels = {};
var _currentSampleSize = 0;
_.each(group.top(Infinity), function(label) {
var _labelDatum = {};
var _labelValue = Number(label.value);
if (_labelValue > 0) {
_labelDatum.id = labelInitData[label.key].id;
_labelDatum.index = labelInitData[label.key].index;
_labelDatum.name = label.key;
_labelDatum.color = labelInitData[label.key].color;
_labelDatum.cases = _labelValue;
_currentSampleSize += _labelValue;
_labels[_labelDatum.id] = _labelDatum;
}
});
_.each(_labels, function(label) {
label.caseRate = iViz.util.calcFreq(Number(label.cases), _currentSampleSize);
});
categories_ = _labels;
}
function mutatedGenesData(_selectedGenesMap, _selectedSampleUids) {
genePanelMap = window.iviz.datamanager.updateGenePanelMap(genePanelMap, _selectedSampleUids);
selectedGeneData.length = 0;
var numOfCases_ = content.getCases().length;
if (geneData_) {
_.each(geneData_, function(item, index) {
var datum = {};
var freq = 0;
datum.gene = item.gene;
if (_selectedGenesMap === undefined) {
datum.case_uids = item.case_uids;
datum.cases = datum.case_uids.length;
datum.uniqueId = index;
if (typeof genePanelMap[item.gene] !== 'undefined') {
freq = iViz.util.calcFreq(datum.cases, genePanelMap[item.gene].sampleNum);
} else {
freq = iViz.util.calcFreq(datum.cases, numOfCases_);
}
switch (type_) {
case 'mutatedGene':
datum.numOfMutations = item.num_muts;
datum.sampleRate = freq;
break;
case 'cna':
datum.cytoband = item.cytoband;
datum.altType = item.cna;
datum.altrateInSample = freq;
break;
default:
break;
}
} else {
if (_selectedGenesMap[item.index] === undefined) {
return;
}
datum.case_uids = _selectedGenesMap[item.index].case_uids;
datum.cases = datum.case_uids.length;
if (typeof genePanelMap[item.gene] !== 'undefined') {
freq = iViz.util.calcFreq(datum.cases, genePanelMap[item.gene].sampleNum);
} else {
freq = iViz.util.calcFreq(datum.cases, numOfCases_);
}
switch (type_) {
case 'mutatedGene':
datum.numOfMutations = _selectedGenesMap[item.index].num_muts;
datum.sampleRate = freq;
datum.uniqueId = datum.gene;
break;
case 'cna':
datum.cytoband = item.cytoband;
datum.altType = item.cna;
datum.altrateInSample = freq;
datum.uniqueId = datum.gene + '-' + datum.altType;
break;
default:
break;
}
}
if (item.qval === null) {
datum.qval = '';
} else {
var qval = Number(item.qval);
if (qval === 0) {
datum.qval = 0;
} else {
datum.qval = qval.toExponential(1);
}
}
selectedGeneData.push(datum);
});
}
return selectedGeneData;
}
function initReactData(_selectedMap, _selectedSampleUids) {
attr_ = iViz.util.tableView.getAttributes(type_);
var result = {
data: [],
attributes: attr_
};
if (isMutatedGeneCna) {
var _mutationData = mutatedGenesData(_selectedMap, _selectedSampleUids);
_.each(_mutationData, function(item) {
for (var key in item) {
if (item.hasOwnProperty(key)) {
var datum = {
attr_id: key,
uniqueId: item.uniqueId,
attr_val: key === 'case_uids' ? item.case_uids.join(',') : item[key]
};
result.data.push(datum);
}
}
});
} else {
categories_ = {};
result.attributes[0].display_name = displayName;
updateCategories(_selectedMap);
initRegularTableData();
result.data = reactData_;
}
return result;
}
function reactSubmitClickCallback() {
callbacks_.submitClick(selectedRowData);
}
function reactRowClickCallback(data, selected) {
if (selected) {
selectedRowData.push(data);
} else {
selectedRowData = _.filter(selectedRowData, function(item) {
return (item.uniqueid !== data.uniqueid);
});
}
}
function reactGeneClickCallback(selectedRow) {
callbacks_.addGeneClick(selectedRow);
}
function initTsvDownloadData() {
var attrs =
iViz.util.tableView.getAttributes(type_).filter(function(attr) {
return attr.attr_id !== 'uniqueId' && (_.isBoolean(attr.show) ? attr.show : true);
});
var downloadOpts = {
fileName: displayName,
data: ''
};
var rowsData;
if (isMutatedGeneCna) {
rowsData = selectedGeneData;
} else {
rowsData = _.values(categories_);
}
rowsData = _.sortBy(rowsData, function(item) {
return -item.cases;
});
if (_.isArray(attrs) && attrs.length > 0) {
var data = [attrs.map(
function(attr) {
if (attr.attr_id === 'name') {
attr.display_name = displayName;
}
return attr.display_name;
}).join('\t')];
_.each(rowsData, function(row) {
var _tmp = [];
_.each(attrs, function(attr) {
_tmp.push(row[attr.attr_id] || '');
});
data.push(_tmp.join('\t'));
});
downloadOpts.data = data.join('\n');
}
content.setDownloadData('tsv', downloadOpts);
}
};
iViz.view.component.TableView.prototype =
new iViz.view.component.GeneralChart('table');
iViz.util.tableView = (function() {
var content = {};
content.compare = function(arr1, arr2) {
if (arr1.length !== arr2.length) {
return false;
}
for (var i = 0; i < arr2.length; i++) {
if (arr1.indexOf(arr2[i]) === -1) {
return false;
}
}
return true;
};
content.getAttributes = function(type) {
var _attr = [];
switch (type) {
case 'mutatedGene':
_attr = [
{
attr_id: 'gene',
display_name: 'Gene',
datatype: 'STRING',
column_width: 110
}, {
attr_id: 'numOfMutations',
display_name: '# Mut',
description: 'Number of mutations in all samples',
datatype: 'NUMBER',
column_width: 95
},
{
attr_id: 'cases',
display_name: '#',
description: 'Number of samples with mutation',
datatype: 'NUMBER',
column_width: 95
},
{
attr_id: 'sampleRate',
display_name: 'Freq',
description: '% of samples with this mutation',
datatype: 'PERCENTAGE',
column_width: 93
},
{
attr_id: 'case_uids',
display_name: 'Cases',
datatype: 'STRING',
show: false
},
{
attr_id: 'uniqueId',
display_name: 'uniqueId',
datatype: 'STRING',
show: false
},
{
attr_id: 'qval',
datatype: 'NUMBER',
display_name: 'MutSig',
show: false
}
];
break;
case 'cna':
_attr = [
{
attr_id: 'gene',
display_name: 'Gene',
datatype: 'STRING',
column_width: 85
},
{
attr_id: 'cytoband',
display_name: 'Cytoband',
datatype: 'STRING',
column_width: 100
},
{
attr_id: 'altType',
display_name: 'CNA',
datatype: 'STRING',
column_width: 55
},
{
attr_id: 'cases',
display_name: '#',
description: 'Number of samples with copy number alteration',
datatype: 'NUMBER',
column_width: 75
},
{
attr_id: 'altrateInSample',
display_name: 'Freq',
description: '% of samples with this copy number alteration',
datatype: 'PERCENTAGE',
column_width: 78
},
{
attr_id: 'case_uids',
display_name: 'Cases',
datatype: 'STRING',
show: false
},
{
attr_id: 'uniqueId',
display_name: 'uniqueId',
datatype: 'STRING',
show: false
},
{
attr_id: 'qval',
datatype: 'NUMBER',
display_name: 'Gistic',
show: false
}
];
break;
default:
_attr = [
{
attr_id: 'name',
display_name: 'Unknown',
datatype: 'STRING',
column_width: 230
}, {
attr_id: 'color',
display_name: 'Color',
datatype: 'STRING',
show: false
}, {
attr_id: 'cases',
display_name: '#',
datatype: 'NUMBER',
column_width: 75
}, {
attr_id: 'caseRate',
display_name: 'Freq',
datatype: 'PERCENTAGE',
column_width: 90
}, {
attr_id: 'case_uids',
display_name: 'Cases',
datatype: 'STRING',
show: false
}, {
attr_id: 'uniqueId',
display_name: 'uniqueId',
datatype: 'STRING',
show: false
}];
break;
}
return _attr;
};
return content;
})();
})(
window.iViz,
window.dc,
window._,
window.React,
window.ReactDOM,
window.EnhancedFixedDataTableSpecial
);