Using hold for multiple tiledlayout figures in a for loop.

104 vues (au cours des 30 derniers jours)
Andrew Relyea
Andrew Relyea le 21 Mar 2024
Commenté : Voss le 21 Mar 2024
I am building a post processor for batches of Monte-Carlo simulations with excessive amounts of data associated with each run, which prohibits loading/storing all of the data at once. I have a semi-functional code that uses subplot(3,1,x) to group like axis data, but my universal legend either covers portions of the data or skews one of the axes of one of the subplots. I know tiledlayout can make a common legend and place it such that it does not disrupt the figure or introduce excessive amounts of white space.
When I run this code
close all;clc
% data2 = figure();
% % data3 = figure();
t = 1:100;
d1a = randn(10,100);
d1b = randn(10,100);
d1c = randn(10,100);
data1 = figure();
tileddata1 = tiledlayout(3,1);
figure()
nexttile
for x = 1:10
tileddata1;
nexttile(1)
hold on
plot(t,d1a(x,:), 'b-')
hold off
nexttile(2)
hold on
plot(t,d1b(x,:),'b-')
hold off
nexttile(3)
hold on
b = plot(t,d1c(x,:),'b-');
hold off
end
tileddata1;
nexttile(1)
hold on
plot(t, mean(d1a,1),'r--')
hold off
nexttile(2)
hold on
plot(t, mean(d1b,1),'r--')
hold off
nexttile(3)
hold on
r = plot(t,mean(d1c,1),'r--');
xlabel('Time')
leg = legend([b,r],'data','E[data]','Orientation','horizontal');
leg.Layout.Tile = 'south';
I get the intended result, though here it looks like my plot was reformatted to save space. But when I try to add an independent figure utilizing different code
t = 1:100;
d1a = randn(10,100);
d1b = randn(10,100);
d1c = randn(10,100);
data1 = figure();
tileddata1 = tiledlayout(3,1);
nexttile
figure()
tileddata2 = tiledlayout(3,1,"TileSpacing","tight");
nexttile
d2a = randn(10,100);
d2b = randn(10,100);
d2c = randn(10,100);
for x = 1:10
tileddata1;
nexttile(1)
hold on
plot(t,d1a(x,:), 'b-')
hold off
nexttile(2)
hold on
plot(t,d1b(x,:),'b-')
hold off
nexttile(3)
hold on
b = plot(t,d1c(x,:),'b-');
hold off
tileddata2;
nexttile(1)
hold on
plot(t,d2a(x,:))
hold off
nexttile(2)
hold on
plot(t,d2b(x,:))
hold off
nexttile(3)
hold on
b = plot(t,d2c(x,:));
hold off
end
tileddata1;
nexttile(1)
hold on
plot(t, mean(d1a,1),'r--')
hold off
nexttile(2)
hold on
plot(t, mean(d1b,1),'r--')
hold off
nexttile(3)
hold on
r = plot(t,mean(d1c,1),'r--');
xlabel('Time')
leg = legend([b,r],'data','E[data]','Orientation','horizontal');
leg.Layout.Tile = 'south';
All the data gets thrown into the second figure. I need to maintain separation of my data.

Réponse acceptée

Voss
Voss le 21 Mar 2024
Modifié(e) : Voss le 21 Mar 2024
Specify which tiledlayout you want to use by passing it as the first input to nexttile.
Example of plotting to two figures with tiledlayouts simultaneously:
t = 1:100;
d1a = randn(10,100);
d1b = randn(10,100);
d1c = randn(10,100);
d2a = randn(10,100);
d2b = randn(10,100);
d2c = randn(10,100);
f1 = figure();
t1 = tiledlayout(3,1);
f2 = figure();
t2 = tiledlayout(3,1,"TileSpacing","tight");
for x = 1:10
nexttile(t1,1)
hold on
plot(t,d1a(x,:), 'b-')
hold off
nexttile(t1,2)
hold on
plot(t,d1b(x,:),'b-')
hold off
nexttile(t1,3)
hold on
b = plot(t,d1c(x,:),'b-');
hold off
nexttile(t2,1)
hold on
plot(t,d2a(x,:))
hold off
nexttile(t2,2)
hold on
plot(t,d2b(x,:))
hold off
nexttile(t2,3)
hold on
b = plot(t,d2c(x,:));
hold off
end
nexttile(t1,1)
hold on
plot(t, mean(d1a,1),'r--')
hold off
nexttile(t1,2)
hold on
plot(t, mean(d1b,1),'r--')
hold off
nexttile(t1,3)
hold on
r = plot(t,mean(d1c,1),'r--');
xlabel('Time')
leg = legend([b,r],'data','E[data]','Orientation','horizontal');
leg.Layout.Tile = 'south';
(I'm not sure what the intent is for the legend, because b and r are lines in two different tiledlayouts.)
  2 commentaires
Andrew Relyea
Andrew Relyea le 21 Mar 2024
@Voss Thanks. This was exactly what I needed. I was operating under the assumption that the tiledlayout handle was equivalent to a figure handle. My plots are looking great now.
Voss
Voss le 21 Mar 2024
You're welcome!

Connectez-vous pour commenter.

Plus de réponses (1)

Taylor
Taylor le 21 Mar 2024
It always helps to be explicit with your figure and axis handles. Also, the for loops were unecessary. Hope this is more what you're looking for!
t = 1:100;
d1a = randn(10, 100);
d1b = randn(10, 100);
d1c = randn(10, 100);
tileddata1 = tiledlayout(3, 1);
d2a = randn(10, 100);
d2b = randn(10, 100);
d2c = randn(10, 100);
ax11 = nexttile(tileddata1, 1);
hold(ax11, "on")
plot(ax11, t, d1a, 'b-')
plot(ax11, t, mean(d1a, 1), 'r--')
hold(ax11, "off")
ax12 = nexttile(tileddata1, 2);
hold(ax12, "on")
plot(ax12, t, d1b,'b-')
plot(ax12, t, mean(d1b, 1), 'r--')
hold(ax12, "off")
ax13 = nexttile(tileddata1, 3);
hold(ax13, "on")
b = plot(ax13, t, d1c, 'b-');
r = plot(ax13, t, mean(d1c, 1), 'r--');
hold(ax13, "off")
leg = legend([b(1), r], {'data', 'E[data]'}, 'Orientation', 'horizontal');
leg.Layout.Tile = 'south';
xlabel(ax13, 'Time')
figure;
tileddata2 = tiledlayout(3, 1, "TileSpacing", "tight");
ax21 = nexttile(tileddata2, 1);
plot(ax21, t, d2a)
ax22 = nexttile(tileddata2, 2);
plot(ax22, t, d2b)
ax23 = nexttile(tileddata2, 3);
b = plot(ax23, t, d2c);
  1 commentaire
Andrew Relyea
Andrew Relyea le 21 Mar 2024
@Taylor, This is a sample data set just used to help me get the concept across. My actual data is pre-release and can't be used published here. The for loop is used to bring in the data from a single run out of the batch (in this case one row of each array represents the data for that variable in that run).

Connectez-vous pour commenter.

Catégories

En savoir plus sur Specifying Target for Graphics Output dans Help Center et File Exchange

Produits


Version

R2022a

Community Treasure Hunt

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

Start Hunting!

Translated by