From 4dc5e0142996c071367210dde1160d06caaeff00 Mon Sep 17 00:00:00 2001 From: Onur Sumer Date: Mon, 12 Sep 2016 17:04:22 -0400 Subject: [PATCH 01/15] added mutation data filter controller --- src/js/component/MutationDetailsTable.js | 7 +- .../MutationDataFilterController.js | 159 ++++++++++++++++++ 2 files changed, 163 insertions(+), 3 deletions(-) create mode 100644 src/js/controller/MutationDataFilterController.js diff --git a/src/js/component/MutationDetailsTable.js b/src/js/component/MutationDetailsTable.js index b7d69fa..e3c8cb6 100644 --- a/src/js/component/MutationDetailsTable.js +++ b/src/js/component/MutationDetailsTable.js @@ -1335,6 +1335,7 @@ function MutationDetailsTable(options, gene, mutationUtil, dataProxies, dataMana _prevSearch != currSearch) { // trigger corresponding event + // TODO attach self instead of selector to the event _dispatcher.trigger( MutationDetailsEvents.MUTATION_TABLE_FILTERED, tableSelector); @@ -1350,7 +1351,7 @@ function MutationDetailsTable(options, gene, mutationUtil, dataProxies, dataMana // trigger redraw event _dispatcher.trigger( MutationDetailsEvents.MUTATION_TABLE_REDRAWN, - tableSelector); + self); // get the unique number of samples for the current visible data var rowData = $(tableSelector).DataTable().rows({filter: "applied"}).data(); @@ -1403,7 +1404,7 @@ function MutationDetailsTable(options, gene, mutationUtil, dataProxies, dataMana // trigger corresponding event _dispatcher.trigger( MutationDetailsEvents.MUTATION_TABLE_INITIALIZED, - tableSelector); + self); }, "fnHeaderCallback": function(nHead, aData, iStart, iEnd, aiDisplay) { $(nHead).find('th').addClass("mutation-details-table-header"); @@ -1412,7 +1413,7 @@ function MutationDetailsTable(options, gene, mutationUtil, dataProxies, dataMana //Trigger fnHeader callback function _dispatcher.trigger( MutationDetailsEvents.MUTATION_TABLE_HEADER_CREATED, - tableSelector); + self); } // "fnFooterCallback": function(nFoot, aData, iStart, iEnd, aiDisplay) { // addFooterTooltips(nFoot, nameMap); diff --git a/src/js/controller/MutationDataFilterController.js b/src/js/controller/MutationDataFilterController.js new file mode 100644 index 0000000..9eee7e8 --- /dev/null +++ b/src/js/controller/MutationDataFilterController.js @@ -0,0 +1,159 @@ +/** + * Mutation Data Filter/Select/Highlight/Update controller. + * + * @author Selcuk Onur Sumer + */ +// TODO all other component controllers (Diagram, Table, Info Panel, etc.) should only listen +// to the events trigger by the mutation data filter manager, and update accordingly +function MutationDataFilterController(mainMutationView, mutationDetailsView) +{ + var _mutationDiagram = null; + var _mutationTable = null; + + function init() + { + if (mainMutationView.diagramView) + { + diagramInitHandler(mainMutationView.diagramView.mutationDiagram); + } + else + { + mainMutationView.dispatcher.on( + MutationDetailsEvents.DIAGRAM_INIT, + diagramInitHandler); + } + + if (mainMutationView.tableView) + { + tableInitHandler(mainMutationView.tableView.mutationTable); + } + else + { + mainMutationView.dispatcher.on( + MutationDetailsEvents.MUTATION_TABLE_INITIALIZED, + tableInitHandler); + } + + if (mainMutationView.infoView) + { + infoPanelInitHandler(mainMutationView.infoView); + } + else + { + mainMutationView.dispatcher.on( + MutationDetailsEvents.INFO_PANEL_INIT, + infoPanelInitHandler); + } + } + + function infoPanelInitHandler(infoView) + { + // add listeners to the custom event dispatcher of the info panel view + if (infoView) + { + infoView.dispatcher.on( + MutationDetailsEvents.INFO_PANEL_MUTATION_TYPE_SELECTED, + infoPanelFilterHandler); + } + } + + function tableInitHandler(mutationTable) + { + // update class variable + _mutationTable = mutationTable; + + mutationTable.dispatcher.on( + MutationDetailsEvents.MUTATION_TABLE_FILTERED, + tableFilterHandler); + } + + function diagramInitHandler(mutationDiagram) + { + // update class variable + _mutationDiagram = mutationDiagram; + + // add listeners to the custom event dispatcher of the diagram + mutationDiagram.dispatcher.on( + MutationDetailsEvents.ALL_LOLLIPOPS_DESELECTED, + allDeselectHandler); + + mutationDiagram.dispatcher.on( + MutationDetailsEvents.LOLLIPOP_DESELECTED, + diagramDeselectHandler); + + mutationDiagram.dispatcher.on( + MutationDetailsEvents.LOLLIPOP_SELECTED, + diagramSelectHandler); + + mutationDiagram.dispatcher.on( + MutationDetailsEvents.LOLLIPOP_MOUSEOVER, + diagramMouseoverHandler); + + mutationDiagram.dispatcher.on( + MutationDetailsEvents.LOLLIPOP_MOUSEOUT, + diagramMouseoutHandler); + + mutationDiagram.dispatcher.on( + MutationDetailsEvents.DIAGRAM_PLOT_UPDATED, + diagramUpdateHandler); + + mutationDiagram.dispatcher.on( + MutationDetailsEvents.DIAGRAM_PLOT_RESET, + diagramResetHandler); + } + + function diagramResetHandler() + { + // TODO reset all mutation data filters + // we may also consider to remove the updatePlot function of mutation diagram, + // and perform updates only to the mutation data set itself, then handle the updates by events. + // that would simplify the mutation diagram code... + } + + function diagramUpdateHandler() + { + // TODO reset all mutation data filters + } + + function allDeselectHandler() + { + // TODO deselect all mutations and trigger the corresponding event + // (selected mutations <- empty set) + } + + function diagramDeselectHandler(datum, index) + { + // TODO update currently selected set of mutations and trigger the corresponding event + // (selected mutations <- new set) + } + + function diagramSelectHandler(datum, index) + { + // TODO update currently selected set of mutations and trigger the corresponding event + // (selected mutations <- new set) + } + + function infoPanelFilterHandler(mutationType) + { + // TODO update currently filtered set of mutations and trigger the corresponding event + // (filtered mutations <- new set) + } + + function diagramMouseoverHandler(datum, index) + { + // TODO update currently highlighted set of mutations and trigger the corresponding event + // (highlighted mutations <- new set) + } + + function diagramMouseoutHandler(datum, index) + { + // TODO update currently highlighted set of mutations and trigger the corresponding event + // (highlighted mutations <- new set) + } + + function tableFilterHandler(tableSelector) + { + // TODO update currently filtered set of mutations and trigger the corresponding event + // (filtered mutations <- new set) + } +} From 17f7a8de141fc375ddefe93c8b1b58dd6bfc8120 Mon Sep 17 00:00:00 2001 From: Onur Sumer Date: Wed, 14 Sep 2016 17:40:50 -0400 Subject: [PATCH 02/15] added mutation data model, and started refactoring controllers --- debug/debug.html | 2 + .../MutationDataFilterController.js | 20 ++- .../controller/MutationDetailsController.js | 8 +- src/js/controller/MutationDetailsEvents.js | 7 + .../MutationDetailsTableController.js | 112 ++++++++++--- src/js/data/MutationData.js | 151 ++++++++++++++++++ src/js/view/MutationDetailsTableView.js | 2 +- src/js/view/MutationDiagramView.js | 2 +- src/js/view/MutationInfoPanelView.js | 4 +- 9 files changed, 275 insertions(+), 33 deletions(-) create mode 100644 src/js/data/MutationData.js diff --git a/debug/debug.html b/debug/debug.html index ea6f8c5..98d8f57 100644 --- a/debug/debug.html +++ b/debug/debug.html @@ -115,6 +115,7 @@ + @@ -123,6 +124,7 @@ + diff --git a/src/js/controller/MutationDataFilterController.js b/src/js/controller/MutationDataFilterController.js index 9eee7e8..482362e 100644 --- a/src/js/controller/MutationDataFilterController.js +++ b/src/js/controller/MutationDataFilterController.js @@ -5,10 +5,11 @@ */ // TODO all other component controllers (Diagram, Table, Info Panel, etc.) should only listen // to the events trigger by the mutation data filter manager, and update accordingly -function MutationDataFilterController(mainMutationView, mutationDetailsView) +function MutationDataFilterController(mainMutationView) { var _mutationDiagram = null; var _mutationTable = null; + var _mutationData = mainMutationView.model.mutationData; function init() { @@ -104,21 +105,22 @@ function MutationDataFilterController(mainMutationView, mutationDetailsView) function diagramResetHandler() { - // TODO reset all mutation data filters - // we may also consider to remove the updatePlot function of mutation diagram, - // and perform updates only to the mutation data set itself, then handle the updates by events. - // that would simplify the mutation diagram code... + _mutationData.unHighlightMutations(); + _mutationData.unSelectMutations(); + _mutationData.unfilterMutations(); } function diagramUpdateHandler() { - // TODO reset all mutation data filters + // TODO we may consider to remove the updatePlot function of mutation diagram, + // and perform updates only to the mutation data set itself, then handle the updates by events. + // that would simplify the mutation diagram code... + diagramResetHandler(); } function allDeselectHandler() { - // TODO deselect all mutations and trigger the corresponding event - // (selected mutations <- empty set) + _mutationData.unSelectMutations(); } function diagramDeselectHandler(datum, index) @@ -156,4 +158,6 @@ function MutationDataFilterController(mainMutationView, mutationDetailsView) // TODO update currently filtered set of mutations and trigger the corresponding event // (filtered mutations <- new set) } + + init(); } diff --git a/src/js/controller/MutationDetailsController.js b/src/js/controller/MutationDetailsController.js index c531eaa..b743919 100644 --- a/src/js/controller/MutationDetailsController.js +++ b/src/js/controller/MutationDetailsController.js @@ -161,9 +161,12 @@ function MutationDetailsController( uniprotId = sequenceData.metadata.identifier; } + var mutationModel = new MutationData(); + mutationModel.setData(mutationData); + // prepare data for mutation view var model = {geneSymbol: gene, - mutationData: mutationData, + mutationData: mutationModel, dataProxies: dataProxies, dataManager: dataManager, uniprotId: uniprotId, @@ -181,6 +184,9 @@ function MutationDetailsController( mainView.render(); + // init mutation data filter controller + new MutationDataFilterController(mainView); + // update the references after rendering the view _geneTabView[gene].mainMutationView = mainView; dataManager.addView(gene, mainView); diff --git a/src/js/controller/MutationDetailsEvents.js b/src/js/controller/MutationDetailsEvents.js index 92d4c14..ab11d43 100644 --- a/src/js/controller/MutationDetailsEvents.js +++ b/src/js/controller/MutationDetailsEvents.js @@ -36,6 +36,10 @@ */ var MutationDetailsEvents = (function() { + var _mutationSelected = "mutationDataSelected"; + var _mutationHighlighted = "mutationDataHighlighted"; + var _mutationFiltered = "mutationDataFiltered"; + var _lollipopSelected = "mutationDiagramLollipopSelected"; var _lollipopDeselected = "mutationDiagramLollipopDeselected"; var _allLollipopsDeselected = "mutationDiagramAllDeselected"; @@ -68,6 +72,9 @@ var MutationDetailsEvents = (function() var _3dStructureReloaded = "mutation3dStructureReloaded"; return { + MUTATION_HIGHLIGHT: _mutationHighlighted, + MUTATION_SELECT: _mutationSelected, + MUTATION_FILTER: _mutationFiltered, LOLLIPOP_SELECTED: _lollipopSelected, LOLLIPOP_DESELECTED: _lollipopDeselected, LOLLIPOP_MOUSEOVER: _lollipopMouseover, diff --git a/src/js/controller/MutationDetailsTableController.js b/src/js/controller/MutationDetailsTableController.js index 5211cc9..54a16bd 100644 --- a/src/js/controller/MutationDetailsTableController.js +++ b/src/js/controller/MutationDetailsTableController.js @@ -44,32 +44,104 @@ function MutationDetailsTableController(mainMutationView, mutationDetailsView) function init() { - if (mainMutationView.diagramView) - { - diagramInitHandler(mainMutationView.diagramView.mutationDiagram); - } - else - { - mainMutationView.dispatcher.on( - MutationDetailsEvents.DIAGRAM_INIT, - diagramInitHandler); - } + //if (mainMutationView.diagramView) + //{ + // diagramInitHandler(mainMutationView.diagramView.mutationDiagram); + //} + //else + //{ + // mainMutationView.dispatcher.on( + // MutationDetailsEvents.DIAGRAM_INIT, + // diagramInitHandler); + //} - if (mainMutationView.infoView) - { - infoPanelInitHandler(mainMutationView.infoView); - } - else - { - mainMutationView.dispatcher.on( - MutationDetailsEvents.INFO_PANEL_INIT, - infoPanelInitHandler); - } + //if (mainMutationView.infoView) + //{ + // infoPanelInitHandler(mainMutationView.infoView); + //} + //else + //{ + // mainMutationView.dispatcher.on( + // MutationDetailsEvents.INFO_PANEL_INIT, + // infoPanelInitHandler); + //} // add listeners for the mutation details view mutationDetailsView.dispatcher.on( MutationDetailsEvents.GENE_TAB_SELECTED, geneTabSelectHandler); + + var mutationDataDispatcher = $(mainMutationView.model.mutationData.dispatcher); + + mutationDataDispatcher.on( + MutationDetailsEvents.MUTATION_FILTER, + mutationFilterHandler + ); + + mutationDataDispatcher.on( + MutationDetailsEvents.MUTATION_HIGHLIGHT, + mutationHighlightHandler + ); + + mutationDataDispatcher.on( + MutationDetailsEvents.MUTATION_SELECT, + mutationSelectHandler + ); + } + + function mutationSelectHandler(event, mutationData) + { + if (mainMutationView.tableView) + { + // remove all table highlights + mainMutationView.tableView.clearHighlights(); + + // get all selected elements + var selected = mutationData.getState().selected; + var filtered = mutationData.getState().filtered; + + // if there are selected mutations, then only show selected + if (!_.isEmpty(selected)) + { + // filter table for the selected mutations + mainMutationView.tableView.filter(selected); + } + // if currently no selected mutations, then show only filtered ones + else if (!_.isEmpty(filtered)) + { + // filter table for the selected mutations + mainMutationView.tableView.filter(filtered); + } + // nothing selected, nothing filtered, show all available data + else + { + // reset all previous table filters + mainMutationView.tableView.resetFilters(); + } + } + } + + function mutationHighlightHandler(event, mutationData) + { + if (mainMutationView.tableView) + { + // remove all table highlights + mainMutationView.tableView.clearHighlights(); + + var mutations = mutationData.getState().highlighted; + + // get all highlighted elements + if (!_.isEmpty(mutations)) + { + // highlight table for the highlighted mutations + mainMutationView.tableView.highlight(mutations); + } + } + } + + function mutationFilterHandler(event, mutationData) + { + //TODO same as select, but may not need to implement... } function diagramInitHandler(mutationDiagram) diff --git a/src/js/data/MutationData.js b/src/js/data/MutationData.js new file mode 100644 index 0000000..d28d290 --- /dev/null +++ b/src/js/data/MutationData.js @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2016 Memorial Sloan-Kettering Cancer Center. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS + * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder + * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no + * obligations to provide maintenance, support, updates, enhancements or + * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be + * liable to any party for direct, indirect, special, incidental or + * consequential damages, including lost profits, arising out of the use of this + * software and its documentation, even if Memorial Sloan-Kettering Cancer + * Center has been advised of the possibility of such damage. + */ + +/* + * This file is part of cBioPortal. + * + * cBioPortal is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +/** + * @author Selcuk Onur Sumer + */ +function MutationData(options) +{ + var _self = this; + var _dispatcher = {}; + + var _data = { + + }; + + var _defaultOpts = { + + }; + + var _state = { + highlighted: [], + selected: [], + filtered: [] + }; + + // merge options with default options to use defaults for missing values + var _options = jQuery.extend(true, {}, _defaultOpts, options); + + function updateData(data) + { + _data = jQuery.extend(true, {}, _data, data); + } + + function setData(data) + { + _data = data; + } + + function getData() + { + return _data; + } + + function getState() + { + return _state; + } + + function add(state, mutations, event) + { + // add given mutations to the corresponding set + _state[state] = _.union(_state[state], mutations); + + // trigger a custom event + $(_dispatcher).trigger(event, _self); + } + + function remove(state, mutations, event) + { + if (mutations == null) + { + // reset all + _state[state] = []; + } + else + { + // remove given mutations from the corresponding set + _state[state] = _.difference(_state[state], mutations); + } + + // trigger a custom event + $(_dispatcher).trigger(event, _self); + } + + function highlightMutations(mutations) + { + // add given mutations to the set of highlighted mutations + add("highlighted", mutations, MutationDetailsEvents.MUTATION_HIGHLIGHT); + } + + function unHighlightMutations(mutations) + { + // remove given mutations from the set of highlighted mutations + remove("highlighted", mutations, MutationDetailsEvents.MUTATION_HIGHLIGHT); + } + + function filterMutations(mutations) + { + // add given mutations to the set of filtered mutations + add("filtered", mutations, MutationDetailsEvents.MUTATION_FILTER); + } + + function unfilterMutations(mutations) + { + // remove given mutations from the set of filtered mutations + remove("filtered", mutations, MutationDetailsEvents.MUTATION_FILTER); + } + + function selectMutations(mutations) + { + // add given mutations to the set of selected mutations + add("selected", mutations, MutationDetailsEvents.MUTATION_SELECT); + } + + function unSelectMutations(mutations) + { + // remove given mutations from the set of selected mutations + remove("selected", mutations, MutationDetailsEvents.MUTATION_SELECT); + } + + this.updateData = updateData; + this.setData = setData; + this.getData = getData; + this.getState = getState; + this.highlightMutations = highlightMutations; + this.unHighlightMutations = unHighlightMutations; + this.filterMutations = filterMutations; + this.unfilterMutations = unfilterMutations; + this.selectMutations = selectMutations; + this.unSelectMutations = unSelectMutations; + this.dispatcher = _dispatcher; +} diff --git a/src/js/view/MutationDetailsTableView.js b/src/js/view/MutationDetailsTableView.js index f5466ac..ce3f692 100644 --- a/src/js/view/MutationDetailsTableView.js +++ b/src/js/view/MutationDetailsTableView.js @@ -85,7 +85,7 @@ var MutationDetailsTableView = Backbone.View.extend({ var options = jQuery.extend(true, {}, self.model.tableOpts); options.el = options.el || self.$el.find(".mutation_details_table"); - var mutationColl = new MutationCollection(self.model.mutations); + var mutationColl = new MutationCollection(self.model.mutations.getData()); var mutationUtil = new MutationDetailsUtil(mutationColl); var table = new MutationDetailsTable( diff --git a/src/js/view/MutationDiagramView.js b/src/js/view/MutationDiagramView.js index f884975..dbe662e 100644 --- a/src/js/view/MutationDiagramView.js +++ b/src/js/view/MutationDiagramView.js @@ -128,7 +128,7 @@ var MutationDiagramView = Backbone.View.extend({ options.el = self.$el.find(".mutation-diagram-container"); // create a backbone collection for the given data - var mutationColl = new MutationCollection(mutationData); + var mutationColl = new MutationCollection(mutationData.getData()); // create a data object var diagramData = { diff --git a/src/js/view/MutationInfoPanelView.js b/src/js/view/MutationInfoPanelView.js index 8e18715..61d2727 100644 --- a/src/js/view/MutationInfoPanelView.js +++ b/src/js/view/MutationInfoPanelView.js @@ -49,13 +49,13 @@ var MutationInfoPanelView = Backbone.View.extend({ // initial count by type map //this.initialMapByType = this._mapMutationsByType(this.model.mutations); - this.initialMapByType = this._mapMutationsByMainType(this.model.mutations); + this.initialMapByType = this._mapMutationsByMainType(this.model.mutations.getData()); //this.selectionMap = this.resetSelectionMap(); }, render: function() { var self = this; - self.updateView(self.model.mutations); + self.updateView(self.model.mutations.getData()); }, format: function() { From 0724dc30145ff0fdb2c65a74ab01f41b8c01c2bc Mon Sep 17 00:00:00 2001 From: Onur Sumer Date: Thu, 15 Sep 2016 17:22:58 -0400 Subject: [PATCH 03/15] improved mutation data structure and mutation data filter controller --- .../MutationDataFilterController.js | 53 ++++++++++++++----- .../MutationDetailsTableController.js | 2 +- src/js/data/MutationData.js | 30 +++++++++++ 3 files changed, 72 insertions(+), 13 deletions(-) diff --git a/src/js/controller/MutationDataFilterController.js b/src/js/controller/MutationDataFilterController.js index 482362e..85ef05b 100644 --- a/src/js/controller/MutationDataFilterController.js +++ b/src/js/controller/MutationDataFilterController.js @@ -115,7 +115,9 @@ function MutationDataFilterController(mainMutationView) // TODO we may consider to remove the updatePlot function of mutation diagram, // and perform updates only to the mutation data set itself, then handle the updates by events. // that would simplify the mutation diagram code... - diagramResetHandler(); + + // TODO do we need to handle this event anymore? + //diagramResetHandler(); } function allDeselectHandler() @@ -125,37 +127,64 @@ function MutationDataFilterController(mainMutationView) function diagramDeselectHandler(datum, index) { - // TODO update currently selected set of mutations and trigger the corresponding event - // (selected mutations <- new set) + diagramSelectHandler(datum, index); } function diagramSelectHandler(datum, index) { - // TODO update currently selected set of mutations and trigger the corresponding event - // (selected mutations <- new set) + var selected = []; + + // get mutations for all selected elements + if (_mutationDiagram) + { + _.each(_mutationDiagram.getSelectedElements(), function (ele, i) { + selected = selected.concat(ele.datum().mutations); + }); + } + + // all deselected + if (_.isEmpty(selected)) + { + allDeselectHandler(); + } + else + { + // update currently selected set of mutations + _mutationData.updateSelectedMutations(selected); + } } function infoPanelFilterHandler(mutationType) { - // TODO update currently filtered set of mutations and trigger the corresponding event - // (filtered mutations <- new set) + // get currently filtered mutations + var filtered = mainMutationView.infoView.currentMapByType[mutationType]; + + // if all the mutations of this type are already filtered out, + // then show all mutations of this type + if (_.size(filtered) === 0) + { + filtered = mainMutationView.infoView.initialMapByType[mutationType]; + } + + // update currently filtered set of mutations + _mutationData.updateFilteredMutations(filtered); } function diagramMouseoverHandler(datum, index) { - // TODO update currently highlighted set of mutations and trigger the corresponding event - // (highlighted mutations <- new set) + // update currently highlighted set of mutations + _mutationData.updateHighlightedMutations(datum.mutations); } function diagramMouseoutHandler(datum, index) { - // TODO update currently highlighted set of mutations and trigger the corresponding event - // (highlighted mutations <- new set) + // reset currently highlighted set of mutations + _mutationData.unHighlightMutations(); } function tableFilterHandler(tableSelector) { - // TODO update currently filtered set of mutations and trigger the corresponding event + // TODO update currently filtered set of mutations // (filtered mutations <- new set) } diff --git a/src/js/controller/MutationDetailsTableController.js b/src/js/controller/MutationDetailsTableController.js index 54a16bd..e7f54bd 100644 --- a/src/js/controller/MutationDetailsTableController.js +++ b/src/js/controller/MutationDetailsTableController.js @@ -141,7 +141,7 @@ function MutationDetailsTableController(mainMutationView, mutationDetailsView) function mutationFilterHandler(event, mutationData) { - //TODO same as select, but may not need to implement... + mutationSelectHandler(event, mutationData); } function diagramInitHandler(mutationDiagram) diff --git a/src/js/data/MutationData.js b/src/js/data/MutationData.js index d28d290..0a92c1a 100644 --- a/src/js/data/MutationData.js +++ b/src/js/data/MutationData.js @@ -75,6 +75,18 @@ function MutationData(options) return _state; } + // TODO do not fire an event in case the state remains identical after an add/remove/update function call! + + function update(state, mutations, event) + { + // update the corresponding set with the given mutations + // this overrides all the previous content! + _state[state] = mutations; + + // trigger a custom event + $(_dispatcher).trigger(event, _self); + } + function add(state, mutations, event) { // add given mutations to the corresponding set @@ -101,6 +113,11 @@ function MutationData(options) $(_dispatcher).trigger(event, _self); } + function updateHighlightedMutations(mutations) + { + update("highlighted", mutations, MutationDetailsEvents.MUTATION_HIGHLIGHT); + } + function highlightMutations(mutations) { // add given mutations to the set of highlighted mutations @@ -113,6 +130,11 @@ function MutationData(options) remove("highlighted", mutations, MutationDetailsEvents.MUTATION_HIGHLIGHT); } + function updateFilteredMutations(mutations) + { + update("filtered", mutations, MutationDetailsEvents.MUTATION_FILTER); + } + function filterMutations(mutations) { // add given mutations to the set of filtered mutations @@ -125,6 +147,11 @@ function MutationData(options) remove("filtered", mutations, MutationDetailsEvents.MUTATION_FILTER); } + function updateSelectedMutations(mutations) + { + update("selected", mutations, MutationDetailsEvents.MUTATION_SELECT); + } + function selectMutations(mutations) { // add given mutations to the set of selected mutations @@ -141,10 +168,13 @@ function MutationData(options) this.setData = setData; this.getData = getData; this.getState = getState; + this.updateHighlightedMutations = updateHighlightedMutations; this.highlightMutations = highlightMutations; this.unHighlightMutations = unHighlightMutations; + this.updateFilteredMutations = updateFilteredMutations; this.filterMutations = filterMutations; this.unfilterMutations = unfilterMutations; + this.updateSelectedMutations = updateSelectedMutations; this.selectMutations = selectMutations; this.unSelectMutations = unSelectMutations; this.dispatcher = _dispatcher; From f7ef18dc7417fbf9f3a46991ce34e3d30e4dd3e8 Mon Sep 17 00:00:00 2001 From: Onur Sumer Date: Fri, 16 Sep 2016 17:37:42 -0400 Subject: [PATCH 04/15] most of the controllers now listen to the mutation data events instead of the events dispatched from other components --- src/js/controller/MainMutationController.js | 100 +++------ .../MutationDataFilterController.js | 55 ++--- .../controller/MutationDetailsController.js | 3 +- .../MutationDetailsTableController.js | 190 +----------------- .../controller/MutationDiagramController.js | 97 +++------ src/js/controller/MutationInfoController.js | 110 ++++------ src/js/data/MutationData.js | 11 +- src/js/view/MainMutationView.js | 6 + 8 files changed, 144 insertions(+), 428 deletions(-) diff --git a/src/js/controller/MainMutationController.js b/src/js/controller/MainMutationController.js index 6f54cd8..5079690 100644 --- a/src/js/controller/MainMutationController.js +++ b/src/js/controller/MainMutationController.js @@ -43,97 +43,63 @@ function MainMutationController(mainMutationView) function init() { - if (mainMutationView.diagramView) - { - diagramInitHandler(mainMutationView.diagramView.mutationDiagram); - } - else - { - mainMutationView.dispatcher.on( - MutationDetailsEvents.DIAGRAM_INIT, - diagramInitHandler); - } - - // also init reset link call back + // init reset link call back mainMutationView.addResetCallback(handleReset); - } - - function diagramInitHandler(mutationDiagram) - { - // update class variable - _mutationDiagram = mutationDiagram; - - // add listeners to the custom event dispatcher of the diagram - mutationDiagram.dispatcher.on( - MutationDetailsEvents.ALL_LOLLIPOPS_DESELECTED, - allDeselectHandler); - - mutationDiagram.dispatcher.on( - MutationDetailsEvents.LOLLIPOP_DESELECTED, - deselectHandler); - mutationDiagram.dispatcher.on( - MutationDetailsEvents.LOLLIPOP_SELECTED, - selectHandler); + var mutationDataDispatcher = $(mainMutationView.model.mutationData.dispatcher); - mutationDiagram.dispatcher.on( - MutationDetailsEvents.DIAGRAM_PLOT_UPDATED, - diagramUpdateHandler); - } + mutationDataDispatcher.on( + MutationDetailsEvents.MUTATION_FILTER, + mutationFilterHandler + ); - function handleReset(event) - { - // reset the diagram contents - if (_mutationDiagram) - { - _mutationDiagram.resetPlot(); - } + mutationDataDispatcher.on( + MutationDetailsEvents.MUTATION_HIGHLIGHT, + mutationHighlightHandler + ); - // hide the filter info text - mainMutationView.hideFilterInfo(); + mutationDataDispatcher.on( + MutationDetailsEvents.MUTATION_SELECT, + mutationSelectHandler + ); } - function diagramUpdateHandler() + function mutationSelectHandler(event, mutationData) { - if (_mutationDiagram && - _mutationDiagram.isFiltered()) + // get all selected elements + var selected = mutationData.getState().selected; + var filtered = mutationData.getState().filtered; + var data = mutationData.getData(); + + // if there are selected or filtered out mutations then show filter info + if (!_.isEmpty(selected) || + _.size(data) !== _.size(filtered)) { - // display info text mainMutationView.showFilterInfo(); } + // nothing selected, nothing filtered out, hide filter info else { - // hide info text mainMutationView.hideFilterInfo(); } } - function allDeselectHandler() + function mutationHighlightHandler(event, mutationData) { - // hide filter reset info - if (_mutationDiagram && - !_mutationDiagram.isFiltered()) - { - mainMutationView.hideFilterInfo(); - } + // no need to handle for now, update if necessary } - function deselectHandler(datum, index) + function mutationFilterHandler(event, mutationData) { - // check if all deselected - // (always show text if still there is a selected data point) - if (_mutationDiagram && - _mutationDiagram.getSelectedElements().length == 0) - { - // hide filter reset info - allDeselectHandler(); - } + mutationSelectHandler(event, mutationData); } - function selectHandler(datum, index) + function handleReset(event) { - // show filter reset info - mainMutationView.showFilterInfo(); + // TODO it might be better to call one function instead of three! + mainMutationView.model.mutationData.unHighlightMutations(); + mainMutationView.model.mutationData.unSelectMutations(); + mainMutationView.model.mutationData.unfilterMutations(); } init(); diff --git a/src/js/controller/MutationDataFilterController.js b/src/js/controller/MutationDataFilterController.js index 85ef05b..4e00b0a 100644 --- a/src/js/controller/MutationDataFilterController.js +++ b/src/js/controller/MutationDataFilterController.js @@ -93,31 +93,6 @@ function MutationDataFilterController(mainMutationView) mutationDiagram.dispatcher.on( MutationDetailsEvents.LOLLIPOP_MOUSEOUT, diagramMouseoutHandler); - - mutationDiagram.dispatcher.on( - MutationDetailsEvents.DIAGRAM_PLOT_UPDATED, - diagramUpdateHandler); - - mutationDiagram.dispatcher.on( - MutationDetailsEvents.DIAGRAM_PLOT_RESET, - diagramResetHandler); - } - - function diagramResetHandler() - { - _mutationData.unHighlightMutations(); - _mutationData.unSelectMutations(); - _mutationData.unfilterMutations(); - } - - function diagramUpdateHandler() - { - // TODO we may consider to remove the updatePlot function of mutation diagram, - // and perform updates only to the mutation data set itself, then handle the updates by events. - // that would simplify the mutation diagram code... - - // TODO do we need to handle this event anymore? - //diagramResetHandler(); } function allDeselectHandler() @@ -184,8 +159,34 @@ function MutationDataFilterController(mainMutationView) function tableFilterHandler(tableSelector) { - // TODO update currently filtered set of mutations - // (filtered mutations <- new set) + var filtered = []; + + // add current (filtered) mutations into an array + var rowData = []; + + // TODO this try/catch block is for backward compatibility, + // we will no longer need this once we completely migrate to DataTables 1.10 + try { + // first, try new API. + // this is not backward compatible, requires DataTables 1.10 or later. + rowData = $(tableSelector).DataTable().rows({filter: "applied"}).data(); + } catch(err) { + // if DataTables 1.10 is not available, try the old API function. + // DataTables 1.9.4 compatible code (which doesn't work with deferRender): + rowData = $(tableSelector).dataTable()._('tr', {filter: "applied"}); + } + + _.each(rowData, function(data, index) { + // assuming only the first element contains the datum + var mutation = data[0].mutation; + + if (mutation) + { + filtered.push(mutation); + } + }); + + _mutationData.updateFilteredMutations(filtered); } init(); diff --git a/src/js/controller/MutationDetailsController.js b/src/js/controller/MutationDetailsController.js index b743919..97d41c6 100644 --- a/src/js/controller/MutationDetailsController.js +++ b/src/js/controller/MutationDetailsController.js @@ -307,8 +307,7 @@ function MutationDetailsController( new MutationInfoController(mainView); } - new MutationDiagramController( - diagramView.mutationDiagram, mutationTable, infoView, mutationUtil); + new MutationDiagramController(mainView); } } diff --git a/src/js/controller/MutationDetailsTableController.js b/src/js/controller/MutationDetailsTableController.js index e7f54bd..72cfbaf 100644 --- a/src/js/controller/MutationDetailsTableController.js +++ b/src/js/controller/MutationDetailsTableController.js @@ -40,32 +40,8 @@ */ function MutationDetailsTableController(mainMutationView, mutationDetailsView) { - var _mutationDiagram = null; - function init() { - //if (mainMutationView.diagramView) - //{ - // diagramInitHandler(mainMutationView.diagramView.mutationDiagram); - //} - //else - //{ - // mainMutationView.dispatcher.on( - // MutationDetailsEvents.DIAGRAM_INIT, - // diagramInitHandler); - //} - - //if (mainMutationView.infoView) - //{ - // infoPanelInitHandler(mainMutationView.infoView); - //} - //else - //{ - // mainMutationView.dispatcher.on( - // MutationDetailsEvents.INFO_PANEL_INIT, - // infoPanelInitHandler); - //} - // add listeners for the mutation details view mutationDetailsView.dispatcher.on( MutationDetailsEvents.GENE_TAB_SELECTED, @@ -112,11 +88,10 @@ function MutationDetailsTableController(mainMutationView, mutationDetailsView) // filter table for the selected mutations mainMutationView.tableView.filter(filtered); } - // nothing selected, nothing filtered, show all available data + // nothing selected, nothing filtered, show nothing else { - // reset all previous table filters - mainMutationView.tableView.resetFilters(); + // TODO hide everything! } } } @@ -144,167 +119,6 @@ function MutationDetailsTableController(mainMutationView, mutationDetailsView) mutationSelectHandler(event, mutationData); } - function diagramInitHandler(mutationDiagram) - { - // update class variable - _mutationDiagram = mutationDiagram; - - // add listeners to the custom event dispatcher of the diagram - mutationDiagram.dispatcher.on( - MutationDetailsEvents.ALL_LOLLIPOPS_DESELECTED, - allDeselectHandler); - - mutationDiagram.dispatcher.on( - MutationDetailsEvents.LOLLIPOP_DESELECTED, - deselectHandler); - - mutationDiagram.dispatcher.on( - MutationDetailsEvents.LOLLIPOP_SELECTED, - selectHandler); - - mutationDiagram.dispatcher.on( - MutationDetailsEvents.LOLLIPOP_MOUSEOVER, - mouseoverHandler); - - mutationDiagram.dispatcher.on( - MutationDetailsEvents.LOLLIPOP_MOUSEOUT, - mouseoutHandler); - - mutationDiagram.dispatcher.on( - MutationDetailsEvents.DIAGRAM_PLOT_RESET, - diagramResetHandler); - } - - function infoPanelInitHandler(infoView) - { - // add listeners to the custom event dispatcher of the info panel view - if (infoView) - { - infoView.dispatcher.on( - MutationDetailsEvents.INFO_PANEL_MUTATION_TYPE_SELECTED, - infoPanelFilterHandler); - } - } - - function diagramResetHandler() - { - if (mainMutationView.tableView) - { - // reset all previous table filters - mainMutationView.tableView.resetFilters(); - } - } - - function allDeselectHandler() - { - if (mainMutationView.tableView) - { - // remove all table highlights - mainMutationView.tableView.clearHighlights(); - - // filter with all visible diagram mutations - mainMutationView.tableView.filter(PileupUtil.getPileupMutations( - _mutationDiagram.pileups)); - } - } - - function deselectHandler(datum, index) - { - if (mainMutationView.tableView) - { - // remove all table highlights - mainMutationView.tableView.clearHighlights(); - - var mutations = []; - - // get mutations for all selected elements - if (_mutationDiagram) - { - _.each(_mutationDiagram.getSelectedElements(), function (ele, i) { - mutations = mutations.concat(ele.datum().mutations); - }); - } - - // reselect with the reduced selection - if (mutations.length > 0) - { - // filter table for the selected mutations - mainMutationView.tableView.filter(mutations); - } - // rollback only if none selected - else - { - // filter with all visible diagram mutations - mainMutationView.tableView.filter(PileupUtil.getPileupMutations( - _mutationDiagram.pileups)); - } - } - } - - function selectHandler(datum, index) - { - if (mainMutationView.tableView) - { - // remove all table highlights - mainMutationView.tableView.clearHighlights(); - - var mutations = []; - - // get mutations for all selected elements - if (_mutationDiagram) - { - _.each(_mutationDiagram.getSelectedElements(), function (ele, i) - { - mutations = mutations.concat(ele.datum().mutations); - }); - } - - // filter table for the selected mutations - mainMutationView.tableView.filter(mutations); - } - } - - function infoPanelFilterHandler(mutationType) - { - if (mainMutationView.tableView !== null) - { - // get currently filtered mutations - var mutations = mainMutationView.infoView.currentMapByType[mutationType]; - - if (_.size(mutations) > 0) - { - mainMutationView.tableView.filter(mutations); - } - // if all the mutations of this type are already filtered out, - // then show all mutations of this type - else - { - mutations = mainMutationView.infoView.initialMapByType[mutationType]; - mainMutationView.tableView.filter(mutations); - // clear search box value since the filtering with that value is no longer valid - mainMutationView.tableView.clearSearchBox(); - } - } - } - - function mouseoverHandler(datum, index) - { - if (mainMutationView.tableView) - { - // highlight mutations for the provided mutations - mainMutationView.tableView.highlight(datum.mutations); - } - } - - function mouseoutHandler(datum, index) - { - if (mainMutationView.tableView) - { - // remove all highlights - mainMutationView.tableView.clearHighlights(); - } - } - function geneTabSelectHandler(gene) { if (mainMutationView.tableView) diff --git a/src/js/controller/MutationDiagramController.js b/src/js/controller/MutationDiagramController.js index c7658ac..19b43ec 100644 --- a/src/js/controller/MutationDiagramController.js +++ b/src/js/controller/MutationDiagramController.js @@ -35,27 +35,10 @@ * * @author Selcuk Onur Sumer */ -function MutationDiagramController(mutationDiagram, mutationTable, infoPanelView, mutationUtil) +function MutationDiagramController(mainMutationView) { function init() { - // add listeners to the custom event dispatcher of the mutation table - if (mutationTable) - { - mutationTable.dispatcher.on( - MutationDetailsEvents.MUTATION_TABLE_FILTERED, - tableFilterHandler); - } - - // TODO add info panel init handler, this will require controller parameter modification/simplification - // add listeners to the custom event dispatcher of the info panel view - if (infoPanelView) - { - infoPanelView.dispatcher.on( - MutationDetailsEvents.INFO_PANEL_MUTATION_TYPE_SELECTED, - infoPanelFilterHandler); - } - // TODO make sure to call these event handlers before 3D controller's handler, // otherwise 3D update will not work properly. // (this requires event handler prioritization which is not trivial) @@ -69,63 +52,43 @@ function MutationDiagramController(mutationDiagram, mutationTable, infoPanelView // mutationTable.dispatcher.on( // MutationDetailsEvents.PDB_LINK_CLICKED, // proteinChangeLinkHandler); - } - function tableFilterHandler(tableSelector) - { - var currentMutations = []; - - // add current (filtered) mutations into an array - var rowData = []; - - // TODO this try/catch block is for backward compatibility, - // we will no longer need this once we completely migrate to DataTables 1.10 - try { - // first, try new API. - // this is not backward compatible, requires DataTables 1.10 or later. - rowData = $(tableSelector).DataTable().rows({filter: "applied"}).data(); - } catch(err) { - // if DataTables 1.10 is not available, try the old API function. - // DataTables 1.9.4 compatible code (which doesn't work with deferRender): - rowData = $(tableSelector).dataTable()._('tr', {filter: "applied"}); - } + var mutationDataDispatcher = $(mainMutationView.model.mutationData.dispatcher); - _.each(rowData, function(data, index) { - // assuming only the first element contains the datum - var mutation = data[0].mutation; + mutationDataDispatcher.on( + MutationDetailsEvents.MUTATION_FILTER, + mutationFilterHandler + ); - if (mutation) - { - currentMutations.push(mutation); - } - }); + mutationDataDispatcher.on( + MutationDetailsEvents.MUTATION_HIGHLIGHT, + mutationHighlightHandler + ); - // update mutation diagram with the current mutations - if (mutationDiagram !== null) - { - var mutationData = new MutationCollection(currentMutations); - mutationDiagram.updatePlot(mutationData); - } + mutationDataDispatcher.on( + MutationDetailsEvents.MUTATION_SELECT, + mutationSelectHandler + ); + } + + function mutationSelectHandler(event, mutationData) + { + // TODO highlight mutations on the diagram } - function infoPanelFilterHandler(mutationType) + function mutationHighlightHandler(event, mutationData) { - if (mutationDiagram !== null) + mutationSelectHandler(event, mutationData); + } + + function mutationFilterHandler(event, mutationData) + { + if (mainMutationView.diagramView) { - // get currently filtered mutations - var mutations = infoPanelView.currentMapByType[mutationType]; - - if (_.size(mutations) > 0) - { - mutationDiagram.updatePlot(new MutationCollection(mutations)); - } - // if all the mutations of this type are already filtered out, - // then show all mutations of this type - else - { - mutations = infoPanelView.initialMapByType[mutationType]; - mutationDiagram.updatePlot(new MutationCollection(mutations)); - } + var filtered = mutationData.getState().filtered; + + mainMutationView.diagramView.mutationDiagram.updatePlot( + new MutationCollection(filtered)); } } diff --git a/src/js/controller/MutationInfoController.js b/src/js/controller/MutationInfoController.js index b29d7c0..7e6e083 100644 --- a/src/js/controller/MutationInfoController.js +++ b/src/js/controller/MutationInfoController.js @@ -37,103 +37,63 @@ */ function MutationInfoController(mainMutationView) { - var _mutationDiagram = null; - function init() { - // TODO if diagram is disabled, use table data instead... - - if (mainMutationView.diagramView) - { - diagramInitHandler(mainMutationView.diagramView.mutationDiagram); - } - else - { - mainMutationView.dispatcher.on( - MutationDetailsEvents.DIAGRAM_INIT, - diagramInitHandler); - } - } - - function diagramInitHandler(mutationDiagram) - { - // update class variable - _mutationDiagram = mutationDiagram; - - // add listeners to the custom event dispatcher of the diagram - mutationDiagram.dispatcher.on( - MutationDetailsEvents.DIAGRAM_PLOT_RESET, - diagramResetHandler); - - mutationDiagram.dispatcher.on( - MutationDetailsEvents.DIAGRAM_PLOT_UPDATED, - diagramUpdateHandler); - - mutationDiagram.dispatcher.on( - MutationDetailsEvents.LOLLIPOP_SELECTED, - selectHandler); - - mutationDiagram.dispatcher.on( - MutationDetailsEvents.LOLLIPOP_DESELECTED, - deselectHandler); - - mutationDiagram.dispatcher.on( - MutationDetailsEvents.ALL_LOLLIPOPS_DESELECTED, - allDeselectHandler); - } - - function allDeselectHandler() - { - diagramUpdateHandler(); + var mutationDataDispatcher = $(mainMutationView.model.mutationData.dispatcher); + + mutationDataDispatcher.on( + MutationDetailsEvents.MUTATION_FILTER, + mutationFilterHandler + ); + + mutationDataDispatcher.on( + MutationDetailsEvents.MUTATION_HIGHLIGHT, + mutationHighlightHandler + ); + + mutationDataDispatcher.on( + MutationDetailsEvents.MUTATION_SELECT, + mutationSelectHandler + ); } - function deselectHandler(datum, index) + function mutationSelectHandler(event, mutationData) { if (mainMutationView.infoView) { - var pileups = []; + // get all selected elements + var selected = mutationData.getState().selected; + var filtered = mutationData.getState().filtered; - // get pileups for all selected elements - if (_mutationDiagram) + // if there are selected mutations, then only show selected + if (!_.isEmpty(selected)) { - _.each(_mutationDiagram.getSelectedElements(), function (ele, i) { - pileups = pileups.concat(ele.datum()); - }); + // filter info for the selected mutations + mainMutationView.infoView.updateView(selected); } - - // reselect with the reduced selection - if (pileups.length > 0) + // if currently no selected mutations, filter info filtered ones + else if (!_.isEmpty(filtered)) { - mainMutationView.infoView.updateView( - PileupUtil.getPileupMutations(pileups)); + // filter table for the selected mutations + mainMutationView.infoView.updateView(filtered); } - // rollback only if none selected + // nothing selected, nothing filtered, show nothing else { - // roll back the table to its previous state - // (to the last state when a manual filtering applied) - diagramUpdateHandler(); + // reset all previous table filters + mainMutationView.infoView.updateView([]); } } } - function selectHandler(datum, index) + function mutationHighlightHandler(event, mutationData) { - deselectHandler(datum, index); + // no need to handle for now, update if required... } - function diagramResetHandler() + function mutationFilterHandler(event, mutationData) { - diagramUpdateHandler(); - } - - function diagramUpdateHandler() - { - if (mainMutationView.infoView) - { - mainMutationView.infoView.updateView( - PileupUtil.getPileupMutations(_mutationDiagram.pileups)); - } + mutationSelectHandler(event, mutationData); } init(); diff --git a/src/js/data/MutationData.js b/src/js/data/MutationData.js index 0a92c1a..f7f584e 100644 --- a/src/js/data/MutationData.js +++ b/src/js/data/MutationData.js @@ -63,6 +63,7 @@ function MutationData(options) function setData(data) { _data = data; + _state.filtered = data; } function getData() @@ -143,8 +144,14 @@ function MutationData(options) function unfilterMutations(mutations) { - // remove given mutations from the set of filtered mutations - remove("filtered", mutations, MutationDetailsEvents.MUTATION_FILTER); + if (mutations == null) { + _state.filtered = _data; + $(_dispatcher).trigger(MutationDetailsEvents.MUTATION_FILTER, _self); + } + else { + // remove given mutations from the set of filtered mutations + remove("filtered", mutations, MutationDetailsEvents.MUTATION_FILTER); + } } function updateSelectedMutations(mutations) diff --git a/src/js/view/MainMutationView.js b/src/js/view/MainMutationView.js index df19a3c..e18bf55 100644 --- a/src/js/view/MainMutationView.js +++ b/src/js/view/MainMutationView.js @@ -265,6 +265,12 @@ var MainMutationView = Backbone.View.extend({ { console.log("Error initializing mutation table: %s", self.model.geneSymbol); } + else + { + self.dispatcher.trigger( + MutationDetailsEvents.MUTATION_TABLE_INITIALIZED, + self.tableView.mutationTable); + } return self.tableView; }, From 010af81511f70db0baf9e9ec4359c37bdeeead96 Mon Sep 17 00:00:00 2001 From: Onur Sumer Date: Mon, 19 Sep 2016 15:38:51 -0400 Subject: [PATCH 05/15] 3D controller is now handling mutation data events instead of mutation diagram events --- src/js/controller/Mutation3dController.js | 163 ++++++++-------------- 1 file changed, 60 insertions(+), 103 deletions(-) diff --git a/src/js/controller/Mutation3dController.js b/src/js/controller/Mutation3dController.js index b65518d..ef9332e 100644 --- a/src/js/controller/Mutation3dController.js +++ b/src/js/controller/Mutation3dController.js @@ -65,15 +65,19 @@ function Mutation3dController(mutationDetailsView, mainMutationView, viewOptions function init() { - if (mainMutationView.diagramView) + if (mainMutationView.diagramView && + mainMutationView.diagramView.mutationDiagram) { - diagramInitHandler(mainMutationView.diagramView.mutationDiagram); + //diagramInitHandler(mainMutationView.diagramView.mutationDiagram); + _mutationDiagram = mainMutationView.diagramView.mutationDiagram; } else { mainMutationView.dispatcher.on( MutationDetailsEvents.DIAGRAM_INIT, - diagramInitHandler); + function(diagram) { + _mutationDiagram = diagram; + }); } if (mainMutationView.tableView && @@ -109,41 +113,67 @@ function Mutation3dController(mutationDetailsView, mainMutationView, viewOptions MutationDetailsEvents.VIS_3D_PANEL_CREATED, vis3dCreateHandler); } - } - function diagramInitHandler(mutationDiagram) - { - // update class variable - _mutationDiagram = mutationDiagram; + var mutationDataDispatcher = $(mainMutationView.model.mutationData.dispatcher); - // add listeners to the custom event dispatcher of the diagram - mutationDiagram.dispatcher.on( - MutationDetailsEvents.ALL_LOLLIPOPS_DESELECTED, - allDeselectHandler); + mutationDataDispatcher.on( + MutationDetailsEvents.MUTATION_FILTER, + mutationFilterHandler + ); - mutationDiagram.dispatcher.on( - MutationDetailsEvents.LOLLIPOP_DESELECTED, - diagramDeselectHandler); + mutationDataDispatcher.on( + MutationDetailsEvents.MUTATION_HIGHLIGHT, + mutationHighlightHandler + ); - mutationDiagram.dispatcher.on( - MutationDetailsEvents.LOLLIPOP_SELECTED, - diagramSelectHandler); + mutationDataDispatcher.on( + MutationDetailsEvents.MUTATION_SELECT, + mutationSelectHandler + ); + } - mutationDiagram.dispatcher.on( - MutationDetailsEvents.LOLLIPOP_MOUSEOVER, - diagramMouseoverHandler); + function mutationSelectHandler(event, mutationData, noWarning) + { + if (_mut3dVisView && _mut3dVisView.isVisible()) + { + // get all selected and highlighted elements + var selected = mutationData.getState().selected; + var highlighted = mutationData.getState().highlighted; - mutationDiagram.dispatcher.on( - MutationDetailsEvents.LOLLIPOP_MOUSEOUT, - diagramMouseoutHandler); + var combined = _.union(selected, highlighted); - mutationDiagram.dispatcher.on( - MutationDetailsEvents.DIAGRAM_PLOT_UPDATED, - diagramUpdateHandler); + if (!_.isEmpty(combined)) + { + // TODO this is an expensive conversion, + // find a better/faster way to highlight residues without using pileup data + var pileups = PileupUtil.convertToPileups(new MutationCollection(combined)); + highlight3dResidues(pileups, noWarning); + } + // nothing selected, nothing filtered, show nothing + else + { + // remove all highlights! + _mut3dVisView.resetHighlight(); + _mut3dVisView.hideResidueWarning(); + } + } + } - mutationDiagram.dispatcher.on( - MutationDetailsEvents.DIAGRAM_PLOT_RESET, - diagramResetHandler); + function mutationHighlightHandler(event, mutationData) + { + // in case of highlight event, no need to update the warning message. + // so set noWarning = true + mutationSelectHandler(event, mutationData, true); + } + + function mutationFilterHandler(event, mutationData) + { + // refresh view wrt to filtered data + if (_mut3dVisView && _mut3dVisView.isVisible()) + { + // reset all previous visualizer filters + _mut3dVisView.refreshView(); + } } function vis3dCreateHandler(mutation3dVisView) @@ -399,79 +429,6 @@ function Mutation3dController(mutationDetailsView, mainMutationView, viewOptions } } } - function diagramResetHandler() - { - if (_mut3dVisView && _mut3dVisView.isVisible()) - { - // reset all previous visualizer filters - _mut3dVisView.refreshView(); - } - } - - function diagramUpdateHandler() - { - // refresh 3d view with filtered positions - if (_mut3dVisView && _mut3dVisView.isVisible()) - { - _mut3dVisView.refreshView(); - } - } - - function allDeselectHandler() - { - if (_mut3dVisView && _mut3dVisView.isVisible()) - { - _mut3dVisView.resetHighlight(); - _mut3dVisView.hideResidueWarning(); - } - } - - function diagramDeselectHandler(datum, index) - { - // check if the diagram is still highlighted - if (_mutationDiagram && - _mutationDiagram.isHighlighted()) - { - // reselect with the reduced selection - diagramSelectHandler(); - } - else - { - // no highlights (all deselected) - allDeselectHandler(); - } - } - - function diagramSelectHandler(datum, index) - { - // highlight the corresponding residue in 3D view - if (_mut3dVisView && _mut3dVisView.isVisible()) - { - highlightSelected(); - } - } - - function diagramMouseoverHandler(datum, index) - { - // highlight the corresponding residue in 3D view - if (_mut3dVisView && _mut3dVisView.isVisible()) - { - // selected pileups (mutations) on the diagram - var pileups = getSelectedPileups(); - - // add the mouse over datum - pileups.push(datum); - - // highlight (selected + mouseover) residues - highlight3dResidues(pileups, true); - } - } - - function diagramMouseoutHandler(datum, index) - { - // same as the deselect action... - diagramDeselectHandler(datum, index); - } function proteinChangeLinkHandler(mutationId) { From 1a558cc990ce59ae074794003e50d8175d82fc9f Mon Sep 17 00:00:00 2001 From: Onur Sumer Date: Wed, 21 Sep 2016 17:23:31 -0400 Subject: [PATCH 06/15] added protein change and pdb link click handlers into the mutation data filter controller --- src/js/controller/Mutation3dController.js | 41 ++----------------- .../MutationDataFilterController.js | 36 ++++++++++++++++ .../MutationDetailsTableController.js | 1 + .../controller/MutationDiagramController.js | 30 +------------- src/js/data/MutationData.js | 9 ++++ 5 files changed, 52 insertions(+), 65 deletions(-) diff --git a/src/js/controller/Mutation3dController.js b/src/js/controller/Mutation3dController.js index ef9332e..a61a0b5 100644 --- a/src/js/controller/Mutation3dController.js +++ b/src/js/controller/Mutation3dController.js @@ -87,10 +87,6 @@ function Mutation3dController(mutationDetailsView, mainMutationView, viewOptions mainMutationView.tableView.mutationTable.dispatcher.on( MutationDetailsEvents.PDB_LINK_CLICKED, pdbLinkHandler); - - mainMutationView.tableView.mutationTable.dispatcher.on( - MutationDetailsEvents.PROTEIN_CHANGE_LINK_CLICKED, - proteinChangeLinkHandler); } // add listeners for the mutation 3d view @@ -430,23 +426,10 @@ function Mutation3dController(mutationDetailsView, mainMutationView, viewOptions } } - function proteinChangeLinkHandler(mutationId) - { - var mutation = highlightDiagram(mutationId); - - if (mutation) - { - // highlight the corresponding residue in 3D view - if (_mut3dVisView && _mut3dVisView.isVisible()) - { - highlightSelected(); - } - } - } - function pdbLinkHandler(mutationId) { - var mutation = highlightDiagram(mutationId); + var mutationMap = mutationUtil.getMutationIdMap(); + var mutation = mutationMap[mutationId]; if (mutation) { @@ -456,24 +439,6 @@ function Mutation3dController(mutationDetailsView, mainMutationView, viewOptions } } - // TODO ideally diagram should be highlighted by MutationDiagramController, - // but we need to make sure that diagram is highlighted before refreshing the 3D view - // (this needs event handler prioritization which is not trivial) - function highlightDiagram(mutationId) - { - var mutationMap = mutationUtil.getMutationIdMap(); - var mutation = mutationMap[mutationId]; - - if (mutation && _mutationDiagram) - { - // highlight the corresponding pileup (without filtering the table) - _mutationDiagram.clearHighlights(); - _mutationDiagram.highlightMutation(mutation.get("mutationSid")); - } - - return mutation; - } - /** * Retrieves the pileup data from the selected mutation diagram * elements. @@ -500,6 +465,8 @@ function Mutation3dController(mutationDetailsView, mainMutationView, viewOptions */ function highlightSelected() { + // TODO use the mutationHighlightHandler instead? + // selected pileups (mutations) on the diagram var selected = getSelectedPileups(); diff --git a/src/js/controller/MutationDataFilterController.js b/src/js/controller/MutationDataFilterController.js index 4e00b0a..92ff258 100644 --- a/src/js/controller/MutationDataFilterController.js +++ b/src/js/controller/MutationDataFilterController.js @@ -66,6 +66,14 @@ function MutationDataFilterController(mainMutationView) mutationTable.dispatcher.on( MutationDetailsEvents.MUTATION_TABLE_FILTERED, tableFilterHandler); + + mutationTable.dispatcher.on( + MutationDetailsEvents.PDB_LINK_CLICKED, + pdbLinkHandler); + + mutationTable.dispatcher.on( + MutationDetailsEvents.PROTEIN_CHANGE_LINK_CLICKED, + proteinChangeLinkHandler); } function diagramInitHandler(mutationDiagram) @@ -97,6 +105,7 @@ function MutationDataFilterController(mainMutationView) function allDeselectHandler() { + _mutationData.unHighlightMutations(); _mutationData.unSelectMutations(); } @@ -189,5 +198,32 @@ function MutationDataFilterController(mainMutationView) _mutationData.updateFilteredMutations(filtered); } + function proteinChangeLinkHandler(mutationId) + { + var mutationMap = _mutationData.getDataUtil().getMutationIdMap(); + var mutation = mutationMap[mutationId]; + + if (mutation) + { + // TODO ideally diagram should be highlighted by MutationDiagramController + // by using the mutation data state (both current state and prev state) + + // highlight the corresponding pileup (without filtering the table) + _mutationDiagram.clearHighlights(); + _mutationDiagram.highlightMutation(mutation.get("mutationSid")); + + _mutationData.updateHighlightedMutations([mutation]); + } + else + { + _mutationData.unHighlightMutations(); + } + } + + function pdbLinkHandler(mutationId) + { + proteinChangeLinkHandler(mutationId); + } + init(); } diff --git a/src/js/controller/MutationDetailsTableController.js b/src/js/controller/MutationDetailsTableController.js index 72cfbaf..6699fb8 100644 --- a/src/js/controller/MutationDetailsTableController.js +++ b/src/js/controller/MutationDetailsTableController.js @@ -92,6 +92,7 @@ function MutationDetailsTableController(mainMutationView, mutationDetailsView) else { // TODO hide everything! + // (currently we don't need this because, table filter handles this internally) } } } diff --git a/src/js/controller/MutationDiagramController.js b/src/js/controller/MutationDiagramController.js index 19b43ec..a128303 100644 --- a/src/js/controller/MutationDiagramController.js +++ b/src/js/controller/MutationDiagramController.js @@ -39,20 +39,6 @@ function MutationDiagramController(mainMutationView) { function init() { - // TODO make sure to call these event handlers before 3D controller's handler, - // otherwise 3D update will not work properly. - // (this requires event handler prioritization which is not trivial) - - // add listeners for the mutation table view - -// mutationTable.dispatcher.on( -// MutationDetailsEvents.PROTEIN_CHANGE_LINK_CLICKED, -// proteinChangeLinkHandler); - -// mutationTable.dispatcher.on( -// MutationDetailsEvents.PDB_LINK_CLICKED, -// proteinChangeLinkHandler); - var mutationDataDispatcher = $(mainMutationView.model.mutationData.dispatcher); mutationDataDispatcher.on( @@ -73,7 +59,8 @@ function MutationDiagramController(mainMutationView) function mutationSelectHandler(event, mutationData) { - // TODO highlight mutations on the diagram + // TODO this is a bit complicated right now + // we need the previous state of the mutation data to have a seamless visual transition } function mutationHighlightHandler(event, mutationData) @@ -92,18 +79,5 @@ function MutationDiagramController(mainMutationView) } } - function proteinChangeLinkHandler(mutationId) - { - var mutationMap = mutationUtil.getMutationIdMap(); - var mutation = mutationMap[mutationId]; - - if (mutation) - { - // highlight the corresponding pileup (without filtering the table) - mutationDiagram.clearHighlights(); - mutationDiagram.highlightMutation(mutation.get("mutationSid")); - } - } - init(); } diff --git a/src/js/data/MutationData.js b/src/js/data/MutationData.js index f7f584e..5249ece 100644 --- a/src/js/data/MutationData.js +++ b/src/js/data/MutationData.js @@ -37,6 +37,7 @@ function MutationData(options) { var _self = this; var _dispatcher = {}; + var _mutationDataUtil = null; var _data = { @@ -64,6 +65,8 @@ function MutationData(options) { _data = data; _state.filtered = data; + _mutationDataUtil = new MutationDetailsUtil( + new MutationCollection(data)); } function getData() @@ -71,6 +74,11 @@ function MutationData(options) return _data; } + function getDataUtil() + { + return _mutationDataUtil; + } + function getState() { return _state; @@ -174,6 +182,7 @@ function MutationData(options) this.updateData = updateData; this.setData = setData; this.getData = getData; + this.getDataUtil = getDataUtil; this.getState = getState; this.updateHighlightedMutations = updateHighlightedMutations; this.highlightMutations = highlightMutations; From fd2cf8d74928fbe3c6ba6fc6b62f7c152b90760a Mon Sep 17 00:00:00 2001 From: Onur Sumer Date: Thu, 22 Sep 2016 16:52:00 -0400 Subject: [PATCH 07/15] minor improvement for 3D controller --- src/js/controller/Mutation3dController.js | 18 ++++++------------ src/js/data/MutationData.js | 2 +- 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/src/js/controller/Mutation3dController.js b/src/js/controller/Mutation3dController.js index a61a0b5..cf8647e 100644 --- a/src/js/controller/Mutation3dController.js +++ b/src/js/controller/Mutation3dController.js @@ -300,11 +300,11 @@ function Mutation3dController(mutationDetailsView, mainMutationView, viewOptions function view3dReloadHandler() { - // highlight mutations on the 3D view - // (highlight only if the corresponding view is visible) - if (mut3dView.isVisible() && - _mutationDiagram && - _mutationDiagram.isHighlighted()) + var mutationData = mainMutationView.model.mutationData; + + // highlight mutations on the 3D view only if there are mutations to highlight + if (!_.isEmpty(mutationData.getState().selected) || + !_.isEmpty(mutationData.getState().highlighted)) { highlightSelected(); } @@ -465,13 +465,7 @@ function Mutation3dController(mutationDetailsView, mainMutationView, viewOptions */ function highlightSelected() { - // TODO use the mutationHighlightHandler instead? - - // selected pileups (mutations) on the diagram - var selected = getSelectedPileups(); - - // highlight residues - highlight3dResidues(selected); + mutationSelectHandler(null, mainMutationView.model.mutationData); } /** diff --git a/src/js/data/MutationData.js b/src/js/data/MutationData.js index 5249ece..5587785 100644 --- a/src/js/data/MutationData.js +++ b/src/js/data/MutationData.js @@ -58,7 +58,7 @@ function MutationData(options) function updateData(data) { - _data = jQuery.extend(true, {}, _data, data); + setData(jQuery.extend(true, {}, _data, data)); } function setData(data) From 171d7ad40abbfc02ff11025bdf6ed1357050dbb4 Mon Sep 17 00:00:00 2001 From: Onur Sumer Date: Thu, 13 Oct 2016 14:58:55 -0400 Subject: [PATCH 08/15] prevented double filtering of the mutation table --- src/js/controller/MainMutationController.js | 9 +-- src/js/controller/Mutation3dController.js | 10 ++-- .../MutationDataFilterController.js | 4 +- .../MutationDetailsTableController.js | 21 +++++-- .../controller/MutationDiagramController.js | 10 ++-- src/js/controller/MutationInfoController.js | 10 ++-- src/js/data/MutationData.js | 60 +++++++++++-------- 7 files changed, 76 insertions(+), 48 deletions(-) diff --git a/src/js/controller/MainMutationController.js b/src/js/controller/MainMutationController.js index 5079690..d2715ce 100644 --- a/src/js/controller/MainMutationController.js +++ b/src/js/controller/MainMutationController.js @@ -64,8 +64,9 @@ function MainMutationController(mainMutationView) ); } - function mutationSelectHandler(event, mutationData) + function mutationSelectHandler(event, params) { + var mutationData = params.mutationData; // get all selected elements var selected = mutationData.getState().selected; var filtered = mutationData.getState().filtered; @@ -84,14 +85,14 @@ function MainMutationController(mainMutationView) } } - function mutationHighlightHandler(event, mutationData) + function mutationHighlightHandler(event, params) { // no need to handle for now, update if necessary } - function mutationFilterHandler(event, mutationData) + function mutationFilterHandler(event, params) { - mutationSelectHandler(event, mutationData); + mutationSelectHandler(event, params); } function handleReset(event) diff --git a/src/js/controller/Mutation3dController.js b/src/js/controller/Mutation3dController.js index cf8647e..e7737d0 100644 --- a/src/js/controller/Mutation3dController.js +++ b/src/js/controller/Mutation3dController.js @@ -128,8 +128,10 @@ function Mutation3dController(mutationDetailsView, mainMutationView, viewOptions ); } - function mutationSelectHandler(event, mutationData, noWarning) + function mutationSelectHandler(event, params, noWarning) { + var mutationData = params.mutationData; + if (_mut3dVisView && _mut3dVisView.isVisible()) { // get all selected and highlighted elements @@ -155,14 +157,14 @@ function Mutation3dController(mutationDetailsView, mainMutationView, viewOptions } } - function mutationHighlightHandler(event, mutationData) + function mutationHighlightHandler(event, params) { // in case of highlight event, no need to update the warning message. // so set noWarning = true - mutationSelectHandler(event, mutationData, true); + mutationSelectHandler(event, params, true); } - function mutationFilterHandler(event, mutationData) + function mutationFilterHandler(event, params) { // refresh view wrt to filtered data if (_mut3dVisView && _mut3dVisView.isVisible()) diff --git a/src/js/controller/MutationDataFilterController.js b/src/js/controller/MutationDataFilterController.js index 92ff258..3c539d0 100644 --- a/src/js/controller/MutationDataFilterController.js +++ b/src/js/controller/MutationDataFilterController.js @@ -3,8 +3,6 @@ * * @author Selcuk Onur Sumer */ -// TODO all other component controllers (Diagram, Table, Info Panel, etc.) should only listen -// to the events trigger by the mutation data filter manager, and update accordingly function MutationDataFilterController(mainMutationView) { var _mutationDiagram = null; @@ -195,7 +193,7 @@ function MutationDataFilterController(mainMutationView) } }); - _mutationData.updateFilteredMutations(filtered); + _mutationData.updateFilteredMutations(filtered, {view: mainMutationView.tableView}); } function proteinChangeLinkHandler(mutationId) diff --git a/src/js/controller/MutationDetailsTableController.js b/src/js/controller/MutationDetailsTableController.js index 6699fb8..90159b4 100644 --- a/src/js/controller/MutationDetailsTableController.js +++ b/src/js/controller/MutationDetailsTableController.js @@ -65,8 +65,10 @@ function MutationDetailsTableController(mainMutationView, mutationDetailsView) ); } - function mutationSelectHandler(event, mutationData) + function mutationSelectHandler(event, params) { + var mutationData = params.mutationData; + if (mainMutationView.tableView) { // remove all table highlights @@ -97,8 +99,10 @@ function MutationDetailsTableController(mainMutationView, mutationDetailsView) } } - function mutationHighlightHandler(event, mutationData) + function mutationHighlightHandler(event, params) { + var mutationData = params.mutationData; + if (mainMutationView.tableView) { // remove all table highlights @@ -115,9 +119,18 @@ function MutationDetailsTableController(mainMutationView, mutationDetailsView) } } - function mutationFilterHandler(event, mutationData) + function mutationFilterHandler(event, params) { - mutationSelectHandler(event, mutationData); + // if the source view is this table view, no need to filter again + // this is a workaround for now to prevent double filtering! + var needToFilter = (params && params.view && params.view !== mainMutationView.tableView) || + (params && !params.view) || + !params; + + if (needToFilter) + { + mutationSelectHandler(event, params); + } } function geneTabSelectHandler(gene) diff --git a/src/js/controller/MutationDiagramController.js b/src/js/controller/MutationDiagramController.js index a128303..26cbad5 100644 --- a/src/js/controller/MutationDiagramController.js +++ b/src/js/controller/MutationDiagramController.js @@ -57,19 +57,21 @@ function MutationDiagramController(mainMutationView) ); } - function mutationSelectHandler(event, mutationData) + function mutationSelectHandler(event, params) { // TODO this is a bit complicated right now // we need the previous state of the mutation data to have a seamless visual transition } - function mutationHighlightHandler(event, mutationData) + function mutationHighlightHandler(event, params) { - mutationSelectHandler(event, mutationData); + mutationSelectHandler(event, params); } - function mutationFilterHandler(event, mutationData) + function mutationFilterHandler(event, params) { + var mutationData = params.mutationData; + if (mainMutationView.diagramView) { var filtered = mutationData.getState().filtered; diff --git a/src/js/controller/MutationInfoController.js b/src/js/controller/MutationInfoController.js index 7e6e083..0b7d04e 100644 --- a/src/js/controller/MutationInfoController.js +++ b/src/js/controller/MutationInfoController.js @@ -57,8 +57,10 @@ function MutationInfoController(mainMutationView) ); } - function mutationSelectHandler(event, mutationData) + function mutationSelectHandler(event, params) { + var mutationData = params.mutationData; + if (mainMutationView.infoView) { // get all selected elements @@ -86,14 +88,14 @@ function MutationInfoController(mainMutationView) } } - function mutationHighlightHandler(event, mutationData) + function mutationHighlightHandler(event, params) { // no need to handle for now, update if required... } - function mutationFilterHandler(event, mutationData) + function mutationFilterHandler(event, params) { - mutationSelectHandler(event, mutationData); + mutationSelectHandler(event, params); } init(); diff --git a/src/js/data/MutationData.js b/src/js/data/MutationData.js index 5587785..fbd7f42 100644 --- a/src/js/data/MutationData.js +++ b/src/js/data/MutationData.js @@ -86,26 +86,26 @@ function MutationData(options) // TODO do not fire an event in case the state remains identical after an add/remove/update function call! - function update(state, mutations, event) + function update(state, mutations, event, info) { // update the corresponding set with the given mutations // this overrides all the previous content! _state[state] = mutations; // trigger a custom event - $(_dispatcher).trigger(event, _self); + $(_dispatcher).trigger(event, buildParams(info)); } - function add(state, mutations, event) + function add(state, mutations, event, info) { // add given mutations to the corresponding set _state[state] = _.union(_state[state], mutations); // trigger a custom event - $(_dispatcher).trigger(event, _self); + $(_dispatcher).trigger(event, buildParams(info)); } - function remove(state, mutations, event) + function remove(state, mutations, event, info) { if (mutations == null) { @@ -119,64 +119,74 @@ function MutationData(options) } // trigger a custom event - $(_dispatcher).trigger(event, _self); + $(_dispatcher).trigger(event, buildParams(info)); } - function updateHighlightedMutations(mutations) + function updateHighlightedMutations(mutations, info) { - update("highlighted", mutations, MutationDetailsEvents.MUTATION_HIGHLIGHT); + update("highlighted", mutations, MutationDetailsEvents.MUTATION_HIGHLIGHT, info); } - function highlightMutations(mutations) + function highlightMutations(mutations, info) { // add given mutations to the set of highlighted mutations - add("highlighted", mutations, MutationDetailsEvents.MUTATION_HIGHLIGHT); + add("highlighted", mutations, MutationDetailsEvents.MUTATION_HIGHLIGHT, info); } - function unHighlightMutations(mutations) + function unHighlightMutations(mutations, info) { // remove given mutations from the set of highlighted mutations - remove("highlighted", mutations, MutationDetailsEvents.MUTATION_HIGHLIGHT); + remove("highlighted", mutations, MutationDetailsEvents.MUTATION_HIGHLIGHT, info); } - function updateFilteredMutations(mutations) + function updateFilteredMutations(mutations, info) { - update("filtered", mutations, MutationDetailsEvents.MUTATION_FILTER); + update("filtered", mutations, MutationDetailsEvents.MUTATION_FILTER, info); } - function filterMutations(mutations) + function filterMutations(mutations, info) { // add given mutations to the set of filtered mutations - add("filtered", mutations, MutationDetailsEvents.MUTATION_FILTER); + add("filtered", mutations, MutationDetailsEvents.MUTATION_FILTER, info); } - function unfilterMutations(mutations) + function unfilterMutations(mutations, info) { if (mutations == null) { _state.filtered = _data; - $(_dispatcher).trigger(MutationDetailsEvents.MUTATION_FILTER, _self); + $(_dispatcher).trigger(MutationDetailsEvents.MUTATION_FILTER, + buildParams(info)); } else { // remove given mutations from the set of filtered mutations - remove("filtered", mutations, MutationDetailsEvents.MUTATION_FILTER); + remove("filtered", mutations, MutationDetailsEvents.MUTATION_FILTER, info); } } - function updateSelectedMutations(mutations) + function updateSelectedMutations(mutations, info) { - update("selected", mutations, MutationDetailsEvents.MUTATION_SELECT); + update("selected", mutations, MutationDetailsEvents.MUTATION_SELECT, info); } - function selectMutations(mutations) + function selectMutations(mutations, info) { // add given mutations to the set of selected mutations - add("selected", mutations, MutationDetailsEvents.MUTATION_SELECT); + add("selected", mutations, MutationDetailsEvents.MUTATION_SELECT, info); } - function unSelectMutations(mutations) + function unSelectMutations(mutations, info) { // remove given mutations from the set of selected mutations - remove("selected", mutations, MutationDetailsEvents.MUTATION_SELECT); + remove("selected", mutations, MutationDetailsEvents.MUTATION_SELECT, info); + } + + function buildParams(info) + { + var params = info || {}; + + params.mutationData = _self; + + return params; } this.updateData = updateData; From 1800893a70bb9c54857d9d452b81e854d9b88582 Mon Sep 17 00:00:00 2001 From: Onur Sumer Date: Thu, 13 Oct 2016 15:08:57 -0400 Subject: [PATCH 09/15] minor fix for the 3D controller highlight action handler --- src/js/controller/Mutation3dController.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/js/controller/Mutation3dController.js b/src/js/controller/Mutation3dController.js index e7737d0..271ee33 100644 --- a/src/js/controller/Mutation3dController.js +++ b/src/js/controller/Mutation3dController.js @@ -467,7 +467,7 @@ function Mutation3dController(mutationDetailsView, mainMutationView, viewOptions */ function highlightSelected() { - mutationSelectHandler(null, mainMutationView.model.mutationData); + mutationSelectHandler(null, {mutationData: mainMutationView.model.mutationData}); } /** From 1c105154f5bafef07690678bfc03291138960301 Mon Sep 17 00:00:00 2001 From: Onur Sumer Date: Thu, 27 Oct 2016 17:20:55 -0400 Subject: [PATCH 10/15] improved handling of mutation diagram events --- src/js/component/MutationDiagram.js | 54 ++------------- src/js/controller/Mutation3dController.js | 1 + .../MutationDataFilterController.js | 69 +++++++++++-------- src/js/controller/MutationDetailsEvents.js | 4 ++ .../controller/MutationDiagramController.js | 19 ++++- src/js/util/MutationDetailsUtil.js | 5 ++ 6 files changed, 76 insertions(+), 76 deletions(-) diff --git a/src/js/component/MutationDiagram.js b/src/js/component/MutationDiagram.js index 6205ec9..74bdd9f 100644 --- a/src/js/component/MutationDiagram.js +++ b/src/js/component/MutationDiagram.js @@ -1611,16 +1611,8 @@ MutationDiagram.prototype.addDefaultListeners = function() // diagram background click self.addListener(".mut-dia-background", "click", function(datum, index) { - // ignore the action (do not dispatch an event) if: - // 1) the diagram is already in a graphical transition: - // this is to prevent inconsistency due to fast clicks on the diagram. - // 2) there is no previously highlighted data point - // 3) multi selection mode is on: - // this is to prevent reset due to an accidental click on background - var ignore = !self.isHighlighted() || - self.multiSelect; - - if (!ignore) + // ignore the action (do not dispatch an event) if multi selection mode is on + if (!self.multiSelect) { // remove all diagram highlights self.clearHighlights(); @@ -1633,51 +1625,24 @@ MutationDiagram.prototype.addDefaultListeners = function() // lollipop circle click self.addListener(".mut-dia-data-point", "click", function(datum, index) { - // if already highlighted, remove highlight on a second click - if (self.isHighlighted(this)) + if (self.multiSelect) { - // remove highlight for the target circle - self.removeHighlight(this); - - // also clear previous highlights if multiple selection is not active - if (!self.multiSelect) - { - // remove all diagram highlights - self.clearHighlights(); - } - // trigger corresponding event self.dispatcher.trigger( - MutationDetailsEvents.LOLLIPOP_DESELECTED, + MutationDetailsEvents.LOLLIPOP_MULTI_SELECT, datum, index); } else { - // clear previous highlights if multiple selection is not active - if (!self.multiSelect) - { - // remove all diagram highlights - self.clearHighlights(); - } - - // highlight the target circle on the diagram - self.highlight(this); - // trigger corresponding event self.dispatcher.trigger( - MutationDetailsEvents.LOLLIPOP_SELECTED, + MutationDetailsEvents.LOLLIPOP_SINGLE_SELECT, datum, index); } }); // lollipop circle mouse out self.addListener(".mut-dia-data-point", "mouseout", function(datum, index) { - // if not highlighted, make the lollipop smaller - if (!self.isHighlighted(this)) - { - self.resizeLollipop(d3.select(this), self.options.lollipopSize); - } - // trigger corresponding event self.dispatcher.trigger( MutationDetailsEvents.LOLLIPOP_MOUSEOUT, @@ -1686,13 +1651,6 @@ MutationDiagram.prototype.addDefaultListeners = function() // lollipop circle mouse over self.addListener(".mut-dia-data-point", "mouseover", function(datum, index) { - // if not highlighted, make the lollipop bigger - // (if highlighted, it should be already bigger by default) - if (!self.isHighlighted(this)) - { - self.resizeLollipop(d3.select(this), self.options.lollipopHighlightSize); - } - // trigger corresponding event self.dispatcher.trigger( MutationDetailsEvents.LOLLIPOP_MOUSEOVER, @@ -1738,6 +1696,7 @@ MutationDiagram.prototype.addDefaultListeners = function() * * @param selector [optional] selector for a specific data point element * @return {boolean} true if highlighted, false otherwise + * @deprecated */ MutationDiagram.prototype.isHighlighted = function(selector) { @@ -1883,6 +1842,7 @@ MutationDiagram.prototype.fadeOut = function(element, callback) * Returns selected (highlighted) elements as a list of svg elements. * * @return {Array} a list of SVG elements + * @deprecated */ MutationDiagram.prototype.getSelectedElements = function() { diff --git a/src/js/controller/Mutation3dController.js b/src/js/controller/Mutation3dController.js index 271ee33..2f11f6d 100644 --- a/src/js/controller/Mutation3dController.js +++ b/src/js/controller/Mutation3dController.js @@ -446,6 +446,7 @@ function Mutation3dController(mutationDetailsView, mainMutationView, viewOptions * elements. * * @return {Array} an array of Pileup instances + * @deprecated */ function getSelectedPileups() { diff --git a/src/js/controller/MutationDataFilterController.js b/src/js/controller/MutationDataFilterController.js index 3c539d0..cf6c1b8 100644 --- a/src/js/controller/MutationDataFilterController.js +++ b/src/js/controller/MutationDataFilterController.js @@ -85,12 +85,12 @@ function MutationDataFilterController(mainMutationView) allDeselectHandler); mutationDiagram.dispatcher.on( - MutationDetailsEvents.LOLLIPOP_DESELECTED, - diagramDeselectHandler); + MutationDetailsEvents.LOLLIPOP_SINGLE_SELECT, + diagramSingleSelectHandler); mutationDiagram.dispatcher.on( - MutationDetailsEvents.LOLLIPOP_SELECTED, - diagramSelectHandler); + MutationDetailsEvents.LOLLIPOP_MULTI_SELECT, + diagramMultiSelectHandler); mutationDiagram.dispatcher.on( MutationDetailsEvents.LOLLIPOP_MOUSEOVER, @@ -103,36 +103,58 @@ function MutationDataFilterController(mainMutationView) function allDeselectHandler() { - _mutationData.unHighlightMutations(); - _mutationData.unSelectMutations(); + if (_.size(_mutationData.getState().selected) > 0) { + _mutationData.unSelectMutations(); + } + + if (_.size(_mutationData.getState().highlighted) > 0) { + _mutationData.unHighlightMutations(); + } } - function diagramDeselectHandler(datum, index) + function diagramSingleSelectHandler(datum, index) { - diagramSelectHandler(datum, index); + diagramSelectHandler(datum, index, false); } - function diagramSelectHandler(datum, index) + function diagramMultiSelectHandler(datum, index) + { + diagramSelectHandler(datum, index, true); + } + + function diagramSelectHandler(datum, index, multi) { var selected = []; - // get mutations for all selected elements - if (_mutationDiagram) + // TODO intersection function might be very expensive in case too many lollipops selected! + // find a faster way to check if the given mutations are already selected! + var alreadySelected = + _.size(_.intersection(_mutationData.getState().selected, datum.mutations)) === + _.size(datum.mutations); + + // check if the mutations are already selected + if (multi) { - _.each(_mutationDiagram.getSelectedElements(), function (ele, i) { - selected = selected.concat(ele.datum().mutations); - }); + if (alreadySelected) + { + _mutationData.unSelectMutations(datum.mutations); + _mutationData.unHighlightMutations(datum.mutations); + } + else + { + _mutationData.selectMutations(datum.mutations); + } } - - // all deselected - if (_.isEmpty(selected)) + else if (!alreadySelected) { - allDeselectHandler(); + selected = selected.concat(datum.mutations); + _mutationData.updateSelectedMutations(selected); } else { - // update currently selected set of mutations - _mutationData.updateSelectedMutations(selected); + // no multi selection and not already selected, + // so nothing should be selected in this case + allDeselectHandler(); } } @@ -203,13 +225,6 @@ function MutationDataFilterController(mainMutationView) if (mutation) { - // TODO ideally diagram should be highlighted by MutationDiagramController - // by using the mutation data state (both current state and prev state) - - // highlight the corresponding pileup (without filtering the table) - _mutationDiagram.clearHighlights(); - _mutationDiagram.highlightMutation(mutation.get("mutationSid")); - _mutationData.updateHighlightedMutations([mutation]); } else diff --git a/src/js/controller/MutationDetailsEvents.js b/src/js/controller/MutationDetailsEvents.js index ab11d43..3c8b49f 100644 --- a/src/js/controller/MutationDetailsEvents.js +++ b/src/js/controller/MutationDetailsEvents.js @@ -40,6 +40,8 @@ var MutationDetailsEvents = (function() var _mutationHighlighted = "mutationDataHighlighted"; var _mutationFiltered = "mutationDataFiltered"; + var _lollipopSingleSelect = "mutationDiagramLollipopSingleSelect"; + var _lollipopMultiSelect = "mutationDiagramLollipopMultiSelect"; var _lollipopSelected = "mutationDiagramLollipopSelected"; var _lollipopDeselected = "mutationDiagramLollipopDeselected"; var _allLollipopsDeselected = "mutationDiagramAllDeselected"; @@ -75,6 +77,8 @@ var MutationDetailsEvents = (function() MUTATION_HIGHLIGHT: _mutationHighlighted, MUTATION_SELECT: _mutationSelected, MUTATION_FILTER: _mutationFiltered, + LOLLIPOP_SINGLE_SELECT: _lollipopSingleSelect, + LOLLIPOP_MULTI_SELECT: _lollipopMultiSelect, LOLLIPOP_SELECTED: _lollipopSelected, LOLLIPOP_DESELECTED: _lollipopDeselected, LOLLIPOP_MOUSEOVER: _lollipopMouseover, diff --git a/src/js/controller/MutationDiagramController.js b/src/js/controller/MutationDiagramController.js index 26cbad5..80382e4 100644 --- a/src/js/controller/MutationDiagramController.js +++ b/src/js/controller/MutationDiagramController.js @@ -59,8 +59,23 @@ function MutationDiagramController(mainMutationView) function mutationSelectHandler(event, params) { - // TODO this is a bit complicated right now - // we need the previous state of the mutation data to have a seamless visual transition + var mutationData = params.mutationData; + + if (mainMutationView.diagramView) + { + var diagram = mainMutationView.diagramView.mutationDiagram; + var selected = mutationData.getState().selected; + var highlighted = mutationData.getState().highlighted; + + // TODO do not clear highlights, just update the diff of current and prev selections! + // We need the previous state of the mutation data to have a seamless visual transition + diagram.clearHighlights(); + + _.each(_.union(selected, highlighted), function(mutation) { + diagram.highlightMutation( + mutation.get("mutationSid")); + }); + } } function mutationHighlightHandler(event, params) diff --git a/src/js/util/MutationDetailsUtil.js b/src/js/util/MutationDetailsUtil.js index 0d29190..f4e2393 100644 --- a/src/js/util/MutationDetailsUtil.js +++ b/src/js/util/MutationDetailsUtil.js @@ -65,6 +65,11 @@ var MutationDetailsUtil = function(mutations) return _mutationIdMap; }; + this.getProteinChangeMap = function() + { + return _mutationProteinChangeMap; + }; + this.getMutations = function() { return _mutations; From 5dbf84559562416ac25ae87e7d6658f4df991a1f Mon Sep 17 00:00:00 2001 From: Onur Sumer Date: Tue, 1 Nov 2016 16:43:27 -0400 Subject: [PATCH 11/15] now triggering an event only if there is a change in the mutation data state --- src/js/data/MutationData.js | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/src/js/data/MutationData.js b/src/js/data/MutationData.js index fbd7f42..aaec356 100644 --- a/src/js/data/MutationData.js +++ b/src/js/data/MutationData.js @@ -84,29 +84,39 @@ function MutationData(options) return _state; } - // TODO do not fire an event in case the state remains identical after an add/remove/update function call! - function update(state, mutations, event, info) { + var prevState = _state[state]; + // update the corresponding set with the given mutations // this overrides all the previous content! _state[state] = mutations; - // trigger a custom event - $(_dispatcher).trigger(event, buildParams(info)); + // trigger an event only if there is a change in the state + if (!_.isEqual(prevState, _state[state])) { + // trigger a custom event + $(_dispatcher).trigger(event, buildParams(info)); + } } function add(state, mutations, event, info) { + var prevState = _state[state]; + // add given mutations to the corresponding set _state[state] = _.union(_state[state], mutations); - // trigger a custom event - $(_dispatcher).trigger(event, buildParams(info)); + // trigger an event only if there is a change in the state + if (!_.isEqual(prevState, _state[state])) { + // trigger a custom event + $(_dispatcher).trigger(event, buildParams(info)); + } } function remove(state, mutations, event, info) { + var prevState = _state[state]; + if (mutations == null) { // reset all @@ -118,8 +128,11 @@ function MutationData(options) _state[state] = _.difference(_state[state], mutations); } - // trigger a custom event - $(_dispatcher).trigger(event, buildParams(info)); + // trigger an event only if there is a change in the state + if (!_.isEqual(prevState, _state[state])) { + // trigger a custom event + $(_dispatcher).trigger(event, buildParams(info)); + } } function updateHighlightedMutations(mutations, info) From 5b3b7d3fb06ec2e662d300c4d5bd541cfb3e0312 Mon Sep 17 00:00:00 2001 From: Onur Sumer Date: Tue, 8 Nov 2016 14:51:48 -0500 Subject: [PATCH 12/15] updated mutation collection initialization --- src/js/controller/Mutation3dController.js | 3 ++- src/js/controller/MutationDiagramController.js | 2 +- src/js/view/MutationDetailsTableView.js | 3 ++- src/js/view/MutationDiagramView.js | 3 ++- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/js/controller/Mutation3dController.js b/src/js/controller/Mutation3dController.js index 2f11f6d..a527da8 100644 --- a/src/js/controller/Mutation3dController.js +++ b/src/js/controller/Mutation3dController.js @@ -144,7 +144,8 @@ function Mutation3dController(mutationDetailsView, mainMutationView, viewOptions { // TODO this is an expensive conversion, // find a better/faster way to highlight residues without using pileup data - var pileups = PileupUtil.convertToPileups(new MutationCollection(combined)); + var pileups = PileupUtil.convertToPileups( + new MutationCollection(_.pluck(combined, "attributes"))); highlight3dResidues(pileups, noWarning); } // nothing selected, nothing filtered, show nothing diff --git a/src/js/controller/MutationDiagramController.js b/src/js/controller/MutationDiagramController.js index 80382e4..638d92d 100644 --- a/src/js/controller/MutationDiagramController.js +++ b/src/js/controller/MutationDiagramController.js @@ -92,7 +92,7 @@ function MutationDiagramController(mainMutationView) var filtered = mutationData.getState().filtered; mainMutationView.diagramView.mutationDiagram.updatePlot( - new MutationCollection(filtered)); + new MutationCollection(_.pluck(filtered, "attributes"))); } } diff --git a/src/js/view/MutationDetailsTableView.js b/src/js/view/MutationDetailsTableView.js index ce3f692..00f910f 100644 --- a/src/js/view/MutationDetailsTableView.js +++ b/src/js/view/MutationDetailsTableView.js @@ -85,7 +85,8 @@ var MutationDetailsTableView = Backbone.View.extend({ var options = jQuery.extend(true, {}, self.model.tableOpts); options.el = options.el || self.$el.find(".mutation_details_table"); - var mutationColl = new MutationCollection(self.model.mutations.getData()); + var mutationColl = new MutationCollection( + _.pluck(self.model.mutations.getData(), "attributes")); var mutationUtil = new MutationDetailsUtil(mutationColl); var table = new MutationDetailsTable( diff --git a/src/js/view/MutationDiagramView.js b/src/js/view/MutationDiagramView.js index dbe662e..e0d4d39 100644 --- a/src/js/view/MutationDiagramView.js +++ b/src/js/view/MutationDiagramView.js @@ -128,7 +128,8 @@ var MutationDiagramView = Backbone.View.extend({ options.el = self.$el.find(".mutation-diagram-container"); // create a backbone collection for the given data - var mutationColl = new MutationCollection(mutationData.getData()); + var mutationColl = new MutationCollection( + _.pluck(mutationData.getData(), "attributes")); // create a data object var diagramData = { From ed41f2c01673106b76eb04beecff731c35b98b16 Mon Sep 17 00:00:00 2001 From: Onur Sumer Date: Tue, 8 Nov 2016 16:58:25 -0500 Subject: [PATCH 13/15] added mutation data converter utility class --- debug/debug.html | 1 + src/js/controller/Mutation3dController.js | 2 +- .../controller/MutationDiagramController.js | 2 +- src/js/util/MutationDataConverter.js | 52 +++++++++++++++++++ src/js/view/MutationDetailsTableView.js | 4 +- src/js/view/MutationDiagramView.js | 4 +- 6 files changed, 59 insertions(+), 6 deletions(-) create mode 100644 src/js/util/MutationDataConverter.js diff --git a/debug/debug.html b/debug/debug.html index 98d8f57..c241d46 100644 --- a/debug/debug.html +++ b/debug/debug.html @@ -97,6 +97,7 @@ + diff --git a/src/js/controller/Mutation3dController.js b/src/js/controller/Mutation3dController.js index a527da8..236655c 100644 --- a/src/js/controller/Mutation3dController.js +++ b/src/js/controller/Mutation3dController.js @@ -145,7 +145,7 @@ function Mutation3dController(mutationDetailsView, mainMutationView, viewOptions // TODO this is an expensive conversion, // find a better/faster way to highlight residues without using pileup data var pileups = PileupUtil.convertToPileups( - new MutationCollection(_.pluck(combined, "attributes"))); + MutationDataConverter.convertToCollection(combined)); highlight3dResidues(pileups, noWarning); } // nothing selected, nothing filtered, show nothing diff --git a/src/js/controller/MutationDiagramController.js b/src/js/controller/MutationDiagramController.js index 638d92d..8f35c67 100644 --- a/src/js/controller/MutationDiagramController.js +++ b/src/js/controller/MutationDiagramController.js @@ -92,7 +92,7 @@ function MutationDiagramController(mainMutationView) var filtered = mutationData.getState().filtered; mainMutationView.diagramView.mutationDiagram.updatePlot( - new MutationCollection(_.pluck(filtered, "attributes"))); + MutationDataConverter.convertToCollection(filtered)); } } diff --git a/src/js/util/MutationDataConverter.js b/src/js/util/MutationDataConverter.js new file mode 100644 index 0000000..e800461 --- /dev/null +++ b/src/js/util/MutationDataConverter.js @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2016 Memorial Sloan-Kettering Cancer Center. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS + * FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder + * is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no + * obligations to provide maintenance, support, updates, enhancements or + * modifications. In no event shall Memorial Sloan-Kettering Cancer Center be + * liable to any party for direct, indirect, special, incidental or + * consequential damages, including lost profits, arising out of the use of this + * software and its documentation, even if Memorial Sloan-Kettering Cancer + * Center has been advised of the possibility of such damage. + */ + +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +/** + * Singleton utility class. + * + * @author Selcuk Onur Sumer + */ +var MutationDataConverter = (function() +{ + function convertToCollection(models) + { + var collection = new MutationCollection(); + + _.each(models, function(mutation) { + collection.push(mutation); + }); + + return collection; + } + + return { + convertToCollection: convertToCollection + }; +})(); diff --git a/src/js/view/MutationDetailsTableView.js b/src/js/view/MutationDetailsTableView.js index 00f910f..18e5379 100644 --- a/src/js/view/MutationDetailsTableView.js +++ b/src/js/view/MutationDetailsTableView.js @@ -85,8 +85,8 @@ var MutationDetailsTableView = Backbone.View.extend({ var options = jQuery.extend(true, {}, self.model.tableOpts); options.el = options.el || self.$el.find(".mutation_details_table"); - var mutationColl = new MutationCollection( - _.pluck(self.model.mutations.getData(), "attributes")); + var mutationColl = MutationDataConverter.convertToCollection( + self.model.mutations.getData()); var mutationUtil = new MutationDetailsUtil(mutationColl); var table = new MutationDetailsTable( diff --git a/src/js/view/MutationDiagramView.js b/src/js/view/MutationDiagramView.js index e0d4d39..c66ea1a 100644 --- a/src/js/view/MutationDiagramView.js +++ b/src/js/view/MutationDiagramView.js @@ -128,8 +128,8 @@ var MutationDiagramView = Backbone.View.extend({ options.el = self.$el.find(".mutation-diagram-container"); // create a backbone collection for the given data - var mutationColl = new MutationCollection( - _.pluck(mutationData.getData(), "attributes")); + var mutationColl = MutationDataConverter.convertToCollection( + mutationData.getData()); // create a data object var diagramData = { From c506edfcd5340f67419aa47a26c4c7d1746c4223 Mon Sep 17 00:00:00 2001 From: Onur Sumer Date: Tue, 8 Nov 2016 18:24:31 -0500 Subject: [PATCH 14/15] improved mutation data converter --- src/js/util/MutationDataConverter.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/js/util/MutationDataConverter.js b/src/js/util/MutationDataConverter.js index e800461..f97e550 100644 --- a/src/js/util/MutationDataConverter.js +++ b/src/js/util/MutationDataConverter.js @@ -37,11 +37,14 @@ var MutationDataConverter = (function() { function convertToCollection(models) { - var collection = new MutationCollection(); + var collection = new (MutationCollection.extend({ + // this is to make sure that no new MutationModel is created for any given model + model: function (model, options) { + return model; + } + }))(); - _.each(models, function(mutation) { - collection.push(mutation); - }); + collection.add(models); return collection; } From 061b72d6601552a96c3d399f651775eed579b580 Mon Sep 17 00:00:00 2001 From: Onur Sumer Date: Wed, 9 Nov 2016 14:27:36 -0500 Subject: [PATCH 15/15] improved data util initialization for the MutationData --- src/js/data/MutationData.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/js/data/MutationData.js b/src/js/data/MutationData.js index aaec356..09cde66 100644 --- a/src/js/data/MutationData.js +++ b/src/js/data/MutationData.js @@ -66,7 +66,7 @@ function MutationData(options) _data = data; _state.filtered = data; _mutationDataUtil = new MutationDetailsUtil( - new MutationCollection(data)); + MutationDataConverter.convertToCollection(data)); } function getData()