# Gauges and Meters - Rotary Gauge.

Gauges and Meters - Rotary Gauge.
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 Gauge widget draws a semi-circular gauge. You supply raw_limits,

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

``````from pylab import figure, show

raw_value = -4.0

raw_limits = [-1.0,1.0,1,0.1]

raw_zones = [[-1.0,0.0,'r'],[0.0,0.5,'y'],[0.5,1.0,'g']]

attribute_name = "Rx MOS (24h)"

graph_height = 1.6

graph_width  = 2.4

fig_height   = graph_height

fig_width    = graph_width

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

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

(graph_width/fig_width), (graph_height/fig_height)]

gauge = Gauge(fig, rect,

xlim=( -0.1, graph_width+0.1 ),

ylim=( -0.4, graph_height+0.1 ),

xticks=[],

yticks=[],

)

gauge.set_axis_off()

show()
``````

“”"

from future import division

from matplotlib.figure import Figure

from matplotlib.axes import Axes

import math

import types

from math import pi

class Gauge(Axes):

``````def __init__(self, raw_value, raw_limits, raw_zones, attribute_name, field_names, file_name, resolution, x_length, y_length, *args, **kwargs):

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

#Perform Checking

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

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

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

self.graph_positive = True

else:    #Swap the raw_limits around

self.graph_positive = False

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

#There must be an integer number of minor ticks for each major tick

if not( ((raw_limits[2]/raw_limits[3]) % 1.0) * raw_limits[3] == 0 ):

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]) ):

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] ):

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

zone[0] = raw_limits[0]

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

zone[1] = raw_limits[1]

#Stuff all of the variables into self.

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.x_length = x_length

self.y_length = y_length

#Draw the gauge

for zone in raw_zones:

self.draw_arch( zone, False )

self.draw_arch( None, True )

self.draw_ticks()

self.draw_needle()

self.draw_bounding_box()

self.text(0.0, 0.2, self.attribute_name, size=10, va='bottom', ha='center')

#The black dot

p = self.plot([0.0],[0.0],'.', color='#000000')

def draw_arch( self, zone, border ):

if( border ):

start  = self.raw_limits[0]

end    = self.raw_limits[1]

else:

start  = zone[0]

end    = zone[1]

colour = zone[2]

x_vect = []

y_vect = []

if( self.graph_positive ):

start_value = int(180 - (start - self.raw_limits[0]) * (180.0/(self.raw_limits[1]-self.raw_limits[0])))

end_value   = int(180 - (end   - self.raw_limits[0]) * (180.0/(self.raw_limits[1]-self.raw_limits[0])))

else:

start_value = int(      (end   - self.raw_limits[0]) * (180.0/(self.raw_limits[1]-self.raw_limits[0])))

end_value   = int(      (start - self.raw_limits[0]) * (180.0/(self.raw_limits[1]-self.raw_limits[0])))

#Draw the arch

theta = start_value

while (theta >= end_value):

x_vect.append( radius * math.cos(theta * (pi/180)) )

y_vect.append( radius * math.sin(theta * (pi/180)) )

theta -= 1

theta = end_value

while (theta <= start_value):

x_vect.append( radius * math.cos(theta * (pi/180)) )

y_vect.append( radius * math.sin(theta * (pi/180)) )

theta += 1

if( border ):

#Close the loop

x_vect.append(-0.85)

y_vect.append(0.0)

p = self.plot(x_vect, y_vect, 'b-', color='black', linewidth=1.0)

else:

p = self.fill(x_vect, y_vect, colour, linewidth=0.0, alpha=0.4)

def draw_needle( self ):

x_vect = []

y_vect = []

if self.raw_value == None:

self.text(0.0, 0.4, "N/A", size=10, va='bottom', ha='center')

else:

self.text(0.0, 0.4, "%.2f" % self.raw_value, size=10, va='bottom', ha='center')

#Clamp the value to the raw_limits

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

self.raw_value = self.raw_limits[0]

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

self.raw_value = self.raw_limits[1]

theta = 0

length = 0.95

if( self.graph_positive ):

angle = 180.0 - (self.raw_value - self.raw_limits[0]) *(180.0/abs(self.raw_limits[1]-self.raw_limits[0]))

