Compute x/y min and max and x/y scale and set labels
327056
def _compute(self):
        """"""
        if self.xvals:
            xmin = min(self.xvals)
            xmax = max(self.xvals)
            xrng = (xmax - xmin)
        else:
            xrng = None

        if self.yvals:
            ymin = min(min(self.yvals), self.zero)
            ymax = max(max(self.yvals), self.zero)
            yrng = (ymax - ymin)
        else:
            yrng = None

        for serie in self.all_series:
            serie.points = serie.values

        if xrng:
            self._box.xmin, self._box.xmax = xmin, xmax
        if yrng:
            self._box.ymin, self._box.ymax = ymin, ymax

        if self.range and self.range[0] is not None:
            self._box.ymin = self.range[0]

        if self.range and self.range[1] is not None:
            self._box.ymax = self.range[1]
1092173
function scale(x, y) {
         y = typeof y !== "undefined" ? y : x;
         return this.setShape(this.pos.x, this.pos.y, this.radiusV.x * 2 * x, this.radiusV.y * 2 * y);
       }
998390
function () {
            if (!this.coords.w_rs) {
                return;
            }

            this.labels.p_min = this.labels.w_min / this.coords.w_rs * 100;
            this.labels.p_max = this.labels.w_max / this.coords.w_rs * 100;
        }
