Exemple #1
0
class Labels():
    def __init__(self, N_labels, fontSize):
        self.fontSize = fontSize
        self.initLabels(N_labels)
        self.fontManager = FontManager(fontSize)

    def stepFont(self):
        for label in self.labels:
            newFont = QtGui.QFont(self.fontManager.step(),
                                  self.fontManager.fontSize)
            label.setFont(newFont)

    def changeFontSize(self, delta):
        self.fontManager.changeFontSize(delta)
        for label in self.labels:
            font = label.font()
            font.setPointSize(self.fontManager.fontSize)
            label.setFont(font)

    def initLabels(self, N_labels):
        self.labels = []
        self.N_labels = N_labels
        for i in range(N_labels):
            self.labels.append(QLabel(""))
            self.labels[-1].setAlignment(Qt.AlignCenter)

    def setText(self, string_list):
        for i, s in enumerate(string_list):
            self.labels[i].setText(s)
Exemple #2
0
    def __init__(self,
                 title,
                 outputFile,
                 paperSize,
                 timestamp="",
                 includeSplunkLogo=None,
                 cidFontList=None):
        """ outputFile can either be a filename or a file-like object """
        self.outputFile = outputFile
        self.paperSize = paperSize
        self.reportLabPaperSize = PAPERSIZES[
            self.paperSize]['reportLabPaperSize']
        self.logoTransformSize = PAPERSIZES[
            self.paperSize]['logoTransformSize']
        self._log("outputFile: " + str(self.outputFile))
        self._log("reportLabPaperSize: " + str(self.reportLabPaperSize))
        self._title = title
        self._timestamp = timestamp
        if includeSplunkLogo != None:
            self._includeSplunkLogo = includeSplunkLogo
        logger.debug("pdf-init pdfrenderer include-splunk-logo=%s" %
                     self._includeSplunkLogo)

        self._fontManager = FontManager(cidFontList=cidFontList)

        self.TITLE_STYLE.fontSize = 14
        self.TITLE_STYLE.leading = 16
        self.CENTER_STYLE.alignment = reportlab.lib.enums.TA_CENTER

        # TODO: need a better way to determine max cell height
        #       225 ~= margins + footer height + a few lines for header row
        self.maxTableCellHeight = self.reportLabPaperSize[1] - 225
        return
Exemple #3
0
class PDFRenderer(object):

    ONE_INCH = 1.0 * inch
    MIN_HEIGHT_TABLE_AND_CHART = 4 * inch

    _fontManager = None

    outputFile = None
    reportLabPaperSize = (0, 0)
    _includeSplunkLogo = True
    _title = ""
    _story = []
    _runningAsScript = False

    _style = STYLES["Normal"]
    CENTER_STYLE = copy.deepcopy(STYLES['Normal'])
    TITLE_STYLE = copy.deepcopy(STYLES["Normal"])
    BULLET_STYLE = STYLES["Bullet"]
    _bulletStyle = STYLES["Bullet"]
    _tableTitleStyle = STYLES["Title"]
    _listTitleStyle = STYLES["Bullet"]
    _hardWrapStyle = copy.deepcopy(STYLES["Normal"])
    _hardWrapStyle.wordWrap = "CJK"
    _TABLE_COL_LEFT_PADDING = 2
    _TABLE_COL_RIGHT_PADDING = 2
    _MARGINS = [inch, inch, inch, inch]

    def __init__(self,
                 title,
                 outputFile,
                 paperSize,
                 timestamp="",
                 includeSplunkLogo=None,
                 cidFontList=None):
        """ outputFile can either be a filename or a file-like object """
        self.outputFile = outputFile
        self.paperSize = paperSize
        self.reportLabPaperSize = PAPERSIZES[
            self.paperSize]['reportLabPaperSize']
        self.logoTransformSize = PAPERSIZES[
            self.paperSize]['logoTransformSize']
        self._log("outputFile: " + str(self.outputFile))
        self._log("reportLabPaperSize: " + str(self.reportLabPaperSize))
        self._title = title
        self._timestamp = timestamp
        if includeSplunkLogo != None:
            self._includeSplunkLogo = includeSplunkLogo
        logger.debug("pdf-init pdfrenderer include-splunk-logo=%s" %
                     self._includeSplunkLogo)

        self._fontManager = FontManager(cidFontList=cidFontList)

        self.TITLE_STYLE.fontSize = 14
        self.TITLE_STYLE.leading = 16
        self.CENTER_STYLE.alignment = reportlab.lib.enums.TA_CENTER

        # TODO: need a better way to determine max cell height
        #       225 ~= margins + footer height + a few lines for header row
        self.maxTableCellHeight = self.reportLabPaperSize[1] - 225
        return

    def conditionalPageBreak(self):
        self._story.append(CondPageBreak(self.MIN_HEIGHT_TABLE_AND_CHART))

    def spaceBetween(self, space=0.5 * inch):
        self._story.append(EnsureSpaceBetween(space))

    def renderText(self, text, style=None, escapeText=True):
        if style is None:
            style = self._style

        if escapeText:
            readyText = su.escape(text)
        else:
            readyText = text

        logger.debug("renderText readyText='%s'" % readyText)
        self._story.append(
            Paragraph(self._fontManager.encodeTextForParagraph(readyText),
                      style))

    def renderBulletText(self, text, bullet='-', style=None):
        if style is None:
            style = self._bulletStyle
        self._story.append(
            Paragraph(self._fontManager.encodeTextForParagraph(
                su.escape(text)),
                      style,
                      bulletText=bullet))

    def renderHtml(self, text):
        if text is None:
            return

        def multiple_replacer(*key_values):
            replace_dict = dict(key_values)
            replacement_function = lambda match: replace_dict[match.group(0)]
            pattern = re.compile(
                "|".join([re.escape(k) for k, v in key_values]), re.M)
            return lambda string: pattern.sub(replacement_function, string)

        def multiple_replace(string, *key_values):
            return multiple_replacer(*key_values)(string)

        # reportlab supports a set of text manipulation tags
        #  transform those HTML tags that aren't supported into reportlab
        #  supported tags
        lineBreakingTagReplacements = (u"<li>", u"<li><br/>"), (
            u"<h1>", u"<h1><font size='24'><br/><br/>"
        ), (u"</h1>", u"</font><br/></h1>"), (
            u"<h2>", u"<h2><font size='20'><br/><br/>"
        ), (u"</h2>", u"</font><br/></h2>"), (
            u"<h3>", u"<h3><font size='18'><br/><br/>"
        ), (u"</h3>", u"</font><br/></h3>"), (
            u"<h4>",
            u"<h4><font size='14'><br/>"), (u"</h4>", u"</font><br/></h4>"), (
                u"<h5>", u"<h5><font size='12'><br/>"
            ), (u"</h5>", u"</font><br/></h5>"), (u"<h6>", u"<h6><br/>"), (
                u"</h6>", u"<br/></h6>"), (u"<h7>", u"<h7><br/>"), (
                    u"</h7>", u"<br/></h7>"), (u"<h8>", u"<h8><br/>"), (
                        u"</h8>", u"<br/></h8>"), (u"<h9>", u"<h9><br/>"), (
                            u"</h9>", u"<br/></h9>"), (
                                u"<h10>",
                                u"<h10><br/>"), (u"</h10>", u"<br/></h10>"), (
                                    u"<br>", u"<br/>"), (u"<p>", u"<p><br/>")

        repText = multiple_replace(text, *lineBreakingTagReplacements)

        # need to remove some elements
        #  any elements that make references to external things -- don't want reportlab to try to resolve links
        #  reportlab doesn't like the title attribute
        removeElements = [
            '(<img[^>]*>)', '(</img>)', '(title="[^"]*")', '(<a[^>]*>)',
            '(</a>)'
        ]

        repText = re.sub('|'.join(removeElements), '', repText)
        logger.debug("renderHtml text='%s' repText='%s'" % (text, repText))

        self.renderText(repText, escapeText=False)

    def renderTextNoFormatting(self, text):
        self._story.append(TableText(text, fontManager=self._fontManager))

    def renderListItem(self, text, sequencerNum=None, style=None):
        if style is None:
            style = self._listTitleStyle
        if sequencerNum != None:
            text = "<seq id=" + str(sequencerNum) + "/>" + text
        self._story.append(
            Paragraph(
                self._fontManager.encodeTextForParagraph(su.escape(text)),
                style))

    def renderTable(self,
                    data,
                    title=None,
                    headerRow=None,
                    columnWidths=[],
                    columnHardWraps=[],
                    columnVAlignments=[],
                    displayLineNumbers=False):
        """ data should be a 2-D list of embedded lists e.g. [[a,b],[c,d],[e,f]]
            if headerRow is specified, then that row will be repeated at the top of each page if the table spans multiple pages,
            columnWidths ([int]) specifies the width of each column, if a column is not specified it will be sized automatically,
            columnHardWraps ([bool]) specifies whether or not to hard wrap a column, if a column is not specified it will be wrapped softly
            columnVAlignments (['TOP','MIDDLE','BOTTOM']) specifies vertical alignment of cells in a column, if not specified will be aligned at BOTTOM
            displayLineNumbers (bool) specifies whether or not to show line numbers
        """

        # handle title and header
        if title != None:
            self.renderText(title, style=self._tableTitleStyle)
        if headerRow != None:
            data.insert(0, headerRow)
            logger.debug("renderTable> headerRow: " + str(headerRow))

        # handle row numbers
        if displayLineNumbers:
            for index, row in enumerate(data):
                if index == 0 and headerRow != None:
                    row.insert(0, "")
                else:
                    rowNumber = index
                    if headerRow == None:
                        rowNumber = rowNumber + 1
                    row.insert(0, str(rowNumber))

        numDataCols = 0

        # iterate over the data in order to wrap each cell in a Paragraph flowable with a style
        numberCells = [
        ]  # an array of tuples identifying cells that are numbers
        cellWidthsByCol = []
        styledData = []
        for rowIdx, row in enumerate(data):
            styledRow = []

            for cellNum, cell in enumerate(row):
                # set the style based on columnHardWraps[cellNum]
                style = self._style
                if len(columnHardWraps) > cellNum:
                    if columnHardWraps[cellNum]:
                        style = self._hardWrapStyle

                cellFlowable = None
                if "##__SPARKLINE__##" in str(cell):
                    # build sparkline and insert into row
                    cellFlowable = Sparkline(str(cell))
                    styledRow.append(cellFlowable)
                else:
                    cellFlowable = TableText(
                        str(cell),
                        fontManager=self._fontManager,
                        maxCellHeight=self.maxTableCellHeight)
                    styledRow.append(cellFlowable)
                    if cellFlowable.isNumeric():
                        numberCells.append((cellNum, rowIdx))

                # build up matrix of cell widths by column
                if rowIdx == 0:
                    cellWidthsByCol.append([])
                cellWidthsByCol[cellNum].append(cellFlowable.width)

            numDataCols = len(styledRow)
            styledData.append(styledRow)

        columnWidths = self.determineColumnWidths(
            cellWidthsByCol,
            tableWidth=self.reportLabPaperSize[0] - self._MARGINS[0] -
            self._MARGINS[2],
            columnPadding=self._TABLE_COL_LEFT_PADDING +
            self._TABLE_COL_RIGHT_PADDING)

        # create the necessary table style commands to handle vertical alignment setting
        tableStyleCommands = []
        if columnVAlignments is not None:
            for i, valign in enumerate(columnVAlignments):
                tableStyleCommands.append(('VALIGN', (i, 0), (i, -1), valign))

        for numberCell in numberCells:
            tableStyleCommands.append(
                ('ALIGN', numberCell, numberCell, 'RIGHT'))

        # line to the right of all columns
        tableStyleCommands.append(
            ('LINEAFTER', (0, 0), (-2, -1), 0.25, colors.lightgrey))

        firstDataRow = 0
        if headerRow != None:
            tableStyleCommands.append(
                ('LINEBELOW', (0, 0), (-1, 0), 1, colors.black))
            firstDataRow = 1

        # lines to the bottom and to the right of each cell
        tableStyleCommands.append(
            ('LINEBELOW', (0, firstDataRow), (-1, -2), 0.25, colors.lightgrey))

        # tighten up the columns
        tableStyleCommands.append(
            ('LEFTPADDING', (0, 0), (-1, -1), self._TABLE_COL_LEFT_PADDING))
        tableStyleCommands.append(
            ('RIGHTPADDING', (0, 0), (-1, -1), self._TABLE_COL_RIGHT_PADDING))

        # create the Table flowable and insert into story
        table = Table(styledData,
                      repeatRows=(headerRow != None),
                      colWidths=columnWidths)
        table.setStyle(TableStyle(tableStyleCommands))
        self._story.append(table)

    def determineColumnWidths(self, cellWidthsByCol, tableWidth,
                              columnPadding):
        columnSizer = ColumnSizer(cellWidthsByCol, tableWidth, columnPadding)
        return columnSizer.getWidths()

    def renderSvgString(self, svgString, title=None):
        svgImageFlowable = pdfgen_svg.getSvgImageFromString(
            svgString, self._fontManager)
        if svgImageFlowable is None:
            self._log("renderSvg> svgImageFlowable for " + svgString +
                      " is invalid")
        else:
            if title != None:
                self.renderText(title, style=self._tableTitleStyle)
            self._story.append(svgImageFlowable)

    def save(self):
        #        self._log("starting save", logLevel='info')
        doc = PDFGenDocTemplate(self.outputFile,
                                pagesize=self.reportLabPaperSize)
        doc.setTitle(self._title)
        doc.splunkPaperSize = self.paperSize
        doc.setTimestamp(self._timestamp)
        doc.setFontManager(self._fontManager)
        if self._includeSplunkLogo:
            doc.setLogoSvgString(
                _splunkLogoSvg.replace("***logoTransformSize***",
                                       str(self.logoTransformSize)))
        self._log("Doc pageSize: " + str(getattr(doc, "pagesize")))

        for flowable in self._story:
            flowable.hAlign = 'CENTER'
