MIJ: execute imageJ (Fiji) macro until end in Matlab - matlab

I am using MIJ to execute an ImageJ macro within Matlab. The macro has to be executed multiple times in a "for" loop. The problem is that Matlab does not wait until the macro ends. Initially I solved the problem with a "while" loop, checking if the "Results" table generated from the macro was empty or not. However, it only solves the problem the first time, then from the second time the "Results" table is not empty anymore.
I also thought about generating a variable at the end of the macro and use it to check if the macro finished, but I don't know how to read it in Matlab.
Do you have any suggestion about how I can solve the problem?
Thanks a lot in advance,
Alessia
Here is an example of my code:
javaaddpath 'C:/Program Files/MATLAB/R2019a_x64/java/ij.jar'
javaaddpath 'C:/Program Files/MATLAB/R2019a_x64/java/mij.jar'
MIJ.start('C:/fiji-win64/Fiji.app/plugins');
IJ=ij.IJ();
macro_path=...
'C:/Macro_waterinoil.ijm';
for pos=1:16
im = mijread(strcat('E:/droplets.tif'));
figure(1)
imshow(im,[0 255])
IJ.runMacroFile(java.lang.String(macro_path));
res_Hough=0;
res_Hough=MIJ.getResultsTable();
while res_Hough==0;
res_Hough=MIJ.getResultsTable();
end
im_res=MIJ.getCurrentImage();
MIJ.run('Clear Results');
MIJ.run('Close All');
end

Edit: Ignore the below, I was on the right track but wasn’t paying as much attention as I should have been. I think this issue is the line right after you set res_Hough to 0 (i.e. res_Hough=MIJ.getResultsTable();). Try deleting it so that the next line is the while loop, then we can check the output and see if the below might also apply
If I am understanding correctly, you are using the while loop to continuously ping until the table is full, then store those values in res_Hough, right? I'm wondering if this is a limitation inherent to ImageJ/FIJI. The reason I think this might be the case is that a very simple explanation for your issue is that the table retains the previous values, and so will always be full after the first loop unless cleared manually somehow. Do you think that could be the case? Perhaps add a print statement after the while loop and see if it prints the same values for the duration of the for loop.
I suppose the next thing to do is for me to actually try to offer a solution regardless of the above. My idea is to try having the while loop check against the previous iteration's table values until they are different, then stash the updated values. Does that make sense? Something like:
while (res_Hough[i]==0) or (res_Hough[i-1]==MIJ.getResultsTable());
res_Hough[i]=MIJ.getResultsTable();
Where i is incremented by the for loop

Related

Can the MATLAB editor show the file from which text is displayed? [duplicate]

