Implementing multiple syntaxes for a MATLAB plot function - matlab

Many of the plotting functions in MATLAB and toolboxes (thought not all) allow both the following syntaxes:
plotfcn(data1, data2, ...)
plotfcn(axes_handle, data1, data2, ...)
The first plots into the current axes (gca) or creates and plots into a new axes if none exists. The second plots into the axes with handle axes_handle.
Having looked into the internals of several MATLAB and toolbox plotting functions, it looks like there isn't really a standardised way that MathWorks do this. Some plotting routines use the internal, but open, function axescheck to parse the input arguments; some do a simple check on the first input argument; and some use a more complex input-parsing subfunction that can handle a larger variety of input syntaxes.
Note that axescheck appears to use an undocumented syntax of ishghandle - the doc says that ishghandle takes only one input, returning true if it is any Handle Graphics object; but axescheck calls it as ishghandle(h, 'axes'), which returns true only if it's specifically an axes object.
Is anyone aware of a best practice or standard for implementing this syntax? If not, which way have you found to be most robust?

In case anyone is still interested, four years after I posted the question, this is the pattern that I have mostly settled on.
function varargout = myplotfcn(varargin)
% MYPLOTFCN Example plotting function.
%
% MYPLOTFCN(...) creates an example plot.
%
% MYPLOTFCN(AXES_HANDLE, ...) plots into the axes object with handle
% AXES_HANDLE instead of the current axes object (gca).
%
% H = MYPLOTFCN(...) returns the handle of the axes of the plot.
% Check the number of output arguments.
nargoutchk(0,1);
% Parse possible axes input.
[cax, args, ~] = axescheck(varargin{:});
% Get handle to either the requested or a new axis.
if isempty(cax)
hax = gca;
else
hax = cax;
end
% At this point, |hax| refers either to a supplied axes handle,
% or to |gca| if none was supplied; and |args| is a cell array of the
% remaining inputs, just like a normal |varargin| input.
% Set hold to on, retaining the previous hold state to reinstate later.
prevHoldState = ishold(hax);
hold(hax, 'on')
% Do the actual plotting here, plotting into |hax| using |args|.
% Set the hold state of the axis to its previous state.
switch prevHoldState
case 0
hold(hax,'off')
case 1
hold(hax,'on')
end
% Output a handle to the axes if requested.
if nargout == 1
varargout{1} = hax;
end

not sure I understand the question.
What I do is to separate the plotting of data from the generation / setup of plots. So if I want to plot a histogram in a standardized way I have a function called setup_histogram(some, params) which will return the appropriate handles. Then I have a function update_histogram(with, some, data, and, params) which will write the data into the appropriate handles.
This works very well, if you have to plot lots of data the same way.

Two recommendations from the sideline:
Don't go undocumented if you don't need to.
If a simple check is sufficient, this would have my personal preference.

Related

Efficient computation and redoing graphics actions

Are there any general guidelines on how Matlab handles graphics-based commands that ultimately result in no action being taken? A simple illustrative example--note the actual computational cost here is quite negligible:
fig=figure;
ax=axes;
for i=1:10
data=myFunction(i) %e.g. rand(i)
plot(data)
hold(ax,'on') %perform this repeatedly even though it's only needed once
end
versus:
fig=figure;
ax=axes;
for i=1:10
data=myFunction(i) %e.g. rand(i)
plot(data)
if ~ishold(ax)
hold(ax,'on') %perform this only if it is needed
end
end
If Matlab internally determines whether the hold(ax,'on') command is needed before actually doing it, then presumably the computational cost is similar or lower for the first form. The coding is also simpler to implement and read. But, if the action is carried out in full, then there are cases where it would be better, from a computational cost standpoint, to use the second form.
It's worth noting that the definition of "no action" here is deliberately vague, there's a lot of nuance here. For instance, it's easy to create an example where Matlab must perform some level of computation before it can evaluate whether the graphics command would have no effect. For instance, in colormap(myColormapFunction), Matlab would have to call myColormapFunction in order to evaluate whether what it returns is the same as the existing plot's CData property. Thanks.
As far as I know, there are no official guidelines on how "no action" commands are handled by the built-in MATLAB functions. Meanwhile, MathWorks does provide guidelines for optimizing graphics performance; which I feel, is a much more important thing to consider.
Graphics Performance Documentation Page
Now I apologize in advance if the following section doesn't answer your question. But if you are truly curious about the behind the scenes and real-world performance, you should use the provided Code Profiling Tool, and built-in timing functions.
With that said, the next section is about optimizing graphics performance in general.
For example, in the code you've provided, I would strongly recommend against putting hold and plot in the for-loop to begin with. From my experience, these are never necessary and can be optimized away.
Here, I'm guessing that you are trying to animate MATLAB plots; in which case, try updating the plot markers instead of using the plot function. For example:
figure
% Plot an empty plot with placeholder values (NaNs) the size of your data
% Save handle to plot object as `h`
h = plot( nan(size(data)) );
for i = 1:10
[Xdata, Ydata] = MyFunction(...);
% Update your plot markers with the handle update method
h.XData = Xdata;
h.YData = Ydata;
drawnow % drawnow to see animation
end
In this case, I don't even need to use the hold function, since I'm just updating the same plot, which is much faster.
Even if your function is outputting new data series, and you want to plot them on top of the old data series, you can use the same trick; it will only require you to pre-allocate the plot handles and data arrays. (Which, honestly is a good programming practice in general.)
figure
hold on % Hold the plot now
N = 100; % Number of data series you expect to have
H = cell(N,1); % Preallocate N Cells for all the plot handles
for i = 1:N
% Save plot handles to cell array in a loop, if you have so many series
H{i} = plot ( nan(size(data)) );
end
% Your iterative function calls
for t = 1:100
...
% Iteratively update all plot handles with a syntax like this
% (Not entirely sure, this is off the top of my head)
for i = 1:N
H{i}.XData = newX;
H{i}.YData = newY;
end
end

