2012年09月22日

【Matplotlib】温度とFAN回転率解析「ipmiSensor9.py」リリース

 「HP ProLiantサーバー ML110 G7の各温度とFAN回転率推移解析の為に手掛けた「ipmiSensor」作成で必要な「Matplotlib」上の機能について一通り理解出来たので、一つの区切りとして、ここに掲載公開する。
 「Matplotlib」は例えば時系列の副目盛のラベルの回転や、主目盛との併記時の位置合わせ等の様に、オブジェクトに入れ子で包含される個別のインスタンスに対しメソッドを実行することで変更が可能になるものもあり、かゆい処に手が届く様になるには、相応に実行で生成されるインスタンスのクラス構造をマニュアル等で調べ包含されるオブジェクトのメソッドを知ることが不可欠となる。「ipmiSensor.py」では、それらの処理を関数内に組込み、「Matplotlib」の仕様を認識しなくとも、その引数に値を指定するだけで望みの見栄えを追求出来る様に努めている。その仕様は未だ汎用化には程遠い出来だが任意の時系列期間をレンジとして、その期間内に含まれるDB上のデータを折れ線グラフとしてプロットする用途に限定すれば、それ程不自由しない程度にはなったと思う。
 尚、ソースコードの既定の変数を変更せずとも、コマンドオプションとして数値と文字列であれば変数に指定することも出来る。但し、セキュリティ的視点での制限は一切加えていないので今後は適宜変数個別に展開して行く方が望ましいだろう。因みにグラフ化する時系列範囲はstartとendで、凡例の゜配置や列数をl_locationとl_colで指定すると以下の様になる。



[root@www mire]# date; ./ipmiSensor9.py start="2012-09-19 05:55:01" end="2012-09-22 05:55:01" l_col=8 l_location="lower center"
2012年 9月 22日 土曜日 00:13:41 JST
l_col=8
l_location=lower center
HP_ProLiant_ML110_G7_Sensors_Graph_2012-09-19_055501__2012-09-22_001001
2012-09-22 05:55:01
2012-09-19 05:55:01
tm_range= 3 days, 0:00:00
1日〜3日: 1日〜3日: 副目盛は毎時の「時」表示
処理時間: 0:00:03.862130
[root@www mire]#
「HP ProLiant ML110 G7 FANと温度(via ipmi & lm_sensors)」2012-09-19 05:55:01〜2012-09-22 05:55:01

 さて、現状はその程度だが、今後はこの「ipmiSensor.py」のコードは、長期の時系列範囲のグラフは、crondのスクリプトとして定期作成する形で、時々刻々変わる当日分についてはCGIスクリプトとして、Webアクセス時に作成する形で活用することにする。そこで現在は全定義関数を同一ソースコードに置いているが、今後は共通定義分をモジュールとしてsite-packagesに置き、それを各スクリプト側でimportする形の利用となる予定だ。

 「ipmiSensor9.py」のソースコードは以下の通り。(2012-09-22追記: 0.0.9a 凡例背景等の透明度設定を追加した。)
            ~/ipmiSensor9.py (前半)


#!/usr/bin/python2.6
#!/usr/bin/python2.6
#-*- coding: utf-8 -*-
u"""
スクリプト利用
===============

ipmitool sensorで得られるセンサー値をDBにcrondで蓄積、グラフ化


定義関数群
==========

:sensors() : ipmitool sensorで得られるセンサー値を辞書として数値listで返す関数
:prn_sensors() : ipmitool sensorのデータをコンソール出力(sensors()動作check用)
:names_dic() : センサーIDに対する表示名の辞書を返す関数
:query_datas() : DB上のDataを読込む関数
:ins_db() : ipmitool sensor で得られるセンサー値をDBに書込むモジュール
:mk_graph() : DB上のDataをグラフ化する関数
:set_ticks_label(): 目盛ラベルの各種設定値の変更


グラフ化可能な時系列の範囲
==========================

西暦100年1月1日0時〜9900年12月31日23時59分59秒

:datetime.datetime() : 西暦 1年1月1日 〜 9999年12月31日
:datetime.strptime() : 西暦1000年1月1日 〜 9999年12月31日
:自作strptime()関数 : 西暦 1年1月1日 〜 9999年12月31日(未使用)
:Firebird timestamp型: 西暦 100年1月1日 〜 32768年 2月29日
:matplotlib/dates.py : 西暦 100年1月1日 〜 9900年12月31日 """

__author__ = "Mire in Japan"
__date__ = "2012-09-22"
__version__ = '0.0.9a'
__copyright__ = 'Copyright (c) 2012-07-27 Mire'
__license__ = 'GPL'
__url__ = 'http://pythonlife.seesaa.net/article/293580501.html '

__todo__ = u"""
1. 済: 取り敢えず、crondで定期的にDBにぶち込んだデータを取出しグラフ化する初期バージョンを作成
2. 済: DB,pythonコード処理でどの程度速度的に有利かを比較し最適なものを採用: id個別queryとする!!
3. 済: OpenIPMI-python活用によるメリットを探る: ん、探しあてたsampleも動かぬ。深追いせず(笑)。
4. 生成グラフX軸の時系列目盛を期間により多段で変更する様に
5. NET-SNMPの情報活用を附加
6. NET-SNMP-python活用によるメリットを探る
7. RRD的なデータ処理附加の検討
8. Ninoの様なシステム化の可能性を探る"""
__history__ = """
0.0.7 2012-08-25 【機能拡張】期間による目盛間隔の自動調整(副目盛の活用)
Y軸目盛線とグラフ秒が重なる場合に副目盛間隔一つ分進める
【初期設定】ほぼ全ての埋込み初期設定値を関数の引数に変更しカプセル化
グラフ出力期間をstartとendのコマンドオプションで指定可能に
【処理改善】DB Connectionを大元で生成、関数の引数渡しとし生成負荷を低減
0.0.8 2012-09-20 【機能改善】生成グラフX軸の時系列目盛を期間により適切に変更する様に
目盛ラベルの各種設定値の変更を関数化
【障害対策】指定センサーの一部または全てにデータが無い場合の対処加筆
【コメント】mireのpythonコード恒例通り、ほぼ全行コメントで埋め尽くした。
【初期設定】単純な数値と文字列変数についてコマンドオプションで指定可能に
0.0.9 2012-09-21 【Clean Up】Blog掲載制限回避の為、コメントや不要な記述を整理
0.0.9a 2012-09-22 【機能拡張】画像背景色と透明度、凡例背景の透明度設定を追加"""

def sensors():
u"""
ipmitool sensor で得られるセンサー値を
辞書として数値リストで返す関数
"""
from os import popen
# ipmitool sensor > /tmp/result_of_ipmitool_sensor.txt を実行
result_txt = "/tmp/result_of_ipmitool_sensor.txt"
cmd_ipmi_Sensor = "ipmitool sensor > %s" % (result_txt)
pp = popen(cmd_ipmi_Sensor, 'r')
pp.close()

# /tmp/result_of_ipmitool_sensor.txt を
#linesに読込み
fpi = open(result_txt, "r")
lines = fpi.readlines()
fpi.close()

# 各行をリストにして、itemsリストに挿入する
items=[]
for l in lines:
#print l,
itms = l.split('|')
#print itms
item = []
for itm in itms:
i = itm.strip()
try:
i = float(i)
except:
#print 'Error:', item
pass
if i == 'degrees C':
i = u'°C'
elif i == 'unspecified':
i = '%'
elif i == 'discrete':
i = u' '
elif i == 'na':
i = 'N/A'
elif i == 'nc':
i = '(NC)'
elif i == '0x0':
i = 0
item.append(i)
items.append(item)
#print items
#itemname, value, unit, na, na, na, threshold, critical
#makes item files or stdout for other management system
Sensor = {}
for itm in items:
Sensor[itm[0]] = itm[1:]
return Sensor

def prn_sensors():
u"""
ipmitool sensorのデータをコンソール出力
"""
# 関数Sensors()を実行し、項目: 値 単位を表示 ℃
datas = sensors()
#print datas
keys = datas.keys()
keys.sort()
item_name = ('測定項目', '測定値', '単位', '判定', '閾値', '危急')
print '%-24s: %-10s %-4s %-8s %-9s %-9s' % item_name
for k in keys:
s = '%-20s:' % ('\''+k+'\'')
try:
s = s + ' %7.3f' % (datas[k][0])
except:
s = s + ' %-7s' % (datas[k][0])
try:
s = s + ' %-4s %-6s %7.3f %7.3f' % (datas[k][1], datas[k][2]
, datas[k][7], datas[k][8])
except:
s = s + ' %-4s %-6s %7s %7s' % (datas[k][1], datas[k][2]
, datas[k][7], datas[k][8])
print s

def ins_db(datas, now, dsn='127.0.0.1:default.fdb'
, user='SYSDBA', password='pass', charset='UTF-8'):
u"""
ipmtool sensorの吐くデータと測定日時をDB書込み
"""
import fdb # Firebird接続にfdbを活用
conn = fdb.connect(dsn=dsn, user=user, password=password, charset=charset)
cur = conn.cursor()
#print 'datas=', datas
skeys = datas.keys()
skeys.sort()
for key in skeys:
sql_select_id = 'SELECT SENSOR_ID FROM SENSOR WHERE SENSOR_NAME=\'%s\';'
#print key
cur.execute(sql_select_id % (key))
sensor_id = cur.fetchone()
if sensor_id:
sql_ins='INSERT INTO SENSOR_LOG (YMD_HMS, SENSOR_ID, SVALUE) VALUES (\'%s\', %d, %f);'
try:
cur.execute(sql_ins % (now, sensor_id[0], datas[key][0]))
conn.commit()
except:
print 'Error: %s ,%s, %s, %s' % (sql_ins, now, sensor_id[0], datas[key][0])
conn.close()

def names_dic(dsn='127.0.0.1:default.fdb', user='SYSDBA', password='pass'
, charset='UTF-8', conn=None, cur=None):
u"""
センサーIDに対する表示名の辞書を返す関数
"""
names={}
import fdb # Firebird接続にfdbを活用
if cur==None:
if conn==None:
conn = fdb.connect(dsn=dsn, user=user, password=password, charset=charset)
create_conn_in_func = True
else:
create_conn_in_func = False
cur = conn.cursor()
else:
create_conn_in_func = False
sql_qry = 'SELECT a.SENSOR_ID, a.SENSOR_NAME, a.DISP_NAME FROM SENSOR a'
cur.execute(sql_qry)
datas = cur.fetchall()
if create_conn_in_func==True:
conn.close()
for data in datas:
names[data[0]]=data[-1]
return names