#        self._log("before doc.build", logLevel='info')
        doc.build(self._story, onFirstPage=_footer, onLaterPages=_footer)
#        self._log("after doc.build", logLevel='info')
#        if len(wrapTimes) > 1:
#            self._log("wrap time stats; min=%s, max=%s, agg=%s, avg=%s, num=%s" % _getStats(wrapTimes), logLevel='info')
#        if len(stringWidthTimes) > 1:
#            self._log("width time stats; min=%s, max=%s, agg=%s, avg=%s, num=%s" % _getStats(stringWidthTimes), logLevel='info')
#        self._log("font manager cache length=%s" % len(self._fontManager._textWidthCache), logLevel='info')
#        if len(drawTimes) > 1:
#            self._log("draw time stats; min=%s, max=%s, agg=%s, avg=%s, num=%s" % _getStats(drawTimes), logLevel='info')

    def _log(self, msg, logLevel='debug'):
        if self._runningAsScript:
            print logLevel + " : " + msg
            return

        if logLevel == 'debug':
            logger.debug(msg)
        elif logLevel == 'info':
            logger.info(msg)
        elif logLevel == 'warning':
            logger.warning(msg)
        elif logLevel == 'error':
            logger.error(msg)
def main() -> None:
    mode = input('MODE (L, R, C): ')

    # Initialize a fullscreen window
    pygame.init()
    screen = pygame.display.set_mode((0, 0), pygame.FULLSCREEN)

    # Window title
    pygame.display.set_caption('ESW Digital Waste Bins')

    # Make a display
    # TODO: add more modules to the display
    # TODO: store in subclass? for each bin
    # Landfill
    if mode == 'L':
        title_fm = FontManager(['impact'])
        text = title_fm.create_text('LANDFILL', 100, color=WHITE)
        title = TitleFrame(text=text, bg=BLACK, pady=100)
        content = Content(display_bg_color=WHITE)
        Display(title, content).draw(screen)
    # Compost
    elif mode == 'C':
        title_fm = FontManager(['impact'])
        text = title_fm.create_text('COMPOST', 100, color=WHITE)
        title = TitleFrame(text=text, bg=GREEN, pady=100)
        content = Content(display_bg_color=WHITE)
        Display(title, content).draw(screen)
    # Recycle
    elif mode == 'R':
        title_fm = FontManager(['impact'])
        text = title_fm.create_text('RECYCLE', 100, color=WHITE)
        title = TitleFrame(text=text, bg=BLUE, pady=100)
        content = Content(display_bg_color=WHITE)
        Display(title, content).draw(screen)
    else:
        print('Not a valid option.')
        return None

    # Game loop
    clock = pygame.time.Clock()
    running = True
    prev_reading = scaleReading()  # initial scale reading

    while running:
        # Handle events
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
                break
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    running = False
                    break
        curr_reading = scaleReading()
        weight_diff = curr_reading-prev_reading
        # check if the reading has changed compared to last time
        if weight_diff > MIN_WEIGHT_DIFF and motionReading():
            # start telling the thrower how much he she saved etc
            prev_reading = curr_reading
        elif weight_diff < MIN_WEIGHT_DIFF and motionReading():
            # thank the thrower but don't display the weight
            prev_reading = curr_reading
        else:
            prev_reading = curr_reading

        # Next frame (20 fps)
        clock.tick(20)

        # Repaint screen
        pygame.display.flip()
    # Exit
    pygame.quit()
