ソフトウェア/Igor/グラフ関連 の履歴(No.3)

更新


ソフトウェア/Igor

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

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 まで引っかかってしまいます。

グラフ上の選択領域を得る

グラフ上をマウスで斜めにドラッグすると矩形領域を選べますが、 この範囲を 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 でも、 内部か外部かを正しく判別できるようにしてあります。

グラフ上の選択範囲を設定する

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 について

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

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

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

  1. SetDrawEnv gstart, gname = the_group_name で一連の描画を入れる名前付きグループを作成する
  2. DrawXXX を使って描画する
  3. SetDrawEnv gstop で名前付きグループを閉じる
  4. あとから、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: 18563 (from 2010/06/03), today: 12, yesterday: 7