Here is the a simpler version of my code.
.....
ch_array = [36, 40, 44, 48, 149, 161];
figure;
for i=1:length(ch_array)
ch = ch_array(i);
subplot(3, 3, i);
eval(sprintf('plot(mean_a_%d_f, ''r'')', ch));
hold on;
eval(sprintf('plot(mean_b_%d_f, ''b'')', ch));
xlabel('Subcarrier (f)');
ylabel('Absolute values');
eval(sprintf('title(''Channel: %d'')', ch));
end
.....
The mean_a
and mean_b
depend on the ch_array
so that as a result, there are mean_a_36_f
, mean_a_40_f
,..., mean_a_161_f
and the same thing with the mean_b
.
This for
loop plots graphs according to ch_array
, the following figure:
As you can see, for each ch_array
element is plotted the corresponding mean_a_ch
and mean_b_ch
.
Now, the purpose is these subplots to concatenate so that all are on one figure, but concatenated and not so how the hold on
does. The concatenation should look like this:
where for the each concatenated plot will be denoted on the X axis, as can be seen on the pic.
You have two problems. I'll start with the one you didn't ask about, since I'm worried you'll stop reading once I answer the other one.
You should not be using eval
unless it's really necessary, and it's never necessary. eval
is slow and insecure. If you eval
malicious code, it can easily do serious harm to your system. In this case this is unlikely, but still using eval
prevents MATLAB's just-in-time compiler to be able to optimize anything in the code inside, so you'll get the worst possible performance.
Now, you're claiming that you're stuck with eval
because the variables are already set up dynamically. Note that this is a perfect example of an XY problem: you shouldn't end up with these data in the first place. Do them differently. If you're not in control of data creation, keep hitting the head of the person who is, so that they stop.
Anyway, once the damage is done, you can still quickly recover from the eval
pit of doom. You need to save and reload your variables, which allows you to push them into a struct. This is nice, because struct fields can be accessed dynamically. Rewriting your original:
tmpfile = 'tmp.mat';
save(tmpfile,'mean_*_*_f'); % save relevant variables to tmp mat file
dat = load(tmpfile); % reload them into a struct named dat
ch_array = [36, 40, 44, 48, 149, 161]; % we could deduce these programmatically
figure;
for i=1:length(ch_array)
ch = ch_array(i);
subplot(3, 3, i);
plot(dat.(sprintf('mean_a_%d_f',ch)), 'r'); % look, Ma, no eval!
hold on;
plot(dat.(sprintf('mean_b_%d_f',ch)), 'b');
xlabel('Subcarrier (f)');
ylabel('Absolute values');
title(sprintf('Channel: %d',ch)); % seriously, this DID NOT need eval
end
Now, for your question. The problem is that plot(y)
with this simple syntax plots y
as a function of 1:numel(y)
: essentially plot(1:numel(y),y)
. What you want to do is manually shift the x
points for each data set so they don't overlap:
figure;
offset = 0;
midpoints = zeros(size(ch_array));
for i=1:length(ch_array)
ch = ch_array(i);
% deduce data to plot
tmpdat_a = dat.(sprintf('mean_a_%d_f',ch));
tmpdat_b = dat.(sprintf('mean_b_%d_f',ch));
x_a = offset+1:offset+numel(tmpdat_a);
x_b = offset+1:offset+numel(tmpdat_b);
% plot
plot(x_a, tmpdat_a, 'r');
hold on;
plot(x_b, tmpdat_b, 'b');
% store xtick position
midpoints(i) = mean(mean(x_a), mean(x_b));
% increment offset
offset = offset + numel(max([tmpdat_a, tmpdat_b])) + 10; % leave a border of width 10, arbitrary now
end
xlabel('Subcarrier (f)');
ylabel('Absolute values');
xticks(midpoints);
xticklabels(arrayfun(@num2str, ch_array, 'uniformoutput', false));
title('All channels');