前回同様、「データ確認のためちょこっとだけ画像表示させるマクロ」の改良版(ver.3)です。
//FileWatcher_Modoki.ijm
//Detect if there are "New created files" or "Modified files" in selected dir.
version = "3.3.0";
print("");
print("FileWatcher_Modoki.ijm");
print("ver",version);
print("");
checkImageTime = 1800;
var width = 570; //seinen size comic
//var width = 550; //syounen size comic
var height = 1000;
//define var
var zeroTime;
var tempTime = 0;
var flagDetect = 0;
var sCount = 0;
var RECENT = newArray("","","","","");
//select dir
dir = getDirectory("Choose a Directory");
print("Watching :",dir);
print("");
//get zeroTime
zeroTime = getTime();
//Main ope
getDateAndTime(year0,month0,week0,day0,hour0,min0,sec0,msec0);
var min = 0;
while(min < 30){
//Show WaitingCount
getDateAndTime(year,month,week,day,hour,min,sec,msec);
msec = floor(msec/10 -msec0/10);
if(msec < 0){
msec = 100+msec;
sec = sec-1;
}
sec = sec - sec0;
if(sec < 0) {
sec = 60 + sec;
min = min -1;
}
min = min - min0;
if(min < 0) {
min = 60 + min;
hour = hour -1;
}
hour = hour - hour0;
if(hour <0){
hour = 24 + hour;
}
bytes = parseInt(IJ.currentMemory());
bytes = d2s(bytes/1000000,2);
print("\\Update:"+pad2(hour)+":"+pad2(min)+":"+pad2(sec)+":"+pad2(msec),"<",bytes,"MB >");
//Detect New File
list = getFileList(dir);
for(i=0;i<list.length;i++){
lastModifiedTime = File.lastModified(dir + list[i]);
lastModifiedTime = parseFloat(lastModifiedTime);
if(lastModifiedTime > zeroTime){
call("ij.gui.ImageWindow.setNextLocation",0,0);
open(dir+list[i]);
setLocation(0,0,width,height);
close("\\Others");
wait(checkImageTime);
flagDetect = 1;
if(lastModifiedTime > tempTime) tempTime = lastModifiedTime;
sCount++;
RECENT[sCount%5] = list[i];
}else if(lastModifiedTime == zeroTime){
if(fileExistInArray(list[i],RECENT) == 0){
call("ij.gui.ImageWindow.setNextLocation",0,0);
open(dir+list[i]);
setLocation(0,0,width,height);
close("\\Others");
wait(checkImageTime);
flagDetect = 1;
if(lastModifiedTime > tempTime) tempTime = lastModifiedTime;
sCount++;
RECENT[sCount%5] = list[i];
}
}
}
if(flagDetect == 1) {
zeroTime = tempTime;
getDateAndTime(year0,month0,week0,day0,hour0,min0,sec0,msec0);
}
flagDetect = 0;
wait(100);
}
showMessage("Time out");
//-----------------------------------------------------------------------------
function pad2(n){
n = toString(n);
if(lengthOf(n) == 1) n="0"+n;
return n;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
function fileExistInArray(fileName,ARRAY){
output = 0;
for(i=0;i<ARRAY.length;i++){
if(ARRAY[i] == fileName) {
output = 1;
break;
}
}
return output;
}
//-----------------------------------------------------------------------------
コードのざっくり説明
「マクロ開始時の時間を取得し、これをファイル最終更新時間と比較して、新規ファイルを検出する」というシンプルなアルゴリズムです。
ファイルの最終更新時間を調べるために、File.lastModified(path)という命令を使っています。
このFile.lastModified(path)を実行すると、1970年1月1日午前0時0分から数えた時間である「UNIXTIME(単位はmsec)」が出力されます。
UNIXTIMEについてはこちらの記事を。
「UNIXTIME⇄普通の東京時間」で変換するのは面倒なので、『マクロ開始時にgetTimeを使うことで「マクロ開始UNIXTIME」を取得。これをディレクトリ内ファイルの「最終更新UNIXTIME」と比較する』という方法にしました。
マクロ開始UNIXTIME(zeroTime)は、新規ファイル検出時の最終更新UNIXTIMEで随時上書きしていくことで、継続して新規ファイルを検出することができます。
ちょっと脱線して、ややこしいけど大事な解説もしておきます。
getTime()で出力されるUNIXTIMEは「浮動小数点型の数値」、File.lastModifiedで出力されるUNIXTIMEは「文字列」となっています。
ImageJマクロでは、if内で比較を行う際に、「先に書いたモノの型」のルールで比較を行うっぽいです。つまり、if(文字列>数値)と書けば「文字列のルールで比較(昇順ソートで上か下か)」、if(数値>文字列)と書けば「数値のルールで比較(数値として大きいか小さいか)」となります。
コード内のif(lastModifiedTime > zeroTime)のところで、文字列のルールで比較されてしまうと処理が狂ってしまいます。しかも多くの場合で、文字列の比較は求めていないはずです。そこでImageJ側が変な誤解をしないように、parseFloatを利用して、lastModifiedTimeを「浮動小数点の数値」として扱うように明確に指示しています。
以前のverとの比較
せっかくなので前回のデータベース分割式(ver.2)と今回のModifiedTime式(ver.3)と、で処理時間にどれぐらい変化が出るのかを調べてみました。
比較の環境は、
・監視ディレクトリのファイル数は0個、214個、2172個、8100個、10272個の 5条件
・新規ファイルなしで、監視ループ処理を1回だけ回す
・データベース分割式はデータベース作成の時間を含む(毎回ループで更新される部分)
結果
データベース分割式では、ファイル数の二乗に比例して処理時間、つまり、画像表示までの遅延時間が長くなるようです。
データベース分割式では、ファイル数が10,272個では画像表示までの遅延時間が最大1.998秒かかることがわかりました。
Modified Time式では、ファイル数が10,272個でも遅延時間が最大0.252秒で表示できることがわかりました。
以上より、Modified Time式だと、遅延時間をかな〜り抑えることが出来るので、「安心して使える」ということがわかりました。
おしまい
ライセンスなんかは一切無いので、ぜひぜひ自由に使ってみてください!