6

I have a plot with two lines and two different x-axis (different data units), which I plot like the following.

My problem is that I would like to draw the top line of the box black as well (horizontally), and not leave it "open" like it is. It would be great if the line had the x-axis ticks as well, same as the bottom horizontal axis line.

Obviously, grid on doesn't work, because it draws the y1-axis ticks on the right and the y2-axis ticks on the left, which I don't want.

Also, I think in Matlab 2014, this worked: set(ax(2),'XAxisLocation','top','XTickLabel',[]); but it doesn't anymore in Matlab 2015a.

Here's the example:

figure(1);
x = [0, 1, 2, 3];
y_1 = [3, 2, 1.5, 1];
y_2 = [0, 0.5, 0.7, 0.9];
parula_blue = [0, 0.447, 0.741]; parula_red = [0.85, 0.325, 0.098];

[ax, h1, h2] = plotyy(x, y_1, x, y_2);
set(get(ax(1),'Ylabel'),'String','Data 1', 'Color', 'k');
set(h1,'LineWidth',2,'LineStyle','-','Color',parula_blue,'DisplayName', 'Name 1');
set(ax(1),'ycolor',parula_blue);
set(ax(1), 'YTick', [0 1 2 3 4]);
set(ax(1), 'ylim', [0 4]);

set(get(ax(2),'Ylabel'),'String','Data 2', 'Color', 'k');
set(h2,'LineWidth',2,'LineStyle','--','Color',parula_red,'DisplayName','Name 2');
set(ax(2),'ycolor',parula_red);
set(ax(2),'YDir','reverse');
set(ax(2), 'YTick', [0 0.2 0.4 0.6 0.8 1]);

xlabel('X axis desc')
legend('show')
set(ax, 'XTick', x)

set(ax(1),'Box','off') % Turn off box of axis 1, which removes its right-hand ticks
set(ax(2),'Box','off') % Turn off box of axis 2, which removes its left-hand   ticks

enter image description here

Dev-iL
  • 23,742
  • 7
  • 57
  • 99
Ela782
  • 5,041
  • 5
  • 53
  • 66
  • 1
    What about adding `hold on` `plot([0 3],[4-0.001 4-0.001],'k') ` ? will that do the job for you? – Ander Biguri May 21 '15 at 11:21
  • 1
    @AnderBiguri: It looks a bit ugly, it doesn't exactly look like the bottom axis line, and it doesn't overdraw the orange/blue ticks at `0`/`4` the same way. Also it doesn't have the axis-ticks. It would be the last resort solution I guess, but it doesn't look good. – Ela782 May 21 '15 at 11:24
  • I agree, it was just worth a try ;) – Ander Biguri May 21 '15 at 11:26
  • Out of curiosity (I don't have R2015) what actually happens when you use `set(ax(2),'XAxisLocation','top','XTickLabel',[])`? Do you get an error message? That's weird this is not working anymore. – Benoit_11 May 21 '15 at 11:34
  • @Benoit_11: Nothing happens in R2015a. I don't have R2014x anymore but I believe it did the trick on the old version. – Ela782 May 21 '15 at 12:35
  • Yes it works perfectly with older versions that's puzzling. – Benoit_11 May 21 '15 at 12:39
  • Yep, but I think it really does something else anyway: If you try it on `ax(1)`, you'll see it will put the complete axis (including the description) from the top to the bottom, which is not what I want either. I guess it was just "luck" or a bug that it actually did what I wanted it to do with `ax(2)` on R2014. – Ela782 May 21 '15 at 12:55
  • 1
    @AnderBiguri is there any reason you subtract `0.001`? It looks much nicer if I just use `...,[4 4],...`. – Ela782 May 22 '15 at 11:08
  • Oh, it looked nicer in my PC, just that. – Ander Biguri May 22 '15 at 11:14

2 Answers2

3

Based on this answer, you can simply add another axes to your plot, and specify that its horizontal axis is at the top (this code goes at the end of your code):

hBox = axes('xlim', [x(1) x(end)],'XTick', x, 'YTick',[],'XAxisLocation', 'top',...
            'XTickLabel',[]);

Edit:

As per the OP's clarification in the comment, it is possible to draw the black axes "underneath" the blue\orange by reordering the children of the figure, namely, after my above code, add also:

uistack(hBox,'bottom'); %// This sends the black axes to the back.
ax(1).Color = 'none';   %// This makes the plot area transparent for the top axes, so 
                        %// that ticks belonging to the black axes are visible.

enter image description here


BTW, I remember using a similar trick when I wanted to have minor and major gridlines with different colors - each set of gridlines belonged to its own axes with their own color.

Dev-iL
  • 23,742
  • 7
  • 57
  • 99
  • Your solution draws with black over the blue left y-axis. That's an absolute no-go in this case (you probably didn't notice it I guess). Can you avoid that? – Ela782 Jun 14 '15 at 13:57
  • Also, on the top line, I would like to draw the ticks, but not the labels (0, 1, ...). – Ela782 Jun 14 '15 at 13:58
  • This is some Matlab wizardry. Works perfectly. Thank you very much! – Ela782 Jun 14 '15 at 19:12
0

If you want to avoid adding another set of axes, you can still use ax(2) but you need to make it visible first:

ax(1).Box = 'off';
ax(2).Box = 'off';
ax(2).XAxis.Visible = 'on';
ax(2).XAxisLocation = 'top';
ax(2).XTickLabel = [];
ax(2).XTick = ax(1).XTick ;