I have a Matlab function
PlotSubbands(imfx(:,1),wx,3,3,j,j,1);ylabel('Subband');
from TQWT toolbox. eeweb.poly.edu/iselesni/TQWT. When I execute, the function plots 'j' number of plots. (I have not included full code). The function plots the input signal, which is in this case imfx(:,1) for every subplot. And this what I don't want. I tried removing it from the parameters but I got error, 'not enough input arguments'. This is because in the function the first input signal parameters is defined and used. I cannot remove it from there. Appreciate your inputs on the same. Thank you.
The function PlotSubbands include following lines
if isreal(x)
plot((0:N-1)/fs,x/(2*max(abs(x))),'b')
else
plot((0:N-1)/fs, real(x)/(2*max(abs(x))), 'black')
The repeated plotting of input signal is done from these two line. Commenting these lines can solve the problem (If array x does not include imaginary part, then better to comment these lines). However, the to determine the real array, isreal(x) is needed further in the function. So, I defined the value of x here and it solved the repeated plotting issue.
Related
Matlab plot requires the data to be of the same dimension. Meaning, you cannot plot a 1x10 vector with a 1x1x10 vector. This is sometimes necessary. For those purposes, you can use the squeeze function to get rid of the singleton dimensions.
However, this is kind of a hassle. For the plot function specifically, it would be useful to have the argument always squeezed. How would one go about creating a new function, lets call it splot which squeezes every input and passes it onto plot. Here is an attempt (that doesn't work)
function splot(varargin)
for i=1:length(varargin)
varargin{i}=squeeze(varargin{i});
end
plot(varargin)
end
plot(varargin) part fails, because that is simply not how matlab syntax works. But is there any way to achieve what I want? I guess I could write a long if elseif chain where I manually write the case with every possible number of input arguments like:
if length(varargin)==2
plot(varargin{1},varargin{2})
if length(varargin)==3
plot(varargin{1},varargin{2},varargin{3})
But this is going to be very annoying. Any better ideas.
This question is similar to Is there any mechanism to auto squeeze in Matlab / Octave , however, not similar enough, because the other question is for squeezing every vector, which is a bad idea. Here I am asking a way to squeeze only the inputs to the plot function and requiring syntax help.
From the docs there are several ways to call plot. Generally
Just numeric arrays, these can be on their own, or one or more pairs
plot(Y), plot(X,Y) or plot(X1,Y1,...,Xn,Yn)
Numeric arrays as before, with a char array giving the line spec
plot(X,Y,LineSpec) or plot(Y,LineSpec)
Either of the previous two, plus name-value pair options
plot(___,Name,Value)
In any of these cases, you want to squeeze the first N inputs which are numeric, since either of the optional additions have the first non-plottable input as a char.
We can achieve that with the following code, see the comments for details:
function h = splot( varargin )
% Check if there are any optional inputs, which will either be
% LineSpec (which is a char) or name-value pairs (which the
% first of will be a char)
bNumericArg = cellfun( #isnumeric, varargin );
% By default, assume all inputs are arrays to plot
lastArrayArg = numel(varargin);
if ~all(bNumericArg)
% In this case, there are some optional inputs, get last array index
lastArrayArg = find( ~bNumericArg, 1 ) - 1;
end
% Squeeze the arrays
for ii = 1:lastArrayArg
varargin{ii} = squeeze(varargin{ii});
end
% Plot with all inputs, optional output
if nargout > 0
h = plot( varargin{:} );
else
plot( varargin{:} );
end
end
There are two possible cases I've not handled here which the plot function can handle,
Having the first input as the target axes i.e. plot(ax,___), could be achieved by altering the loop slightly to start from 1 or 2 depending if the first input is an axes object
Having pairs of arrays each with their own line spec argument i.e. plot(X1,Y1,LineSpec1,...,Xn,Yn,LineSpecn). The later pairs will be ignored. This would be trickier to handle since you'd likely have to parse all inputs and check whether a char is just a line spec or if you're messing with name-value pairs. Maybe a heuristic to do with "two arrays then a char, repeated". I've never used this syntax so omitting the over-complication for now.
I'm expanding on the question asked at Expand (maximise) subplot figure temporarily — then collapse it back - I tried to post this as a comment to the original post, but I don't have sufficient privileges.
I was using the version in the comments:
function gcaExpandable
set(gca, 'ButtonDownFcn', [...
'set(copyobj(gca, uipanel(''Position'', [0 0 1 1])), ' ...
' ''Units'', ''normal'', ''OuterPosition'', [0 0 1 1], ' ...
' ''ButtonDownFcn'', ''delete(get(gca, ''''Parent''''))''); ']);
end
which worked perfectly in Matlab 2013b. However, I'm now on 2015b and when I try to use that same buttondown function I get the following:
Error using gcaExpandable
Too many input arguments.
Error while evaluating Axes ButtonDownFcn
I don't currently understand what exactly is throwing the error. I've tried to fix it by adding the 'legacy' flag to copyobj based on the documentation:
copyobj(___,'legacy') copies object callback properties and object
application data. This behavior is consistent with versions of copyobj
before MATLAB® release R2014b.
but that doesn't change the behavior at all. If anyone can figure out what's causing the error or how to adapt this very useful function to 2015b it would be greatly helpful! Thanks.
This one works for me on MATLAB R2017a:
set(gca, 'ButtonDownFcn',#(ax,~)set(copyobj(ax,uipanel('Position',[0,0,1,1])),...
'Units','normal', 'OuterPosition',[0,0,1,1],
'ButtonDownFcn',#(co,~)delete(get(co,'parent'))));
You can put this inside a gcaExpandable function as in the OP.
The big difference with the code in the OP is the use of anonymous functions. Callbacks have two input arguments, the first one is the callback object (the thing clicked on), the second one can be ignored, but must be present in the function definition (hence the ~, which signals an ignored parameter).
By using anonymous functions instead of a string to be evaluated, the syntax is clearer (no doubled-up quotes).
Under Octave, the copyobj function works differently. To get the same code to work, you need more than one statement in the callback. For this it is necessary to define the callback function as a regular, named function, and pass its handle as the callback:
function gcaExpandable
set(gca,'ButtonDownFcn',#callback);
function callback(ax,~)
panel = uipanel('Position',[0,0,1,1]);
newax = copyobj(ax,panel);
set(newax,'Units','normal', 'OuterPosition',[0,0,1,1], ...
'ButtonDownFcn',#(~,~)delete(panel))
(The two functions above are defined in the same file gcaExpandable.m.)
Note that the code is also much cleaner this way, there is no advantage to defining it all as a one-liner. This version also works in MATLAB.
I have a Matlab function that has numerous name-value parameter inputs. For some of the parameter names, there are a lot of possible values (which are not always obvious) that the user can choose from. What I would like to do is, IF the user calls the name, but does NOT give a value, THEN Matlab would display possible entries AND THEN take the user's input.
For example I have a function such as:
function getSomeData( varargin )
p=inputParser;
defaultData='abc';
addParameter(p, 'Data', defaultData);
parse(p,varargin{:});
end
If the user were to call the function in the command window such as:
>> getSomeData('Data')
in which the user did not give a value for 'Data', the window would display and prompt
>> getSomeData('Data')
No value for 'Data' Given
Possible Values of 'Data' are:
'abc'
'def'
'other'
Please input your 'Data':
in which I could use the result=input(prompt) function.
Any help or advice is very much appreciated! Cheers
May I ask you to specify the complexity of your input stuff. Either you come from java and think that you need to create an I/O object to be able to read inputs, or else your problem is more complex that the description gives the impression of.
Otherwise, I would give you the design of a less complicated way forward here. One way to do this is to use the nargin property, which finds the number of inputs to the function. Together with nargin, use an if statement (or switch-case?).
if nargin==0
% print alternative inputs with disp or fprintf.
% This alternative can also be replaced with comments (single block with
% no empty rows) right below the function. This will then be seen with
% the `help funName` command
elseif nargin==1
% Print description + permitted values. This can be done from a
% switch-case statement (if you want the switch-case statement
% can be placed in an external function).
elseif ~mod(nargin,2)
%parse input pairs and do the calculations.
else
error('wrong number of input arguments');
% or
% fprintf('wrong number of input arguments\n');
% set outputs to '', {}, [], ...
% return;
end
I hope this helps even though it is not exactly the solution proposed by you. This is however a simple solution with the advantage that you do not mix up the information parts and execution parts. My guess is that this is a convenient way to work with I/O without implementing a complicated parser.
These problems are otherwise normally solved by a complicated parser with a lot of different commands (compare with the terminal (unix based) of cmd prompt (windows)).
Getting started with matlab guide, hit a stumbling block. Got it as simple as I can as a toy gui to illustrate my problem. A gui (named asas) has a pushbutton and an axis. The callback of the button reads
axesHandle= findobj(gcf,'Tag','axes1');
x=rand(randi(10+20,1),4);
plot(axesHandle, x)
There's no other code written by me (guide wrote it).
The 1st time I push the button, everything is fine: the plot gets done. The 2nd time around, I get an error, from the console:
Error using plot
Vectors must be the same lengths.
Error in asas>pushbutton1_Callback (line 83)
plot(axesHandle, x)
Error in gui_mainfcn (line 96)
feval(varargin{:});
etc...
I want to plot the new data x, replacing the old one.
It looks like matlab is not replacing the data to plot, but somehow trying to append to the plot?
I have searched, but haven't found anything that applies.
The explanation is not straightforward - and certainly not if you are new with MATLAB and its handle graphics subsystem.
Your code as it is, line by line:
axesHandle= findobj(gcf,'Tag','axes1');
x=rand(randi(10+20,1),4);
plot(axesHandle, x);
The first line attempts to locate in the current figure (gcf, "get current figure") any child object with the property 'Tag' set to the string 'axes1'. I guess you are aware of this? The second line of course generates some random data to plot. The third line plots the data in x.
But after the plot-call the property 'Tag' is actually reset to '' (the empty string), which in turn makes findobj fail in any subsequent searches for the axes-handle. The variable axesHandle with therefore NOT contain an actual handle but instead the empty matrix []. This will make plot default to another mode an interpret the empty matrix as data for the x-axes (the first argument to plot). This expectedly results in the error you receive:
...
Error using plot Vectors must be the same lengths.
...
The solution by Dan in the comment above is a workaround, but there is good sense in telling plot where to plot - especially in GUIs.
You can instead add a fourth line:
set(axesHandle,'Tag','axes1');
This will set property 'Tag' back to 'axes1' and any subsequent clicks on the button should now also work. And you can add more than one axes-objects now. If that is what you want to.
I have a simple function written
function[] = myfun(p,q)
fminbnd(#(x)myfun1(q,p,b),0,1)
where myfun1's output is from the function quad.
How do I plot myfun? I've tried fplot(#(x)myfun(1,x),0,1) but this gives me a matrix dimensions must agree error...
Your question does not contain enough information to identify exactly where the problem lies, but one issue is certainly that myfun does not return any output. What should fplot plot, if there is nothing returned by the function?
Try
function out = myfun(p,q)
%# you may want to define b here
out = fminbnd(#(x)myfun1(q,p,b),0,1);
If that doesn't fix the issue, turn on the debugging mode by typing dbstop if error at the command line. This will show where exactly the error occurs, and allow you to inspect the variables for correct shape.