2009年 12月 15日

テストで result と exptected が違うときに色つき diff

結構長い文字列を比較させるとどこが違っているのかよくわからん…… ということがあるので、クソコードを書いて結果を読みやすくしました。Test::Builder::_is_diag を書きかえています

use Test::More;
use Algorithm::Diff;
use Term::ANSIColor;

sub colordiff {
    my ($a, $b) = @_;
    my $ret = "";

    my $diff = Algorithm::Diff->new([ split /\n/, $a ], [ split /\n/, $b ]);
    $diff->Base(1);
    while ($diff->Next) {
        if ($diff->Same) {
            $ret .= "  " . $_ . "\n" for $diff->Items(1);
        }
        elsif (!$diff->Items(2)) {
            $ret .= colored("- " . $_, 'red').   "\n" for $diff->Items(1);
        }
        elsif (!$diff->Items(1)) {
            $ret .= colored("+ " . $_, 'green'). "\n" for $diff->Items(2);
        }
        else {
            my $lineDiff = Algorithm::Diff->new(
                [ split //, "* " . join("\n* ", $diff->Items(1)) . "\n" ],
                [ split //, "* " . join("\n* ", $diff->Items(2)) . "\n" ]
            );
            $lineDiff->Base(1);

            while ($lineDiff->Next) {
                if ($lineDiff->Same) {
                    $ret .= $_ for $lineDiff->Items(1);
                } elsif (!$lineDiff->Items(2)) {
                    $ret .= colored($_, 'red')   for $lineDiff->Items(1);
                } elsif (!$lineDiff->Items(1)) {
                    $ret .= colored($_, 'green') for $lineDiff->Items(2);
                } else {
                    $ret .= colored($_, 'red')   for $lineDiff->Items(1);
                    $ret .= colored($_, 'green') for $lineDiff->Items(2);
                }
            }
        }
    }
    $ret;
}

{
    *Test::Builder::_is_diag  = sub {
        my ($self, $got, $type, $expect) = @_;

        $self->_diag_fmt( $type, $_ ) for \$got, \$expect;
        my $diff = colordiff($got, $expect);

        no strict;
        local $Test::Builder::Level = $Test::Builder::Level + 1;
        return $self->diag(<<"DIAGNOSTIC");
         got: $got
    expected: $expect
$diff
DIAGNOSTIC
    };
}

あと、printable ではない文字を、そのままテスト結果に吐かれても困るので

{
    no warnings 'redefine';
    *Test::Builder::_diag_fmt = sub {
        my ($self, $type, $val) = @_;
        if ( defined $$val ) {
            if( $type eq 'eq' or $type eq 'ne' ) {
                $$val = dumper($$val);
                $$val = "'$$val'";
            }
            else {
                $self->_unoverload_num($val);
            }
        } else {
            $$val = 'undef';
        }
    };
}

sub dumper ($) {
    my ($str) = @_;
    $str =~ s{([^\x0a\x20-\x7e\x{3040}-\x{309F}\x{30A0}-\x{30FF}])}{
        sprintf('\\x%02x', ord $1);
    }eg;
    $str;
}

とかやっています。見えない文字があるとかは切実に困るので割と便利です

Data::Dumper は null 文字を Dump しない

全く知らなくて少しまえに大変にハマったのですが、Data::Dumper は普通に使うと \0 を Dump しないようです。(してるけど見えない?)

my $str = "\0";
Dumper $str; #=> ''

[ unpack("C*", $str) ]; #=> [ 0 ];

普段 p を Data::Dumper に展開するようにしてデバッグしているので本当にハマります。

個人的にはデバッグ用に

  • utf8 flagged 文字列かどうかが見た目でわかる
  • \0 がちゃんと出てくる
  • 表示できそうな文字 (英数字・ひらがなカタカナ程度) 以外は全部 \x{} に

みたいなのが簡単にできるモジュールが欲しいのですが既にあるのかな

gerry++

プロンプトをゆのっちから文乃さんに

2009年 12月 14日

そろそろ紅葉も飽きましたね。秋だけにね (ハハハ)

もっと品格や信頼を失くしていかないと!! そんなもんあっても無駄だ!

アナルファック!

2009年 12月 13日

うちの5D先生が完全に後ピンなのが最近気になって仕方がない。AF が基本的に信用ならないので、どんぐらい後ピンか記憶して MF するしかない (ファインダー像ともピントがズレてるので素子の位置がおかしいっぽい?)。近接ならまだいいんだけど遠くのだとピントきてんのかよくわからないのでピント周辺を連射して確認してる (マクロだと)。

が、最近バッテリのへたり具合がひどくて、充電器側で満充電になってもカメラ側では常に減った状態になってしまうぐらい (なので手持ちバッテリで素子清掃 (ミラーアップ) ができない)。IS 付きはかなりバッテリ使うらしくだいぶしんどいなぁ

AF の仕組みがあんまよくわかってないなぁ。フォーカス関係で起こりえる現象のマトメとかないのかな。

  • AF,MF 絞ることでピント位置が後になっていく
    • 球面収差があり、開放側でピント調整されているおこる。 50mm F/1.4 USM とか?
    • (絞るほど口径が小さくなり、球面収差によるピントズレの範囲は狭くなるので、平均的なピントの中心位置が移動していく)
    • 絞った状態で MF すればいいはず
  • AF 被写体までの距離によってピント位置が変わる
    • 距離によって球面収差が変わることで起きる? (よくわかってない)
    • 近くなるほど球面収差が大きくなるので、近い位置でピントが調整されていると遠くを撮ったときに前ピンになる?
    • MF すればいいはず
  • AF,MF ファインダー中心でピントをあわせたあとに構図を変えたときの後ピン
    • カメラを平行に移動させているわけではないため (コサイン誤差)
    • 構図変えたあとに MF
  • AF 色によるピント誤差
    • ピントをあわせる光の周波数によって位相検知にズレが生じるらしい (気になる程度なのかは解らない)
    • MF
    • → 最近のカメラは光源によるAFズレを補正する機能がついてる

レンズ変えてもAFおかしいから、十中八九ボディ側だろうな、と思ってはいたけど、確信が持てなかったので、古い EOS D30 というのをひっぱりだしてきて AF させたら、ちゃんとジャスピンしてくれた。D30 先生には埃かぶせておいて申し分けない気分になった。

D30 は撮影画像にひどいノイズが入るようになってしまってから全く使ってなかったけど、今日撮影してみたら、ノイズは入るものの、Photoshop 先生が完全に補正してくれるので割とまだ使えそうな感じだった。RAW は生きているのかもしれない (JPEG の処理部分だけ壊れるとは思えないけど……)

とはいえ、ISO400 でも結構カラーノイズが多いし、液晶は小さいし、300万画素だし、これに比べるとデジカメって進化してんだなぁと心底思った…… それでも10年程度しか経ってない

そんなことはどうでもいいけど、AF でちゃんとピントが合うのってこんなに感動的なことだったんだ!!! 失なって気付くことばかりです……

しばらく D30 使ってもいいかもなぁと思った。ちなみに 5D とバッテリは共通。画素数は4分の1だけど、基本的に僕の用途 (ウェブにのっける程度) だと画素数多くてもHDDの肥やしになるだけだ。センサがAPS-Cなのと液晶小さいのだけが運用上の問題かな