カテゴリー別アーカイブ: 9.Python

マークデータをDBへ書き込み

Spotfireはデータ分析には非常に便利なのですが、
解析した結果をデータベースに残すことはできません。

結果をエクスポートしてデータベースにInsertする作業は非効率ですし、
複数のツールを行ったり来たりする手間が非常に面倒くさいです。

そんな時にはやはりPython!
一つのインターフェースで様々な機能を実装できるのはすごく便利です。

Spotfireからデータベースに書き込みをする。

Pythonスクリプトを使用して、Spotfireのマーク済みのデータをSQL Serverに書き込んでみました。

使うデータはBaseBallです。
マークした範囲の選手名をSQL Serverのテーブルに書き込みましょう。

1

実行イメージ

このようにサラリーが高いのにホームランをあまり打っていなさそうな人を選択してDBに記録します。

2

ボタンを押すとPythonがSQL ServerにInsertして、処理内容をメッセージボックスで通知します。

3

実行後のテーブルデータ
ちゃんと4人分入っています。

テーブル定義

書き込み先のテーブルはBaseballRecordという名前で
一カラムしかないのですが一応ソースはこちらです。

CREATE TABLE [dbo].[BaseballRecord](
	[Name] [varchar](50) NULL
) ON [PRIMARY]

GO
Pythonコード

データベースの接続情報は環境に合わせて変更してください。

#SQL Server Setting
import clr
clr.AddReference('System.Data')
from System.Data import *
TheConnection = SqlClient.SqlConnection("server=servername;database=database;uid=sa;password=password")
TheConnection.Open()

#MsgBox用
clr.AddReference("System.Windows.Forms")
from System.Windows.Forms import MessageBox

#マークからデータ取得用
from Spotfire.Dxp.Data import DataValueCursor

#マークされた行からデータを抽出
myCursor = DataValueCursor.CreateFormatted(Document.Data.Tables["Baseball"].Columns["Player Name"])
markedRows = Document.Data.Markings["マーク"].GetSelection(Document.Data.Tables["Baseball"]).AsIndexSet()

totalCount = 0 

#SQL Serverへアクセス
for row in Document.Data.Tables["Baseball"].GetRows(markedRows, myCursor):
 print  myCursor.CurrentValue
# 処理SQLの作成と実行
 sqlcmd = "insert into BaseballRecord values ( '" + myCursor.CurrentValue +"')"
 MyAction = SqlClient.SqlCommand( sqlcmd , TheConnection)
 totalCount += MyAction.ExecuteNonQuery()

TheConnection.Close()
MessageBox.Show( str(totalCount) + "人分追加しました。")

挿入処理後にデータテーブルをリフレッシュ

スクリプトを少し改良しました。
Insert対象のBaseballRecordテーブルをデータテーブルとして追加して、
処理後にリロードをするようにしました。
これでボタンを押した後に追加データを確認できます。
スクリプトとしては最初と最後に数行追加したのみです。

4

#テーブルリフレッシュ用に追加
from Spotfire.Dxp.Data import *
from Spotfire.Dxp.Data.Import import *

#SQL Server Setting
import clr
clr.AddReference('System.Data')
from System.Data import *
TheConnection = SqlClient.SqlConnection("server=servername;database=database;uid=sa;password=password")
TheConnection.Open()

#MsgBox用
clr.AddReference("System.Windows.Forms")
from System.Windows.Forms import MessageBox

#マークからデータ取得用
from Spotfire.Dxp.Data import DataValueCursor

#マークされた行からデータを抽出
myCursor = DataValueCursor.CreateFormatted(Document.Data.Tables["Baseball"].Columns["Player Name"])
markedRows = Document.Data.Markings["マーク"].GetSelection(Document.Data.Tables["Baseball"]).AsIndexSet()

totalCount = 0 

#SQL Serverへアクセス
for row in Document.Data.Tables["Baseball"].GetRows(markedRows, myCursor):
 print  myCursor.CurrentValue
# 処理SQLの作成と実行
 sqlcmd = "insert into BaseballRecord values ( '" + myCursor.CurrentValue +"')"
 MyAction = SqlClient.SqlCommand( sqlcmd , TheConnection)
 totalCount += MyAction.ExecuteNonQuery()

TheConnection.Close()
MessageBox.Show( str(totalCount) + "人分追加しました。")

