mjk LISPその3

波形表示... 1

波形の選択... 1

波形の作成... 1

 

 

波形表示

G-widgetのプロパティの操作は基本的に

(resource (G-widget 名前) :プロパティ)で値を取得し

(set-resource (G-widget 名前) :プロパティ )で値を設定します。

また個々のチャンネルの値は

(get-property (G-widget 名前) チャンネル順 :プロパティ)で取得し

(set-property (G-widget 名前) チャンネル順: プロパティ )で値を設定します。

チャンネル順は0,1,2・・・となります。

チャンネルのプロパティには

location チャンネルの位置・向きなど

logical-channel 脳磁図や脳波などでメーカーが割り当てた番号

kind 脳磁図、脳波、STIMなどのチャンネルの種類 1.脳磁図 2.脳波 3. STIM

range スケールその1です

calibration スケールその2です。通常はcalibration×range×チャンネルの値が計測された値となります。

y-unit-number 単位です。Tだと112T/mだと201Vだと107です。

y-unit-multiplier スケールその3です。普通はゼロです。10n乗とスケールその2×その1×チャンネルの値が計測された値となります。

name チャンネルの名前

などがあります。

 

とりあえずコントロールパネルを開きます。

(manage *control-panel*)

#<X-widget>

matrix-source widgetを作成し、srcという名前にします。

(require-widget :matrix-source  "src")

#<matrix-source: src>

作成したG-widgetを消去するのはGtDeleteWidget関数を使います。aという名前のwidgetを作成します。

(require-widget :rawfile "a")

#<rawfile: a>

aというwidgetができました。

(GtDeleteWidget (G-widget "a"))

nil

結果は変わりません。

 

5×100-11の乱数行列を作成します。+と―はそのままでは使えないのでmap-matrix関数を使っています。

(setq A (map-matrix (/ (random-matrix 5 100)(pow 2 30)) #'1-))

#<5x100 matrix>

(matrix-extent A)

(-0.999188840389  0.992883205414)

行列Asrcmatrixプロパティに代入します。

(set-resource (G-widget "src") :matrix A)

t

srccoreを押したところです。

low-boundhigh-boundは表示幅です。plotter widgetなどで表示幅を変えると値が変わります。鍵マークがあるプロパティはset-resource関数で変更することはできません。

srcdisplaylink関数で繋ぎます。

(G-widget “名前”)といちいち記すのが面倒なのでsetqで簡単にします。

(setq src (G-widget "src") display (G-widget "display"))

#<plotter: display>

(link src display)

nil

ScaleOffsetを変更します。

(set-resource display

  :scales (make-matrix 5 1 1)

  :offsets (make-matrix 5 1 0)

)

t

標本化周波数を100Hz1smp=0.01秒とします。

(progn (set-resource src :x-scale 0.01 :x-unit "s")(link src display))

nil

周波数はsfreq関数を用います。

(sfreq src)

100.0

x-startで開始時間、x-lengthで期間、x-endで終了時間が表示されます。

(list (x-start src) (x-length src) (x-end src))

( 0.0  0.99  0.99)

sample-to-x関数とx-to-sample関数でサンプル数〜秒の変換ができます。

(list (sample-to-x src 50)(x-to-sample src 0.5))

( 0.5 50)

(show-bounds &optional widget)

nil

 

チャンネル名を表示させてみます。

(set-resource display :ch-label-space 80)

t

そもそもチャンネル名を設定してないので出るわけがないです。

(get-property src 0 :name)

nil

以下の関数を作りました。

(defun chnumber()

  (dotimes (i 5)

    (set-property src i :name (format nil "ch~d" (1+ i))))

  (link src this)

)

(progn (loadtest)(chnumber))

nil

尚、loadtest関数は

(defun loadtest()

(load “/home/neurosurgery/test.lsp”)

)

で、chnumber関数と同じ/home/neurosurgery/test.lspファイルにまとめたものです。

pick-value関数を使うと新しいwindowが表示され値が表示されます。Enterを押すと値が表示されます。

(pick-value)

0.967191457748

pick-time関数を使うと新しいwindowが表示されpick-value関数と同じ値が表示されます。Enterを押すと時間が表示されます。

(pick-time)

0.52999997139

この関数の本体はrequest-sample関数です。

(request-sample display)

#<Other type sample-point>

pick-value関数はsample-port関数、pick-time関数はsample-y関数とほぼ等価です。違いはG-widget名前の指定が必要かどうかだけです。

(sample-port (request-sample display))

1

(sample-y (request-sample display))

0.0302401781082

時間幅を表示させます。

(set-resource display :show-x-span t)

t

スケールを表示させます。

(set-resource display :show-scales t)

t

Y-scale:のところが1?となっています。set-property関数でsrcy-unit-number107V)にします。

面倒なのでエディタで作成して選択してGraphにコピーします(マウスホイールクリック)。

(progn

  (dotimes (i 5)

    (set-property src i :y-unit-number 107)

  )

  (link src display)

)

nil

0.2秒おきに目盛りを入れてみます。

(set-resource display :tick-interval 0.2)

t

表示時間・幅を変えてみます。:startでなく:pointになっています。

(set-resource display :point 0.3 :length 0.4)

t

x-startx-lengthx-endは表示開始時間、表示幅、表示終了時間を示します。

(list

  (x-start display)

  (x-length display)

  (x-end display)

)

( 0.3  0.4  0.7)

元に戻します。lengthは適当に大きな数を入れています。

(set-resource display

  :point 0

  :length 2

  :show-scales nil

  :tick-interval -1

  :show-x-span nil

)

t

 

波形の選択

plotter widgetの波形を右クリック・ドラッグして白黒反転させます。

x-selection関数を使うと白黒反転した時間の最初と期間が表示されます。

(x-selection)

( 0.3  0.34 #<plotter: display>)

実はplotterselection-startselection-lengthというプロパティを見ています。

(list

  (resource display :selection-start)

  (resource display :selection-length)

)

( 0.3  0.34)

選択した時間幅を変えてみます。

(set-resource display

 :selection-start 0.4

 :selection-length 0.2

)

t

selection-length0の時、線に0より小さいと表示されません。

(set-resource display :selection-length 0)

t

 

データを取得するにはget-data-matrix関数を使います。単位は秒ではなくサンプルです。

0.10.2秒のデータを行列として得るには以下のようにします。

(setq A

  (get-data-matrix display

  (x-to-sample display 0.1)

  (x-to-sample display 0.1)

  )

)

#<5x10 matrix>

検算してみます。

元の行列はmtxです。1019サンプルまでの行列Bを作成します。行列の取り出しは・・・面倒ですが、dotimesmat-append関数を組み合わせます。

(progn

  (setq B (column 10 mtx))

  (dotimes (i 9 B)

    (setq B (mat-append B (column (+ i 11) mtx)))

  )

)

#<5x10 matrix>

(setq C (- A B))

#<5x10 matrix>

(matrix-extent C)

( 0.0  0.0)

一致していることがわかりました。一応確認です。

(print-array C)

#<5x10 matrix>

#m(

( 0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0 )

( 0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0 )

( 0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0 )

( 0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0 )

( 0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0 ))

 

波形の作成

010秒までを1001分割して以下のような波形を作成します。

progn

  (setq x (ruler-vector 0 10 1001))

  (defun func(x)(- x (round x) -0.5))

  (setq x1 (map-matrix x (function func)))

  (setq x2 (map-matrix x1 (function round)))

  (defun func(x)(if (> x 0.99) 1 0))

  (setq x3 (map-matrix x1 (function func)))

  (defun func(x)(* x (* 2 pi)))

  (setq x (map-matrix x (function func)))

  (setq x4 (map-matrix x (function sin)))

  (setq x5 (map-matrix x (function cos)))

  (defun func(x)(sin (* x 2)))t

  (setq x6 (map-matrix x (function func)))

  (setq mtx x1)

  (setq mtx (mat-append mtx x2))

  (setq mtx (mat-append mtx x3))

  (setq mtx (mat-append mtx x4))

  (setq mtx (mat-append mtx x5))

  (setq mtx (mat-append mtx x6))

  (set-resource src :matrix (transpose mtx))

  (link src display)

  (set-resource display

    :point -1

    :length 999

  )

)