525447
function setMeasures(data, config, ctx, height, width, ylabels, ylabels2, reverseLegend, reverseAxis, drawAxis, drawLegendOnData, legendBox, typegraph) {
		if (config.canvasBackgroundColor != "none") ctx.canvas.style.background = config.canvasBackgroundColor;
		var borderWidth = 0;
		var xAxisLabelPos = 0;
		var graphTitleHeight = 0;
		var graphTitlePosY = 0;
		var graphSubTitleHeight = 0;
		var graphSubTitlePosY = 0;
		var footNoteHeight = 0;
		var footNotePosY = 0;
		var yAxisUnitHeight = 0;
		var yAxisUnitPosY = 0;
		var widestLegend = 0;
		var nbeltLegend = 0;
		var nbLegendLines = 0;
		var nbLegendCols = 0;
		var spaceLegendHeight = 0;
		var xFirstLegendTextPos = 0;
		var yFirstLegendTextPos = 0;
		var xLegendBorderPos = 0;
		var yLegendBorderPos = 0;
		var yAxisLabelWidth = 0;
		var yAxisLabelPosLeft = 0;
		var yAxisLabelPosRight = 0;
		var xAxisLabelHeight = 0;
		var xLabelHeight = 0;
		var widestXLabel = 1;
		var highestXLabel = 1;
		var widestYLabel = 0;
		var highestYLabel = 1;
		var widestYLabel2 = 0;
		var highestYLabel2 = 1;
		var leftNotUsableSize = 0;
		var rightNotUsableSize = 0;
		var rotateLabels = 0;
		var xLabelPos = 0;
		var legendBorderWidth = 0;
		var legendBorderHeight = 0;
		
		ctx.widthAtSetMeasures=width;
		ctx.heightAtSetMeasures=height;
		
		// Borders
		if (config.canvasBorders) borderWidth = config.canvasBordersWidth;
		// compute widest X label
		if (drawAxis) {
			ctx.font = config.scaleFontStyle + " " + config.scaleFontSize + "px " + config.scaleFontFamily;
			for (var i = 0; i < data.labels.length; i++) {
				var textMsr = ctx.measureTextMultiLine(fmtChartJS(config, data.labels[i], config.fmtXLabel), config.scaleFontSize);
				//If the text length is longer - make that equal to longest text!
				widestXLabel = (textMsr.textWidth > widestXLabel) ? textMsr.textWidth : widestXLabel;
				highestXLabel = (textMsr.textHeight > highestXLabel) ? textMsr.textHeight : highestXLabel;
			}
			if (widestXLabel < config.xScaleLabelsMinimumWidth) {
				widestXLabel = config.xScaleLabelsMinimumWidth;
			}
		}
		// compute Y Label Width
		if (drawAxis) {
			widestYLabel = 1;
			if (ylabels != null && ylabels != "nihil") {
				ctx.font = config.scaleFontStyle + " " + config.scaleFontSize + "px " + config.scaleFontFamily;
				for (var i = ylabels.length - 1; i >= 0; i--) {
					if (typeof(ylabels[i]) == "string") {
						if (ylabels[i].trim() != "") {
							var textMsr = ctx.measureTextMultiLine(fmtChartJS(config, ylabels[i], config.fmtYLabel), config.scaleFontSize);
							//If the text length is longer - make that equal to longest text!
							widestYLabel = (textMsr.textWidth > widestYLabel) ? textMsr.textWidth : widestYLabel;
							highestYLabel = (textMsr.textHeight > highestYLabel) ? textMsr.textHeight : highestYLabel;
						}
					}
				}
			}
			if (widestYLabel < config.yScaleLabelsMinimumWidth) {
				widestYLabel = config.yScaleLabelsMinimumWidth;
			}
			widestYLabel2 = 1;
			if (ylabels2 != null && config.yAxisRight) {
				ctx.font = config.scaleFontStyle + " " + config.scaleFontSize + "px " + config.scaleFontFamily;
				for (var i = ylabels2.length - 1; i >= 0; i--) {
					if (typeof(ylabels2[i]) == "string") {
						if (ylabels2[i].trim() != "") {
							var textMsr = ctx.measureTextMultiLine(fmtChartJS(config, ylabels2[i], config.fmtYLabel2), config.scaleFontSize);
							//If the text length is longer - make that equal to longest text!
							widestYLabel2 = (textMsr.textWidth > widestYLabel2) ? textMsr.textWidth : widestYLabel2;
							highestYLabel2 = (textMsr.textHeight > highestYLabel2) ? textMsr.textHeight : highestYLabel2;
						}
					}
				}
			} else {
				widestYLabel2 = widestYLabel;
			}
			if (widestYLabel2 < config.yScaleLabelsMinimumWidth) {
				widestYLabel2 = config.yScaleLabelsMinimumWidth;
			}
		}
		// yAxisLabel
		leftNotUsableSize = borderWidth + config.spaceLeft
		rightNotUsableSize = borderWidth + config.spaceRight;
		if (drawAxis) {
			if (typeof(config.yAxisLabel) != "undefined") {
				if (config.yAxisLabel.trim() != "") {
					yAxisLabelWidth = (config.yAxisFontSize + config.yAxisLabelSpaceLeft + config.yAxisLabelSpaceRight);
					yAxisLabelPosLeft = borderWidth + config.spaceLeft + config.yAxisLabelSpaceLeft + config.yAxisFontSize;
					yAxisLabelPosRight = width - borderWidth - config.spaceRight - config.yAxisLabelSpaceLeft - config.yAxisFontSize;
				}
			}
			if (config.yAxisLeft) {
				if (reverseAxis == false) leftNotUsableSize = borderWidth + config.spaceLeft + yAxisLabelWidth + widestYLabel + config.yAxisSpaceLeft + config.yAxisSpaceRight;
				else leftNotUsableSize = borderWidth + config.spaceLeft + yAxisLabelWidth + widestXLabel + config.yAxisSpaceLeft + config.yAxisSpaceRight;
			}
			if (config.yAxisRight) {
				if (reverseAxis == false) rightNotUsableSize = borderWidth + config.spaceRight + yAxisLabelWidth + widestYLabel2 + config.yAxisSpaceLeft + config.yAxisSpaceRight;
				else rightNotUsableSize = borderWidth + config.spaceRight + yAxisLabelWidth + widestXLabel + config.yAxisSpaceLeft + config.yAxisSpaceRight;
			}
		}
		availableWidth = width - leftNotUsableSize - rightNotUsableSize;
		// Title
		if (config.graphTitle.trim() != "") {
			graphTitleHeight = (config.graphTitleFontSize * (config.graphTitle.split("\n").length || 1) + config.graphTitleSpaceBefore + config.graphTitleSpaceAfter);
			graphTitlePosY = borderWidth + config.spaceTop + graphTitleHeight - config.graphTitleSpaceAfter;
		}
		// subTitle
		if (config.graphSubTitle.trim() != "") {
			graphSubTitleHeight = (config.graphSubTitleFontSize * (config.graphSubTitle.split("\n").length || 1) + config.graphSubTitleSpaceBefore + config.graphSubTitleSpaceAfter);
			graphSubTitlePosY = borderWidth + config.spaceTop + graphTitleHeight + graphSubTitleHeight - config.graphSubTitleSpaceAfter;
		}
		// yAxisUnit
		if (drawAxis) {
			if (config.yAxisUnit.trim() != "") {
				yAxisUnitHeight = (config.yAxisUnitFontSize + config.yAxisUnitSpaceBefore + config.yAxisUnitSpaceAfter);
				yAxisUnitPosY = borderWidth + config.spaceTop + graphTitleHeight + graphSubTitleHeight + yAxisUnitHeight - config.yAxisUnitSpaceAfter;
			}
		}
		topNotUsableSize = borderWidth + config.spaceTop + graphTitleHeight + graphSubTitleHeight + yAxisUnitHeight + config.graphSpaceBefore;
		// footNote
		if (typeof(config.footNote) != "undefined") {
			if (config.footNote.trim() != "") {
				footNoteHeight = (config.footNoteFontSize + config.footNoteSpaceBefore + config.footNoteSpaceAfter);
				footNotePosY = height - config.spaceBottom - borderWidth - config.footNoteSpaceAfter;
			}
		}
		
		// xAxisLabel
		if (drawAxis) {
			if (typeof(config.xAxisLabel) != "undefined") {
				if (config.xAxisLabel.trim() != "") {
					xAxisLabelHeight = (config.xAxisFontSize + config.xAxisLabelSpaceBefore + config.xAxisLabelSpaceAfter);
					xAxisLabelPos = height - borderWidth - config.spaceBottom - footNoteHeight - config.xAxisLabelSpaceAfter;
				}
			}
		}

		bottomNotUsableHeightWithoutXLabels = borderWidth + config.spaceBottom + footNoteHeight + xAxisLabelHeight + config.graphSpaceAfter;

		// compute space for Legend
		if (typeof(config.legend) != "undefined") {
			if (config.legend == true) {
				ctx.font = config.legendFontStyle + " " + config.legendFontSize + "px " + config.legendFontFamily;
				if (drawLegendOnData) {
					for (var i = data.datasets.length - 1; i >= 0; i--) {
						if (typeof(data.datasets[i].title) == "string") {
							if (data.datasets[i].title.trim() != "") {
								nbeltLegend++;
								var textLength = ctx.measureText(fmtChartJS(config, data.datasets[i].title, config.fmtLegend)).width;
								//If the text length is longer - make that equal to longest text!
								widestLegend = (textLength > widestLegend) ? textLength : widestLegend;
							}
						}
					}
				} else {
					for (var i = data.length - 1; i >= 0; i--) {
						if (typeof(data[i].title) == "string") {
							if (data[i].title.trim() != "") {
								nbeltLegend++;
								var textLength = ctx.measureText(fmtChartJS(config, data[i].title, config.fmtLegend)).width;
								//If the text length is longer - make that equal to longest text!
								widestLegend = (textLength > widestLegend) ? textLength : widestLegend;
							}
						}
					}
				}
				if (nbeltLegend > 1 || (nbeltLegend == 1 && config.showSingleLegend)) {
					widestLegend += config.legendBlockSize + config.legendSpaceBetweenBoxAndText;
					if(config.legendPosY==1 || config.legendPosY==2 || config.legendPosY==3) {
						availableLegendWidth = availableWidth- config.legendSpaceLeftText - config.legendSpaceRightText;
					} else {
						availableLegendWidth = width - config.spaceLeft - config.spaceRight - 2 * (borderWidth) - config.legendSpaceLeftText - config.legendSpaceRightText;
					}
					if (config.legendBorders == true) availableLegendWidth -= 2 * (config.legendBordersWidth) - config.legendBordersSpaceLeft - config.legendBordersSpaceRight;
					maxLegendOnLine = Min([Math.floor((availableLegendWidth + config.legendSpaceBetweenTextHorizontal) / (widestLegend + config.legendSpaceBetweenTextHorizontal)),config.maxLegendCols]);
					nbLegendLines = Math.ceil(nbeltLegend / maxLegendOnLine);
					nbLegendCols = Math.ceil(nbeltLegend / nbLegendLines);
				
					var legendHeight = nbLegendLines * (config.legendFontSize + config.legendSpaceBetweenTextVertical) - config.legendSpaceBetweenTextVertical + config.legendSpaceBeforeText + config.legendSpaceAfterText;
					if (config.legendBorders == true) {
//						legendHeight += 2 * config.legendBordersWidth + config.legendBordersSpaceBefore + config.legendBordersSpaceAfter;
					}

					switch (config.legendPosY) {
						case 0:
							xFirstLegendTextPos = config.spaceLeft + (width - config.spaceLeft - config.spaceRight - nbLegendCols * (widestLegend + config.legendSpaceBetweenTextHorizontal) + config.legendSpaceBetweenTextHorizontal) / 2;
							spaceLegendHeight = legendHeight;
							if (config.legendBorders == true) {
								yLegendBorderPos = topNotUsableSize + config.legendBordersSpaceBefore + (config.legendBordersWidth/2);
								yFirstLegendTextPos = yLegendBorderPos  + (config.legendBordersWidth/2) + config.legendSpaceBeforeText+config.legendFontSize;
								spaceLegendHeight += 2 * config.legendBordersWidth + config.legendBordersSpaceBefore + config.legendBordersSpaceAfter;
								xLegendBorderPos = Math.floor(xFirstLegendTextPos - config.legendSpaceLeftText - (config.legendBordersWidth / 2));
								legendBorderHeight = Math.ceil(spaceLegendHeight - config.legendBordersWidth) - config.legendBordersSpaceBefore - config.legendBordersSpaceAfter;
								legendBorderWidth = Math.ceil(nbLegendCols * (widestLegend + config.legendSpaceBetweenTextHorizontal)) - config.legendSpaceBetweenTextHorizontal + config.legendBordersWidth + config.legendSpaceRightText + config.legendSpaceLeftText;
							} else {
								yFirstLegendTextPos = topNotUsableSize + config.legendBordersSpaceBefore + (config.legendBordersWidth/2);
							}
							if(yAxisUnitHeight>0) {
								yAxisUnitPosY+=spaceLegendHeight;
								if(config.legendBorders==true)yLegendBorderPos-=yAxisUnitHeight;
								yFirstLegendTextPos-=yAxisUnitHeight;
							}
							topNotUsableSize += spaceLegendHeight;
							break;
						case 1:
							spaceLegendHeight = legendHeight;
							xFirstLegendTextPos = config.spaceLeft + (width - config.spaceLeft - config.spaceRight - nbLegendCols * (widestLegend + config.legendSpaceBetweenTextHorizontal) + config.legendSpaceBetweenTextHorizontal) / 2;
							yFirstLegendTextPos = topNotUsableSize + config.legendSpaceBeforeText+config.legendFontSize;
							if (config.legendBorders == true) {
								yFirstLegendTextPos += config.legendBordersSpaceBefore+config.legendBordersWidth;
								yLegendBorderPos = yFirstLegendTextPos - config.legendSpaceBeforeText - config.legendFontSize - (config.legendBordersWidth /2 );
								spaceLegendHeight += 2 * config.legendBordersWidth + config.legendBordersSpaceBefore + config.legendBordersSpaceAfter;
								xLegendBorderPos = Math.floor(xFirstLegendTextPos - config.legendSpaceLeftText - (config.legendBordersWidth / 2));
								legendBorderHeight = Math.ceil(spaceLegendHeight - config.legendBordersWidth) - config.legendBordersSpaceBefore - config.legendBordersSpaceAfter;
								legendBorderWidth = Math.ceil(nbLegendCols * (widestLegend + config.legendSpaceBetweenTextHorizontal)) - config.legendSpaceBetweenTextHorizontal + config.legendBordersWidth + config.legendSpaceRightText + config.legendSpaceLeftText;
							}
							break;
						case 2:
							spaceLegendHeight = legendHeight;
							xFirstLegendTextPos = config.spaceLeft + (width - config.spaceLeft - config.spaceRight - nbLegendCols * (widestLegend + config.legendSpaceBetweenTextHorizontal) + config.legendSpaceBetweenTextHorizontal) / 2;
							yFirstLegendTextPos = topNotUsableSize + (height - topNotUsableSize - bottomNotUsableHeightWithoutXLabels - spaceLegendHeight) /2 + config.legendSpaceBeforeText+config.legendFontSize;
							if (config.legendBorders == true) {
								yFirstLegendTextPos += config.legendBordersSpaceBefore - config.legendBordersSpaceAfter;
								yLegendBorderPos = yFirstLegendTextPos - config.legendSpaceBeforeText - config.legendFontSize - (config.legendBordersWidth /2 );
								spaceLegendHeight += 2 * config.legendBordersWidth + config.legendBordersSpaceBefore + config.legendBordersSpaceAfter;
								xLegendBorderPos = Math.floor(xFirstLegendTextPos - config.legendSpaceLeftText - (config.legendBordersWidth / 2));
								legendBorderHeight = Math.ceil(spaceLegendHeight - config.legendBordersWidth) - config.legendBordersSpaceBefore - config.legendBordersSpaceAfter;
								legendBorderWidth = Math.ceil(nbLegendCols * (widestLegend + config.legendSpaceBetweenTextHorizontal)) - config.legendSpaceBetweenTextHorizontal + config.legendBordersWidth + config.legendSpaceRightText + config.legendSpaceLeftText;
							}
							break;
						case 3:
							spaceLegendHeight = legendHeight;
							xFirstLegendTextPos = config.spaceLeft + (width - config.spaceLeft - config.spaceRight - nbLegendCols * (widestLegend + config.legendSpaceBetweenTextHorizontal) + config.legendSpaceBetweenTextHorizontal) / 2;
							availableHeight = height - topNotUsableSize - bottomNotUsableHeightWithoutXLabels;
							yFirstLegendTextPos = topNotUsableSize + availableHeight - spaceLegendHeight + config.legendSpaceBeforeText+config.legendFontSize;
							if (config.legendBorders == true) {
								yFirstLegendTextPos -= (config.legendBordersSpaceAfter+config.legendBordersWidth);
								yLegendBorderPos = yFirstLegendTextPos - config.legendSpaceBeforeText - config.legendFontSize - (config.legendBordersWidth /2 );
								spaceLegendHeight += 2 * config.legendBordersWidth + config.legendBordersSpaceBefore + config.legendBordersSpaceAfter;
								xLegendBorderPos = Math.floor(xFirstLegendTextPos - config.legendSpaceLeftText - (config.legendBordersWidth / 2));
								legendBorderHeight = Math.ceil(spaceLegendHeight - config.legendBordersWidth) - config.legendBordersSpaceBefore - config.legendBordersSpaceAfter;
								legendBorderWidth = Math.ceil(nbLegendCols * (widestLegend + config.legendSpaceBetweenTextHorizontal)) - config.legendSpaceBetweenTextHorizontal + config.legendBordersWidth + config.legendSpaceRightText + config.legendSpaceLeftText;
							}
							break;
						default:
							spaceLegendHeight = legendHeight;
							yFirstLegendTextPos = height - borderWidth - config.spaceBottom - footNoteHeight - spaceLegendHeight + config.legendSpaceBeforeText + config.legendFontSize;
							xFirstLegendTextPos = config.spaceLeft + (width - config.spaceLeft - config.spaceRight - nbLegendCols * (widestLegend + config.legendSpaceBetweenTextHorizontal) + config.legendSpaceBetweenTextHorizontal) / 2;
							if (config.legendBorders == true) {
								spaceLegendHeight += 2 * config.legendBordersWidth + config.legendBordersSpaceBefore + config.legendBordersSpaceAfter;
								yFirstLegendTextPos -= (config.legendBordersWidth + config.legendBordersSpaceAfter);
								yLegendBorderPos = Math.floor(height - borderWidth - config.spaceBottom - footNoteHeight - spaceLegendHeight + (config.legendBordersWidth / 2) + config.legendBordersSpaceBefore);
								xLegendBorderPos = Math.floor(xFirstLegendTextPos - config.legendSpaceLeftText - (config.legendBordersWidth / 2));
								legendBorderHeight = Math.ceil(spaceLegendHeight - config.legendBordersWidth) - config.legendBordersSpaceBefore - config.legendBordersSpaceAfter;
								legendBorderWidth = Math.ceil(nbLegendCols * (widestLegend + config.legendSpaceBetweenTextHorizontal)) - config.legendSpaceBetweenTextHorizontal + config.legendBordersWidth + config.legendSpaceRightText + config.legendSpaceLeftText;
							} 
							xAxisLabelPos -= spaceLegendHeight;
//							xLabelPos -= spaceLegendHeight;
							bottomNotUsableHeightWithoutXLabels +=spaceLegendHeight;
							break;
					}		
					var fullLegendWidth=config.legendSpaceRightText + nbLegendCols * (widestLegend + config.legendSpaceBetweenTextHorizontal) - config.legendSpaceBetweenTextHorizontal +config.legendSpaceLeftText;
					if (config.legendBorders == true) {
						fullLegendWidth+=2*config.legendBordersWidth+config.legendBordersSpaceLeft+config.legendBordersSpaceRight;
					}

					switch (config.legendPosX) {
						case 0:
							xFirstLegendTextPos = config.spaceLeft + config.canvasBorders * config.canvasBordersWidth + config.legendSpaceLeftText;  
							if (config.legendBorders == true) {
								xFirstLegendTextPos += config.legendBordersWidth+config.legendBordersSpaceLeft;
								xLegendBorderPos = config.spaceLeft + config.canvasBorders * config.canvasBordersWidth + config.legendBordersSpaceLeft;
							}
							if(config.legendPosY>=1 && config.legendPosY <=3) {
								leftNotUsableSize+=fullLegendWidth;
								yAxisLabelPosLeft+=fullLegendWidth;
							}
							break;
						case 1:
							xFirstLegendTextPos = leftNotUsableSize + config.legendSpaceLeftText;  
							if (config.legendBorders == true) {
								xLegendBorderPos = xFirstLegendTextPos;
								xFirstLegendTextPos += config.legendBordersWidth+config.legendBordersSpaceLeft;
							}
							break;
						case 2:
							xFirstLegendTextPos = leftNotUsableSize + (width - rightNotUsableSize - leftNotUsableSize)/2 - (config.legendSpaceLeftText-config.legendSpaceRightText) - (nbLegendCols * (widestLegend + config.legendSpaceBetweenTextHorizontal) - config.legendSpaceBetweenTextHorizontal) / 2;  
							if (config.legendBorders == true) {
								xFirstLegendTextPos -= (config.legendBordersWidth + config.legendBordersSpaceRight);
								xLegendBorderPos = xFirstLegendTextPos - config.legendBordersWidth/2 - config.legendSpaceLeftText ;
							}
							break;
						case 3:
							
							xFirstLegendTextPos = width - rightNotUsableSize - config.legendSpaceRightText - nbLegendCols * (widestLegend + config.legendSpaceBetweenTextHorizontal) + config.legendSpaceBetweenTextHorizontal / 2;  
							if (config.legendBorders == true) {
								xFirstLegendTextPos -= (config.legendBordersWidth + config.legendBordersSpaceRight);
								xLegendBorderPos = xFirstLegendTextPos - config.legendBordersWidth/2 - config.legendSpaceLeftText ;
							}
							break;
						case 4:
							xFirstLegendTextPos = width - config.spaceRight - config.canvasBorders * config.canvasBordersWidth - config.legendSpaceRightText - nbLegendCols * (widestLegend + config.legendSpaceBetweenTextHorizontal) + config.legendSpaceBetweenTextHorizontal / 2;  
							if (config.legendBorders == true) {
								xFirstLegendTextPos -= (config.legendBordersWidth+config.legendBordersSpaceRight);
								xLegendBorderPos = xFirstLegendTextPos - config.legendBordersSpaceLeft - config.legendBordersWidth/2;
							}
							if(config.legendPosY>=1 && config.legendPosY <=3) {
								rightNotUsableSize+=fullLegendWidth;
								yAxisLabelPosRight-=fullLegendWidth;
							}
							break;
							
						default:
							break;
					}
					if(config.legendBorders==true) {
						yLegendBorderPos+=config.legendYPadding;
						xLegendBorderPos+=config.legendXPadding;
						
					}
					yFirstLegendTextPos+=config.legendYPadding;	
					xFirstLegendTextPos+=config.legendXPadding;	
					
				}
			}
		}
		xLabelWidth = 0;
		bottomNotUsableHeightWithXLabels = bottomNotUsableHeightWithoutXLabels;
		if (drawAxis && (config.xAxisBottom || config.xAxisTop)) {
			if (reverseAxis == false) {
				var widestLabel = widestXLabel;
				var highestLabel = highestXLabel;
				nblab = data.labels.length;
			} else {
				var widestLabel = widestYLabel;
				var highestLabel = highestYLabel;
				nblab = ylabels.length;
			}
			if (config.rotateLabels == "smart") {
				rotateLabels = 0;
				if ((availableWidth + config.xAxisSpaceBetweenLabels) / nblab < (widestLabel + config.xAxisSpaceBetweenLabels)) {
					rotateLabels = 45;
					if (availableWidth / nblab < Math.abs(Math.cos(rotateLabels * Math.PI / 180) * widestLabel)) {
						rotateLabels = 90;
					}
				}
			} else {
				rotateLabels = config.rotateLabels
				if (rotateLabels < 0) rotateLabels = 0;
				if (rotateLabels > 180) rotateLabels = 180;
			}
			if (rotateLabels > 90) rotateLabels += 180;
			xLabelHeight = Math.abs(Math.sin(rotateLabels * Math.PI / 180) * widestLabel) + Math.abs(Math.sin((rotateLabels + 90) * Math.PI / 180) * highestLabel) + config.xAxisSpaceBefore + config.xAxisSpaceAfter;
			xLabelPos = height - borderWidth - config.spaceBottom - footNoteHeight - xAxisLabelHeight - (xLabelHeight - config.xAxisSpaceBefore) - config.graphSpaceAfter;
			xLabelWidth = Math.abs(Math.cos(rotateLabels * Math.PI / 180) * widestLabel) + Math.abs(Math.cos((rotateLabels + 90) * Math.PI / 180) * highestLabel);
			leftNotUsableSize = Max([leftNotUsableSize, borderWidth + config.spaceLeft + xLabelWidth / 2]);
			rightNotUsableSize = Max([rightNotUsableSize, borderWidth + config.spaceRight + xLabelWidth / 2]);
			availableWidth = width - leftNotUsableSize - rightNotUsableSize;
			if (config.legend && config.xAxisBottom && config.legendPosY==4) {
				xLabelPos-=spaceLegendHeight;
			} 
			bottomNotUsableHeightWithXLabels = bottomNotUsableHeightWithoutXLabels + xLabelHeight ;
		}  else {
			availableWidth = width - leftNotUsableSize - rightNotUsableSize;
		}

		availableHeight = height - topNotUsableSize - bottomNotUsableHeightWithXLabels;

		// ----------------------- DRAW EXTERNAL ELEMENTS -------------------------------------------------
		dispCrossImage(ctx, config, width / 2, height / 2, width / 2, height / 2, false, data, -1, -1);
 		if (ylabels != "nihil") {
			// Draw Borders
			if (borderWidth > 0) {
				ctx.save();
				ctx.beginPath();
				ctx.lineWidth = 2 * borderWidth;
				ctx.strokeStyle = config.canvasBordersColor;
				ctx.moveTo(0, 0);
				ctx.lineTo(0, height);
				ctx.lineTo(width, height);
				ctx.lineTo(width, 0);
				ctx.lineTo(0, 0);
				ctx.stroke();
				ctx.restore();
			}
			// Draw Graph Title
			if (graphTitleHeight > 0) {
				ctx.save();
				ctx.beginPath();
				ctx.font = config.graphTitleFontStyle + " " + config.graphTitleFontSize + "px " + config.graphTitleFontFamily;
				ctx.fillStyle = config.graphTitleFontColor;
				ctx.textAlign = "center";
				ctx.textBaseline = "bottom";
				ctx.translate(config.spaceLeft + (width - config.spaceLeft - config.spaceRight) / 2, graphTitlePosY);
				ctx.fillTextMultiLine(config.graphTitle, 0, 0, ctx.textBaseline, config.graphTitleFontSize);
				ctx.stroke();
				ctx.restore();
			}
			// Draw Graph Sub-Title
			if (graphSubTitleHeight > 0) {
				ctx.save();
				ctx.beginPath();
				ctx.font = config.graphSubTitleFontStyle + " " + config.graphSubTitleFontSize + "px " + config.graphSubTitleFontFamily;
				ctx.fillStyle = config.graphSubTitleFontColor;
				ctx.textAlign = "center";
				ctx.textBaseline = "bottom";
				ctx.translate(config.spaceLeft + (width - config.spaceLeft - config.spaceRight) / 2, graphSubTitlePosY);
				ctx.fillTextMultiLine(config.graphSubTitle, 0, 0, ctx.textBaseline, config.graphSubTitleFontSize);
				ctx.stroke();
				ctx.restore();
			}
			// Draw Y Axis Unit
			if (yAxisUnitHeight > 0) {
				if (config.yAxisLeft) {
					ctx.save();
					ctx.beginPath();
					ctx.font = config.yAxisUnitFontStyle + " " + config.yAxisUnitFontSize + "px " + config.yAxisUnitFontFamily;
					ctx.fillStyle = config.yAxisUnitFontColor;
					ctx.textAlign = "center";
					ctx.textBaseline = "bottom";
					ctx.translate(leftNotUsableSize, yAxisUnitPosY);
					ctx.fillText(config.yAxisUnit, 0, 0);
					ctx.stroke();
					ctx.restore();
				}
				if (config.yAxisRight) {
					if (config.yAxisUnit2 == '') config.yAxisUnit2 = config.yAxisUnit;
					ctx.save();
					ctx.beginPath();
					ctx.font = config.yAxisUnitFontStyle + " " + config.yAxisUnitFontSize + "px " + config.yAxisUnitFontFamily;
					ctx.fillStyle = config.yAxisUnitFontColor;
					ctx.textAlign = "center";
					ctx.textBaseline = "bottom";
					ctx.translate(width - rightNotUsableSize, yAxisUnitPosY);
					ctx.fillText(config.yAxisUnit2, 0, 0);
					ctx.stroke();
					ctx.restore();
				}
			}
			// Draw Y Axis Label
			if (yAxisLabelWidth > 0) {
				if (config.yAxisLeft) {
					ctx.save();
					ctx.beginPath();
					ctx.font = config.yAxisFontStyle + " " + config.yAxisFontSize + "px " + config.yAxisFontFamily;
					ctx.fillStyle = config.yAxisFontColor;
					ctx.textAlign = "center";
					ctx.textBaseline = "bottom";
					ctx.translate(yAxisLabelPosLeft, topNotUsableSize + (availableHeight / 2));
					ctx.rotate(-(90 * (Math.PI / 180)));
					ctx.fillText(config.yAxisLabel, 0, 0);
					ctx.stroke();
					ctx.restore();
				}
				if (config.yAxisRight) {
					if (config.yAxisLabel2 == '') config.yAxisLabel2 = config.yAxisLabel;
					ctx.save();
					ctx.beginPath();
					ctx.font = config.yAxisFontStyle + " " + config.yAxisFontSize + "px " + config.yAxisFontFamily;
					ctx.fillStyle = config.yAxisFontColor;
					ctx.textAlign = "center";
					ctx.textBaseline = "bottom";
					ctx.translate(yAxisLabelPosRight, topNotUsableSize + (availableHeight / 2));
					ctx.rotate(+(90 * (Math.PI / 180)));
					ctx.fillText(config.yAxisLabel2, 0, 0);
					ctx.stroke();
					ctx.restore();
				}
			}
			// Draw X Axis Label
			if (xAxisLabelHeight > 0) {
				if (config.xAxisBottom) {
					ctx.save();
					ctx.beginPath();
					ctx.font = config.xAxisFontStyle + " " + config.xAxisFontSize + "px " + config.xAxisFontFamily;
					ctx.fillStyle = config.xAxisFontColor;
					ctx.textAlign = "center";
					ctx.textBaseline = "bottom";
					ctx.translate(leftNotUsableSize + (availableWidth / 2), xAxisLabelPos);
					ctx.fillText(config.xAxisLabel, 0, 0);
					ctx.stroke();
					ctx.restore();
				}
			}
			// Draw Legend

			if (nbeltLegend > 1 || (nbeltLegend == 1 && config.showSingleLegend)) {
				var legendMsr={dispLegend : true, xLegendBorderPos : xLegendBorderPos,
					   yLegendBorderPos : yLegendBorderPos, legendBorderWidth : legendBorderWidth, legendBorderHeight : legendBorderHeight, 
					   nbLegendCols: nbLegendCols, xFirstLegendTextPos : xFirstLegendTextPos , yFirstLegendTextPos : yFirstLegendTextPos, 
					   drawLegendOnData : drawLegendOnData, reverseLegend : reverseLegend, legendBox : legendBox, widestLegend : widestLegend };
				if(config.legendPosY==0 || config.legendPosY==4 || config.legendPosX==0 || config.legendPosX==4) {
					drawLegend(legendMsr,data,config,ctx,typegraph);
					var legendMsr={dispLegend : false};
				} 
			} else {
				var legendMsr={dispLegend : false };
			}
			// Draw FootNote
			if (config.footNote.trim() != "") {
				ctx.save();
				ctx.font = config.footNoteFontStyle + " " + config.footNoteFontSize + "px " + config.footNoteFontFamily;
				ctx.fillStyle = config.footNoteFontColor;
				ctx.textAlign = "center";
				ctx.textBaseline = "bottom";
				ctx.translate(leftNotUsableSize + (availableWidth / 2), footNotePosY);
				ctx.fillText(config.footNote, 0, 0);
				ctx.stroke();
				ctx.restore();
			}
		}
		clrx = leftNotUsableSize;
		clrwidth = availableWidth;
		clry = topNotUsableSize;
		clrheight = availableHeight;
		return {
			leftNotUsableSize: leftNotUsableSize,
			rightNotUsableSize: rightNotUsableSize,
			availableWidth: availableWidth,
			topNotUsableSize: topNotUsableSize,
			bottomNotUsableHeightWithoutXLabels: bottomNotUsableHeightWithoutXLabels,
			bottomNotUsableHeightWithXLabels: bottomNotUsableHeightWithXLabels,
			availableHeight: availableHeight,
			widestXLabel: widestXLabel,
			highestXLabel: highestXLabel,
			widestYLabel: widestYLabel,
			widestYLabel2: widestYLabel2,
			highestYLabel: highestYLabel,
			rotateLabels: rotateLabels,
			xLabelPos: xLabelPos,
			clrx: clrx,
			clry: clry,
			clrwidth: clrwidth,
			clrheight: clrheight,
			legendMsr : legendMsr
		};
	}
