ソフトウェア/Igor のバックアップ差分(No.4)

更新


  • 追加された行はこの色です。
  • 削除された行はこの色です。
[[公開メモ]]

#contents

* Igor とは [#k3f1dcd4]

データ解析に Wave Metrics 社の Igor Pro を使っています。

なかなか癖のあるソフトですが、
Igor 上でプログラムを組むことでかなり複雑なデータ解析も自動化できていろいろ捗ります。

ここには使い回しの効きそうなコード例を上げていこうと思います。

公式のオンラインヘルプはこちら:
http://www.hulinks.co.jp/support/igor/programming/index.html

* 分野別記事へのリンク [#cb75dc8d]

#ls2("ソフトウェア/Igor")

* あるグラフ上に表示されたウェーブの一覧を表示する [#n02b667a]
* Igor のマルチスレッド対応 [#w13d601c]

Igor Pro 6.1 から、マルチスレッド対応が強化されたそうです。

 LANG:Igor
 string graph_name = "Graph1"
 string traces = TraceNameList(graph_name, ";", 1)
 variable i
 for(i = ItemsInList(traces) - 2; i>=0; i-=1)
     print StringFromList(i, traces)
 endfor
 wave0 = any_expression(x)

画像の一覧なら、TraceNameList ではなく ImageNameList を呼べばいい。
のような代入文で時間がかかっている場合、

 LANG:Igor
 string graph_name = "Graph1"
 string images = ImageNameList(graph_name, ";", 1)
 variable i
 for(i = ItemsInList(images) - 2; i>=0; i-=1)
     print StringFromList(i, images)
 endfor
 MultiThread wave0 = any_expression(x)

* グラフウィンドウ上の選択領域を得る [#d6fd38cf]
とするだけで、個々の座標値に対する計算を異なるスレッドで行ってくれます。

グラフ上をマウスで斜めにドラッグすると矩形領域を選べますが、
この範囲を Igor では Marquee と呼んでいます。
当然、wave の個々の座標の値の間に依存関係がある場合にはうまくいきませんが、
独立に計算できる場合にはこれだけでかなり速度が上がります。

使用例
** より高度なマルチスレッド [#fe54477c]

 LANG:Igor
 // 与えられた座標がグラフの選択領域に含まれているかどうか返す
 function IsPointInSelectedRegion(x, y)
 variable x, y
 
     string graph_name = "Graph1"
 
     struct Rectangle selected_region
     GetMarqueeRegion(graph_name, selected_region)
 
     return IsPointInRect(x, y, selected_region)
 end
もっと複雑なことをしたい場合には、
ThreadGroupCreate / ThreadStart / ThreadGroupPutDF / 
ThreadGroupGetDF / ThreadGroupWait / ThreadGroupRelease 
といった関数を使うことで、きめ細やかなマルチスレッド制御を行えます。

コード
実際やってみると、メモリ確保などに時間がかかっていることも多いようで、
単純にスレッド数倍もの速度向上は望めませんが、シングルスレッド比で
2倍くらいの速度は簡単に出せるようでした。

 LANG:Igor
 // 矩形領域を格納するための構造体
 Structure Rectangle
     double left
     double right
     double top
     double bottom
 EndStructure
 
 // 指定された名前のグラフから選択範囲を得る
 // 選択されていなければ全範囲 (left, bottom 軸で) を返す
 function GetMarqueeRegion(graph_name, region)
 string graph_name
 Struct Rectangle &region
 
     GetMarquee/W=$graph_name left, bottom
     if(!V_Flag)
         GetAxis/q/W=$graph_name bottom
         V_Left   = V_min
         V_Right  = V_max
         GetAxis/q/W=$graph_name left
         V_Top    = V_min
         V_Bottom = V_max
     endif
 
     region.left = V_Left
     region.right = V_Right
     region.top = V_Top
     region.bottom = V_Bottom
 end
 
 // x, y で指定された点が rect 領域に入っているかどうかを返す 
 function IsPointInRect(x, y, rect)
 variable x, y
 Struct Rectangle &rect
     variable result
     result = rect.left <= x
     result = x <= rect.right   && result
     result = rect.top <= y     && result
     result = y <= rect.bottom  && result
     return result
 end
例えば、Intel Core i7-3520M @ 2.9GHz + Windows 7 (64bit) 
で 1024 本のスペクトルに対して解析を行った結果、

* グラフ上の選択範囲を設定する [#dcd89a94]
- シングルスレッド = 11.0 秒
- マルチスレッド = 4.3秒

SetMarquee を使えばいいのですが、単位をポイントに直さなければならないので、
PixelFromAxisVal と ScreenResolution を呼んで変換します。
という結果が得られました。

コード

 LANG:Igor
 // 下軸、左軸の値を指定してグラフの選択範囲を設定する
 function image_mouseup(x1, y1, x2, y2)
 variable x1, y1, x2, y2
     x1 = PixelFromAxisVal("image", "bottom", x1) / ScreenResolution * 72
     x2 = PixelFromAxisVal("image", "bottom", x2) / ScreenResolution * 72
     y1 = PixelFromAxisVal("image", "left", y1) / ScreenResolution * 72
     y2 = PixelFromAxisVal("image", "left", y2) / ScreenResolution * 72
     SetMarquee/w=image, x1, y1, x2, y2
 end


Counter: 14272 (from 2010/06/03), today: 3, yesterday: 3