In MATLAB, how do you tell where in the code a variable is getting output?
I have about 10K lines of MATLAB code with about 4 people working on it. Somewhere, someone has dumped a variable in a MATLAB script in the typical way:
foo
Unfortunately, I do not know what variable is getting output. And the output is cluttering out other more important outputs.
Any ideas?
p.s. Anyone ever try overwriting Standard.out? Since MATLAB and Java integration is so tight, would that work? A trick I've used in Java when faced with this problem is to replace Standard.out with my own version.
Ooh, I hate this too. I wish Matlab had a "dbstop if display" to stop on exactly this.
The mlint traversal from weiyin is a good idea. Mlint can't see dynamic code, though, such as arguments to eval() or string-valued figure handle callbacks. I've run in to output like this in callbacks like this, where update_table() returns something in some conditions.
uicontrol('Style','pushbutton', 'Callback','update_table')
You can "duck-punch" a method in to built-in types to give you a hook for dbstop. In a directory on your Matlab path, create a new directory named "#double", and make a #double/display.m file like this.
function display(varargin)
builtin('display', varargin{:});
Then you can do
dbstop in double/display at 2
and run your code. Now you'll be dropped in to the debugger whenever display is implicitly called by the omitted semicolon, including from dynamic code. Doing it for #double seems to cover char and cells as well. If it's a different type being displayed, you may have to experiment.
You could probably override the built-in disp() the same way. I think this would be analagous to a custom replacement for Java's System.out stream.
Needless to say, adding methods to built-in types is nonstandard, unsupported, very error-prone, and something to be very wary of outside a debugging session.
This is a typical pattern that mLint will help you find:
So, look on the right hand side of the editor for the orange lines. This will help you find not only this optimization, but many, many more. Notice also that your variable name is highlighted.
If you have a line such as:
foo = 2
and there is no ";" on the end, then the output will be dumped to the screen with the variable name appearing first:
foo =
2
In this case, you should search the file for the string "foo =" and find the line missing a ";".
If you are seeing output with no variable name appearing, then the output is probably being dumped to the screen using either the DISP or FPRINTF function. Searching the file for "disp" or "fprintf" should help you find where the data is being displayed.
If you are seeing output with the variable name "ans" appearing, this is a case when a computation is being done, not being put in a variable, and is missing a ';' at the end of the line, such as:
size(foo)
In general, this is a bad practice for displaying what's going on in the code, since (as you have found out) it can be hard to find where these have been placed in a large piece of code. In this case, the easiest way to find the offending line is to use MLINT, as other answers have suggested.
I like the idea of "dbstop if display", however this is not a dbstop option that i know of.
If all else fails, there is still hope. Mlint is a good idea, but if there are many thousands of lines and many functions, then you may never find the offender. Worse, if this code has been sloppily written, there will be zillions of mlint flags that appear. How will you narrow it down?
A solution is to display your way there. I would overload the display function. Only temporarily, but this will work. If the output is being dumped to the command line as
ans =
stuff
or as
foo =
stuff
Then it has been written out with display. If it is coming out as just
stuff
then disp is the culprit. Why does it matter? Overload the offender. Create a new directory in some directory that is on top of your MATLAB search path, called #double (assuming that the output is a double variable. If it is character, then you will need an #char directory.) Do NOT put the #double directory itself on the MATLAB search path, just put it in some directory that is on your path.
Inside this directory, put a new m-file called disp.m or display.m, depending upon your determination of what has done the command line output. The contents of the m-file will be a call to the function builtin, which will allow you to then call the builtin version of disp or display on the input.
Now, set a debugging point inside the new function. Every time output is generated to the screen, this function will be called. If there are multiple events, you may need to use the debugger to allow processing to proceed until the offender has been trapped. Eventually, this process will trap the offensive line. Remember, you are in the debugger! Use the debugger to determine which function called disp, and where. You can step out of disp or display, or just look at the contents of dbstack to see what has happened.
When all is done and the problem repaired, delete this extra directory, and the disp/display function you put in it.
You could run mlint as a function and interpret the results.
>> I = mlint('filename','-struct');
>> isErrorMessage = arrayfun(#(S)strcmp(S.message,...
'Terminate statement with semicolon to suppress output (in functions).'),I);
>>I(isErrorMessage ).line
This will only find missing semicolons in that single file. So this would have to be run on a list of files (functions) that are called from some main function.
If you wanted to find calls to disp() or fprintf() you would need to read in the text of the file and use regular expresions to find the calls.
Note: If you are using a script instead of a function you will need to change the above message to read: 'Terminate statement with semicolon to suppress output (in scripts).'
Andrew Janke's overloading is a very useful tip
the only other thing is instead of using dbstop I find the following works better, for the simple reason that putting a stop in display.m will cause execution to pause, every time display.m is called, even if nothing is written.
This way, the stop will only be triggered when display is called to write a non null string, and you won't have to step through a potentially very large number of useless display calls
function display(varargin)
builtin('display', varargin{:});
if isempty(varargin{1})==0
keyboard
end
A foolproof way of locating such things is to iteratively step through the code in the debugger observing the output. This would proceed as follows:
Add a break point at the first line of the highest level script/function which produces the undesired output. Run the function/script.
step over the lines (not stepping in) until you see the undesired output.
When you find the line/function which produces the output, either fix it, if it's in this file, or open the subfunction/script which is producing the output. Remove the break point from the higher level function, and put a break point in the first line of the lower-level function. Repeat from step 1 until the line producing the output is located.
Although a pain, you will find the line relatively quickly this way unless you have huge functions/scripts, which is bad practice anyway. If the scripts are like this you could use a sort of partitioning approach to locate the line in the function in a similar manner. This would involve putting a break point at the start, then one half way though and noting which half of the function produces the output, then halving again and so on until the line is located.
I had this problem with much smaller code and it's a bugger, so even though the OP found their solution, I'll post a small cheat I learned.
1) In the Matlab command prompt, turn on 'more'.
more on
2) Resize the prompt-y/terminal-y part of the window to a mere line of text in height.
3) Run the code. It will stop wherever it needed to print, as there isn't the space to print it ( more is blocking on a [space] or [down] press ).
4) Press [ctrl]-[C] to kill your program at the spot where it couldn't print.
5) Return your prompt-y area to normal size. Starting at the top of trace, click on the clickable bits in the red text. These are your potential culprits. (Of course, you may need to have pressed [down], etc, to pass parts where the code was actually intended to print things.)
You'll need to traverse all your m-files (probably using a recursive function, or unix('find -type f -iname *.m') ). Call mlint on each filename:
r = mlint(filename);
r will be a (possibly empty) structure with a message field. Look for the message that starts with "Terminate statement with semicolon to suppress output".