1335500
def set_ylim_cb(self, redraw=True):
        """"""
        try:
            ymin = float(self.w.y_lo.get_text())
        except Exception:
            set_min = True
        else:
            set_min = False

        try:
            ymax = float(self.w.y_hi.get_text())
        except Exception:
            set_max = True
        else:
            set_max = False

        if set_min or set_max:
            self.tab_plot.draw()
            self.set_ylimits_widgets(set_min=set_min, set_max=set_max)

        if not (set_min and set_max):
            self.tab_plot.ax.set_ylim(ymin, ymax)
            if redraw:
                self.tab_plot.draw()
774834
def _compute_secondary(self):
        """"""
        # secondary y axis support
        if self.secondary_series and self._y_labels:
            y_pos = list(zip(*self._y_labels))[1]
            if self.include_x_axis:
                ymin = min(self._secondary_min, 0)
                ymax = max(self._secondary_max, 0)
            else:
                ymin = self._secondary_min
                ymax = self._secondary_max
            steps = len(y_pos)
            left_range = abs(y_pos[-1] - y_pos[0])
            right_range = abs(ymax - ymin) or 1
            scale = right_range / ((steps - 1) or 1)
            self._y_2nd_labels = [(self._y_format(ymin + i * scale), pos)
                                  for i, pos in enumerate(y_pos)]

            self._scale = left_range / right_range
            self._scale_diff = y_pos[0]
            self._scale_min_2nd = ymin
