Can I force Matlab to wait 'til it finishes one command to run another?

93 views (last 30 days)
Jim Bosley
Jim Bosley on 19 Sep 2019
Edited: Jim Bosley on 26 May 2020
I have a script that loads a SimBiology model using the simbiology() command. Then I try to get a handle for the model
simbiology('mymodel.sbproj'); % There are reasons why I use simbiology and not sbioloadproject
sbr = sbioroot;
mdls = sbr.models;
nmdls = numel(mdls);
mc = mdls(nmdls);
The problem is when I first try to get mdls. I get an empty array. Apparently, the model is still loading when the sbr=sbioroot and mdls = sbr.models commands run.
In windows command line files, you can use
START /WAIT myprogram.exe
to force myprogram.exe to finish running before going on the next line. Is there a similar artifice in Matab/Simbiology? Something like
finish('simbiology('mymodel.sbproj')' ;
% or
I keep thinking that there's an easy way that I've forgotten...
The above is a general case. Of course, if simbiology() were re-written to return the model handle, and when the handle was requested, would not allow the script to proceed until the model was loaded, it would be great. Logical, too, because generally when you're loading a model you want to do something with that model before proceeding.
mc = simbiology('mymodel.sbproj'); % This solves the specific problem!
% or
mc = simbiology('mymodel.sbproj','WaitToComplete'); % or this
Jim Bosley
Jim Bosley on 19 Sep 2019
Ok. Guillame, as much as I liked your proposed solution, it didn't work. The first instance of mdls = sbr.Models does not return an empy object [], it returns a 0x1 Model object structure. So the while/end loop terminates before the model has loaded.
I suspect that I may have an insoluble problem here. Because I think that while the script is running, the Simbiology desktop stops running. At least the simbiology('myproj.sbproj') comman doesn't complete. So if I run this the code below
pstate = pause('on'); % Capture pause state and turn pause on
sbr = sbioroot; % Get sbioroot handle
simbiology('mymodel.sbproj') % Tell SimBiology to open file
mdls = sbr.Models; % Get original model state (numel should == 0)
i = 0; % Safety counter
while numel(mdls)==0
pause(1); % Don't chew up CPU with a tight, do-nothing loop
sbr=sbioroot; % Doesn't work with this line, or without this line.
mdls = sbr.Models; % To force mdls to be current
i = i + 1;
nmdls=numel(mdls); % Get the number of models
disp(['Time is ' num2str(i) ' Number is: ' num2str(nmdls)]);
if i>120
mdls = sbr.Models;
pause(pstate); % back to original state
clear pstate;
I get a output with the value of i increasing to 120, and the value of nmlds constant at 0. If I then see what it returned in mdls by typing mdls, I get:
mdls =
0×1 Model array with properties:
And the model doesn't complete loading til the script ends. So after the script ends if I wait a few seconds and let the model load, I can type mdls=sbr.models and get:
SimBiology Model - REGN TG
Model Components:
Compartments: 7
Events: 0
Parameters: 300
Reactions: 84
Rules: 143
Species: 46
So its pretty clear that the model doesn't load until the script finishes.
I see no sensible reason for not letting the model load while the script runs. This seems like a bug to me.

Sign in to comment.

Accepted Answer

Arthur Goldsipe
Arthur Goldsipe on 19 Sep 2019
Hi Jim,
The previous responses are correct: The simbiology command returns before the desktop completely loads the project, because the desktop is operating on different threads. So, welcome to the world of multi-threaded / parallel / asynchronous / <insert buzzword> complexity! Believe me, it makes life harder for SimBiology's developers, too. But hopefully you're mostly seeing the benefits of us living in that complexity and hiding it from you as much as possible.
Right now, there's one-line command that does what you want, but I'll suggest a workaround below. But thinking longer term, we hope to eliminate the need to open a project in the desktop just to preserve the diagram. If you can think of other reasons why it's important to know when a project is fully loaded, let us know so we can address those workflows, too.
Anyway, if all you care about is whether the model is accessible from the MATLAB command prompt (and not whether the desktop has completely finished loading the project), I came up with a solution (pasted below) that uses timer objects to periodically check whether the models have been loaded.
Here's the function. It takes the name of a project, the name of a variable to assign models to in the base workspace, and an optional callback that you can use to execute tasks that take the models as input arguments. So here's an example usage that simulates the Lotka demo project as soon as it's loaded (assigning the result to the base workspace variable sd): simbiologyNotify('lotka.sbproj', 'models', @(m) assignin('base', 'sd', sbiosimulate(m)))
function simbiologyNotify(projectName, varName, callback)
if ~exist('callback', 'var')
callback = @(models) [];
root = sbioroot;
oldModels = root.Models;
t = timer('ExecutionMode', 'fixedSpacing');
t.TimerFcn = @(t,e) timerFcn(t, root, oldModels, varName, callback);
function timerFcn(t, root, oldModels, varName, callback)
models = setdiff(root.Models, oldModels);
if isempty(models)
fprintf('Models have been loaded. Assigning to base workspace variable "%s".\n', varName);
assignin('base', varName, models);
Note that you can't directly call this function from a script or function. If you do, you'll block the MATLAB interpreter, and that will prevent the desktop from loading the project. So you have to start thinking about asynchronous tasks the way we developers do: as a series of callback functions that get called as soon as their preconditions are met.
And one last note: If you really need to know whether the desktop has fully loaded the project into the GUI, I'll see if there's a way to get that information.
Jim Bosley
Jim Bosley on 26 May 2020
Aha. So its a "There are more things in heaven and earth [and Matlab], Horatio, Than are dreamt of in your philosophy" type of thing. Where I'm Horatio. In any case, I know that its a difficult problem: not something I was stupidly missing an easy answer to. Cuz there isn't one.
I did test your procedure and it works nicely, and so one can open models using simbiology via script, and the callback feature does wait until the model is loaded. At least it waits till sbioroot.Models changes - I assume that once a new model object is put into the sbioroot.Models vector, this indicates that the whole model is loaded. But for a simple test (my callback function is essentionally models.Dose, to show that I have doses loaded).
Your replies have helped me learn - thanks.

Sign in to comment.

More Answers (0)



Community Treasure Hunt

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

Start Hunting!