# Refresh table
Document.Data.Tables["BaseballRecord"].Refresh()

起動時にPython起動

起動時にPython起動

何回かにわたり記事を書いてきましたが、今回で一区切りです。
今回は起動時にPythonを起動する方法をご紹介します。

Python連携
Pythonスクリプトの入出力
閾値を超えた場合にメール送信
基準値の変更時にスクリプトを実行

SpotfireのPythonは「ボタンを押す」「プロパティ変更時」などのタイミングで起動しますが、ファイルを開いたときに起動するオプションはありません。

しかし、いくつかの機能を組み合わせることで実現可能です。

前回プロパティからPythonを起動させました。なので、起動時にプロパティを変更する事ができれば良いですね。

起動時に実行可能なスクリプトとしてはTERRがあります。
TERRからプロパティを変更する事ができるので、連携でPythonを実行します。

<全体のイメージ図>
9

TERRによるプロパティの更新

まずはプロパティを設定します。
curTimeというDatatime型のプロパティを作成し、メール送信スクリプトを設定しました。

2

このプロパティが変更される度にPythonスクリプトが実行されます。
TERRスクリプトは起動時に実行されるので、データロード時にチェック操作を行うことが可能です。

データ関数の登録

TERRスクリプトはデータ関数として登録します。
「ツール」→「データ関数の登録」で

名前はGetCurTimeとし

スクリプトは

print ( sysdate ) 
OutCurTime <- Sys.time()

sysdateを受け取って、OutCurTimeを返すスクリプトです。

3

パラメータの入力でDatatime型のsysdateを設定
4

出力パラメータでOutCurTimeを設定します。
5

右上のアイコンから実行します。
6

実行パラメータ

TERRの引数と戻り値を設定します。
入力のsysdateは引数として「式」でDateTimeNow()を指定します。

これでシステム日付けを渡しています。
7

出力は
OutCurTimeを文章のプロパティでcurTimeとして受け取るよう設定します。
「関数を自動的に更新」チェックボックスもONにしておいてくださいね。
8

これでDXPファイルを開く時にスクリプトが実行されます。

基準値の変更時にスクリプトを実行

前回の記事では基準値を設定して測定がそれをオーバーした際に
Pythonからメールを送信する例を紹介しました。

それはそれで便利なのですが、
条件判別のために都度ボタンを押す必要があり、いまいち利便性に欠けます。

Spotfireではプロパティの変更をトリガーとしてPythonスクリプトを起動する事ができるのでこちらの設定をしてみましょう。

この閾値を変更した際にPythonを実行したい。
1

プロパティにPythonを登録

「編集」から「ドキュメントのプロパティ」を選択し
「プロパティ」タブを開きます。

2
ファイル内のプロパティ一覧が表示されています。
3列目に「スクリプト」とあり、Pythonが設定されている場合は
ここに表示されます。

今回はPTPara1MaxLimitというプロパティが変更された時にPythonを起動します。
「スクリプト」ボタンを押して起動時の条件を設定します。

3

この設定はボタンから実行する場合と同じです。

4
設定完了です。
これで閾値を変更した際にPythonが実行されるようになります。

閾値を超えた場合にメール送信

Pythonでメール送信

前回の続きです。

データ分析の結果、異常条件や閾値を判別できるようになります。

その結果をリアルタイムのデータに当てはめ、
同様の条件が発生した場合にアラートとしてメールで通知できると便利です。
Pythonを使用したサンプルを作成してみました。

外部ライブラリの取り込み

Pythonのsmtplibライブラリを使ってメール送信します。
このライブラリを使用すると簡単にメール送信ロジックを実装できるのですが、
残念なことにSpotfireのironPythonには含まれていませんので
pythonを別途インストールしそちらのライブラリを読み込みます。

手順は普通のPythonと同じです。

import clr
import sys
paths = 'C:\Python25\Lib'
sys.path.append ( paths ) 

pythonのバージョンですが、
SpotfireのPythonと合わせるために2.5を使用しました。

Gailを使用してメール送信

今回のサンプルではsmtpサーバーとしてgmailを使用しています。
あらかじめgoogleのアカウント情報から
ログインとセキュリティの「安全性の低いアプリの許可」を有効化する必要があります。

1

ソースはこちら

※ログイン情報はご自分の物に書き換えてください。