Exemple #5
0
    def _get_chart_settings(self):
        """ getting data for layout"""
        self._db.Query("""SELECT
                                dashboard_element.metric_show_max_ever_on_chart_ind,
                                dashboard_element.metric_show_min_ever_on_chart_ind,
                                dashboard_element.name,
                                dashboard_element.metric_display_label,

                                chart_display_format.chart_object_size_x,
                                chart_display_format.chart_object_size_y,
                                chart_display_format.plot_area_x_coord,
                                chart_display_format.plot_area_y_coord,
                                chart_display_format.plot_area_width,
                                chart_display_format.plot_area_height,
                                chart_display_format.title_font_id,
                                chart_display_format.title_font_size,
                                chart_display_format.legend_x_coord,
                                chart_display_format.legend_y_coord,
                                chart_display_format.max_bar_data_points_to_chart,
                                chart_display_format.max_line_data_points_to_chart,
                                chart_display_format.max_x_axis_labels,
                                chart_display_format.include_title_ind,

                                chart_layout.bar_positive_value_color,
                                chart_layout.bar_negative_value_color,

                                chart_layout.background_color,
                                chart_layout.bar_shape,
                                chart_layout.bar_soft_lighting_direction,
                                chart_layout.border_color,
                                chart_layout.current_value_dot_color,
                                chart_layout.current_value_dot_size,
                                chart_layout.current_value_font_id,
                                chart_layout.current_value_font_size,
                                chart_layout.data_gap_line_type,
                                chart_layout.highlight_current_value_ind,
                                chart_layout.include_legend_ind,
                                chart_layout.include_x_axis_label_ind,
                                chart_layout.include_y_axis_label_ind,
                                chart_layout.legend_background_color,
                                chart_layout.legend_font_id,
                                chart_layout.legend_font_size,
                                chart_layout.line_data_point_dot_size,
                                chart_layout.line_width,
                                chart_layout.metric_bar_color,
                                chart_layout.metric_line_color,
                                
                                chart_layout.bar_gap,
                                chart_layout.bar_group_gap,
                                chart_layout.show_expired_zone_ind,
                                chart_layout.expired_zone_color,
                                
                                chart_layout.min_max_ever_font_id,
                                chart_layout.min_max_ever_font_size,
                                chart_layout.min_max_ever_line_color,
                                chart_layout.min_max_ever_line_type,
                                chart_layout.min_max_ever_line_width,

                                chart_layout.month_display_format,
                                chart_layout.plot_area_background_color,
                                chart_layout.plot_area_background_color_ind,
                                chart_layout.plot_area_horizontal_grid_color,
                                chart_layout.plot_area_vertical_grid_color,
                                chart_layout.show_line_data_points_ind,
                                chart_layout.show_plot_area_grid_ind,
                                chart_layout.title_font_color,
                                chart_layout.x_axis_label_font_color,
                                chart_layout.x_axis_label_font_id,
                                chart_layout.x_axis_label_font_size,
                                chart_layout.x_axis_tick_mark_position,
                                chart_layout.y_axis_font_color,
                                chart_layout.y_axis_font_id,
                                chart_layout.y_axis_font_size,
                                chart_layout.data_gap_line_type,

                                chart_layout.metric_moving_average_line_color,
                                chart_layout.moving_average_line_width,

                                chart_display_format.include_title_ind,
                                
                                chart_layout.metric_stoplight_good_range_start_color,
                                chart_layout.metric_stoplight_good_range_end_color,
                                chart_layout.metric_stoplight_bad_range_start_color,
                                chart_layout.metric_stoplight_bad_range_end_color,
                                
                                chart_layout.metric_stoplight_good_mark_color,
                                chart_layout.metric_stoplight_bad_mark_color,

                                dashboard_element.type,
                                dashboard_element.max_time_before_expired_sec,
                                dashboard_element.metric_start_y_axis_from_zero_ind AS start_y_axis_from_zero_ind,
                                dashboard_element.multi_chart_primary_axis_start_from_zero_ind AS primary_axis_start_from_zero_ind,
                                dashboard_element.multi_chart_secondary_axis_start_from_zero_ind AS secondary_axis_start_from_zero_ind,
                                chart_layout_id
                            FROM dashboard_element
                                LEFT JOIN chart_layout
                            ON chart_layout.layout_id = dashboard_element.chart_layout_id
                            LEFT JOIN chart_display_format
                            ON chart_display_format.chart_display_format_id = chart_layout.chart_display_format_id
                            WHERE element_id=%s
                        """, (self.metric_id, ))
        data = self._db.record[0]
        
        if data['type'] == 'metric':
            self.metric_type = 'single'
            data['primary_axis_start_from_zero_ind'] = data['start_y_axis_from_zero_ind']
            data['secondary_axis_start_from_zero_ind'] = data['start_y_axis_from_zero_ind']

        #special settings for preview and thumbnail
        data['include_min_max_ever_ind'] = 'Y'
        data['include_compare_ind'] = 'Y'
        data['include_average_ind'] = 'Y'
        data['include_annotations_ind'] = 'Y'
        if self.type == 'large':
            self._db.Query("""    SELECT *
                                    FROM chart_display_format
                                    WHERE preview_display_format_ind = 'Y'""")
            chart_display_format = self._db.record[0]
            data['preview'] = chart_display_format
        else:
            data['preview'] = None
            data['include_min_max_ever_ind'] = 'N'
            data['include_compare_ind'] = 'N'
            data['include_average_ind'] = 'N'
            data['include_annotations_ind'] = 'N'
            if self.type == 'thumbnail':
                data['show_plot_area_grid_ind'] = 'N'
                data['show_line_data_points_ind'] = 'N'
                data['include_title_ind'] = 'N'
                data['include_legend_ind'] = 'N'
                data['include_x_axis_label_ind'] = 'N'
                data['include_y_axis_label_ind'] = 'N'
                if self.metric_type == 'single':
                    self._db.Query("""SELECT *
                                        FROM chart_display_format
                                        WHERE metric_thumbnail_display_format_ind = 'Y'""")
                else:
                    self._db.Query("""SELECT *
                                        FROM chart_display_format
                                        WHERE multi_metric_thumbnail_display_format_ind = 'Y'""")
                    
            elif self.type == 'preview':
                self._db.Query("""    SELECT *
                                    FROM chart_display_format
                                    WHERE preview_display_format_ind = 'Y'""")
            chart_display_format = self._db.record[0]
            for k, v in chart_display_format.iteritems():
                data[k] = v

        if data['bar_gap'] is None:
            data['bar_gap'] = 0.0
        if data['bar_group_gap'] is None:
            data['bar_group_gap'] = 0.0

        #if not data.has_key('chart_layout_id') or not data['chart_layout_id']:
        if 'chart_layout_id' not in data or not data['chart_layout_id']:
            raise Exception("missing chart_layout_id")

        if data['include_legend_ind'] == 'Y':
            self._db.Query("""SELECT * FROM font
                                WHERE font_id=%s""", (data['legend_font_id']))
            data['legend_font'] = self._db.record[0]

        if data['include_x_axis_label_ind'] == 'Y':
            # getting font for x axis label
            self._db.Query("""SELECT * FROM font
                                WHERE font_id=%s""", (data['x_axis_label_font_id']))
            data['x_axis_label_font'] = self._db.record[0]

        # getting font for y axis label
        if data['include_y_axis_label_ind'] == 'Y':
            self._db.Query("""SELECT * FROM font
                                WHERE font_id=%s""", (data['y_axis_font_id']))
            data['y_axis_label_font'] = self._db.record[0]

        # getting font for values
        self._db.Query("""SELECT * FROM font
                            WHERE font_id=%s""", (data['current_value_font_id']))
        data['current_value_font'] = self._db.record[0]

        # getting font for title
        if data['include_title_ind'] == 'Y':
            self._db.Query("""SELECT * FROM font
                                WHERE font_id=%s""", (data['title_font_id']))
            data['title_font'] = self._db.record[0]
            if data['title_font_color']:
                data['title_font_color'] = FontManager.get_db_color(data['title_font_color'])
            else:
                data['title_font_color'] = 0xffffff

        if data['bar_positive_value_color']:
            data['bar_positive_value_color'] = FontManager.get_db_color(data['bar_positive_value_color'])
        else:
            data['bar_positive_value_color'] = None

        if data['bar_negative_value_color']:
            data['bar_negative_value_color'] = FontManager.get_db_color(data['bar_negative_value_color'])
        else:
            data['bar_negative_value_color'] = None
        

        # getting styles for min max ever lines
        if data['include_min_max_ever_ind'] == 'Y':
            self._db.Query("""SELECT * FROM font
                                WHERE font_id=%s""", (data['min_max_ever_font_id']))
        
            data['min_max_ever_font'] = self._db.record[0]

        # emulate charting settings for compatibility with report charts
        data['flip_x_and_y_axis'] = 'N'
        data['use_stacked_bars_ind'] = 'N'


        return data