Concise way to implement optional plotting in MATLAB

I like to plot things when I'm testing, but for the full run I would like the plotting to be turned off in an easy and efficient way. Currently I have a variable at the top of the script as follows
plotting = true;
Then, in all the sections with plotting, I have something along the lines of
if plotting
figure;
plot(x,y)
...
end
So of course if I don't want to plot, I simply set plotting = false;
at the top of the script.
Is there a better, more efficient way of doing this? Or does anyone have a method that they use that is different?
As mentioned in the comments, your current method is about as good as it gets... Here is a note on that method and an alternative though.
Keeping the editor warnings tidy
The MATLAB editor will underline the first line in your if statement if you use the syntax you've show, i.e. no comparison operator on a Boolean:
plotting = false;
if plotting
figure % <- this line will be underlined orange
% as the editor "knows" it will never be reached!
% ...
end
A quick fix is to use an equals comparison (==) which the editor doesn't check in the same way. This is also more explicit and slightly clearer for future reference:
plotting = false;
if plotting == true
figure % <- this line is now not highlighted
% ...
end
Using figure-number arrays
You use the word "efficient" in your question. You won't find a more efficient method than the two-liner above, but you might want to play around with arrays of figures. This method allows you to specify certain figures for plotting, and means you can have an array of optional figures:
plotting = [1 3]; % We want to plot figures 1 and 3
if any(plotting == 1)
figure(1); % do stuff with figure 1
end
if any(plotting == 2)
figure(2); % won't enter this condition because plotting = [1 3]
end
if any(plotting == 3)
figure(3); % do stuff with figure 3
end
If you don't want to plot anything, simply set plotting = [];
Note that if you had many similar figures then the 3 above conditionals could be placed in a simple loop, with minor variations (dictated by further if statements) in each plot.
You can add the line:
set(0,'DefaultFigureVisible','off')
At the beginning of your code to keep figures hidden.
Undo this by setting:
set(0,'DefaultFigureVisible','on')
Note that the figures and plots are still created, just hidden.
Example:
set(0,'DefaultFigureVisible','off') % Visible off
figure(6); % This figure will be created but hidden
plot(6:8); % Plot is created but on the hidden figure
set(0,'DefaultFigureVisible','on') % Visible on
figure(6); % The figure will now be shown, with the previous plot.

The hold function for multiple plots in MATLAB

