legendx: グラフ別に凡例を表示する/しない設定を簡単にできるlegendを作った - MATLAB

## Abstract
`legend`の強化版，`legendx`を提案します．`legendx`では，凡例に表示させる/させない設定を簡単にできるようになります．

https://gist.github.com/Mya-Mya/35553a00c7bffe1577bbd09957c338c2

`legendx`では，`DisplayName`引数を指定したグラフについては凡例が表示され，`DisplayName`引数を指定なかったグラフについては凡例が表示されないようになります．具体的には
```MATLAB
figure
hold on

plot(X,A,DisplayName="log")
plot(X,B,DisplayName="linear")
plot(X,C)%←特に何も指定しないだけ
plot(X,D)%←特に何も指定しないだけ
legendx

hold off
```
と打つだけでAとBの凡例は表示され，CとDの判例は表示されません▼
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3116310/f1cc08a3-58d6-8863-9d1e-eac2d83bf98b.png)

従来の`legend`メソッドでは，一部のグラフのみを凡例として表示したい時，そのコードが煩雑になりがちになっていました．`legendx`では，その問題を解決することができます．

## legendxを普段使いするには
1. `legendx.m`というファイルで[legendxのコード](https://gist.github.com/Mya-Mya/35553a00c7bffe1577bbd09957c338c2)を自分のコンピュータ内の適当な場所に保存します．
1. MATLABの「コマンド　ウィンドウ」に`pathtool`と打ちます．
1. 「フォルダーを追加」を押して，先ほど`legendx.m`を保存したフォルダを選択します．
1. MATLABの「コマンド　ウィンドウ」に`legendx`と打ってなんか動いてる感じがしたら成功です🎉

## 従来の`legend`の厄介ポイント
次の4本のグラフを表示することを考えます．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3116310/b2b2e6db-a936-ac1c-f5ab-e520e95d8eaa.png)

ここで，青と赤のグラフ**のみ**に凡例を付けたいとします．こんな感じ▼
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3116310/6aeaa034-b22b-fcd1-a2d6-e21f9e432fcd.png)

こうするためのMATLABの実装は様々考えられますが，それぞれいくつか問題点があります．

```MATLAB:準備：データの準備
X = linspace(1,10);
A = log(X);
B = X;
C = sin(X);
D = 10 * exp(-X+1);
```
AとBの凡例を表示し，CとDの凡例を表示しないことにします．

最も正統なやり方の1つ目は，次のように判例を表示したいグラフを表すオブジェクトと表示名を`legend`に渡すことです．
```MATLAB:正統なやり方 - オブジェクトと表示名をlegendに渡す
figure
hold on
p1 = plot(X,A);
p2 = plot(X,B);
plot(X,C)
plot(X,D)
legend([p1,p2],["log","linear"])　
%▲
%🥺グラフオブジェクトを取得していないといけない
%🥺グラフに描いた順番を覚えていないといけない
hold off
```
ですが，この方法は表示するグラフが多くなると管理するのが大変になります．

次に示すのも正統なやり方ですが，やはりグラフが多くなった時の管理が大変です．
```MATLAB:正統なやり方 - オブジェクトをlegendに渡す
figure
hold on
p1 = plot(X,A,DisplayName="log");
p2 = plot(X,B,DisplayName="linear");
plot(X,C)
plot(X,D)
legend([p1,p2]) %🥺グラフオブジェクトを取得していないといけない
hold off

```
```MATLAB:正統なやり方 - 表示名をlegendに渡す
figure
hold on
plot(X,A);
plot(X,B);
plot(X,C)
plot(X,D)
legend("log","linear") %🥺グラフに描いた順番を覚えていないといけない
hold off
```
まあこの程度の規模なら正統なやり方でもやれそうではあります．しかし，シミュレーション結果のデータなど，ループしながら何回もグラフを描画する場合などになると，本当に大変になってやってられなくなります．

`legend`はかなり厄介です．例えば，次のように`DisplayName`引数だけで何とかすることができません．
```MATLAB:問題のある書き方
figure
hold on
plot(X,A,DisplayName="log")
plot(X,B,DisplayName="linear")
plot(X,C)%😭displays!!
plot(X,D,DisplayName="")%😭displays!!
legend
hold off
```
▼このように，"data○○"もしくは空白のまま凡例に出てきやがるのです．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3116310/7eb57d3f-3452-28c1-7c01-e4a1038f66db.png)

## legendx
そこでlegendxでは，`DisplayName`が指定されている・空ではないグラフのみを選び，`legend`に渡します．

https://gist.github.com/Mya-Mya/35553a00c7bffe1577bbd09957c338c2

ですので，先ほどの「問題のある書き方」に対して`legend`→`legendx`と置き換えるだけで，所望の動作を実現できます．
```MATLAB:legendx
figure
hold on
plot(X,A,DisplayName="log")
plot(X,B,DisplayName="linear")
plot(X,C)
plot(X,D)
legendx
hold off
```

その他，subplot環境内でもちゃんと動きます．また，[`varargin`という特殊な引数](https://jp.mathworks.com/help/matlab/ref/varargin.html)を使用しているので，`legend`で使える引数(`FontSize`など)も渡せます．
```MATLAB:legendx in subplot / with arguments
figure
subplot 211
hold on
plot(X,A,DisplayName="log")
plot(X,B)
legendx
hold off
subplot 212
hold on
plot(X,C)
plot(X,D,DisplayName="exp")
legendx(FontSize=16, Color="yellow")
hold off
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3116310/4d47da5d-53a8-f14a-53ee-acdb729f5937.png)