# coding: UTF-8 #文字コード設定
# -*- coding: utf-8 -*-

import clr
import sys
paths = 'C:\Python25\Lib'
sys.path.append ( paths ) 

import smtplib
from email.MIMEText import MIMEText
from email.header import Header
from email import charset
from email.Utils import formatdate

#メールを作成
def create_message(from_addr, to_addr, subject, body):
    cset = 'iso-2022-jp'
    msg  = MIMEText(body.encode(cset), 'plain' , cset )
    msg['Subject'] =  Header ( subject.encode(cset) ,cset ) 
    msg['From']    = from_addr
    msg['To']      = to_addr
    msg['Date']    = formatdate()
    return msg

#メールを送信
def send_gmail(from_addr, to_addr, msg):
    s = smtplib.SMTP('smtp.gmail.com', 587)
    s.ehlo()
    s.starttls()
    s.ehlo()
    s.login('xxxxxxxxxxxxx@gmail.com', 'xxxxxxxxxx')
    s.sendmail(from_addr, [to_addr], msg.as_string())
    s.close()

#----------------
#  specValue(閾値)がtheValue(測定値)を超えている場合はメール送信
#    from_addr : メール送信元( gmailの場合は認証アドレスが指定される )
#    to_addr   : メール送信先
#    Title     : 件名
#    Body      : 本文
#    specValue : 設定値
#    theValue  : 測定値
#----------------

if ( specValue < theValue ) :
    msg = create_message(from_addr, to_addr, Title, Body )
    send_gmail(from_addr, to_addr, msg)

送信先アドレスやメールタイトルと本文
閾値と測定値はそれぞれパラメータとして入力できるようにしてありますので
from_addr , to_addr , Title , Body , specValue , theValueの値をプロパティなり
計算式で設定してください。

Pythonスクリプトの入出力

Pythonスクリプトの入出力に関して

前回、Pythonを使用してメッセージボックスを表示しましたが、
実際に使用する場合はSpotfireからデータを渡したり、Pythonの結果をSpotfireに戻したりする処理が必要になってくることが多いと思います。

今回は入出力のサンプルとして、プロパティの値やカスタム演算式の値をPythonに渡して、
結果をプロパティで受け取りましょう。

やりたい事

まずこのようなグラフがあるとします。
1

途中に大きな外れ値が発生しているようです。
このようなイレギュラーなデータが発生した場合に何かの処理を追加します。

プロパティの作成

プロパティの作成は必須ではないですが、
インタラクティブな操作と非常に相性がいいので使用頻度が多いです。

2

ドキュメントプロパティを新規に作成して上限値を入力し、
それを元に閾値のラインを引くようにしました。
プロパティ名はULで
5.2だとこの辺で、

3

6.0だとここまでです。

1.5

プロパティの作成は、テキストエリアの編集画面で「プロパティコントロールの挿入」で「入力フィールド」を選択します。

1.7

新規作成で今回はULという名前のReal型プロパティを作成します。
初期値は5にしておきます。
これでテキストエリアで入力する事ができるようになります。

18

ちなみに作成したULに連動したラインをチャートに引く場合は
プロパティの「線およびカーブ」から「追加」→「水平線」→「直線」
でカスタム演算式を選択して${UL}のプロパティを指定します。

1.8

Pythonへのインプット

閾値を超えている場合をPythonで判別して、テキストエリアの表示を変更しましょう。
前回作成したPythonを流用します。
ボタンとして埋め込まれているPythonをダブルクリックして編集します。

4

パラメータ設定
プロパティの渡し方

まずはプロパティ変数として上限の閾値を設定します。
スクリプトのパラメータで「追加」を選択
名前は「upperLimit」値は「プロパティ」でULを指定します。
これでSpotfireのULプロパティをPython側ではupperLimitとして扱えます。

6

次は平均値を集計して渡します。
名前はmaxValで、式は「式の編集」から入力する事ができます。
こちらはカスタム演算式で設定します。

8

メッセージボックスで表示する内容を変更してみました。
パラメータとして渡されているulvalとmaxValを使用しています。

9

import clr
clr.AddReference("System.Windows.Forms")
from System.Windows.Forms import MessageBox
MessageBox.Show( "上限閾値は" + str(ulval) + " 最大値は " + str(maxVal) ) 

