Repository: incubator-edgent
Updated Branches:
  refs/heads/master b0d44b587 -> f05ca87d4


[EDGENT-179] Console: Adjust oplet coloring


Project: http://git-wip-us.apache.org/repos/asf/incubator-edgent/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-edgent/commit/f05ca87d
Tree: http://git-wip-us.apache.org/repos/asf/incubator-edgent/tree/f05ca87d
Diff: http://git-wip-us.apache.org/repos/asf/incubator-edgent/diff/f05ca87d

Branch: refs/heads/master
Commit: f05ca87d40ac8b51dd931882b789dc4b824e5330
Parents: b0d44b5
Author: Queenie Ma <queeniema.apa...@gmail.com>
Authored: Tue Sep 27 08:44:20 2016 -0700
Committer: Queenie Ma <queeniema.apa...@gmail.com>
Committed: Thu Sep 29 08:51:47 2016 -0700

----------------------------------------------------------------------
 console/servlets/webapp_content/js/graph.js |  34 +++-
 console/servlets/webapp_content/js/index.js | 248 ++++++++++++++++++++++-
 2 files changed, 270 insertions(+), 12 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-edgent/blob/f05ca87d/console/servlets/webapp_content/js/graph.js
----------------------------------------------------------------------
diff --git a/console/servlets/webapp_content/js/graph.js 
b/console/servlets/webapp_content/js/graph.js
index e279b91..538a892 100644
--- a/console/servlets/webapp_content/js/graph.js
+++ b/console/servlets/webapp_content/js/graph.js
@@ -16,15 +16,31 @@ KIND, either express or implied.  See the License for the
 specific language governing permissions and limitations
 under the License.
 */