405529
def label_subplot(ax=None, x=0.5, y=-0.25, text="(a)", **kwargs):
    """"""
    if ax is None:
        ax = plt.gca()
    ax.text(x=x, y=y, s=text, transform=ax.transAxes,
            horizontalalignment="center", verticalalignment="top", **kwargs)
591312
function () {
        var axis = this;
        var labelModel = axis.getLabelModel();

        var ordinalScale = axis.scale;
        var ordinalExtent = ordinalScale.getExtent();
        // Providing this method is for optimization:
        // avoid generating a long array by `getTicks`
        // in large category data case.
        var tickCount = ordinalScale.count();

        if (ordinalExtent[1] - ordinalExtent[0] < 1) {
            return 0;
        }

        var tickValue = ordinalExtent[0];
        var unitSpan = axis.dataToCoord(tickValue + 1) - axis.dataToCoord(tickValue);
        var unitH = Math.abs(unitSpan);

        // Not precise, just use height as text width
        // and each distance from axis line yet.
        var rect = textContain.getBoundingRect(
            tickValue, labelModel.getFont(), 'center', 'top'
        );
        var maxH = Math.max(rect.height, 7);

        var dh = maxH / unitH;
        // 0/0 is NaN, 1/0 is Infinity.
        isNaN(dh) && (dh = Infinity);
        var interval = Math.max(0, Math.floor(dh));

        var cache = inner(axis.model);
        var lastAutoInterval = cache.lastAutoInterval;
        var lastTickCount = cache.lastTickCount;

        // Use cache to keep interval stable while moving zoom window,
        // otherwise the calculated interval might jitter when the zoom
        // window size is close to the interval-changing size.
        if (lastAutoInterval != null
            && lastTickCount != null
            && Math.abs(lastAutoInterval - interval) <= 1
            && Math.abs(lastTickCount - tickCount) <= 1
            // Always choose the bigger one, otherwise the critical
            // point is not the same when zooming in or zooming out.
            && lastAutoInterval > interval
        ) {
            interval = lastAutoInterval;
        }
        // Only update cache if cache not used, otherwise the
        // changing of interval is too insensitive.
        else {
            cache.lastTickCount = tickCount;
            cache.lastAutoInterval = interval;
        }

        return interval;
    }
