MATLABアプリを「外から」ぶったたく方法

# はじめに
MATLABの（割と）最近の便利機能としてApp Designerがあります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302506/ceb16943-cc52-481c-7964-666883de0533.png)

詳しくは下記の記事を参照ですが、ドラッグ&ドロップでGUIを設計できるためアプリ作成をめっちゃスムーズに行うことができます。（語彙）
[MATLABで簡単にGUIを作ろう！](https://qiita.com/griffin921/items/d761abc656542f62a611)

どれぐらいスムーズかというと、気が付いたらアプリを滅茶苦茶作りこんでしまい、後になってから「<b>やべっ、再利用性を考えたらコードをアプリに書くんじゃなくて関数化しとくべきだった…</b>」と後悔するぐらいにスムーズです。

別に後から関数化すればよいだけの話ですが、コードの量が嵩みがちなアプリから必要な個所を抜き出して関数化するのはちょっと面倒です。

本記事はそのような面倒を避けるための方法を提案したもので、具体的にはMATLABアプリの関数やプロパティを「外から」、すなわちmファイルから読み書きするにはどうしたら良いか？の解説を行います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302506/07c888c6-32ed-1c74-e9df-07e3debaa072.png)

余談ですがMATLABアプリは要するにクラスなので、クラスの作法を理解している場合は本記事は飛ばし読みで十分と思います。読んでほしいポイントをあえて挙げるとしたら 3.1 かなぁ。


# 1. 解説に用いるアプリ
App Designerのサンプルに「住宅ローン計算器」があったので、これを例として用います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302506/7efbd259-ede3-81ac-66b4-0f4f13765c37.png)
利率やローン年数をもとに、月々の支払額やら元本(Principal)とか利息(Interest)とかを計算してくれるようです、知らんけど。

ローン年数を色々変えた場合の支払額がどうなるか？　を調べたいと思った場合に、計算をアプリ内に組み込んでいた場合はアプリをポチポチいじって結果をエクセルとかにまとめなければなりません。
耐え難い作業ですね。
ローンの支払いのように。

効率化したいですよね？
ローンの支払いのように。


ということで、「外から」アプリを読み書きすることで解決します。


# 2. データを外から出し入れできるようにする
# 2.1 データの名前を調べる
例として、入力＝ローン年数(Loan Period)を書き換えた場合の、
出力＝月々の支払い(Monthly Payment)　と、元本(principal) を取り出したいものとします。

アプリ画面にテキストエリアが存在する情報については、設計ビューから該当のテキストエリアを左クリックすると右側ウィンドウにてコード内でのオブジェクト名がグレーで強調されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302506/5f4fa955-23e3-9171-837b-45dc0d7203f7.png)
ローン年数は`LoanPeriodYearsEditField`、
月々の支払いは`MonthlyPaymentEditField`というオブジェクト名のようです。
またこれらのオブジェクトの数値については`LoanPeriodYearsEditField.Value`のように定義されているようです。

一方で　principal(グラフの青線)　はテキストエリアがありません。
この場合、principalが表示されるグラフを右クリックしてグラフのオブジェクト名を調べ、コード内でどのような処理が行われているかを調べる必要があります。
オブジェクト名は`PrincipalInterestUIAxes`だったので、コード該当箇所は下記。

```matlab
            % Plot the principal and interest
            plot(app.PrincipalInterestUIAxes,(1:nper)',principal, ...
                (1:nper)',interest);
            legend(app.PrincipalInterestUIAxes,{'Principal','Interest'},'Location','Best')
            xlim(app.PrincipalInterestUIAxes,[0 nper]); 
```

データ名はそのまま、`principal`であったことが分かります。

# 2.2 データの公開／非公開を調べる
コードビュー内をデータ名で検索して調べます。
`LoanPeriodYearsEditField`、`MonthlyPaymentEditField`についてはいずれも`public`すなわち公開オブジェクトとなっていることが分かります。
この場合、外部から読み書きする上での特別な措置は不要です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302506/822a5147-0cf9-3fdf-87dc-3ba21e6dd249.png)


