Igor Proでプロシージャの配色を変えて楽しく作業する

はじめに

前回はIgor Proから外部のエディタを呼び出しましたが,今回はIgor Pro内部で楽しくプログラミングするためのプロシージャを紹介します.

f:id:ryotako:20160922140226p:plain

Igor Proではプログラムのキーワードは青,コメントは赤,といったようにプログラムの要素に自動で色が付きます(シンタックスハイライト).実はこのシンタックスハイライトの色はユーザーの好みで変えることができて,

SetIgorOption colorize,keywordColor=(28928,40448,1792)

のようにすると色が変わります*1

この場合はFunctionForIfのようなキーワードの色がデフォルトの青から黄緑に変更されます.

しかし,(28928,40448,1792)という数字の組(16bit RGB値)から「黄緑」を連想するのは多くのIgor Proユーザにとって困難です. また,プログラムで色を指定するために16bitのRGB値を指定する,というのはあまり一般的でなく,他のエディタで使っていたシンタックスハイライトの色を移植するのも面倒です.

そこで,Igor Proのシンタックスハイライトの色を簡単に指定するためのプロシージャを作りました. github.com

使い方

まず例によって,上記のサイトからSyntaxColor.ipfをダウンロードしてIgor Proに読み込んでください.

f:id:ryotako:20160910201958p:plain

そうすると,以下の5つの方法でIgor Proのシンタックスハイライトの色が変更できるようになります.

  • 上図のように,メニューバーからカラーパレットで色を選ぶ.
  • SyntaxColor#rgb16("string",1,39321,19939) のように16bitのRGB値を指定する.
  • SyntaxColor#rgb8("operation",220,20,60) のように8bitのRGB値を指定する.
  • SyntaxColor#hex("function" ,"#FF69B4") のように16進トリプレット表記で指定する.
  • SyntaxColor#x11("pound", "DarkTurquoise") のようにX11の色名称で指定する.

16進トリプレット表記X11の色名称についてはWikipediaのこちらの項目(ウェブカラー - Wikipedia)を参照してください.

8bit RGB値16進トリプレット表記が使えるので,他のエディタで使っている色設定の移植も簡単にできます.

色付け可能なIgor Proの構文要素はkeyword, comment, string, operation, function, poundの6種類です. これらの色を変更する関数(or マクロ)を作成したら,関数の名前をColorSchemeで始まるものにしておくと,自動検出されてSyntaxColor.ipfのメニューから呼び出せるようになるので便利です.

注意点

シンタックスハイライトの色は関数で変更することができますが,ウィンドウの背景色と地の文の色は手動で変える必要があります.

背景色はメニューの「プロシージャ」→「ドキュメント設定」→「背景色」,地の文はメニューの「プロシージャ」→「テキストカラー」から色が設定できます.

なお,シンタックスハイライトの色はIgor Proを終了するとリセットされてしまいます.

メニューバーからカラーパレットで色を指定していた場合,メニューのSave Colorschemeを選ぶことで,色設定がメインプロシージャウィンドウにマクロとして書き出されます.このマクロを実行することで,Igor Proを再起動した際にも色設定を再現できるようになります.

追記 (2016/11/21)

Igor Pro 7だと普通に設定できるみたいです.

f:id:ryotako:20161121153150p:plain

*1:この関数を実行後,ウィンドウを再描画させる必要があります.プロシージャウィンドウをスクロールするか,Windowsの場合は他のウィンドウを前面において一度文字を隠すと再描画されます.

Igor Proから外部のエディタを呼び出して編集する

はじめに

Igor Proでプロシージャをよく書くようになると,使い慣れたテキストエディタでプログラムを書きたい,という欲求が高まってきます.

しかし,プロシージャファイルを外部で変更するためには,ファイルをIgor Proから切り離さなければなりません. これはMac版のIgorではとくに重要で,メインプロシージャウィンドウに#include文を書いて読み込んだファイルを,そのまま外部エディタで変更して再コンパイルするとIgorがフリーズします*1

