Commit cac69476 authored by Piotr Gawron's avatar Piotr Gawron
Browse files

Merge branch '39-visualization-of-two-overlaying-drugs' into 'master'

Resolve "visualization of two overlaying drugs"

See merge request piotr.gawron/minerva!136
parents 7154070b c98f7cc2
Pipeline #2588 passed with stage
in 40 seconds
......@@ -14,6 +14,8 @@ var PointInfoWindow = require('./window/PointInfoWindow');
var ReactionInfoWindow = require('./window/ReactionInfoWindow');
var ReactionSurface = require('./surface/ReactionSurface');
var MarkerSurfaceCollection = require('./marker/MarkerSurfaceCollection');
/**
* Default constructor.
*/
......@@ -53,6 +55,8 @@ function AbstractCustomMap(model, options) {
// array with info windows for reactions
this._reactionInfoWindow = [];
this._markerSurfaceCollection = new MarkerSurfaceCollection({map: this});
// this is google.maps.drawing.DrawingManager that will allow user to draw
// elements in the client
this._drawingManager = null;
......@@ -76,6 +80,10 @@ function AbstractCustomMap(model, options) {
AbstractCustomMap.prototype = Object.create(ObjectWithListeners.prototype);
AbstractCustomMap.prototype.constructor = AbstractCustomMap;
AbstractCustomMap.prototype.getMarkerSurfaceCollection = function () {
return this._markerSurfaceCollection;
};
/**
* Assigns layouts with images to the google map (which set of images should be
* used by google maps api for which layout).
......@@ -650,7 +658,7 @@ AbstractCustomMap.prototype._showSelectedLayout = function (layoutId, index, len
return self.getTopMap().callListeners("onBioEntityClick", element);
}],
customized: (length === 1)
}).then(function(result){
}).then(function (result) {
surface = result;
self.selectedLayoutOverlays[layoutId].push(surface);
surface.show();
......
......@@ -6,10 +6,6 @@ var logger = require('../logger');
var Functions = require('../Functions');
var AbstractCustomMap = require('./AbstractCustomMap');
var AbstractMarker = require('./marker/AbstractMarker');
var AbstractSurfaceElement = require('./surface/AbstractSurfaceElement');
var AliasMarker = require('./marker/AliasMarker');
var AliasSurface = require('./surface/AliasSurface');
var Alias = require('./data/Alias');
var CommentDialog = require('../gui/CommentDialog');
var ControlType = require('./ControlType');
......@@ -18,10 +14,7 @@ var GuiConnector = require('../GuiConnector');
var IdentifiedElement = require('./data/IdentifiedElement');
var LayoutData = require('./data/LayoutData');
var PointData = require('./data/PointData');
var PointMarker = require('./marker/PointMarker');
var Reaction = require('./data/Reaction');
var ReactionMarker = require('./marker/ReactionMarker');
var ReactionSurface = require('./surface/ReactionSurface');
var ReferenceGenome = require('./data/ReferenceGenome');
var SecurityError = require('../SecurityError');
var Submap = require('./Submap');
......@@ -243,11 +236,6 @@ CustomMap.prototype.registerDbOverlay = function (dbOverlay) {
this.overlayCollections[dbOverlay.getName()] = dbOverlay;
dbOverlay.markers = {
ALIAS: [],
REACTION: [],
POINT: []
};
dbOverlay.mapOverlays = {
ALIAS: [],
REACTION: [],
......@@ -334,20 +322,14 @@ CustomMap.prototype.refreshMarkers = function (force) {
};
CustomMap.prototype.refreshOverlayMarkers = function (overlay, force) {
var self = this;
logger.debug("Refresh overlay: " + overlay.name);
if (!this.isMarkerOptimization() || force) {
for (var markerType in overlay.markers) {
if (overlay.markers.hasOwnProperty(markerType)) {
var markers = overlay.markers[markerType];
for (var key in markers) {
if (markers.hasOwnProperty(key)) {
var marker = markers[key];
marker.hide();
marker.show();
}
}
}
self.getMarkerSurfaceCollection().refreshOverlayMarkers(overlay);
var submaps = self.getSubmaps();
for (var i = 0; i < submaps.length; i++) {
submaps[i].getMarkerSurfaceCollection().refreshOverlayMarkers(overlay);
}
}
};
......@@ -666,12 +648,11 @@ CustomMap.prototype.refreshInfoWindows = function () {
};
/**
* Opens {@link AliasInfoWindow} for an {@link Alias} in a given model/submodel.
* Opens {@link AliasInfoWindow} for an {@link Alias}.
*
* @param aliasId
* identifier of {@link Alias}
* @param modelId
* identifier of {@link AbstractCustomMap}
* @param alias
* {@link Alias}
* @param marker google.maps.Marker object
*/
CustomMap.prototype.openInfoWindowForAlias = function (alias, marker) {
logger.debug("Opening info window for alias: " + alias.getId() + ", model: " + alias.getModelId());
......@@ -682,10 +663,9 @@ CustomMap.prototype.openInfoWindowForAlias = function (alias, marker) {
/**
* Renders markers, lines, etc. for elements highlighted in OverlayCollection.
*
* @param overlayCollection
* {@link OverlayCollection} to be processed
* @param fitBounds
* <code>true</code> if the borders should fit bounds after creating
* @param params: {overlayCollection, fitBounds}
* overlayCollection - to be processed
* fitBounds - <code>true</code> if the borders should fit bounds after creating
* all elements
*/
CustomMap.prototype.renderOverlayCollection = function (params) {
......@@ -696,25 +676,19 @@ CustomMap.prototype.renderOverlayCollection = function (params) {
var elements;
var markers = [];
var submaps = self.getSubmaps().concat([self]);
return overlayCollection.getIdentifiedElements().then(function (identifiedElements) {
elements = identifiedElements;
return Promise.each(elements, function (element) {
var icon = element.getIcon();
if (icon !== null && icon !== undefined) {
return self.createMarkerForDbOverlay(element, overlayCollection).then(function (marker) {
markers.push(marker);
});
} else {
return self.createSurfaceForDbOverlay(element, overlayCollection).then(function (mapOverlay) {
markers.push(mapOverlay);
});
}
});
}).then(function () {
self.removeUnmodifiedMarkersAndSurfaces(markers, overlayCollection);
var promises = [];
for (var i = 0; i < submaps.length; i++) {
promises.push(submaps[i].getMarkerSurfaceCollection().renderOverlay(identifiedElements, overlayCollection));
}
return Promise.all(promises);
}).then(function (mapMarkers) {
for (var i = 0; i < mapMarkers.length; i++) {
markers = markers.concat(mapMarkers[i]);
}
return Promise.each(elements, function (element) {
var infoWindow = self.getInfoWindowForIdentifiedElement(element);
if (infoWindow !== null && infoWindow !== undefined) {
......@@ -725,64 +699,13 @@ CustomMap.prototype.renderOverlayCollection = function (params) {
});
}).then(function () {
if (elements.length > 0 && fitBounds) {
self.fitBounds(markers);
for (var j = 0; j < self.submaps.length; j++) {
self.submaps[j].fitBounds(markers);
for (var j = 0; j < submaps.length; j++) {
submaps[j].fitBounds(markers);
}
}
});
};
CustomMap.prototype.removeUnmodifiedMarkersAndSurfaces = function (modifiedMarkersAndSurfaces, dbOverlay) {
var modifiedMarkers = {
"ALIAS": [],
"REACTION": [],
"POINT": [],
};
var modifiedSurfaces = {
"ALIAS": [],
"REACTION": [],
"POINT": [],
};
for (var i = 0; i < modifiedMarkersAndSurfaces.length; i++) {
var object = modifiedMarkersAndSurfaces[i];
var identifiedElement = object.getIdentifiedElement();
if (object instanceof AbstractSurfaceElement) {
modifiedSurfaces[identifiedElement.getType()][identifiedElement.getId()] = true;
} else if (object instanceof AbstractMarker) {
modifiedMarkers[identifiedElement.getType()][identifiedElement.getId()] = true;
} else {
throw new Error("Unknown class type: " + object.prototype.name);
}
}
var markerType, key;
for (markerType in dbOverlay.markers) {
if (dbOverlay.markers.hasOwnProperty(markerType)) {
var markers = dbOverlay.markers[markerType];
for (key in markers) {
if (markers.hasOwnProperty(key) && !modifiedMarkers[markerType][key]) {
markers[key].setMap(null);
delete markers[key];
}
}
}
}
for (markerType in dbOverlay.mapOverlays) {
if (dbOverlay.mapOverlays.hasOwnProperty(markerType)) {
var mapOverlays = dbOverlay.mapOverlays[markerType];
for (key in mapOverlays) {
if (mapOverlays.hasOwnProperty(key) && !modifiedSurfaces[markerType][key]) {
mapOverlays[key].setMap(null);
delete mapOverlays[key];
}
}
}
}
};
/**
* Opens {@link AbstractInfoWindow} for a marker.
*
......@@ -1206,90 +1129,6 @@ CustomMap.prototype.getVisibleDataOverlays = function () {
return Promise.all(dataOverlayPromises);
};
CustomMap.prototype.createMarkerForDbOverlay = function (element, dbOverlay) {
var self = this;
var result = dbOverlay.markers[element.getType()][element.getId()];
if (result !== undefined) {
result.updateIdentifiedElement(element);
return Promise.resolve(result);
}
var submap = self.getSubmapById(element.getModelId());
var MarkerConstructor = null;
if (element.getType() === "ALIAS") {
MarkerConstructor = AliasMarker;
} else if (element.getType() === "REACTION") {
MarkerConstructor = ReactionMarker;
} else if (element.getType() === "POINT") {
MarkerConstructor = PointMarker;
} else {
throw new Error("Unknown type of the element in overlay: " + element.type);
}
result = new MarkerConstructor({
element: element,
map: submap,
onClick: [function () {
return self._openInfoWindowForIdentifiedElement(element, result.getGoogleMarker());
}, function () {
return self.callListeners("onBioEntityClick", element);
}]
});
return result.init().then(function () {
dbOverlay.markers[element.getType()][element.getId()] = result;
return result;
});
};
CustomMap.prototype.createSurfaceForDbOverlay = function (element, dbOverlay) {
var self = this;
var result = dbOverlay.mapOverlays[element.getType()][element.getId()];
if (result !== undefined) {
result.updateIdentifiedElement(element);
return Promise.resolve(result);
}
var map = self.getSubmapById(element.getModelId());
if (element.getType() === "ALIAS") {
return AliasSurface.createFromIdentifiedElement({
element: element,
map: self,
onClick: [function () {
return self.openInfoWindowForIdentifiedElement(element, result.getGoogleMarker());
}, function () {
return self.callListeners("onBioEntityClick", element);
}]
}).then(function (surface) {
result = surface;
dbOverlay.mapOverlays[element.getType()][element.getId()] = result;
return result;
});
} else if (element.getType() === "REACTION") {
return map.getModel().getReactionById(element.getId()).then(function (reactionData) {
return ReactionSurface.create({
reaction: reactionData,
map: map,
customized: true,
color: element.getColor(),
onClick: [function () {
return self.openInfoWindowForIdentifiedElement(element, result.getGoogleMarker());
}, function () {
return self.callListeners("onBioEntityClick", element);
}]
}).then(function (surface) {
result = surface;
result.show();
dbOverlay.mapOverlays[element.getType()][element.getId()] = result;
return result;
});
});
} else if (element.getType() === "POINT") {
throw new Error("Not implemented");
} else {
throw new Error("Unknown type of the element in overlay: " + element.type);
}
};
/**
* Opens {@link AbstractInfoWindow} for a marker.
......
......@@ -44,4 +44,8 @@ PointData.prototype.getModelId = function() {
return this._modelId;
};
PointData.prototype.isComplete = function() {
return true;
};
module.exports = PointData;
......@@ -9,7 +9,7 @@ var logger = require('../../logger');
/**
* Class representing reaction data.
*
*
* @param javaObject
* object de-serialized from ajax query to the server side
*/
......@@ -55,11 +55,11 @@ function Reaction(javaObject) {
Reaction.prototype = Object.create(BioEntity.prototype);
Reaction.prototype.constructor = Reaction;
Reaction.prototype.getCenter = function() {
Reaction.prototype.getCenter = function () {
return this._center;
};
Reaction.prototype.getLines = function() {
Reaction.prototype.getLines = function () {
var result = [];
result = result.concat(this.startLines);
result = result.concat(this.endLines);
......@@ -67,24 +67,24 @@ Reaction.prototype.getLines = function() {
return result;
};
Reaction.prototype.getMidLines = function() {
Reaction.prototype.getMidLines = function () {
return this.midLines;
};
Reaction.prototype.getStartLines = function() {
Reaction.prototype.getStartLines = function () {
return this.startLines;
};
Reaction.prototype.getEndLines = function() {
Reaction.prototype.getEndLines = function () {
return this.endLines;
};
Reaction.prototype.setCenter = function(center) {
Reaction.prototype.setCenter = function (center) {
if (center === null || center === undefined) {
throw new Error("Setting undefined center: ", center);
}
this._center = center;
};
Reaction.prototype.update = function(javaObject) {
Reaction.prototype.update = function (javaObject) {
if (javaObject.reactionId === undefined) {
return;
}
......@@ -123,85 +123,87 @@ Reaction.prototype.update = function(javaObject) {
this.setIsComplete(true);
};
Reaction.prototype.isComplete = function() {
Reaction.prototype.isComplete = function () {
var self = this;
var result = self._complete;
var reactants = self.getReactants();
if (reactants.length === 0) {
result = false;
} else {
if (!(self.getReactants()[0] instanceof Alias)) {
if (result) {
var reactants = self.getReactants();
if (reactants.length === 0) {
result = false;
} else {
if (!(self.getReactants()[0] instanceof Alias)) {
result = false;
}
}
}
return result;
};
Reaction.prototype.getReactionId = function() {
Reaction.prototype.getReactionId = function () {
return this._reactionId;
};
Reaction.prototype.setReactionId = function(reactionId) {
Reaction.prototype.setReactionId = function (reactionId) {
this._reactionId = reactionId;
};
Reaction.prototype.getMechanicalConfidenceScore = function() {
Reaction.prototype.getMechanicalConfidenceScore = function () {
return this._mechanicalConfidenceScore;
};
Reaction.prototype.setMechanicalConfidenceScore = function(mechanicalConfidenceScore) {
Reaction.prototype.setMechanicalConfidenceScore = function (mechanicalConfidenceScore) {
this._mechanicalConfidenceScore = mechanicalConfidenceScore;
};
Reaction.prototype.getLowerBound = function() {
Reaction.prototype.getLowerBound = function () {
return this._lowerBound;
};
Reaction.prototype.setLowerBound = function(lowerBound) {
Reaction.prototype.setLowerBound = function (lowerBound) {
this._lowerBound = lowerBound;
};
Reaction.prototype.getUpperBound = function() {
Reaction.prototype.getUpperBound = function () {
return this._upperBound;
};
Reaction.prototype.setUpperBound = function(upperBound) {
Reaction.prototype.setUpperBound = function (upperBound) {
this._upperBound = upperBound;
};
Reaction.prototype.setGeneProteinReaction = function(geneProteinReaction) {
Reaction.prototype.setGeneProteinReaction = function (geneProteinReaction) {
this._geneProteinReaction = geneProteinReaction;
};
Reaction.prototype.getGeneProteinReaction = function() {
Reaction.prototype.getGeneProteinReaction = function () {
return this._geneProteinReaction;
};
Reaction.prototype.setSubsystem = function(subsystem) {
Reaction.prototype.setSubsystem = function (subsystem) {
this._subsystem = subsystem;
};
Reaction.prototype.getSubsystem = function() {
Reaction.prototype.getSubsystem = function () {
return this._subsystem;
};
Reaction.prototype.getReactants = function() {
Reaction.prototype.getReactants = function () {
return this._reactants;
};
Reaction.prototype.setReactants = function(reactants) {
Reaction.prototype.setReactants = function (reactants) {
this._reactants = reactants;
};
Reaction.prototype.setProducts = function(products) {
Reaction.prototype.setProducts = function (products) {
this._products = products;
};
Reaction.prototype.getProducts = function() {
Reaction.prototype.getProducts = function () {
return this._products;
};
Reaction.prototype.getElements = function() {
Reaction.prototype.getElements = function () {
var result = [];
result = result.concat(this.getReactants());
result = result.concat(this.getProducts());
......@@ -209,11 +211,11 @@ Reaction.prototype.getElements = function() {
return result;
};
Reaction.prototype.setModifiers = function(modifiers) {
Reaction.prototype.setModifiers = function (modifiers) {
this._modifiers = modifiers;
};
Reaction.prototype.getModifiers = function() {
Reaction.prototype.getModifiers = function () {
return this._modifiers;
};
......
......@@ -16,6 +16,7 @@ function AbstractMarker(params) {
// call super constructor
ObjectWithListeners.call(this);
self._icons = [];
self.setIdentifiedElement(params.element);
self.setIcon(params.element.getIcon());
self.setCustomMap(params.map);
......@@ -48,18 +49,89 @@ AbstractMarker.prototype.getId = function () {
/**
* Returns icon of the marker.
*
* @returns icon of the marker
* @returns string/undefined identifying icon of the marker
*/
AbstractMarker.prototype.getIcon = function () {
return this._icon;
var icons = this._icons;
if (icons.length === 0) {
return undefined;
} else if (icons.length === 1) {
return icons[0];
} else {
var result = icons[0];
//if we have many identical icons then return this specific icon
for (var i = 1; i < icons.length; i++) {
if (icons[i] !== result) {
return "marker/generic/search_green.png";
}
}
return result;
}
};
AbstractMarker.prototype.setIcon = function (icon) {
AbstractMarker.prototype._updateIcon = function () {
var self = this;
self._icon = icon;
var googleMarker = self.getGoogleMarker();
if (googleMarker !== undefined) {
googleMarker.setIcon(GuiConnector.getImgPrefix() + self.getIcon());
if (self.getIcon() === undefined) {
self.hide();
} else {
googleMarker.setIcon(GuiConnector.getImgPrefix() + self.getIcon());
if (googleMarker.getMap() === null) {
self.show();
}
}
}
};
AbstractMarker.prototype.setIcon = function (icon) {
var self = this;
if (icon === null || icon === undefined) {
self._icons = [];
} else {
self._icons = [icon];
}
self._updateIcon(self);
};
AbstractMarker.prototype.setIcons = function (icons) {
var self = this;
self._icons = icons;
self._updateIcon(self);
};
AbstractMarker.prototype.addIcon = function (icon) {
var self = this;
self._icons.push(icon);
self._updateIcon(self);
};
AbstractMarker.prototype.addIcons = function (icons) {
var self = this;
for (var i = 0; i < icons.length; i++) {
self._icons.push(icons[i]);
}
self._updateIcon(self);
};
AbstractMarker.prototype.removeIcons = function (icons) {
var self = this;
for (var i = 0; i < icons.length; i++) {
self.removeIcon(icons[i