Igor Pro コーディング規約
Thomas Braun氏によってIgor Exchangeに投稿されているIgor Proのコーディング規約(非公式)が,簡潔で分かりやすかったので本人の許可を得て翻訳しました. ドキュメント作成ソフトのDoxygen等,日本のIgor Proユーザーにはおそらく馴染みのないものもありますが,規約の多くの部分がコーディングの参考にできると思います.
原文:
http://www.igorexchange.com/project/CodingConventions
https://github.com/t-b/igor-pro-coding-conventions
1 プロシージャ
コードはIgor Proの外部のプロシージャファイルに直接,書き込むべきです.
プロシージャファイル名はアルファベットの大文字小文字,アンダースコア,ハイフンのみで構成され,.ipfで終わります.
ファイルのエンコーディングはOSに依存します.しかし使用する文字は常にASCII文字に限られるべきです.Igor Pro 7でだけ使用するコードでは,テキストエンコーディングとしてUTF-8を用い
#pragma TextEncoding = "UTF-8"
を指定します.プロシージャファイルは
#pragma rtGlobals=3
およびその説明コメント*1で開始されます.改行コードは常にUNIXスタイル(LF)を用いるべきです.
2 空白文字とコメント
コメント
ファイル,関数,マクロ,定数の説明(ドキュメント)にはdoxygenを用います.
次のように,末尾のコメントの前には常に一つの空白文字を置くべきです.
if (a < 0) b = 1 else // positive numbers (including zero) b = 4711 endif
- コメントを行末に付すよりは,行を分けて書くべきです.
Doxygen
@paramキーワードに続けて引数の名前と説明を書く場合,引数の説明は関数に渡す順番に通りに並べるべきです.
/// @param pressure Pressure of the cell /// @param temperature Outdoor temperature /// @param length Length of a soccer field Function PerformCalculation(pressure, temperature, length) variable pressure, temperature, length // code End
- 関数が引数の値渡しと参照渡し*3の両方を使うとき場合は,in/out指定を@paramに付けるべきです.
/// @param[in] name Name of the device /// @param[out] type Device type /// @param[out] number Device number Function ParseString(name, type, number) string name variable &type, &number // code End
- オプション変数の説明は次のようにします.
/// @param verbose [optional, default = 0] Verbosely output /// the steps of the performed calculations Function DoCalculation([verbose]) variable verbose // code End
空白文字
各関数は他のコードから改行1行分だけ隔てて書くべきです.
インデントにはタブ文字を用い,(Igor Pro以外のソフトウェアでコーディングしていてタブ文字が使えない場合は)タブ文字には4つの空白文字を当てるべきです.
行を分けてコメントする場合,コメントのインデントの深さは周囲のコードに合わせます.
関数の引数の宣言,ローカル変数の宣言,関数の残りの部分はそれぞれ改行で隔てて書きます.
Function CalculatePressure(weight, size) variable weight, size variable i, numEntries // code End
a = b + c * (d + 1) / 5 if(a < b) c = a^2 + b^2 end Make/O/N={1, 2} data for(i = 0; i < numWaves; i += 1) a = i^2 endfor if(myStatus && myClock) e=f endif
- 行の末尾の余分な空白を避けるように心掛けてください.以下,空白文字を␣で,タブ文字を⇥で表します.
良い例: Function␣DoStuff() ⇥print␣"Hi" ⇥if(a␣<␣b) ⇥⇥c␣=␣a^2␣+␣b^2 ⇥end ⇥Make/O/N={1,␣2}␣data End 悪い例: Function␣DoStuff()␣ ⇥print␣"Hi"␣⇥ ⇥ ⇥if(a␣<␣b)␣␣␣␣ ⇥⇥c␣=␣a^2␣+␣b^2⇥ ⇥end␣ ⇥ ⇥Make/O/N={1,␣2}␣data␣ End
if/endif
,for/endfor
,do/while
,switch/endswitch
のようなコードブロックがプログラムのロジックを表している場合には,前後には改行を入れます.
for(i = 0; i < numEntries; i += 1) // code endfor if(a > b) c=d elseif(a == b) c=e else c=0 endif switch(mode) case MODE1: a = "myString" break case MODE2: a = "someOtherString" break default: Abort "unknown mode" break endswitch
以下のような場合は,直前の代入文がロジックの一部なのでif
やfor
の前に改行を入れません.
numEntries = ItemsInList(list) for(i = 0; i < numEntries; i += 1) // code endfor NVAR num = root:fancyNumber if(num < 5) // code endif
複数のend文が続く場合には,改行を省略します.
for(i = 0; i < numEntries; i += 1) // code if(i < 5) // code endif endfor
- 操作関数のフラグの間には空白を入れません.また,フラグへの代入を行う場合の
=
の前後にも空白を入れません.
良い例: Wave/Z/T/SDFR=dfr wv = myWave Function/S DoStuff() // code End 悪い例: Wave /Z /T /SDFR = dfr wv = myWave
- 引数の参照渡しに使う
&
は変数名の直前に置きます.
良い例: Function DoStuff(length, height, weight) variable &length, &height, &weight // code End 悪い例: Function DoStuff(length, height, weight) variable& length, & height,& weight // code End
3 コード
3.1 基本
1行は80文字を超えないようにします.
variable
/string
/wave
/dfref
の名前にはcamelCaseを使い,構造体の名前にはCamelCaseを使います.i
,j
,k
,l
という名前の変数はループカウンターとしてだけ使うべきです.後者ほど内側のループで使われます.一時的に値を格納するウェーブとして,フリーウェーブを使うべきです.
できる限り
SetDataFolder
を使わずにコードを書くべきです.関数が呼ばれるときに特定のデータフォルダをカレントフォルダとしていることを期待するなら,適切なドキュメントを書いておくべきです.関数中でカレントフォルダを変更した場合は常に,関数の終了前にカレントフォルダをもとに戻します.Igor Proのコードは大文字小文字の違いを問題にしませんが,可読性の向上のため,Igor Proのヘルプファイルに書かれている公式の名称に合わせて大文字小文字を書き分けるべきです.
Make/N=(10) data AppendToGraph/W=$graph data WAVE/Z wv SVAR sv = abcd STRUCT Rectangular rect print ItemsInList(list)
ただし,以下のふたつの場合は例外です*4.
variable storageCount string name
変数や関数を定義するときや,それらを使うときには,大文字小文字の使い方を変えてはいけません.
関数の戻り値とする値を,一時的に格納するために変数を使うべきではありません.
良い例: if(someCondition) // code return 0 else // code return 1 endif // 関数の戻り値が状態であることを知らせたいのなら, // 関数名をGetStatusForFooのようにするか.doxygenのコメントとして@returnを使うべきです. // あるいは,関数名とdoxygenコメントの両方を使うべきです. 悪い例: variable status // code if(someCondition) // code status = 0 else // code status = 1 endif return status
コメントアウトされたコードを残しておくべきではありません.
その必要がないなら,数値変数や文字列変数を初期化するべきではありません.もし変数の初期化を行うなら,それぞれ別の行で行うべきです.
良い例: variable i = 1 variable numEntries, maxLength string list 悪い例: variable i = 0, numEntries = ItemsInList(list), maxLength string list = ""
- 関数のオプション変数としてデフォルト値を使うなら,それをわざわざ書くべきではありません.
良い例: StringFromList(0, list) 悪い例: StringFromList(0, list, ";")
- 括弧は省略できるのなら省略するべきです.
良い例: variable a = b * (1 + 2) if(a < b || a < c) // code endif 悪い例: variable a = (b * (1 + 2)) if((a < b) || (a < c)) // code endif
- 優先度が等しい演算子を組み合わせるときには,括弧を使うべきです.
良い例: if((A || B) && C) // code endif if(A == (B >= C)) // code endif 悪い例: if(A || B && C) // same as above as these are left to right // code endif if(A == B >= C) // same as above as these are right to left // code endif
正確な結合則を記憶しておくのは難しく,エラーを起こしやすくなるからです.
DisplayHelpTopic "Operators"
も参照してください.
3.2 定数
- あるファイルの内部でだけ有効なstatic定数は,そのファイルの先頭で定義します.
- グローバル定数の名前はアルファベット大文字とアンダースコアのみで構成します,グローバル定数の定義はただ一つのファイルに集約されるべきです.
- マジックナンバー*5にはコメントで説明をつけるべきです.
static Constant DEFAULT_WAVE_SIZE = 128 // equals 2^8 which is // the width of the DAC signal
3.3 マクロ
- マクロはウィンドウ再構成マクロとしてだけ使うべきです.
- ウィンドウ再構成マクロを自分の手で書き換えるのは避けるべきです.パネルをデフォルトの状態に戻したいのなら,関数中で
DoWindow/R
を呼び出し,Igor Proにマクロを書き換えさせるべきです.
3.4 関数
関数の長さは50行(あるいは画面の高さの半分)に収めるようにします.
関数名にはCamelCaseを用います(ファイル名を表すために
SomeString_
といった接頭語を付けることは認められます).関数がそのプロシージャファイルの内部でしか使われないのなら,それらの関数は
static
にします*6.次のように,すべての変数を関数の初めの部分で定義します.
Function CalculatePressure(weight, size) variable weight, size variable i, numEntries // code End
これは,Igor Proではブロックスコープが存在しないからです*7.すなわち
if(someCondition) variable a = 4711 end print a
は正しいコードです.これはC/C++経験者を混乱させます.
4 リンク・文献
- ASCII: https://en.wikipedia.org/wiki/ASCII
- Doxygen: http://www.stack.nl/~dimitri/doxygen/index.html
- Git settings for Igor Pro code: http://www.igorexchange.com/node/6013
- Robert C. Martin, Clear Code: A Handbook of Agile Software Craftmanship, Prentice Hall (2008)
- How to write good commit messages: http://who-t.blogspot.de/2009/12/on-commit-messages.html
*1:訳注:新しいプロシージャウィンドウを作成したときに書いてある#pragma rtGlobals = 3 // Use modern global access method and strict wave access.を消すべきではないということ.
*2:訳注:Variable num ///< number of points のように,変数定義等の直後にその説明を置く場合
*3:訳注:例のように,変数名の頭に&を付けて引数を受け取ると,関数内での変数値の変更が関数の呼び出し元にも反映されるようになります.この機能を変数の参照渡しと呼びます.
*4:訳注:Igor ProヘルプファイルではVariable,Stringは大文字で始まります.この例外はおそらく,組み込み型が小文字で書かれるC/C++の慣習に合わせたものでしょう.
*5:訳注:プログラムに現れる,ぱっと見て意味の分からない数字のこと.
*6:訳注:関数定義をFunctionのかわりにstatic Functionで始めると,プロシージャファイルの外からその関数が使えなくなります.ただし,#pragma ModuleName=SomeStringによってモジュール化するとstaticな関数をファイルの外からも使うことができるようになります.
*7:訳注:if/endifブロックの内部で定義した変数はブロックの内部でだけ有効(ブロックスコープ)だと便利ですが,Igor Proではそうなっていない,ということ.
Igor Pro上のシェル,CommandPanelをちょっとアップデート
以前紹介したIgor Pro上のシェルことCommandPanel,ちょこちょこアップデートしていたので改善点の報告など.
Igor Pro 7でも起動できるようになった
以前のバージョンは,Igor Pro 7で起動するとそれだけで無限ループに陥ってしまっていました. 新しいバージョンはIgor Pro 7でも起動できます.
しかし,Shift
とEnter
の同時押しが認識されないらしく,コマンドの補完やバッファの絞り込みができません.
ウィンドウの描画が改善された
ウィンドウサイズを変更した際,ウィンドウフック関数を用いてコマンドラインやバッファの再描画をするようにしました.
古い版ではコントロールアクションを利用していたので,ウィンドウサイズ変更に対してコントロールの描画が一拍遅れていました.
テストを作成した
以前のエントリで紹介したテスト関数を用い,テストを作成しました.
ブレース展開が速くなった
テストの作成と合わせてリファクタリングを行い,とくにブレース展開の速度を改善しました.
以前は
print {1..500}
などとするとかなり待たされたのですが,我慢できるレベルになった気がします.ただbashが一瞬で処理してくれるのを考えると今でも相当遅いので,そのうちなんとかしたいです.
標準のフォントがIgor Proの標準フォントになった
標準のフォントをArial
からIgor Proの標準のフォントに変更しました.日本語版Igor Proを使っている方は,とくに設定せずに日本語文字が表示されます.
パス名の補完・展開で上位のフォルダを参照できるようになった
Igor Pro内部での相対パス指定では,::
がひとつ上のフォルダ,:::
がふたつ上のフォルダを表します.これらの上位のパスを参照する書き方をパス名補完とパス名展開が認識するようになりました.
バッファの見た目と中身を別々に指定できるようななった
詳細はwikiの該当箇所を見ていただくとして,具体的には次のような関数が定義できるようになりました.
バッファの全ての要素に共通するHelpDisplayTopicを無視して,disで絞り込みができていることに注目してください.この関数,結構便利度高い気がします.
関数定義も,以下のようにそれほど複雑ではありません.
#include "CommandPanel" Function Helps() String list = FunctionList ("*", ";", "KIND:1") + OperationList("*", ";" ,"") Variable n = ItemsInList(list) Make/FREE/T/N=(n) word = StringFromList(p, list) Make/FREE/T/N=(n) buffer = "[DisplayHelpTopic] ¥"" + word +"¥"" Make/FREE/T/N=(n) line = "DisplayHelpTopic ¥"" + word + "¥"" Sort word, word, buffer, line CommandPanel_SetBuffer(word, line = line, buffer = buffer) End
Igor Proの最小構成のテスト関数群を書いた
はじめに
Igor Proのプロシージャを書いていると,改良したつもりが既存の機能を壊してしまっていた,ということがよくあります. よくありますがよくないです.何より「改良が怖い」というのが精神衛生上とてもよくないです.
で,調べたところソフトウェア開発には「単体テスト」なる技法がある模様. 関数の振る舞いをチェックするテストコードを用意しておき,変更を行うたびにそのテストがパスすることを確認するのだとか.
よし,それじゃあ(よく分かってないけど)Igor Proでも単体テストしよう!と思い立ち,単体テスト用のプロシージャを探したところ次のふたつを見つけました.
上記2つのプロシージャはどうも
を参考にして作られているようです.汎用プログラミング言語のテスティングフレームワークを参考にしていて高機能なのですが,単純な手続き型のIgor Proには機能過多かなぁ...と思いました. そもそもIgor Proユーザにしめるプログラマの割合ってそれほど大きくないはずで,「既存のテスティングフレームワークに似ている」はあまりメリットでもない気がしました.
なので,Igor Proに必要な,ミニマルな単体テスト関数群を書きました.
使い方
MinTest.ipfを読み込むと,以下の4つの関数が使えるようになります.
- eq_var
- eq_str
- eq_wave
- eq_text
publicな関数はこれだけ*1.ミニマルです.以下のようにTest
で始まる関数を定義して,その中で使います.
Function TestDemo() eq_var(word_count("it is a test"), 4) eq_str(hello_world(), "Hello, world!") eq_wave(fibonacci(5), {1,1,2,3,5}) eq_text(fizzbuzz(5), {"1","2","Fizz","4","Buzz"}) End Function word_count(s) String s return ItemsInList(RemoveFromList(" ", s, " "), " ") End Function/S hello_world() return "Hello, world" End Function/WAVE fibonacci(n) Variable n Make/FREE/N=(n) w = 1 w[2,inf] = w[p-1] + w[p-2] return w End Function/WAVE fizzbuzz(n) Variable n Make/FREE/T/N=(n) w = Num2Str(p+1) w = SelectString(mod(p+1, 3), "Fizz", w) w = SelectString(mod(p+1, 5), "Buzz", w) w = SelectString(mod(p+1, 15), "FizzBuzz", w) return w End
ただこれだけだと,単体テストを知っている方からツッコミが来そうです. 単体テストはコードを改変するたびに実行することが大事で,自動実行できるようにしておくべきなのだ,比較用の関数だけ用意しても意味ないのだ,と.
MinTest.ipfでもテストの一括実行はサポートしていて,どこから行うかというとメニューバーを使います.
Igor ProはもともとGUIのソフトなのでメニューバー使ってしまうことにしました.で,実行した結果がこちら.
...失敗しました.テストの結果は履歴エリアに表示されるとともに,メニューバーの表示が変化します.
履歴エリアには期待された値(want),と実際に受け取った値(got)が表示されます.また,メニューバーのjump
欄をクリックすると,テストコードの失敗した箇所にジャンプできます*2.
hello_world()関数を修正してテストをパスするとこうなります.
おわりに
テスト便利です.いちいちテスト書くの面倒そう...と思ってましたが,コード修正後の安心感は非常に大きいです. Igor Proはデータ解析用ソフトなので,関数にバグが有ると図らずもデータを歪めてしまうことになります. 学術分野で使われるコードにこそ,テストが必要な気がします.
余談
フィボナッチ数列の実装を見るとIgor Proがすごくデキる子に見える.代入がそのままmapなのが強力.
当然ですが代入をMultiThreadにして高速化しようとすると失敗します.
Function/WAVE fibonacci(n) Variable n Make/FREE/N=(n) w = 1 MultiThread w[2,inf] = w[p-1] + w[p-2] return w // -> {1,1,2,2,4, ...} End
実験系研究者がVimを使うと幸せになれる10の理由
はじめに
この記事はVimアドベントカレンダー2016の3日目の記事です.
先日はrhysdさんでピュアVim scriptのCコンパイラを作る話でした.
変態すぎ凄すぎてちょっと意味が分かりません.
昨日とは一転,本日担当の私はプログラミングが本職でないゆるいvimmerです.というか,専攻は情報系でさえなく実験物理をやっています. プログラマでなくてもvimを使うと幸せになれるよ,というのが本記事の趣旨になります.
vimガチ勢の方には,ゆるいvimmerはそんな視点でvimを選んでいるのねと,生暖かく見守っていただければ幸いです.
10の理由
1. 研究室は独自記法の宝庫
手を動かして実験する研究者でも,プレーンテキストに触れる機会は多いものです.具体的には
- 測定機器の設定ファイルや,測定を自動化するためのシークエンスを書いたファイル
- 測定データそのもの
- 解析ソフトの設定ファイルや,解析のためのスクリプト
- 論文を書くためのLaTeXのファイル
- 先輩が残していったソフトウェアのための,奇怪な書式の入力ファイル
等です.これらをまとめて扱うにはメモ帳は明らかに力不足で,何らかの高機能テキストエディタの導入が必要になります.
2. 実験に使うWindowsでも,解析に使うMacでも動く
実験系の研究者の場合,実験を行ってその結果を解析する必要があります. で,実験装置の制御ソフトはメーカーからWindows版が提供されることが多いのに対して,便利な解析ソフトはMac(unix)で動くものが多いという事情があります*1.
つまり,エディタもWindowsでもMacでも同じように動くものだととても便利です.
3. 専門用語の入力はGoogle IMEにおまかせ
どのOSでも動く高機能なテキストエディタ,というとvimとemacsが二強なわけですが,私がvimを選んだ理由のひとつにIMEとの連携がありました.どうもemacsはその内部に独自のIMEを持っているらしく,外部のIMEが使えません*2.
私の場合,研究に関する文書を書くときには,例えば「しゅれ」の変換候補に「シュレーディンガー」を出してくれるGoogle日本語入力が手放せないため,emacsではなくvimを使うことに決めました.
4. キーバインドが覚えやすい
暗記科目が苦手だったから理系を選んだって話,自分の周りでは結構聞く気がします. 高機能エディタを使っても,機能が覚えられなければ意味がないのですが,vimには「モード」の概念があるため,キーバインドが比較的覚えやすいです. 少なくとも,ControlとAltとコレを同時に押すと...といったパターンはありません.
ただし,カーソルの移動がhjklなのは敷居が高い気がします*3.
5. 最近は実験家も理論計算する
技術の進歩により,最近は実験家でも比較的簡単に理論計算ができるようになりました. 量子計算用のQuantum-ESPRESSO等,オープンソースの解析ソフトも多数開発されています.
ただ,こういった学術用のソフトはユーザー数が少ないため,多くのエディタではシンタックスハイライト等の対応がなされていません.しかしvimであれば,emacsと並んで最も広く使われているエディタであるので,誰かが専用の設定を書いてくれている公算が高いです.前記のQuantum-ESPRESSOであればこちら.
6. 強力なLaTeXサポート
実験系にかぎらず,理系研究者なら避けては通れないプレーンテキストファイルに,論文執筆のためのLaTeXファイルがあります. PDFビューアの設定に若干の面倒臭さがあるものの,例えばこちらのプラグインを使うことで,強力なLaTeX用エディタを手に入れることができます.
7. プレーンテキストで簡単ドキュメント
実験を安全にスムーズに行うため,実験装置には使い方のマニュアルがついているべきです.ただ,実験装置に付属のマニュアルは分厚すぎて参照性が低かったり,装置の魔改造によって本来の使い方と異なる手順が必要になっていたりします. しかし厄介なことに,そういった装置の使い方は先輩から口伝で教え継がれていたりします.
vimに限った話ではないのですが,プレーンテキストだとmarkdown記法を用いて簡単にマニュアルが作れます.見た目を整えたかったり,ボスから「Wordでくれ」と言われた場合には,pandocを使って(Wordを使わずに)プレーンテキストから.docxファイルが生成できる時代になってます.(詳細は以下の記事を参照してください.)
8. 設定を簡単に持ち運べるので出張でも安心
実験家であれば,共同実験先を訪問したり学会発表しに行ったりと,出張の機会も多々あるはずです. vimのカスタマイズには.vimrcというプレーンテキストファイルを使うので,これさえどうにかして*4持ち運べば,研究室のパソコンと同じ環境が出張用ノートパソコンに簡単に再現できます.
9. 安心の日本語マニュアル
以上が,実験家でも高機能のテキストエディタを使うと幸せになれる!といったポイントなのですが,高機能なソフトを使うときの不安として「使いこなすのが大変なのではないか?」というものがあります.ご安心ください.vimのマニュアルは日本語化されています.
10. コミュニティが活発
マニュアルを見ても使い方がよく分からない場合や,そもそもマニュアルのどこを見ればよいかわからない場合には?
日本のvimコミュニティは非常に活発なので,ググると大概回答が(日本語の記事として)見つかります.というか前記のヘルプ日本語化もvimコミュニティのお仕事で,大変ありがたいです.teratailのような質問サイトでも,質問すれば教えてもらえるはずです.
また,前述の.vimrcという設定ファイルの読書会(vimrc読書会)が毎週開かれているので,ぜひ覗いてみるのをおすすめします.便利な設定や,やってしまいがちな危ない設定等の貴重な情報が得られます*5.
おわりに
記事の途中でも触れましたが,hjklでカーソル移動,という謎の独自の操作に慣れてしまえば,vimは大変便利なエディタです.プログラマーほどテキストに向き合う時間が多くない実験系研究者でも,充分その恩恵に与れます.
今回の記事でvimに興味を持つ研究者が少しでも増えれば幸いです.
Igor Proで関数をメニューバーから呼び出す.たった3行で
はじめに
Igor Proで処理を自動化する際には①マクロを書く,②関数を書く,の二種類の方法があります. 現在では,高速に動作する,コンパイル時にエラーチェックが入る,といった理由でマクロより関数の利用が推奨されているようです*1
ただ,関数と比べたマクロの利点として,マクロを定義するとメニューバーの「マクロ」欄に名前が表示されてワンクリックで実行できるようになります.
関数も,マクロみたいにメニューバーから使えるようにならないかな? と思ったのが今回の動機です.
結論: 3行でOK
調べてみたところ,思った以上に簡単に実現できることがわかりました. 以下の3行をどこか*2に書くと引数なしのユーザー定義関数がメニューバーから実行できるようになります.
Menu "Functions" FunctionList("*",";","KIND:2,NPARAMS:0") End
メニューに;
区切りのリストを渡すと複数のメニュー項目に展開されることを利用しています.KIND:2
は(組み込み関数ではなく)自作関数の指定,NPARAMS:0
は引数なしの関数の指定です.
FunctionList
関数の引数を工夫すると,いろいろと便利にできそうです.
// 例1: Renameで始まる名前の関数のみ表示 Menu "Rename" FunctionList("Rename*",";","KIND:2,NPARAMS:0") End // 例2: 特定のウィンドウで定義されている関数のみ表示 Menu "Experiment" FunctionList("*",";","KIND:2,NPARAMS:0,WIN:experiment.ipf") End
追記 (2016/11/25)
単に関数を実行する以上のことをしたい場合は,GetLastUserMenuInfo
操作関数を使うとよいようです.
// ユーザー定義関数の定義部分をメニューバーからワンクリックで表示 // (Windowsだとメニュー項目の数に制限があるようです) Menu "Definitions" FunctionList("*",";","KIND:2"), DisplayDefinition() End Function DisplayDefinition() GetLastUserMenuInfo DisplayProcedure S_Value // 直前に選択したメニュー項目がS_Valueに格納されている End
Igor Proに標準添付されているWaveMetrics製プロシージャを使おう
はじめに
データ解析ソフトIgor Proには,実に280ものWaveMetrics社製プロシージャが標準添付されています*1.
これらは#include <プロシージャ名>
とプロシージャウィンドウに書くことで使えるようになるのですが,そもそもどんなプロシージャがあるのかよくわからないため,今ひとつ有効活用できていませんでした.なんともったいない!
そこで,メニューバーからワンクリックでこれらのWaveMetrics社製プロシージャを使えるようにしました.
使い方
まずは上記サイトからWMProcMenu.ipf
をダウンロードしてIgorに読み込んでください.
そうすると上記のようなメニューが表示され,プロシージャがアルファベット順に一覧表示されるとともに,クリックして読み込めるようになります. メニューの各部の役割は以下の通りです.
① WaveMetrics社製のプロシージャの数.
② プロシージャ名一覧.この名前をクリックするとメインプロシージャウィンドウに#include <プロシージャ名>
が挿入されてコンパイルされます.コンパイル後,読み込んだプロシージャウィンドウを最前面に表示します*2.
③ プロシージャを読み込んだ後に,そのプロシージャウィンドウを最前面に表示するのが鬱陶しい,という場合はこのチェックを外してください.
④ プロシージャ名一覧の取得は一度だけ行われます.Igorのファイルを別なパソコンで開き直した場合など,Igorのバージョンが変わった場合にはこれをクリックしてプロシージャ名の取得をやり直してください.
おわりに
プロシージャ名が一覧表示できるようになったことで,標準添付プロシージャが探しやすくなりました. スキャナで取り込んだグラフの画像からデータを抽出するIgorThiefなど,知らなかった便利機能がまだまだありそうです.
Igor Proで「それ全部テキストファイルで頂戴」に備える
はじめに
データ解析・グラフ作成用ソフトのIgor Pro,これ非常に便利なんですけれども,いかんせん有料ソフトなのでデータを受け渡しする際に相手がIgorを持っていないということがままあります.
そういった場合はウェーブをテキストファイルとして保存する必要があるのですが,データを一つずつ保存するのは難儀なのでプロシージャにしました.
使い方
例によって,上記のサイトからtxtsave.ipfをダウンロードしてIgor Proに読み込んでください.
そうすると以下の2つの関数が使用可能になります
- TxtSave(
データフォルダ名
,ウェーブ名
,ファイル名
[option]) - TxtSave_Recursive(
起点のデータフォルダ名
,ウェーブ名
,ファイル名
[ignore,option])
ひとつずつ説明します.
TxtSave
これはほぼ,Igor Proの操作関数Save
と同じ働きをします.
関数の引数にデータフォルダ名
,ウェーブ名
,ファイル名
を指定すると,指定したデータフォルダ中にあるウェーブを,指定した名前のファイルとして保存します.
この関数と組み込みのSave
操作関数の一番の違いは,ファイルの保存先のディレクトリが自動的に決定されることです.
たとえば,test.pxpというIgorのファイルで作業していた場合は,test.pxpと同じディレクトリにtest_txtfiles
というフォルダが作成され,Igor Pro内部のデータフォルダ構造と同じディレクトリ構造を保ったままウェーブが保存されます*1.
TxtSave("root:folder1:sub1:","dataX;dataY","data.txt") // test.pxpと同じ階層に,test_txtfilesディレクトリが作成され,その中に`test_txtfiles/root/folder1/sub1/data.txt`が作成される. TxtSave("","dataX;dataY","data.txt") // 第一引数を""にした場合,現在のデータフォルダのウェーブを保存する.
TxtSave_Recursive
TxtSave
ではウェーブのデータフォルダを指定して保存します.それに対してTxtSave_Recursive
では,起点となるデータフォルダを指定すると,そのデータフォルダ以下に存在する指定した名前のウェーブを一括で保存します*2.
以下の画像が,TxtSave_Recursive
関数を使って,エクスペリメント中のdataX
,dataY
という名前のウェーブを一気に保存した例です*3.
便利!
ignoreオプション
あるデータフォルダ以下全て保存してくれるのは便利ですが,データ解析の過程で作成したウェーブ等,無視して欲しいデータフォルダもあるかもしれません.そのような場合はTxtSave_Recursive
のignore
オプションで無視するフォルダを指定します.
ignore
オプションでは*
によるワイルドカードと!
による否定が使えます.また;
を区切り文字として複数条件を指定することもできます.複数条件を指定した場合は,後に指定した条件が優先されます*4.
TxtSave_Recursive("root:","dataX;dataY","data.txt",ignore="root:Packages") // root:Packages フォルダ以下を無視する TxtSave_Recursive("root:","dataX;dataY","data.txt",ignore="root:Packages;*folder*") // root:Packagesおよび,名前にfolderを含むフォルダ以下を無視する TxtSave_Recursive("root:","dataX;dataY","data.txt",ignore="*folder*;!folder1") // 名前にfolderを含むフォルダ以下を無視するが,folder1は無視しない.(後ろの条件が優先)
optionオプション
TxtSave
関数は内部でSave
操作関数を呼び出していますが,このときのオプションを明示的に指定することもできます.デフォルトでは,内部で
Save/G/O/W/M="\n"/B/P=[自動決定されたパス] [ウェーブ名] as [ファイル名]
としています*5.最後の/B/P
はTxtSave
関数を使う上で絶対に必要な部分なので,ユーザーが変更できるのは/G/O/W/M="\n"
の部分になります.
たとえば,空白区切りではなくタブ区切りの形式でデータを保存したい場合,以下のようにします.
TxtSave_Recursive("root:","dataX;dataY","data.txt",option="/J/O/W/M=\"\\n\"")
メニュー
txtsave.ipfを読み込むと,メニューバーにTxtSave
という項目ができ,そこから関数を呼び出したり,保存したファイルが存在するディレクトリを開いたりできます.
また,TxtSave_
で始まる関数を定義すると,このメニューから呼び出せるようになります.なので,TxtSave_Recursive
を使った関数を用意したら,TxtSave_
で始まる名前にしておくと便利です.
このメニューが邪魔な場合,ファイルを読み込む際に#include "txtsave"
の代わりに#include "txtsave", menus=0
とするとメニューが消えます.
また,メインプロシージャウィンドウに以下のように書くとメニューが「ウェーブを保存」メニュー以下に表示されるようになります.
override strconstant TxtSave_Menu="Save Waves;-;(TxtSave" // あるいは単に,以下のように書いてもよい // override strconstant TxtSave_Menu="Save Waves"
おわりに
ウェーブを全てテキストファイルとして保存する,なんて,絶対に誰かがすでに方法を作っているはずで,車輪の再開発な気がしないでもないです.ただ,無視するフォルダの設定なんかは,あまり例がないんじゃないかなと思います.