つまり,#includeで読み込んだファイルを編集したい場合,その前に#include文を消してやる必要があります.

一応,#include文を消すという操作をプログラムから行う方法はあって

Execute/P "DELETEINCLUDE \"procname\""
Execute/P "COMPILEPROCEDURES "

で消せます*2

ただ,この方法にも問題はあって,#includeで読み込んだファイルで定義されている関数を他で使っていた場合にはコンパイルエラーになります.こうなってしまうと,コンパイルエラー中は(独立モジュール*3として書かれていない)すべてのユーザ定義関数が無効になるので,手動で#include文を書きなおして再コンパイルすることになり面倒です.

上記の問題を解決しつつ,外部のエディタで簡単に安全にプロシージャを編集する方法を模索した結果を,以下のサイトで公開しています.

github.com

消しても問題にならない#include文と,消すとコンパイルエラーになる#include文を区別するためにファイルをincludeする機構そのものを新たに用意しました.

使い方

まずinclude.ipfをダウンロードして,User Proceduresフォルダ以下に置きます. その後,Igor Proceduresフォルダ以下に適当な.ipfファイルをつくり,以下の書式*4で読み込みたいプロシージャを書いていきます.

#include "include"

// 使いたい外部エディタを指定しておく.
// Windowsでは,パスを通してあるのでなければフルパスを指定
override strconstant Include_WinEditor="C:¥Program Files¥vim74-kaoriya-win64¥gvim.exe"
// Macではアプリ名でOK
override strconstant Include_MacEditor="MacVim"


Function IncludeList() // 関数名はIncludeListにしておく必要がある.
  include#start()

  // 読み込みたいプロシージャを列挙する.これが#includeの代わりになる
  include("CommandPanel")
  include("relabel")
  include("resize")

  include#finish()
End

IgorProを再起動するとメニューバーにIncludeという項目ができているので,その中のIncludeという項目をクリックします.これで,プロシージャの読み込みが行われます.

この段階でメインプロシージャウィンドウを見ると以下のようになっています*5

#include "include_procedures",optional // <- プロシージャの管理をこの一文に凝縮

メインプロシージャウィンドウに関数を書いていき,includeした関数を使用する場合には,メインプロシージャウィンドウに#include文を書いていきます.

#include "include_procedures",optional

#include "sample" // <- 以下で使用する関数を含むものは,本来の#include文を書く.

Function do_something()
  sample#somefunction() // sample.ipfがないとコンパイルエラーになる.
End

メニューバーのIncludeメニューからEdit Externallyを選択すると,読み込んだプロシージャウィンドウを外部エディタで編集できます.ただし,どこか他所で使われているためにプロシージャをIgorから切り離せなかった場合は外部エディタでは編集できません(コンパイルエラーを出さず,単にエディタが開きません).

注意点

この方法は,include_procedures.ipfというファイルに(必ずしも関数が使用されるとは限らない)プロシージャを列挙することで問題を解決しています.そのため,

  • User Proceduresフォルダ直下にinclude_procedures.ipfというファイルが勝手に作成される.
  • include_procedures.ipfを外部エディタで編集すると問題が発生するおそれがある.

といった問題点があります. 現在も,もっとよい解決方法がないか模索中なので,よいアイデアがありましたらぜひご連絡ください.

*1:includeしたファイルがincludeしているファイル,は外部で変更して再コンパイルしてもその変更が反映されないだけで済むようです

*2:Execute/PはExecuteではできないことが色々できる操作関数で,複数のエクスペリメントファイルのマージをしたり,メインプロシージャウィンドウに任意の文字列を挿入する,といった芸当が可能です

*3:独立モジュールに含まれる関数は,他のプロシージャのコンパイルが失敗していても使うことができます.ファイルの頭に#pragma IndependentModule=procnameと書くことで独立モジュール化できます.しかし他のプロシージャに依存しない,という制約のため,includeの挙動が特殊,メニューの書き方が特殊,グローバルな定数を参照できない,というように扱いが難しいです.

*4:vim等でプラグインマネージャを使っている方にはお馴染みの書式.