Exemple #6
0
    def get_modified_data(self, data):
        # expired zone settings
        data['expired_zone'] = {}
        
        if data['expired_date'] and data['orig_header']:
            data['expired_zone']['start'] = data['expired_date']
            data['expired_zone']['end'] = data['orig_header'][-1]
            data['expired_zone']['color'] = FontManager.get_db_color(self.settings['expired_zone_color'])

        if self.metric_type == 'single':
            # get line point shape. for single metrics it's circle
            self._db.Query("""SELECT * FROM chart_data_point_shape WHERE chartdirector_shape_id = 'CircleShape'""")
            line_point_shapes = cycle([shape for shape in self._db.record])
        else:
            # get line point shapes for multi-metrics
            self._db.Query("""SELECT * FROM chart_data_point_shape ORDER BY charting_order""")
            line_point_shapes = cycle([shape for shape in self._db.record])

        for metric_uid in data['rows']:
            if not self.chart_display_mode:
                self.chart_display_mode = data['rows'][metric_uid]['data_settings']['display_type']
            elif self.chart_display_mode != data['rows'][metric_uid]['data_settings']['display_type']:
                self.chart_display_mode = 'both'

            # set line point shape
            data['rows'][metric_uid]['data_settings']['line_point_shape'] = None
            if data['rows'][metric_uid]['data_settings']['display_type'] == 'line':
                if data['rows'][metric_uid]['data_settings']['shape_id']:
                    res = self._db.Query("""SELECT * FROM chart_data_point_shape WHERE chart_data_point_shape_id = %s""", (data['rows'][metric_uid]['data_settings']['shape_id']))
                    if res:
                        data['rows'][metric_uid]['data_settings']['line_point_shape'] = self._db.record[0]

                if not data['rows'][metric_uid]['data_settings']['line_point_shape']:
                    data['rows'][metric_uid]['data_settings']['line_point_shape'] = line_point_shapes.next()

            if data['rows'][metric_uid]['average_settings']:
                if self.settings['include_average_ind'] == 'N':
                    del(data['rows'][metric_uid]['average_settings'])

            if data['compare_lines']:
                for compare_line in data['compare_lines']:
                    compare_setting = 'compare_settings_%s' % compare_line
                    if (self.settings['include_compare_ind'] == 'N' and
                            not (self.type == 'preview'
                                and data['rows'][metric_uid][compare_setting]['highlight_interval_ind'] == 'Y')):
                        del(data['rows'][metric_uid][compare_setting])
                    else:
                        data['rows'][metric_uid][compare_setting]['axis_number'] = 1
                        data['rows'][metric_uid][compare_setting]['display_type'] = 'line'
                        data['rows'][metric_uid][compare_setting]['color'] = FontManager.get_db_color(data['rows'][metric_uid][compare_setting]['line_color'])
                        data['rows'][metric_uid][compare_setting]['line_style'] = data['rows'][metric_uid]['data_settings']['line_style']
                if self.settings['include_compare_ind'] == 'N':
                    del(data['compare_lines'])

            if data['rows'][metric_uid]['min_ever_settings']:
                if self.settings['include_min_max_ever_ind'] == 'N':
                    del(data['rows'][metric_uid]['min_ever_settings'])
                else:
                    data['rows'][metric_uid]['min_ever_settings']['axis_number'] = 1
                    data['rows'][metric_uid]['min_ever_settings']['display_type'] = 'line'
                    data['rows'][metric_uid]['min_ever_settings']['line_type'] = 'solid'
                    data['rows'][metric_uid]['min_ever_settings']['color'] = FontManager.get_db_color(self.settings['min_max_ever_line_color'])
                    data['rows'][metric_uid]['min_ever_settings']['line_width'] = self.settings['min_max_ever_line_width']
                    data['rows'][metric_uid]['min_ever_settings']['line_style'] = 'jagged'

            if data['rows'][metric_uid]['max_ever_settings']:
                if self.settings['include_min_max_ever_ind'] == 'N':
                    del(data['rows'][metric_uid]['max_ever_settings'])
                else:
                    data['rows'][metric_uid]['max_ever_settings']['axis_number'] = 1
                    data['rows'][metric_uid]['max_ever_settings']['display_type'] = 'line'
                    data['rows'][metric_uid]['max_ever_settings']['line_type'] = 'solid'
                    data['rows'][metric_uid]['max_ever_settings']['color'] = FontManager.get_db_color(self.settings['min_max_ever_line_color'])
                    data['rows'][metric_uid]['max_ever_settings']['line_width'] = self.settings['min_max_ever_line_width']
                    data['rows'][metric_uid]['max_ever_settings']['line_style'] = 'jagged'

        if self.metric_type == 'single' and self.chart_display_mode == 'bar' and data['metric_change_bar_color_on_value_ind'] == 'Y':
            self.settings['is_pos_neg_colored_bars'] = True
        else:
            self.settings['is_pos_neg_colored_bars'] = False

        #thinning data according to maximum data points number
        max_data_len = self.settings['max_line_data_points_to_chart']
        if self.chart_display_mode == 'line':
            max_data_len = self.settings['max_line_data_points_to_chart']
        elif self.chart_display_mode == 'bar':
            max_data_len = self.settings['max_bar_data_points_to_chart']
        elif self.chart_display_mode == 'both':
            max_data_len = min(self.settings['max_line_data_points_to_chart'], self.settings['max_bar_data_points_to_chart'])
        self.settings['is_reduced'] = False

        thinned_data = copy.deepcopy(data)

        if self.chart_display_mode == 'bar' or self.chart_display_mode == 'both':
            thinned_data = self.get_thinned_data_bar(thinned_data, max_data_len, data['thin_by_metric_uid'])
        else:
            thinned_data = self.get_thinned_data(thinned_data, max_data_len, data['thin_by_metric_uid'])

        return thinned_data
    def create_chart(self):
        """
        Main function for creating chart
        """
        self._create_plot_area()

        if not self.inited:
            self._prepare_x_scale_values()
        self._set_x_axis_props()
        self._set_y_axis_props()

        self._set_x_axis_date_scale()

        self._set_y_axes_formats()

        self._create_layers()

        # GOOD area start color
        if self.settings['show_stop_light']:
            # GOOD whisker mark color
            if self.layout_data['metric_stoplight_good_mark_color'] is None:
                self.layout_data['metric_stoplight_good_mark_color'] = 0x00ff00
            else:
                self.layout_data['metric_stoplight_good_mark_color'] = FontManager.get_db_color(self.layout_data['metric_stoplight_good_mark_color'])

            # BAD whisker mark color
            if self.layout_data['metric_stoplight_bad_mark_color'] is None:
                self.layout_data['metric_stoplight_bad_mark_color'] = 0xff0000
            else:
                self.layout_data['metric_stoplight_bad_mark_color'] = FontManager.get_db_color(self.layout_data['metric_stoplight_bad_mark_color'])

            # GOOD area start color
            if self.layout_data['metric_stoplight_good_range_start_color'] is None:
                self.layout_data['metric_stoplight_good_range_start_color'] = 0xa0defacc
            else:
                self.layout_data['metric_stoplight_good_range_start_color'] = FontManager.get_db_color(self.layout_data['metric_stoplight_good_range_start_color'])

            # GOOD area end color
            if self.layout_data['metric_stoplight_good_range_end_color'] is None:
                self.layout_data['metric_stoplight_good_range_end_color'] = 0xa000ff00
            else:
                self.layout_data['metric_stoplight_good_range_end_color'] = FontManager.get_db_color(self.layout_data['metric_stoplight_good_range_end_color'])

            # BAD area start color
            if self.layout_data['metric_stoplight_bad_range_start_color'] is None:
                self.layout_data['metric_stoplight_bad_range_start_color'] = 0xa0f0c9c9
            else:
                self.layout_data['metric_stoplight_bad_range_start_color'] = FontManager.get_db_color(self.layout_data['metric_stoplight_bad_range_start_color'])

            # BAD area end color
            if self.layout_data['metric_stoplight_bad_range_end_color'] is None:
                self.layout_data['metric_stoplight_bad_range_end_color'] = 0xa0ff0000
            else:
                self.layout_data['metric_stoplight_bad_range_end_color'] = FontManager.get_db_color(self.layout_data['metric_stoplight_bad_range_end_color'])

        compare_lines = []
        if 'compare_lines' in self.chart_data and self.chart_data['compare_lines']:
            for compare_line in self.chart_data['compare_lines']:
                compare_lines.append('compare_settings_%s' % compare_line)

        bar_ind = -1

        # iterate metrics. uid: metric uid, _v: metric data
        for uid, metric_elements in self.chart_data['rows'].iteritems():
            # iterate metric elements
            for element_type, element_data in metric_elements.iteritems():
                if element_data is not None:
                    shape = None
                    if element_type == 'max_ever_settings' or element_type == 'min_ever_settings':
                        element_data['line_type'] = self.layout_data['min_max_ever_line_type']
                        element_data['display_type'] = 'line'
                        element_data['color'] = FontManager.get_db_color(self.layout_data['min_max_ever_line_color'])

                    if 'axis_number' in element_data and element_data['axis_number'] == '2':
                        axis = self.c.yAxis2()
                        axis_index = 1
                    else:
                        axis_index = 0
                        axis = self.c.yAxis()

                    # set color and line type dash/dot/solid
                    if 'line_type' not in element_data:
                        element_data['line_type'] = ''
                    color = self._get_element_color(element_data['display_type'], element_data['line_type'], element_data['color'])

                    if element_type == 'max_ever_settings' or element_type == 'min_ever_settings':
                        # draw max/min ever mark
                        element_data['line_type'] = self.layout_data['min_max_ever_line_type']
                        element_data['display_type'] = 'line'
                        element_data['color'] = FontManager.get_db_color(self.layout_data['min_max_ever_line_color'])
                        mark = axis.addMark(
                                            element_data['data'][0],
                                            element_data['color'],
                                            element_data['label'],
                                            FontManager.get_db_font(self.layout_data['min_max_ever_font']),
                                            self.layout_data['min_max_ever_font_size'])
                        mark.setLineWidth(self.layout_data['min_max_ever_line_width'])
                        mark.setAlignment(TopLeft)
                        mark.setDrawOnTop(False)
                    elif element_type == 'stop_light':
                        # draw invisible stop light lines to make this areas visible (included in charting view)
                        if self.chart_data['show_stop_light'] and self.settings['type'] == 'large':
                            self.datasets[self.layers_count] = {}
                            self.datasets[self.layers_count][0] = {'uid': uid, 'metric_data': element_type, 'type': 'good_stop_light', 'shape': ''}
                            self.datasets[self.layers_count][1] = {'uid': uid, 'metric_data': element_type, 'type': 'good_stop_light', 'shape': ''}
                            self.dataset_ids[self.layers_count] = 1
                            self.layers_count += 1

                            stop_light_area_line = self.c.addSplineLayer()
                            stop_light_area_line.setXData(self._x_axis_data)
                            stop_light_area_line.setUseYAxis(axis)
                            stop_light_area_line.addDataSet(element_data['bad'], Transparent)
                            stop_light_area_line.addDataSet(element_data['good'], Transparent)

                            stop_light_type = 'line'

                            # if chart is bar type and show stop light is True
                            if self.chart_data['rows'][uid]['data_settings']['display_type'] == 'bar' and self.settings['show_stop_light']:
                                stop_light_type = 'bar'

                                bad_stop_light_box = self.c.addBoxWhiskerLayer(
                                        None,
                                        None,
                                        None,
                                        None,
                                        element_data['bad'],
                                        -1,
                                        self.layout_data['metric_stoplight_bad_mark_color'])

                                bad_stop_light_box.setLineWidth(2)
                                bad_stop_light_box.setXData(self._x_axis_data)
                                bad_stop_light_box.setUseYAxis(axis)
                                bad_stop_light_box.moveFront()

                                good_stop_light_box = self.c.addBoxWhiskerLayer(
                                        None,
                                        None,
                                        None,
                                        None,
                                        element_data['good'],
                                        -1,
                                        self.layout_data['metric_stoplight_good_mark_color'])
                                good_stop_light_box.setLineWidth(2)
                                good_stop_light_box.setXData(self._x_axis_data)
                                good_stop_light_box.setUseYAxis(axis)
                                good_stop_light_box.moveFront()

                                self.datasets[self.layers_count] = {}
                                self.datasets[self.layers_count][0] = {'uid': uid, 'metric_data': element_type, 'type': 'good_stop_light', 'shape': ''}
                                self.dataset_ids[self.layers_count] = 0
                                self.layers_count += 1

                                self.datasets[self.layers_count] = {}
                                self.datasets[self.layers_count][0] = {'uid': uid, 'metric_data': element_type, 'type': 'good_stop_light', 'shape': ''}
                                self.dataset_ids[self.layers_count] = 0
                                self.layers_count += 1

                            # add title to legend box
                            if self.layout_data['include_legend_ind'] == 'Y' and self.settings['show_stop_light']:
                                if stop_light_type == 'bar':
                                    good_color = self.layout_data['metric_stoplight_good_mark_color']
                                    bad_color = self.layout_data['metric_stoplight_bad_mark_color']

                                    # add GOOD/BAD title to legend box
                                    l_legend = self.legend_layer.addDataSet([], bad_color, u"Bad Level")
                                    l_legend.setDataLabelStyle(self.legend_font, self.legend_font_size, Transparent)
                                    l_legend.setLineWidth(2)
                                    #l_legend.setDataSymbol4(self._cSquareSymbol, 15, bad_color, -1)
                                    l_legend.setDataSymbol(CircleShape, 1, bad_color, bad_color)

                                    l_legend = self.legend_layer.addDataSet([], good_color, u"Good Level")
                                    l_legend.setLineWidth(2)
                                    #l_legend.setDataSymbol4(self._cSquareSymbol, 15, good_color, -1)
                                    l_legend.setDataSymbol(CircleShape, 1, good_color, good_color)
                                else:
                                    good_color = self.layout_data['metric_stoplight_good_range_end_color']
                                    bad_color = self.layout_data['metric_stoplight_bad_range_end_color']

                                    # add GOOD/BAD title to legend box
                                    l_legend = self.legend_layer.addDataSet([], bad_color, u"Bad Area")
                                    l_legend.setDataLabelStyle(self.legend_font, self.legend_font_size, Transparent)
                                    l_legend.setLineWidth(0)
                                    l_legend.setDataSymbol4(self._cSquareSymbol, 15, bad_color, -1)

                                    l_legend = self.legend_layer.addDataSet([], good_color, u"Good Area")
                                    l_legend.setLineWidth(0)
                                    l_legend.setDataSymbol4(self._cSquareSymbol, 15, good_color, -1)
                    else:
                        # draw bar/line chart
                        std_deviation_color = None

                        # hide compare lines for deviation/stoplight chart
                        if element_type in compare_lines and (self.settings['show_std_deviation'] or self.settings['show_stop_light']):
                            color = Transparent
                        # chart average line
                        if element_type == 'average_settings':
                            # hide average line if it should be shown on main chart
                            if not element_data['show_moving_average'] and not self.settings['show_std_deviation']:
                                color = Transparent

                            # chart standard deviation area
                            if element_data['show_std_deviation']:
                                # hide deviation lines for main chart
                                if not self.settings['show_std_deviation']:
                                    # make it absolute transparent
                                    std_deviation_color = Transparent
                                else:
                                    # make it half transparent
                                    std_deviation_color = color + 0xa0000000

                                min_deviation = []
                                max_deviation = []

                                for i, avg in enumerate(element_data['data']):
                                    if avg == NoValue or element_data['std_deviation_data'][i] is None:
                                        min_deviation.append(NoValue)
                                        max_deviation.append(NoValue)
                                    else:
                                        min_deviation.append(avg - element_data['metric_unusual_value_std_dev'] * element_data['std_deviation_data'][i])
                                        max_deviation.append(avg + element_data['metric_unusual_value_std_dev'] * element_data['std_deviation_data'][i])

                                top_line = self.c.addLineLayer(max_deviation, Transparent)
                                top_line.setUseYAxis(axis)
                                top_line.setXData(self._x_axis_data)

                                bottom_line = self.c.addLineLayer(min_deviation, Transparent)
                                bottom_line.setUseYAxis(axis)
                                bottom_line.setXData(self._x_axis_data)

                                inter_layer = self.c.addInterLineLayer(top_line.getLine(), bottom_line.getLine(), std_deviation_color)
                                inter_layer.setUseYAxis(axis)

                                self.datasets[self.layers_count] = {}
                                self.datasets[self.layers_count][0] = {'uid': uid, 'metric_data': element_type, 'type': 'std_deviation_top_line', 'shape': ''}
                                self.dataset_ids[self.layers_count] = 0
                                self.layers_count += 1

                                self.datasets[self.layers_count] = {}
                                self.datasets[self.layers_count][0] = {'uid': uid, 'metric_data': element_type, 'type': 'std_deviation_bottom_line', 'shape': ''}
                                self.dataset_ids[self.layers_count] = 0
                                self.layers_count += 1

                                self.datasets[self.layers_count] = {}
                                self.datasets[self.layers_count][0] = {'uid': uid, 'metric_data': element_type, 'type': 'std_deviation_inter_line_area', 'shape': ''}
                                self.dataset_ids[self.layers_count] = 0
                                self.layers_count += 1

                        if element_data['display_type'] == 'line':
                            # line chart
                            line_description = {'uid': uid, 'metric_data': element_type, 'type': 'line_data', 'shape': 'point'}
                            line_point_description = {'uid': uid, 'metric_data': element_type, 'type': 'data', 'shape': 'point'}
                            if element_type == 'data_settings' and self.layout_data['show_line_data_points_ind'] == 'Y':
                                show_data_points = True
                                shape = self._set_shape(self.chart_data['rows'][uid]['data_settings']['line_point_shape'])
                            else:
                                show_data_points = False
                                shape = None

                            if 'line_width' in element_data:
                                line_width = element_data['line_width']
                            else:
                                line_width = None
                            if self.chart_data['split_xtd_periods']:
                                self._create_line_layer_xtd(element_data['data'], element_data['line_style'], line_width, color, axis, show_data_points, shape, line_description, line_point_description)
                            else:
                                self._create_line_layer(element_data['data'], element_data['line_style'], line_width, color, axis, show_data_points, shape, line_description, line_point_description)

                        else:
                            bar_ind += 1
                            # bar chart
                            self._create_bar_layer(element_data['data'], color, axis, axis_index, bar_ind, True, {'uid': uid, 'metric_data': element_type, 'type': 'data', 'shape': 'bar'})

                        # add layer for annotation markers
                        if element_type == 'data_settings' and self.layout_data['include_annotations_ind'] == 'Y':
                            # process range annotations
                            if not self.inited:
                                # calculate range annotations only if they are not calculated before
                                # this is needed only for charting deviation/stoplight metrics
                                self._collect_range_annotations(
                                        self.chart_data['range_annotations'][uid],
                                        axis_index,
                                        {'uid': uid, 'element_type': element_type})

                            # draw point annotations
                            self._draw_point_annotations(
                                    self.chart_data['point_annotations'][uid],
                                    element_data['data'],
                                    axis,
                                    axis_index,
                                    element_data['display_type'],
                                    bar_ind,
                                    True,
                                    {'uid': uid, 'metric_data': element_type, 'type': 'annotation'})

                        # add element name to legend box
                        if self.layout_data['include_legend_ind'] == 'Y':
                            axis = self.c.yAxis()
                            # do not show legend if compare lines are hidden
                            if element_type in compare_lines and (self.settings['show_std_deviation'] or self.settings['show_stop_light']):
                                continue

                            if element_type == 'average_settings':
                                if not element_data['show_moving_average'] and not self.settings['show_std_deviation']:
                                    continue

                            l_legend = self.legend_layer.addDataSet([], color, element_data['label'])

                            if element_data['display_type'] == 'line':
                                l_legend.setDataSymbol(CircleShape, element_data['line_width'], color, color)

                            l_legend.setUseYAxis(axis)

                            if element_type == 'data_settings':
                                if element_data['display_type'] == 'line':
                                    #if element_data.has_key('line_width'):
                                    if 'line_width' in element_data:
                                        l_legend.setLineWidth(element_data['line_width'])

                                    if self.layout_data['show_line_data_points_ind'] == 'Y':
                                        l_legend.setDataSymbol(shape, self.layout_data['line_data_point_dot_size'], color, color)
                                    else:
                                        l_legend.setDataSymbol(CircleShape, element_data['line_width'], color, color)
                                elif element_data['display_type'] == 'bar':
                                    l_legend.setLineWidth(0)
                                    l_legend.setDataSymbol4(self._cSquareSymbol, 15, color, -1)

                            if element_type == 'average_settings' and self.settings['show_std_deviation'] and element_data['show_std_deviation']:
                                l_legend = self.legend_layer.addDataSet([], color, element_data['std_deviation_label'])
                                l_legend.setLineWidth(0)
                                l_legend.setDataSymbol4(self._cSquareSymbol, 15, std_deviation_color, -1)

        # show expired zone
        if self.chart_data['expired_zone']:
            self.c.xAxis().addZone(chartTime2(float(self.chart_data['expired_zone']['start'].strftime("%s"))), chartTime2(float(self.chart_data['expired_zone']['end'].strftime("%s"))), self.chart_data['expired_zone']['color'])

        if self.layout_data['include_annotations_ind'] == 'Y':
            if self._range_annotations:
                if not self.inited:
                    self._calc_annotations()
                self.draw_range_annotations()

        if not self.inited:
            self.inited = True

        # final scale y axis
        self._set_y_axes_scaling()

        # ensure that plots fit within specified layout dimensions
        self._pack_plot_area()

        # show real stop light ares for line chart
        if self.settings['show_stop_light']:
            #freeze chart
            self.c.layoutAxes()
            #get max value of y-axis
            max_y_val1 = self.c.yAxis().getMaxValue()
            max_y_val2 = self.c.yAxis2().getMaxValue()

            min_y_val1 = self.c.yAxis().getMinValue()
            min_y_val2 = self.c.yAxis2().getMinValue()

            for uid, _v in self.chart_data['rows'].iteritems():
                for element_type, element_data in _v.iteritems():
                    if element_type == 'stop_light':
                        #if element_data.has_key('axis_number') and element_data['axis_number'] == '2':
                        if 'axis_number' in element_data and element_data['axis_number'] == '2':
                            axis = self.c.yAxis2()
                            max_y_val = max_y_val2
                            min_y_val = min_y_val2
                        else:
                            axis = self.c.yAxis()
                            max_y_val = max_y_val1
                            min_y_val = min_y_val1

                        # for line metric draw GOOD/BAD areas
                        if self.chart_data['rows'][uid]['data_settings']['display_type'] == 'line':
                            not_empty_bad = [val for val in element_data['bad'] if val != NoValue]
                            not_empty_good = [val for val in element_data['good'] if val != NoValue]

                            if element_data['metric_more_is_better_ind'] == 'Y':
                                top_area = element_data['good']
                                bottom_area = element_data['bad']

                                top_start_color = self.layout_data['metric_stoplight_good_range_start_color']
                                top_end_color = self.layout_data['metric_stoplight_good_range_end_color']

                                bottom_start_color = self.layout_data['metric_stoplight_bad_range_start_color']
                                bottom_end_color = self.layout_data['metric_stoplight_bad_range_end_color']

                                if not_empty_bad:
                                    bottom_largest = max([val for val in element_data['bad'] if val != NoValue])
                                else:
                                    bottom_largest = min_y_val

                                if not_empty_good:
                                    top_smallest = min([val for val in element_data['good'] if val != NoValue])
                                else:
                                    top_smallest = max_y_val
                            else:
                                top_area = element_data['bad']
                                bottom_area = element_data['good']

                                top_start_color = self.layout_data['metric_stoplight_bad_range_start_color']
                                top_end_color = self.layout_data['metric_stoplight_bad_range_end_color']

                                bottom_start_color = self.layout_data['metric_stoplight_good_range_start_color']
                                bottom_end_color = self.layout_data['metric_stoplight_good_range_end_color']

                                if not_empty_good:
                                    bottom_largest = max([val for val in element_data['good'] if val != NoValue])
                                else:
                                    bottom_largest = min_y_val

                                if not_empty_bad:
                                    top_smallest = max([val for val in element_data['bad'] if val != NoValue])
                                else:
                                    top_smallest = max_y_val

                            # bottom area
                            top_line = self.c.addLineLayer(bottom_area, Transparent)
                            top_line.setUseYAxis(axis)
                            top_line.setXData(self._x_axis_data)

                            bottom_line = self.c.addLineLayer([min_y_val for i in bottom_area], Transparent)
                            bottom_line.setXData(self._x_axis_data)
                            bottom_line.setUseYAxis(axis)

                            top_y = stop_light_area_line.getYCoor(bottom_largest)
                            bottom_y = stop_light_area_line.getYCoor(min_y_val)

                            bottom_color = self.c.linearGradientColor(0,
                                                              bottom_y,
                                                              0,
                                                              top_y,
                                                              bottom_end_color,
                                                              bottom_start_color)

                            bottom_area = self.c.addInterLineLayer(top_line.getLine(), bottom_line.getLine(), bottom_color)
                            bottom_area.setUseYAxis(axis)

                            self.datasets[self.layers_count] = {}
                            self.datasets[self.layers_count][0] = {'uid': uid, 'metric_data': element_type, 'type': 'good_stop_light', 'shape': ''}
                            self.dataset_ids[self.layers_count] = 0
                            self.layers_count += 1

                            self.datasets[self.layers_count] = {}
                            self.datasets[self.layers_count][0] = {'uid': uid, 'metric_data': element_type, 'type': 'good_stop_light', 'shape': ''}
                            self.dataset_ids[self.layers_count] = 0
                            self.layers_count += 1

                            self.datasets[self.layers_count] = {}
                            self.datasets[self.layers_count][0] = {'uid': uid, 'metric_data': element_type, 'type': 'good_stop_light', 'shape': ''}
                            self.dataset_ids[self.layers_count] = 0
                            self.layers_count += 1

                            # top area
                            bottom_line = self.c.addLineLayer(top_area, Transparent)
                            bottom_line.setXData(self._x_axis_data)
                            bottom_line.setUseYAxis(axis)

                            top_line = self.c.addLineLayer([max_y_val for i in top_area], Transparent)
                            top_line.setUseYAxis(axis)
                            top_line.setXData(self._x_axis_data)

                            top_y = stop_light_area_line.getYCoor(max_y_val)
                            bottom_y = stop_light_area_line.getYCoor(top_smallest)

                            top_color = self.c.linearGradientColor(0,
                                                              bottom_y,
                                                              0,
                                                              top_y,
                                                              top_start_color,
                                                              top_end_color)

                            top_area = self.c.addInterLineLayer(top_line.getLine(), bottom_line.getLine(), top_color)
                            top_area.setUseYAxis(axis)

                            self.datasets[self.layers_count] = {}
                            self.datasets[self.layers_count][0] = {'uid': uid, 'metric_data': element_type, 'type': 'good_stop_light', 'shape': ''}
                            self.dataset_ids[self.layers_count] = 0
                            self.layers_count += 1

                            self.datasets[self.layers_count] = {}
                            self.datasets[self.layers_count][0] = {'uid': uid, 'metric_data': element_type, 'type': 'good_stop_light', 'shape': ''}
                            self.dataset_ids[self.layers_count] = 0
                            self.layers_count += 1

                            self.datasets[self.layers_count] = {}
                            self.datasets[self.layers_count][0] = {'uid': uid, 'metric_data': element_type, 'type': 'good_stop_light', 'shape': ''}
                            self.dataset_ids[self.layers_count] = 0
                            self.layers_count += 1

        filename = ''
        if self.settings['type'] == 'large':
            if self.settings['show_stop_light']:
                filename = self._jfile.get_chart_file_name(self.interval, suffix='_stoplight')
            elif self.settings['show_std_deviation']:
                filename = self._jfile.get_chart_file_name(self.interval, suffix='_std_dev')
            else:
                filename = self._jfile.get_chart_file_name(self.interval, suffix='')
        elif self.settings['type'] == 'thumbnail':
            filename = self._jfile.get_thumbnail_file_name()
        elif self.settings['type'] == 'preview':
            filename = self._jfile.get_preview_file_name()

        # draw chart
        if not self.c.makeChart(filename):
            raise Exception("ChartDirector cannot create image file %s." % filename)
        self.file_man.change_perm(filename)

        if self.settings['type'] == 'large' and not (self.settings['show_stop_light'] or self.settings['show_std_deviation']) and self.settings['is_index']:
            self.create_resized_preview()
