Can I use parfeval in App Designer to plot to a UIAxes while the code keeps running?

24 views (last 30 days)
Hi everyone,
I am building a tool with App Designer which has basically two goals:
  1. Visualize Data as it is being aquired
  2. Perform calculations on this data
To simulate this I load a vector containing a bunch of numbers. I epoch the data into chunks of equal size, e.g. 5 seconds with a sampling rate of 250 Hz. I want to plot this chunk using a for loop an animated line and drawnow. While this is being plotted I want to do some calculations, such as Fast-Fourier-Transform or other signal processing routines. The result from these calculations would optimally also be visualized somewhere. The main issue I am having at the moment is however to plot and calculate in parallel.
I was quickly drawn to parfeval, however I feel like this is not easy to run in App Designer for some reasons which are beyond my understanding. One of the problems seems to be that it cannot find my function in my App Designer Class. So when I supply the @app.plotFcn to parfeval, it gives me an error.
So first question: Should I in general not define the functions I want to run in parallel within the class but as a separate .m file?
I also get the following warning: "Warning: While loading an object of class 'MonitorAnesthesia':
Unable to load App Designer app object. Load not supported for matlab.apps.AppBase objects. "
So second question: Should I simply put the for loop into the function I want to run in parallel, let it give me a value, and then plot it outside using an animated line and drawnow. Could this be a solution? I think I am not understanding to a 100% how the pafeval works and how best to use it. So it would also be great if you can simply point me into a different direction if I am completly off here.
Thank you very much
Julian

Accepted Answer

Matt J
Matt J on 6 Jun 2023
Edited: Matt J on 6 Jun 2023
A mechanism equivalent to .mat file saving is how data is transferred to parpool workers. The plotFcn that you give to parfeval must therefore not reference the app object because an app object cannot be saved to a .mat file. Can you not extract just the data you need for plotting and build an anonymous or nested function based on that alone?
  2 Comments
Julian Ostertag
Julian Ostertag on 6 Jun 2023
Edited: Matt J on 6 Jun 2023
Ok I see, that is good to know, because I was confused as I am not saving anything. So in theory this would work:
data = app.data
idx = 1;
ax = app.UIAxes;
F1 = parfeval(Pool,@plotFcn,0,data,idx,ax)
And this would not: F1 = parfeval(Pool,@plotFcn,0,app.data,idx,app.UIAxes)
Also this would not work: F1 = parfeval(Pool,@app.plotFcn,0,data,idx,ax)
Is this correct? Any reference to app within the parfeval will trigger the warning? Meaning any function will definitively have to be supplied as a separate .m file and cannot be part of the class. This would actually not be too much of an issue. But i think this would still mean I cannot really make it work if the app obj is off limits.
Matt J
Matt J on 6 Jun 2023
Edited: Matt J on 6 Jun 2023
Your code is difficult to read because it is unformatted and has no line breaks (something I have now corrected for you).
In any case, because of what Walter said, I think the best thing to do is give the non-graphical operation to parfeval and do the plotting on the host. Below is a simplified example, which is a callback for the attached single-button app. It simply opens a figure with 3 random subplots while summing the data for each plot in the background (backgroundCalc).
% Button pushed function: ParfevalLoopButton
function ParallelPlotButton(app, event)
figure;
for i=1:3
data=rand(1,10);
F=parfeval(backgroundPool, @backgroundCalc,1, data);
subplot(1,3,i);plot(data);
wait(F)
end
function y=backgroundCalc(x)
y=sum(x);
end
end

Sign in to comment.

More Answers (2)

Hiro Yoshino
Hiro Yoshino on 6 Jun 2023
As for the 1st question, are you familiar with "Object Oriented Programming"?
You should write your code in an OOP manner in the App Designer and the function like things you can define in the class are "Methods". So I am wondering if the "methods" can be passed as a function hundle to parfeval. (I suppose parfeval requires a funciton handle as an argument?). You should try with separated functions to see if it works.
As for the 2nd question.
I would suggest you use parfeval + background. This let the time-comsuming command run behind the sence and let the next code run in a parallel manner.
  1 Comment
Julian Ostertag
Julian Ostertag on 6 Jun 2023
Thank you for the quick reply. It is still not working even when calling the function from an outside .m file. I still get that warning:
Warning: Unable to save App Designer app object. Save not supported for matlab.apps.AppBase objects.
It is super weird. I also started using timer() and putting the start() into parfeval, but I am getting similar errors. I just cant get it to run. Is this simply something that MATLAB is not supposed to do or am I just not able to it due to lack of skill? Do you maybe have another idea what I could do?

Sign in to comment.


Walter Roberson
Walter Roberson on 6 Jun 2023
Regardless of whether you use a parallel pool or the newer background pool, no parallel worker of any kind can directly affect the display.
This is not exactly the same as saying that you cannot create graphics in a parallel worker: you can create graphics on parallel workers, but they are created in memory. copies of graphics objects that are created on parallel workers can be sent back to the client process by using parallel data queues.
Because the parallel workers cannot affect the graphics display, it is typically not useful to send graphics objects into parallel workers. It is possible though -- you can send in copies of graphics objects, understanding that in doing so the copies the workers receive will be disconnected from graphics.
So for example if you had created a histogram() then you could deliberately pass the handle to the uiaxes into a parallel worker for it to examine the histogram properties and other related objects -- but any changes that the workers made to the received objects would not affect the display. It's like photocopying, sort of.
You cannot pass app to a parallel worker, or anything that has a copy of the app handle. But you can pick out individual properties of the app and pass them in
parfeval(@my_worker, 1, app.UIbutton7)
for example
  2 Comments
Julian Ostertag
Julian Ostertag on 6 Jun 2023
Thank you for this information. That is quite interesting. Using parallel data queues that you mention would inolve more than just calling parfeval i suppose? Is this particularly complicated? I am just wondering if what I am trying to achieve is just not really something that one should do... Also in your example. The myworker function is supplied from a separate .m file, right? It is not part of the App Designer class which it is being called from, right? Is this a prerequiste for it to work?
Walter Roberson
Walter Roberson on 6 Jun 2023
The short summary: you create an endpoint in the client, arrange for the endpoint to get to the worker, then the worker can write data to the endpoint, and the client can read the results while the workers are still executing.
The myworker function is supplied from a separate .m file, right? It is not part of the App Designer class which it is being called from, right?
Consider a function that is part of the App Designer class. There are three possibilities:
  1. The function might be the class constructor for the app class. The function would be trying to create an object of class app . Attempting to execute such a function on a parallel worker would require that the parallel worker be able to handle items of the appropriate class... but transfering members of the class across the parallel boundary is not permitted. It would be anywhere between tricky and impossible to get this to function properly
  2. The function might be a regular method of the app class. In such a case, the app object needs to be a parameter to the method, somewhere in the parameter list. But transporting app objects across parallel boundaries is not permitted. So the @my_worker cannot be the handle to a regular method of the app class.
  3. The function might be a static method of the app class. In such a case, the app object is not necessarily involved. If the static method did not refer to the app or any properties of the class... it might maybe be possible to pass it in to parfeval ?? I wouldn't rule it out at the moment.

Sign in to comment.

Categories

Find more on Asynchronous Parallel Programming in Help Center and File Exchange

Products


Release

R2023a

Community Treasure Hunt

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

Start Hunting!