190917
function BoundingBox2D( xMin , yMin , xMax , yMax ) {
	this.min = new Vector2D( xMin , yMin ) ;
	this.max = new Vector2D( xMax , yMax ) ;
}
741430
def scale_values(numbers, num_lines=1, minimum=None, maximum=None):
    ""

    # find min/max values, ignoring Nones
    filtered = [n for n in numbers if n is not None]
    min_ = min(filtered) if minimum is None else minimum
    max_ = max(filtered) if maximum is None else maximum
    dv = max_ - min_

    # clamp
    numbers = [max(min(n, max_), min_) if n is not None else None for n in numbers]

    if dv == 0:
        values = [4 * num_lines if x is not None else None for x in numbers]
    elif dv > 0:
        num_blocks = len(blocks) - 1

        min_index = 1.
        max_index = num_lines * num_blocks

        values = [
            ((max_index - min_index) * (x - min_)) / dv + min_index
            if not x is None else None for x in numbers
        ]

        values = [round(v) or 1 if not v is None else None for v in values]
    return values
1083228
function scale(x, y) {
         return this._set(this._x * x, this._y * (typeof y !== "undefined" ? y : x));
       }
138326
def set_ylabels(self, label=None, **kwargs):
        """"""
        if label is None:
            label = label_from_attrs(self.data[self._y_var])
        for ax in self._left_axes:
            ax.set_ylabel(label, **kwargs)
        return self