def query_datas(sensor_ids=[], dsn='127.0.0.1:default.fdb', user='SYSDBA', password='pass'
, charset='UTF8', start='', end='', conn=None, cur=None, debug=0):
u"""
DB上のDataを読込む関数
"""
import fdb # Firebird接続にfdbを活用
from datetime import datetime
if debug>0:
st = datetime.now()
if cur==None:
if conn==None:
conn = fdb.connect(dsn=dsn, user=user, password=password, charset=charset)
create_conn_in_func = True
else:
create_conn_in_func = False
cur = conn.cursor()
else:
create_conn_in_func = False

if len(sensor_ids)==1: # 単一IDのwhere条件なら
sql_qry = """SELECT b.YMD_HMS, b.SVALUE FROM SENSOR a
LEFT OUTER JOIN SENSOR_LOG b ON a.SENSOR_ID=b.SENSOR_ID
WHERE a.SENSOR_ID=%d""" % (sensor_ids[0]) + """%s%s
ORDER BY b.YMD_HMS;"""
elif len(sensor_ids)>1: # 複数IDのwhere条件有りなら、IDを附加したqueryで全て一括取得
wheres=[]
for id in sensor_ids:
wheres.append('a.SENSOR_ID=%d' % (id))
whereis=' or '.join(wheres)
sql_qry = """SELECT b.YMD_HMS, b.SVALUE, b.SENSOR_ID FROM SENSOR a
LEFT OUTER JOIN SENSOR_LOG b ON a.SENSOR_ID=b.SENSOR_ID
WHERE %s""" % (whereis) + """%s%s
ORDER BY b.YMD_HMS;"""
else: # IDのwhere条件無しなら
sql_qry = """
SELECT b.YMD_HMS, b.SVALUE FROM SENSOR a
LEFT OUTER JOIN SENSOR_LOG b ON a.SENSOR_ID=b.SENSOR_ID
WHERE %s%s
ORDER BY b.YMD_HMS;"""
if not len(start.strip())==0:
ws = ' and b.YMD_HMS>=\'%s\'' % (start)
else:
ws = ''
if not len(end.strip())==0:
we = ' and b.YMD_HMS<=\'%s\'' % (end)
else:
we =''
#print sql_qry % (sensor_ids, ws, we)
cur.execute(sql_qry % (ws, we))
datas = cur.fetchall()
if create_conn_in_func==True:
conn.close()
if debug>0:
et = datetime.now()
print 'query_datas():', et - st
return datas

def set_graph_params(subplot, major_format=None, minor_format=None
, major_locator='day', major_by=None, major_interval=1, major_bymonthday=1
, minor_locator='hour', minor_by=None, minor_interval=1, minor_bymonthday=1
, yearmonth=1, yearday=1, tz=None

, major_label=None
, major_fontcolor=None, major_fontsize=None, major_fontfamily=None
, major_fontstyle=None, major_fontstretch=None, major_fontweight=None
, major_rotation=None, major_dy=0, major_horizontalalignment=None
, major_verticalalignment=None

, minor_label=None
, minor_fontcolor=None, minor_fontsize=None, minor_fontfamily=None
, minor_fontstyle=None, minor_fontstretch=None, minor_fontweight=None
, minor_rotation=None, minor_dy=0, minor_horizontalalignment=None
, minor_verticalalignment=None

, lines_width=None, markers_size=None
):
u""""
目盛設定を行なう関数
主副目盛に指定の時系列LocatorとDateFormatterの各引数を指定し設定
* 目盛ラベル文字列が不要な場合はNoneのままで
*
"""
import matplotlib.dates as mdates #日時様式[for DateFormatter,HourLocator, etc...]

if not major_format==None:
subplot.xaxis.set_major_formatter(mdates.DateFormatter(major_format)) #主目盛ラベル様式
if not minor_format==None:
subplot.xaxis.set_minor_formatter(mdates.DateFormatter(minor_format)) #副目盛ラベル様式

if major_by==None: #主目盛のlistによる間隔指定がないなら、intervalで間隔指定を優先
if major_locator=='second':
subplot.xaxis.set_major_locator(mdates.SecondLocator(interval=major_interval, tz=tz))
elif major_locator=='minute':
subplot.xaxis.set_major_locator(mdates.MinuteLocator(interval=major_interval, tz=tz))
elif major_locator=='hour':
subplot.xaxis.set_major_locator(mdates.HourLocator(interval=major_interval, tz=tz))
elif major_locator=='day':
subplot.xaxis.set_major_locator(mdates.DayLocator(interval=major_interval, tz=tz))
elif major_locator=='month':
subplot.xaxis.set_major_locator(mdates.MonthLocator(bymonthday=major_bymonthday
, interval=major_interval, tz=tz))
elif major_locator=='year':
subplot.xaxis.set_major_locator(mdates.YearLocator(base=major_interval
, month=yearmonth, day=yearday, tz=tz))
else: #そうでないなら、major_byのlistによる間隔指定を優先
if major_locator=='second':
subplot.xaxis.set_major_locator(mdates.SecondLocator(bysecond=major_by
, interval=1, tz=tz))
elif major_locator=='minute':
subplot.xaxis.set_major_locator(mdates.MinuteLocator(byminute=major_by
, interval=1, tz=tz))
elif major_locator=='hour':
subplot.xaxis.set_major_locator(mdates.HourLocator(byhour=major_by
, interval=1, tz=tz))
elif major_locator=='day':
subplot.xaxis.set_major_locator(mdates.DayLocator(bymonthday=major_by
, interval=1, tz=tz))
elif major_locator=='month':
subplot.xaxis.set_major_locator(mdates.MonthLocator(bymonth=major_by
, bymonthday=major_bymonthday
, interval=1, tz=tz))
elif major_locator=='year': #yearではmajor_byは無いが、馬鹿避けで重複記載
subplot.xaxis.set_major_locator(mdates.YearLocator(base=major_interval
, month=yearmonth, day=yearday, tz=tz))

if minor_by==None: #副目盛のlistによる間隔指定がないなら、intervalで間隔指定を優先
if minor_locator=='second':
subplot.xaxis.set_minor_locator(mdates.SecondLocator(interval=minor_interval, tz=tz))
elif minor_locator=='minute':
subplot.xaxis.set_minor_locator(mdates.MinuteLocator(interval=minor_interval, tz=tz))
elif minor_locator=='hour':
subplot.xaxis.set_minor_locator(mdates.HourLocator(interval=minor_interval, tz=tz))
elif minor_locator=='day':
subplot.xaxis.set_minor_locator(mdates.DayLocator(interval=minor_interval, tz=tz))
elif minor_locator=='month':
subplot.xaxis.set_minor_locator(mdates.MonthLocator(bymonthday=minor_bymonthday
, interval=minor_interval, tz=tz))
elif minor_locator=='year':
subplot.xaxis.set_minor_locator(mdates.YearLocator(base=minor_interval
, month=yearmonth, day=yearday, tz=tz))
else: #そうでないなら、minor_byのlistによる間隔指定を優先
if minor_locator=='second':
subplot.xaxis.set_minor_locator(mdates.SecondLocator(bysecond=minor_by
, interval=1, tz=tz))
elif minor_locator=='minute':
subplot.xaxis.set_minor_locator(mdates.MinuteLocator(byminute=minor_by
, interval=1, tz=tz))
elif minor_locator=='hour':
subplot.xaxis.set_minor_locator(mdates.HourLocator(byhour=minor_by
, interval=1, tz=tz))
elif minor_locator=='day':
subplot.xaxis.set_minor_locator(mdates.DayLocator(bymonthday=minor_by
, interval=1, tz=tz))
elif minor_locator=='month':
subplot.xaxis.set_minor_locator(mdates.MonthLocator(bymonth=minor_by
, bymonthday=minor_bymonthday, interval=1, tz=tz))
elif minor_locator=='year': #yearではminor_byは無いが、馬鹿避けで重複記載
subplot.xaxis.set_minor_locator(mdates.YearLocator(base=minor_interval
, month=yearmonth, day=yearday, tz=tz))
set_ticks_label(ticks=subplot.xaxis.get_major_ticks(), label=major_label
, dy=major_dy, rotation=major_rotation
, fontcolor=major_fontcolor, fontsize=major_fontsize
, fontfamily=major_fontfamily, fontstyle=major_fontstyle
, fontweight=major_fontweight, fontstretch=major_fontstretch
, horizontalalignment=major_horizontalalignment
, verticalalignment=major_verticalalignment)
set_ticks_label(ticks=subplot.xaxis.get_minor_ticks(), label=minor_label
, dy=minor_dy, rotation=minor_rotation
, fontcolor=minor_fontcolor, fontsize=minor_fontsize
, fontfamily=minor_fontfamily, fontstyle=minor_fontstyle
, fontweight=minor_fontweight, fontstretch=minor_fontstretch
, horizontalalignment=minor_horizontalalignment
, verticalalignment=minor_verticalalignment)
if not lines_width==None:
## 各要素のマーカーSizeと線幅を太くし視認性を高める ##
lines = subplot.get_lines()
if not markers_size==None:
for l in lines:
l.set_markersize(markers_size)
l.set_linewidth(lines_width)
else:
for l in lines:
l.set_linewidth(lines_width)
else:
if not markers_size==None:
lines = subplot.get_lines()
for l in lines:
l.set_markersize(markers_size)

def set_ticks_label(ticks, label=1, dy=0, rotation=None
, fontcolor=None, fontsize=None #, fontproperties=None
, fontfamily=None, fontstyle='normal'
, fontweight='normal', fontstretch='normal'
, horizontalalignment=None, verticalalignment=None):
u"""
目盛ラベルの各種設定値の変更
(ここで必要なもののみコーディング。目盛ラベルに対する全てを網羅してはいない)
【使い方】
ticks = subplot.xaxis.get_major_ticks()
chgtick(ticks=ticks, label=1, color=None, verticalalignment)
"""
from matplotlib.font_manager import FontProperties
ticks_font = FontProperties(family='times new roman', style='normal'
, size=12, weight='normal', stretch='normal')

for tick in ticks:
if label==2: #適用対象がlabel1なら
ticklabel=tick.label2 # tick.label2
else: #それ以外は
ticklabel=tick.label1 # tick.label2
if not fontsize==None:
tick.label.set_fontsize(fontsize) #目盛ラベル文字列の文字Size
if not fontcolor==None:
ticklabel.set_color(fontcolor) #目盛ラベル文字列の文字色
if not fontfamily==None:
tick.label.set_fontproperties(FontProperties(family=fontfamily #目盛ラベル文字列の
, style=fontstyle, weight=fontweight, stretch=fontstretch)) #フォントプロパティ
if not verticalalignment==None: #目盛ラベル文字列の
ticklabel.set_verticalalignment(verticalalignment) #垂直方向の位置合わせ
if not horizontalalignment==None: #xdate_horizontal_alignment()
ticklabel.set_horizontalalignment(horizontalalignment) #が優先され無効
if not rotation==None:
ticklabel.set_rotation(rotation) #目盛ラベル文字列の傾け角
if not dy==0: #Y座標を増減し主目盛ラベルの
ticklabel.set_position([0, dy]) #配置を縦方向にずらす
            ~/ipmiSensor7.py (後半)


