Overlay some line plots selectively from different .fig files in Matlab?
2 views (last 30 days)
Show older comments
I have some lone plots which I want to merge into a single plot. For example I have attached the screenshots of the raw plots and their desired overlay (raw).
I got the third plot by using 'edit plot' in the tools strip option. But this way the colors and legends and of the lines are messed up. (same color for multiple line plots. Is there a better way to merge plots systematically? I have attached the .fig files as well.
0 Comments
Accepted Answer
Adam Danz
on 4 Jan 2023
Edited: Adam Danz
on 4 Jan 2023
> Is there a better way to merge plots systematically?
The color of the lines and markers in your plots were intentionally set so when those objects are copied to another figure, their colors and other set properties are maintained. From what I understand, you'd like to merge the objects from both figures into a new figure but without resulting in duplicate colors.
I noticed there is color grouping in each of the two figures. Small points have the same colors as lines and errorbars. I assume these color groupings are important. The solution below copies all objects to a 3rd figure while maintaining the color groupings. It assigns color based on the axes default ColorOrder.
It works for your figures containing lines and errorbar objects but might meed firtjer customization if there are other objects within the axes.
Original Figures
New combined figure
See inline comments for details.
% Define the two figure files that are on the MATLAB path
% These are the only "inputs" to this script
f1 = 'logicalapproach_P2L1_Food Deprivation.fig';
f2 = 'logicalapproach_P2L1_Pre-Feeding.fig';
% Open the figures
fig1 = openfig(f1);
fig2 = openfig(f2);
% get axes handles - this assumes there is only 1 axes per figure!
fig1ax = gca(fig1);
fig2ax = gca(fig2);
leg = findobj(fig2,'Type','legend');
% Get axis children
fig1axChildren = get(fig1ax,'Children');
fig2axChildren = get(fig2ax,'Children');
% Create new fig, copy items from fig 1
% This will maintain set properties such as color
figFinal = figure();
ax = axes(figFinal);
h1 = copyobj(fig1axChildren, ax);
% Reset color but maintain color groups
recolorgroups(h1)
% Copy items from fig 2
h2 = copyobj(fig2axChildren, ax);
% Reset color but maintain color groups
recolorgroups(h2)
% Add legend to same location as the legend in fig2
% but only include objects with a defined DisplayName
h = [h1;h2];
hasDisplayName = ~cellfun('isempty',get(h,'DisplayName'));
legend(ax, h(hasDisplayName),'Location', leg.Location)
% Add title
title(ax,"Combined plot")
% Copy axis labels
xlabel(ax, fig2ax.XLabel.String)
ylabel(ax, fig2ax.YLabel.String)
function recolorgroups(objs)
% objs is a vector of objects
% ax is the parent axes
% Group new objects by color
objColors = cell2mat(get(objs,'color'));
[~, groups, groupID] = unique(objColors,'rows');
% For each color group, set 1 member to use the next series index and set
% the other members to the same series index value.
for i = 1:numel(groups)
hh = objs(groupID == groups(i));
set(hh,'ColorMode','auto');
set(hh(2:end),'SeriesIndex', hh(1).SeriesIndex)
set(hh,{'MarkerFaceColor'},get(hh,'color'));
end
end
2 Comments
Adam Danz
on 4 Jan 2023
> Is there a way we can use all different colors
- remove the recolorgroups function
- Add this to the end of the script
set(h,'ColorMode','auto')
set(h, {'SeriesIndex'}, num2cell(1:numel(h))')
set(h,{'MarkerFaceColor'},get(h,'color'));
Then you can set the axis' ColorOrder' property to control the line color. Example:
ax.ColorOrder = lines(numel(h));
% or
ax.ColorOrder = turbo(numel(h));
> I want to use only 1 baseline in the combined plot
Replace the legend section in my answer with this one. But then the second basline line will have a different color and will not be represented in the lenged which doesn't sound useful.
h = [h1;h2];
baselineIdx = find(contains(get(h,'DisplayName'), 'baseline'));
h(baselineIdx(2)).DisplayName = '';
hasDisplayName = ~cellfun('isempty',get(h,'DisplayName'));
legend(ax, h(hasDisplayName),'Location', leg.Location)
> and put 'baseline' legend at the beginning.
This is a little more trickly. You'll need to plot that line first. You can use the logic in the block above that finds the first baseline line, plot it first, and then plot the other lines.
More Answers (0)
See Also
Categories
Find more on Line Plots in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!