一方でグラフ内に表示されていた`principal`で調べると、publicプロパティとしては定義されていないようです。この場合、publicプロパティに引き出してやる必要があります。次節参照。

## 2.3 非公開データの公開化
まずはじめに、publicプロパティの設定枠を準備します。
コードビューから下記のボタンをクリック。（別に手打ちでも良いです）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302506/de1a813d-456c-80e7-5a0d-0cd630b897e5.png)

公開プロパティを記載する欄が出来るので、そこに公開プロパティとしての名称を書きます。

```matlab
    properties (Access = public)
        principal_pub % Description
    end
```

`principal`自体を公開プロパティとしても良いですが、便宜上新たなプロパティとして`principal_pub`を定義しました。
続いてコード内で`principal`を公開プロパティである`principal_pub`に受け渡して外部から読めるようにします。
今回はグラフの描画直後に受け渡しの処理を書きました。

```matlab
            plot(app.PrincipalInterestUIAxes,(1:nper)',principal, ...
                (1:nper)',interest);
            app.principal_pub = principal;
```

アプリ内部で公開プロパティに読み書きを行う場合、上記のように`app.`を付けてやる必要がある点注意下さい。

# 3. アプリを外から実行可能にする
## 3.1 コールバック関数の公開化
この住宅ローン計算器は、「Monthly Payment」ボタンを押すことで計算が行われます。
このため、このボタンを押したことによって実行される関数を公開化する必要があります。
プロパティと同じ要領で、公開関数の作成を行います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302506/031e5ff1-2ed1-c3dc-0589-f701b22e4f6c.png)

ボタンを押した場合のコールバック関数 `MonthlyPaymentButtonPushed`は既にプライベート関数として定義されており、同じ関数名を公開関数として記載することは出来ません。
このため、下記のように関数名は別の名前で定義しておき、その中で呼び出したい関数`MonthlyPaymentButtonPushed`を呼ぶような処理とします。

```matlab
    methods (Access = public)
        function MonthlyPaymentButtonPushed_pub(app)
            MonthlyPaymentButtonPushed(app)
        end
    end
```

関数に対する措置はこれだけです、簡単。

# 4. アプリを「外から」ぶったたく
## ポイント：アプリをオブジェクトとして定義する
冒頭で少し述べた通り、アプリ＝クラスなのでmファイル内でオブジェクトとして定義することが出来ます。アプリのファイル名を`Mortgage_EX.mlapp`とすると、オブジェクト定義は下記のコマンドにて可能です。

```matlab
app = Mortgage_EX;
```
オブジェクト定義したら後は簡単で、あとは公開データに書き込む・公開関数を呼び出す・公開データを読み込めばよいのです。

## サンプルコードおよび実行結果
下記のデータを取りだすためのコードを下記に示します。
・ローン年数10~40年の場合の元本
・ローン年数10~40年の場合の月々の支払額


```matlab
yearsArry = [];
mpArry = [];
app = Mortgage_EX;
for i = 1 : 4
    years = i * 10;
    app.LoanPeriodYearsEditField.Value = years;
    app.MonthlyPaymentButtonPushed_pub;
    prLegend = "principal("+ num2str(years) + "years)";
    figure(1);
    hold on;
    plot(app.principal_pub,"DisplayName", prLegend);
    legend();
    
    yearsArry = [yearsArry years];
    mpArry = [mpArry app.MonthlyPaymentEditField.Value];
end

figure(2);
hold on;
mpLegend = "MonthlyPayment("+ num2str(years) + "years)";
bar(yearsArry,mpArry);

```

ローン年数10~40年の場合の元本
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302506/351b53a8-93e0-8cb5-4838-0056eede0a30.png)

ローン年数10~40年の場合の月々の支払額
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302506/44d347d1-0b3d-51d3-87cb-7d0bb45913cc.png)

ね、簡単でしょう？

# おわりに
何気にApp Designer関連の記事はこれが始めてでした。
ちなみに著者は余り自分でApp Designer作ることは無く、本手法は「自分意外の誰かに作って頂いたアプリを俺々mファイルでいじくりまわす」事を目的として開拓したものとなります（ひどい）
ボタン押したりするのめんどくさいからね、しょうがないね。