File reading in matlab

I'm having troubles with my code in Matlab. I want to get the mean value of all the elements in the second column in a file, but for some reason the code does not include the last line.
My file looks like this:
And my code looks like this:
As you might already understand, my code gets the mean value of all numbers except the last one for Italy.
Any suggestions on how to proceed would be highly appreciated.
It's actually suggested by Mathworks to not use feof with fgetl loops, but to instead check whether the output is with ischar. Simply replace ~feof(fid) with ischar(line).
A side note: line is also a MATLAB function, by using it as a variable name you are shadowing the function. While it is not critical here, you should try to avoid doing this. If you try to use line the function or another function which calls line while you have a variable line in the workspace, you'll likely get an error. This is why you'll see the examples in the help use things like tline as variable names instead.
You should put
line=fgetl(fid)
to the top in the while loop.

Anonymous function corruption in MATLAB. What does '#sf%' mean?

I was stumped by a segmentation fault in MATLAB.
It seems like it was caused by an anonymous function that was loaded from a mat file.
The original anonymous function handle was:
#(x)scaledNlfun(x,#logexp1,1e3)
But when it is loaded, it becomes:
#sf%1#(x)scaledNlfun(x,#logexp1,1e3)
It seems to be okay, when I call it in command line, but it creates a segmentation fault (or Segmentation violation) within a function. Not the function call itself, but a few lines after that. In debugging mode, if I step through the statement, it is fine as well.
The stack trace shows bunch of
[ 0] 0x00002b20b97baba4 /usr/local/MATLAB/R2013a/bin/glnxa64/libmwm_interpreter.so+04127652
and it happens on both MATLAB 2012a and 2013a on a Linux 2.6.18-371.3.1.el5 SMP.
This function handle was saved within a parfor loop using '-v7.3' option because the struct that contains the handle was too big. If I replace the anonymous function after loading the mat file, everything works fine, so I'm thinking the matlab load function has a bug.
Unfortunately, I cannot create a minimal example to reproduce the error. I tried saving anonymous function handles within parfor with '-v7.3', but without the other complex data structures, it seems to work fine. But I have 80 mat files that would reliably crash matlab (many of them more than 1GB).
In any case, does anybody know what that "#sf%" mean? (it's not the stateflow toolbox)
The core of the problem seems to be that you have #sf%1# where you would expect # just looking at this, I can think of a few possibilities:
Somehow sf%1# was inserted after the original #
Somehow #sf%1# was substituted in place of the original #
Somehow #sf%1 was attached before the original #
I would actually bet on the third one, but here are the most logical scenarios I can think of that could cause this problem:
Perhaps there was an invisible char?
Perhaps some kind of strange character conversion?
Probably a situation where two things are stored in a variable instead of one. Perhaps something like #s or #sf and some separating characters.
All in all, this does not explain why it would go well if you run the entire program in the console, but perhaps you just ran part of it. In that case these could be some things to look out for.

How to remove the variable "clear" in MATLAB

Let's say you are some new programmer and you do something like...
%...la da da
%...programming away
if such && such
clear = 1;
else
clear = 0;
end
or in some other way, you assign the variable clear a value.
Is there some way to "clear" clear?
clearvars doesn't work. Clicking the workspace variable and manually clicking delete does work, but I think it's cheating.
This will do it:
builtin('clear','clear')
Note: Keep in mind to avoid such operations to keep code clarity. Only do overwrite when it is the exact action you want to take place. Otherwise it may cause future bugs if you forgot (or if another person uses your code and didn't realize it) that you have the clear (or any other) function overwritten. You could easily name this variable as doClear for example.
Any name, even builtin and feval can be overriden. In such case, you can use function handles instead to force MALTAB into interpreting a statement as a function call:
clear = str2func('clear');
clear('clear')
Obviously, str2func can also be overrriden! :) however, there exists a similar solution (inspired by Loren's article), which is creating a separate m-file that does the same thing:
function clearclear()
assignin('caller', 'clear', #clear);
Calling this function in the main workspace should allow you to do clear('clear') safely.
The second solution takes advantage of the fact that the m-file doesn't "see" the variable clear in the main workspace, and therefore can access the actual handle of the clear function properly.
A non intuitive way is
clear = rand(1000,500,700);
pack
This produces the following warning:
Warning: Variable 'clear' cannot be saved to a MAT-file whose version
is older than 7.3. To save this variable, use the -v7.3 switch.
Skipping...
It also suffers from the same issue that you can assign pack to be a variable.
Interesting problem! I found it surprisingly hard to find an ways to do this programatically (besides the one suggested by #TryHard)
Here is the I have come up with though it is a bit more powerfull than clear:
!matlab &
exit
Note that if you want to type this in the command line at once, you need to use a shift+enter in between.

How to interrupt MATLAB IDE when it hangs on displaying very large array?

Suppose I'm using the MATLAB IDE and happen to have some very large objects in my workspace (e.g. arrays of 500k+ elements). Now, suppose that I stupidly and accidentally double click on one of these very large variables, which triggers a load to the array editor. Unfortunately, with arrays this big, MATLAB just hangs.
I've tried CTRL+C, CTRL+BREAK, CTRL+D, but none seem able to interrupt the behavior of the IDE. I know I can force matlab to quit, but reading all of those variables into the workspace in the first place takes a lot of time, and I may have unsaved changes in an editor window, etc.
The variable editor is launched using the command openvar. To solve your problem you can take advantage of a Matlab quirk that causes functions to be masked by variables with the same name. For example if you create a variable named plot the plot() function stops working.
The solution, although hackish, is to simply create an empty variable named openvar. Then anytime attempt to open the variable editor will fail because the function openvar is being hidden by the variable.
If you want to use the variable editor again simple call clear openvar to delete the variable and the function will be unmasked.
I found a way, but it's not the best, it requires a change of path and back once to get a handle to the original openvar
function openvar(name,array)
persistent org_openvar
if isempty(org_openvar)
curdir=pwd;
cd(fullfile(matlabroot,'toolbox/matlab/codetools'));
org_openvar = #openvar;
cd(curdir);
end
if numel(array)>1e5
if strcmp(questdlg(sprintf('Opening ''%s'' which has %d elements.\n\nAre you sure? This is gonna take a while!',name,numel(array)), ...
'Variable editor','Yes','Cancel','Cancel') , 'Yes')
org_openvar(name,array)
end
else
org_openvar(name,array)
end
end
getting that handle is the biggest problem, calling it is just fine. If openvar would be built in, you could use the function builtin:
builtin('openvar',name,array)
but this is unfortunately not the case :(
str2func in combination with the complete path also doesn't work, at least I don't get it to work...