Gauges and Meters - Vert/Horiz Meter.

Gauges and Meters - Vert/Horiz Meter.
Hello,

A few posts back, I included source code to some gauges I had whipped together. After some constructive advice from John Hunter (Thanks!), I’ve had time to polish them a bit and include the logarithmic ones as promised.

···

===============================================================================

#!/usr/bin/env python

“”"

The Meter widget draws a linear meter, either horizontally or vertically. You supply the direction, limits,

shaded regions, names and the current value, and invoke it like this:

from pylab import figure, show



raw_value = -4.0

raw_limits = [-10.0,10.0,5,1]

raw_zones = [[-10.0,0.0,'r'],[0.0,5.0,'y'],[5.0,10.0,'g']]

attribute_name = "Rx MOS (24h)"



s_length = 0.3

p_length  = 2.0

fig_height   = s_length + 1.0

fig_width    = p_length + 0.4

fig = figure( figsize=(fig_width, fig_height) )



rect = [(0.2/fig_width), (0.5/fig_height),

        (p_length/fig_width), (s_length/fig_height)]



meter = H_Meter(fig, rect,

           xlim=( -0.1, p_length+0.1 ),

           ylim=( -0.4, s_length+0.1 ),

           xticks=[],

           yticks=[],

           )

meter.set_axis_off()

fig.add_axes(meter)

show()

“”"

from future import division

from matplotlib.figure import Figure

from matplotlib.axes import Axes

import math

import types

from math import pi

class Meter(Axes):

def __init__(self, vertical, raw_value, raw_limits, raw_zones, attribute_name, field_names, file_name, resolution, p_length, s_length, *args, **kwargs):

    Axes.__init__(self, *args, **kwargs)

    #Perform Checking

    if( raw_limits[0] == raw_limits[1] ):

        raise ValueError('identical_limits_exception: %s' % raw_limits)

    if( raw_limits[1] > raw_limits[0] ):

        self.graph_positive = True

    else:   #Swap the limits around

        self.graph_positive = False

        raw_limits[0], raw_limits[1] = raw_limits[1] = raw_limits[0]

           

    if not( ((raw_limits[2]/raw_limits[3]) % 1.0) * raw_limits[3] == 0 ):   #There must be an integer number of minor ticks for each major tick

        raise ValueError('bad_tick_spacing_exception')

    if( raw_limits[2] <= 0 or raw_limits[3] <= 0 or raw_limits[2] < raw_limits[3] or raw_limits[3] > abs(raw_limits[1]-raw_limits[0]) ):

        raise ValueError('bad_limits_exception:%s' % raw_limits)

    for zone in raw_zones:

            if( zone[0] > zone[1] ):        #Swap the zones so zone[1] > zone[0]

                zone[0], zone[1] = zone[1] = zone[0]

            if( zone[1] < raw_limits[0] or zone[0] > raw_limits[1] ):

                raise ValueError('bad_zone_exception'%zone)

            if( zone[0] < raw_limits[0] ):

                zone[0] = raw_limits[0]

            if( zone[1] > raw_limits[1] ):

                zone[1] = raw_limits[1]

               

    #Adjust the scaling

    self.scaled_limits = []

    for limit in raw_limits:

        self.scaled_limits.append( limit * p_length / (raw_limits[1]-raw_limits[0]))

   

              

    #Stuff all of the variables into self.

    self.vertical = vertical

    self.raw_value = raw_value

    self.raw_limits = raw_limits

    self.raw_zones = raw_zones

    self.attribute_name = attribute_name

    self.field_names = field_names

    self.file_name = file_name

    self.resolution = resolution

    self.p_length = p_length

    self.s_length = s_length

   

    #Draw the meter

    self.graph_center = ((self.scaled_limits[1]+self.scaled_limits[0])/2)

    for zone in raw_zones:

        self.draw_bar( zone, False)

    self.draw_bar( None, True)

    self.draw_ticks()

    self.draw_needle()

    if( self.vertical ):

        self.text( self.s_length/2, self.scaled_limits[0]-0.1, self.attribute_name, size=12, va='top', ha='center')

    else:

        self.text( self.graph_center, self.s_length+0.25, self.attribute_name, size=12, va='bottom', ha='center')

   

