20
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

MATLAB/SimulinkAdvent Calendar 2019

Day 24

MATLABのプロットでアノテーションをつける

Last updated at Posted at 2019-12-25

MATLABでfigureの中のグラフにアノテーション(矢印)をつける方法を書きます。
ほとんど忘備録であり、他にも方法はあるのかもしれません。

###1.手で張る
いきなり何を言うのかと思うでしょうが、大多数の人はこれでしのいでいるのではないでしょうか。Figureをパワポか何かにコピーして、パワポの上で矢印をつける方法です。
MATLABのノウハウも不要であり、ある意味、無敵と言えます。
やり方がわからず時間もない場合は、ためらわず、これをやることをお勧めします(マジ)。

###2.まともな方法
では、まじめにMATLAB上でアノテーションをつける方法を説明します。
MathWorksのドキュメントには、構文は、

  annotation(lineType,x,y)

こうなっています。
説明を読んで分かった気になり、スクリプトを書いてみます。
サイン波を1周期分描いて、180度の点にアノテーションをつけてみましょう。
まず、グラフを描きます。

annotationwrite.m
t=0:100;
A=sin(2*pi*t/100);%正弦波1周期分

figure(1);
plot(t,A,'r');

figure1.jpg

これにアノテーションをつけてみます。座標はデフォルトでは正規化されているので、座標の指定は0~1の範囲でなければなりません。
1/2周期の部分(50,0)はグラフの真ん中ですから、[0.5 0.5]でよいのでしょうか。

annotationwrite2.m
t=0:100;
A=sin(2*pi*t/100);%正弦波1周期分

figure(1);
plot(t,A,'r');

x = [0.3 0.5];%右側が矢印の先
y = [0.6 0.5];%右側が矢印の先
annotation('arrow',x,y);

figure2.jpg

矢印がずれます。

figure3.jpg

これは、なぜかというと、figure全体で座標が0~1に割り振られており、グラフを描く領域(Axes)は、その一部であることによります。

figure4.png

では、Axesの座標はどこからどこまでなのでしょうか。
これは、下記のようにするとわかります。

annotationwrite3.m
t=0:100;
A=sin(2*pi*t/100);%正弦波1周期分

figure(1);
plot(t,A,'r');

%-------Axesの範囲を調べる ------
AxesHandle=findobj(gcf,'Type','axes');
pt1 = get(AxesHandle,{'Position'});
cell2mat(pt1)%cell配列を数値配列に変換

こうしますと、コマンドウィンドウに、
ans =

0.1300    0.1100    0.7750    0.8150

このように出力されていると思います。この意味は、
figure5.png
こうなります。

###3.アノテーションの座標を計算するfunctionを作ってみました。
以上のようになっていることがわかれば、正しい位置にアノテーションを表示することができるはずです。が、いちいち計算するのは面倒なので、functionを作成してみました。

PositionCalc.m
%% Numfig:figureの中の図面領域の数(1か2)
%% Orderfig:figureの中のどちらのaxesについて計算するか
%% Left:対象のAxesの左端の数値
%% Bottom:対象のAxesの下端の数値
%% Width:対象のAxesの表示幅
%% Height:対象のAxesの表示高さ
%% x: アノテーションをつける場所のx座標
%% y: アノテーションをつける場所のy座標
%% Xpos: アノテーションの正規化されたX座標
%% Ypos: アノテーションの正規化されたY座標

function [Xpos, Ypos] = PositionCalc(Numfig,Orderfig,Left,Bottom,Width,Height,x,y)
if Numfig == 1
    AxesPos = [0.1300 0.1100 0.7750 0.8150];
elseif Numfig == 2
    if Orderfig == 1
        AxesPos = [0.1300 0.5838 0.7750 0.3412];
    else
        AxesPos = [0.1300 0.1100 0.7750 0.3412];
    end
end

X_Ratio = (x-Left) / Width * AxesPos(3);
Y_Ratio = (y-Bottom) / Height * AxesPos(4);

