Call Matlab GUI variables in a loop - matlab

For MATLAB GUI in the m-file, I want to call a set of variables. I have tagged the variables as axes1,axes2,axes3,.......axes125. How can I call it in a loop? Is it possible?
L = imread('white.jpg','jpg');
set(project.cantStop,'CurrentAxes',project.axes1);
set (imshow(L));
See the code
set(project.cantStop,'CurrentAxes',project.axes1);
I want to set it the same way for all 125 variables

Use a cell array to store the axes' tags as strings and use them as the fieldnames to handles as shown below:
%// Cell arary of strings wih the axes's tags
axes_list = {'axes1','axes2','axes3'};
%// For demo on how to use the cell array, use it to choose the axes with
%// tag - `project.axes2`
axes(project.(axes_list{2}));
Thus, you can use a for-loop to loop through the axes for your case, like this -
for k = 1:numel(axes_list)
set(project.cantStop,'CurrentAxes',project.(axes_list{k}));
end
As an example to something similar to what you are trying to achieve with your sample codes, you can show a series of images on the axes. For the demo, let's suppose if you have a set of three images that you would like to show on three axes of the GUI.
%// List of image filenames as a cell array
files_list = {'p1.jpg','p2.jpg','p3.jpg'};
%// List of axes tags as a cell array of strings
axes_list = {'axes1','axes2','axes3'};
%// Show those three images on three different axes of the GUI
for k = 1:numel(files_list)
L = imread(files_list{k},'jpg');
axes(project.(axes_list{k}));
imshow(L);
end

Related

Changing the legend of a figure so that various lines share the same legend entry

A colleague has passed me a .fig file that has many lines on the same plots and they are coloured based on which group they belong to. The figure is shown below for reference.
I need to change the legend so that lines with the same colour have the same legend entry. The problem is that I don't have access to the raw data so I can't use the method mentioned here so is there a way to change the legend entries just using the .fig file? I tried changing some of the legend names to NaN in the property inspector but that just changes the entries to NaN.
If you have the *.fig file you can extract any included data with the 'get' method if you have understood the MATLAB Graphics Objects Hierarchy.
For example, see the left plot below as example of your *.fig file. you can extract the data in there by digging through the Children of your current figure object.
% Open your figure
fig = openfig('your_figure.fig');
% fig = gcf % If you have the figure already opened
title('loaded figure')
% Get all objects from figure (i.e. legend and axis handle)
Objs = get(fig, 'Children');
% axis handle is second entry of figure children
HA = Objs(2);
% get line objects from axis (is fetched in reverse order)
HL = flipud(get(HA, 'Children'));
% retrieve data from line objects
for i = 1:length(HL)
xData(i,:) = get(HL(i), 'XData');
yData(i,:) = get(HL(i), 'YData');
cData{i} = get(HL(i), 'Color');
end
xy data of all lines in the figure is now extracted to xData and yData. The color information is saved to cell cData. You can now replot the figure with a legend the way you want (e.g. using the SO solution you found already):
% Draw new figure with data extracted from old figure
figure()
title('figure with reworked legend')
hold on
for i = 1:length(HL)
h(i) = plot(xData(i,:), yData(i,:), 'Color', cData{i});
end
% Use method of the SO answer you found already to combine equally colored
% line objects to the same color
legend([h(1), h(3)], 'y1', 'y2+3')
Result is the plot below on the right, where each color is only listed once.

Edit objects within a figure

