pythonからMATLABにデータを送る方法

pythonで定義した変数をMATLABに送る方法がわかりません。
仮に、pythonでA=2と定義した場合、MATLABのワークスペースにA=2をどのように
移転させられますか?

 Risposta accettata

Kojiro Saito
Kojiro Saito il 2 Ago 2019

0 voti

こちらのドキュメントが一番近い例だと思います。
2通り紹介します。
どちらも前提としてPython用MATLABエンジンを使用しますので、まず、こちらのドキュメントを参考に、Pythonでインストールを行います。
ここではWindowsの場合を紹介します。コマンドプロンプトを起動し、以下のコマンドを実行します。
cd "$MATLAB_INSTALL\extern\engines\python"
python setup.py install
ここで、$MATLAB_INSTALLはMATLABのインストールフォルダー(例: C:\Program Files\MATLAB\R2019a)です。
これで、Pythonでimport matlab.engineが使えるようになります。
(1) 起動中のMATLABのワークスペースにPythonから変数を送る場合
起動したMATLABで、セッションを共有セッションにします。
【MATLAB側で実行】
% MATLABセッションを共有セッションにする
matlab.engine.shareEngine
次に、Pythonからmatlab.engine.connect_matlab()で接続し、eng.workspace['A'] = Aの形でPythonの変数をMATLABに送ります。
【Python側で実行
sample.py
import matlab.engine
eng = matlab.engine.connect_matlab()
A = 2.0
eng.workspace['A'] = A
# セッションへの接続を切断
eng.quit()
sample.pyをPythonで実行すると、MATLABのワークスペースに変数が追加されます。
Capture.PNG
(2) MATLABを起動してワークスペースにPythonから変数を送る場合
MATLABを新規に起動させるにはmatlab.engine.start_matlab()を使います。
【Python側で実行】
import matlab.engine
eng = matlab.engine.start_matlab()
A = 2.0
eng.workspace['A'] = A
# 確認用(MATLABのワークスペースから変数Aを取得して、Python側で表示)
B = eng.workspace['A']
print(B)
# エンジンの停止
eng.quit()

9 Commenti

