ソフトウェア/Igor/グラフ関連 のバックアップソース(No.3)

更新

[[ソフトウェア/Igor]]

#contents

* グラフに表示されたウェーブの一覧を取得する [#n02b667a]

TraceNameList という関数で読み取った値をリスト関数で処理します。

 LANG:Igor(linenumber)
 function TestTraceNameList(graph_name)
    string graph_name
    string traces = TraceNameList(graph_name, ";", 1)
    variable i
    for(i = 0; i < ItemsInList(traces); i+=1)
        print StringFromList(i, traces)
    endfor
 end
 
 // コマンドラインから
 
 make wave1, wave2, wave3, wave4
 display wave1, wave2, wave3, wave4
 TestTraceNameList("Graph0")
 // wave1
 // wave2
 // wave3
 // wave4

Igor には他にも XxxxNameList という名前の関数がたくさんあって、
同じパターンを使い回せます。

例えば、画像の一覧なら、TraceNameList ではなく ImageNameList 
を呼べばいいわけです。

 LANG:Igor(linenumber)
 string graph_name = "Graph1"
 string images = ImageNameList(graph_name, ";", 1)
 variable i
 for(i = 0; i < ItemsInList(images); i+=1)
     print StringFromList(i, images)
 endfor

当然、名前が手に入れば何でもできますね。

例えばあるグラフから名前が "wave1?" の形のトレース、~
例えば "wave10", "wave11", ... をすべて消去するには、

 LANG:Igor(linenumber)
 function test()
     string graph_name = "Graph0"
     string traces = TraceNameList(graph_name, ";", 1)
     variable i
     for(i = ItemsInList(traces) - 1; i>=0; i-=1)
         string trace_name = StringFromList(i, traces)
         if(GrepString(trace_name, "^wave1.(#\d*)?$"))
             RemoveFromGraph $trace_name
         endif
     endfor
 end
 
 // コマンドラインから
 
 // いくつもウェーブを表示した中から
 make wave0, wave1, wave10, wave11
 display wave0, wave1, wave10, wave11, wave1, wave11
 // wave10, wave11 だけを取り除く
 test()

などとします。

for を逆順に回しているのは、トレースを Remove すると
残されたトレースの名前が変化することがあるためです。

例えば、wave10 が2回 AppendToGraph されていると、wave10 と wave10#1
という2つのトレースができます。ここで、先に wave10 を消してしまうと
wave10#1 の名前が wave10 になってしまい、後から wave10#1 を消そうと
したときに見付からずエラーになります。

逆順に回すとこの問題を回避できます。

"wave1?" という形のウェーブを探すのに GrepString を使いました。
正規表現で検索できるので、strsearch に比べると凝ったことが簡単にできますね。

この部分を strsearch(trace_name, "wave1", 0) >= 0 としてしまうと、
wave10 などだけでなく、wave1 まで引っかかってしまいます。


* グラフ上の選択領域を得る [#d6fd38cf]

グラフ上をマウスで斜めにドラッグすると矩形領域を選べますが、
この範囲を Igor では Marquee と呼んでいます。

使用例

 LANG:Igor(linenumber)
 // 与えられた座標がグラフの選択領域に含まれているかどうか返す
 function IsPointInSelectedRegion(x, y)
 variable x, y
 
     string graph_name = "Graph0"
 
     struct Rectangle selected_region
     GetMarqueeRegion(graph_name, selected_region)
 
     return IsPointInRect(x, y, selected_region)
 end
 
 // コマンドラインから
 
 make/N=100 wave0 = x
 display wave0
 
 // 適当な領域をマウスで選択してから
 print IsPointInSelectedRegion(20,20)

コード

 LANG:Igor(linenumber)
 // 矩形領域を格納するための構造体
 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 = (x-rect.left)*(x-rect.right) <= 0
     result = (y-rect.top)*(y-rect.bottom) <= 0 && result
     return result
 end

IsPointInRect は、left < right, top < bottom を期待せず、
right < left や bottom < top でも、
内部か外部かを正しく判別できるようにしてあります。

* グラフ上の選択範囲を設定する [#dcd89a94]

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

また、普通にやると上下逆さまに指定することになって正しく選択されないため、
数値の大小で指定を並べ替えています。

コード

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

* グラフ上への DrawAction について [#b8aac765]

DrawLine, DrawArc, DrawRect など、一連の DrawXXX 関数によってグラフ上に様々な図形を描画できます。

しかし、注釈を付ける際の TextBox 等と違って DrawXXX で書いた図形には名前が付かないため、
一旦描いた DrawXXX 図形をスクリプトから変更する方法が分かりづらいです。

例えば、一旦書いた DrawXXX 図形を後から消去したいような場合には、

+ SetDrawEnv gstart, gname = the_group_name で一連の描画を入れる名前付きグループを作成する
+ DrawXXX を使って描画する
+ SetDrawEnv gstop で名前付きグループを閉じる
+ あとから、DrawAction getgroup=the_group_name, delete のようにグループを消去する

という手順を取ります。

コード例:(コマンドラインに貼り付けられます)

 LANG:Igor
 // 適当なグラフを作成
 Make wave0 = {0, 1}
 Display wave0
 // グループを指定して四角形を描画
 SetDrawEnv gstart, gname=my_group_name
 SetDrawEnv xcoord=bottom, ycoord=left
 SetDrawEnv linefgc= (0,65280,0), fillpat=0, dash=1
 DrawRect 0.1, 0.1, 0.3, 0.4
 SetDrawEnv gstop
 // グループを指定せずに描画 (色指定などは持ち越されない)
 DrawRect 0.4, 0.5, 0.6, 0.7

コード例(続き):(コマンドラインに貼り付けられます)

 LANG:Igor
 // 1つ目に書いた図形を消去
 DrawAction getgroup=my_group_name, delete

コード例(続き):(コマンドラインに貼り付けられます)

 LANG:Igor
 // 残っている2つ目に書いた図形も含めて全部消去
 DrawAction delete

Counter: 17390 (from 2010/06/03), today: 2, yesterday: 2