123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223 |
- /**
- * jqPlot
- * Pure JavaScript plotting plugin using jQuery
- *
- * Version: @VERSION
- * Revision: @REVISION
- *
- * Copyright (c) 2009-2013 Chris Leonello
- * jqPlot is currently available for use in all personal or commercial projects
- * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL
- * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can
- * choose the license that best suits your project and use it accordingly.
- *
- * Although not required, the author would appreciate an email letting him
- * know of any substantial use of jqPlot. You can reach the author at:
- * chris at jqplot dot com or see http://www.jqplot.com/info.php .
- *
- * If you are feeling kind and generous, consider supporting the project by
- * making a donation at: http://www.jqplot.com/donate.php .
- *
- * sprintf functions contained in jqplot.sprintf.js by Ash Searle:
- *
- * version 2007.04.27
- * author Ash Searle
- * http://hexmen.com/blog/2007/03/printf-sprintf/
- * http://hexmen.com/js/sprintf.js
- * The author (Ash Searle) has placed this code in the public domain:
- * "This code is unrestricted: you are free to use it however you like."
- *
- */
- (function($) {
-
- /**
- * Class: $.jqplot.Trendline
- * Plugin which will automatically compute and draw trendlines for plotted data.
- */
- $.jqplot.Trendline = function() {
- // Group: Properties
-
- // prop: show
- // Wether or not to show the trend line.
- this.show = $.jqplot.config.enablePlugins;
- // prop: color
- // CSS color spec for the trend line.
- // By default this wil be the same color as the primary line.
- this.color = '#666666';
- // prop: renderer
- // Renderer to use to draw the trend line.
- // The data series that is plotted may not be rendered as a line.
- // Therefore, we use our own line renderer here to draw a trend line.
- this.renderer = new $.jqplot.LineRenderer();
- // prop: rendererOptions
- // Options to pass to the line renderer.
- // By default, markers are not shown on trend lines.
- this.rendererOptions = {marker:{show:false}};
- // prop: label
- // Label for the trend line to use in the legend.
- this.label = '';
- // prop: type
- // Either 'exponential', 'exp', or 'linear'.
- this.type = 'linear';
- // prop: shadow
- // true or false, whether or not to show the shadow.
- this.shadow = true;
- // prop: markerRenderer
- // Renderer to use to draw markers on the line.
- // I think this is wrong.
- this.markerRenderer = {show:false};
- // prop: lineWidth
- // Width of the trend line.
- this.lineWidth = 1.5;
- // prop: shadowAngle
- // Angle of the shadow on the trend line.
- this.shadowAngle = 45;
- // prop: shadowOffset
- // pixel offset for each stroke of the shadow.
- this.shadowOffset = 1.0;
- // prop: shadowAlpha
- // Alpha transparency of the shadow.
- this.shadowAlpha = 0.07;
- // prop: shadowDepth
- // number of strokes to make of the shadow.
- this.shadowDepth = 3;
- this.isTrendline = true;
-
- };
-
- $.jqplot.postSeriesInitHooks.push(parseTrendLineOptions);
- $.jqplot.postDrawSeriesHooks.push(drawTrendline);
- $.jqplot.addLegendRowHooks.push(addTrendlineLegend);
-
- // called witin scope of the legend object
- // current series passed in
- // must return null or an object {label:label, color:color}
- function addTrendlineLegend(series) {
- var ret = null;
- if (series.trendline && series.trendline.show) {
- var lt = series.trendline.label.toString();
- if (lt) {
- ret = {label:lt, color:series.trendline.color};
- }
- }
- return ret;
- }
- // called within scope of a series
- function parseTrendLineOptions (target, data, seriesDefaults, options, plot) {
- if (this._type && (this._type === 'line' || this._type == 'bar')) {
- this.trendline = new $.jqplot.Trendline();
- options = options || {};
- $.extend(true, this.trendline, {color:this.color}, seriesDefaults.trendline, options.trendline);
- this.trendline.renderer.init.call(this.trendline, null);
- }
- }
-
- // called within scope of series object
- function drawTrendline(sctx, options) {
- // if we have options, merge trendline options in with precedence
- options = $.extend(true, {}, this.trendline, options);
- if (this.trendline && options.show) {
- var fit;
- // this.renderer.setGridData.call(this);
- var data = options.data || this.data;
- fit = fitData(data, this.trendline.type);
- var gridData = options.gridData || this.renderer.makeGridData.call(this, fit.data);
- this.trendline.renderer.draw.call(this.trendline, sctx, gridData, {showLine:true, shadow:this.trendline.shadow});
- }
- }
-
- function regression(x, y, typ) {
- var type = (typ == null) ? 'linear' : typ;
- var N = x.length;
- var slope;
- var intercept;
- var SX = 0;
- var SY = 0;
- var SXX = 0;
- var SXY = 0;
- var SYY = 0;
- var Y = [];
- var X = [];
-
- if (type == 'linear') {
- X = x;
- Y = y;
- }
- else if (type == 'exp' || type == 'exponential') {
- for ( var i=0; i<y.length; i++) {
- // ignore points <= 0, log undefined.
- if (y[i] <= 0) {
- N--;
- }
- else {
- X.push(x[i]);
- Y.push(Math.log(y[i]));
- }
- }
- }
- for ( var i = 0; i < N; i++) {
- SX = SX + X[i];
- SY = SY + Y[i];
- SXY = SXY + X[i]* Y[i];
- SXX = SXX + X[i]* X[i];
- SYY = SYY + Y[i]* Y[i];
- }
- slope = (N*SXY - SX*SY)/(N*SXX - SX*SX);
- intercept = (SY - slope*SX)/N;
- return [slope, intercept];
- }
- function linearRegression(X,Y) {
- var ret;
- ret = regression(X,Y,'linear');
- return [ret[0],ret[1]];
- }
- function expRegression(X,Y) {
- var ret;
- var x = X;
- var y = Y;
- ret = regression(x, y,'exp');
- var base = Math.exp(ret[0]);
- var coeff = Math.exp(ret[1]);
- return [base, coeff];
- }
- function fitData(data, typ) {
- var type = (typ == null) ? 'linear' : typ;
- var ret;
- var res;
- var x = [];
- var y = [];
- var ypred = [];
-
- for (i=0; i<data.length; i++){
- if (data[i] != null && data[i][0] != null && data[i][1] != null) {
- x.push(data[i][0]);
- y.push(data[i][1]);
- }
- }
-
- if (type == 'linear') {
- ret = linearRegression(x,y);
- for ( var i=0; i<x.length; i++){
- res = ret[0]*x[i] + ret[1];
- ypred.push([x[i], res]);
- }
- }
- else if (type == 'exp' || type == 'exponential') {
- ret = expRegression(x,y);
- for ( var i=0; i<x.length; i++){
- res = ret[1]*Math.pow(ret[0],x[i]);
- ypred.push([x[i], res]);
- }
- }
- return {data: ypred, slope: ret[0], intercept: ret[1]};
- }
- })(jQuery);
|