def mk_graph(sensor_ids, names ##【必須】センサーIDのリスト, センサー名(凡例に記載) ##
, start, end ##【必須】対象データのDBクエリ範囲とグラフの全時系列範囲 ##
## 【必須】DB接続 ##
, conn=None, cur=None #DBコネクション、カーソル(以下のdsn user passwordに優先)
, dsn='l127.0.0.1:dedault.fdb', user='SYSDBA' #DB接続dsn、DB接続ユーザ
, password='pass', charset='UTF-8' #DB接続パスワード、DB接続既定文字コード

, exec_show_method=False #pyplot.show()メソッド実行の有無
, fname='HP_ProLiant_ML110_G7_Sensors_Graph_' #コピペ用期間付ファイル名のヘッダ文字列
, saving_name='/var/www/ipmi/graph' #保存ファイル名
, figure_size=(12, 6) #figureオブジェクトの画像Size
#ファイル書出の既定値100dpiは1200x600に
, f_color='white' #figure背景色:facecolor
, f_alpha=None #figure背景の透明度
, s_color='white'M
, s_alpha='None'
, styles=['', '', '', '', '', '', '', '' #各グラフ要素の様式をリスト指定
, '', '', '', '', '', '', '', ''
, '', '', '', '', '', '', '', '', '', '']
, colors=[] #各グラフ要素の色指定
#マーカー
, markersize=0.8 #大きさ
, markeredgecolor=None #輪郭色
, markeredgewidth=0.0 #輪郭線幅
, linewidth=0.2 #折れ線の太さ

, rcParams={'font.size': 9} #Matplotlib既定値を修正
#表題
, title=u'' #文字列
, title_size=14 #Size
, title_font='/usr/share/fonts/ipa-pgothic/ipagp.ttf' #フォント
#X軸ラベル
, xlabel=u'' #文字列
, xlabel_size=10 #Size
, xlabel_font='/usr/share/fonts/ipa-pgothic/ipagp.ttf' #フォント
#X軸時系列文字列
, xdate_rotation=90 #傾斜角
, xdate_horizontal_alignment='center' #位置合わせ
#X軸ラベル
, ylabel=u'' #文字列
, ylabel_size=10 #Size
, ylabel_font='/usr/share/fonts/ipa-pgothic/ipagp.ttf' #フォント
#主目盛補助線
, g_major = True #表示
, g_major_linestyle = ':' #線種
, g_major_linewidth = 0.2 #太さ
, g_major_linecolor = 'b' #色
, major_interval=1 #間隔
#副目盛補助線
, g_minor = True #表示
, g_minor_linestyle = ':' #線種
, g_minor_linewidth = 0.15 #太さ
, g_minor_linecolor = 'c' #色
, minor_interval=6 #間隔
#軸線幅
, bottom_linewidth=1 #下
, left_linewidth=1 #左
, top_linewidth=0.1 #上
, right_linewidth=0.1 #右
#余白調整位置
, bottom=0.01, top=0.955, left=0.035, right=0.99 #下、上、左、右
#凡例
, l_location='lower left' #配置
, l_title=u'' #表題文字列
, l_title_size=8 #表題文字Size
, l_title_font='/usr/share/fonts/ipa-pgothic/ipagp.ttf' #表題文字フォント
, l_bgcolor='None' #背景色
, l_bgalpha=None #凡例背景の透明度
, l_linewidth=0.3 #外枠線幅
, l_size=7 #文字Size
, l_font='/usr/share/fonts/ipa-pgothic/ipagp.ttf' #文字フォント
, l_col=4 #列数
, l_columnspacing=0.2 #列間余白
, l_labelspacing=0.0 #間余白
, l_markersizes=[None] #凡例内マーカーSize
, l_linewidths=[None] #凡例内折れ線幅
, debug=0):
u"""
DB上のDataをグラフ化する関数
指定必須なのは、グラフ化するデータを記録したFiredird DBへの接続と

"""
import fdb # Firebird接続にfdbを活用

from datetime import datetime #時間軸はdatetime.datetime()オブジェクトで渡す
from datetime import timedelta
import matplotlib
if not exec_show_method: #show()メソッドを使わないなら
matplotlib.use('Agg') #お呪いを唱える

import matplotlib.pyplot as plt #グラフ描画
import matplotlib.font_manager as fmng #利用Font指定
import matplotlib.dates as mdates #日時表示様式設定
from matplotlib.ticker import AutoMinorLocator, MultipleLocator
import numpy as np
import pylab
matplotlib.ticker.AutoMinorLocator()
minorLocator = AutoMinorLocator()

if cur==None:
if conn==None:
conn = fdb.connect(dsn=dsn, user=user, password=password, charset=charset)
create_conn_in_func = True
else:
create_conn_in_func = False
cur = conn.cursor()
else:
create_conn_in_func = False

## figureオブジェクト生成 ##
figure = plt.figure(figsize=figure_size, facecolor=f_color) #Size色指定でfigureオブジェクト生成
if not f_alpha==None:
figure.patch.set_alpha(f_alpha) #画像背景の透明度
#figure.subplots_adjust(left=left, bottom=bottom #余白調整(※bottomは
# , right=right, top=top) #作図後でないと有効にならない)

## figureに一つのsubplotを配置し ##
subplot = figure.add_subplot(111) #figureに一つだけグラフを配置
## if not s_alpha==None: #グラフ背景の透明度
## subplot.patch.set_alpha(s_alpha) #saving()で例外発生

## そのsubplotグラフの軸線の太さ調整 ##
subplot.spines['top'].set_linewidth(top_linewidth) #上
subplot.spines['right'].set_linewidth(right_linewidth) #右
subplot.spines['bottom'].set_linewidth(bottom_linewidth) #下
subplot.spines['left'].set_linewidth(left_linewidth) #左

## データ時系列の最大最小値→X軸ラベルに記載 ##
earliest = datetime(9999, 12, 31, 23, 59, 59, 999999) #min比較用初期値
latest = datetime(100, 1, 1, 0, 0, 0, 0) #max比較用初期値

latest_values = [] #最終のセンサー値→凡例内に併記

## そのsubplotのグラフにプロット ##
# DBに対し対象全ID個別にデータ取得し処理
s = 0 #センサー個別の表示スタイルリスト用添字
for sensor_id in sensor_ids: # センサーを一つずつ個別に処理
datas = query_datas(sensor_ids=[sensor_id], dsn=dsn, user=user
, password=password, charset=charset, start=start, end=end
, conn=conn, cur=cur)
if len(datas)>0:
earliest = min(datas[0][0], earliest) # 最初の測定日時
latest = max(datas[-1][0], latest) # 最終の測定日時
#A.素直に処理すると
#dtim = [] #測定日時list for plot
#vals = [] #センサー値list for plot
#for data in datas: #データを一つずつ取出し
# dtim.append(data[0]) #日時データをdtimリストに追加
# vals.append(data[1]) #測定値をvalsリストに追加
#B.numpyを使うと3行(別解)
arr = np.array(datas) #データをアレイ化し
dtim = arr[:,0] #第1列全てを測定日時list「dtim」でリスト参照
vals = arr[:,1] #第2列全てをセンサー値list「vals」でリスト参照
plt.plot(dtim, vals, styles[s], lw=linewidth #個別に指定スタイルでプロット
, ms=markersize, mec=markeredgecolor, mew=markeredgewidth)
#, dashes=(LINE_WIDTH, LINE_WIDTH))
latest_values.append(vals[-1]) #最終センサー値取得
else:
print u'id=', sensor_id, u'のデータはありませんでした。'
s += 1 #センサー個別の表示スタイルリスト用添字

if (earliest==datetime(9999, 12, 31, 23, 59, 59, 999999)
or latest==datetime(100, 1, 1, 0, 0, 0, 0)):
print u'グラフ化するデータが1つも存在しませんでした。\nグラフ作成を中止しました。'
return
## 出力ファイル名向け文字列の生成と表示(コピペ活用用) ##
if debug>0:
fname = fname + '%04d-%02d-%02d_%02d%02d%02d_' % earliest.timetuple()[:6]
fname = fname + '_%04d-%02d-%02d_%02d%02d%02d' % latest.timetuple()[:6]
print fname

if create_conn_in_func==True:
conn.close()

## グラフ目盛のピッチをグラフ化期間により自動調整 ##
tm_range = latest - earliest #実データのプロット期間
if debug>0:
print end
print start

en = datetime.strptime(end, '%Y-%m-%d %H:%M:%S')
st = datetime.strptime(start, '%Y-%m-%d %H:%M:%S')
tm_range = en - st
tick_len = matplotlib.rcParams['ytick.major.size'] #目盛線の長さ(いくらか係数をかける必要が)
dpi = matplotlib.rcParams['savefig.dpi'] #画像ファイル上のインチ当りのドット数
x_len = int(figure_size[0] * dpi * (right - left)) - tick_len * 2 #目盛線を重ねないX軸長
tm_len = tm_range * (matplotlib.rcParams['ytick.major.size'] + 1) // x_len #目盛線相等時間逆算

#xm = latest + tm_len #最尾データに目盛線を加味したX軸長の総時間
xm = datetime.strptime(end, '%Y-%m-%d %H:%M:%S') + tm_len #end日時に目盛線を加味したX軸総時間
#※end指定がない場合はendは現在時が既定となるので稼働中は最尾データ+5分以内がX軸長の総時間の基礎
#となり実用上それ程の不具合はないと考えたので「latest + tm_len」をこれに置替えた

xn = datetime.strptime(start, '%Y-%m-%d %H:%M:%S') - tm_len #作図するグラフのX座標の開始値
plt.xlim(xmin=xn, xmax=xm) #作図するグラフのX座標の範囲を設定

## Y軸目盛間隔を固定 ##
subplot.yaxis.set_major_locator(MultipleLocator(10)) #主目盛は10度間隔に
subplot.yaxis.set_minor_locator(MultipleLocator(5)) #副目盛は 5度間隔に

