"Barchart with bespoke bars" #Autogenerated by ReportLab guiedit do not edit from reportlab.lib.colors import toColor, _PCMYK_white, PCMYKColor from reportlab.graphics.shapes import _DrawingEditorMixin, Group, String, Rect, Drawing, Path from reportlab.lib.formatters import DecimalFormatter from reportlab.lib.units import mm from reportlab.graphics.charts.barcharts import HorizontalBarChart, VerticalBarChart from reportlab.pdfbase.pdfmetrics import registerFont def pot_curve(x=0,y=0,width=30,height=None,fillColor='red',strokeColor=None,strokeWidth=0): operators=[0, 2, 1, 1, 2, 2, 1, 2, 2, 1, 1, 2, 2, 2, 1, 2, 2, 3, 0, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 2, 3] points = [13.198, 7.4, 12.01, 8.469, 10.347, 9.127, 8.56, 9.245, 8.56, 9.683, 8.675, 9.683, 8.889, 9.683, 9.063, 9.877, 9.063, 10.112, 9.063, 10.353, 8.889, 10.546, 8.675, 10.546, 7.289, 10.546, 7.074, 10.546, 6.901, 10.353, 6.901, 10.112, 6.901, 9.877, 7.074, 9.683, 7.289, 9.683, 7.403, 9.683, 7.403, 9.245, 5.617, 9.127, 3.953, 8.469, 2.765, 7.4, 2.765, 7.4, 2.686, 7.116, 2.686, 7.023, 2.686, 6.845, 2.795, 6.703, 2.928, 6.703, 13.037, 6.703, 13.17, 6.703, 13.28, 6.845, 13.28, 7.023, 13.28, 7.116, 13.198, 7.4, 13.198, 7.4, 15.571, 5.731, 13.66, 5.731, 13.443, 5.731, 13.266, 5.52, 13.266, 5.261, 13.266, 5.089, 13.342, 4.94, 13.456, 4.856, 13.378, 4.791, 13.283, 4.737, 13.175, 4.698, 13.175, 6.373, 2.79, 6.373, 2.79, 4.698, 2.682, 4.737, 2.584, 4.791, 2.508, 4.856, 2.622, 4.94, 2.697, 5.089, 2.697, 5.261, 2.697, 5.52, 2.521, 5.731, 2.305, 5.731, 0.394, 5.731, 0.176, 5.731, 0.0, 5.52, 0.0, 5.261, 0.0, 4.999, 0.176, 4.789, 0.394, 4.789, 1.777, 4.789, 1.954, 4.432, 2.33, 4.16, 2.79, 4.06, 2.79, 0.811, 2.79, 0.364, 3.313, 0.0, 3.961, 0.0, 12.004, 0.0, 12.649, 0.0, 13.175, 0.364, 13.175, 0.811, 13.175, 4.06, 13.633, 4.16, 14.008, 4.432, 14.187, 4.789, 15.571, 4.789, 15.788, 4.789, 15.965, 4.999, 15.965, 5.261, 15.965, 5.52, 15.788, 5.731, 15.571, 5.731] iPotTop = points.index(5.731) n = len(points) xMax = max((points[i] for i in range(0,n,2))) xMin = min((points[i] for i in range(0,n,2))) yMax = max((points[i] for i in range(1,n,2))) sx = float(width)/xMax for i in range(0,n,2): points[i] = x + sx*points[i] sy = (sx*5)/6 if height is None: height = yMax*sy dy = height-yMax*sy if dy<0: sy = float(height)/yMax dy = 0 for i in range(1,n,2): points[i] = y + sy*points[i] + (dy if points[i]>0.811 else 0) P = Path( points = points, operators = operators, fillColor= fillColor and toColor(fillColor) or None, strokeColor= strokeColor and toColor(strokeColor) or None, strokeWidth = strokeWidth or 0, ) P._potTop = points[iPotTop] P._x = x P._y = y P._width = width P._height = height return P class PotBarChart(_DrawingEditorMixin,Drawing): def __init__(self,width=400,height=200,*args,**kw): Drawing.__init__(self,width,height,*args,**kw) self._stdFont = 'Helvetica' self._boldFont = 'Helvetica-Bold' self._lightBlue = PCMYKColor(0, 39, 0, 2) self._boxBlue = PCMYKColor(95.69,0,1.57,0) self._darkBlue = PCMYKColor(95.29,47.84,6.27,1.57) self._darkGrey = PCMYKColor(47.06,35.29,30.98,16.47) self._data = [[106000.0, 26300.0]] self._add(self,Group(),name='pots',validate=None,desc=None) self._add(self,VerticalBarChart(),name='bc',validate=None,desc=None) #splitPath(self.db) self.width = 105*mm self.height = 97*mm self.bc.data = [(0,)] self.bc.valueAxis.valueMin = 0 self.bc.x = 13*mm self.bc.y = 15*mm self.bc.height = 74*mm self.bc.width = 89*mm self.bc.valueAxis.valueMax = 65000 self.bc.valueAxis.tickLeft = 0 self.bc.valueAxis.tickRight = 6 self.bc.valueAxis.strokeColor = self._darkGrey self.bc.valueAxis.labels.fillColor = self._darkGrey self.bc.valueAxis.labelTextFormat = DecimalFormatter(0,thousandSep=',') self.bc.valueAxis.labels.dx = -2 self.bc.valueAxis.labels.fontSize = 9 self.bc.valueAxis.maximumTicks = 16 self.bc.valueAxis.rangeRound = 'ceiling' self.bc.valueAxis.labels.fontName = self._stdFont self.bc.categoryAxis.tickDown = 0 self.bc.categoryAxis.tickUp = 6 self.bc.categoryAxis.strokeColor = self._darkGrey iy0 = self.bc.y+73*mm iy1 = self.bc.y+68*mm self._potWidth = 39*mm self._pot0x = self.bc.x + 5*mm self._pot1x = self.bc.x + 49*mm self._add(self,pot_curve(x=self.bc.x+49*mm,y=iy0,width=5*mm,fillColor=self._lightBlue),name='icon0',validate=None,desc=None) self._add(self,pot_curve(x=self.bc.x+49*mm,y=iy1,width=5*mm,fillColor=self._darkBlue),name='icon1',validate=None,desc=None) self._add(self,String(self.bc.x+56*mm,iy0+1,'Current Pensionable Salary',fontName=self._stdFont,fontSize=2*mm,fillColor=self._darkGrey),name='txt0',validate=None,desc=None) self._add(self,String(self.bc.x+56*mm,iy1+1,'Statutory Illustration',fontName=self._stdFont,fontSize=2*mm,fillColor=self._darkGrey),name='txt1',validate=None,desc=None) self._add(self,String(self.bc.x-8,self.bc.y+self.bc.height+8,'\xc2\xa3',fontName=self._stdFont,fontSize=3*mm,fillColor=self._darkGrey),name='txt2',validate=None,desc=None) self._add(self,String(self._pot0x+self._potWidth*0.5,self.bc.y+22*mm,'XX,XXX',fontName=self._boldFont,fontSize=3*mm,textAnchor='middle'),name='lab0',validate=None,desc=None) self._add(self,String(self._pot1x+self._potWidth*0.5,self.bc.y+13*mm,'XX,XXX',fontName=self._boldFont,fontSize=3*mm,textAnchor='middle'),name='lab1',validate=None,desc=None) self._add(self,Rect(x=0,y=0,width=self.width,height=self.height,strokeColor=self._boxBlue,fillColor=None),name='bg',validate=None,desc=None) self._labFormat = DecimalFormatter(0,thousandSep=',',prefix='\xa3') def getContents(self): data = self._data bc = self.bc vA = bc.valueAxis vA.valueMax = max(data[0]) if vA.valueMax<=1e-8: vA.valueMax = 5000 vA._length = bc.height vA._y = bc.y vA.configure(data) v0 = data[0][0] v1 = data[0][1] h0 = vA.scale(v0)-bc.y h1 = vA.scale(v1)-bc.y bc = self.bc pots = self.pots pots.contents[:] = [] pot0 = pot_curve(x=self._pot0x,y=bc.y,width=self._potWidth,height=h0,fillColor=self._lightBlue) pot1 = pot_curve(x=self._pot1x,y=bc.y,width=self._potWidth,height=h1,fillColor=self._darkBlue) pots.add(pot0) pots.add(pot1) phLim = 25 ph0 = pot0._potTop - pot0._y self.lab0.y = pot0._y+(ph0*0.5 if ph0>=phLim else h0+5) self.lab0.fillColor = _PCMYK_white if ph0>=phLim else self._darkGrey self.lab0.text = self._labFormat(v0) ph1 = pot1._potTop - pot1._y self.lab1.y = pot1._y+(ph1*0.5 if ph1>=phLim else h1+5) self.lab1.fillColor = _PCMYK_white if ph1>=phLim else self._darkGrey self.lab1.text = self._labFormat(v1) return Drawing.getContents(self) if __name__=="__main__": #NORUNTESTS PotBarChart().save(formats=['pdf'],outDir='.',fnRoot=None)