def draw_bar( self, zone, border):

    if( border ):

        start  = self.scaled_limits[0]

        end    = self.scaled_limits[1]

    else:

        start  = (zone[0] * self.p_length / (self.raw_limits[1]-self.raw_limits[0]))

        end    = (zone[1] * self.p_length / (self.raw_limits[1]-self.raw_limits[0]))

        colour =  zone[2]

       

    if( not self.graph_positive ):

        start = -start

        end = -end

       

    s_vect = [ 0.0, 0.0, self.s_length, self.s_length ]

    p_vect = [ start, end, end, start ]

   

    if( border ):

        #Close the loop

        p_vect.append(start)

        s_vect.append(0.0)

        if( self.vertical ):

            p = self.plot(s_vect, p_vect, 'b-', color='black', linewidth=1.5)

        else:

            p = self.plot(p_vect, s_vect, 'b-', color='black', linewidth=1.5)

    else:

        if( self.vertical ):

            p = self.fill(s_vect, p_vect, colour, linewidth=0.0, alpha=0.4)

        else:

            p = self.fill(p_vect, s_vect, colour, linewidth=0.0, alpha=0.4)

def draw_needle( self ):       

    if( self.raw_value == None ):

        if( self.vertical ):

            self.text( (self.s_length + 0.05), self.graph_center, "N/A", size=10, va='center', ha='left')

        else:

            self.text( self.graph_center, (self.s_length + 0.05), "N/A", size=10, va='bottom', ha='center')

    else:

        #Clamp the value to the limits

        value = self.raw_value * self.p_length / (self.raw_limits[1]-self.raw_limits[0])

        if( self.raw_value < self.raw_limits[0] ):

            value = self.raw_limits[0] * self.p_length / (self.raw_limits[1]-self.raw_limits[0])

        if( self.raw_value > self.raw_limits[1] ):

            value = self.raw_limits[1] * self.p_length / (self.raw_limits[1]-self.raw_limits[0])

       

        if( self.vertical ):

            self.text( (self.s_length + 0.05), value, "%.2f" % self.raw_value, size=10, va='center', ha='left')

        else:

            self.text( value, (self.s_length + 0.05), "%.2f" % self.raw_value, size=10, va='bottom', ha='center')

       

        if( not self.graph_positive ):

            value = -value

        s_vect = [ self.s_length/2, self.s_length, self.s_length ]

        p_vect = [ value + 0.00, value - 0.05, value + 0.05 ]

       

        if( self.vertical ):

            self.fill(s_vect, p_vect, 'black')

        else:

            self.fill(p_vect, s_vect, 'black')

   

   

def draw_ticks( self ):

    if( self.graph_positive ):

        offset = self.scaled_limits[0]

    else:

        offset = self.scaled_limits[1]

    i = 0

    j = self.raw_limits[0]

    while( i*self.scaled_limits[3] + self.scaled_limits[0] <= self.scaled_limits[1] ):

        if( i % (self.scaled_limits[2]/self.scaled_limits[3]) == 0):

            tick_length = self.s_length

            if( self.vertical ):

                if( type(self.raw_limits[2]) is types.FloatType ):

                    self.text( -0.05, offset, "%.2f" % j, size=10, va='center', ha='right')

                else:

                    self.text( -0.05, offset, "%d" % int(j), size=10, va='center', ha='right')

            else:    

                tick_length = self.s_length

                if( type(self.raw_limits[2]) is types.FloatType ):

                    self.text( offset, -0.05, "%.2f" % j, size=10, va='top', ha='center')

                else:

                    self.text( offset, -0.05, "%d" % int(j), size=10, va='top', ha='center')

            j += self.raw_limits[2]

        else:

            tick_length = self.s_length * 0.2

               

        s_vect = [ 0.0, tick_length ]

        p_vect = [ offset, offset ]

       

        if( self.vertical ):

            p = self.plot(s_vect, p_vect, 'b-', linewidth=1, color='black', alpha=0.2)

        else:

            p = self.plot(p_vect, s_vect, 'b-', linewidth=1, color='black', alpha=0.2)

        i += 1

        if( self.graph_positive ):

            offset += self.scaled_limits[3]

        else:

            offset -= self.scaled_limits[3]

   

    if( i % (self.scaled_limits[2]/self.scaled_limits[3]) == 0):

        if( self.vertical ):

            if( type(self.raw_limits[2]) is types.FloatType ):

                self.text( -0.01, offset, "%.2f" % j, size=10, va='top', ha='center')

            else:

                self.text( -0.01, offset, "%d" % int(j), size=10, va='top', ha='center')

        else:

            if( type(self.raw_limits[2]) is types.FloatType ):

                self.text( offset, -0.1, "%.2f" % j, size=10, va='top', ha='center')

            else:

                self.text( offset, -0.1, "%d" % int(j), size=10, va='top', ha='center')

