I've added a number of timeseries to a figures object in Matlab and plotted them as subplots on the graph to display them all together, one after the other. There can be a dynamic number of timeseries plots, I can't know in advance how many there will be.
Unfortunately what seems to be happening is that the figures plot is not expanding to include a scroll bar as new subplots are added. Is there a particular flag I'm not seeing to include this and stop the plots in my figures object from getting smaller and smaller?
As an example:
%Maximise the figure window to full screen
f = figure;
f=gcf;
f.Units='normalized';
f.OuterPosition=[0 0 1 1];
%Add a panel to the figure, we'll add subplots to this
p = uipanel('Parent',f,'BorderType','none');
p.Title = 'Examples';
p.TitlePosition = 'centertop';
p.FontSize = 12;
p.FontWeight = 'bold';
%Add a timeseries subplot to the panel
subplot((length(motifIndexAfterThresholds)*2)+1,1,1, 'Parent',p)
ts0 = timeseries(E4_hrX(startIndex:endIndex),'Name','Parent Motif');
plot(ts0)
title('Parent')
After this point I could add in as many subplots as I like, but the panel is not stretching as I'd have hoped.
If anyone can offer suggestions I'd very much appreciate it.
Anyone with the same problem, check out this (2011) blog post:
https://blogs.mathworks.com/pick/2011/11/23/scrolling-figures-guis/
It turns out that a user submitted function can provide this functionality, and all we need to do is download that .m file, include it in your Matlab path, change the function call from subplot to scrollsubplot in our code.
No idea if this will work long term, a feature like this probably should be included out of the box by matlab itself.
Related
I aim to create 14 subplots with four figures in each subplot. Unfortunately, I do not have any example code to show, as I have not a clue how to go about this. A couple ideas that have popped into my head about how I can go about accomplishing this. One is to create multiple figures separately, then merge them into a single figure. Another is to create subplots with multiple subplots nested inside of them; however, again, I have not a clue how I could go about accomplishing this.
You'll probably find that you are trying to fit too much data onto one figure, and the plots will be too small to see anything of interest. However, a techniques that works, and will give you the option of having individual figures, and combining them into one figure if you wish, is to use individual figures each with a panel on it, then use copyobj to copy to your main figure.
For example,
% Create first figure
hf_sub(1) = figure(1);
hp(1) = uipanel('Parent',hf_sub(1),'Position',[0 0 1 1]);
subplot(2,2,1,'Parent',hp(1));
plot(1:10);
subplot(2,2,2,'Parent',hp(1));
surf(peaks);
subplot(2,2,3,'Parent',hp(1));
membrane;
subplot(2,2,4,'Parent',hp(1));
plot(rand(1,100));
% Create second figure
hf_sub(2) = figure(2);
hp(2) = uipanel('Parent',hf_sub(2),'Position',[0 0 1 1]);
subplot(2,2,1,'Parent',hp(2));
histogram(randn(1,1000));
subplot(2,2,2,'Parent',hp(2));
membrane
subplot(2,2,3,'Parent',hp(2));
surf(peaks)
subplot(2,2,4,'Parent',hp(2));
plot(-(1:10));
% Create combined figure
hf_main = figure(3);
npanels = numel(hp);
hp_sub = nan(1,npanels);
% Copy over the panels
for idx = 1:npanels
hp_sub(idx) = copyobj(hp(idx),hf_main);
set(hp_sub(idx),'Position',[(idx-1)/npanels,0,1/npanels,1]);
end
You may need to be more careful with positioning of the panels, and may want to create the individual figure with their visibility set to off, but the above gives the main idea.
I am trying to create a summary figure that consists of multiple subplots. The issue is that I can not increase the overall size of the figure past the size of the screen. I am trying to create a 12 by 8 subplot so I can view all the figures from an experiment at the same time. However when I generate the subplot this is the result I receive.
Example subplot figure
And here is the code I used to generate said figure.
c = {'r' 'c' 'g' 'm' 'y' 'k'};
for x = 1:96
table = load(file_array(x).name);
table = struct2array(table);
[~,col] = size(table);
subplot_tight(12,8,x);
for t = 1:col
plot(table(:,t), c{t});
hold on
end
H = sprintf('%s\n', file_array(x).name);
title(H);
end
figname = sprintf('%s_Duration_part1',heading.name(1:end-4));
saveas(gcf, figname, 'fig');
close all %reset figure
It's nice that all the sub-figures are visible but it is essentially impossible to actually read the data from the subplots. What would be ideal is to save it so the entire figure is bigger so I can scroll through a bigger figure and look at the sub-figures. Or alternatively if there is a way to save a stack of figures as a slideshow. Ultimately so that all the data for a specific experiment is organized in one respective figure.
If you want to save the whole figure, don't look at the figure itself, but use the print function to configure the renderer.
Try something like:
print('-r1200','Plot','-dpng',)
This sets the DPI setting higher, so you should have more information displayed. You can change some other properties to play with the aspect ratio, the renderer size, etc.
Unfortunately I only have access to octave right now, so I can't really provide you with a working example.
I have the following code in Matlab that runs through a for loop, reads data from a file and plots 9 different figures, that correspond to some particular "channels" in my data, so I decided to annotate them in the for loop.
clear
clc
for i=1:9
subplot(3,3,i);
hold on
x = [4 13]; % from your example
y = ([1 1]); % from your example
y2 = ([-0.4 -0.4]);
H=area(x,y,'LineStyle','none',...
'FaceColor',[1 0.949019610881805 0.866666674613953]);
H1=area(x,y2,'LineStyle','none',...
'FaceColor',[1 0.949019610881805 0.866666674613953]);
% Create textbox
annotation('textbox',...
[0.719849840255583 0.603626943005185 0.176316293929713 0.308290155440411],...
'String',{'FABLIGHT04','Channel',i},...
'FontWeight','bold',...
'FontSize',10,...
'FontName','Geneva',...
'FitBoxToText','off',...
'EdgeColor','none');
axis([0 24 -0.4 1])
set(gca,'XTick',[0:1:24])
set(gca,'YTick',[-0.4:0.2:1])
xlabel('Time (s)');
end
Initially it was giving me 9 different figures and the annotation thing worked fine. But I wanted to be able to tile them onto a subplot for easier comparison.
Since I switched over to using subplot, it does not annotate my figure properly. On opening the editing dock and generating the code, I find that matlab is plotting everything first and then just putting the annotation boxes in the same figure, one on top of the other. Looking at the code it generated, it apparently takes this part of the code:
annotation('textbox',...
[0.719849840255583 0.603626943005185 0.176316293929713 0.308290155440411],...
'String',{'FABLIGHT04','Channel',i},...
'FontWeight','bold',...
'FontSize',10,...
'FontName','Geneva',...
'FitBoxToText','off',...
'EdgeColor','none');
and does it as:
annotation(figure1,'textbox'...)
etc etc
So for all 9 text boxes, it puts them onto the same figure. I tried to do S=subplot(3,3,i) then annotation(S,'textbox') etc etc, I have also tried S(i)=subplot(3,3,i) and then annotation(S,'textbox') etc etc but nothing seems to work.
I have also tried to change the location of the box. I can't seem to figure out how to make it smaller either.
Does anyone know how to have annotation boxes in the right subplot in a for loop?
Thanks
I'm afraid annotation objects are properties of figures and NOT axes, as such its harder to customize the position of each annotation objects because no matter how many subplots you have, they are all part of the same figure and you need to specify their position relatively to the figure coordinate system.
Therefore, you can manually set the position of each text box in your code depending on the subplot it belongs to...
Simple example:
clear
clc
close all
figure('Units','normalized'); %// new figure window
for k = 1:2
str = sprintf('Subplot %d',k);
subplot(1,2,k)
plot(rand(1,10));
%// Customize position here
hAnnot(k) = annotation('textbox', [k*.4-.2 .6 .1 .1],...
'String', str,'FontSize',14);
end
Which looks like this:
Its not very elegant but I'm personally not aware of any other option if you do need to use annotations objects. A less cumbersome alternative would be to use a simple text objects, which are properties of axes and therefore much more friendly to position :)
Hope that helps!
I have a matlab plot that looks like this:
Where the Y values for each of the subplots are stored in single dimensional arrays. What i would like to do is to find an area where the top graph is above a certain height say 0.5. I would also like to highlight the same area in the other graphs as well.
Here is an example of what I am talking about:
The best i have been able to find so far is the function area which will fill an area on the matlab grid. However, if someone could tell me how to make it transparent and also how to fill multiple areas without having to do lots of area commands that would be great.
Otherwise I can identify a group of areas in a struct and use a for loop to plot them. Here is some psuedo code of the way i would do it:
countstruct = 1;
for i = 1:length(yValue)
if (yValue(i) > 1)
outside = [outside, i]
else
areas(countstruct).outside = outside;
countstruct = countstruct + 1;
clear outside;
end
end
Then to plot the areas i would do this:
for i = 1:length(areas)
area(areas(i).outside, ones(length(area), 1)*14, "SomeThingToMakeItTransperant')
end
and i would do this for each of the subplots. Obviously this is quite convoluted so it would be better to have a one liner. Can anyone think of one?
I figured it out, The psuedo code i provided gets the correct regions. You can then do this:
for i = 1:length(areas)
harea = area(areas(i).outside, ones(length(areas(i).outside), 1)*14, 'LineStyle', 'none')
set(harea, 'FaceColor', 'r')
alpha(0.25)
hold on
end
alpha sets the transparency in most area plots. This in combination with the code in the question results in this:
This is pretty cool to plot in matlab.
This should be a problem with a trivial solution, but still I wasn't able to find one.
Say that I have 2 matlab figures fig1.fig, fig2.fig which I want to load and show in the same plotting window.
What should I do?
I mean, I am pretty sure that I can accomplish the task using some low(er) level graphic command which extracts contents from one image and put them in the second one, nonetheless I cannot believe that there is not any high level function (load fig2 on top of fig1) that does this...Comparing 2 plots (unfortunately already saved) is a very common task, I'd say.
Its not clear if you want to extract data from the figures and compare the data, or if you want to combine the plots from two figures into a single figure.
Here is how you combine two figures into one (if thats what you want to do)..
First load the figures:
fig1 = open('FigureFile1.fig');
fig2 = open('FigureFile2.fig');
Get the axes objects from the figures
ax1 = get(fig1, 'Children');
ax2 = get(fig2, 'Children');
Now copy the hangle graphics objects from ax2 to ax1. The loop isn't neccesary if your figures only have a single axes
for i = 1 : numel(ax2)
ax2Children = get(ax2(i),'Children');
copyobj(ax2Children, ax1(i));
end
Note This example assumes that your figures have the same nubmer of axes and that you want to copy objects from the first axes in the second figure to the first axes on the first figure. Its up to you to figure out the proper indexing if the axes indices aren't lined up.
The answer slayton gave is good. Here's another tip: If you have two plots opened in two separate Matlab figure windows, don't forget you can point-and-click copy the proper plots. Do this by clicking the arrow pointer in the Matlab figure window, and then clicking on the plotted line. Copy the (plotted line, textbox, etc...) object. Then, similarly select the axis in the other Matlab figure window and paste it.
I give this 'silly' solution because it has proven to be useful in in collaboration meetings. Point-and-click copying in front of someone (like your adviser) communicates exactly what curves are being compared, and it prevents you from having to fire up code in front of others.
You can also go to File in the menu, Generate Code, for each plots.
Then copy and paste both in the same mfile, with a "hold on" in between and changing details related to the appearance.
Then run the new m-file.