Exemple #8
0
 def __init__(self, N_labels, fontSize):
     self.fontSize = fontSize
     self.initLabels(N_labels)
     self.fontManager = FontManager(fontSize)
Exemple #9
0
    def create_chart(self):
        c = PieChart(self.layout_data['chart_object_size_x'],
                     self.layout_data['chart_object_size_y'],
                     FontManager.get_db_color(self.layout_data['background_color']),
                     FontManager.get_db_color(self.layout_data['border_color']),
                     0)

        # make pretty fonts
        c.setAntiAlias(True, AntiAlias)

        labels = self.chart_data['formatted_header']

        try:
            c.setData(self.chart_data['data'], labels)
        except TypeError:
            raise Exception("Chart %s misconfigured. Sector Values must contain numeric values." % self.report_data_set_chart_id)

        # colors for sectors for the pie chart
        if self.chart_data['colors']:
            c.setColors2(DataColor, self.chart_data['colors'])

        # set chart title
        if self.layout_data['include_title_ind'] == 'Y':
            c.addTitle(self.layout_data['name'],
                        FontManager.get_db_font(self.layout_data['title_font']),
                        self.layout_data['title_font_size'],
                        self.layout_data['title_font_color'])
        # define center coordinates
        if not self.layout_data['pie_chart_center_x_coord']:
            self.layout_data['pie_chart_center_x_coord'] = self.layout_data['chart_object_size_x'] // 2

        if not self.layout_data['pie_chart_center_y_coord']:
            self.layout_data['pie_chart_center_y_coord'] = self.layout_data['chart_object_size_y'] // 2

        # define radius
        if not self.layout_data['pie_chart_radius']:
            if self.layout_data['chart_object_size_y'] > self.layout_data['chart_object_size_x']:
                smallest_side = self.layout_data['chart_object_size_x']
            else:
                smallest_side = self.layout_data['chart_object_size_y']
            self.layout_data['pie_chart_radius'] = int(smallest_side // 2 * 0.7)
            # reduce radius for preview chart
            if self.settings['type'] == 'preview':
                #self.layout_data['pie_chart_radius'] = self.layout_data['pie_chart_radius'] * 0.9
                self.layout_data['pie_chart_radius'] *= 0.9

        # set pie position and radius
        c.setPieSize(self.layout_data['pie_chart_center_x_coord'], self.layout_data['pie_chart_center_y_coord'], self.layout_data['pie_chart_radius'])

        # 3D chart settings
        if self.layout_data['pie_chart_type'] == '3D':
            # if depth not specified use default
            if not self.layout_data['pie_chart_depth']:
                self.layout_data['pie_chart_depth'] = -1
            # if start angle not specified use default
            if not self.layout_data['pie_chart_display_angle']:
                self.layout_data['pie_chart_display_angle'] = -1
            c.set3D(self.layout_data['pie_chart_depth'], self.layout_data['pie_chart_display_angle'])

        # start angle
        if not self.layout_data['pie_chart_start_angle']:
            self.layout_data['pie_chart_start_angle'] = 0
        c.setStartAngle(self.layout_data['pie_chart_start_angle'])

        # set labels position formats
        if self.settings['type'] == 'preview':
            label_pos = 5
        else:
            label_pos = 15
        c.setLabelLayout(SideLayout, label_pos)

        # label font color
        if self.settings['type'] == 'thumbnail':
            self.layout_data['pie_chart_sector_label_font_color'] = Transparent
        else:
            if self.layout_data['pie_chart_sector_label_font_color']:
                # use specified color
                self.layout_data['pie_chart_sector_label_font_color'] = FontManager.get_db_color(self.layout_data['pie_chart_sector_label_font_color'])
            else:
                # same as sector color
                self.layout_data['pie_chart_sector_label_font_color'] = SameAsMainColor

        t = c.setLabelStyle(FontManager.get_db_font(self.layout_data['pie_chart_sector_label_font']),
                            self.layout_data['pie_chart_sector_label_font_size'],
                            self.layout_data['pie_chart_sector_label_font_color'])
        if self.settings['type'] == 'preview' or self.settings['type'] == 'large':
            max_label_width = (self.layout_data['chart_object_size_x'] - self.layout_data['pie_chart_radius'] * 2 - label_pos * 2) / 2
            t.setMaxWidth(max_label_width)

        if self.settings['type'] == 'thumbnail':
            fill_label_color = Transparent
            sector_label_border_color = Transparent
        else:
            if self.layout_data['use_sector_color_for_Label_fill_ind'] == 'Y':
                # same as sector color
                fill_label_color = SameAsMainColor
            else:
                # no background
                fill_label_color = Transparent
            if self.layout_data['sector_label_border_color']:
                # use specified color
                sector_label_border_color = FontManager.get_db_color(self.layout_data['sector_label_border_color'])
            else:
                # no border
                sector_label_border_color = Transparent
        # set label background and border color
        t.setBackground(fill_label_color, sector_label_border_color)

        # rounded corners of labels
        if self.layout_data['sector_label_corner_style'] == 'Rounded':
            t.setRoundedCorners()

        # join line format
        if self.settings['type'] == 'thumbnail':
            # do not draw line
            join_line_color = Transparent
        else:
            if self.layout_data['sector_label_join_line_color']:
                # use specified color
                join_line_color = FontManager.get_db_color(self.layout_data['sector_label_join_line_color'])
            else:
                # use sector color
                join_line_color = SameAsMainColor

        c.setJoinLine(join_line_color)

        # shading format
        if self.layout_data['pie_chart_shading'] == 'Rounded Edge':
            shading = RoundedEdgeShading
        elif self.layout_data['pie_chart_shading'] == 'Flat Gradient' and self.layout_data['pie_chart_type'] == '3D':
            shading = FlatShading
        else:
            shading = DefaultShading

        # explode sectors
        if (self.layout_data['explode_all_pie_sectors'] == 'all' or
                (self.layout_data['explode_all_pie_sectors'] == '2D' and self.layout_data['pie_chart_type'] == '2D') or
                (self.layout_data['explode_all_pie_sectors'] == '3D' and self.layout_data['pie_chart_type'] == '3D')):
            if not self.layout_data['pie_sectors_explode_width']:
                self.layout_data['pie_sectors_explode_width'] = 0
            # reduce border width for small images
            if self.settings['type'] != 'large':
                #self.layout_data['pie_sectors_explode_width'] = self.layout_data['pie_sectors_explode_width'] / 2
                self.layout_data['pie_sectors_explode_width'] /= 2

            c.setExplode(-1, self.layout_data['pie_sectors_explode_width'])
            self.layout_data['pie_chart_sector_border_width'] = 0
            self.layout_data['sector_edge_line_color'] = ''

        # sector border(edge) color
        if self.layout_data['sector_edge_line_color']:
            # use specified color
            edge_line_color = FontManager.get_db_color(self.layout_data['sector_edge_line_color'])
        else:
            # use sector color
            edge_line_color = SameAsMainColor

        # sector border(edge) width
        if not self.layout_data['pie_chart_sector_border_width']:
            self.layout_data['pie_chart_sector_border_width'] = 0

        # reduce border with for small images
        if self.settings['type'] != 'large':
            #self.layout_data['pie_chart_sector_border_width'] = self.layout_data['pie_chart_sector_border_width'] / 2
            self.layout_data['pie_chart_sector_border_width'] /= 2

        c.setSectorStyle(shading, edge_line_color, self.layout_data['pie_chart_sector_border_width'])

        # number of digits after point for % value
        if not self.layout_data['sector_value_pct_precision_digits']:
            self.layout_data['sector_value_pct_precision_digits'] = 0

        # label color
        if self.layout_data['pie_chart_sector_value_font_color']:
            self.layout_data['pie_chart_sector_value_font_color'] = FontManager.get_db_color(self.layout_data['pie_chart_sector_value_font_color'])
        else:
            self.layout_data['pie_chart_sector_value_font_color'] = None

        # label format
        if self.layout_data['show_sector_value_ind'] == 'Y':
            # show label, percentage and value in label
            c.addExtraField(self.chart_data['formatted_data'])
            label_format = "<*block*><*font=%s,size=%s,color=%s*>{label}<*br*>{field0} ({percent|%s}%%)<*/*>"
        else:
            # show label and percentage in label
            label_format = "<*block*><*font=%s,size=%s,color=%s*>{label}<*br*>({percent|%s}%%)<*/*>"

        # sector value font size
        if not self.layout_data['pie_chart_sector_value_font_size'] or self.layout_data['pie_chart_sector_value_font_size'] < 3:
            self.layout_data['pie_chart_sector_value_font_size'] = 8

        #reduce label font size for preview images
        if self.settings['type'] == 'preview':
            self.layout_data['pie_chart_sector_value_font_size'] = 8

        if self.layout_data['pie_chart_sector_value_font_color'] is not None:
            # if label color is specified, use it for all labels
            c.setLabelFormat(label_format % (
                                    FontManager.get_db_font(self.layout_data['pie_chart_sector_value_font']),
                                    self.layout_data['pie_chart_sector_value_font_size'],
                                    self.layout_data['pie_chart_sector_value_font_color'],
                                    self.layout_data['sector_value_pct_precision_digits']))
        else:
            # if label color is not specified, use color of sector
            for i, color in enumerate(self.chart_data['colors']):
                c.sector(i).setLabelFormat(label_format % (
                                    FontManager.get_db_font(self.layout_data['pie_chart_sector_value_font']),
                                    self.layout_data['pie_chart_sector_value_font_size'],
                                    hex(color),
                                    self.layout_data['sector_value_pct_precision_digits']))

        # draw annotations
        if self.settings['type'] == 'large':
            c.layout()
            index = 1
            for i, header in enumerate(self.chart_data['formatted_header']):
                if self.chart_data['annotations'][header]:
                    sector = c.getSector(i)
                    coord_string = sector.getLabelCoor()

                    content = urllib.unquote(coord_string)

                    res = re.findall(r'shape="rect" coords="(.+?),(.+?),(.+?),(.+?)"', content)
                    coords = res[0]

                    x_coord = (int(coords[2]) + int(coords[0])) / 2
                    y_coord = int(coords[1]) + 25

                    annot_marker = "<*img=%s*>" % self.config.resource_file('annotation.png')
                    c.addText(x_coord, y_coord, annot_marker, "", 0, 0x0, BottomCenter)
                    c.addText(x_coord, y_coord - 32, str(index), FontManager.get_default_bold_font(), 10, 0xffffff, BottomCenter)
                    for annot in self.chart_data['annotations'][header]:
                        annot['index'] = index
                        annot['shape'] = 'rect'
                        annot['chart_by_column_value'] = header
                        annot['chart_element_identifier'] = ''
                        annot['value'] = self.chart_data['formatted_data'][self.chart_data['header'].index(header)]
                        marker_coors = [x_coord - 9, y_coord - 47, x_coord + 10, y_coord - 29]
                        annot['coords'] = ','.join(map(str, marker_coors))
                        annot['annotation_interval'] = 'point'
                        annot['start_time'] = ''
                        annot['finish_time'] = ''
                        annot['raw_start_time'] = ''
                        annot['raw_finish_time'] = ''
                        self.annotations_map.append(annot)
                    index += 1

        filename = ''
        if self.settings['type'] == 'large':
            filename = self._jfile.get_chart_file_name(self.report_data_set_chart_id, self.report_data_set_instance_id)
        elif self.settings['type'] == 'thumbnail':
            filename = self._jfile.get_thumbnail_file_name()
        elif self.settings['type'] == 'preview':
            filename = self._jfile.get_preview_file_name()

        if not c.makeChart(filename):
            raise Exception("ChartDirector cannot create image file %s for chart %s." % (filename, self.report_data_set_chart_id))
        self.file_man.change_perm(filename)

        self.c = c

        if self.settings['type'] == 'large':
            self.create_map_file()
            if self.settings['is_index']:
                self.create_resized_preview()