*5:#include文の末尾のoptionalは,読み込もうとしたファイルが見つからなくてもエラーを出さない,という指定です.つまり,この状態で他の(プロシージャの入っていない)パソコンに.pxpファイルを持って行ってもコンパイルエラーを吐きません.

Igor Proにシェルを導入して作業効率を大幅にアップする

はじめに

Igor Pro上で動くシェルのようなコントロールパネルを作成しました.名前はシンプルにCommandPanelです.

背景

Igor Proはマウスを用いたグラフィカルユーザーインターフェース(GUI)と,コマンド入力によるキャラクターユーザーインターフェース(CUI)の両方を備えた強力なグラフ作成ソフトです.

マウスによる直感的な操作が可能な一方で,シンプルな内部プログラミング言語*1CUIの組み合わせにより,定型処理の自動化を容易に行うことができます.

しかしながら,Igor Proの標準のコマンドラインインターフェースはそれほど便利なものではありません.

f:id:ryotako:20160830212449p:plain

具体的な不満点としては次のようなものがあります.

  • Duplicate, AppendToGraphのような長いコマンドを入力するための入力補助機能(短い別名の設定や入力補完)がない.
  • せっかくコマンドの実行履歴を記録しているのに,それを検索する機能が乏しい.
  • GUI操作の結果もコマンド履歴と同じウィンドウに書き出されるため,コマンド履歴が混沌としやすい.
  • まとめて何かを実行したい場合は.関数を書く必要がある.(V_で始まる名前の変数を一括削除せよ,といった指示はコマンドラインからは出せない.)

Igor ProのGUIは非常に洗練されたものであるだけに,コマンドウィンドウの機能が申し訳ばかりのものであるのは非常に残念です.

解決

CUIでパソコンを操作するための,シェルと呼ばれるソフトがあります.

Windowsでは普段意識することはありませんが,他のOSではbashと呼ばれるシェルがもっともポピュラーなものです. コマンドに短い別名をつけたり,コマンドの入力補完を行ったり,コマンドの実行履歴の検索ができたり,コマンドを展開して複数の処理を一気に行ったり...といった機能により快適なCUI操作を実現しています.

Igor Proでもbashのようなシェルが使えればきっと便利だろう...と思ったので,Igor Pro上にそれっぽいものを作りました.

github.com

使い方

上記のサイトからCommandPanel.ipfをダウンロードして,Igor Proに読み込んでください.