## 既定の引数による軸様式 ##
figure.autofmt_xdate(rotation=xdate_rotation #x軸の主目盛ラベルの時系列文字列を斜め/垂直回転
, ha=xdate_horizontal_alignment) #水平方向のx軸の主目盛ラベルの時系列文字列揃え
#※ ここでの設定は何故かx軸の主目盛ラベルにしか及ばない様だ。
# 副目盛ラベルは、「subplot.xaxis.get_minor_ticks()」のリスト内のtickに対し、個別に
# 「tick.label1.set_rotation(30)」の様にloop処理で対処する。
#  ここで設定した既定の引数による軸様式も主目盛ラベルも、同様の手法で表示位置等を
# 変更調整が出来る。その実例は以下の時系列範囲別の最適化で活用し記述している。
#  尚、個別での変更調整を行なう場合は、この記述をそれより前に記述する必要があり、
# もし後述してしまうと、個別での変更調整が既定の軸様式に上書きされてしまい
# コーディングの意図を実現しない処理となってしまう。


## 要素の線色を設定リストcolorsの値に置替 ##
if len(colors)>0: #リストcolorsに指定色が一つでもあれば
lines = subplot.get_lines() # グラフから線を取得し
c = 0 # colorsの添字を0にしてから
r = len(colors) - 1 # リストcolorsの色数から最大添字を取得#added 2012-09-10
for l in lines: # グラフ要素の線を1つずつ
if not colors[c]==None: # 指定がNoneで無い限り
l.set_color(colors[c]) # グラフ要素にcolorsでの指定色を順に設定
#colorsの定義色数が少ない場合はcを0にリセットしてcolorsを循環設定 #added 2012-09-10
if c0:
print u'10秒以内: 副目盛は1秒置きの「秒」形式表示'
set_graph_params(subplot=subplot
, major_format=u'%H:%M' #主目盛ラベルに「時:分」形式の様式を
, minor_format=u'%S' #副目盛ラベルに「秒」形式の様式を
, major_locator='minute' #主目盛は分単位に
, major_interval=major_interval #主目盛間隔は既定のmajor_intervalに従う
, minor_locator='second' #副目盛は秒単位に
, minor_interval=minor_interval #副目盛間隔は既定のminor_intervalに従う
, major_label=1 #主目盛対象ラベルはlabel1
, major_dy=-0.019 #主目盛ラベルを縦方向に-0.019ずらす
, major_fontcolor='b' #主目盛ラベル文字色を青に
, major_horizontalalignment='right' #主目盛ラベルを右寄せ配置
, major_rotation=30 #主目盛ラベルを30度傾斜
, lines_width=0.3 #各要素の線幅を太くし視認性を高める
, markers_size=2.3) #各要素のマーカーSizeを大きく
right = right - 0.0096 #X軸副目盛ラベルではみ出す分グラフの横幅縮小
elif tm_range<=timedelta(0, 0, 0, 0, 1):
if debug>0:
print u'11秒〜1分以内: 副目盛は5秒置きの「秒」形式表示'
set_graph_params(subplot=subplot
, major_format=u'%H:%M' #主目盛ラベルに「時:分」形式の様式を
, minor_format=u'%S' #副目盛ラベルに「秒」形式の様式を
, major_locator='minute' #主目盛は分単位に
, major_interval=major_interval #主目盛間隔は既定のmajor_intervalに従う
, minor_locator='second' #副目盛は秒単位に
, minor_by= [0, 5, 10, 15, 20, 25, 30
, 35, 40, 45, 50, 55] #X軸副目盛の時間表示する時間をリストで
, minor_interval=minor_interval #副目盛間隔は既定のminor_intervalに従う
, major_label=1 #主目盛対象ラベルはlabel1
, major_dy=-0.019 #主目盛ラベルを縦方向に-0.019ずらす
, major_fontcolor='b' #主目盛ラベル文字色を青に
, major_horizontalalignment='right' #主目盛ラベルを右寄せ配置
, major_rotation=30 #主目盛ラベルを30度傾斜
, lines_width=0.3 #各要素の線幅を太くし視認性を高める
, markers_size=2.3) #各要素のマーカーSizeを大きく
right = right - 0.0096 #X軸副目盛ラベルではみ出す分グラフの横幅縮小
elif tm_range<=timedelta(0, 0, 0, 0, 0, 1):
if debug>0:
print u'1分〜1時間以内: 副目盛は1分置きの「分」形式表示'
set_graph_params(subplot=subplot
, major_format=u'%Hh' #主目盛ラベルに「時h」形式の様式を
, minor_format=u'%M' #副目盛ラベルに「分」形式の様式を
, major_locator='hour' #主目盛は時単位に
, major_interval=major_interval #主目盛間隔は既定のmajor_intervalに従う
, minor_locator='minute' #副目盛は分単位に
, minor_interval=minor_interval #副目盛間隔は既定のminor_intervalに従う
, major_label=1 #主目盛対象ラベルはlabel1
, major_dy=-0.019 #主目盛ラベルを縦方向に-0.019ずらす
, major_fontcolor='b' #主目盛ラベル文字色を青に
, major_horizontalalignment='right' #主目盛ラベルを右寄せ配置
, major_rotation=30 #主目盛ラベルを30度傾斜
, lines_width=0.3 #各要素の線幅を太くし視認性を高める
, markers_size=2.3) #各要素のマーカーSizeを大きく
right = right - 0.0096 #X軸副目盛ラベルではみ出す分グラフの横幅縮小
bottom = bottom - 0.009
elif tm_range<=timedelta(0, 0, 0, 0, 0, 6):
if debug>0:
print u'6時間以内: 副目盛は5分置きの「分」形式表示'
set_graph_params(subplot=subplot
, major_format=u'%Hh' #主目盛ラベルに「時h」形式の様式を
, minor_format=u'%M' #副目盛ラベルに「分」形式の様式を
, major_locator='hour' #主目盛は時単位に
, major_interval=major_interval #主目盛間隔は既定のmajor_intervalに従う
, minor_locator='minute' #副目盛は分単位に
, minor_by= [0, 5, 10, 15, 20, 25, 30
, 35, 40, 45, 50, 55] #X軸副目盛の時間表示する時間をリストで
, minor_interval=minor_interval #副目盛間隔は既定のminor_intervalに従う
, major_label=1 #主目盛対象ラベルはlabel1
, major_dy=-0.019 #主目盛ラベルを縦方向に-0.019ずらす
, major_fontcolor='b' #主目盛ラベル文字色を青に
, major_fontweight=10 #主目盛ラベル文字色を青に
, major_horizontalalignment='right' #主目盛ラベルを右寄せ配置
, major_rotation=30 #主目盛ラベルを30度傾斜
, lines_width=0.3 #各要素の線幅を太くし視認性を高める
, markers_size=2.3) #各要素のマーカーSizeを大きく
right = right - 0.0096 #X軸副目盛ラベルではみ出す分グラフの横幅縮小
bottom = bottom - 0.009
elif tm_range<=timedelta(0, 0, 0, 0, 0, 12):
if debug>0:
print u'12時間以内: 副目盛は10分置きの「分」形式表示'
set_graph_params(subplot=subplot
, major_format=u'%Hh' #主目盛ラベルに「時h」形式の様式を
, minor_format=u'%M' #副目盛ラベルに「分」形式の様式を
, major_locator='hour' #主目盛は時単位に
, major_interval=major_interval #主目盛間隔は既定のmajor_intervalに従う
, minor_locator='minute' #副目盛は分単位に
, minor_by= [0, 10, 20, 30, 40, 50] #X軸副目盛の時間表示する時間をリストで
, minor_interval=minor_interval #副目盛間隔は既定のminor_intervalに従う
, major_label=1 #主目盛対象ラベルはlabel1
, major_dy=-0.019 #主目盛ラベルを縦方向に-0.019ずらす
, major_fontcolor='b' #主目盛ラベル文字色を青に
, major_horizontalalignment='right' #主目盛ラベルを右寄せ配置
, major_rotation=30 #主目盛ラベルを30度傾斜
, lines_width=0.3 #各要素の線幅を太くし視認性を高める
, markers_size=2.3) #各要素のマーカーSizeを大きく
right = right - 0.0096 #X軸副目盛ラベルではみ出す分グラフの横幅縮小
bottom = bottom - 0.009
elif tm_range<=timedelta(1):
if debug>0:
print u'12時間〜1日以内: 副目盛は毎時の「00:00」形式表示'
set_graph_params(subplot=subplot
, major_format=u'%m/%d' #主目盛ラベルに「月/日」形式の様式を
, minor_format=u'%H:%M' #副目盛ラベルに「時:分」形式の様式を
, major_locator='day' #主目盛は日単位に
, major_interval=major_interval #主目盛間隔は既定のmajor_intervalに従う
, minor_locator='hour' #副目盛は時単位に
, minor_interval=minor_interval #副目盛間隔は既定のminor_intervalに従う
, major_label=1 #主目盛対象ラベルはlabel1
, major_dy=-0.019 #主目盛ラベルを縦方向に-0.019ずらす
, major_fontcolor='b' #主目盛ラベル文字色を青に
, major_horizontalalignment='right' #主目盛ラベルを右寄せ配置
, lines_width=0.3 #各要素の線幅を太くし視認性を高める
, markers_size=2.3) #各要素のマーカーSizeを大きく
right = right - 0.0096 #X軸副目盛ラベルではみ出す分グラフの横幅縮小
bottom = bottom + 0.006 #X軸主目盛表示がはみ出す分グラフ領域の縦幅を縮小
elif tm_range<=timedelta(3):
if debug>0:
print '1日〜3日: 副目盛は毎時の「時」表示'
set_graph_params(subplot=subplot
, major_format=u'%m/%d' #主目盛ラベルに「月/日」形式の様式を
, minor_format=u'%H' #副目盛ラベルに「時」形式の様式を
, major_locator='day' #主目盛は日単位に
, major_interval=major_interval #主目盛間隔は既定のmajor_intervalに従う
, minor_locator='hour' #副目盛は時単位に
, minor_interval=minor_interval #副目盛間隔は既定のminor_intervalに従
, major_dy=-0.019 #主目盛ラベルを縦方向に-0.019ずらす
, major_fontcolor='b' #主目盛ラベル文字列色を青に
, major_horizontalalignment='right' #主目盛ラベルを右寄せ配置
, lines_width=0.3 #各要素の線幅を太くし視認性を高める
, markers_size=2.3) #各要素のマーカーSizeを大きく
right = right - 0.002 #X軸副目盛ラベルではみ出す分グラフの横幅縮小
bottom=bottom + 0.002 #X軸主目盛表示がはみ出す分グラフ領域の縦幅を縮小
elif tm_range<=timedelta(9):
if debug>0:
print '4日〜9日: 副目盛は3時間置きの「時」表示'
set_graph_params(subplot=subplot
, major_format= u'%m/%d' #主目盛ラベルに「月/日」形式の様式を
, minor_format= u'%H' #副目盛ラベルに「時」形式の様式を
, major_locator= 'day' #主目盛は日単位に
, major_interval= major_interval #主目盛間隔は既定のmajor_intervalに従う
, minor_locator= 'hour' #副目盛は時単位に
, minor_by= [0, 3, 6, 9
, 12, 15, 18, 21] #X軸副目盛の時間表示する時間をリストで
, minor_interval= minor_interval #副目盛間隔は既定のminor_intervalに従う
, major_dy=-0.019 #主目盛ラベルを縦方向に-0.019ずらす
, major_fontcolor='b' #主目盛ラベル文字列色を青に
, major_horizontalalignment='right') #主目盛ラベルを右寄せ配置
right = right - 0.002
bottom=bottom + 0.003 #X軸副目盛ラベルではみ出す分グラフの横幅縮小
elif tm_range<=timedelta(17): #7〜100日なら、副目盛の時間表示は刻みのみ
if debug>0:
print '9日〜16日: 副目盛は6時間置きの「時」表示'
set_graph_params(subplot=subplot
, major_format= u'%m/%d' #主目盛ラベルに「月/日」形式の様式を
, minor_format= u'%H' #副目盛ラベルに「時」形式の様式を
, major_locator= 'day' #主目盛は日単位に
, major_interval= major_interval #主目盛間隔は既定のmajor_intervalに従う
, minor_locator= 'hour' #副目盛は時単位に
, minor_by= [0, 6, 12, 18] #X軸副目盛の時間表示する時間をリストで
, minor_interval= minor_interval #副目盛間隔は既定のminor_intervalに従う
, major_dy=-0.019 #主目盛ラベルを縦方向に-0.019ずらす
, major_fontcolor='b' #主目盛ラベル文字列色を青に
, major_horizontalalignment='right') #主目盛ラベルを右寄せ配置
right = right - 0.002 #中寄せ配置の副目盛ラベル
bottom = bottom + 0.003
elif tm_range<=timedelta(33): #7〜100日なら、副目盛の時間表示は刻みのみ
if debug>0:
print '17日〜32日(1ヶ月)間: 副目盛は6時間置きの目盛刻みのみ'
set_graph_params(subplot=subplot
, major_format= u'%m/%d' #主目盛ラベルに「月/日」形式の様式を
, minor_format= None #副目盛ラベルは非表示
, major_locator= 'day' #主目盛は日単位に
, major_interval= major_interval #主目盛間隔は既定のmajor_intervalに従う
, minor_locator= 'hour' #副目盛は時単位に
, minor_by= [6, 12, 18] #X軸副目盛の時間表示する時間をリストで
, minor_interval= minor_interval #副目盛間隔は既定のminor_intervalに従う
, major_fontcolor='b' #主目盛ラベル文字列色を青に
, major_horizontalalignment='center') #主目盛ラベルを中寄せ配置
right = right - 0.008 #主目盛ラベルが30度傾斜の中寄せ配置によるはみ出しを補正
bottom = bottom - 0.012
elif tm_range<=timedelta(65): #7〜100日なら、副目盛の時間表示は刻みのみ
if debug>0:
print '33日〜64日(2ヶ月)間: 副目盛は12時間置きの目盛刻みのみ。「月/日」の90度回転表示'
set_graph_params(subplot=subplot
, major_format= u'%m/%d' #主目盛ラベルに「月/日」形式の様式を
, minor_format= None #副目盛ラベルは非表示
, major_locator= 'day' #主目盛は日単位に
, major_interval= major_interval #主目盛間隔は既定のmajor_intervalに従う
, minor_locator= 'hour' #副目盛は時単位に
, minor_by= [12] #X軸副目盛の時間表示する時間をリストで
, minor_interval= minor_interval #副目盛間隔は既定のminor_intervalに従う
, major_rotation=90
, major_horizontalalignment='center') #主目盛ラベルを中寄せ配置
#### ここからは、 主目盛は月、副目盛は日となっている ####
elif tm_range<=timedelta(101): #7〜100日なら、副目盛の時間表示は刻みのみ
if debug>0:
print '65日〜100日(3ヶ月)間: 主副目盛共に90度傾斜、日毎'
set_graph_params(subplot=subplot
, major_format= u'%m/' #主目盛ラベルに「月/」形式の様式を
, minor_format= u'%d' #副目盛ラベルに「日」形式の様式を
, major_locator= 'month' #主目盛は月単位に
, major_interval= major_interval #主目盛間隔は既定のmajor_intervalに従う
, minor_locator= 'day' #副目盛は日単位に
, minor_by= None #X軸副目盛の時間表示する時間をリストで
, minor_interval= minor_interval #副目盛間隔は既定のminor_intervalに従う
, major_dy=-0.028 #主目盛ラベル「月/」を縦方向にずらす
, major_rotation=90
, major_fontcolor='b' #主目盛ラベル文字列色を青に
, major_horizontalalignment='center' #主目盛ラベルを中寄せ配置
, minor_rotation=90)
elif tm_range<=timedelta(200): #101〜200日なら、
if debug>0:
print '101〜200日: 主目盛=月, 副目盛=3日置き'
set_graph_params(subplot=subplot
, major_format= '\'%y/%m' #主目盛ラベルに「月/日」形式の様式を
, minor_format= '%d' #副目盛ラベルに「時」形式の様式を
, major_locator= 'month' #主目盛は月単位に
, major_interval= major_interval #主目盛間隔は既定のmajor_intervalに従う
, minor_locator= 'day' #副目盛は日単位に
, minor_by= [1, 6, 11, 16, 21, 26]#X軸副目盛の時間表示する時間をリストで
, minor_interval= minor_interval #副目盛間隔は既定のminor_intervalに従う
, major_dy=-0.019 #主目盛ラベル「年/月」を縦方向にずらす
, major_fontcolor='b' #主目盛ラベル文字列色を青に
, major_horizontalalignment='right') #主目盛ラベルを右寄せ配置
bottom = bottom + 0.006
elif tm_range<=timedelta(366): #201〜366日(1年)なら
if debug>0:
print u'201〜366日: 主目盛=月, 副目盛=5日置き'
set_graph_params(subplot=subplot
, major_format= '%m/%d' #主目盛ラベルに「月/日」形式の様式を
, minor_format= '%d' #副目盛ラベルに「時」形式の様式を
, major_locator= 'month' #主目盛は月単位に
, major_interval= major_interval #主目盛間隔は既定のmajor_intervalに従う
, minor_locator= 'day' #副目盛は日単位に
, minor_by= [6, 11, 16, 21, 26] #X軸副目盛の時間表示する時間をリストで
, minor_interval= minor_interval #副目盛間隔は既定のminor_intervalに従う
, major_rotation=90 #主目盛ラベルを90度傾斜
, major_fontcolor='b' #主目盛ラベル文字列色を青に
, major_horizontalalignment='center' #主目盛ラベルを中寄せ配置
, minor_rotation=90) #副目盛ラベルを90度傾斜
elif tm_range<=timedelta(731): #366日(1年)〜731日(2年)迄なら
if debug>0:
print u'366日(1年)〜731日(2年): '
set_graph_params(subplot=subplot
, major_format= u'\'%y/%m/%d' #主目盛ラベルに「'年/月/日」形式の様式を
, minor_format= '%d' #副目盛ラベルに「日」形式の様式を
, major_locator= 'month' #主目盛は月単位に
, major_interval= major_interval #主目盛間隔は既定のmajor_intervalに従う
, minor_locator= 'day' #副目盛は日単位に
, minor_by= [11, 21] #X軸副目盛の時間表示する時間をリストで
, minor_interval= minor_interval #副目盛間隔は既定のminor_intervalに従う
, major_rotation=90 #主目盛ラベルを90度傾斜
, major_fontcolor='b' #主目盛ラベル文字列色を青に
, major_horizontalalignment='center' #主目盛ラベルを中寄せ配置
, minor_rotation=90) #副目盛ラベルを90度傾斜
bottom = bottom + 0.036
#### ここからは、 主目盛は年、副目盛は月となっている ####
elif tm_range<=timedelta(2200): #732〜2200日(6年)迄なら
if debug>0:
print '732〜2200日(6年): '
set_graph_params(subplot=subplot
, major_format= u'%Y' #主目盛ラベルに「年」形式の様式を
, minor_format= '%m' #副目盛ラベルに「月」形式の様式を
, major_locator= 'year' #主目盛は年単位に
, major_interval= major_interval #主目盛間隔は既定のmajor_intervalに従う
, minor_locator= 'month' #副目盛は月単位に
, minor_interval= minor_interval #副目盛間隔は既定のminor_intervalに従う
, major_dy=-0.019 #主目盛ラベル「年」を縦方向にずらす
, major_fontcolor='b' #主目盛ラベル文字列色を青に
, major_horizontalalignment='right') #主目盛ラベルを右寄せ配置
elif tm_range<=timedelta(3653): #2201〜3653日(10年)迄なら
if debug>0:
print '2201〜3653日(10年)' #このシステム用途ではこれくらいが本来上限
set_graph_params(subplot=subplot
, major_format= u'%Y' #主目盛ラベルに「年」形式の様式を
, minor_format= '%m' #副目盛ラベルに「月」形式の様式を
, major_locator= 'year' #主目盛は年単位に
, major_interval= major_interval #主目盛間隔は既定のmajor_intervalに従う
, minor_locator= 'month' #副目盛は月単位に
, minor_by= [1, 3, 5, 7, 9, 11] #X軸副目盛の表示する月をリストで
, minor_interval= minor_interval #副目盛間隔は既定のminor_intervalに従う
, major_dy=-0.019 #主目盛ラベル「年」を縦方向にずらす
, major_fontcolor='b' #主目盛ラベル文字列色を青に
, major_horizontalalignment='right') #主目盛ラベルを右寄せ配置
elif tm_range<=timedelta(5845): #3653〜5845日(16年)なら、
if debug>0:
print '3653〜5845日(16年)'
set_graph_params(subplot=subplot
, major_format= u'%Y' #主目盛ラベルに「年」形式の様式を
, minor_format= '%m' #副目盛ラベルに「月」形式の様式を
, major_locator= 'year' #主目盛は年単位に
, major_interval= major_interval #主目盛間隔は既定のmajor_intervalに従う
, minor_locator= 'month' #副目盛は月単位に
, minor_by= [1, 4, 7, 10] #X軸副目盛の表示する月をリストで
, minor_interval= minor_interval #副目盛間隔は既定のminor_intervalに従う
, major_dy=-0.019 #主目盛ラベル「年」を縦方向にずらす
, major_fontcolor='b' #主目盛ラベル文字色を青に
, major_horizontalalignment='right') #主目盛ラベルを右寄せ配置
elif tm_range<=timedelta(11689): #5845日(16年)〜11689日(約32年)
if debug>0:
print u'5845日(16年)〜11689日(約32年)'
set_graph_params(subplot=subplot
, major_format= u'%Y' #主目盛ラベルに「年」形式の様式を
, minor_format= '%m' #副目盛ラベルに「月」形式の様式を
, major_locator= 'year' #主目盛は年単位に
, major_interval= major_interval #主目盛間隔は既定のmajor_intervalに従う
, minor_locator= 'month' #副目盛は月単位に
, minor_by= [1, 7] #X軸副目盛の表示する月をリストで
, minor_interval= minor_interval #副目盛間隔は既定のminor_intervalに従う
, major_dy=-0.019 #主目盛ラベル「年」を縦方向にずらす
, major_fontcolor='b' #主目盛ラベル文字色を青に
, major_horizontalalignment='right') #主目盛ラベルを右寄せ配置
elif tm_range<=timedelta(18263):
if debug>0:
print '11689日(約32年)〜18263日(約50年)'
set_graph_params(subplot=subplot
, major_format= u'%Y' #主目盛ラベルに「年」形式の様式を
, minor_format= None #副目盛ラベルは非表示
, major_locator= 'year' #主目盛は年単位に
, major_interval= major_interval #主目盛間隔は既定のmajor_intervalに従う
, minor_locator= 'month' #副目盛は月単位に
, minor_by= [7] #X軸副目盛の表示する月をリストで
, minor_interval= minor_interval #副目盛間隔は既定のminor_intervalに従う
, major_fontcolor='b' #主目盛ラベル文字色を青に
, major_horizontalalignment='right') #主目盛ラベルを右寄せ配置
elif tm_range<=timedelta(29221):
if debug>0:
print '18263日(約50年)〜29221日(約80年)'
set_graph_params(subplot=subplot
, major_format= u'%Y' #主目盛ラベルに「年」形式の様式を
, minor_format= None #副目盛ラベルは非表示
, major_locator= 'year' #主目盛は年単位に
, major_interval= major_interval #主目盛間隔は既定のmajor_intervalに従う
, minor_locator= 'month' #副目盛は月単位に
, minor_by= [7] #X軸副目盛の表示する月をリストで
, minor_interval= minor_interval #副目盛間隔は既定のminor_intervalに従う
, major_rotation=90 #主目盛ラベルを90度回転
, major_fontcolor='b' #主目盛ラベル文字列色を青に
, major_horizontalalignment='center') #主目盛ラベルを中寄せ配置
elif tm_range<=timedelta(58441): #これ以上は目盛文字が重なるので文字省略
if debug>0:
print '29222日(約80年)〜58441(約160年)'
set_graph_params(subplot=subplot
, major_format= u'%Y' #主目盛ラベルに「年」形式の様式を
, minor_format= None #副目盛ラベルは非表示
, major_locator= 'year' #主目盛は年単位に
, major_interval= 10 #主目盛間隔は10年に
, minor_locator= 'year' #副目盛も年単位に
, minor_interval= 1) #副目盛間隔は1年に
elif tm_range<=timedelta(116877): #これ以上は目盛文字が重なるので文字省略
if debug>0:
print '58441日(約160年)〜116877日(約320年)'
set_graph_params(subplot=subplot
, major_format= u'%Y' #主目盛ラベルに「年」形式の様式を
, minor_format= None #副目盛ラベルは非表示
, major_locator= 'year' #主目盛は年単位に
, major_interval= 10 #主目盛間隔は10年に
, minor_locator= 'year' #副目盛も年単位に
, minor_interval= 2) #副目盛間隔は2年に
elif tm_range<=timedelta(175319): #これ以上は目盛文字が重なるので文字省略
if debug>0:
print '116877日(約320年)〜175319(約480年)'
set_graph_params(subplot=subplot
, major_format= u'%Y' #主目盛ラベルに「年」形式の様式を
, minor_format= None #副目盛ラベルは非表示
, major_locator= 'year' #主目盛は年単位に
, major_interval= 10 #主目盛間隔は10年に
, minor_locator= 'year' #副目盛も年単位に
, minor_interval= 5) #副目盛間隔は5年に
elif tm_range<=timedelta(365243): #1753190):
if debug>0:
print '175319(約480年)〜365243日(約1000年)'
set_graph_params(subplot=subplot
, major_format= u'%Y' #主目盛ラベルに「年」形式の様式を
, minor_format= None #副目盛ラベルは非表示
, major_locator= 'year' #主目盛は年単位に
, major_interval= 100 #主目盛間隔は100年に
, minor_locator= 'year' #副目盛も年単位に
, minor_interval= 10) #副目盛間隔は10年に
elif tm_range<=timedelta(730484):
if debug>0:
print '365242日(約1000年)〜730484日(約2000年)'
set_graph_params(subplot=subplot
, major_format= u'%Y' #主目盛ラベルに「年」形式の様式を
, minor_format= None #副目盛ラベルは非表示
, major_locator= 'year' #主目盛は年単位に
, major_interval= 100 #主目盛間隔は100年に
, minor_locator= 'year' #副目盛も年単位に
, minor_interval= 20) #副目盛間隔は20年に
else:
if debug>0:
print '730484日(約2000年)〜'
set_graph_params(subplot=subplot
, major_format= u'%Y' #主目盛ラベルに「年」形式の様式を
, minor_format= None #副目盛ラベルは非表示
, major_locator= 'year' #主目盛は年単位に
, major_interval= 100 #主目盛間隔は100年に
, minor_locator= 'year' #副目盛も年単位に
, minor_interval= 50 #副目盛間隔は50年に
, major_rotation=90) #主目盛ラベルを90度傾斜

