Here we have an example library consisting of masked subsystems.
sys = 'pidLibrary'; open_system(sys)
When you double click on a block, you get the mask dialog, and the Help button displays the MaskHelp if you click on it.
Some of these blocks are properly documented, but others have no MaskHelp. You could click through all the blocks in this library and click on the help button, but that would be a painful manual process. How can you audit this library and ensure that the components are properly documented?
find_system is a very powerful tool for scripting in Simulink which allows you to automate tasks that might otherwise be time-consuming to perform. The find_system syntax is very specific:
find_system(sys, 'c1', cv1, 'c2', cv2,...'p1', v1, 'p2', v2,...)
find_system takes a set of constraints ('c1', cv1, 'c2', cv2) and searches for blocks in the system (sys) that have the specified parameter values ('p1', v1, 'p2', v2). Notice that all constraint/value pairs are passed to find_system before the parameter/value pairs. This confused me once when I got the order wrong, so watch out for that.
Here is a quick find_system command that returns the right answer.
blksNoHelp = find_system(sys,'MaskHelp','') hilite_system(blksNoHelp,'find')
blksNoHelp = 'pidLibrary/Continuous PI Controller' 'pidLibrary/Discrete PI Controller'
It is important to be aware of the search constraint defaults.
- SearchDepth is set to all levels, but this can be changed to 0 for only open systems, 1 to search only the specified system, 2 for that system and its children, etc.
- LookUnderMasks defaults to graphical only, which means find_system doesn’t look under functional masks (those with a dialog and workspace).
- FollowLinks defaults to off, which means linked blocks are not searched. This is very important when the block might reside in a library linked from your system.
- FindAll defaults to off, which means you will only get blocks back from the search. The other option is to specify on and find_system will also return lines and annotations from the model.
- CaseSensitive is on by default, so make sure your caps lock isn’t turned on. This constraint affects the value inputs only; parameters are not treated as being case sensitive.
In our example, if we were also concerned with the contents of those masked blocks, we would need to expand our search to LookUnderMasks. This search would then return Simulink base blocks because they do not use MaskHelp. To reduce the results to only those blocks that are masked, we can do a search where the Mask property is set to on.
blksNoHelp2 = find_system(sys,'LookUnderMasks','all',... 'Mask','on','MaskHelp','') hilite_system(setdiff(blksNoHelp2,blksNoHelp),'find')
blksNoHelp2 = 'pidLibrary/Continuous PI Controller' 'pidLibrary/Discrete PI Controller' 'pidLibrary/Discrete PID Controller/Discrete Derivative'
Another reason constraints are so important is that the amount of work done by find_system is proportional to the number of blocks included in the search. If you are looking under all masks, following all links and searching the full depth of the model hierarchy, the speed of the search will be proportional to the size of your model. find_system is not a Simulink Google search that skips across indexed model information. When find_system is called it has to resolve all block parameters as it works. This means that you will evaluate all the dialog code and parameters required by the search. To speed up find_system, include the appropriate constraints to reduce the number of blocks being evaluated.
Tip: Where ever possible include a SearchDepth to cast a small net.
This got me thinking about how you might perform the inverse of this search. How would you find blocks that have MaskHelp without specifying the value it is set to? The first person to provide a correct answer in the comments gains fame and notoriety as a find_system expert.
Did you already know how to use find_system? This is my second post and I’m looking for feedback on how much experience you have with Simulink. Post a comment and tell me what you think.
Get the MATLAB code
Published with MATLAB® 7.6
25 CommentsOldest to Newest
Very useful !!!!!!
I’ve been using find_system exensively to write my own set of guidelines in the model advisor. It is a very powerful function, but requires some knowledge to operate (e.g. how to find lines or annotations). Seth, I hope you come up with a number of find_system tricks that I don’t know of!
I guess I might do something like:
In commenting on the speed of find_system, if you really need to look everywhere, it has felt faster to do a find_system(‘FollowLinks’,’on’,’LookUnderMasks’,’all’,…) with the SearchDepth at the default of inf, than to make multiple calls to find_system. In general, it has been fast enough.
Does limiting the search by specifying additional properties help the speed at all? For example, is:
faster or slower than
(assuming no other blocks have a Gain property) ? I’ve never had enough open models that I could tell a reasonable difference.
Does setting ‘FindAll’ to ‘on’ so it returns a vector of handles instead of a cell array of strings, but limiting the properties to only those things a block would have affect performance much one way or another? What if you include the time of doing work on the results?
I’ve also recently found the ‘BlockDialogParams’ property useful for searching for that wierd bit of text you know is somewhere in the model.
In general, I’ve found find_system much easier to use than the Edit->Find… (Ctrl-F) dialog.
Well, that’s about all I can think of about find_system at the moment…
Instead of just insert the help text directly into the mask one could use a link to the block’s description using
Whereas the blockname is used as a query-string so the HelpfileIndex.html page could distinguish where to point at.
Advantage: the block and its documentation is separated (but linked together of course) thus enabling you to keep your help files up-to-date. Furthermore, the real path to all of the help files has to be changed only once – the same applies to the file extention if you decide to use for instance *.pdf instead of *.txt
@Bart – find_system is essential for writing Model Advisor checks. Can you share any of your custom checks with the community, or tell us about what you are writing them to check for. I would be interested in a concrete example of your use of find_system if you can share it. THANKS!
@Bob – DING DING DING – we have a winner! Using RegExp in the call to find_system greatly expands the flexibility of your calls. You asked some good questions about performance, and I need to do some more research to answer that. (I haven’t had the TIME to time it myself.)
BlockDialogParams is a very powerful parameter to use in your search. I have already started writing a post to talk about these features. :-) I nearly forgot about the menu option to Find…
Have you tried the Model Explorer?
@impf – Great tip on the options available to documenting masked subsystems! The documentation on how to specify help shows this, as well as other option to specify just the URL.
two small examples (I don’t want to give the entire checks away, because they were written for my company)
The first example checks if there are lines with a name longer than 32 characters.
% Obtain lines
allLines = find_system(system, ‘FollowLinks’, ‘on’, ‘LookUnderMasks’, ‘All’, …
‘FindAll’, ‘on’, ‘Type’, ‘line’);
% Get line names
lineNames = get_param(allLines, ‘Name’);
% Find names longer than 31 char
isLongName = cellfun(@(x) length(x)>31, lineNames);
The second example looks for the number of mask parameters which is limited to 6
% Find all subsystem blocks inside current system
allBlks = find_system(system, ‘FollowLinks’, ‘on’, ‘LookUnderMasks’, …
‘All’, ‘BlockType’, ‘SubSystem’);
allBlks = setdiff(allBlks, bdroot(system));
% Exclude Model Info block
allBlks = setdiff(allBlks, [bdroot(system) ‘/Model Info’]);
% Get Mask names
maskNames = get_param(allBlks, ‘MaskNames’);
% Count names
nMaskNames = cellfun(@(x) length(x), maskNames);
% Maximum number of names is 6
tooMany = nMaskNames > 6;
@Bart – Those are great examples of find_system. I also like the use of cellfun to operate on the results returned from find_system. This could lead into a much bigger discussion about the use of Model Advisor checks, or the reason for these kinds of check. Your limit on the number of characters is an interesting one, and I’m guessing that it is intended to limit the size of identifiers in the generate code to 32 characters. Do you also use the Maximum identifier length control under the Real-Time Workshop options that control Symbols?
Bart, thank you for sharing these examples of how you use find_system.
Seth, the purpose of the character limit is twofold. One reason you have already mentioned, namely the indentifiers size in the generator code. I did not know about the Maximum identifier length option, but I am completely new to RTW. The guidelines were actually written before I obtained RTW. A second reason for the limit is to keep an object name really a name and not a long description (a bad habit of some colleagues of mine)
1. If I use find_system(‘type’,’Block_Diagram’), it returns a string. find_system can return cell string if multiple items found or empty cell if none is found. This makes post processing inconvenient (setdiff/cellfun in post #6 can’t be safely used in many cases.) Therefore, I go with find_system(0, ‘type’,’Block_Diagram’) or like which returns array, albeit it may be empty.
2. Could you explain why find_system(‘findall’,’on’,’type’,’Block_Diagram’) returns handle, and find_system(‘findall’,’off’,’type’,’Block_Diagram’) returns string or cell string?
3. How to best use find_system with find_mdlrefs to search entire model?
4. When will there be APIs for the find facility as in post#5 for combined Simulink and Stateflow?
Great Blogging Seth! Good to see growing love for Simulink!
To Wei, I offer my humble advice:
2. Great Question! The answer lies within your reach. This is actually a great point for everyone who is new to MATLAB/Simulink, or new with using the documentation.
Whenever you have a question with a Simulink Block, you can hit the “Help” button to bring up the documentation page. But what if you want the help doc for a MATLAB function, not a block? At the MATLAB command prompt, type:
If you have the doc loaded on your computer, this will do the same as the “Help” button. (If you don’t have the doc loaded, you can type:
to get a text based version)
The doc is a great place to answer general questions about functions and blocks. Try it! You’ll find the answer to your question, I promise!
3. If you’re trying to search into referenced models, first use FIND_MDLREFS to get the names of ALL the models (this includes all the referenced models and the root model). After that, you can use the answer as an input to FIND_SYSTEM. Try this at the MATLAB command prompt:
This will open a model reference demo. Then try:
[r, b] = find_mdlrefs(‘sldemo_mdlref_basic’)
See what you get?
I hope this helped!
Appreciate the enthusiasm about the doc, definetely second the advice. Just a clarification though, the HELP command does not bring up a text version of the documentation. In general the HELP command dumps the comments at the top of of an M-file into the command window. For MATLAB functions (i.e not user-written), the documentation often contains a lot more information, examples and references (and is written by professional documentation writers).To summarize, use the DOC command to bring up the documentation (preferred) or the HELP command to bring up the comments at the top of a file.
Is it possible to use find_system to find viewers? If I have a viewer in my model (eg a Scope) then I can access it to change some parameters by using its name (eg my_system/Scope) or its handle. However, if I use find_system I cannot find it (even with FindAll set to ‘on’).
Note that if I run find_system(‘my_system/Scope’) it does get found (as a check to whether viewers are totally invisible).
@Kieran Parsons – What are you trying to do with the results of this command? There is a utility you can download from this technical support solution which will allow you to find all the signal viewers in your model. Try it out.
I want to detect which block are connected to each other.
(1) Discover all e.g. sum blocks by find_system.
(2) Discover all blocks connected to the found sum blocks.
Any idea of how to do (2)?
@Seth (13) – Thanks for the info. I would like to programmatically add viewers to a model, but there is no API to do this. Instead I think I can copy a viewer from one model into another and change the port it is connected to. For this the ability to find viewers in a model is useful.
i would like to design PID controller in matlab/simulink for control the process trainer.
i think my designed was wrong….
I have been in Matlab for the past one month .
Can u tell me what is LineChildren is all about.
I don have any idea about this.
The thread above leads us in a direction we really need to go.
We have a need to retrieve a list of signal names and their associated dimensions from an existing compound bus. The retrived information should be in the form of something that cam be copy/pasted in text form.
Reading the above thread, we can see that the following commands yield a list of all lines in a model. How can we get the list of lines within a specific compound bus and get the format of each line?
allLines = find_system(‘Dimensions’, ‘FollowLinks’, ‘on’, ‘LookUnderMasks’, ‘All’, ‘FindAll’, ‘on’, ‘Type’, ‘line’)
lineNames = get_param(allLines, ‘Name’)
Thank you for whatever insights you can offer.
The following does not appear to find enabled subsystems!
find_system(gcs, ‘FollowLinks’,’on’, ‘LookUnderMasks’,’all’, ‘BlockType’,’SubSystem’)
I realize these subsystems have dual identities but I would have expected this to work. Is there a magic argument to find_system to get the expected behavior?
What version are you using? I just tried this on the demo model sl_subsys_enab1 in 9a and got,
find_system(‘sl_subsys_enab1’, ‘FollowLinks’,’on’, ‘LookUnderMasks’,’all’, ‘BlockType’,’SubSystem’)
The one thing I can think of is that “gcs” is not pointing to the model you think it is. If you enter the full model name, does it still not work?
I have to change the DECIMATION of ‘To Workspace’ block in my libraries (and I have a lot of this blocks in my libraries…)
How I can do this from command line (with find_system I think…but I don’t know how…)?
The answer for the question asked by Seth.
How would you find blocks that have MaskHelp without specifying the value it is set to?
blksWithHelp = find_system(gcs,'RegExp','on','MaskHelp','.+')
find_system could be used with regular expressions constraints as well. If ‘on’, search treats search expressions as regular expressions. The default is ‘off’.
“.+” expects atleast one character in the MaskHelp.
@U N Bharathiraja – Thanks for the answer. I am always amazed at what can be done with regular expressions.
Is there a way to exploit find_system to find a simulink line connecting two blocks (say with the blocks port handles at hand)?
As a continuation of @K(24),
After some digging I’ve come up with the following:
It can be used either with SrcBlockHandle or SrcPortHandle to find the desired line.