(Igor ProceduresフォルダにダウンロードしてIgor Proを再起動するか,User ProceduresフォルダにダウンロードしてIgor上のプロシージャウィンドウに#include "CommandPanel"と書いてください.)

詳しい使い方は日本語のWiki に記載しているのでそちらをご覧ください.

ここでは,詳しい説明のかわりにCommandPanelを使った便利な操作の例をいくつか紹介します.

コマンドやパス名を補完する f:id:ryotako:20160901012929g:plain 

コマンドやパス名を展開する f:id:ryotako:20160901015356g:plain

コマンド履歴をキーワードで絞り込む f:id:ryotako:20160901015627g:plain

おわりに

Igor Proにシェルのようなものを作りたい,というアイデアは以前からあって*2試行錯誤の末このような形にまとまりました. 現在では,これなしのIgorには戻れない,というレベルで依存しまくっています.

ただしこのプロシージャ,Igor Pro7では動きません.これが原因で,Igor Pro6からIgor Pro7に移行できずにいたりするのですが...

*1:実はこのIgor Pro内部プログラミング言語の名前がわからないので.もし知っている方がいれば教えて欲しいです.GitHubではIGOR Proという項目に分類されていますが...

*2:実際はunite.vimやpecoのような絞り込み可能なインターフェースがIgorにも欲しい! という欲求が同時にあって,今のような形に.

複数ファイルを自動的にフォルダ分けしてIgor Proに一括読み込みする

追記 (2016/9/25)

しばらく,動作しないバージョンをGitHubにアップロードしてしまっていました.以前ダウンロードして動かなかった方は,もう一度お試しください.

はじめに

f:id:ryotako:20160822223406g:plain

Igor Proで複数ファイルを同時にロードするプロシージャを作りました.ファイル名を頼りに,いい感じに階層化したデータフォルダを作ってウェーブを読み込みます(言葉では説明しにくいので,上のデモを見てください).

上記のデモでプロシージャウィンドウに何か書いてありますが,このようにして簡単にロードの設定(最初の数行を無視するとか,CSVファイルであるとか)を追加できます.

また,特定の種類のファイルを読み込んだら自動で何かを実行する,といった設定も可能です*1

背景

Igor Proでデータを扱う際は通常,データをIgor内部のデータフォルダに入れて管理します.一度内部にデータを読み込んでしまえば,Igor Proのシンプルな内部スクリプト言語を用いてデータを煮るなり焼くなり好きにできます.

しかしデフォルトのIgor Proでは,ファイルをひとつずつロードする必要があり,データ解析の最初のステップが面倒です.

複数ファイル読み込みができない点に不満を感じるIgor Proユーザーは多いようで,IgorのコミュニティサイトIgorExchangeで最もダウンロードされているプロシージャは,複数ファイルを読み込むためのもの(MultifileLoader)だったりします.

ただ,上記のMultifileLoaderが私のmacで動かなかったのと,追加したい機能があったので代替を作りました.

使い方

こちらからmultiload.ipfをダウンロードしてIgor Proに読み込んでください.

github.com

デフォルトではメニューバーにMultiLoadという項目が追加されるはずです.Standard Settingという項目をクリックすると,拡張子がtxtかdatの標準テキストを複数選択するウィンドウが出ます.ファイルを読み込む際には,ファイル名を_(アンダーバー)と(半角空白)を区切り文字として単語に分解し,共通の単語を持つファイルが同じフォルダに入るようにフォルダを自動生成します.

Standard Settingでは,ファイルは標準テキストファイルであるとして読み込みます.ファイルの冒頭5行はコメントなので無視したい,といった場合の特殊なファイル読み込みには対応していません.その場合は,MultiloadメニューのGeneral Settingをクリックすると,設定を変更して読み込みができます*2

ユーザー定義の設定の追加

multiload.ipf の冒頭に以下のような様式でStandard Settingが定義されています,これをコピペして書き換えることで,好きな設定を追加できます.関数名をMultiload_で始まるものにしておくと,メニューにも自動で項目が追加されます.

// Menu: Standard Setting (*.dat, *.txt)
Function Multiload_Standard_Setting()
    STRUCT Multiload ml // これは呪文なので気にしない.
    ml.command    = "LoadWave/A/D/G/Q %P; KillVariables/Z V_Flag; KillStrings/Z S_waveNames" // ファイルを読み込みに使うコマンド.%Pはパスの意.
    ml.dirhint    = "%B" // フォルダの自動生成のための文字列.そのうち詳しい記事を書く予定.
    ml.filetype   = "Data Files" // ファイルの種類.ファイルを開くためのウィンドウに表示されるだけなので,適当で構わない.
    ml.extensions = ".dat;.txt" // 読み込み対象にするファイルの拡張子.;を区切り文字として複数選択可.
    ml.delimiters = "_; " // ファイル名の中の単語の区切り.sampleA-10K-a_axis.datのようにハイフンで区切る流儀の場合,これを"-"に設定.
    ml.load(ml) // 読み込みの実行そのもの.
End

オプション

私の作ったプロシージャに共通する設定ですが,定数を上書きすることによってメニューバーに表示する文字を変えることができます.

override strconstant MultiLoad_Menu="<<" // デフォルトではMultiloadと表示される

残念ながら⇪のようなユニコード文字はメニューに表示できませんが,数学記号や☆くらいならメニューの名前にできます.

*1:このプロシージャの標準設定(standard setting)では,ファイルを読んだ後にV_FlagとS_waveNamesを削除する,といった処理を自動実行します.ロードしたウェーブの名前と数は現物を見ればわかる,ということで.

*2:ちなみに,ファイルの5行目まで無視するには Commandを"LoadWave/A/D/G/L={0,6,0,0,0} %P"に設定します.%Pは実行時にファイルのパスに展開されます.

サイズを揃えて,グラフの再利用性を高めるIgor Proプロシージャ

はじめに

GUIベースのグラフ作成ソフトであるIgor Proでは,グラフウィンドウの端をドラッグすることでグラフサイズを自由に変更できます. しかし自由に変更でき過ぎるために,作ったグラフのサイズがまちまちになりがちです.

たとえば1年前に作ったグラフと最近の結果を横に並べて比較したい,といった場合,グラフのサイズを揃える必要があります.この際,グラフサイズが適当だと,過去のIgorファイルを開き直してサイズを調べ直さなければなりません. (そして多くの場合,なんで自分は7.23 cm × 6.19 cm なんて半端なサイズの図を作ったのだろう...と思うことになるのです)

そこで,グラフをきりの良いサイズに変形するプロシージャを書きました.

github.com

使い方

上のサイトからresize.ipfをダウンロードして,Igor Proに読み込んでください*1.

f:id:ryotako:20160816034054p:plain

メニューバーから,最前面のグラフのサイズを変更できるようになります. デフォルトでは過去3回までの変更履歴が記録され,メニューバーに>>で始まる項目として表示されます.その項目をクリックすると,過去の設定を再利用できます.

メニューバーのCapture Sizeをクリックすることで,最前面のグラフサイズを記録することもできます.過去の履歴と同じく,>>で始まる項目としてメニューバーにサイズが表示されます.

オプション

sbapshot.ipfと同じく,このプロシージャも定数をoverrideすることで挙動を変更できます.たとえば,次のようにメインプロシージャウィンドウに書いてください.

override strconstant Resize_Menu     = "Graph;-" // メニュー項目をメニューバーの「グラフ」配下に配置
override strconstant Resize_Unit     = "inch"    // 単位をインチに変更
override strconstant Resize_Range    = "1;2;3;4" // メニューに表示するサイズ候補を1, 2, 3, 4に変更
override constant Resize_AutoLock    = 1         // サイズを変更したあとで,サイズを固定(ドラッグによるサイズ変更不可)
override constant Resize_ReuseSetting= 5         // 変更履歴を5回まで記録

*1:Igor Proceduresフォルダに入れてIgorを再起動するか,User Proceduresフォルダに入れてプロシージャウィンドウに#include "resize"と書いてください.

Igor Proですべてのグラフを保存する

はじめに

Igor Proのエクスペリメントファイル上に存在する,すべてのグラフを一度に保存するプロシージャを書きました.

それだけだとforループを回すだけで芸がないので,エクスペリメントを保存したときや終了したときにグラフを自動保存する機能もつけています.

f:id:ryotako:20160806015154g:plain

使い方

以下のサイトからsnapshot.ipfをダウンロードしてIgor Proに読み込んでください.

github.com

メニューバーから,保存の形式*1 と自動保存をするかどうか*2 を設定できます.

エクスペリメントファイルが存在するディレクトリに「エクスペリメント名_figures」というディレクトリが作成され,毎回ここにグラフが保存されます.同じ名前のグラフは毎回上書き保存されるので気をつけてください.

オプション

メインプロシージャウィンドウ*3に以下のように記述することで,snapshot.ipfを直接書き換えることなしにプロシージャの挙動を変更できます.

override constant    Snapshot_Resolution = 2 // 4 is default value of Igor Pro  
override constant    Snapshot_ColorPrint = 1 // 0 means RGB and the others means CMYK
override strconstant Snapshot_Menu = "Graph;-;(Snapshot" // Menu title  
override strconstant Snapshot_DefaultFormat = "pdf" // pdf, tiff, jpeg, png, pict, or eps
override strconstant Snapshot_DefaultHook = "Save" // Save, Quit, or Save;Quit

3行目の設定をするとメニューが「グラフ」メニュー配下に表示されるようになります.

プロシージャを書き換える必要がないとはいえ,毎回上の設定をメインプロシージャウィンドウに書くのは手間です.こういった設定をまとめて行うためのプロシージャ(override.ipf)も書いているので.これもそのうち記事を書く予定です.

おわりに

自分でもよく使っているプロシージャのひとつです.

自動保存を有効にしていると,以前作ったグラフを探すのにIgorを開かずに済むので便利です.またグラフを大量に作ってしまった時など,Igor上で探すより,全部保存してからファインダー(エクスプローラ)上で探すほうが手っ取り早かったりします.

*1:pdf, tiff, jpeg, png, pict, epsのいずれかを指定できます.Windowsではpictがbmp形式になります.

*2:ファイルを閉じるとき,あるいはセーブするときにすべてのグラフを自動保存させることができます.グラフ数が多いと保存に時間がかかり,一見フリーズしたような挙動になるので注意してください.

*3:Ctrl+M or Cmd+Mで開かれる,エクスペリメントファイル固有のプロシージャウィンドウのことです.

Yet another 連番生成するVimプラグイン

はじめに

一体何番煎じなのか分かりませんが,連番生成するvimプラグインを作りました.

といっても,改行するごとに数字が増えていく,というタイプの連番に特化したものです.

github.com

f:id:ryotako:20160805211505g:plain

私は普段,Igor Proという解析ソフトのスクリプトをよく書きます.その際,一行コピペしてその行の数字を1ずつ増やす,という作業が頻出したため,これをなんとか楽にしようと思ったのが今回の動機です*1

ぐぐってみたところ,vimで連番生成するには,マクロを使うかvim.rengbangが定番とのこと.

ただ,マクロはその行に何回数字が現れるのかで変わってくるし,正規表現を使うvim.rengbangはプログラミングが本職でない自分には敷居が高いし...

そんな中,最近のvimではvisualモードでg<C-a>することで,1行ごとに増分を増やしつつインクリメントできるのを知りました(vim-jp » Visual モード時の CTRL-A/CTRL-X について).

かなり直感的で分かりやすかったのですが,これは各行の最初に見つかった数字にしか作用しません.

そこで,行全体にインクリメントするコマンドと,行を単位としてvisualモードでg<C-a>するコマンドを作りました.

インストール

NeoBundle "ryotako/vim-incline"
NeoBundle "tpope/vim-repeat" // 必須ではないが,入れるとドットリピートが可能に.

マッピング

" <C-a>や<C-x>のように使います。
" 3gaとすれば現在の行に含まれる数値が3ずつインクリメントされます。
map ga <Plug>(incline-inc)
map gx <Plug>(incline-dec)

" 行選択モードでのみ、行全体インクリメントを適用します。
" 通常のビジュアルモードや矩形選択モードでは標準の<C-a>, <C-x>を適用します。
vmap <expr> <C-a> mode() ==# "V" ? "\<Plug>(incline-inc)" : "\<C-a>"
vmap <expr> <C-x> mode() ==# "V" ? "\<Plug>(incline-dec)" : "\<C-x>"

" 行選択モードで選択した行のインクリメントを行いますが、インクリメントする数値が後の行ほど増えます。
" 連番の生成をするのに便利です。
vmap <expr> g<C-a> mode() ==# "V" ? "\<Plug>(incline-inc-inclined)" : "g\<C-a>"
vmap <expr> g<C-x> mode() ==# "V" ? "\<Plug>(incline-dec-inclined)" : "g\<C-x>"

おわりに

ぶっちゃけると,一度Vimプラグインを作ってみたかった,というのが正直なところです.(なので,コードにつっこみとか入れてもらえるととても嬉しい)

他の連番生成プラグインのような汎用性はないものの,素の<C-a>やg<C-a>と挙動が似ているのが特徴かと思います.

本当は英語ドキュメントとかしっかり書こう,と思っていたのですが,最近また新たな連番生成プラグインが生まれていたので,焦って記事にした次第でした.

*1:冒頭のデモのような状況では,Igor Proの仕様上forループが回せないのです.