# 100-01-01より前を指定するとsaving()実行時に、matplotlib/dates.py側で
#「ValueError: year is out of range」が発生してしまう。

## 目盛補助線(grid)の有効化と線色、線種、線幅の設定 ##
subplot.grid(b=g_major, which='major', color=g_major_linecolor
, linestyle=g_major_linestyle, linewidth=g_major_linewidth) #グラフ上の主目盛補助線
subplot.grid(b=g_minor, which='minor', color=g_minor_linecolor
, linestyle=g_minor_linestyle, linewidth=g_minor_linewidth) #グラフ上の副目盛補助線

## rcParams辞書でrc既定値を変更 ##
matplotlib.rcParams.update(rcParams) #rcParams辞書でrc既定値変更

## 凡例 ##
name_and_latest_values_in_legend=[] #凡例用文字列リスト
n = min(len(names),len(latest_values)) #一致する長さだけ
for i in range(n): #繰り返し:
name_and_latest_values_in_legend.append( # 「測定値: センサー名」の
'%3.2f: %-s' % (latest_values[i], names[i])) # 文字列をリストに追加
leg = subplot.legend(name_and_latest_values_in_legend # 凡例ラベルのリスト,
, loc=l_location , columnspacing=l_columnspacing#, 左下配置, 列間余白幅
, ncol=l_col, labelspacing=l_labelspacing #, 列数, ラベル行間余白
, prop=fmng.FontProperties(fname=l_font)) #, fontプロパティ を指定
leg_title = leg.get_title() #凡例タイトルオブジェクトに
leg_title.set_fontproperties(fmng.FontProperties(fname=l_title_font))
leg_title.set_fontsize(l_title_size) #文字Sizeとフォントを設定
leg.set_title(title=l_title) #凡例タイトルを設定
leg_frame = leg.get_frame() #frameオブジェクトを取出し
leg_frame.set_facecolor(l_bgcolor) #凡例の背景を消し
if not l_bgalpha==None: #added 2012-09-22 11:43:26
leg_frame.set_alpha(l_bgalpha) #凡例背景の透明度
for t in leg.get_texts(): #凡例要素の文字列全ての
t.set_fontsize(l_size) # 文字Sizeを7に設定
leg_frame.set_linewidth(l_linewidth) #凡例枠線幅を設定
i = 0
for w in leg.legendHandles:
if not l_linewidths[i]==None:
w.set_linewidth(l_linewidths[i]) #リスト指定で凡例線を拡大し視認性を高め判り易く
i += 1
if i>=len(l_linewidths):
exit
i = 0
for lin in leg.get_lines():
if not l_markersizes[i]==None:
lin._legmarker.set_ms(l_markersizes[i]) #リスト指定で凡例マーカーを大きく判り易く
i += 1
if i>=len(l_markersizes):
exit
## グラフ表題を設定 ##
plt.title(title
, fontproperties=fmng.FontProperties(fname=title_font)
, fontsize=title_size) #グラフ表題を設定

