コード例 #1
0
ファイル: legend3.py プロジェクト: likaiwen123/VERAview
    def CreateBitmap(self,
                     value_range,
                     bg_color=None,
                     cmap=None,
                     font_size=10,
                     mapper=None,
                     ntick_values=10,
                     scale_type='linear',
                     title=None):
        """Generate the wx.Bitmap.
    Args:
	value_range (tuple): range_min, range_max, data_min, data_max
..        scalar_map (matplotlib.cm.ScalarMappable): instance used to map
..	    values to colors and determine the range and scale type
	bg_color (wx.Colour): optional color for Linux/GTK support
	cmap (matplotlib.colors.Colormap): optional colormap to use if
	    mapper is None, defaulting to 'rainbow'
	font_size (int): font point size
	mapper (matplotlib.cm.ScalarMappable): optional pre-built mapper,
	    if None one is created basd on value_range and scale_type; Note
	    the ``norm`` property determines scale_type, overriding the
	    ``scale_type`` parameter if provided
        ntick_values (int): number of values to show as ticks
	scale_type (str): 'linear' or 'log', used if mapper is None
	title (str): optional title under legend
    Returns:
        wx.Bitmap: new bitmap
"""
        ntick_values = max(2, ntick_values)
        data_max = value_range[3] if len(value_range) > 3 else value_range[1]
        data_min = value_range[2] if len(value_range) > 2 else value_range[0]

        if isinstance(mapper, cm.ScalarMappable):
            norm = mapper.norm
            is_log_scale = isinstance(norm, colors.LogNorm)
        else:
            is_log_scale = scale_type == 'log'
            if is_log_scale:
                norm = colors.LogNorm(
                    #vmin = value_range[ 0 ], vmax = value_range[ 1 ], clip = True
                    vmin=max(data_min, 1.0e-16),
                    vmax=max(data_max, 1.0e-16),
                    clip=True)
            else:
                norm = colors.Normalize(
                    #vmin = value_range[ 0 ], vmax = value_range[ 1 ], clip = True
                    vmin=data_min,
                    vmax=data_max,
                    clip=True)
            if cmap is None:
                cmap = cm.get_cmap(Config.defaultCmapName_)  #'rainbow'
            mapper = cm.ScalarMappable(norm=norm, cmap=cmap)
#cmap = cm.get_cmap( 'rainbow' )
#norm = scalar_map.norm
#is_log_scale = isinstance( norm, colors.LogNorm )

#		-- Pre-step, format values
#		--
        scaler = RangeScaler()
        steps = scaler.Calc(norm.vmin,
                            norm.vmax,
                            scale_type='log' if is_log_scale else 'linear',
                            nticks=ntick_values,
                            cull_outside_range=True)
        labels_mode = 'log' if is_log_scale else 'linear'
        labels = scaler.CreateLabels(steps, labels_mode)

        widest_label = None
        for l in labels:
            if widest_label is None or len(l) > len(widest_label):
                widest_label = l

