let's assume the following easy example:
f = figure;
plot(-10:10, (-10:10).^3, '*-r');
x = 1;
y = 1;
set(f, 'ResizeFcn', {#resizeCallback2, x, y});
while 1
[x, y, button] = ginput(1);
if(button ~= 1)
break;
end
set(f, 'ResizeFcn', {#resizeCallback2, x, y});
end
%%--------------------------
function resizeCallback2(hFig, ~, foo, bar)
foo
bar
end
Is there any easier way to always pass the ACTUAL* values for x and y to the callback function instead of having to always update it in the loop?
Thanks!
It looks like you are trying to store the value of a mouse click position, and then use those values as a part of the resize function (which would be called at a later time). There are a few changes that I would make.
First, instead of the while loop, use another callback to capture the mouse click. For example, you could use the figure ButtonDownFcn call back to trigger a function which was designed to capture the mouse position into some location.
Second, there are better ways to store the mouse position, and the right way will depend on your skill level and the needs of your program. Some of these methods of storing data are:
In the arguments to another callback, like you are doing now. This is pretty painful, but it probably works. So you could keep it if it is good enough for your needs.
The 'userdata' field in most Matlab objects. A few people have brought this up, and it will work fine. I don't like to rely on this because I'm always afraid that some other tool will also want to use the userdata field, and the tools will overwrite data.
A global variable value. I don't like to use globals either, for the same reason I don;t like to use the userdata field. But globals are sometimes the best solution anyway. This is probably the easiest, lowest effort solution to your problem if you only have one figure at a time. (Multiple figures would drive you towards the userdata solution as the easiest solution.)
Provide a handle class to store some data (i.e. x and y) and give a copy of that class to each of the two callbacks (ButtonDownFcn and ResizeFcn). This allows the two functions to pass data, without polluting anyone else's namespace. This is my favorite solution to this sort of problem, so I'll give it a more detailed description below.
To execute option (4) above would need a class to store the data that looks something like this:
classdef ApplicationData < handle
properties (SetAccess = public, GetAccess = public)
x = [];
y = [];
end
end
Note that since ApplicationData extends handle, Matlab treats it as a pass-by-reference object, which is useful to us.
Then you can create an instance of this class, and give it to each callback function.
dataPassing = ApplicationData;
set(f, 'ButtonDownFcn', #(x,y) mouseClickCapture(x,y,dataPassing));
set(f, 'ResizeFcn', #(x,y) resizeCallback2(x,y, dataPassing));
Where mouseClickCapture looks something like this:
function mouseClickCapture(hAxis, ignored, dataPassingClass)
mousePositionData = get(hAxis,'CurrentPoint');
dataPassingClass.x = mousePositionData(1,1);
dataPassingClass.y = mousePositionData(1,2);
And your resizeCallback2 looks something like this:
function resizeCallback2(h, ignored, dataPassingClass)
%Do something here using
%dataPassingClass.x
%and
%dataPassingClass.y
I'm not sure what you're actually trying to do - perhaps your simple example has obscured your real intentions - but rather than repeatedly setting a new version of the ResizeFcn, could you just store something in the UserData property of the figure, and have your ResizeFcn read that when it's executed?
Related
I was having a doubt today :).
For
A=1;
is there any function f that does the same? like following
f(A,1);
It could help me in some cases like in cellfun or something like that.
You can do this easily if your variable A is a handle class object, thus giving it reference behavior. You could then create a method f for the class that accepts a class object A and a new value for it to store. See Object-Oriented Programming for more information.
For data types like double or cell there are no built-in functions that work this way. You could make your own function using assignin and inputname like so:
function f(var, value)
assignin('caller', inputname(1), value);
end
And call it as follows, with A already defined:
A = 0;
f(A, 1); % Changes the value of A to 1
However, this would generally be considered bad practice as it makes the code harder to follow, as call-by-value behavior is the expected norm.
In general no, MATLAB functions cannot change their input.
But, if you are brave, you can create a MEX-file that breaks that promise and does change the input. In a MEX-file you can write to the input array, but doing so carelessly causes havoc. For example,
B = A;
f(A,1); % <- modifies A
would cause B to also be modified, because MATLAB delays copying the data when you do B = A. That is, the two variables point to the same data until you modify one, at which point the data is copied. But in a MEX-file you can write to a matrix without doing this check, thereby modifying B also. The link I provided shows how to modify A carefully.
For debugging, I have some plots of vectors in an embedded matlab function in Simulink. Up to Matlab R2013b, everything works just fine with the following minimum example code:
function fcn
%#minimum example for plot within for-loop of embedded matlab function
coder.extrinsic('delete');
coder.extrinsic('quiver');
coder.extrinsic('gobjects');
numSteps=4;
persistent hFig;
persistent hVector;
if isempty(hFig)
hFig = figure;
hold on;
hVector=zeros(numSteps,1);
hVector=gobjects(numSteps,1);
for i=1:numSteps
hVector(i) = quiver(0,0,0,0);
end
end
set(0, 'CurrentFigure', hFig);
delete(hVector);
for i=1:numSteps
startInc=[1 1;1 1].*i;
endInc=[2 3;2 -3].*i;
hVector(i) = quiver(startInc(1,:),startInc(2,:),endInc(1,:),endInc(2,:));
end
For the handle array hVector, an initialization is necessary due to its use in the for-loop. However, for an Initialization of a graphics handle object, the function gobjects is needed and in turn the initialization as double with zeros(numSteps,1) becomes necessary, since matlab cannot correctly determine the data type of an output of an extrinsic function.
As I said, this code snippet works just fine if copied to an embedded matlab function block in simulink without anything else in the model.
My problem: Mathworks changed a lot of the plotting functions in R2014a, one of the changes being the datatype of the graphics handles which are no of type quiver for my quiver plot. Thus, the initialization with zeros(numSteps,1) initializes the wrong data type for the handle array. However leaving it out still does not work, because of the problem mentioned above. Neither does a init loop or anything similar compile without errors.
I'd greatly appreciate any help on that issue.
You can try to remove the gobject initialisation and use double() to wrap your call to any matlab graphic object. Ex:
hVector(i) = double( quiver(startInc(1,:),startInc(2,:),endInc(1,:),endInc(2,:)) ) ;
I suggest reading Loren's article about the compatibility issues which can arise when switching to HG2 versions of Matlab.
A quick quote from it which apply more to your issue:
Graphics Functions Return Objects, not Numeric Handles
Prior to R2014b, you could store a set of handles to graphics objects
in an array and then add some numeric data to that array. In R2014b,
that will cause an error.
[...]
If you find yourself really stuck, it is possible to cast object
handles to numeric handles using the double function. You can then
cast the number back to an object handle using the handle function. We
don't recommend this as a long term solution. Be aware that we may
choose to remove this feature in a future version of MATLAB. If we do,
we'll let you know in advance.
Now if you really have to use this solution, note that both functions works on single elements but also on arrays. So
hVector_HG = handle( hVector_Num ) ; %// works if "hVector_Num" is an array of numeric handles
%// and ...
hVector_Num = double( hVector_HG ) ; %// works if "hVector_HG" is an array of HG2 graphic handles
That may simplify the round trips between a format or another if they often become necessary.
Edit:
I put this at the bottom of the post for the moment because the beginning is already accepted answer but please try the following and let me know if it works. It may solve your problem in a better (more future-proof) way.
Another way to initialise an array of handle of a given graphic object is to create one (empty is good enough) and replicate it. For example:
hqNaN = quiver(NaN,NaN) ; %// create an empty quiver
hVector = repmat( hqNaN , numSteps , 1 ) ; %// replicate it in an array
will give you an array hVector containing numSteps HG2 graphic object handles. At this point they all point to the very same object but it is perfectly legal to overwrite each element with a handle of the same type. So a later :
hVector(i) = quiver( ... , etc ... ) ; %// overwrite handle "i" with a new quiver plot handle
will (should) work without problem.
A few things to take care with this approach:
where will the empty quiver be created ?
you may already have a "current" figure and you don't want it to be messed up. If not a new empty plot will be created. So to make sure the empty quiver do not cause problem (just a flicker on the screen), you could wrap it this way:
figure ; hqNaN = quiver(NaN,NaN) ; close(gcf) ;
or you can also park it in a figure (it will be invisible anyway) in case you need to re-use a handle of this type for other array initialisation. Just don't forget that once you close the figure it is on, or you delete the graphic object, the hqNaN variable is still there but it is not the same type of handle any more (so not useful to replicate if you want this type exactly).
What if you do not overwrite all you initial handle array ?
Remember all the initial handles of the array point to the same graphic object. So in case your array contains 12 elements but let's say by mistake you only overwrite 10 of them, then 2 elements will be handles pointing to the same object (which you may already have deleted)). This means that calling:
delete(hVector)
will throw you the annoying:
Error using handle.handle/delete. Invalid or deleted object.
gna gna gna ... luckily you can easily prepare for that by programming defensively and using instead:
delete( hVector(ishandle(hVector)) )
Matlab will do the check automatically and only delete the right handles.
This might seem like a strange thing to do, which it probably is. In my main (or how you call it in matlab) I would like to have all the information needed for the program to run. A change of variables or formulas should only happen in my main.
For example I would like to change the number of iterations and the formula of the hypothese in my main and let other function use these, instead of declaring them within the function themselves and having to edit it all over the place. The problem I face is not knowing how to do this properly for hypothese_formula and wonder if there is a better way of doing this?
function prog1()
iterations = 1;
hypothese_formula = x^2;
doSomethingWithFormulaAndIterations(hypothese_formula, iterations);
end
Practical: I would to do linear regression with a hypothesis of the formula and specific starting values of theta and don't want them to be hidden within a function. I don't know how to declare global formula's.
You can use anonymous functions.
function prog1()
iterations = 1;
hypothese_formula = #(x) x.^2
doSomethingWithFormulaAndIterations(hypothese_formula, iterations);
end
I operate on global variable the way below in code. I want to save every time to global variable and keep its content so that it expands. If I declare function with output being this variable, in case of huge structures it may significantly slow down I assume. How to do it?
function test()
global n1;
n1 = [1 2 3];
for x=1:10
% [n1] = global_up(n1,x); % no need for output parameter, as n1 is global right?
f_up(n1,x);
end
end
function f_up(arg1,arg2) %function [arg1] = f_up(arg1,arg2) is wrong?
global n1; % need to write it in every function ?
arg1 = [arg1 arg2];
end
I don't really understand what you are trying to do, but global variables are almost definitely not the way to go. just pass the variable as a parameter:
function test()
n1 = [1 2 3];
for x=1:10
n1 = f_up(n1,x);
end
end
function arg3 = f_up(arg1,arg2)
arg3 = [arg1 arg2];
end
But if you explain the point of this code you might get a much better solution. as it stand f_up really doesn't do anything (i.e. it encapsulates syntax that is already very concise with no benefit)
EDIT: Consider this question for a discussion of your actual problem: How to modify an array in function?
I think what you want to do is call by reference, the usage of a global variable is unnecessary.
You have a variable x, you want to give that variable to a function and you want the function to do manipulations on x directly, so that these manipulations will be visible on the xoutside your function.
This is called call by reference. Matlab doesn't support it for simple variables.
You can however use an object that inhertis from the handle - class. This will give you the desired behaviour.
If you don't want to use objects, you will have to use a return argument in your function. Don't use global variables, they will make your code unreadable and almost certainly lead to mistakes.
when I am doing a function in Matlab. Sometimes I have equations and every one of these have constants. Then, I have to declare these constants inside my function. I wonder if there is a way to call the values of that constants from outside of the function, if I have their values on the workspace.
I don't want to write this values as inputs of my function in the function declaration.
In addition to the solutions provided by Iterator, which are all great, I think you have some other options.
First of all, I would like to warn you about global variables (as Iterator also did): these introduce hidden dependencies and make it much more cumbersome to reuse and debug your code. If your only concern is ease of use when calling the functions, I would suggest you pass along a struct containing those constants. That has the advantage that you can easily save those constants together. Unless you know what you're doing, do yourself a favor and stay away from global variables (and functions such as eval, evalin and assignin).
Next to global, evalin and passing structs, there is another mechanism for global state: preferences. These are to be used when it concerns a nearly immutable setting of your code. These are unfit for passing around actual raw data.
If all you want is a more or less clean syntax for calling a certain function, this can be achieved in a few different ways:
You could use a variable number of parameters. This is the best option when your constants have a default value. I will explain by means of an example, e.g. a regular sine wave y = A*sin(2*pi*t/T) (A is the amplitude, T the period). In MATLAB one would implement this as:
function y = sinewave(t,A,T)
y = A*sin(2*pi*t/T);
When calling this function, we need to provide all parameters. If we extend this function to something like the following, we can omit the A and T parameters:
function y = sinewave(t,A,T)
if nargin < 3
T = 1; % default period is 1
if nargin < 2
A = 1; % default amplitude 1
end
end
y = A*sin(2*pi*t/T);
This uses the construct nargin, if you want to know more, it is worthwhile to consult the MATLAB help for nargin, varargin, varargout and nargout. However, do note that you have to provide a value for A when you want to provide the value of T. There is a more convenient way to get even better behavior:
function y = sinewave(t,A,T)
if ~exists('T','var') || isempty(T)
T = 1; % default period is 1
end
if ~exists('A','var') || isempty(A)
A = 1; % default amplitude 1
end
y = A*sin(2*pi*t/T);
This has the benefits that it is more clear what is happening and you could omit A but still specify T (the same can be done for the previous example, but that gets complicated quite easily when you have a lot of parameters). You can do such things by calling sinewave(1:10,[],4) where A will retain it's default value. If an empty input should be valid, you should use another invalid input (e.g. NaN, inf or a negative value for a parameter that is known to be positive, ...).
Using the function above, all the following calls are equivalent:
t = rand(1,10);
y1 = sinewave(t,1,1);
y2 = sinewave(t,1);
y3 = sinewave(t);
If the parameters don't have default values, you could wrap the function into a function handle which fills in those parameters. This is something you might need to do when you are using some toolboxes that impose constraints onto the functions that are to be used. This is the case in the Optimization Toolbox.
I will consider the sinewave function again, but this time I use the first definition (i.e. without a variable number of parameters). Then you could work with a function handle:
f = #(x)(sinewave(x,1,1));
You can work with f as you would with an other function:
e.g. f(10) will evaluate sinewave(10,1,1).
That way you can write a general function (i.e. sinewave that is as general and simple as possible) but you create a function (handle) on the fly with the constants substituted. This allows you to work with that function, but also prevents global storage of data.
You can of course combine different solutions: e.g. create function handle to a function with a variable number of parameters that sets a certain global variable.
The easiest way to address this is via global variable:
http://www.mathworks.com/help/techdoc/ref/global.html
You can also get the values in other workspaces, including the base or parent workspace, but this is ill-advised, as you do not necessarily know what wraps a given function.
If you want to go that route, take a look at the evalin function:
http://www.mathworks.com/help/techdoc/ref/evalin.html
Still, the standard method is to pass all of the variables you need. You can put these into a struct, if you wish, and only pass the one struct.