## X軸名称 ##
s = '%4d-%02d-%02d %02d:%02d' % earliest.timetuple()[:5] #測定開始日時文字列生成
e = '%4d-%02d-%02d %02d:%02d' % latest.timetuple()[:5] #最終測定日時文字列生成
plt.xlabel(u'%s: %s 〜 %s' % (xlabel, s, e) #x軸名称を設定
, fontproperties=fmng.FontProperties(fname=xlabel_font)
, fontsize=xlabel_size)

## Y軸名称 ##
plt.ylabel(ylabel
, fontproperties=fmng.FontProperties(fname=ylabel_font)
, fontsize=ylabel_size) #y軸名称を設定

## 最後に画像余白を調整してから ##
figure.subplots_adjust(left=left, bottom=bottom
, right=right, top=top) #余白調整(※bottomは描画後実行以外反映不可)

## 画像出力する。 ##
try:
plt.savefig('%s.png' % (saving_name)) #pngファイル保存◎
except:
print 'PNG画像ファイル書出しで失敗しました。'
plt.savefig('%s.png' % (saving_name)) #pngファイル保存◎
try:
plt.savefig('%s.svg' % (saving_name), bbox_inches='tight') #余白除去してsvgファイル保存○
except:
print 'SVG画像ファイル書出しで失敗しました。'
plt.savefig('%s.svg' % (saving_name), bbox_inches='tight') #余白除去してsvgファイル保存○

if exec_show_method:
plt.show() #表示(crond等の自動実行時はコメントに)

if __name__ == "__main__":
import fdb # Firebird接続にfdbを活用
from time import time, localtime # 現地時間取得にtimeモジュール活用
from sys import argv # コマンド引数を活用
from datetime import datetime # 時系列にdatetimeオブジェクトを活用

st = datetime.now() #実行開始日時の取得(debug情報の処理時間の計算用)
dsn = 'localhost:/mnt/XFS4FDB/DB/ipmitool_sensor.fdb' #利用するDBのdsn
user = 'SENSOR' # セキュリティ上、SYSDBAとは別の専用のDBuserを指定
password = 'pass' # 説明上、passwordは埋込みとした。この運用では「実行ソースは外部閲覧厳禁!!」
charset = 'UTF-8' # 表示名称の多言語表記が可能なUTF-8をDBで活用

