tiledlayout not forming figures as intended

11 次查看(过去 30 天)
Sam Vellequette
Sam Vellequette2021-10-13
回答: Dave B ,2021-10-14
So I've been trying to develop code for a program that will automatically input data from this excel spreadsheet I've created. I would like the code to iterate over each site, for each sample, and plot the relative errors of the sample readings into error bars. The plots would then be grouped by Site, but I can't figure our why my tilelayout won't succesfully organize the figures into columns. I would also like to apologize in advance for the potential density of the code; I'm a novice, and my knowledge of good coding etiquette is pretty limited. Tips welcome lol. But a short summary of what's going on in the code down there; there are 20 potential elements in each sample, though most samples only contain around 6. Thus, I plotted each element at some number along the x-axis by having that element assigned to the variable "k".
The variable siteindexes is which rows of the cell structure are both in the sample (whose value is iterated through in the first loop) and contain a matching value within the field .Site.
I've also attached the XSLX file below. Any help in tackling this would be very appreciated.
There are also vestiges of me attempting to figure out how to make matlab automatically save the figures. I've rid of most of those, but other tips are again appreciated.
Here's the code:
data=table2struct(readtable('EDS Quantitative results (1).xlsx'));
%Create field name vector and generate a new struct based on these fields
%and the data length
%Calculate percent error based on each element (Starting with Oxygen, fifth
for k=5:25
for i=1:lengthdata
errdata(i).(fnames{k})= sqrt(((5/data(i).(fnames{k}))^2)+(0.25^2)) * data(i).(fnames{k});
%% Plot by Site
fpath = 'H:\Documents\MATLAB\Figures';
for samples = 1:4
for sites = 1:max([data.Site])
samplelimitmin=find([data.Sample]==samples, 1 );
samplelimitmax=find([data.Sample]==samples, 1, 'last' );
siteindexes=find([data(samplelimitmin:samplelimitmax).Site] == sites)+samplelimitmin-1;
if ~isempty(siteindexes)
for i=1:length(siteindexes)
hold on
xlim([3 28])
ylim([0 100])
ylabel('Weight %')
for k=5:25
hold on
if ~isnan(data(siteindexes(i)).(fnames{k}))
%If the amount of element is trace, plot as red. If not, black
if errdata(siteindexes(i)).(fnames{k}) <= 5.2
errorbar(k, data(siteindexes(i)).(fnames{k}),errdata(siteindexes(i)).(fnames{k}),'r.','MarkerSize',16,'LineWidth',1);
errorbar(k, data(siteindexes(i)).(fnames{k}),errdata(siteindexes(i)).(fnames{k}),'k.','MarkerSize',16,'LineWidth',1);
if isnumeric(data(siteindexes(i)).Spectrum) && ~isnan(data(siteindexes(i)).Spectrum)
title(strcat('Sample',{' '},num2str(samples),{' '},'Site',{' '},num2str(sites),{' '},'Spectrum',{' '},num2str(data(siteindexes(i)).Spectrum),{' '},data(siteindexes(i)).Time))
elseif isnan(data(siteindexes(i)).Spectrum)
title(strcat('Sample',{' '},num2str(samples),{' '},'Site',{' '},num2str(sites),{' '},'Spectrum',{' '},'Map 1',{' '},data(siteindexes(i)).Time))
%if the number of plots is greater than 1, dont want to save as an
%smaller plot. So, if more than 1, full screen, if 1, small
filename=string(strcat('Sample',{' '},num2str(samples),{' '},'Site',{' '},num2str(sites)));
if length(siteindexes) > 1
FigH = figure('Position', get(0, 'Screensize'));
saveas(gca, fullfile(fpath, filename), 'jpeg');
saveas(gca, fullfile(fpath, filename), 'jpeg');
  5 个评论
Sam Vellequette
Sam Vellequette 2021-10-14
This perfectly fixed it! Thanks for the explanation too. I would've definitely been left perpetually mystified as to why it was fixed.
My plots are beautiful now :")
thanks again!!


回答(1 个)

Dave B
Dave B 2021-10-14
Just pasting my comment in the answer in case it may help someone else, it struck me as strange that there was a hold on before a nexttile but I didn't think twice about it, and really it causes some major confusion!
It took me a while but I think I see where your confusing results are coming from:
for i=1:length(siteindexes)
hold on
Short version: call nexttile before calling hold on, I suspect this will solve your issues.
Long version (this is a lot of explanation about a particularly unfortunate corner you landed in):
The first line, tiledlayout(length(siteindexes),2), creates a new TiledChartLayout with a specific size (two columns).
The third line, hold on, just sets the hold state. It seems pretty harmless. But here's a thing to know about MATLAB: for lot's of commands, if you don't specify a "target", MATLAB will pick one for you. Here, hold on, is equivalent to hold(gca, 'on'). gca is a magical command - it find the current axes, and if one doesn't exist, it creates one.
So after hold on runs now there's an axes, and it's not parented to the layout, it's just sort of in the same figure.
On your next line you call nexttile. nexttile has a simlar pattern to hold in this case - if you don't give it a target (which TiledChartLayout it should go into) it just picks one. And if it doesn't find a layout it will create one (and it defaults to creating one with the flow layout).
nexttile's method for picking a layout is pretty straightforward but not documented. In this case, it saw a current axes (gca) and saw that this axes wasn't in a layout, and so decided you must want a new layout. Creating the new layout in turn wiped out the axes (layouts erase things behind them).
Whew! Very particular and confusing result of calling hold on a bit early!
When you got down to plotting, sometimes your plots were arranged as expected, sometimes not. That's because the flow layout is the default when nexttile causes a new layout to be created, and because flow layout automatically picks the number of rows and columns.




Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by