#		-- Calc sizes
#		--
        border = 2
        text_gap = 8  # line drawn from text to color block
        pen_color = (0, 0, 0, 255)

        dc = wx.MemoryDC()
        dc.SelectObject(wx.EmptyBitmapRGBA(64, 64))

        #    if Config.GetOSName() == 'windows':
        #      font_size = int( font_size * 0.8 )

        font_params = \
          {
          'pointSize': font_size,
          'family': wx.FONTFAMILY_SWISS,
          'style': wx.FONTSTYLE_NORMAL,
          'weight': wx.FONTWEIGHT_NORMAL
          }
        if Config.GetOSName() == 'windows':
            font_params['faceName'] = 'Lucida Sans'  # 'Arial'
            font_params['weight'] = wx.FONTWEIGHT_BOLD
        cur_font = wx.Font(**font_params)
        dc.SetFont(cur_font)
        text_size = dc.GetTextExtent('99' + widest_label)
        if title:
            tsize = dc.GetTextExtent(title)
            if tsize[0] > text_size[0]:
                text_size = (tsize[0], tsize[1])

        if Config.GetOSName() == 'darwin':
            block_size = text_size[1] << 1
        else:
            block_size = int(text_size[1] * 1.5)

        im_wd = border + text_size[0] + text_gap + block_size + border
        color_band_ht = block_size * ntick_values
        im_ht = \
     border + (text_size[ 1 ] << 1) + color_band_ht + \
            (text_size[ 1 ] >> 1) + 2 + \
            text_size[ 1 ] + (text_size[ 1 ] >> 1)
        #        border + block_size + color_band_ht +
        #	text_size[ 1 ] + border
        if title:
            im_ht += block_size + text_size[1]

        #this is drawn empty in Windows
        if bg_color is not None:
            bmap = wx.EmptyBitmapRGBA(im_wd, im_ht, bg_color.red,
                                      bg_color.green, bg_color.blue,
                                      bg_color.alpha)
        else:
            bmap = wx.EmptyBitmapRGBA(im_wd, im_ht)

        dc.SelectObject(bmap)
        if bg_color is None:
            if Config.GetOSName() == 'windows':
                dc.SetBackground(
                    wx.TheBrushList.FindOrCreateBrush(
                        wx.WHITE, wx.BRUSHSTYLE_SOLID
                        #wx.Colour( 225, 225, 225, 255 ), wx.BRUSHSTYLE_SOLID
                    ))
                dc.Clear()
            else:
                dc.SetBackground(
                    wx.TheBrushList.FindOrCreateBrush(wx.WHITE,
                                                      wx.TRANSPARENT))
        #end if bg_color is None
        gc = wx.GraphicsContext.Create(dc)

        trans_brush = gc.CreateBrush(
            wx.TheBrushList.FindOrCreateBrush(wx.WHITE, wx.TRANSPARENT))
        black_pen = gc.CreatePen(wx.Pen(wx.BLACK, 1))
        gfont = gc.CreateFont(cur_font, wx.BLACK)
        gc.SetAntialiasMode(wx.ANTIALIAS_DEFAULT)  # wx.ANTIALIAS_NONE
        gc.SetBrush(trans_brush)
        gc.SetFont(gfont)
        gc.SetInterpolationQuality(wx.INTERPOLATION_BEST)
        gc.SetPen(black_pen)

        # x,y is UL position of the contour color block
        x = im_wd - border - block_size
        # do this if not drawing max value
        #y = border + (text_size[ 1 ] >> 1)
        y = border

        #		-- Write max value
        #		--
        data_max_log = int(math.log10(data_max)) if data_max > 0.0 else 0
        steps_max_log = int(math.log10(steps[-1])) if steps[-1] > 0.0 else 0

        #cur_label = scaler.Format( data_max, 3 )
        cur_label = \
            scaler.Format( data_max, 3 )  if data_max_log == steps_max_log else \
     '{0:.3g}'.format( data_max )
        label_size = gc.GetFullTextExtent(cur_label)
        gc.DrawText(cur_label, x + block_size - label_size[0],
                    y + label_size[2])

        #x y += text_size[ 1 ] + (text_size[ 1 ] >> 1)
        y += text_size[1] << 1

        #		-- Draw color band
        #		--
        max_value = max(norm.vmax, steps[-1])
        min_value = min(norm.vmin, steps[0])

        if is_log_scale:
            #      log_delta = \
            #          0  if norm.vmin == 0.0 else  math.log10( max_value / min_value )
            log_delta = \
                0  if norm.vmin == 0.0 else \
         0  if max_value <= 0.0 or  min_value <= 0.0 else \
         math.log10( max_value / min_value )
            log_b = log_delta / color_band_ht
            log_factor = math.pow(10.0, log_b)
            #log_a = value_range[ 1 ] / math.pow( 10.0, log_factor * color_band_ht )
            #                           this is 1
        else:
            #value_delta = norm.vmax - norm.vmin
            value_delta = max_value - min_value
            value_incr = value_delta / (color_band_ht - 1)

        #cur_value = value_range[ 1 ]
        cur_value = max_value
        for j in xrange(color_band_ht):
            #      if is_log_scale:
            #        cur_value = value_range[ 1 ] / math.pow( 10.0, log_b * j )

            #color = cmap( norm( cur_value ), bytes = True )
            color = mapper.to_rgba(cur_value, bytes=True)
            gc.SetBrush(
                gc.CreateBrush(
                    wx.TheBrushList.FindOrCreateBrush(wx.Colour(*color),
                                                      wx.BRUSHSTYLE_SOLID)))
            gc.SetPen(
                gc.CreatePen(
                    wx.ThePenList.FindOrCreatePen(wx.Colour(*color), 1,
                                                  wx.PENSTYLE_SOLID)))
            gc.DrawRectangle(x, y + j, block_size, 1)
            if is_log_scale:
                cur_value /= log_factor
            else:
                cur_value -= value_incr
        #end for

        gc.SetBrush(trans_brush)
        gc.SetPen(
            gc.CreatePen(
                wx.ThePenList.FindOrCreatePen(wx.Colour(*pen_color), 1,
                                              wx.PENSTYLE_SOLID)))
        gc.DrawRectangle(x, y, block_size, color_band_ht)

        #		-- Draw contour values and lines
        #		--
        for j in xrange(len(steps)):
            cur_value = steps[j]
            cur_label = labels[j]
            if is_log_scale:
                tick_delta = math.log10(max_value / cur_value) / log_b
            else:
                tick_delta = (max_value -
                              cur_value) / value_delta * color_band_ht
            tick_y = y + tick_delta
            gc.DrawLines(((x - text_gap, tick_y), (x, tick_y)))

            label_size = gc.GetFullTextExtent(cur_label)
            gc.DrawText(cur_label, x - text_gap - label_size[0] - 1,
                        tick_y - (label_size[1] / 2.0))
        #end for j
        y += color_band_ht

        #		-- Write min value
        #		--
        if data_min == 0.0 or steps[0] == 0.0:
            data_min_log = steps_min_log = 0
        else:
            data_min_log = int(math.log10(abs(data_min)))
            steps_min_log = int(math.log10(abs(steps[0])))

        #cur_label = scaler.Format( data_min, 3 )
        cur_label = \
            scaler.Format( data_min, 3 )  if data_min_log == steps_min_log else \
     '{0:.3g}'.format( data_min )
        label_size = gc.GetFullTextExtent(cur_label)
        #x gc.DrawText( cur_label, x + block_size - label_size[ 0 ], y + 2 )
        y += (text_size[1] >> 1) + 2
        gc.DrawText(cur_label, x + block_size - label_size[0], y)

        if title:
            #x y += block_size
            y += text_size[1] + (text_size[1] >> 1)
            title_size = gc.GetFullTextExtent(title)
            tx = im_wd - title_size[0]
            gc.DrawText(title, tx, y)
        #end if title

        dc.SelectObject(wx.NullBitmap)

        return bmap