nw = localtime(time()) # 現在時取得
now = '%04d-%02d-%02d %02d:%02d:%02d' % nw[:6] # 現在時文字列の生成

################################ 測定値をDB書込 ################################
# datas = sensors() ##crond実行分でipmitool sensorの吐くデータの取得
# ins_db(datas=datas, now=now, dsn=dsn ##crond実行分でDB登録
# , user=user, password=password, charset=charset)
################################################################################

############################### 測定値グラフ作成 ###############################
## 設定値代入 ##
# 出力設定 #
debug = 1 #debug情報のコンソール出力
fname = 'HP_ProLiant_ML110_G7_Sensors_Graph_' #コピペ用期間付ファイル名のヘッダ文字列
exec_show_method = False #pyplot.show()メソッド実行の有無
saving_name = '/var/www/ipmi/graph' #保存ファイル名
figure_size = [12, 6] #figureオブジェクトを1200x600で生成
# 共通グラフ要素 #
markersize = 1.8 #0.8 #マーカーSize
markeredgecolor = None #マーカー輪郭線色
markeredgewidth = 0 #マーカー輪郭線幅
linewidth = 0.15 #0.2 #折れ線グラフ線幅
# グラフのタイトル名 #
title = u'HP ProLiant ML110 G7 FANと温度(via ipmi & lm_sensors)'
title_size = 14 #タイトル文字Size
title_font = '/usr/share/fonts/ipa-pgothic/ipagp.ttf' #タイトル文字フォント
# 軸ラベル #
xlabel = u'時間(5分間隔)' #X軸ラベル文字列
xlabel_size=10 #X軸ラベルの文字Size
xlabel_font = '/usr/share/fonts/ipa-pgothic/ipagp.ttf' #X軸ラベルの文字フォント
ylabel = u'温度(°C) / 回転率(%)' #Y軸ラベル
ylabel_size=10 #Y軸ラベルの文字Size
ylabel_font = '/usr/share/fonts/ipa-pgothic/ipagp.ttf' #Y軸ラベルの文字フォント
xdate_rotation = 30 #X軸時系列文字列の回転角度 30度を既定に
xdate_horizontal_alignment = 'center' #X軸時系列文字列の位置合わせ
# 目盛間隔 #
major_interval = 1 #主目盛間隔日数
minor_interval = 1 #副目盛間隔時間数
# 主目盛補助線 #
g_major = True #主目盛補助線(表示)
g_major_linecolor = 'b' #主目盛補助線色(青)
g_major_linestyle = ':' #主目盛補助線線種(点線)
g_major_linewidth = 0.2 #主目盛補助線幅(0.2)
# 副目盛補助線 #
g_minor = True #副目盛補助線(表示)
g_minor_linecolor = 'c' #副目盛補助線色(Cyan)
g_minor_linestyle = ':' #副目盛補助線線種(点線)
g_minor_linewidth = 0.15 #副目盛補助線幅(0.15)
# グラフ軸線幅 #
top_linewidth = 0.1 #グラフ上側軸線幅
right_linewidth = 0.1 #グラフ右側軸線幅
bottom_linewidth = 1 #グラフ下側軸線幅
left_linewidth =1 #グラフ左側軸線幅
# 画像余白調整位置 #
top = 0.955 #上側余白調整位置
right = 0.996 #右側余白調整位置
bottom = 0.102 #下側余白調整位置
left = 0.035 #左側余白調整位置
# 凡例 #
l_location = 'lower center' #凡例配置
l_bgcolor = '#F0F0F0' #凡例の背景色
l_bgalpha = 0.2 #凡例の背景の透明度
l_linewidth = 0.3 #凡例の枠線幅
l_col = 4 #凡例の列数
l_columnspacing = 0.2 #凡例の列間余白
l_labelspacing = 0.0 #凡例行間余白
# 凡例タイトル #
l_title = u'右端値:センサー名(*はlm_sensorsの出力)' #凡例タイトル
l_title_size = 8 #凡例タイトルの文字Size
l_title_font = '/usr/share/fonts/ipa-pgothic/ipagp.ttf' #凡例タイトル文字フォント
l_size = 7 #凡例の文字Size
l_font = '/usr/share/fonts/ipa-pgothic/ipagp.ttf' #凡例の文字フォント
# 凡例対象ID別属性(解像度と視認性を補正する為凡例側は大きく) #
l_linewidths = [0.4, 0.4, 0.4, 0.4 #凡例個別の線幅を指定することで
, None, None, None, None #吸気音とFan回転率のみ折れ線幅を太く
, None, None, None, None
, None, None, None, None]
l_markersizes = [2.3, 2.3, 2.3, 2.3 #凡例個別のマーカーSizeを指定することで
, None, None, None, None #吸気音とFan回転率のみマーカーを大きく
, None, None, None, None
, None, None, None, None]
# グラフ化対象ID: SENSORテーブルのSENSOR_IDリストでグラフ化する要素を指定 ここでは次の16sensor値 #
#ID:SENSOR_NAME [DISP_NAME ] ※
sensor_ids = [1 # 1:01-Inlet Ambient[01吸気温 ]
, 21 #21:Fan 1 [Fan1(背面) ]
, 27 #27:Fan 7 [Fan7(CPU) ]
, 28 #28:Fan 8 [Fan8(前面) ]

, 3 # 3:03-P1 DIMM 1-4 [03メモリDIMM ]
, 4 # 4:04-P1 Mem Zone [04メモリゾーン ]
, 5 # 5:05-P1 Mem Zone [05メモリゾーン ]
, 6 # 6:06-HD Max [06HD Max(50°) ] ※ 固定値を吐く

, 7 # 7:07-VR P1 [07電源]
, 8 # 8:08-VR P1 [08電源(FANかも) ]
, 9 # 9:09-VR P1 Zone [09電源ゾーン ]
, 10 #10:10-VR P1Mem Zone[10電源メモリゾーン]

, 15 #15:15-System Board [15システムボード ]
, 16 #16:16-System Board [16システムボード ]
#, 2 # 2:02-CPU [02CPU(40°) ] ※ 固定値を吐くので
, 40 #40:Core 0 [CPU Core0* ] im_sensorの
, 41] #41:Core 1 [CPU Core1* ] core別温度を採用
#※ 2012-09-20角括弧内は現在の表示用名称(DISP_ANME)の値
# 個別要素スタイル(※ 色はcolorsで決まる仕様にしたのでcolorsがあれば指定しても無意味) #
styles = ['o-', 's-', '^-', 'D-' #グラフ[●■▲◆] ※ 色文字マーカー線種の順でMatplotlibの
, '', '', '', '' #要素の[ ] 定義スタイル文字列で指定する
, '', ',-', '', ',-' #様式 [ ・ ・]
, ',-', '', '', ''] # [・ ]
# 個別要素色 #
colors = ['b', 'r', 'g', '#F4F400' #ここでは要素の色分けを
, 'darkcyan', 'orangered', 'orange', 'yellowgreen' #HTML内表記でより自由に
, 'darkblue', 'black', 'indigo', '#F0F000' #指定する仕様にしている
, 'deepskyblue', 'darkgreen', 'hotpink', 'darkorange']
# 開始終了日時の既定値指定(※ DBクエリで使う時系列条件をここで指定) #
start = '2012-07-08 05:56:08' #query範囲はDB登録以降の日時。
end = now #query範囲は現時点迄とする。

## 引数指定の開始終了日時を取込む ##
if len(argv)>1: #半角スペースで区切って指定した要素があれば
for a in argv[1:]: # スクリプト名を除くargvの要素を一つずつ取出し
try: # 想定内の引数処理なら
key,value = a.split('=') # 各引数に「=」が含まれるなら
if key=='start': # キーが「start」なら
if len(value.split(' '))==1: # 日時の区切りに半角スペースがないなら
start = value + ' 00:00:00' # 時間指定がないとして、00:00:00からに
else: # 時間指定が有りそうなら
start = value # それをそのまま開始日時とする
elif key=='end': # endについても同様に処理
if len(value.split(' '))==1:
end = value + ' 23:59:59' #時間指定がないなら23:59:59迄に
else:
end = value
#以下は「要、セキュリティ考察!!」#
else: #それ以外は取り敢えず性善説に立ちexec文で変数値代入
if debug>0:
print a
try: #数字化可能な値なら
exec '%s=%f' % (key, float(value)) # 浮動小数点値として代入可なら
if not len(value.split('.'))==2: # 小数点の存在しない場合には
exec '%s=%d' % (key, int(value))# 整数値として代入処理
except: #そうでなかったら、
exec '%s=\'%s\'' % (key, value) # 文字列値として代入処理
except: #想定外の引数指定なら、以下のエラーメッセージを表示
print u'startまたはendの後に=を挿み開始または終了の日付を指定して下さい。'
print '例: %s start=\'2012-07-10 13:12:27\' end=2012-08-23' % (argv[0])
## 4桁でない西暦の頭にOを附加補正 ##
s = start.split('-')[0] #開始日時文字列の頭の西暦年の文字列を抽出
leny = len(s) #西暦年の文字列長を取得
if leny<4: #それが4桁未満なら
start = s.zfill(4) + start[leny:] #足りないだけ頭に0を附加補正
if debug>0:
print start, u'0を頭に附加し4桁に補正'
s = end.split('-')[0] #終了日時文字列の頭の西暦年の文字列を抽出
leny = len(s) #西暦年の文字列長を取得
if leny<4: #それが4桁未満なら
end = s.zfill(4) + end[leny:] #足りないだけ頭に0を附加補正
if debug>0:
print end, u'0を頭に附加し4桁に補正'
#※ strptime()で活用する日時format文字列「%Y」は必ず4桁であることを
# 求める性質がある。その為、西暦999年以下の日付文字列はdatetime()に変換
# することが出来ない。1桁の月日時分秒の頭にOを付け2桁書きすることは、
# コンピュータ処理を意識した仕組みから、わりと一般的になっているが、
# 3桁以下の西暦を記入する機会は少なく、0を付加して4桁にしていない場合も
# それを補正して処理を可能にすることにした。