Xpos = X_Ratio + AxesPos(1);
Ypos = Y_Ratio + AxesPos(2);

Axesの座標はデフォルトの座標で固定にしています。
例として、下図の点にアノテーションをつける場合をやってみます。
figure6.png
functionに渡すパラメータですが、
Numfig=1 (Axesは1つ)
Orderfig=1 (1番目のAxesを操作したい)
Left=0 (Axesの左端の座標)
Bottom= -1 (Axesの下端の座標)
Width=100 (Axesの横幅)
Height=2 (Axesの高さ)
x=42 (アノテーションのx座標)
y=0.4818 (アノテーションのY座標)

annotationwrite4.m
t=0:100;
A=sin(2*pi*t/100);%正弦波1周期分

figure(1);
plot(t,A,'r');

Numfig=1;% (Axesは1つ)
Orderfig=1;% (1番目のAxesを操作したい)
Left=0;% (Axesの左端の座標)
Bottom= -1;% (Axesの下端の座標)
Width=100;% (Axesの横幅)
Height=2;% (Axesの高さ)
x=42;% (アノテーションのx座標)
y=0.4818;% (アノテーションのY座標)

[Xpos, Ypos] = PositionCalc(Numfig,Orderfig,Left,Bottom,Width,Height,x,y);

x = [Xpos+0.2 Xpos];% 右側の座標が矢印の先
y = [Ypos Ypos];
annotation('textarrow',x,y,'String','できた!')

figure7.png
このように描画されているかと思います。
矢印の形や大きさなどは変えられます。詳細は MathWorksのドキュメントを見てください。

###追記:矢印か、テキストか、それが問題
コメントをいただいたので、少し追記します。
テキストでアノテーションを入れるのも出来て、前に載せたI2C解析の記事では、テキストでアノテーションを入れています(下図の下の文字部分)。
I2Csample.png
これだと、わりとアバウトな範囲しか示せないですが、ご指摘にあったとおり、矢印がtexで追加できて、グラフ上にドットも打てます。

textannotation.m
t=0:360;
%A=sin(2*pi*t/100);
A=sind(t);

figure(1);
subplot(2,1,1);
plot(t,A,'r');
xlim([0 360]);

%アノテーションを入れる
txt = '\bullet \leftarrow ここが 180度';
text(t(180),A(180),txt);

xlabel('[deg]');
ylabel('Amplitude');

texannotation.png
しかし、もっと混み入った表示をする場合、例えば、下記のような場合、
annotation2.png
グラフに曲線がプロットされていて(緑色)、なにかイベントが発生したところに矢印でアノテーションを入れる。かつ、イベントの種類で矢印の色を変え、さらにイベントの大きさで矢印の長さを変える、というような内容を直感的に図示するとなると、やはり、このような表記になってしまうのでは、と思います。
(追記ここまで)。

###おまけ:Qiitaに動画を埋め込むには
MATLAB EXPOのデモを動画して、Qiitaに埋め込もうとしたところ、多くの先人が指摘しているように、動画はアップロードもできないことがわかりました。
Youtubeだと埋め込みはできないようです。
GIFアニメは画質が汚いし。
なんのかんので、Twitterに動画をアップロードし、Qiitaにリンクを張ると動画埋め込みができることがわかり、それを採用しました。

Twitterで動画をQiita上で公開し、評判はよかったのですが、1つ問題が起こりました。
Twitterのアカウントがフォローされてしまったのです。しかもビミョーな範囲に。
ということで、下手なことはつぶやけないし、来年のMATLAB EXPOの動画を先にTwitterに上げてしまえばネタバレするし。
(ただ、Qiitaの記事をストックするならQiitaのアカウントが必要だけど持ってないし、Twitterのアカウントは大半の人が持っているので、Twitterにフォローかけてしまうのは理解はできます。公開したときに自分がそこまで計算してなかったわけですね)

ということで、お返事は書けませんが、見てはおりますので。

以上でMATLABのプロットでアノテーションを終わります。

おつかれさまでした。

20
10
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
20
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?