From 6396253e53748dfd3af33b78648645e78c41ce11 Mon Sep 17 00:00:00 2001 From: Aysam Guerler Date: Sat, 14 Jun 2014 04:15:45 -0400 Subject: [PATCH] Charts: Add clustered heatmap --- .../static/charts/others/heatmap/config.js | 5 +- .../charts/others/heatmap/heatmap-plugin.js | 210 ++++++++++++++++++ .../static/charts/others/heatmap/wrapper.js | 199 +---------------- .../charts/others/heatmap_cluster/config.js | 9 + .../charts/others/heatmap_cluster/logo.png | Bin 0 -> 14531 bytes .../charts/others/heatmap_cluster/wrapper.js | 37 +++ .../charts/static/charts/tools.js | 7 +- .../charts/static/charts/types.js | 9 +- 8 files changed, 271 insertions(+), 205 deletions(-) create mode 100644 config/plugins/visualizations/charts/static/charts/others/heatmap/heatmap-plugin.js create mode 100644 config/plugins/visualizations/charts/static/charts/others/heatmap_cluster/config.js create mode 100644 config/plugins/visualizations/charts/static/charts/others/heatmap_cluster/logo.png create mode 100644 config/plugins/visualizations/charts/static/charts/others/heatmap_cluster/wrapper.js diff --git a/config/plugins/visualizations/charts/static/charts/others/heatmap/config.js b/config/plugins/visualizations/charts/static/charts/others/heatmap/config.js index 593c6b85f49..9eab9e68b77 100644 --- a/config/plugins/visualizations/charts/static/charts/others/heatmap/config.js +++ b/config/plugins/visualizations/charts/static/charts/others/heatmap/config.js @@ -1,12 +1,13 @@ define(['plugin/charts/forms/default'], function(config_default) { return $.extend(true, {}, config_default, { - title : 'Heat map', + title : 'Heatmap', category : 'Others', - query_limit : 1, + query_limit : 1000, library : 'Custom', tag : 'div', keywords : 'small', + zoomable : true, columns : { x : { title : 'Column labels', diff --git a/config/plugins/visualizations/charts/static/charts/others/heatmap/heatmap-plugin.js b/config/plugins/visualizations/charts/static/charts/others/heatmap/heatmap-plugin.js new file mode 100644 index 00000000000..8b40a1747b0 --- /dev/null +++ b/config/plugins/visualizations/charts/static/charts/others/heatmap/heatmap-plugin.js @@ -0,0 +1,210 @@ +// dependencies +define(['plugin/charts/tools'], function(Tools) { + +// widget +return Backbone.View.extend({ + // initialize + initialize: function(app, options) { + this.app = app; + this.chart = options.chart; + }, + + // render + render : function(canvas_id, groups) { + // categories + this.categories = Tools.makeUniqueCategories(groups); + + // collect parameters + this.canvas_id = canvas_id; + this.data = groups[0].values; + this.color_set = ['#ffffd9','#edf8b1','#c7e9b4','#7fcdbb','#41b6c4','#1d91c0','#225ea8','#253494','#081d58']; + + // get limits + this.zMax = d3.max(this.data, function(d) { return d.z; }); + + // + // domains/scales + // + this.xScale = d3.scale.linear().domain([0, this.categories.array.x.length]); + this.yScale = d3.scale.linear().domain([0, this.categories.array.y.length]); + this.zScale = d3.scale.ordinal().domain([0, this.zMax]); + + // create axis + this.xAxis = d3.svg.axis().scale(this.xScale).orient('bottom'); + this.yAxis = d3.svg.axis().scale(this.yScale).orient('left'); + + // set ticks + this.xAxis.tickValues(d3.range(this.xScale.domain()[0], this.xScale.domain()[1], 1)); + this.yAxis.tickValues(d3.range(this.yScale.domain()[0], this.yScale.domain()[1], 1)); + + // make categories + this._makeTickFormat('x'); + this._makeTickFormat('y'); + + // refresh on window resize + var self = this; + $(window).on('resize', function () { + self.redraw(); + }); + + // draw + this.redraw(); + + // add zoom + Tools.addZoom({ + xAxis : this.xAxis, + yAxis : this.yAxis, + redraw : function() { self.redraw() }, + svg : d3.select('#' + this.canvas_id) + }); + + // return + return true; + }, + + // redraw + redraw: function() { + // get parameters + var chart = this.chart; + var data = this.data; + var color_set = this.color_set; + var self = this; + + // get/reset container + var container = $('#' + this.canvas_id); + container.empty(); + + // set margin and heights + var margin = {top: 20, right: 90, bottom: 90, left: 100}, + width = parseInt(container.width()) - margin.left - margin.right, + height = parseInt(container.height()) - margin.top - margin.bottom; + + // + // set range + // + this.xScale.range([0, width]); + this.yScale.range([height, 0]); + this.zScale.range(color_set); + + // + // draw boxes + // + // get box properties + var rowCount = this.yScale.domain()[1] - this.yScale.domain()[0], + colCount = this.xScale.domain()[1] - this.xScale.domain()[0], + boxWidth = Math.max(1, Math.floor(width / colCount)), + boxHeight = Math.max(1, Math.floor(height / rowCount)); + + // box location + function _locator(d) { + return 'translate(' + self.xScale(d.x) + ',' + self.yScale(d.y+1) + ')'; + }; + + // box color + function _color (d) { + return self.zScale(d.z); + }; + + // + // create svg + // + var svg = d3.select('#' + this.canvas_id) + .append('svg') + .attr('width', width + margin.left + margin.right) + .attr('height', height + margin.top + margin.bottom) + .append('g') + .attr('class', 'heatmap') + .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); + + // set background color + var background = svg.append('rect') + .attr('width', width) + .attr('height', height) + .attr('fill', '#FFFFF8'); + + // clip path + var clip = svg.append('clipPath') + .attr('id', 'clip') + .append('rect') + .attr('x', 0) + .attr('y', 0) + .attr('width', width) + .attr('height', height); + + // create chart area + var chartBody = svg.append('g') + .attr('clip-path', 'url(#clip)'); + + // add boxes to chart area + var boxes = chartBody.selectAll('g.box-group').data(data, function(d, i) { + return d.x + '\0' + d.y; + }); + var gEnter = boxes.enter().append('g') + .attr('class', 'box-group'); + gEnter.append('rect') + .attr('class','heat-box') + .attr('fill', 'red'); + boxes.selectAll('rect') + .attr('rx', 1) + .attr('ry', 1) + .attr('fill', _color) + .attr('width', boxWidth) + .attr('height', boxHeight) + .attr('transform', _locator); + boxes.exit().remove(); + + // draw x axis + this.gxAxis = svg.append('g') + .attr('class', 'x axis') + .style('stroke-width', 1) + .attr('transform', 'translate(0,' + height + ')') + .call(this.xAxis); + + // draw y axis + this.gyAxis = svg.append('g') + .attr('class', 'y axis') + .style('stroke-width', 1) + .call(this.yAxis); + + // fix text + var xFontSize = Math.min(boxWidth, 12); + this.gxAxis.selectAll('text') + .style({'font-size': xFontSize + 'px'}) + .attr('transform', function(d) { + var y = -this.getBBox().height - 10; + var x = -xFontSize + boxWidth/2; + return 'rotate(-90)translate(' + y + ',' + x + ')'; + }); + + // fix text + var yFontSize = Math.min(boxHeight, 12); + this.gyAxis.selectAll('text') + .style({'font-size': yFontSize + 'px'}) + .attr('y', -boxHeight/2); + }, + + // create axes formatting + _makeTickFormat: function(id) { + var settings = this.chart.settings; + var self = this; + Tools.makeTickFormat({ + categories : self.categories.array[id], + type : settings.get(id + '_axis_type'), + precision : settings.get(id + '_axis_precision'), + formatter : function(formatter) { + if (formatter) { + self[id + 'Axis'].tickFormat(function(value) { + return formatter(value); + }); + } + } + }); + }, + + // handle error + _handleError: function(err) { + this.chart.state('failed', err); + } +}); + +}); \ No newline at end of file diff --git a/config/plugins/visualizations/charts/static/charts/others/heatmap/wrapper.js b/config/plugins/visualizations/charts/static/charts/others/heatmap/wrapper.js index 686bf50f983..49f5f701f76 100644 --- a/config/plugins/visualizations/charts/static/charts/others/heatmap/wrapper.js +++ b/config/plugins/visualizations/charts/static/charts/others/heatmap/wrapper.js @@ -1,5 +1,5 @@ // dependencies -define(['plugin/charts/tools'], function(Tools) { +define(['plugin/charts/tools', 'plugin/charts/others/heatmap/heatmap-plugin'], function(Tools, HeatMap) { // widget return Backbone.View.extend({ @@ -14,6 +14,9 @@ return Backbone.View.extend({ // backup chart this.chart = chart; + // create heatmap + this.heatmap = new HeatMap(app, { chart : chart }); + // distribute data groups on svgs and handle process var self = this; var plot = Tools.panelHelper({ @@ -23,201 +26,9 @@ return Backbone.View.extend({ chart : chart, request_dictionary : request_dictionary, render : function(canvas_id, groups) { - return self.render(canvas_id, groups) + return self.heatmap.render(canvas_id, groups) } }); - }, - - // render - render : function(canvas_id, groups) { - // categories - this.categories = Tools.makeUniqueCategories(groups); - - // collect parameters - this.canvas_id = canvas_id; - this.data = groups[0].values; - this.color_set = ['#ffffd9','#edf8b1','#c7e9b4','#7fcdbb','#41b6c4','#1d91c0','#225ea8','#253494','#081d58']; - - // get limits - this.xMax = d3.max(this.data, function(d) { return d.x; }); - this.yMax = d3.max(this.data, function(d) { return d.y; }); - this.zMax = d3.max(this.data, function(d) { return d.z; }); - - // - // domains/scales - // - this.xScale = d3.scale.linear().domain([0, this.xMax]); - this.yScale = d3.scale.linear().domain([0, this.yMax]); - this.zScale = d3.scale.ordinal().domain([0, this.zMax]); - - // create axis - this.xAxis = d3.svg.axis().scale(this.xScale).orient('bottom'); - this.yAxis = d3.svg.axis().scale(this.yScale).orient('left'); - - // set ticks - this.xAxis.tickValues(d3.range(this.xScale.domain()[0], this.xScale.domain()[1], 1)); - this.yAxis.tickValues(d3.range(this.yScale.domain()[0], this.yScale.domain()[1], 1)); - - // make categories - this._makeTickFormat('x'); - this._makeTickFormat('y'); - - // refresh on window resize - var self = this; - $(window).on('resize', function () { - self.redraw(); - }); - - // draw - this.redraw(); - - // add zoom - Tools.addZoom({ - xAxis : this.xAxis, - yAxis : this.yAxis, - redraw : function() { self.redraw() }, - svg : d3.select('#' + this.canvas_id), - discrete : true - }); - - // return - return true; - }, - - // redraw - redraw: function() { - // get parameters - var chart = this.options.chart; - var type = this.options.type; - var data = this.data; - var color_set = this.color_set; - var self = this; - - // get/reset container - var container = $('#' + this.canvas_id); - container.empty(); - - // set margin and heights - var margin = {top: 20, right: 90, bottom: 90, left: 100}, - width = parseInt(container.width()) - margin.left - margin.right, - height = parseInt(container.height()) - margin.top - margin.bottom; - - // - // set range - // - this.xScale.range([0, width]); - this.yScale.range([height, 0]); - this.zScale.range(color_set); - - // - // draw boxes - // - // get box properties - var rowCount = this.yScale.domain()[1] - this.yScale.domain()[0], - colCount = this.xScale.domain()[1] - this.xScale.domain()[0], - boxWidth = Math.max(1, Math.floor(width / colCount)), - boxHeight = Math.max(1, Math.floor(height / rowCount)); - - // box location - function _locator(d) { - return 'translate(' + self.xScale(d.x) + ',' + self.yScale(d.y) + ')'; - }; - - // box color - function _color (d) { - return self.zScale(d.z); - }; - - // - // create svg - // - var svg = d3.select('#' + this.canvas_id) - .append('svg') - .attr('width', width + margin.left + margin.right) - .attr('height', height + margin.top + margin.bottom) - .append('g') - .attr('class', 'heatmap') - .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); - - // clip path - var clip = svg.append('clipPath') - .attr('id', 'clip') - .append('rect') - .attr('x', 0) - .attr('y', boxHeight) - .attr('width', width) - .attr('height', height); - - // create chart area - var chartBody = svg.append('g') - .attr('clip-path', 'url(#clip)'); - - // add boxes to chart area - var boxes = chartBody.selectAll('g.box-group').data(data, function(d, i) { - return d.x + '\0' + d.y; - }); - var gEnter = boxes.enter().append('g') - .attr('class', 'box-group'); - gEnter.append('rect') - .attr('class','heat-box') - .attr('fill', 'red'); - boxes.selectAll('rect') - .attr('rx', 2) - .attr('ry', 2) - .attr('fill', _color) - .attr('width', boxWidth) - .attr('height', boxHeight) - .attr('transform', _locator); - boxes.exit().remove(); - - // draw x axis - this.gxAxis = svg.append('g') - .attr('class', 'x axis') - .style('stroke-width', 0) - .attr('transform', 'translate(0,' + (height + margin.top + boxHeight) + ')') - .call(this.xAxis); - - // draw y axis - this.gyAxis = svg.append('g') - .attr('class', 'y axis') - .style('stroke-width', 0) - .call(this.yAxis); - - // fix text - var xFontSize = Math.min(boxWidth, 12); - this.gxAxis.selectAll('text') - .style({'font-family': 'Courier New', 'font-size': xFontSize + 'px'}) - .attr('transform', 'rotate(-90)') - .attr('y', (boxWidth-xFontSize)/2); - - // fix text - var yFontSize = Math.min(boxHeight, 12); - this.gyAxis.selectAll('text') - .style({'font-family': 'Courier New', 'font-size': yFontSize + 'px'}) - .attr('y', -boxHeight/2 + boxHeight); - }, - - // create axes formatting - _makeTickFormat: function(id) { - var settings = this.chart.settings; - var self = this; - Tools.makeTickFormat({ - categories : self.categories.array[id], - type : settings.get(id + '_axis_type'), - precision : settings.get(id + '_axis_precision'), - formatter : function(formatter) { - if (formatter) { - self[id + 'Axis'].tickFormat(function(value) { - return formatter(value); - }); - } - } - }); - }, - - // handle error - _handleError: function(chart, err) { - chart.state('failed', err); } }); diff --git a/config/plugins/visualizations/charts/static/charts/others/heatmap_cluster/config.js b/config/plugins/visualizations/charts/static/charts/others/heatmap_cluster/config.js new file mode 100644 index 00000000000..671260eb9ae --- /dev/null +++ b/config/plugins/visualizations/charts/static/charts/others/heatmap_cluster/config.js @@ -0,0 +1,9 @@ +define(['plugin/charts/others/heatmap/config'], function(config_default) { + +return $.extend(true, {}, config_default, { + title : 'Clustered Heatmap', + category : 'Data processing (requires \'charts\' tool from Toolshed)', + execute : 'heatmap' +}); + +}); \ No newline at end of file diff --git a/config/plugins/visualizations/charts/static/charts/others/heatmap_cluster/logo.png b/config/plugins/visualizations/charts/static/charts/others/heatmap_cluster/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..1dd9dc5591c10f6869891d650b864820f8284bdb GIT binary patch literal 14531 zcmV;!I6TLRP)4Tx05}naRo`#hR1`jmZ&IWdKOk5~hl<6oRa0BJ8yc;~21%2p?MfD<>DVeH z9(p*dx19w`~g7O0}n_%Aq@s%d)fBDv`JHkDym6Hd+5XuAtvnwRpGmK zVkc9?T=n|PIo~X-eVh__(Z?q}P9Z-Dj?gOW6|D%o20XmjW-qs4UjrD(li^iv8@eK9k+ZFm zVRFymFOPAzG5-%Pn|1W;U4vNroTa&AxDScmEA~{ri9gr1^c?U@uwSpaNnw8l_>cP1 zd;)kMQS_;jeRSUEM_*s96y65j1$)tOrwdK{YIQMt92l|D^(E_=$Rjw{b!QT@q!)ni zR`|5oW9X5n$Wv+HVc@|^eX5yXnsHX8PF3UX~a6)MwxDE0HaPjyrlI!;jX{6Kvuh*8ej?;85ekN$?5uuCiS zBTvvVG+XTxAO{m@bvM#Jr)z6J><&E22D|vq?Y?Vkbo_DijopiF$2PET#mZ8eu=y$(ArYkv7@Ex`GL?QCc!_*KFrd&;n1r7 zqW-CFs9&fT)ZaU5gc&=gBz-DaCw(vdOp0__x+47~U6sC(E(JNe@4cTT*n6*E zVH4eoU1-&7pEV~_PRe`a7v+@vy!^5}8?Y3)UmlaER00009a7bBm000*f000*f0cW4mQUCxnMM*?KRCodH zoei*L$5r3&e7dHk=4@Mxzo4L>C@+&KHYszcaImx@jLnZFn`BA5}!qVzLH)h96+E?@~8BT zY7(DC{t7RX=6%^WL%sC|f7ki*zwEj3GGu@R+~=>yU-U9;-cm6U zrLq^1$eURy41uCTwbAWg{*ga^^09jT9e({+|M1Scj~)KH)s;#q2&3>I_(Cy`==)3i zjlq@Q`kjw`s$TyW-8X&jzdhF2Z@(e-f~B}v@Jo@G3T=w$umE^isFo^~-IciV*y(z` z^U(L!kF;C8uZyFoHV-_iSS}ZDo)8{{4|5v9P-|_uFxBAjv<4r*{Sc?mBP=bgl!jp`!=tYGvtQJb;ZmCv#?98Ku zT_@!1a5D?q<)-w`%j6;mXQN>GG9pduN_H`&QsTItcue zz25%2{UAIMhhYTwa@%iGk7M6MJ4=PQu^boQ4*Z`y^w2xXr%%uCvq%Lz_ZVD6omN&> zz2#cP8w>^q$OrC3QF(c_=9NmNsyA?ggd62$!Se@qioApF{1k>kd1bZYRm$b6AGcjW zdKAXF0$)+)uD_=4QFz5QQmta7pT3K0L72aaO#GBsBYU?eeRKN%J;4I#*ABDS(mRIXlydVg}Vlm%D%X*iJML+O5)mGQ1r?d=ByB9=z z&2|i%3jO{d0G>upCzv3v4dPONso5L&7-N%STq=i^>e2uPRN}Zap!Eoge{)koJ-CXc z^XZ9JrcfzIQ3T6Rmc2us^1_j0zbPf}k--AuUv>!e#72cp*jtP| z%#8FmSAE6JB0Zo`jlI4fQD)7kiy*T%hzv*9M?XxJ^9UE_xKIru2VZk#q)^C=fuTeP z_SFMaKYw{LE)^}p$^5<@R8
T@XVW?)rP@D$&9-`doiLwWLO?&X%W3UrWi0wka!KmSRb(r-n zBS?g~MhBLW?jm3@W=VqM)6LPQTWR?;vLpo=j1+_c-D3=-16RB_fPvNl^J+&ppel$&y#8 zGB=}VgfLEJrr}+#u&EwdQs?l~B*}O5qqKdai&uKBB(9~;$zxQgn5D{g24-oFe(HC1 zkLpVqshNSUlwl_#iZXqQTN9W~5^c8iS*;5?)L%9b`>?89d{#nRiKf7Cf(1Haky{pd#83hO{f8eOyt}TKJ@CDx>yhlW5Xk#NUX4S^BMF zqe~rtX=N6Cp=SwL{^lF%7<;57iWtu-;NcqE@;lmKt9>_+!L6P$w ze8w`F5%FkNf`o*%LnL^x)NR~%bF>X#O=HnS!||3vPC;0JTb zwNL17nnb50bqi_n9?bd(2ZUEH6*V*j5P1NL3%;Bc*x`Ulk&_7(QWN1(8p+w!BteUEgF_>@4BR%7s^E5cmdPxU{puLct1Z4$bmtqf%S*f_B z9P+xI_R^>)8}`vZpk&RACvV+rHutyim{=dgIG31O9#Z|G-(%)Ty+cbd0#|-aCn&32 zdv7Z)gl0UlCFXff1+2!;)R1}xQ)hp_ap8rtSE|)Yh*D}LIl-AxVHzLA7cXq@H(TfA z_tKkotKGPK@xq11?$s(2hdyQUH3YOE_OD*LbhO!OK3}r=H)ERL--kiZ_JaO4O4LL+ zxB>H(lCBm8z4oCv4xYoUs`(9br9lg$^ZDNX)jN>E{z32%fNnJLNk(VGsB5#Vu-EVH z-PnD4(CZzKR_! zo-c)d&=&pc$9JTSb0-N{>ljQuxv*BGr#%2zViO#cf4(F zr55>2d}a*6RvY7Ugc(}iZ8XpQgJ1lk_nkU*s`s~>qfS}0bFQP5|CFQbx$A0jfm za)}nb!EV@D`3P?sD`oGVJC7XtrTgx?cctBG0`I(G87Lkd4Vr1MuWxu~pFihsoh^Qr z7ne)b%JJhzw}1YtUia#){rv;rLE*#St?fhJ*|X>U^XGTY0e|6bZ#!M8*JsO$GGi$f zu!f!kX4P(ST*jn1DyrGR8Bd;l1GdHpgOv2UDCvvCI5R-czC` z5l&$Q40RH-5t*P+TbT;87A_3yw^yZ7uRj>9h<w(3Mym&L0j^5A zs0GEdY)J~k8@x4Gp>C-~d@zj%?%`U$50kcd@{0tEzxQIw$so4v{fw}$U0gD{{z<1ijUfnEu zdW>*uV}g@iuSs-0vopD4Y_0;p9)W_iP)Ys?;Zq1waal|x6V++?xYBG0qa5^RG!S1l@nD%|W&p@Q zuclW5VAP99(Ihls2ygLV;@FCbE1r#l%xHjggje_{L}wZ<#B4*m;Kdg$Gt3w!NRpyTL+(gM zW4IjeEnG-&B27IcEVwp72s#qnp%W%1HZ3#yR5S`3Lb<`v$d+-HC|pRC$b8w9R^53C zdR#nsRKI$I+T+57v_GXg{mkHz=~cK;<}+93MV;bDj;ffuZqm!5(Zf=^y7 z*oD=D7fJ)HvV!%ac<`81#&8t~7kb2lrLAc^ctE2po~kiO(WG&yPQWW3?81eqd=ypb z0JluO?U<1g&FsM}!>gI7kFYbRQiO(HtSPpuFDu}*Ii@ryh{b~~#Nf&zVF}DOESP{? zcHX~I-iUyIHXiI01m%?C@i#NM9?VFhx)8AKFPvF==8MGztj57yTr@6RXaY((lyFCe z$26Mn2w2P*#)GvZ1o$eAbMauxq&;wGDFLQ|!d66sE#RNnX!)bk9wfZj+Khn5>lZrp zV3ki5L=x7HpQ6HzTBHq=5j_0n8UVZ$!OA%T6c6rV#nb~uzm*djfm`Csa72YixKX5t zOj(9W?J)~r3Zl01Dup+}Dlf?_IrxKgVTd^AVPOHwTB--C2fG-h2+2tZ%|cybuHwc? z5_~d#Y7C+sGvFz&H$~uGJlKgyCSGt7n*Q+gz?&g=(rWm0d1b4Ae0t&Hu~nE4jr?aO zJ_DJs)(FssPz!fvP-uc_N&{{u%-LN?UNlT!P1 z1(Sab;V?(vtlUrm(pQMpECg({&oqDZ>DbJ7z0WA2#H8@Hf2-#2HypIkdgQ!Z!h@9KzM?cF5dh z%Z{OA`Iu_@0f<}&9WS7*%pi7|qHDHnhO`yDy#dDMA#d|PoTZ?5ziU$)d($?6~pyR5895fH&3w{&@>=7*ykIlq`2@fcg2JJqq zR=jkI%@QtX@MXAouwQoZSb8KC8s25bUyJ8b<ReHSuyd#^SN;k9P2^jtDV;m&qbZ zME!sQFvced-rSTJfSh=+wTq!bpTId+);I>C)a-zEQa|Mgi&_cM;oxn%lEDw@9V0^M zX(#Q6!EDQ3Y_*f3T3Eoyt+u+cO+2{7+Rm@e^kkX&iY%Uc`O>AWG#*UFOUtVpt4`TJlLVl#X%di?RL<Oq zaLd#&^Lp%2J)Ew*)oQmtQLAZsfirn;_tFc`J@d(B4mZish?XAU$%_3K&z(KoYPCP! z>NG5#N-P$6U--!0^{ZQQ3enAV6eTxdf9YmtH(RadlifjEv0HKm*UMh`(WrIhD5hhd zt|m{$B#Oj<^49lO%29MK^1D`lyVq-8y>j_a+s*wu35ay*eRNd*&q*MWnOMbRccs~Ow%6dqRsbPx@KR~JJ#4_#%)Hzv*C zkB}$joCjX@YYMJ-vP`0Sl8#v@e;#IuJ}q*z>lgYTpeLQVlV{ZbAa&@4?p~H>Cs1}B)6Xa>3@3v z(rfSDymM=5y)#;D2fSC8Qp}y^ zGSMhHOt6Ve{MFz6Z{8S%-5;`}k8YyR{4>hc{NklSZMT>;NjPnOXJ zCBfRl+QyB_b07P?{l5dQ7ry&Pe);(4pL_9#IoZi(GmkAt6ieDWY{anr8uAM@LZW-i zwT*Xus{XHEc;mzW?r68W_rq+#IR@=LxJuZ229IIHI+>K+SMw!P|`fsUwUCMniq1z)7nTo8w$UU4dsK z1D%5$CSmlzVVZ;|(iMkG#8aE>ezabOcR3)4(Jn;cD!pfb5^0hIhP2+%GlYRZtQ1Sd zCXp|L$BQ&*w)?v;oZs6fp3T^<9y~2#2^j5(uJ2WAtzK|#5TLCjEJw__rUuKbBZxrw zp?_58uqiyG^%MVXXm^UP{`O4VLBu&e*VH)DXc*JTyE0yvd)T>`FoE8?a zmNk_sF?6?T5MlZ==1tTN-)IkKgY1-8@>1~SYK^HgATA6y6JEHrZM8sDIZXy%;mEA2 z#Yqg7Jb26FpF%+=`J{|V3gIt4?CLstg}afsVPR?(?huMTxL+>fS`4bJN0m*Ov_vdh zM>=I;#+=z{73nAXCj$eEMP-s$mc=@@qFNJp;dND}h0?NQbJo=OMAUzTWTMV;%yG=U_Y;rOh4c}upFx{MTDU6 zWdo!Q1FUciLHaiPDb}Edibl}@E|Rd93_HMUYc=q8yxN4TcfyrPq6=pU3Tldw?v1*I z5%K=Co$1>YQ%b)CY=@bWlI$kI%v0Lvm(L@GNHMq^EDH~Wbflmmr-N^;1KV11 zgn6DPg5+gsC0AaI7?W~igupdiJy6jYqEAUQMFL_Rhj|FtxeEcxHqt@rU-crH!+@c# zJV=IWZB&MA>lsN0vfehV+QAE2PetmFnCzz_7IPH|l7Q3Gfs^ues9c-U1KdOOJji>d z`bQmjntqj6{RPU#wjV1q%s`XTKRiCF(rI$^r>(GXCGBL@k`!3{d~k|+u21zqGn*RM z@;NiY!+Z5WO~?kmF15w5Az(6H51>~%O&@`bKS{uh;p)A~rXAIHVVXpsmH>8(RjO)Ptm(4^Oj$0LNpmD&+bXNc zgSP%2%pk#I0m_`lPdb2^Xkdlc&EyXt!0KlV3nU&)U6M4R4%q9&JzeAoUV=?~q5E{Y zOF5Nw6YvBY1!Fw5b}_yjNI$5xHAo#{q#{+b01~{$=$j=87!7B0#jOeW<|;IU0u#*v zyfrXPi;X3dkP>41?Oake9`p$hK zp@~usP%W4%O%+pypr>AB(7AU;yz(nG!-F+UT8_2ny;3e69nUT1^?yZ2B{# zOkhu$f(^{qF9RI`QU6@kWNI8fE-YZSudvWC$=R-*nQG{)R{(FsnRKwzl1aRSvD_!5 zg}z*Uc}eiDoT?yL=orjS3LFK@yF>%07XejA7;z(ui*scs~vK zYG!JkJ|)I!u^!AUp}gO$?(gq+I>}W(9LK`vP&iT% zU4Bm+tS4$6eU*a9QA0fWFmhxvLi-t&;o0FzP4L|V;n^&(Tv=N6`mGz=&}i@@?DIX% zC*b-|p*?lO=yzMsN5SBa`JyhQh3sqz^PY3Ko4DK`EAMw~rQ#17=YqZd9|6l255Z_u`sMbST!&k@b7Qx%;{A`P*}H>= zcd2={gdsfY6_!g;bbS!?2zOE&2dvAL((lIm7f;ak&P;f_s*N2TgZ(v5>0Jx^?)d6` zH@2b$w??blFIGB88E#I)?Tkgj{>UR)zxU1Sn=DbU=PScxxmn+Dm;PCJ56Yjf2WK!m z^u7O)>v$UvX!x|lp*ny)BWc{>f9?{kTtE7?r86I@7Xn@9+wFv3h52!ZOAmn8y%aEI z34ikSdroeDj+t-&Cw}F34!`!~$=4C?t48bw*LAfss>c`_ODm22ZsWs`f9}kwQ-z-3 zzv9HnH?G%eOITL|TQkCy%o^y#Y_}+tZ|rwlAN=UKkJsyk?mw!(Z{^Kjcl^P%Wi9YI zK$>x*PSTd+t8`>l^DU zN0@Lm$kU>n50y_pdDJtLFv5Ww7cX7=^m?hF`k&iaS$X6ACy%^)V{Mr&H!<62bgAhi zzZ@GLy%F$Q1hxE0sI$ zI)1FsYW3DpX-{I}=cY)8>ZxqYU2OrvA z1^(hutiiHyF6OAz1ZBa*{nUe4=P=48IqI}bnbCu#lO?u$7FUYiQnRvTYb!3is0?sp zqk&wWqI1Is!sCH16;}(zrDnfWv89&JRp}fDZM?X%w>jwdJ1~MCIHM8VsNU^I%kAD^ zpE|UUQSR@>1A;(D@7k2gz^#}bPkn~_T%#1g~<|_keUBN^*x;?vb zbCG*UjVTKYm@x@28v(zf{Eudy^IHdcdI6p~6fg2CVX$Q7bleueid=PcO)XJo!h-;} z^)in3KJYH~O5mNVe8VcYpAa2-%}NZg#B-TQ z43$&STo0z%u%q)Iu5~jJlnAed{z!s$9dSR5nYeJu&}R}v2N=Dc#1oe&N7RUGYFs=? z%XbtcZj-OWb(BnLPjUV6{2`2#xF!a9~|DWxF` zFQhOz=J=)^G)oaMxajbh;E5B-) zPo`&@b|bb)gw~|jUOMKQ|z$_t4Ms_|}$3HX2M@7G#F9t_$-A0w@ zf^PL->gT$P$;Qp~ec>J~SL)FJYX0v$;izs}$9wJF!hbv>#;h}2U2IQRI&a9lPfI2m ztaA8%(_Ayw9C;~lY{ebnwBbFU2IX2gdT2Iaue|JazdQ-@F;%h>+P&(mPr$F3e24Lji39G*!&O zPGx6trMPnnp)j_F&?F`cGWk4Gi}5$gH>S=ip!X@r@FC6Mo#wsdtNw$8;~?@7jOfmJ zJE}-eDj+j;i)rB=tZ<>svlFfc(flT&0GjLTv^a6T%+W{P2aE@Sf7LIgm$}4~Da0r{ zQArd&4Hp_TnVJI#5AgDpQpE%ZKmZLCqYBEg&ByAI^FeS}0Sz%T;Dt;S(9tX&%#@Ow zHC2PQ&1!>%@TwoGnNxKOS}|NsepvmkodU-IDg>R-54wLC< znYncD7x;H!0hhJuQ)^STO_zw}wJs%@P3tO4SZp~B7eX|9_G<7++i-lG9rDyoCzEa% z)XKnfXoLlCCW-UA@A=2IjkTvgWzx7w}M0>^C)9y~Mv z`Zr_&X2MJGK`^L^{#LWOYI_ZZV8OJofVrQy6SW&H)KjrEO(Q4!jw3-Dj4zfuoe$Gr zt}ewkqtV`?4gtEH;Z_X zpYYYooN0I2waTSEi^tx$cJ{-ZB{@aEb=L`-rJez=V_hLT?Y;Q=rS5ed|MZ?d^Y}-e zKl{1w$5*23fCD00)-&=j=-NU|TO}L}_FBFD9fSYeW1nnYdEo~Mg4CGLGe6aD)=VdS z%uZ==#&Pvx``Xou7gg%1=RS4r#!DCeVYOV6iw=96nE_6qvGzNo+}jVXKc&~_o;!UZ z?(h9$?%Q5fG)j4lH@Q5-V?cqZ5=3$L+TM*PRJQ(>Z#5V_f8mp&O1F`2_d4Ehz0K={ zztqB-q*jqeqZ4C|7wJn4;wV>*;8_tiB%7bOANT>^RK%1 z$Oj(%ZQnC(^^+6*`E<*qApPHuS89N`)1A(~HNd$N%?->ThYi;qU(J zy#>GjZQ9O5odfz$K0GfmfufQ6E0^xxIPn2pNBqx!;eB_1{cBHr`|?UXq+e*jQs88t;f zqC47jKwNq@-zNkypMb%LaE%FrPV>$DsN_2tTtTI=B9}g^Mzd5lz7r3KKYr;_?IUDf z?KK;38uYvG;*=gEA0~W81BC#M4VaK|k|+A)^+Vy~WVP6O^9{Xr`&U?oE+b?`wB$2Y z@u_69&vI4Un4jKWTmCc!n(LL|!IO6%{^dK59bMz60tg{Ux|8s<31EgFZ*^_mJAeMA zi&5-*}1g;!b>}E2Y%;Pt`i1s{zSXWiUcwG0;Iou0ZT8@ zLOQQDs0UTQ-!k(;HWP7$f%$6VcRsvP#HKmh_#F+ZIKvz~^%Kw{#)7L;AtB+JmEf<{ z&-MSMV&4i9^(({trOHx`UvBQRsZ#p|oPe^FC`$t77er8@QneqsO?!m_NB)b&C3>Yz zGY?t?u+kvb#S|h^C`~~$aB}vHo&VKJjr#dfRmGDf%tgx_q?8cs9QnH=WldAYu*T%&Pa;)cdWP6zTkJ8T0DITFqJ-UH!b0o`wf z3xK->{>?1$J*Y%WE&Bcj!DR($ERa8=?QAzKV?y}J#AwOj`Sp~b-3wcnukCFSPX@jZ zyc6&^4ozZ-8ui0!s~5JpUC7{B7|JTO`I($G>X(Pw1UC-rzJWlyUTQ4u+Hu9559Vfo zh)7iD^0fx8Qf{-h+m`aoywol7`(b05AB<@A2ksX#7mPJ59`M(`;hnP_z_izkQuGQXc<9gOi*M{c=03Y5f|vGF|Q z2}nfg_@$jM=As-2@8ZD$@z|n#(yT*)&jC+*6!BnwQDcBkCG}gU)bHbIf)R0t*8vJ{ z^|Nz@)moX}Z1gLx%nn>OdKMI=GWZ!bS|*-g4Rk7gOdMM+S~LwAKQ|x*Gx5OSC>o@_ z?^(k(i3Mjr!3Okm$U-|?WIQF4765%9f+XAszmwGg^&(;rD_Ftj5c6c+_8kFnCdtl; zyZ73*kMrK*!2~R*KgT>OPc~W~{HB-1V>9S=TdjQL+EI8g`7~Yozil%{!fI}lLSPn8 zCg1@5nubV4vy?cl+RMH!KP8@RtN08Nb3QICU^+03V`AuBg^)F!#Pc-Y0`{6rXTycs z93c-DIMQ-iEMxEph`Vhu){a!wui?z1Q8RWlX5lTgnW;qQgB4~}$WLKMqcj0j6UX#1gF4%U;j=qFIw~bJ;43JaW#LX~s9tA@HfX1K1-p#&iyaR} zgC!hkUzRDuR;3TTmVnuRK8y$JbRqT``Er1IhJaIWed_oqlQima0a>#E_WQrgJLID< z7K=MM$?C6}g7BjeRzUtV30Co3F*xPz6m%kC7Y`m^m1v`$CV#l84{W}KX62wU+X2&f zvf|Os1dS9RrNhys1`saP?vX5lw9p)%i}zq%;h^y|#zdO0e!7+{x$X)E>8%}1K)(2o zF!M6;i6ed*0Xb&2XrB&%Yp9FT-_HfE#H7-Wl`_cNEH>?d38qwN`gB)F5RXol>=y7R zJ}V)+eQ@e2X-c1fOuI1gSjB@!9a!y$1}uway0cQMceV=9{A^^Q5th3%+pZIy?z)E3 zwLvosS&%R4b;8t-d38Pxjr%E6CYuV0CIGDz#~ERa5srh_>%bW6`PB6kX&=(^NSGy9 zje|Vu`&6<#S5QTUWNNabKjtqEr;$I|1{?hVvv|?4?qMZrkLc6qtYl@tt8%u`NLwJ? zarjwFCnzTC7r73%=%gckY2v|-%vmiIWoipdnxtR7!+OX}?MU7m4j7z8pfH`F?Oj5G z=Ic3$itR<_tsNhg=gepjjIq)cRJr62xyU^5O+`n-akZ#=Lu&uHyorDHe$?=Za;|bj zsQl@=EkC78MRcKM;v1i+=4M|PHqi{eu5r)^6NbFcwqT^!6tZ%euBu2dYe~g}c_$>s zy)3+lb~t#aA_`d~iDgQRg|vKNwDy=1qhO6KMxUw>o@7&%!)cXlH$QF{KjR+1RbL+7T0WjJn%SQG}F(ZiD1>@(Sz<t877zdx%kfSxp;00IPuB)w_2(!Glv+g%4;C-99ZCO5jM*gH&GFVHmD}InTc^w|$Z9zBXHg&gOrT*mZtXq~O|q3* zsElb}78(}uYp|^?#=NJ3Qp0pOj{3WUcK9^or*F@90iwq_bG%J~CS~MondFaQN$NjD{bzbn*W#(oMze9{%H_xR8#i=guEmp~V+`I2 zSe=N7L9w{fZg-w921D!HRx6 z7bVk0Vh1N;MK~wJ*7NtTUeG0)+rV#zmAkm128R~$6uVV-G)Em_!-vb<)xlR<+r<|y zo<4orKk|*=y}sm^?jiueFH|dDM29?p4#C5$&RVU~cN-15czf$y%uhd?;c=~-h51s1YEXXfq{`gq4FeUVgg<-M)w+kVKKv~Z9P>-0rbTl%weI~iTM_Dswtn&9J?gJ#>c=E6)NZKv>d9nKjjj`uoxAZ# z!FpX5*ID8^6U?7l5CK*Qc*C(Ef(YF$#DKBu3Pd1-#`C)ZBZ2#^TI;836%zS-gTG(V|FIP@oB z>+_Fa5inf%0w;N_v_D9}mDEDYi>L3lC5z8=yRRJ9>7RO>{`7tLiExL{%15~A`?35C hobn~tL;U^8{{{W}xD3Y#RdxUX002ovPDHLkV1g}X+dcpQ literal 0 HcmV?d00001 diff --git a/config/plugins/visualizations/charts/static/charts/others/heatmap_cluster/wrapper.js b/config/plugins/visualizations/charts/static/charts/others/heatmap_cluster/wrapper.js new file mode 100644 index 00000000000..daf6b571a94 --- /dev/null +++ b/config/plugins/visualizations/charts/static/charts/others/heatmap_cluster/wrapper.js @@ -0,0 +1,37 @@ +// dependencies +define(['plugin/charts/tools', 'plugin/charts/others/heatmap/heatmap-plugin'], function(Tools, HeatMap) { + +// widget +return Backbone.View.extend({ + // initialize + initialize: function(app, options) { + this.app = app; + this.options = options; + }, + + // render + draw : function(process_id, chart, request_dictionary) { + // backup chart + this.chart = chart; + + // create heatmap + this.heatmap = new HeatMap(app, { + chart : chart + }); + + // distribute data groups on svgs and handle process + var self = this; + var plot = Tools.panelHelper({ + app : this.app, + canvas_list : this.options.canvas_list, + process_id : process_id, + chart : chart, + request_dictionary : request_dictionary, + render : function(canvas_id, groups) { + return self.heatmap.render(canvas_id, groups) + } + }); + } +}); + +}); \ No newline at end of file diff --git a/config/plugins/visualizations/charts/static/charts/tools.js b/config/plugins/visualizations/charts/static/charts/tools.js index cf875e86939..5ef91299bf4 100644 --- a/config/plugins/visualizations/charts/static/charts/tools.js +++ b/config/plugins/visualizations/charts/static/charts/tools.js @@ -297,7 +297,7 @@ function makeTickFormat (options) { // add zoom handler function addZoom(options) { // scaleExtent - var scaleExtent = 10; + var scaleExtent = 100; // parameters var yAxis = options.yAxis; @@ -306,7 +306,6 @@ function addZoom(options) { var yDomain = options.yDomain || yAxis.scale().domain; var redraw = options.redraw; var svg = options.svg; - var discrete = options.discrete; // scales var xScale = xAxis.scale(); @@ -325,10 +324,6 @@ function addZoom(options) { // fix domain function fixDomain(domain, boundary) { - if (discrete) { - domain[0] = Math.floor(domain[0]); - domain[1] = Math.ceil(domain[1]); - } domain[0] = Math.min(Math.max(domain[0], boundary[0]), boundary[1] - boundary[1]/scaleExtent); domain[1] = Math.max(boundary[0] + boundary[1]/scaleExtent, Math.min(domain[1], boundary[1])); return domain; diff --git a/config/plugins/visualizations/charts/static/charts/types.js b/config/plugins/visualizations/charts/static/charts/types.js index 8d66eea0a5e..bb8cc9b3faf 100644 --- a/config/plugins/visualizations/charts/static/charts/types.js +++ b/config/plugins/visualizations/charts/static/charts/types.js @@ -16,7 +16,8 @@ define(['plugin/charts/nvd3/bar/config', 'plugin/charts/jqplot/line/config', 'plugin/charts/jqplot/scatter/config', 'plugin/charts/jqplot/boxplot/config', - 'plugin/charts/others/heatmap/config' + 'plugin/charts/others/heatmap/config', + 'plugin/charts/others/heatmap_cluster/config' ], function(nvd3_bar, nvd3_bar_stacked, nvd3_bar_horizontal, @@ -34,7 +35,8 @@ define(['plugin/charts/nvd3/bar/config', jqplot_line, jqplot_scatter, jqplot_boxplot, - others_heatmap + others_heatmap, + others_heatmap_cluster ) { // widget @@ -59,7 +61,8 @@ return Backbone.Model.extend( 'jqplot_line' : jqplot_line, 'jqplot_scatter' : jqplot_scatter, 'jqplot_boxplot' : jqplot_boxplot, - 'others_heatmap' : others_heatmap + 'others_heatmap' : others_heatmap, + 'others_heatmap_cluster' : others_heatmap_cluster } });