I have been trying to create a MATLAB GUI using Guide which :
i) has a function that takes in input parameters (Temperature, Superconducting Gap Energy, Broadening Parameter) and outputs a plot - a Density of States plot showing a superconducting energy gap.
Note: This function involves numerical double integration, so the parameters can not be varied in a straightforward manner by using sliders. To study the variation in the curve from different parameters, each time the new parameters are input, the function double integrates again and a new curve is generated within the same axes.
ii) The GUI has 4 sets of input fields so that 4 curves can be plotted within the same axes at at a given time for comparison.
I used the following code:
handles.P1=plot(handles.dIdV,bias1,cond1,'r','linewidth',2);
%P1 = plot(handles.dIdV,bias1,cond1,'r','linewidth',2);
hold on
%plot(x,data(:,2),'b','linewidth',2)
%scatter(E,XDOS)
%xlim([min(bias) max(bias)])
%title(nem)
(Kindly do not get confused by the comments. 'cond1' is the result of integration for set1 of parameters, this is plotted against the array 'bias'. Thus the DOS (function of bias, temperature, delta-gap value, etc) is integrated up to each 'bias' value and stored in 'cond1', which is then plotted against that 'bias' value. )
to clear this, I wrote:
% --- Executes on button press in clear1.
function clear1_Callback(hObject, eventdata, handles)
% hObject handle to clear1 (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
handles.temp1=0;
handles.delta1=0;
handles.tao1=0;
handles.vmod1=0;
handles.val1=0;
hold off
i.e. all the parameters are reset to zero and hold function is turned off.
The same bit of code has been written 4 times for 4 different curves.
So each curve has a hold function when the plot command is given and when the clear button is pressed, the 'hold' is supposed to turn off.
e.g. Curve1 is generated using parameterset1. Pressing the clear1 button should turn hold off for curve1 so that new values can be put in parameterset1 and a new curve1 can be plotted on same axes as curve2, curve3 and curve4, without affecting these other curves.
There is a problem with the execution of the 'hold on' and 'hold off' lines in that I cannot delete one curve at a time and replace it with a new one.
The moment I enter new parameters into any of the handles, all the other plots disappear.
Where could I be going wrong?
Is it possible to replace one curve at a time in a single axis with hold on in MATLAB?
Thanks a lot.
Well that is how hold is supposed to work. If you would like to overwrite individual items, just reassign the data that each plot object holds. For example, if you want to replace the handles.temp1 object's data, it would look like:
set(handles.temp1, 'XData', (New xdata), 'YData', (new ydata))
%You might need a drawnow() here but not sure.
You can also update other line object properties the exact same way using set().
Also, note that hold never is off, because otherwise the next plot item will overwrite everything else.
Edit: I would also like to point out that setting handles.temp1 = 0 is not what you are trying to do. Note that a line object has "properties", which is really what you are trying to manipulate. See this for line properties. If you don't know anything about objects and OOP see this

Matlab: Plotting on same figure using 2 different functions

I have written a function of the form
function myplot(x,y)
plot(x,y)
end
This function creates a plot for given values of x and y. The actual function is more complex, but it does not serve the purpose of the question to include its content here. The main point follows.
I have tried to run the following script:
x = [1:0.01:10]
y = [1:0.01:10]
figure
plot(sin([1:0.01:10]))
hold on
myplot(x,y)
The intent here is to plot 2 sets of data on the same graph. The first set of data is generated by Matlab's native plot command while the second set of data is generated by the user custom myplot function (in this case what should be a straight line). The script above wont do it....
How to get Matlab to include both sets of data on the same plot?
your script plots them both but with different x values. if you don't specify x input in plot it uses 1:length(y), while your myplot function does specify x values (which in your case are 10-fold smaller).
just do: plot(x,sin([1:0.01:10])) instead of plot(sin([1:0.01:10]))
You could save the current axes (on which you create the first plot) in a variable and pass it as an argument to your function to be sure it gets plot on the same axes no matter what happens elsewhere in your code.
So your main code could look like this:
x = [1:0.01:10];
y = [1:0.01:10];
figure
plot(sin([1:0.01:10]))
hold on
%// Save axes in variable
CurrentAxes = gca;
%// Pass it as argument to function
myplot(x,y,CurrentAxes)
and the function:
function myplot(x,y,hAxes)
plot(hAxes,x,y);
end

Copy specific axes from figure to new figure

Ive saved a figure as a .fig-file in MATLAB which I did now reopen after some time.
Is there a way to access the data which is saved in the Histogram? I want to replot it by using the hist() command instead of imhist into a new figure (the reason is that matlab2tikz cant export the histogram plotted by imhist properly).
I imagine I could access the data when I would know the handle of the histogram, right?
EDIT:
A = findall(gcf,'type','axes');
then inspecting
get(A(i))
to see which axes the histogram is plotted in. This works but I have to figure out how to retrieve the actual data.
But I somehow assume that I have to look at a parent/children of the axes handle (depending which hierarchy MATLAB creates of objects).
Okay I figured it out finally.
As written in my edit above, you can use findall to find the handles of all axes-objects.
After using it, try to find out which handle refers to which axes by looking at the entries like X/YLim in get(A(i)), after finding the axes-ID and storing it (the k-th element in A) to idx = A(K), use this script to read the entries from the histogram plotted by imhist() -> The values are replicated as often as described by the bins (YData) and then replotted by hist into a new figure:
% ----------------------------------------------------------------------- %
b = get(idx);
b = get(b.Children); % Get the Plot-Handle
x = b.XData; % Bins
y = b.YData; % Bin-Counts
data = [];
for i = 1:length(x)
data = [data x(i)*ones(1,y(i))]; % replicate data
end
figure
hist(data, length(unique(x)));
xlim([min(data) max(data)]);
Edit: The for-loop is a quick and dirty one ;-) Im sure there's a nicer solution e.g. by using repmat, but I was only interested in a quick solution :-)