I have figures (in Matlab's fig file format) each of which contains a line plot with two lines (representing EEG curves), axes, bunch of labels etc.
I want to:
change the color of the lines
remove some of the labels
I would loop over the fig files and do the same thing for each of them.
Is there a list of all the objects within the figure that I could index and edit? How can I get to those objects using commands (i.e. without the gui)?
Line, lable, etc. are children of axis, which is itself a child of a figure. What you need to do is acquire handles to the objects you want to change through this hierarchy.
% Get a handle to the figure
hfig = openfig('testfig');
% Get all children of the CurrentAxes. Most of what you want is here.
axes_obj = allchild(hfig.CurrentAxes);
% Edit Axes object according to its type
For ii = 1:length(axes_obj)
switch axes_obj(ii).Type
case 'Text'
% Do something, for example:
axes_obj(ii).String = 'changed';
case 'Line'
% Do something, for example:
axes_obj(ii).MarkerEdgeColor = 'b';
end
end
% Save figure
savefig(hfig, 'testfig')
You can see all the properties of the object you wish to edit by simply typing axes_obj(ii) in the command window.

Accessing legend entries exceeds matrix dimensions

I am trying to plot some data with Matlab R2015a and as the data sets are changing for different plots I want to create the legend (semi-)automatically. I do this with a list of strings (called list) and then
leg = legend(list);
legtxt=findobj(leg,'type','text');
set(legtxt(1),'color','r');
set(legtxt(2),'color','b');
a.s.o. according to the entries.
However, no matter what index I give in the 'set(legtxt(i))' part, Matlab always tells me 'Index exceeds matrix dimensions.' Same, if I create the the legend manually by not using 'legend(list)' but explicitly typing the legend entries. Does anyone know why this happens or how to solve it? Thanks!
You need to use additional outputs from the call to legend. Specifically, check out the 2nd output called icons in the docs.
As for the error, the call to findobj(...) yields an empty vector, so matrix dimensions are indeed exceeded. Indeed (from the docs):
Starting in R2014b, the legend function returns a legend object. In
previous releases it returns an axes object.
So maybe that's why you can't use findobj to fetch legend text...
Anyhow here is how to solve your problem. In this example I create 3 plots and change the color of the text of the 1st and 2nd entry inside the legend:
x = 1:10;
y1 = sin(x);
y2 = cos(x);
y3 = x;
plot(x,y1,'y*',x,y2,'g--',x,y3,'k')
list = {'y1';'y2';'y3'};
%// You want to play with icons and possibly plots.
[leg,icons,plots,str] = legend(list)
set(icons(1),'color','r','FontSize',12)
set(icons(2),'color','b','FontSize',12)
Output:
Of course you can use the plots output to change any property you want of the plots to make them fit with their legend entry.

Montage in Matlab - save and show

When I run this code:
fileFolder = fullfile(matlabroot,'toolbox','images','imdemos');
dirOutput = dir(fullfile(fileFolder,'AT3_1m4_*.tif'));
fileNames = {dirOutput.name}'
zImg=montage(fileNames, 'Size', [2 5]);
imwrite(zImg,'C:\Users\xc\Desktop\ATMtemp.png')
I get the montage image in a new figure, but can I cancel it and just store it in memory?
Furthermore, I cannot save the montage. Any reason why and how can I do it without using getframe as I do not want to show the figure generated?
The montage function in MATLAB's image processing toolbox is for display purposes only and so it only shows a figure. The only way that you'd be able to get the image data from this figure is if you assign a handle to a function as output (which is zImg in your case), then use the getframe/cdata idiom you have suggested. However, this will give you a white border as you have also noticed.
If you want to create an image that is doing the same thing as montage, you can construct what montage is doing yourself. An alternative to montage would be to read in all of the images in a cell array, then arrange them in a montage manually. I'm going to assume that you are stacking the images in row-major format, so the rows are being populated one row at a time. That means images 1 to 5 will be the first row while images 6 to 10 will be the second row.
The trick to get it into a 2D matrix is that you need to use reshape. reshape will populate elements in column-major format, so you need to construct the transpose of your result, then transpose that when you're done. After, use cell2mat to eliminate the cell arrays and make a final 2D matrix.
As such, do something like this:
%// Your code to get all of the image file names
fileFolder = fullfile(matlabroot,'toolbox','images','imdemos');
dirOutput = dir(fullfile(fileFolder,'AT3_1m4_*.tif'));
fileNames = {dirOutput.name};
%// Create a 1D cell array that will store all of the images
images = cell(1, numel(fileNames));
%// Read in the images yourself and populate the cell array
for idx = 1 : numel(fileNames);
images{idx} = imread(fileNames{idx});
end
%// Reshape the cell array so that it's a 2 x 5 matrix, then
%// convert the 2D cell array into a final 2D matrix.
zImg = cell2mat(reshape(images, [5, 2]).');
%// Write to file
imwrite(zImg,'C:\Users\xc\Desktop\ATMtemp.png')
I'm not 100% sure I understand what you're asking, but if you want to plot a bunch of figures and save them to file without having the figure windows flashing by, you could use figure('Visible', 'Off').

Apply plot properties to all MATLAB subplots simultaneously

I would like to create a figure, and once subplots have been created, I would like to apply properties to all of them simultaneously, without going through a for-loop. In fact, I would like to do all the following without having the need to go through a for-loop:
Create all subplots without a for-loop. (For example, create a figure with 4x5 subplots, not using a for-loop).
Apply the same background color to each subplot w/o a foor-loop.
Apply the same axis command to all of them w/o a for-loop. (Like axis equal, axis tight, etc).
Is there a way to do this?
The most convenient approach is to create an array of axes handles, and then to set properties:
for i=1:4,
axesHandles(i) = subplot(2,2,i);
plot(...)
end
%# set background to black for all handles in the array
%# note that this needs no loop
set(axesHandles,'color','k')
If you don't have the axes handles collected, you need to collect the array of handles first. For this, you can use the children properties of the figure window (gcf gets the handle of the currently active figure)
axesHandles = get(gcf,'children');
and if you have axes across several figures, you can use findall to collect everything:
axesHandles = findall(0,'type','axes');
From then on, it's again a single call to set, or to axis, for example
set(axesHandles,'color','k','lineWidth',2)
axis(axesHandles,'tight')
I can't understand why you think that for loop is evil, but anyhow ...
Here is an answer on part 2 and 3 of your question, assuming that the axes handles were saved in an array:
a(1) = axes();
a(2) = axes();
arrayfun( #(x)(set(x,'Color','r')),a);
arrayfun( #(x)(axis(x,'equal')),a);
arrayfun applies a function to each and one of the elements in a. Anonymous function in this case is only a shortcut for writing it in the following way:
a(1) = axes();
a(2) = axes();
arrayfun( #SetRedColor ,a);
arrayfun( #SetAxisEqual,a);
function SetRedColor(x)
set(x,'Color','r');
end
function SetAxisEqual(x)
axis(x,'equal');
end
Another possible way is to link the axes, and set only one property:
linkprop(a,'Color');
set(a(1),'Color','r'); %#Now a(2) color is also red