-opletColor = {"org.apache.edgent.streamscope.oplets.StreamScope": "#c7c7c7",
-        "org.apache.edgent.metrics.oplets.CounterOp": "#c7c7c7", 
"org.apache.edgent.metrics.oplets.RateMeter": "#aec7e8", 
"org.apache.edgent.oplet.core.FanIn": "#ff7f0e",
-               "org.apache.edgent.oplet.core.FanOut": "#ffbb78", 
"org.apache.edgent.oplet.core.Peek": "#2ca02c", 
"org.apache.edgent.oplet.core.PeriodicSource": "#98df8a", 
-               "org.apache.edgent.oplet.core.Pipe": "#d62728", 
"org.apache.edgent.oplet.core.PipeWindow": "#ff9896", 
"org.apache.edgent.oplet.core.ProcessSource": "#9467bd", 
-               "org.apache.edgent.oplet.core.Sink": "#c5b0d5", 
"org.apache.edgent.oplet.core.Source": "#8c564b", 
"org.apache.edgent.oplet.core.Split": "#c49c94", 
"org.apache.edgent.oplet.core.Union" : "#1f77b4",
-               "org.apache.edgent.oplet.functional.ConsumerEventSource": 
"#e377c2", "org.apache.edgent.oplet.functional.ConsumerPeek": "#f7b6d2", 
"org.apache.edgent.oplet.functional.ConsumerSink": "#7f7f7f", 
-               "org.apache.edgent.oplet.functional.Filter": "#7F7F7F", 
"org.apache.edgent.oplet.functional.FlatMapper": "#bcbd22", 
"org.apache.edgent.oplet.functional.Isolate": "#dbdb8d", 
-               "org.apache.edgent.oplet.functional.Map": "#17becf", 
"org.apache.edgent.oplet.functional.SupplierPeriodicSource": "#9edae5", 
"org.apache.edgent.oplet.functional.SupplierSource": "#b5cf6b", 
-               "org.apache.edgent.oplet.plumbing.PressureReliever": "#e7cb94", 
"org.apache.edgent.oplet.plumbing.TextFileReader": "#ad494a", 
"org.apache.edgent.oplet.plumbing.UnorderedIsolate": "#de9ed6"};
+opletColor = {
+               "org.apache.edgent.metrics.oplets.CounterOp": "#c7c7c7",
+               "org.apache.edgent.metrics.oplets.RateMeter": "#1f77b4",
+               "org.apache.edgent.oplet.core.FanIn": "#aec7e8",
+               "org.apache.edgent.oplet.core.FanOut": "#ff7f0e",
+               "org.apache.edgent.oplet.core.Peek": "#ffbb78",
+               "org.apache.edgent.oplet.core.PeriodicSource": "#bcbd22",
+               "org.apache.edgent.oplet.core.Pipe": "#98df8a",
+               "org.apache.edgent.oplet.core.ProcessSource": "#d62728",
+               "org.apache.edgent.oplet.core.Sink": "#ff9896",
+               "org.apache.edgent.oplet.core.Source": "#9467bd",
+               "org.apache.edgent.oplet.core.Split": "#c5b0d5",
+               "org.apache.edgent.oplet.core.Union": "#c49c94",
+               "org.apache.edgent.oplet.functional.Filter": "#e377c2",
+               "org.apache.edgent.oplet.functional.Isolate": "#f7b6d2",
+               "org.apache.edgent.oplet.functional.Map": "#f2d979",
+               "org.apache.edgent.oplet.functional.Peek": "#dbdb8d",
+               "org.apache.edgent.oplet.functional.SupplierPeriodicSource": 
"#17becf",
+               "org.apache.edgent.oplet.functional.SupplierSource": "#9edae5",
+               "org.apache.edgent.oplet.plumbing.Isolate": "#79a7f2",
+               "org.apache.edgent.oplet.plumbing.PressureReliever": "#2ca02c",
+               "org.apache.edgent.oplet.plumbing.TextFileReader": "#c0f279",
+               "org.apache.edgent.oplet.plumbing.UnorderedIsolate": "#e279f2",
+               "org.apache.edgent.streamscope.oplets.StreamScope": "#c7c7c7"
+};
 colorMap = {};
 
 addValuesToEdges = function(graph, counterMetrics) {

http://git-wip-us.apache.org/repos/asf/incubator-edgent/blob/f05ca87d/console/servlets/webapp_content/js/index.js
----------------------------------------------------------------------
diff --git a/console/servlets/webapp_content/js/index.js 
b/console/servlets/webapp_content/js/index.js
index 1a4bb7d..5cc3565 100644
--- a/console/servlets/webapp_content/js/index.js
+++ b/console/servlets/webapp_content/js/index.js
@@ -766,6 +766,204 @@ var makeRows = function() {
        return theRows;
 };
 
+// Convert HSV to RGB
+var hsvToRGB = function(h, s, v) {
+       var r, g, b, i, f, p, q, t;
+       if (arguments.length === 1) {
+               s = h.s, v = h.v, h = h.h;
+       }
+       i = Math.floor(h * 6);
+       f = h * 6 - i;
+       p = v * (1 - s);
+       q = v * (1 - f * s);
+       t = v * (1 - (1 - f) * s);
+       switch (i % 6) {
+               case 0:
+                       r = v, g = t, b = p;
+                       break;
+               case 1:
+                       r = q, g = v, b = p;
+                       break;
+               case 2:
+                       r = p, g = v, b = t;
+                       break;
+               case 3:
+                       r = p, g = q, b = v;
+                       break;
+               case 4:
+                       r = t, g = p, b = v;
+                       break;
+               case 5:
+                       r = v, g = p, b = q;
+                       break;
+       }
+       return {
+               r: Math.round(r * 255),
+               g: Math.round(g * 255),
+               b: Math.round(b * 255)
+       };
+};
+
+var componentToHex = function(c) {
+       var hex = c.toString(16);
+       return hex.length == 1 ? "0" + hex : hex;
+};
+
+// Convert RGB to Hex
+var rgbToHex = function(r, g, b) {
+       return "#" + componentToHex(r) + componentToHex(g) + componentToHex(b);
+};
+
+// Convert Hex to RGB
+var hexToRGB = function(hex) {
+       var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
+       return result ? {
+               r: parseInt(result[1], 16),
+               g: parseInt(result[2], 16),
+               b: parseInt(result[3], 16)
+       } : null;
+};
+
+// Convert RGB to XYZ
+var rgbToXYZ = function(r, g, b) {
+       var _r = (r / 255);
+       var _g = (g / 255);
+       var _b = (b / 255);
+
+       if (_r > 0.04045) {
+               _r = Math.pow(((_r + 0.055) / 1.055), 2.4);
+       } else {
+               _r = _r / 12.92;
+       }
+
+       if (_g > 0.04045) {
+               _g = Math.pow(((_g + 0.055) / 1.055), 2.4);
+       } else {
+               _g = _g / 12.92;
+       }
+
+       if (_b > 0.04045) {
+               _b = Math.pow(((_b + 0.055) / 1.055), 2.4);
+       } else {
+               _b = _b / 12.92;
+       }
+
+       _r = _r * 100;
+       _g = _g * 100;
+       _b = _b * 100;
+
+       var X = _r * 0.4124 + _g * 0.3576 + _b * 0.1805;
+       var Y = _r * 0.2126 + _g * 0.7152 + _b * 0.0722;
+       var Z = _r * 0.0193 + _g * 0.1192 + _b * 0.9505;
+
+       return [X, Y, Z];
+};
+
+// Convert XYZ to LAB
+var xyzToLAB = function(x, y, z) {
+       var ref_X = 95.047;
+       var ref_Y = 100.000;
+       var ref_Z = 108.883;
+
+       var _X = x / ref_X;
+       var _Y = y / ref_Y;
+       var _Z = z / ref_Z;
+
+       if (_X > 0.008856) {
+               _X = Math.pow(_X, (1 / 3));
+       } else {
+               _X = (7.787 * _X) + (16 / 116);
+       }
+
+       if (_Y > 0.008856) {
+               _Y = Math.pow(_Y, (1 / 3));
+       } else {
+               _Y = (7.787 * _Y) + (16 / 116);
+       }
+
+       if (_Z > 0.008856) {
+               _Z = Math.pow(_Z, (1 / 3));
+       } else {
+               _Z = (7.787 * _Z) + (16 / 116);
+       }
+
+       var CIE_L = (116 * _Y) - 16;
+       var CIE_a = 500 * (_X - _Y);
+       var CIE_b = 200 * (_Y - _Z);
+
+       return [CIE_L, CIE_a, CIE_b];
+};
+
+// Compute Delta E using CIE94
+var getDeltaE = function(x, y, isTextiles) {
+       var x = {
+               l: x[0],
+               a: x[1],
+               b: x[2]
+       };
+       var y = {
+               l: y[0],
+               a: y[1],
+               b: y[2]
+       };
+       labx = x;
+       laby = y;
+       var k2;
+       var k1;
+       var kl;
+       var kh = 1;
+       var kc = 1;
+       if (isTextiles) {
+               k2 = 0.014;
+               k1 = 0.048;
+               kl = 2;
+       } else {
+               k2 = 0.015;
+               k1 = 0.045;
+               kl = 1;
+       }
+
+       var c1 = Math.sqrt(x.a * x.a + x.b * x.b);
+       var c2 = Math.sqrt(y.a * y.a + y.b * y.b);
+
+       var sh = 1 + k2 * c1;
+       var sc = 1 + k1 * c1;
+       var sl = 1;
+
+       var da = x.a - y.a;
+       var db = x.b - y.b;
+       var dc = c1 - c2;
+
+       var dl = x.l - y.l;
+       var dh = Math.sqrt(da * da + db * db - dc * dc);
+
+       return Math.sqrt(Math.pow((dl / (kl * sl)), 2) + Math.pow((dc / (kc * 
sc)), 2) + Math.pow((dh / (kh * sh)), 2));
+};
+
+// Generate a random color using the golden ratio conjugate
+var genRandomColor = function(s, v) {
+       var goldenRatioConjugate = 0.618033988749895;
+       var h = Math.random();
+       h += goldenRatioConjugate;
+       h %= 1;
+       var hsv = {
+               h: h,
+               s: s,
+               v: v
+       };
+       var rgb = hsvToRGB(hsv.h, hsv.s, hsv.v);
+       var hex = rgbToHex(rgb.r, rgb.g, rgb.b);
+       return {
+               hsv: hsv,
+               rgb: rgb,
+               hex: hex
+       };
+};
+
+var checkDeltaE = function(deltaE) {
+    return deltaE >= 15;
+};
+
 vertexMap = {};
 
 var renderGraph = function(jobId, counterMetrics, bIsNewJob) {
@@ -937,7 +1135,9 @@ var renderGraph = function(jobId, counterMetrics, 
bIsNewJob) {
                        return document.createElementNS(d3.ns.prefix.svg, 
'circle');
                }
       });