else:

angle =         (self.raw_value - self.raw_limits[0]) *(180.0/abs(self.raw_limits[1]-self.raw_limits[0]))

while (theta <= 270):

x_vect.append( length * math.cos((theta + angle) * (pi/180)) )

y_vect.append( length * math.sin((theta + angle) * (pi/180)) )

length = 0.05

theta += 90

p = self.fill(x_vect, y_vect, 'b', alpha=0.4)

def draw_ticks( self ):

if( self.graph_positive ):

angle = 180.0

else:

angle = 0.0

i = 0

j = self.raw_limits[0]

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

x_vect = []

y_vect = []

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

x_pos = 1.1 * math.cos( angle * (pi/180.0))

y_pos = 1.1 * math.sin( angle * (pi/180.0))

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

self.text( x_pos, y_pos, "%.2f" % j, size=10, va='center', ha='center', rotation=(angle - 90))

else:

self.text( x_pos, y_pos, "%d" % int(j), size=10, va='center', ha='center', rotation=(angle - 90))

tick_length = 0.15

j += self.raw_limits[2]

else:

tick_length = 0.05

i += 1

x_vect.append( 1.0 * math.cos( angle * (pi/180.0)))

x_vect.append( (1.0 - tick_length) * math.cos( angle * (pi/180.0)))

y_vect.append( 1.0 * math.sin( angle * (pi/180.0)))

y_vect.append( (1.0 - tick_length) * math.sin( angle * (pi/180.0)))

p = self.plot(x_vect, y_vect, 'b-', linewidth=1, alpha=0.4, color="black")

if( self.graph_positive ):

angle -= self.raw_limits[3] * (180.0/abs(self.raw_limits[1]-self.raw_limits[0]))

else:

angle += self.raw_limits[3] * (180.0/abs(self.raw_limits[1]-self.raw_limits[0]))

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

x_pos = 1.1 * math.cos( angle * (pi/180.0))

y_pos = 1.1 * math.sin( angle * (pi/180.0))

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

self.text( x_pos, y_pos, "%.2f" % j, size=10, va='center', ha='center', rotation=(angle - 90))

else:

self.text( x_pos, y_pos, "%d" % int(j), size=10, va='center', ha='center', rotation=(angle - 90))

def draw_bounding_box( self ):

x_vect = [

self.x_length/2,

self.x_length/2,

-self.x_length/2,

-self.x_length/2,

self.x_length/2,

]

y_vect = [

-0.1,

self.y_length,

self.y_length,

-0.1,

-0.1,

]

p = self.plot(x_vect, y_vect, 'r-', linewidth=0)
``````

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

``````from pylab import figure, show, savefig

x_length = 2.4  # Length of the Primary axis

y_length = 1.6  # Length of the Secondary axis

fig_height = y_length

fig_width  = x_length

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

rect = [(0.0/fig_width), (0.2/fig_height), (x_length/fig_width), (y_length/fig_height)]

gauge = Gauge( raw_value,

raw_limits, raw_zones,

attribute_name, field_names,

file_name, resolution,

x_length, y_length,

fig, rect,

xlim=( -0.1, x_length+0.1 ),

ylim=( -0.4, y_length+0.1 ),

xticks=[],

yticks=[],

)

gauge.set_axis_off()

``````

# show()

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

#make_widget( -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’], ‘gauge.png’, 100)

‘’’

if name==‘main’:

``````from pylab import figure, show

raw_value = -4.0

raw_limits = [-1.0,1.0,1,0.1]

raw_zones = [[-1.0,0.0,'r'],[0.0,0.5,'y'],[0.5,1.0,'g']]

attribute_name = "Rx MOS (24h)"

graph_height = 1.6

graph_width  = 2.4

fig_height   = graph_height

fig_width    = graph_width

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

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

(graph_width/fig_width), (graph_height/fig_height)]

gauge = Gauge(fig, rect,

xlim=( -0.1, graph_width+0.1 ),

ylim=( -0.4, graph_height+0.1 ),

xticks=[],

yticks=[],

)

gauge.set_axis_off()