Pythonへの入力はパラメータを使用しますが、出力はこちらではできません。
今回は新規プロパティを作成し、それをPythonで書き換えましょう。
プロパティを変更する事ができれば、計算カラムやカスタム演算式の内容や、テキストエリアの中身など様々な変更が可能になります。

結果プロパティの作成

テキストエリアの編集から「プロパティの作成」でラベルを選択します。

10

pythonOutputという名前のString型のプロパティを作成しました。
初期値は”デフォルト”にしてみました。

11

作成すると”デフォルト”というラベルがテキストエリアに表示されています。

12

ドキュメントプロパティの変更

再度Pythonを編集します
プロパティをPythonから変更するには
Document.Properties[‘property name’] = ‘変更したい内容’
というAPIを使用します。

今回は分岐で上限値を超えている場合は’閾値オーバー’を表示します。

15

import clr
clr.AddReference("System.Windows.Forms")
from System.Windows.Forms import MessageBox
outputStr = ""

if ulval > maxVal :
	outputStr = ( "閾値オーバー:上限閾値は" + str(ulval) + " 最大値は " + str(maxVal) ) 
else:
	outputStr = ( "上限閾値は" + str(ulval) + " 最大値は " + str(maxVal) ) 

Document.Properties['pythonOutput'] = outputStr

結果です。今回は閾値に引っかかったので、閾値オーバーになっています。

16

閾値をオーバーしない場合の実行結果です。

17

次回は閾値を超えた時にメール送信するようにしてみます。

Python連携

Python連携初歩の初歩

Python連携に関して

Pyrhonとは汎用のインタプリタ言語で、Spotfireだけで無く、多くのプラットフォームで動作します。
日本ではそれほどメジャーではないかもしれませんが、多くのライブラリを持っており、データ分析をお手軽に実装するのにはかなり便利な言語です。

Spotfireに搭載されているPythonはironPythonというWindowsと親和性の高いディストリビューションになっております。
Pythonを使用することにより、ライブラリを使用した解析や、外部ツールとの連携など、Spotfireの分析をより有効活用できます。

Pythonの実装

それではテキストエリアのボタンにPythonを実装して見ましょう。
クリックで”Hello Python”というメッセージボックスを表示するのが今回のゴールです。

テキストエリアの作成と実行

1

新規のテキストエリアを作成します。

2

右クリックし、テキストエリアを編集。

3

Pythonスクリプトは「アクションコントロール」というカテゴリになりますので、
アクションコントロールの挿入アイコンをクリックします。

4

表示テキストにはボタンに表示したい文言を記載します。
左の選択項目から「スクリプト」を選択し「新規」をクリックしてください。

ちなみにアクションコントロールはPython以外にもR言語を埋め込んだり、
他のページへ移動するボタンなども作成する事ができます。
左から「データ関数」を選択した場合はR言語
「アクション」を選択した場合はページ移動や、ブックマークの実行を指定できます。

5

スクリプトを記載していきます。
「スクリプト名」に”helloPython”
「スクリプト」には下記のスクリプトを記載してください。

import clr
clr.AddReference("System.Windows.Forms")
from System.Windows.Forms import MessageBox
MessageBox.Show("hello Python")

最初の3行はWindowsのメッセージボックスを表示するのに必要な設定です。
逆に言うとこれらの設定を色々することでWindowsの機能や他のライブラリの機能が簡単に実装できるようになっています。

5.5

ちなみに超見ずらいですが「出力」の右の隠れたボタンをクリックすると
この場で動作させることが可能です。
日本語に翻訳した際にレイアウト崩れたのでしょうか?

6

これでスクリプトは完成したので、保存して編集画面を閉じます。

7

ボタンを押すと”hello Python”とメッセージウインドウが表示されました。

お疲れさまでした。
今回はさわりですが、次回からPythonとの入出力や、他のライブラリを使用した例を紹介していきたいと思います。

その他

Spotfireで登録したPythonはDXPファイル内に保存されています。
「文書のプロパティ」から「スクリプト」で一覧を確認できますので、
こちらから編集することも可能です。
7.5

テキストエリア以外にもPythonを設定する事が可能です。
グラフィカルテーブルの軸や、文書のプロパティに設定する事ができますので、
プロパティの値が変更されたときに自動的にスクリプトを実行することもできます。

8

9