|
From: Jamil K. <jam...@ca...> - 2005-07-27 04:04:16
|
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.
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D
#!/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 =3D -4.0
raw_limits =3D [-1.0,1.0,1,0.1]
raw_zones =3D [[-1.0,0.0,'r'],[0.0,0.5,'y'],[0.5,1.0,'g']]
attribute_name =3D "Rx MOS (24h)"
=20
graph_height =3D 1.6
graph_width =3D 2.4
fig_height =3D graph_height
fig_width =3D graph_width
fig =3D figure(figsize=3D(fig_width, fig_height ))
=20
rect =3D [(0.0/fig_width), (0.2/fig_height),
(graph_width/fig_width), (graph_height/fig_height)]
=20
gauge =3D Gauge(fig, rect,
xlim=3D( -0.1, graph_width+0.1 ),
ylim=3D( -0.4, graph_height+0.1 ),
xticks=3D[],
yticks=3D[],
)
gauge.set_axis_off()
fig.add_axes(gauge)
show()
"""
from __future__ import division
from matplotlib.figure import Figure
from matplotlib.axes import Axes
import math
import types
from math import pi
=20
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] =3D=3D raw_limits[1] ):
raise ValueError('identical_raw_limits_exception: =
%s'%raw_limits)
if( raw_limits[1] > raw_limits[0] ):
self.graph_positive =3D True
else: #Swap the raw_limits around
self.graph_positive =3D False
raw_limits[0], raw_limits[1] =3D raw_limits[1] =3D =
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] =
=3D=3D 0 ): =20
raise ValueError('bad_tick_spacing_exception')
if( raw_limits[2] <=3D 0 or
raw_limits[3] <=3D 0 or
raw_limits[2] < raw_limits[3] or
raw_limits[3] > abs(raw_limits[1]-raw_limits[0]) ):
raise ValueError('bad_raw_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] =3D 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] =3D raw_limits[0]
if( zone[1] > raw_limits[1] ):
zone[1] =3D raw_limits[1]
#Stuff all of the variables into self.
self.raw_value =3D raw_value
self.raw_limits =3D raw_limits
self.raw_zones =3D raw_zones
self.attribute_name =3D attribute_name
self.field_names =3D field_names
self.file_name =3D file_name
self.resolution =3D resolution
self.x_length =3D x_length
self.y_length =3D y_length
=20
=20
#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=3D10, =
va=3D'bottom', ha=3D'center')
#The black dot
p =3D self.plot([0.0],[0.0],'.', color=3D'#000000')
def draw_arch( self, zone, border ):
if( border ):
start =3D self.raw_limits[0]
end =3D self.raw_limits[1]
else:
start =3D zone[0]
end =3D zone[1]
colour =3D zone[2]
=20
x_vect =3D []
y_vect =3D []
if( self.graph_positive ):
start_value =3D int(180 - (start - self.raw_limits[0]) * =
(180.0/(self.raw_limits[1]-self.raw_limits[0])))
end_value =3D int(180 - (end - self.raw_limits[0]) * =
(180.0/(self.raw_limits[1]-self.raw_limits[0])))
else:
start_value =3D int( (end - self.raw_limits[0]) * =
(180.0/(self.raw_limits[1]-self.raw_limits[0])))
end_value =3D int( (start - self.raw_limits[0]) * =
(180.0/(self.raw_limits[1]-self.raw_limits[0])))
#Draw the arch
theta =3D start_value
radius =3D 0.85
while (theta >=3D end_value):
x_vect.append( radius * math.cos(theta * (pi/180)) )
y_vect.append( radius * math.sin(theta * (pi/180)) )
theta -=3D 1
theta =3D end_value
radius =3D 1.0
while (theta <=3D start_value):
x_vect.append( radius * math.cos(theta * (pi/180)) )
y_vect.append( radius * math.sin(theta * (pi/180)) )
theta +=3D 1
if( border ):
#Close the loop
x_vect.append(-0.85)
y_vect.append(0.0)
p =3D self.plot(x_vect, y_vect, 'b-', color=3D'black', =
linewidth=3D1.0)
else:
p =3D self.fill(x_vect, y_vect, colour, linewidth=3D0.0, =
alpha=3D0.4)
def draw_needle( self ):
x_vect =3D []
y_vect =3D []
if self.raw_value =3D=3D None:
self.text(0.0, 0.4, "N/A", size=3D10, va=3D'bottom', =
ha=3D'center')
else:
self.text(0.0, 0.4, "%.2f" % self.raw_value, size=3D10, =
va=3D'bottom', ha=3D'center')
#Clamp the value to the raw_limits
if( self.raw_value < self.raw_limits[0] ):
self.raw_value =3D self.raw_limits[0]
if( self.raw_value > self.raw_limits[1] ):
self.raw_value =3D self.raw_limits[1]
theta =3D 0
length =3D 0.95
if( self.graph_positive ):
angle =3D 180.0 - (self.raw_value - self.raw_limits[0]) =
*(180.0/abs(self.raw_limits[1]-self.raw_limits[0]))
else:
angle =3D (self.raw_value - self.raw_limits[0]) =
*(180.0/abs(self.raw_limits[1]-self.raw_limits[0]))
while (theta <=3D 270):
x_vect.append( length * math.cos((theta + angle) * =
(pi/180)) )
y_vect.append( length * math.sin((theta + angle) * =
(pi/180)) )
length =3D 0.05
theta +=3D 90
p =3D self.fill(x_vect, y_vect, 'b', alpha=3D0.4)
def draw_ticks( self ):
if( self.graph_positive ):
angle =3D 180.0
else:
angle =3D 0.0
i =3D 0
j =3D self.raw_limits[0]
while( i*self.raw_limits[3] + self.raw_limits[0] <=3D =
self.raw_limits[1] ):
x_vect =3D []
y_vect =3D []
if( i % (self.raw_limits[2]/self.raw_limits[3]) =3D=3D 0 ):
x_pos =3D 1.1 * math.cos( angle * (pi/180.0))
y_pos =3D 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=3D10, =
va=3D'center', ha=3D'center', rotation=3D(angle - 90))
else:
self.text( x_pos, y_pos, "%d" % int(j), size=3D10, =
va=3D'center', ha=3D'center', rotation=3D(angle - 90))
tick_length =3D 0.15
j +=3D self.raw_limits[2]
else:
tick_length =3D 0.05
i +=3D 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 =3D self.plot(x_vect, y_vect, 'b-', linewidth=3D1, =
alpha=3D0.4, color=3D"black")
if( self.graph_positive ):
angle -=3D self.raw_limits[3] * =
(180.0/abs(self.raw_limits[1]-self.raw_limits[0]))
else:
angle +=3D 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]) =3D=3D 0 ):
x_pos =3D 1.1 * math.cos( angle * (pi/180.0))
y_pos =3D 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=3D10, =
va=3D'center', ha=3D'center', rotation=3D(angle - 90))
else:
self.text( x_pos, y_pos, "%d" % int(j), size=3D10, =
va=3D'center', ha=3D'center', rotation=3D(angle - 90)) =20
def draw_bounding_box( self ):
x_vect =3D [
self.x_length/2,
self.x_length/2,
-self.x_length/2,
-self.x_length/2,
self.x_length/2,
]
y_vect =3D [
-0.1,
self.y_length,
self.y_length,
-0.1,
-0.1,
]
p =3D self.plot(x_vect, y_vect, 'r-', linewidth=3D0)
def make_widget( raw_value, raw_limits, raw_zones, attribute_name, =
field_names, file_name, resolution=3D72 ):
from pylab import figure, show, savefig
=20
x_length =3D 2.4 # Length of the Primary axis
y_length =3D 1.6 # Length of the Secondary axis
=20
fig_height =3D y_length
fig_width =3D x_length
fig =3D figure( figsize=3D(fig_width, fig_height) )
rect =3D [(0.0/fig_width), (0.2/fig_height), (x_length/fig_width), =
(y_length/fig_height)]
gauge =3D Gauge( raw_value,=20
raw_limits, raw_zones,=20
attribute_name, field_names,=20
file_name, resolution,
x_length, y_length,
fig, rect,
xlim=3D( -0.1, x_length+0.1 ),
ylim=3D( -0.4, y_length+0.1 ),
xticks=3D[],
yticks=3D[],
)
=20
gauge.set_axis_off()
fig.add_axes(gauge)
# show()
fig.canvas.print_figure( file_name,dpi=3Dresolution ) =20
=20
=20
#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)
=20
=20
'''
if __name__=3D=3D'__main__':
from pylab import figure, show
=20
raw_value =3D -4.0
raw_limits =3D [-1.0,1.0,1,0.1]
raw_zones =3D [[-1.0,0.0,'r'],[0.0,0.5,'y'],[0.5,1.0,'g']]
attribute_name =3D "Rx MOS (24h)"
=20
graph_height =3D 1.6
graph_width =3D 2.4
fig_height =3D graph_height
fig_width =3D graph_width
fig =3D figure( figsize=3D(fig_width, fig_height) )
=20
rect =3D [(0.0/fig_width), (0.2/fig_height),
(graph_width/fig_width), (graph_height/fig_height)]
=20
gauge =3D Gauge(fig, rect,
xlim=3D( -0.1, graph_width+0.1 ),
ylim=3D( -0.4, graph_height+0.1 ),
xticks=3D[],
yticks=3D[],
)
gauge.set_axis_off()
fig.add_axes(gauge)
show()
fig.canvas.print_figure('gauge',dpi=3D72)
=20
'''
=20
|