Author: clopes
Date: 2011-07-22 13:51:02 -0700 (Fri, 22 Jul 2011)
New Revision: 26254
Added:
cytoscapeweb/trunk/cytoscapeweb/src-test/org/cytoscapeweb/model/data/InteractionVOTest.as
Modified:
cytoscapeweb/trunk/cytoscapeweb/html-template/js/cytoscapeweb.js
cytoscapeweb/trunk/cytoscapeweb/src-test/org/cytoscapeweb/AllTests.as
cytoscapeweb/trunk/cytoscapeweb/src/org/cytoscapeweb/model/GraphProxy.as
cytoscapeweb/trunk/cytoscapeweb/src/org/cytoscapeweb/model/converters/ExternalObjectConverter.as
cytoscapeweb/trunk/cytoscapeweb/src/org/cytoscapeweb/model/data/InteractionVO.as
cytoscapeweb/trunk/cytoscapeweb/src/org/cytoscapeweb/view/layout/ForceDirectedLayout.as
Log:
Created default "merged" data attributes for merged edges, so visual mappers
can be correctly applied to merged edges.
Modified: cytoscapeweb/trunk/cytoscapeweb/html-template/js/cytoscapeweb.js
===================================================================
--- cytoscapeweb/trunk/cytoscapeweb/html-template/js/cytoscapeweb.js
2011-07-22 19:26:33 UTC (rev 26253)
+++ cytoscapeweb/trunk/cytoscapeweb/html-template/js/cytoscapeweb.js
2011-07-22 20:51:02 UTC (rev 26254)
@@ -896,7 +896,7 @@
* use {@link org.cytoscapeweb.Visualization#visualStyle} or {@link
org.cytoscapeweb.Visualization#visualStyleBypass}.</p>
* <p>If you try to change an attribute that has not been previously
defined, Cytoscape Web will throw an {@link org.cytoscapeweb.Error}.
* In this case, you have to add the attribute definition first, by
calling {@link org.cytoscapeweb.Visualization#addDataField}.</p>
- * <p>Another important thing to remember is that you cannot directly
change merged edges attributes.</p>
+ * <p>Another important thing to remember is that you cannot update
merged edges data, since they are derived attributes.</p>
* <p>Finally, all the continuous and custom mappers - defined by the
current visual style - will be automatically recomputed after
* updating the data.</p>
*
Modified:
cytoscapeweb/trunk/cytoscapeweb/src/org/cytoscapeweb/model/GraphProxy.as
===================================================================
--- cytoscapeweb/trunk/cytoscapeweb/src/org/cytoscapeweb/model/GraphProxy.as
2011-07-22 19:26:33 UTC (rev 26253)
+++ cytoscapeweb/trunk/cytoscapeweb/src/org/cytoscapeweb/model/GraphProxy.as
2011-07-22 20:51:02 UTC (rev 26254)
@@ -56,6 +56,8 @@
import org.cytoscapeweb.model.data.GraphicsDataTable;
import org.cytoscapeweb.model.data.InteractionVO;
import org.cytoscapeweb.model.data.VisualStyleVO;
+ import org.cytoscapeweb.model.error.CWError;
+ import org.cytoscapeweb.util.ErrorCodes;
import org.cytoscapeweb.util.Groups;
import org.cytoscapeweb.util.Layouts;
import org.puremvc.as3.patterns.proxy.Proxy;
@@ -230,7 +232,7 @@
for (var key:String in _interactions) {
var inter:InteractionVO = _interactions[key];
- inter.update();
+ inter.update(edgesSchema);
}
if (value == null) graphData.removeGroup(Groups.FILTERED_EDGES);
@@ -414,20 +416,41 @@
public function updateData(ds:DataSprite, data:Object):void {
if (ds != null && data != null) {
+ if (ds is EdgeSprite && ds.props.$merged) {
+ throw new Error("It is not allowed to update a merged edge
data: " + ds.data.id);
+ }
+
var schema:DataSchema = ds is NodeSprite ? _nodesSchema :
_edgesSchema;
+ var updated:Boolean = false;
for (var k:String in data) {
if ( k !== "id" && !(ds is EdgeSprite && (k === "source"
|| k === "target")) ) {
var f:DataField = schema.getFieldByName(k);
+
if (f != null) {
var v:* = data[k];
- v = ExternalObjectConverter.normalizeDataValue(v,
f.type, f.defaultValue);
+
+ try {
+ v =
ExternalObjectConverter.normalizeDataValue(v, f.type, f.defaultValue);
+ } catch (err:Error) {
+ throw new CWError("Cannot update data for
'"+k+"':" + err.message,
+
ErrorCodes.INVALID_DATA_CONVERSION);
+ }
+
ds.data[k] = v;
+ updated = true;
} else {
- throw new Error("Cannot update data: there is no
Data Field for '"+k+"'.");
+ throw new CWError("Cannot update data: there is no
Data Field for '"+k+"'.");
}
}
}
+
+ if (ds is EdgeSprite && updated) {
+ // Update the merged edge data
+ var edge:EdgeSprite = EdgeSprite(ds);
+ var interaction:InteractionVO =
getInteraction(edge.source, edge.target);
+ interaction.update(edgesSchema);
+ }
}
}
@@ -537,7 +560,8 @@
}
}
- for (var key:String in interactions)
interactions[key].update();
+ for (var key:String in interactions)
+ interactions[key].update(edgesSchema, false);
}
return changed;
@@ -594,7 +618,7 @@
if (inter == null) {
inter = createInteraction(e.source, e.target);
} else {
- inter.update();
+ inter.update(edgesSchema);
}
return e;
@@ -656,7 +680,7 @@
var edgeCount:int = inter.edges.length;
if (edgeCount > 0) {
- inter.update();
+ inter.update(edgesSchema);
} else {
delete _interactions[inter.key];
removeEdge(inter.mergedEdge);
@@ -852,7 +876,7 @@
var inter:InteractionVO;
if (getInteraction(source, target) == null) {
- inter = new InteractionVO(source, target);
+ inter = new InteractionVO(source, target, edgesSchema);
_interactions[inter.key] = inter;
var me:EdgeSprite = inter.mergedEdge;
Modified:
cytoscapeweb/trunk/cytoscapeweb/src/org/cytoscapeweb/model/converters/ExternalObjectConverter.as
===================================================================
---
cytoscapeweb/trunk/cytoscapeweb/src/org/cytoscapeweb/model/converters/ExternalObjectConverter.as
2011-07-22 19:26:33 UTC (rev 26253)
+++
cytoscapeweb/trunk/cytoscapeweb/src/org/cytoscapeweb/model/converters/ExternalObjectConverter.as
2011-07-22 20:51:02 UTC (rev 26254)
@@ -151,7 +151,12 @@
default: mandatoryDefValue = null;
}
- defValue = normalizeDataValue(obj[DEF_VALUE],
type, mandatoryDefValue);
+ try {
+ defValue = normalizeDataValue(obj[DEF_VALUE],
type, mandatoryDefValue);
+ } catch (err:Error) {
+ throw new CWError("Invalid default value of '"
+ name + "'--" + err.message,
+
ErrorCodes.INVALID_DATA_CONVERSION);
+ }
schema.addField(new DataField(name, type,
defValue, name));
}
@@ -311,7 +316,13 @@
field = schema.getFieldAt(i);
name = field.name;
value = data[name];
- data[name] = normalizeDataValue(value, field.type,
field.defaultValue);
+
+ try {
+ data[name] = normalizeDataValue(value, field.type,
field.defaultValue);
+ } catch (err:Error) {
+ throw new CWError("Invalid value of '" + field.name +
"'--" + err.message,
+ ErrorCodes.INVALID_DATA_CONVERSION);
+ }
}
// Look for missing fields:
Modified:
cytoscapeweb/trunk/cytoscapeweb/src/org/cytoscapeweb/model/data/InteractionVO.as
===================================================================
---
cytoscapeweb/trunk/cytoscapeweb/src/org/cytoscapeweb/model/data/InteractionVO.as
2011-07-22 19:26:33 UTC (rev 26253)
+++
cytoscapeweb/trunk/cytoscapeweb/src/org/cytoscapeweb/model/data/InteractionVO.as
2011-07-22 20:51:02 UTC (rev 26254)
@@ -28,6 +28,9 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package org.cytoscapeweb.model.data {
+ import flare.data.DataField;
+ import flare.data.DataSchema;
+ import flare.data.DataUtil;
import flare.vis.data.EdgeSprite;
import flare.vis.data.NodeSprite;
@@ -40,7 +43,7 @@
//
=========================================================================================
- public function InteractionVO(node1:NodeSprite,
node2:NodeSprite) {
+ public function InteractionVO(node1:NodeSprite,
node2:NodeSprite, edgesSchema:DataSchema) {
_key = InteractionVO.createKey(node1, node2);
_node1 = node1;
@@ -50,13 +53,8 @@
_mergedEdge = new EdgeSprite(node1, node2, false);
node1.addOutEdge(_mergedEdge);
node2.addInEdge(_mergedEdge);
-
- if (_mergedEdge.data != null) _mergedEdge.data = {};
-
- _mergedEdge.data.source = node1.data.id;
- _mergedEdge.data.target = node2.data.id;
- _mergedEdge.data.directed = false;
+ // props attributes and functions
_mergedEdge.props.$merged = true;
mergedEdge.props.$getDataList = function():Array {
@@ -75,7 +73,7 @@
return filteredList;
}
- update();
+ update(edgesSchema);
}
// ========[ PUBLIC METHODS
]===============================================================
@@ -114,7 +112,10 @@
return (_node1 == node1 && _node2 == node2) || (_node1
== node2 && _node2 == node1);
}
- public function update():void {
+ public function update(edgesSchema:DataSchema,
updateData:Boolean=true):void {
+ // Merged edge data:
+ if (updateData) recreateDataFields(edgesSchema);
+
// Update merged edge cached data:
mergedEdge.props.$selected = false;
mergedEdge.props.$edges = edges;
@@ -133,11 +134,10 @@
}
var src:NodeSprite;
- // This will be the summed merged edge's weight:
- var weight:Number = 0;
- // Update the each edge index:
for (var i:int = 0; i < length; i++) {
+ // Update each edge index:
+
// Calculate the curvature coefficient that will give the
// direction and distance of each curve:
e = edgesList[i];
@@ -155,14 +155,34 @@
// Merged edge selection state:
if (e.props.$selected) mergedEdge.props.$selected = true;
- // Summed weight:
- var w:Number = Number(e.data.weight);
- if (!isNaN(w)) weight += w;
+ // Merged edge data:
+ if (updateData) {
+ for each (var df:DataField in edgesSchema.fields) {
+ if (isMergeable(df)) {
+ var mv:* = mergedEdge.data[df.name];
+ var v:* = e.data[df.name];
+
+ switch (df.type) {
+ case DataUtil.INT:
+ case DataUtil.NUMBER:
+ mv += (isNaN(v) ? 0 : v);
+ break;
+ case DataUtil.BOOLEAN:
+ mv |= v;
+ break;
+ default:
+ mv.push(v !== undefined ? v : null);
+ }
+
+ _mergedEdge.data[df.name] = mv;
+ }
+ }
+ }
+
e.dirty();
}
// Other cached data:
- mergedEdge.data.weight = weight;
mergedEdge.props.$filteredOut = edgesList.length === 0;
mergedEdge.dirty();
}
@@ -177,5 +197,31 @@
// ========[ PRIVATE METHODS
]==============================================================
+ private function recreateDataFields(edgesSchema:DataSchema):void {
+ _mergedEdge.data = {};
+ _mergedEdge.data.source = node1.data.id;
+ _mergedEdge.data.target = node2.data.id;
+ _mergedEdge.data.directed = false;
+
+ var v:*;
+
+ for each (var df:DataField in edgesSchema.fields) {
+ if (isMergeable(df)) {
+ switch (df.type) {
+ case DataUtil.INT: v = 0; break;
+ case DataUtil.NUMBER: v = 0.0; break;
+ case DataUtil.BOOLEAN: v = false; break;
+ default: v = [];
+ }
+
+ _mergedEdge.data[df.name] = v;
+ }
+ }
+ }
+
+ private static function isMergeable(df:DataField):Boolean {
+ var n:String = df.name;
+ return (n != "id" && n != "source" && n !== "target" &&n !==
"directed");
+ }
}
}
\ No newline at end of file
Modified:
cytoscapeweb/trunk/cytoscapeweb/src/org/cytoscapeweb/view/layout/ForceDirectedLayout.as
===================================================================
---
cytoscapeweb/trunk/cytoscapeweb/src/org/cytoscapeweb/view/layout/ForceDirectedLayout.as
2011-07-22 19:26:33 UTC (rev 26253)
+++
cytoscapeweb/trunk/cytoscapeweb/src/org/cytoscapeweb/view/layout/ForceDirectedLayout.as
2011-07-22 20:51:02 UTC (rev 26254)
@@ -100,11 +100,7 @@
public function set maxWeight(max:Number):void { _maxWeight = max; }
public function get edges():DataList {
- // The layout is optimized for merged edges only if it is not
weighted,
- // because it needs to get the weight attribute from regular edges!
- var gr:String = weighted ? Groups.REGULAR_EDGES :
Groups.MERGED_EDGES;
-
- return visualization.data.group(gr);
+ return visualization.data.group(Groups.MERGED_EDGES);
}
// ========[ CONSTRUCTOR
]==================================================================
Modified: cytoscapeweb/trunk/cytoscapeweb/src-test/org/cytoscapeweb/AllTests.as
===================================================================
--- cytoscapeweb/trunk/cytoscapeweb/src-test/org/cytoscapeweb/AllTests.as
2011-07-22 19:26:33 UTC (rev 26253)
+++ cytoscapeweb/trunk/cytoscapeweb/src-test/org/cytoscapeweb/AllTests.as
2011-07-22 20:51:02 UTC (rev 26254)
@@ -39,6 +39,7 @@
import org.cytoscapeweb.model.data.ContinuousVizMapperVOTest;
import org.cytoscapeweb.model.data.DiscreteVizMapperVOTest;
import org.cytoscapeweb.model.data.FirstNeighborsVOTest;
+ import org.cytoscapeweb.model.data.InteractionVOTest;
import org.cytoscapeweb.model.data.VisualPropertyVOTest;
import org.cytoscapeweb.model.data.VisualStyleBypassVOTest;
import org.cytoscapeweb.model.data.VisualStyleVOTest;
@@ -56,6 +57,8 @@
addTestSuite(UtilsTest);
addTestSuite(VisualPropertiesTest);
+ addTestSuite(InteractionVOTest);
+
addTestSuite(VisualPropertyVOTest);
addTestSuite(VisualStyleVOTest);
addTestSuite(VisualStyleBypassVOTest);
Added:
cytoscapeweb/trunk/cytoscapeweb/src-test/org/cytoscapeweb/model/data/InteractionVOTest.as
===================================================================
---
cytoscapeweb/trunk/cytoscapeweb/src-test/org/cytoscapeweb/model/data/InteractionVOTest.as
(rev 0)
+++
cytoscapeweb/trunk/cytoscapeweb/src-test/org/cytoscapeweb/model/data/InteractionVOTest.as
2011-07-22 20:51:02 UTC (rev 26254)
@@ -0,0 +1,161 @@
+/*
+ This file is part of Cytoscape Web.
+ Copyright (c) 2009, The Cytoscape Consortium (www.cytoscape.org)
+
+ The Cytoscape Consortium is:
+ - Agilent Technologies
+ - Institut Pasteur
+ - Institute for Systems Biology
+ - Memorial Sloan-Kettering Cancer Center
+ - National Center for Integrative Biomedical Informatics
+ - Unilever
+ - University of California San Diego
+ - University of California San Francisco
+ - University of Toronto
+
+ This library 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 2.1 of the License, or (at your option) any later version.
+
+ 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. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+package org.cytoscapeweb.model.data {
+ import flare.data.DataField;
+ import flare.data.DataSchema;
+ import flare.data.DataUtil;
+ import flare.vis.data.Data;
+ import flare.vis.data.EdgeSprite;
+ import flare.vis.data.NodeSprite;
+
+ import flexunit.framework.TestCase;
+
+
+ public class InteractionVOTest extends TestCase {
+
+ // ========[ PRIVATE PROPERTIES
]===========================================================
+
+ private var data:Data;
+ private var src:NodeSprite;
+ private var tgt:NodeSprite;
+ private var edge1:EdgeSprite;
+ private var edge2:EdgeSprite;
+ private var edge3:EdgeSprite;
+ private var interaction:InteractionVO;
+ private var edgesSchema:DataSchema;
+ // ========[ PUBLIC METHODS
]===============================================================
+
+ override public function setUp():void {
+ data = new Data(false);
+
+ src = data.addNode({ id: "n1" });
+ tgt = data.addNode({ id: "n2" });
+
+ edge1 = data.addEdgeFor(src, tgt, true, { id: "e1", source: "n1",
target: "n2", directed: true,
+ s: "a", i: 1, n: 0.5, b:
false });
+ edge2 = data.addEdgeFor(src, tgt, false, { id: "e2", source: "n1",
target: "n2", directed: false,
+ s: "b", i: 2, n: 1.5,
b: true });
+ edge3 = data.addEdgeFor(tgt, src, true, { id: "e3", source: "n2",
target: "n1", directed: true });
+
+ edgesSchema = new DataSchema();
+ edgesSchema.addField(new DataField("id", DataUtil.STRING));
+ edgesSchema.addField(new DataField("source", DataUtil.STRING));
+ edgesSchema.addField(new DataField("target", DataUtil.STRING));
+ edgesSchema.addField(new DataField("id", DataUtil.STRING));
+ edgesSchema.addField(new DataField("directed", DataUtil.BOOLEAN));
+ edgesSchema.addField(new DataField("s", DataUtil.STRING));
+ edgesSchema.addField(new DataField("i", DataUtil.INT));
+ edgesSchema.addField(new DataField("n", DataUtil.NUMBER));
+ edgesSchema.addField(new DataField("b", DataUtil.BOOLEAN));
+
+ interaction = new InteractionVO(src, tgt, edgesSchema);
+ }
+
+ public function testGetKey():void {
+ var key1:String = InteractionVO.createKey(src, tgt);
+ var key2:String = InteractionVO.createKey(tgt, src);
+
+ assertNotNull(key1);
+ assertEquals(key1, key2);
+ assertEquals(key1, interaction.key);
+ }
+
+ public function testGetNodes():void {
+ assertEquals(src, interaction.node1);
+ assertEquals(tgt, interaction.node2);
+ }
+
+ public function testGetEdges():void {
+ assertEquals(3, interaction.edges.length);
+ }
+
+ public function testGetMergedEdge():void {
+ var me:EdgeSprite = interaction.mergedEdge;
+
+ assertTrue(me.props.$merged);
+ assertEquals(3, me.props.$edges.length);
+ assertEquals(3, me.props.$getFilteredEdges().length);
+ }
+
+ public function testCurvatureFactors():void {
+ assertEquals(0, edge1.props.$curvatureFactor);
+ assertEquals(-1, edge2.props.$curvatureFactor);
+ assertEquals(-1, edge3.props.$curvatureFactor); // would be +1,
but it is inverted (tgt->src)
+ }
+
+ public function testIsLoop():void {
+ assertFalse(interaction.loop);
+ interaction = new InteractionVO(src, src, edgesSchema);
+ assertTrue(interaction.loop);
+ }
+
+ public function testHasNodes():void {
+ assertTrue(interaction.hasNodes(tgt, src));
+ assertTrue(interaction.hasNodes(src, tgt));
+ assertFalse(interaction.hasNodes(src, src));
+ assertFalse(interaction.hasNodes(tgt, tgt));
+ }
+
+ public function testGetMergedEdgeData():void {
+ var me:EdgeSprite = interaction.mergedEdge;
+
+ // should never be merged
+ assertNull(me.data.id); // not created yet
+ assertTrue(me.data.source is String);
+ assertTrue(me.data.target is String);
+ assertFalse(me.data.directed); // always undirected
+
+ // s
+ assertStrictlyEquals(null, me.data.s[0]);
+ assertEquals("a", me.data.s[1]);
+ assertEquals("b", me.data.s[2]);
+ // i
+ assertEquals(3, me.data.i);
+ // n
+ assertEquals(2.0, me.data.n);
+ // b
+ assertTrue(me.data.b);
+ }
+
+ public function testUpdateMergedEdgeData():void {
+ var me:EdgeSprite = interaction.mergedEdge;
+
+ edge3.data.s = "c";
+ edge3.data.i = 2;
+ edge2.data.b = false;
+
+ interaction.update(edgesSchema);
+
+ assertEquals("c", me.data.s[0]);
+ assertEquals(5, me.data.i);
+ assertFalse(me.data.b);
+ }
+ }
+}
\ No newline at end of file
--
You received this message because you are subscribed to the Google Groups
"cytoscape-cvs" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/cytoscape-cvs?hl=en.