1082079
def feature_scaling(x, xmin, xmax, a=0, b=1):
    ''''''
    return a + float(x - xmin) * (b - a) / (xmax - xmin)
546055
def min(x, y, context=None):
    
    return _apply_function_in_current_context(
        BigFloat,
        mpfr.mpfr_min,
        (
            BigFloat._implicit_convert(x),
            BigFloat._implicit_convert(y),
        ),
        context,
    )
1115775
def autoscale_y(ax,margin=0.1):
    """"""
    # Thanks to http://stackoverflow.com/questions/29461608/matplotlib-fixing-x-axis-scale-and-autoscale-y-axis for inspiring this!
    
    import numpy as np

    def get_bottom_top(line,lo,hi):
        xd = line.get_xdata()
        yd = line.get_ydata()
        y_displayed = yd[((xd>lo) & (xd<hi))]
        if len(y_displayed)==0:
            #No plotted data is inside the xlims
            return None, None
        else:
            h = np.max(y_displayed) - np.min(y_displayed)
            bot = np.min(y_displayed)-margin*h
            top = np.max(y_displayed)+margin*h
            return bot,top

    lines = ax.get_lines()
     
    lo,hi = ax.get_xlim()
    
    # Do a quick check to see if the x-axis has been inverted
    if lo>hi: # Reverse them for now
        lo,hi = hi,lo
        
    # Initialize limits
    bot,top = np.inf, -np.inf

    for line in lines:
        new_bot, new_top = get_bottom_top(line,lo,hi)
        if new_bot is not None:
            if new_bot < bot: bot = new_bot
            if new_top > top: top = new_top

    # Check to see if it is appropriate to change the boundaries
    if bot !=np.inf and top != -np.inf:    
        ax.set_ylim(bot,top)
    
    return ax