qrqr
qrqr il 2 Ago 2019
ありがとうございます。
コマンドプロンプトで試したのですが、'python'は、内部コマンドまたは外部コマンド、操作可能なプログラムまたはバッチファイルとして認識されません。
このようなエラーが出ますが、原因がわかりません。
宜しくお願いします。
※MATLAB R2019a
※python2.7
Kojiro Saito
Kojiro Saito il 2 Ago 2019
python.exeが環境変数PATHに追加されていないのかもですね。フルパスで指定してみたらどうでしょうか?
C:\Python27\python.exe setup.py install
Toshihiko Baba
Toshihiko Baba il 21 Dic 2022
コメント失礼します。(1)の方法でMATLABのワークスペースにPythonから変数を送ることができましたが、その変数に格納されている値をエディタで使うことができません。(上記の場合、Aに格納されている2を使いたい)どのようにmatlabのコードを書けばよいでしょうか。
すみません、具体的にはエディタで実行しているときに変数の値を更新したいです。
Pythonからデータを送り続け、そのデータをmatlabのグラフにプロットし、リアルタイムでグラフを更新したいです。
現在、matlabでプログラム実行中はPythonからのデータの更新を反映できません。下記のプログラムでは、55行目のdataという変数をPythonから受け取り、グラフをリアルタイムで更新したいです。
figure('Position',[600,600,800,600],'Name','show data','NumberTitle','off');
Xpix=400;
Yline=32;
Pixels=Xpix*Yline;
loop_time=300;
num=linspace(0,4096,Pixels);
X=zeros(1,Pixels);
Y=zeros(1,Pixels);
for i=0:Yline-1
for j=0:Xpix-1
if j==0
X(i*Xpix+j+1)=1;
Y(i*Xpix+j+1)=i;
else
X(i*Xpix+j+1)=j;
Y(i*Xpix+j+1)=i;
end
end
end
gpuX = gpuArray(X);
gpuY = gpuArray(Y);
Z=randn(1,Pixels);
S=25;% plot size
caz=-37.5;cel=30;% original veiw angle
z1=num;
H=scatter3(Z,gpuY,gpuX,S,z1,'.');
xlabel('Distance(m)') ;
ylabel('X,θ') ;
zlabel('Y,Φ') ;
ax = gca;
ax.FontSize = 10;
% color map reference
xlim([-100 4100])
ylim([0 Yline])
zlim([0 Xpix])
clim([0 4096]); % color map scale
colormap(flipud(jet));
set(gca,'YDir','reverse');
H.SizeData = 30;
colorbar;
for I=1:loop_time
Z=data;
%count=1;
%for iy=1:Yline
% for ix=1:Xpix
% tpm=2048+2048*sin((0.5*pi/Xpix*ix)+(2*pi/(Yline-1)*iy)+(4*pi/100*I));
% Z(count)=tpm;
% count=count+1;
% end
%end
if size(Z)==size(X)
set(H,'XData',Z) ;
set(H,"CData",Z)
view(caz,cel);
drawnow
pause(0.00001);
[caz,cel] = view;
end
end
下記のようなforとpauseを使用した周期処理ではなくtimerを使用した周期処理にしてみてください。
pause中であってもPythonからのデータ送信は受け取れませんが、timerの非実行時であれば、Pythonからデータを受け取ることができるはずです。
for I=1:loop_time
% 処理
pause(0.00001);
end
回答いただきありがとうございます。以下のサイトhttps://qiita.com/sanmojih/items/0bd8a326a6a022c4b615を参考にさせていただき、timerを使用して0.1秒ごとにグラフが更新していくプログラムの実装を試みました。
function data_polt_sample()
matlab.engine.shareEngine
fig = figure();
fig.CloseRequestFcn = @Close_fig;
fig.Name = 'data_plot';
t = timer();
t.ExecutionMode = 'FixedRate';
t.Period = 0.1;
t.TimerFcn = @update_plot;
Xpix=400;
Yline=32;
Pixels=Xpix*Yline;
X=zeros(1,Pixels);
Y=zeros(1,Pixels);
for i=0:Yline-1
for j=0:Xpix-1
if j==0
X(i*Xpix+j+1)=0;
Y(i*Xpix+j+1)=i;
else
X(i*Xpix+j+1)=j;
Y(i*Xpix+j+1)=i;
end
end
end
gpuX = gpuArray(X);
gpuY = gpuArray(Y);
data=ones(1,Pixels);
S=25;% plot size
H=scatter3(data,gpuY,gpuX,S,data,'.');
xlabel('Distance(m)') ;
ylabel('X,θ') ;
zlabel('Y,Φ') ;
ax = gca;
ax.FontSize = 10;
% color map reference
xlim([-100 4100])
ylim([0 Yline])
zlim([0 Xpix])
clim([0 4096]); % color map scale
colormap(flipud(jet));
set(gca,'YDir','reverse');
H.SizeData = 30;
colorbar;
start(t);%timer start
function Close_fig(~,~)
stop(t);
delete(t);
delete(fig);
end
function update_plot(~,~)
set(H,'XData',data);
set(H,"CData",data);
drawnow;
%pause(0.001);
end
end
Pythonコードは以下のようになっていて、ワークスペースの'data'にデータを送信します。
import numpy as np
import matlab.engine
eng = matlab.engine.connect_matlab()
Xpix=400
Yline=32
Pixels=Xpix*Yline
point_data=np.ones(Pixels)
loop_count=1000
for looptime in range(loop_count):
count=0
for iy in range(Yline):
for ix in range(Xpix):
tpm=2048+2048*np.sin((2*np.pi/Xpix*ix)+(2*np.pi/(Yline-1)*iy)+(2*np.pi/Xpix*looptime))
point_data[count]=tpm.astype("int")
count=count+1
A = matlab.double(vector=point_data)
eng.workspace['data'] = A
eng.quit()
Pythonからは正常にデータが送信されていることを確認しましたが、MATLABでリアルタイムに更新されるグラフを得ることはできませんでした。
他の方法ではリアルタイムに更新されるグラフを表示させることには成功しています。(csvファイルを介してデータを読み書きさせたり、PythonからMATLABの自作関数を呼び出したり)しかし、いずれも速度に問題があります。Python、MATLAB間で高速に配列データをやりとりする方法があればご教授願いたいです。
Toshihiko Baba
Toshihiko Baba il 22 Dic 2022
すみません、やはりMATLABでプログラム動作中にも(外部からの干渉による)ワークスペースの値の変動を反映できるようにしたいです。
update_plotの関数ですが、データが更新されているのはベースワークスペースの変数なので、下記のようにevalinを使用してベースワークワークスペースからデータを取得すると、うまく行くかもしれません。
function update_plot(~,~)
if evalin('base', "exist('data', 'var')") == 1
data = evalin('base', 'data');
set(H,'XData',data);
set(H,"CData",data);
drawnow;
%pause(0.001);
end
end
>> MATLABでプログラム動作中にも(外部からの干渉による)ワークスペースの値の変動を反映できるようにしたいです。
→ 私は試みたことはなく、上手くいくかは分かりませんが、backgroundPool(R2021b~)のバックグラウンド実行やparallelComputingtoolboxを使用した並列処理などを利用したら、プログラム動作中にもワークスペース値の変動ができるかもしれません。
また、ベースワークスペースの値の更新とは異なるアプローチになりますが、pythonコードでeng.workspace['data'] = Aを使用したベースワークスペースの更新ではなく、eng.update_plot(A, nargout = 0)のように、PythonからMATLAB関数を呼び出して、MATLABのグラフの更新を行うという方法もいいのではと思います。
Toshihiko Baba
Toshihiko Baba il 26 Dic 2022
毎回丁寧なご回答ありがとうございます。上記の教えていただいたevalinを使った方法で、リアルタイムでワークスペースからデータを取得することができました。ありがとうございました。ただ、高速でワークスペースのデータを書き換えようとすると動作が安定しないことが分かりました。また試行錯誤していきたいと思います。
>>また、ベースワークスペースの値の更新とは異なるアプローチになりますが、pythonコードでeng.workspace['data'] = Aを使用したベースワークスペースの更新ではなく、eng.update_plot(A, nargout = 0)のように、PythonからMATLAB関数を呼び出して、MATLABのグラフの更新を行うという方法もいいのではと思います。
こちらの方法でも試してみましたが、関数を呼ぶたびに軸の設定やカラーマップの設定を行わなければいけなく、結果として高速な動作は実現できませんでした。
しかし、調べてもすぐ出てこないような、とても参考になることを教えていただき感謝しています。私が作るプログラムにもまだ荒があると思うので、直していけたらと思います。ありがとうございました。

Accedi per commentare.

Più risposte (0)

Prodotti

Release

R2019a

Tag

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!