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 #2
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()