## names_dic()とmk_graph()で必要なfirebirdとのconnectionを親元で生成 ##
conn = fdb.connect(dsn=dsn, user=user, password=password, charset=charset)
cur = conn.cursor()
## mk_graph()のnames引数の生成 ##
name_dic = names_dic(dsn=dsn, user=user, password=password #要素名の辞書を生成
, charset=charset, conn=conn, cur=cur)
names = [] #要素IDに対応する凡例表示名称のリストnameを
for id in sensor_ids: #センサIDの順番で
names.append(name_dic[id]) # 追加生成
## mk_graph()でグラフ作成 ##
mk_graph(sensor_ids=sensor_ids, names=names, start=start, end=end #グラフ作成

, dsn=dsn, user=user, password=password, charset=charset #DB Connection用の引数
, conn=conn, cur=cur #conn, cur指定がdsnに優先

, exec_show_method=exec_show_method #pyplot.show()メソッド実行の有無
, saving_name=saving_name #保存ファイル名
, fname=fname #コピペ用期間付ファイル名のヘッダ文字列
, figure_size=figure_size #figureオブジェクトの画像Size

, styles=styles, colors=colors #各グラフ要素個別の様式,色をリスト指定

, markersize=markersize, markeredgecolor=markeredgecolor #マーカー: 大きさ,輪郭色
, markeredgewidth=markeredgewidth, linewidth=linewidth #マーカー: 輪郭線幅,折れ線幅

, title=title, title_size=title_size, title_font=title_font #表題: 文字列,Size,フォント

, l_location=l_location, l_title=l_title #凡例配置、凡例表題、
, l_title_size=l_title_size, l_title_font=l_title_font #凡例表題文字Size,フォント
, l_bgcolor=l_bgcolor, l_linewidth=l_linewidth #凡例背景色, 外枠線色
, l_bgalpha=l_bgalpha #凡例背景の透明度
, l_size=l_size, l_font=l_font #凡例の文字Size, フォント
, l_col=l_col , l_columnspacing=l_columnspacing #凡例の列数, 列間余白
, l_labelspacing=l_labelspacing #凡例間余白
, l_markersizes=l_markersizes, l_linewidths=l_linewidths #凡例内: マーカーSize,線幅

, xlabel=xlabel, xlabel_size=xlabel_size #X軸ラベル:文字列,Size
, xlabel_font=xlabel_font #,フォント
, ylabel=ylabel, ylabel_size=ylabel_size #Y軸ラベル:文字列,Size
, ylabel_font=ylabel_font #,フォント

, xdate_rotation=xdate_rotation #X軸時系列文字列傾斜角
, xdate_horizontal_alignment=xdate_horizontal_alignment #X軸時系列文字列位置合わせ

, major_interval=major_interval, minor_interval=minor_interval #X軸主/副目盛間隔
, g_major=g_major, g_major_linestyle=g_major_linestyle #主目盛補助線: 表示,線種
, g_major_linewidth=g_major_linewidth # 線幅
, g_major_linecolor=g_major_linecolor # 線色
, g_minor=g_major, g_minor_linestyle=g_minor_linestyle #副目盛補助線: 表示,線種
, g_minor_linewidth=g_minor_linewidth # 線幅
, g_minor_linecolor=g_minor_linecolor # 線色

, bottom_linewidth=bottom_linewidth, top_linewidth=top_linewidth#下軸線幅、上軸線幅
, left_linewidth=left_linewidth, right_linewidth=right_linewidth#左軸線幅、右軸線幅

, bottom=bottom, top=top, left=left, right=right #余白調整位置: 下,上,左,右

, debug=debug)
conn.close() #firebirdとのconnectionを閉じる
if debug>0:
et = datetime.now() #処理終了時刻の取得
tt = et - st #経過時間を計算
print '処理時間:', tt #経過時間を表示
################################################################################

2012-09-22追記: 透明度設定機能を追加。変更差分は以下の通り。



[mire@localhost Blog]$ diff -du ipmiSensor9.py ipmiSensor9a.py
--- ipmiSensor9.py 2012-09-22 19:50:21.000000000 +0900
+++ ipmiSensor9a.py 2012-09-22 18:42:29.000000000 +0900
@@ -32,7 +32,7 @@

__author__ = "Mire in Japan"
__date__ = "2012-09-20"
-__version__ = '0.0.9'
+__version__ = '0.0.9a'
__copyright__ = 'Copyright (c) 2012-07-27 Mire'
__license__ = 'GPL'
__url__ = 'http://pythonlife.seesaa.net/article/293580501.html '
@@ -57,7 +57,8 @@
【障害対策】指定センサーの一部または全てにデータが無い場合の対処加筆
【コメント】mireのpythonコード恒例通り、ほぼ全行コメントで埋め尽くした。
【初期設定】単純な数値と文字列変数についてコマンドオプションで指定可能に
-0.0.9 2012-09-21 【Clean Up】Blog掲載制限回避の為、コメントや不要な記述を整理"""
+0.0.9 2012-09-21 【Clean Up】Blog掲載制限回避の為、コメントや不要な記述を整理
+0.0.9a 2012-09-22 【機能拡張】画像背景色と透明度、凡例背景の透明度設定を追加"""

def sensors():
u"""
@@ -426,6 +427,10 @@
, saving_name='/var/www/ipmi/graph' #保存ファイル名
, figure_size=(12, 6) #figureオブジェクトの画像Size
#ファイル書出の既定値100dpiは1200x600に
+ , f_color='white' #figure背景色:facecolor
+ , f_alpha=None #figure背景の透明度
+ , s_color='white'
+ , s_alpha='None'
, styles=['', '', '', '', '', '', '', '' #各グラフ要素の様式をリスト指定
, '', '', '', '', '', '', '', ''
, '', '', '', '', '', '', '', '', '', '']
@@ -477,6 +482,7 @@
, l_title_size=8 #表題文字Size
, l_title_font='/usr/share/fonts/ipa-pgothic/ipagp.ttf' #表題文字フォント
, l_bgcolor='None' #背景色
+ , l_bgalpha=None #凡例背景の透明度
, l_linewidth=0.3 #外枠線幅
, l_size=7 #文字Size
, l_font='/usr/share/fonts/ipa-pgothic/ipagp.ttf' #文字フォント
@@ -519,13 +525,16 @@
create_conn_in_func = False

## figureオブジェクト生成 ##
- figure = plt.figure(figsize=figure_size) #Sizeを指定しfigureオブジェクトを生成
-
+ figure = plt.figure(figsize=figure_size, facecolor=f_color) #Size色指定でfigureオブジェクト生成
+ if not f_alpha==None:
+ figure.patch.set_alpha(f_alpha) #画像背景の透明度
#figure.subplots_adjust(left=left, bottom=bottom #余白調整(※bottomは
# , right=right, top=top) #作図後でないと有効にならない)

## figureに一つのsubplotを配置し ##
subplot = figure.add_subplot(111) #figureに一つだけグラフを配置
+## if not s_alpha==None: #グラフ背景の透明度
+## subplot.patch.set_alpha(s_alpha) #saving()で例外発生
## そのsubplotグラフの軸線の太さ調整 ##
subplot.spines['top'].set_linewidth(top_linewidth) #上
subplot.spines['right'].set_linewidth(right_linewidth) #右
@@ -1063,6 +1072,8 @@
leg.set_title(title=l_title) #凡例タイトルを設定
leg_frame = leg.get_frame() #frameオブジェクトを取出し
leg_frame.set_facecolor(l_bgcolor) #凡例の背景を消し
+ if not l_bgalpha==None: #added 2012-09-22 11:43:26
+ leg_frame.set_alpha(l_bgalpha) #凡例背景の透明度
for t in leg.get_texts(): #凡例要素の文字列全ての
t.set_fontsize(l_size) # 文字Sizeを7に設定
leg_frame.set_linewidth(l_linewidth) #凡例枠線幅を設定
@@ -1104,11 +1115,14 @@
## 画像出力する。 ##
try:
plt.savefig('%s.png' % (saving_name)) #pngファイル保存◎
+ except:
+ print 'PNG画像ファイル書出しで失敗しました。'
+ plt.savefig('%s.png' % (saving_name)) #pngファイル保存◎
+ try:
plt.savefig('%s.svg' % (saving_name), bbox_inches='tight') #余白除去してsvgファイル保存○
except:
- print '画像ファイル書出しで失敗しました。'
- plt.savefig('/var/www/ipmi/graph.svg', bbox_inches='tight') #余白除去してsvgファイル保存○
- plt.savefig('/var/www/ipmi/graph.png') #pngファイル保存◎
+ print 'SVG画像ファイル書出しで失敗しました。'
+ plt.savefig('%s.svg' % (saving_name), bbox_inches='tight') #余白除去してsvgファイル保存○

if exec_show_method:
plt.show() #表示(crond等の自動実行時はコメントに)
@@ -1185,7 +1199,8 @@
left = 0.035 #左側余白調整位置
# 凡例 #
l_location = 'lower center' #凡例配置
- l_bgcolor = 'None' #凡例の背景色
+ l_bgcolor = '#F0F0F0' #凡例の背景色
+ l_bgalpha = 0.2 #凡例の背景の透明度
l_linewidth = 0.3 #凡例の枠線幅
l_col = 4 #凡例の列数
l_columnspacing = 0.2 #凡例の列間余白
@@ -1320,6 +1335,7 @@
, l_location=l_location, l_title=l_title #凡例配置、凡例表題、
, l_title_size=l_title_size, l_title_font=l_title_font #凡例表題文字Size,フォント
, l_bgcolor=l_bgcolor, l_linewidth=l_linewidth #凡例背景色, 外枠線色
+ , l_bgalpha=l_bgalpha #凡例背景の透明度
, l_size=l_size, l_font=l_font #凡例の文字Size, フォント
, l_col=l_col , l_columnspacing=l_columnspacing #凡例の列数, 列間余白
, l_labelspacing=l_labelspacing #凡例間余白
[mire@localhost Blog]$
posted by Mire at 00:20 | Comment(0) | TrackBack(0) | 自宅サーバ構築管理 | このブログの読者になる | 更新情報をチェックする
この記事へのコメント
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント:

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。
この記事へのトラックバックURL
http://blog.seesaa.jp/tb/293580501
※ブログオーナーが承認したトラックバックのみ表示されます。

この記事へのトラックバック
月額見放題1,000円開始キャンペーンバナー(画像ありver)
紺碧の艦隊 ルパン三世 GREAT CHASE クリックプロモーション
<< 2013年01月 >>
    1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31    
カテゴリ
タグクラウド
ファン
利用中のオープンソース
最近のコメント
最近の記事
過去ログ
QRコード
レガシーなアプリはいかが?
Dell 法人のお客様ページ
  • 【法人様向け】デル、お得なキャンペーン情報
  • 法人のお客様向け ストレージソリューション
  • 法人のお客様向け ネットワークソリューション
  • 【SOHO法人様向け】デル・オンライン広告限定ページ
  • デル-個人のお客様ページ
  • 【個人のお客様向け】デル・オンライン広告限定ページ
  • オンライン広告限定キャンペーンページ
  • ソフトウェア&周辺機器 パソコン工房
    ツートップインターネットショップ(twotop.co.jp) マウスコンピューター/G-Tune
  • ×

    この広告は1年以上新しい記事の投稿がないブログに表示されております。