def make_widget( vertical, raw_value, raw_limits, raw_zones, attribute_name, field_names, file_name, resolution=72 ):

from pylab import figure, show, savefig



p_length = 2.0  # Length of the Primary axis

s_length = 0.3  # Length of the Secondary axis

   

if( vertical ):

    fig_height = p_length + 0.6

    fig_width  = s_length + 1.0

    fig = figure( figsize=(fig_width, fig_height) )

    rect = [(0.5/fig_width), (0.4/fig_height), (s_length/fig_width), (p_length/fig_height)]

    meter = Meter(vertical, raw_value,

        raw_limits, raw_zones,

        attribute_name, field_names,

        file_name, resolution,

        p_length, s_length,

        fig, rect,

        xlim=( -0.2, s_length+0.1 ),

        ylim=( -0.1, p_length+0.1 ),

        xticks=[],

        yticks=[]

        )

else:

    fig_height = s_length + 1.0

    fig_width  = p_length + 0.4

    fig = figure( figsize=(fig_width, fig_height) )

    rect = [(0.2/fig_width), (0.5/fig_height), (p_length/fig_width), (s_length/fig_height)]

    meter = Meter(vertical, raw_value,

        raw_limits, raw_zones,

        attribute_name, field_names,

        file_name, resolution,

        p_length, s_length,

        fig, rect,

        xlim=( -0.1, p_length+0.1 ),

        ylim=( -0.4, s_length+0.1 ),

        xticks=[],

        yticks=[],

        )

       

meter.set_axis_off()

fig.add_axes(meter)

show()

fig.canvas.print_figure( file_name,dpi=resolution )             

#make_widget( False, -3.0, [-10.0,10.0,5,1], [[-10.0,0.0,‘r’],[0.0,5.0,‘y’],[5.0,10.0,‘g’]], “Rx MOS (24h)”, [‘WLL to LAS’,‘LAS to WLL’,‘WLL to LAS’,‘LAS to WLL’], ‘meter.png’, 100)

‘’’

if name==‘main’:

from pylab import figure, show, savefig



vertical = True   



raw_value = None

raw_limits = [-10.0,10.0,5,1]

raw_zones = [[-10.0,0.0,'r'],[0.0,5.0,'y'],[5.0,10.0,'g']]

attribute_name = "Rx MOS (24h)"



p_length = 2.0  # Length of the Primary axis

s_length = 0.3  # Length of the Secondary axis

   

if( vertical ):

    fig_height = p_length + 0.6

    fig_width  = s_length + 1.0

    fig = figure( figsize=(fig_width, fig_height) )

    rect = [(0.5/fig_width), (0.4/fig_height), (s_length/fig_width), (p_length/fig_height)]

    meter = Meter(fig, rect,

        xlim=( -0.2, s_length+0.1 ),

        ylim=( -0.1, p_length+0.1 ),

        xticks=[],

        yticks=[],

        )

else:

    fig_height = s_length + 1.0

    fig_width  = p_length + 0.4

    fig = figure( figsize=(fig_width, fig_height) )

    rect = [(0.2/fig_width), (0.5/fig_height), (p_length/fig_width), (s_length/fig_height)]

    meter = Meter(fig, rect,

        xlim=( -0.1, p_length+0.1 ),

        ylim=( -0.4, s_length+0.1 ),

        xticks=[],

        yticks=[],

        )

       

meter.set_axis_off()

fig.add_axes(meter)

show()

fig.canvas.print_figure('meter',dpi=72)

‘’’