MATLAB fails to execute line with uigetfile-- why?

6 ビュー (過去 30 日間)
Sarah
Sarah 2014 年 7 月 31 日
回答済み: Martijn 2015 年 1 月 23 日
I call a function using uigetfile() from another function, but when it runs, MATLAB seems to ignore the line entirely. (The function runs just fine when called from the command line.)
The function is simply:
function [sl] = InputSeaLevel()
%InputSeaLevel prompts for the location of a file containing sea level data
[fname,pname]=uigetfile('*.mat','Select the file containing sea level data');
varname=load(strcat(pname,fname));
name=fieldnames(varname); sl=getfield(varname,name{1});
end
The script that calls InputSeaLevel() does so from within an if loop-- specifically, an if loop created to parse the output from a menu box, e.g.:
c=menu('Make a choice','Yes','No');
if c==1
sl=InputSeaLevel();
{more code}
else
{other code}
end
I successfully ran the function from the command line from within the following loop:
a=1;
if a==1
sl=InputSeaLevel();
end
and the function runs well when removed from the if loop, so I believe that the if loop itself (or perhaps the use of menu() is the problem. I do use eval in an earlier script:
eval([XYZ_var '= tempXYZ;';])
eval([StackName '= stackXYZ;';])
but I don't believe these lines are the cause of the problem, since the problem still occurs when these lines are commented out.
I've seen some discussion of similar problems with uigetfile() before (see here), but I haven't understood the proposed solutions-- presumably the dialog box opened by menu() (and closed when one of its option buttons is clicked) shouldn't be stuck waiting for a response. I don't follow the explanation for how to force any open (but somehow hidden) dialogs to stop waiting, and I don't understand how it could still be open to begin with.
I am running MATLAB R2013a from a Windows 7 machine.
Does anyone have an explanation for what is about this code that is preventing MATLAB from "seeing" uigetfile() when it executes my function? Does anyone know what I can do to either avoid or circumvent this (without simply excluding the function or removing it from the if statement)?
Thanks in advance!
  3 件のコメント
dpb
dpb 2014 年 7 月 31 日
The solution (at least as posted by the OP) to the problem there was to make sure his previous function had an end statement (to ensure cleanup code was executed in sequence apparently). This sounds flaky to me but for that to have any pertinence to your problem you'd need a structure similar to that described there.
That would mean the function containing the call to your function needs an end attached to it. But, you say "script", not function. It still seems unlikely that the diagnosis was really the cure there but to see if it has legs turn your script into a function (not necessary to have arguments or return, just function) and then try it with/without the end statement explicitly included.
Sarah
Sarah 2014 年 8 月 1 日
Geoff and dpb-- thanks for your responses. I have attached the code that's generating the error for me-- it's sort of an all-in-one script for automated data processing, so it calls several other scripts (ReadXYZ) and functions (InputSeaLevel, GridXYZ), also attached.
I ran the example code from the initial post in my command window and hit the same error-- a screen capture of the example code as run is attached so that you can see the exact error, which occurs not in the line containing uigetfile, but in the next line, which uses the output of uigetfile.)
The menu box does appear in the code when it is called, and it seems to work normally (i.e., it disappears when the Yes or No button is clicked and returns the proper value according to the button).
The problem does not happen when I run InputSeaLevel() itself (the function that calls uigetfile) from the command line, but it does happen when I call InputSeaLevel from the all-in-one script--specifically, from within the if loop after the menu() command. (It runs fine when called before menu()-- which very much implicates menu() as the cause of all this, even if it's not clear how or why.)
I have tried running the guts of InputSeaLevel() without the function wrapper (i.e., simply the text of lines 3 through 5) directly in ProcessXYZ, but it still generated the error. I've also tried converting ProcessXYZ to a no-input, no-output function with the same results.
The problem happens regardless of whether I'm running ProcessXYZ from the command window or through the GUI on the code editor, and really does seem to be that MATLAB simply ignores the line that calls uigetfile().
Thanks again for your help!

サインインしてコメントする。

回答 (2 件)

Geoff Hayes
Geoff Hayes 2014 年 8 月 1 日
編集済み: Geoff Hayes 2014 年 8 月 1 日
Maria - I get that same error message
Warning: Input should be a string.
> In strcat at 83
In InputSeaLevel at 4
Warning: Input should be a string.
> In strcat at 91
In InputSeaLevel at 4
Error using load
File name is empty.
Error in InputSeaLevel (line 4)
varname=load(strcat(pname,fname));
if I run the code and choose not to select a file i.e. press the Cancel button. Is this what you are doing, or are you in fact selecting a file?
The InputSeaLevel code should be modified to handle the case of the user not selecting a file
function [sl] = InputSeaLevel()
[fname,pname]=uigetfile('*.mat','Select the file containing sea level data');
% if no file selected, then fname is a double - so check for char/string
if ischar(fname)
varname=load(strcat(pname,fname));
name=fieldnames(varname);
sl=getfield(varname,name{1});
else
% raise error indicating no file selected
error('InputSeaLevel - no file selected!');
end
-------------
As for running your script, if I create one or more dummy text files with 26 numeric elements in it (as per the specification) and run ProccessXYZ, I am prompted for a directory (for the XYZ data), I then see the menu (from which I select yes), and then I'm prompted with the file chooser, and the code runs to completion if I have chosen a file.
Have you thought about stepping through the code in the debugger? i.e. put a breakpoint in ProcessXYZ at line 10
if c1==1
and then re-run ProcessXYZ. What is the value of c1, at this point, when the user has selected Yes in the menu.
  4 件のコメント
Sarah
Sarah 2014 年 8 月 1 日
Thanks again, Geoff. I tried changing the conditional statement to 1==1, and that didn't help-- MATLAB was already entering the if loop to try to run InputSeaLevel. I edited the last statement in ReadXYZ to use the clearvars command, too, without effect. (If nothing else, that's probably a best practice I should generally adopt. Thanks for making me aware of it.)
I tried commenting out the ReadXYZ, and, voila, the code worked. Once. (I tried it a second time to be sure and for reasons unknown, it failed.) I can't makes heads or tails of why it worked-- and why it subsequently failed to work.
I think I may chalk this up to a computer (or institution)-specific issue, since you and the other commenters haven't been able to reproduce the bug using my codes (or even my simplified if statement), but my officemate could.
Thank you again for all your help-- one day I will figure this out and post a more definitive answer. Until then, people are just going to have to load sea level manually. (Or find the answer themselves!)
Geoff Hayes
Geoff Hayes 2014 年 8 月 2 日
Good luck, Sarah! One thing you may want to consider doing is following the suggestion from dpb and make your ReadXYZ and ProcessXYZ into functions (with the end as the last line for each). Just to see what happens.
One other positive benefit of making functions is that all variables are local to the function and so don't populate the base workspace. This removes the need for the clearvars or other statements. I realize that some of your variables from ReadXYZ need to be made available to ProcessXYZ, and they could be with just simple return to the function signature. For example, the first line of ReadXYZ becomes
function [stackXYZ,RunName,SaveDir] = ReadXYZ
and you can remove the clearvars at the end.
And the first couple of lines of ProcessXYZ becomes
function ProcessXYZ
close all
%%Loading and Gridding
%Loads the data and combines them into a single "stack" of output arrays
[stackXYZ,RunName,SaveDir] = ReadXYZ;
__
And the final thing I will say about the uigetfile problem and how when you commented out ReadXYZ it worked the first time but not the second. Could this have to do with some of the script variables (now in the base workspace) conflicting with some built-in function name? Anyway, if you have time, then please try the above.

サインインしてコメントする。


Martijn
Martijn 2015 年 1 月 23 日
It looks like you are running into the bug which is described here:
https://www.mathworks.com/support/bugreports/895795
The menu function creates a figure which after you have made a choice is deleted. This then leads to a threading issue which can be resolved by calling drawnow between calling menu and uigetfile.

カテゴリ

Help Center および File ExchangeFunction Creation についてさらに検索

製品

Community Treasure Hunt

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

Start Hunting!

Translated by