Passing real time plot data from a Matlab function to App Designer for plotting

100 views (last 30 days)
Hi,
Once again I find myself in a pickle that I'm hoping one of you guys may be able to help resolve.
I am using App Designer for the first time to contruct an app. From this app, I wish to call a function, bring the plot data into my app, and show the electromagnetic wave propagating in real time - just like it does in the figure when I run the Matlab function. Is this possible? At present, once I click on the 'Ping' button (see image below), the program runs then after a short while the final result is plotted (not filling the full box - but that is another problem)!
Best regards,
Andy
The code is as follows:
In my App I have the following to call the function fdtd_time_reversal
[E,frames] = fdtd_time_reversal(X,Y,app.signal,app.media);
imagesc(app.UIAxes2,E)
axis image
colormap(app.UIAxes,"jet");
app.frames
In my matlab function, I have the following
function [E,frames] = fdtd_time_reversal(X,Y,signal,media
% Defined parameters etc. to set up the FDTD solver
Then
% Start the main loop for FDTD calculations
%*****************************************************
% The outer loop enters each step, one at a time, while the inner loop inputs that
% step for each trace.
for j = 1:Nt,
for i = 1:tr;
% enter the signal from the last time step to the first (reversed in time)
%The Electric field is initiated by creating a magnetic loop
hx((i-1)*space+nb+start,offset+nb) = signal(i,j);
hy((i-1)*space+nb+start,offset+nb) = -signal(i,j);
hx((i-1)*space+nb+start,offset+nb+1) = -signal(i,j);
hy((i-1)*space+nb+start+1,offset+nb) = signal(i,j);
ezy((i-1)*space+nb+start,offset+nb)=0;
ezx((i-1)*space+nb+start,offset+nb)=0;
end;
% Advance the fields using code 'fdtd_andy'
[ezx,ezy,hx,hy] = fdtd_andy(ezx,ezy,hx,hy,alphaex,alphaey,alphamx,alphamy,betaex,betaey,betamx,betamy);
%The extra layers from the boundary conditions are removed
E=(ezx+ezy);
[a,b] = size(E);
E = E(33:(a-32), 33:(b-32));
%The desired signal is recorded
% V(1:array,j)=[E(rstart:rspace:rstart+(array-1)*rspace,offset+depth)];
%The current electric field is plotted and saved for the movie
% figure(2)
colormap(jet)
imagesc(E)
caxis([-100 100])
axis image
frames(j)=getframe;
end;
%######################################################################
  3 Comments
Andy
Andy on 8 Feb 2024
Hi Mario,
Thank you for responding to my question, all this is bit new to me too, its my first time using uiaxes and imagesc.
I think what you say is correct, the outer loop does return the E value at each step of the simulation, so that makes sense if the value could passes directly to the uiaxes figure. I'm a bit confused how you suggest returning this value within the function - any chance you can elaborate a little more?
Best regards,
Andy
Andy
Andy on 9 Feb 2024
I have manage to get the animated plot to open in a new figure (see below). I'm thinking is there a easy way of geting the animated figure 1 to be displayed in app.UIAxes 2?
Best regards,
Andy

Sign in to comment.

Accepted Answer

Benjamin Kraus
Benjamin Kraus on 9 Feb 2024
There seems to be at least three difficulties you are running into:
  • One is about calling the axis command without specifying an axes handle.
  • One is a difference between regular Axes and UIAxes.
  • One is a question about getting real time results plotted in App Designer.
Calling the axis command without specifying a handle
This line of code:
axis image
Will operate on the "Current Axes", but by default the axes that is within an App Designer app is never the current axes. Therefore, you always need to explicitly state which axes you want to operate on. This is a simple change:
axis(app.UIAxes, 'image')
This same statement applies to:
  • The colormap command (which by default works on the current figure), but you can tell it to work on either a particular figure or a particular axes: colormap(app.UIAxes, jet).
  • The caxis command
  • The imagesc command
  • etc.
Looking at your function called "fdtd_time_reversal", it doesn't provide any way to specify which axes to use when calling colormap or imagesc or axis or getframe. You will need to find a way to fix that issue if you want to use this code within App Designer.
Alternatively you can set the HandleVisibility of your App's Figure to 'on' so that it allow axes inside your App to be the current axes. This is by far the simplest solution, but it comes with some drawbacks. Namely, if you have your App open and someone calls plot at the MATLAB command line, it will mess with the graphics inside your App. For this reason, this is not recommended.
app.Figure.HandleVisibility = 'on';
Differences between regular Axes and UIAxes
Short summary: After calling imagesc, you want to call:
imagesc(app.UIAxes,E)
axis(app.UIAxes, 'image')
xlim(app.UIAxes, 'tight')
ylim(app.UIAxes, 'tight')
This will tighly crop your axes limits to just fit your image.
Details
When you call the imagesc command, the imagesc command does a few things:
  • It creates an image object with the requested data.
  • It switches the YDir on the axes to 'reverse' so your image is right-side-up.
  • It sets the limits to be tightly cropped around your image.
Those second two bullets don't always happen, but rather they are conditional on the value of the NextPlot property on the axes or UIAxes.
  • When NextPlot is set to 'replace' (this is the same as hold off) then the imagesc command will set the YDir and also the axes limits. This is the default behavior for regular Axes.
  • When NextPlot is set to 'add' (this is the same as hold on) then the imagesc command will not set the YDir or the axes limits.
  • When NextPlot is set to 'replacechildren', then the imagesc command will set the YDir to 'reverse', but it won't set the limits. This is the default behavior for UIAxes.
So, in your images, you can see the limits are not tightly cropped around your image ("not filling the full box - but that is another problem"). That is because the UIAxes you are using has NextPlot set to 'replacechildren', so the limits are not being updated.
Real time results plotted in App Designer
I didn't entirely follow the issue you were experiecing in this regard, but I'm going to speculate a little.
You said "once I click on the 'Ping' button (see image below), the program runs then after a short while the final result is plotted".
This is most likely because you are not giving the graphics system a chance to update while your code is running.
If you call multiple graphics commands in a row, without any breaks, then MATLAB will only draw the last picture.
If you want to see intermediate steps, you need to call some form of drawnow.
Basically, in your for loop:
function [E,frames] = fdtd_time_reversal(ax, X, Y, signal, media) % Note I added "ax" here.
for j = 1:Nt
for i = 1:tr
% Do some math
colormap(ax, jet)
imagesc(ax, E)
caxis(ax, [-100 100])
axis(ax,'image')
xlim(ax, 'tight')
ylim(ax, 'tight')
drawnow % This command will tell MATLAB to draw this frame before moving on.
end
end
  1 Comment
Andy
Andy on 10 Feb 2024
Hi Benjamin,
That's brilliant, you have solved all three of my problems in one go! Also your explanation of the differences between Axes and UIAxes and real time plotting in App Designer has been super helpful - I understand it now.
It's a steep learning curve, but I'm now startng to enjoy using App Designer.
Once again thank you for your help.
Best regards,
Andy

Sign in to comment.

More Answers (0)

Products


Release

R2023b

Community Treasure Hunt

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

Start Hunting!