-      
+
+       var assignedOpletColors = [];
+
        node.selectAll("circle")
        .attr("cx", sankey.nodeWidth()/2)
        .attr("cy", function(d){
@@ -950,11 +1150,53 @@ var renderGraph = function(jobId, counterMetrics, 
bIsNewJob) {
                if (!colorMap[d.id.toString()]) {
                        colorMap[d.id.toString()] = color20(d.id.toString());
                }
+
+               // Generate a random color that is perceptually different than 
all assigned colors:
+               // 1. Convert the assigned oplet colors from Hex to LAB
+               // 2. Generate a random color in the RGB color space
+               // 3. Convert RGB to XYZ
+               // 4. Convert XYZ to LAB
+               // 5. For each assigned oplet color, compute Delta E between 
the two LAB colors (new and assigned)
+               // 6. If Delta E >= 15, consider the color to be different 
enough from the other colors
                if (!opletColor[d.invocation.kind]) {
-                       opletColor[d.invocation.kind] = 
color20(d.invocation.kind);
+                       var assignedOpletColorsLAB = [];
+                       for (var i = 0; i < assignedOpletColors.length; i++) {
+                               var rgb = hexToRGB(assignedOpletColors[i]);
+                               var xyz = rgbToXYZ(rgb.r, rgb.g, rgb.b);
+                               var lab = xyzToLAB(xyz[0], xyz[1], xyz[2]);
+                               assignedOpletColorsLAB.push(lab);
+                       }
+
+                       var deltaEs = [];
+                       var c = null;
+                       var uniqueColor = false;
+
+                       while (!uniqueColor) {
+                               // Use a different color scheme for 
non-org.apache.edgent defined oplets
+                               if 
(d.invocation.kind.includes("org.apache.edgent")) {
+                                       c = genRandomColor(0.5, 0.95);
+                               } else {
+                                       c = genRandomColor(0.99, 0.99);
+                               }
+
+                               var xyz = rgbToXYZ(c.rgb.r, c.rgb.g, c.rgb.b);
+                               var lab = xyzToLAB(xyz[0], xyz[1], xyz[2]);
+
+                               // Compare color to assigned colors and check 
for similarity
+                               deltaEs = [];
+                               for (var m = 0; m < 
assignedOpletColorsLAB.length; m++) {
+                                       deltaE = getDeltaE(lab, 
assignedOpletColorsLAB[m], false);
+                                       deltaEs.push(deltaE);
+                               }
+                               uniqueColor = deltaEs.every(checkDeltaE);
+                       }
+
+                       opletColor[d.invocation.kind] = c.hex;
                }
                
-               return getVertexFillColor(layer, d, counterMetrics);
+               var color = getVertexFillColor(layer, d, counterMetrics);
+               assignedOpletColors.push(color);
+               return color;
        
        })
        .attr("data-legend", function(d) {

Reply via email to