80567
def normalize_pts(pts, ymax, scaler=2):
    
    return [(x * scaler, ymax - (y * scaler)) for x, y in pts]
926601
def _compute_labels(self, element, data, mapping):
        
        if element.vdims:
            edges = Dataset(element)[element[element.vdims[0].name]>0]
            nodes = list(np.unique([edges.dimension_values(i) for i in range(2)]))
            nodes = element.nodes.select(**{element.nodes.kdims[2].name: nodes})
        else:
            nodes = element

        label_dim = nodes.get_dimension(self.label_index)
        labels = self.labels
        if label_dim and labels:
            if self.label_index not in [2, None]:
                self.param.warning(
                    "Cannot declare style mapping for 'labels' option "
                    "and declare a label_index; ignoring the label_index.")
        elif label_dim:
            labels = label_dim
        if isinstance(labels, basestring):
            labels = element.nodes.get_dimension(labels)

        if labels is None:
            text = []
        if isinstance(labels, dim):
            text = labels.apply(element, flat=True)
        else:
            text = element.nodes.dimension_values(labels)
            text = [labels.pprint_value(v) for v in text]

        value_dim = element.vdims[0]
        text_labels = []
        for i, node in enumerate(element._sankey['nodes']):
            if len(text):
                label = text[i]
            else:
                label = ''
            if self.show_values:
                value = value_dim.pprint_value(node['value'])
                if label:
                    label = '%s - %s' % (label, value)
                else:
                    label = value
            if value_dim.unit:
                label += ' %s' % value_dim.unit
            if label:
                text_labels.append(label)

        ys = nodes.dimension_values(1)
        nodes = element._sankey['nodes']
        if nodes:
            offset = (nodes[0]['x1']-nodes[0]['x0'])/4.
        else:
            offset = 0
        if self.label_position == 'right':
            xs = np.array([node['x1'] for node in nodes])+offset
        else:
            xs = np.array([node['x0'] for node in nodes])-offset
        data['text_1'] = dict(x=xs, y=ys, text=[str(l) for l in text_labels])
        align = 'left' if self.label_position == 'right' else 'right'
        mapping['text_1'] = dict(text='text', x='x', y='y', text_baseline='middle', text_align=align)