t

15番目のチャンネルは前回のチャンネル情報が踏襲されていますが、6番目のチャンネル情報は入ってないので平坦な波形となっています。

定義しなおします。

(progn

  (let

    ((chnames '("triangle" "square" "impulse" "sin1Hz" "cos1Hz" "sin2Hz")))

    (dotimes (i (resource src :channels))

      (set-property src i :name (nth i chnames))

      (set-property src i :kind 2)

      (set-property src i :y-unit-number 107)

    )

  )

  (link src display)

  (set-resource display

    :scales (make-matrix 6 1 1)

    :offsets (make-matrix 6 1 0)

    :ch-label-space 100

    :show-x-span t

  )

)   

t

link関数は元のG-widgetの全部のチャンネルをそのままtargetに引き継ぎますが、link-to関数を使うことで順番を変えたり選択したりできます。

(link-to display src 2 src 5 src 3 src 1 src 3)

5

pick-widgetを使うと直感的な操作ができるようになります。

(progn

  (setq chs (require-widget :pick "chs"))

  (set-resource chs 

    :names '("impulse" "sin2Hz" "sin1Hz" "square" "sin1Hz")

  )

  (link src chs)

  (link chs display)

)

nil

直接pick-widgetcontrol panelに書き込むほうがもっと楽かもしれません。

source-matrix:matrixに行列を当てはめると強制的に時間は0秒からとなります。:low-boundを変更すればいいのですが、鍵印がついていて変更できません。

2.5秒ずらしてみます。

(progn

  (setq delay (require-widget :delay "delay"))

  (set-resource delay :delay -2.5)

  (link src delay)

  (link delay chs)

  (link chs display)

)

nil

時間が変わりました。pick-widget chsを見てみます。low-bound-250となっています。

displayのほうは変わっていません。

srcdelaydisplayにリンクしてみます。時間は幅が両者の共用する時間になっています。

(link-to display src 1 delay 1 src 4 delay 4 src 2 delay 2)

6

delay-widget delayを消去してみます。

(GtDeleteWidget delay)

nil

pick-widget chsを消して、fft-widget210Hzの帯域通過フィルタを通してみます。

(progn

  (GtDeleteWidget chs)

  (setq bandpass (require-widget :fft-filter "bandpass"))

  (set-resource bandpass

    :size 512

    :pass-band '(band-pass 2 10)

  )

  (link src bandpass)

  (link bandpass display)

  (set-resource display

    :point -99

    :length 999

  )

)

t

plotter-widgetを新たに作成して帯域通過フィルタで除去した成分を見てみます。残念ながらbinary-widgetlink関数しか使えないようです。

(progn

  (setq disp2 (require-widget :plotter "disp2"))

  (setq fsub  (require-widget :binary "fsub"))

  (set-resource fsub :function 'fsub)

  (link src fsub)

  (link bandpass fsub)

  (link fsub disp2)

  (set-resource disp2

    :scales  (resource display :scales)

    :offsets (resource display :offsets)

    :geometry  (resource display :geometry)

    :tick-interval (resource display :tick-interval)

    :show-x-span   (resource display :show-x-span)

  )

  (GtPopupEditor disp2)

)

nil