Data "hides" when using plotyy

I am using the following to plot two data sets ont he same graph
[AX,H1,H2] = plotyy(A,B,A,C,'plot');
It is in a loop. The first time I run this everything is fine, but if I run again, the second data set disappears after plotting the last point. It is visible upto this time.
set(H2,'Visible','on'); %# Make 2nd y axis visible, H2 as sometimes is disappears
I have used, but to no effect.

6 Commenti

Adam
Adam il 13 Feb 2015
Modificato: Adam il 13 Feb 2015
When you say it is in a loop are you using
hold on
at all in the loop or are you wanting each plot to replace the previous one?
If you aren't using hold on I would expect the first plot to disappear when you plot the 2nd, but not for the 2nd plot to disappear.
I've never really used plotyy though so I'm not sure what its behaviour is with respect to the current axes and whether it keeps replacing the existing axes (I assume so) on a figure.
It might help if you can give a piece of code that can be run as standalone code as I don't have time to work out what I need to create in my workspace to replicate your problem (though someone else will probably provide an answer anyway!)
nrows=13;
for row=0:(nrows-1)
for index = (row*step+1):((row+1)*step)
name=file_list{index};
f = fullfile(folder,name);
IM = imread(f);
%Calc subregion mean and focus metric (Brenner Metric) %Now calc SD on ROI
[xsize, ysize]=size(IM);
xc=ceil(xsize/2);
yc=ceil(ysize/2);
ROI=IM(xc-75:xc+75, yc-75:yc+75);
FM = fmeasure(ROI, 'BREN', []);
mn=mean(ROI(:));
%Plot
axes(handles.axes4)
A(index)=index;
B(index)=FM;
C(index)=mn;
[AX,H1,H2] = plotyy(A,B,A,C,'plot');
set(H1,'LineStyle','--', 'color', 'r','Marker','*','MarkerSize',4);
set(H2,'LineStyle','--', 'color', 'b','Marker','.');
set(get(AX(1),'Ylabel'),'String','FM','FontSize',8,'Color','red');
set(get(AX(2),'Ylabel'),'String','Mean','FontSize',8,'Color','blue');
set(get(AX(1),'Xlabel'),'String','Tile Number','FontSize',8)
set(AX(1),'XLim',[0 lc],'FontSize',8);
set(AX(2),'XLim',[0 lc],'FontSize',8);
set(AX(1),'YColor','r')
set(AX(2),'YColor','b')
grid on;
drawnow
end
axes(handles.axes2)
axis off;
%imagesc(stdmap,[100,500])
imagesc(stdmap,[min(stdmap(:)),max(stdmap(:))]);
ylim([0.5 nrows+0.5]);
axes(handles.axes3)
axis off;
%imagesc(meanmap,[1000,1500])
imagesc(meanmap,[min(meanmap(:)),max(meanmap(:))]);
ylim([0.5 nrows+0.5]);
end
What effect are you trying to create? If you're trying to add additional lines to the initial plot in the loop, use
hold all
on each axis (hold for some reason has never been vectorized to accept a set of handles; must use one at a time) then add the data to each axis in turn as well.
Jason
Jason il 13 Feb 2015
Modificato: Jason il 13 Feb 2015
The two plots are added at the same time for a given x value using the plotyy function. The plots work fine until the very last data point, then the 2nd plot disappears!
Just to add, when I start my program first time it works fine, its subsequent execution of the code above that causes it to do this.
dpb
dpb il 13 Feb 2015
Well, as the other poster notes, w/o any data we can't reproduce your efforts to 'spearmint w/o trying to build an example from scratch. As he, I'd suggest building a runnable small demo that illustrates the problem that can paste/post. Doing that may, in fact, lead to discovering the difficulty on your own in which case you can post the solution! :)
It appears not to be due to any of the code in the loop above, so Im checking my code for after the loop. I have noticed, that as I want to set the yscale for the left y axis myself using code below, its not doing it:
set(AX(1),'YTick',newYTicks,'YTickLabel',num2str(newYTicks'))
where
newYTicks =
0 50 100 150

Accedi per commentare.

 Risposta accettata

dpb
dpb il 18 Feb 2015
Modificato: dpb il 18 Feb 2015
OK, I redid your callback function as follows for the LH plot. It produces same result for multiple clicks now altho needs a reset function to clear the data going forward and I also didn't worry about rescaling the dummy data to be within the axes ranges and all...
Take all the one-time stuff out of the loop and instead of making more line handles with the repetitive calling of plotyy simply update the data arrays and refresh. That's much faster and also far less overhead plus you were overwriting line handles with every call with the same variable when calling inside the loop.
See the documentation in the Graphics section on Animation for more details on how the guts works.
You also need a cleanup callback for the GUI; when you click the Close window X this currently errors as stuff is deleted in wrong order--I "know nuthink!" about GUIs so don't know precisely how that's supposed to be handled. I presume GUIDE will lead you through the process.
But, this should show enough of how to address the various handle graphics objects to stop the conflicting handles problems you're currently having. NB: as I said initially, the top-level outer axes handle is never referenced directly after the initial plotyy call that creates the two axes handles and in this technique it's the two line handles that are referenced instead of axes to update the data.
function pushbutton1_Callback(hObject, eventdata, handles)
% hObject handle to pushbutton1 (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
lc=30;
sum=0;
%axes(handles.axes1)
i=1;
y1=2*i;
y2=3*i;
[hAx,H1,H2] = plotyy(handles.axes1,i,y1,i,y2);
ylabel(hAx(1),'FM', 'FontSize',8,'Color','red');
ylabel(hAx(2),'Mean','FontSize',8,'Color','blue');
xlabel(hAx(1),'Tile Number','FontSize',8)
set(hAx,'XLim',[0 lc],'FontSize',8);
set(hAx(2),'Xtick',[]);
set(hAx(1),'YColor','r')
set(hAx(2),'YColor','b')
grid on;
set(H1,'LineStyle','--', 'color', 'r','Marker','*','MarkerSize',4);
set(H2,'LineStyle','--', 'color', 'b','Marker','.');
hold(hAx(1),'on'), hold(hAx(2),'on')
xdat=i;
for i=2:lc
%Generate some dummy data
i;
xdat=[xdat; i];
y1=[y1;2*i];
y2=[y2;3*i];
set(H1,'xdata',xdat,'ydata',y1)
set(H2,'xdata',xdat,'ydata',y2)
drawnow
%Plot sum of i on axes2
sum=sum+i;
%axes(handles.axes2)
%hold on;
%plot(i,sum)
%hold off;
end
%h=handles.axes1;
%hold on;
h_legend=legend(hAx(1),'FM','Mean');
set(h_legend,'FontSize',7);
%drawnow;
hL=plot(hAx(1),[20 20], [0 150],'color','k','linewidth',2);

1 Commento

dpb
dpb il 18 Feb 2015
"Take all the one-time stuff out of the loop ..."
If your callback isn't actually a loop but are updating data from some source, put all that static stuff in some initialization function not in the callback to be executed every time. Or, at a minimum, have a "first call" flag to only execute the startup code once and branch around it for subsequent calls.

Accedi per commentare.

Più risposte (4)

Jason
Jason il 13 Feb 2015
OK, I've worked out what causes the problem, but don't know why it does. Once the loop above has finished, I then want to superimpose a line on this graph so I use hold on.
axes(handles.axes4);
hold on;
for i=0:numregions-1
plot([20 20],[0 Y1(2)],'k', 'LineWidth',1); %Y1(2) is Y1Max
end
hold off;
So adding the line whilst using hold on causes the 2nd y axis plot to hide??

11 Commenti

dpb
dpb il 13 Feb 2015
As noted previously hold only operates on a single axes handle at a time so you've set that to on for whichever axes handles.axes4 refers to. The status of the other axes is as it was last left.
It's not clear to me why you're referring to other axes beyond AX that were referred to in the plotyy call; don't see anything in the above plot that seems to call for them; certainly don't need another set of axes to add vertical lines to one or the other of the two generated with plotyy as long as the x-data are commensurate with the current xlim values--and even if, for some reason you're adding another scaled-differently set of data it's simpler from a plotting standpoint to simply rescale it to the existing axes rather than add yet another layer/object.
But, you've not really outlined the whole objective well enough to know for sure.
Methinks you need set it for all of them
Jason
Jason il 13 Feb 2015
Modificato: Jason il 13 Feb 2015
Well, handles.axes4 is the GUI axes component which I plot to using plotyy So i thought holding this would hold the overall plot i.e. both Y axis.
How do I call a hold on both y-axis?
axes.AX ??
Thanks
dpb
dpb il 13 Feb 2015
Modificato: dpb il 13 Feb 2015
How do I call a hold on both y-axis? axes.AX ??
No, that's what I've said multiple times; you either call hold multiple times (once for each axes with the single handle) or use the set form with an array of handles.
...handles.axes4 is the GUI axes component which I plot to using ploty...
There's the source of much of your problem methinks...in looking back I see
axes(handles.axes4)
...
[AX,H1,H2] = plotyy(A,B,A,C,'plot');
plotyy creates the two axes into which it plots and returns their handles in AX. They are on top of and hiding the other axes you created above. I suspect it's when you make than one active later on that that is what's wiping out other stuff placed on top of it. Remove the explicit call to axes entirely; just use plotyy to create the axes and then those handles are the only ones you need.
Jason
Jason il 13 Feb 2015
But I have serveral axes on my GUI, axes1, axes2, axes3 etc, so do i not need to direct the plotyy to which axes component I want it to be plotted to?
To use set,
set(handles.AX,'Hold','On) is this what you mean??
Thanks Jason
dpb
dpb il 13 Feb 2015
Modificato: dpb il 14 Feb 2015
A) I don't do GUIs so not positive about whether that's somehow mandatory to create areas within but even if is, once you get the two axes handles from plotyy, use them alone; leave the one in which they are placed in the background. I'm virtually positive that'll solve many of your problems. But, I'd think it also possible to use plotyy alone with a position vector if needed and not have the added complexity altho again, mayhaps there's something unique about the GUI I don't know.
_Addendum: There's an option w/ plotyy to pass an axis handle; on reflection I believe the way to do this if you do need the other axes to partition the GUI real estate would be to use it as
[hAx,hL1,hL2]=plotyy(handles.axes4, ...);
This leaves hAx(1) as gca when done and won't bring the underlying axes to the top in the loop or subsequent times to hide the upper layers (I think; as say, I've never done anything of any import with GUIs so am a neophyte in that area). Anyway, I'd surely try it this way first.
ADDENDUM 2:
On yet further reflection, the above action is ok the first call that creates the two plotyy axes; it also leaves the LH axes as gca. What's interesting is if I
>> hAxTop=axes; % create an axes
>> get(get(hAxTop,'children'),'type') % be default no children exist
ans =
[]
>> [hAx,hL1,hL2]=plotyy(hAxTop,1,1,10,10); % make two more via plotyy
>> get(hAxTop,'children')==hL1
ans =
1
>>
Now, the LH axes line object is a child of the base axes but not the RH axes. You have, as I suspected, two conflicting axes who are the controlling parents of this one line whereas only the RH axes of the second line is in effect.
I'm virtually positive this is why it's the first line that stays visible and the second (RH) that is covered when the underlying root axes becomes the top layer somehow.
I see in reading the documentation on creating programmatic GUIs that they do speak of adding an axes object into which later plot so they've got the same issue with two (but not three) competing axes for their examples.
There's some discussion of setting the 'NextPlot' property to 'ReplaceChildren' to ensure don't wipe out callback functions and other preset conditions; not sure if that somehow might have something to do with what's going on here or not.
Anyway, my upshot is still that when you do anything to these two axes after they're created, only use those two saved handles and I don't think you ever want to refer to the top handle again unless you're deleting the first two in order to then create a new plotyy object unless it's done as shown above as the handle in the call. I'm not sure there about what happens in subsequent calls if they occur; whether it adds more or replaces or just adds more lines; I didn't test that far.
B) Basically, yes, although the figure property is 'NextPlot' and the values are one of '[ new | add | {replace} | replacechildren ]'
hold is a higher-level function but boils down to that for the simple conditions of hold on|off sets default of 'replace' to 'add' and vice versa. The 'all' option does some other things as well.
See
doc hold
for details.
Jason
Jason il 16 Feb 2015
Modificato: Jason il 16 Feb 2015
I've Given up, unfortunately its not working. Thanks for your help though.
Could you make an example that illustrates the problem that can post so we can try to duplicate it here?
I made up a figure with
hAxTop=axes;
hAx=plotyy(x,y1,x,y2);
hold(hAx(1),'on')
hold(hAx(2),'on')
hL=plot([20 20], [0 150],'color','k','linewidth',2);
and both lines stayed visible and the vertical line appeared as expected.
Jason
Jason il 17 Feb 2015
OK, I've tried to simplify my code to demonstrate. In my loop where I plot using ployyy on a GUI axes1, I also plot some other data on GUI Axes2.
Jason
dpb
dpb il 17 Feb 2015
Need to save the figure as a file; then attach that file...this is a link but can't save it.
Jason
Jason il 17 Feb 2015
The only option i have is to save as a fig? do you mean zip it up? Thanks Jason
dpb
dpb il 17 Feb 2015
Modificato: dpb il 17 Feb 2015
No, when you use the File menu SaveAs, save local copy then use the paper clip to attach that file. Then I should be able to copy the file itself instead of just open the figure (which has no menu options so can't save it locally and I'm not adept-enough to try to duplicate it that will match the script w/o more effort than care to try...
ADDENDUM
Or, actually, since you must have it saved on disk already to run the test function, use the Attach File paper clip and attach that existing file.
I tried saveas here from the command window with the figure displayed after opening w/ R2012b but that was unsuccessful...the resulting open ends up w/ nothing but an empty figure for some reason. Having never played w/ the GUI stuff I don't know what the deal is...

Accedi per commentare.

Jason
Jason il 18 Feb 2015

0 voti

Hi, thats exactly how i attached the above files test.fig and test.m using the attach paper clip. I will try again Thanks

1 Commento

dpb
dpb il 18 Feb 2015
Modificato: dpb il 18 Feb 2015
Hmmm....it wouldn't let me download the file previously; I'll try again, too. I thought it had been attached as an image the way it behaved.
[scuffle, drag, ...] OK, this time I got a download option and did work.
What should happen? If I then click the button I get an axes w/ only a single red dot with blue dot moving across. Subsequent times the axes blinks which I presume isn't supposed to be?
It appears the data you're generating is off the axes y-limits for the red trace after the first point? Is that intentional or an accident?

Accedi per commentare.

Jason
Jason il 18 Feb 2015

0 voti

No it should plot two data sets on the axes1 and another one on axes2. In reality i loop thru a setof images and plot their mean and std dev on axes1, but i didnt want to upload all the images.
Jason
Jason il 19 Feb 2015
Modificato: Jason il 19 Feb 2015
Thanks for this. It seems tho as if the Y-axis is remaining fixed so the data is off the scale.
I have tried using the following to scale the Y1 axis and set the ticks: (AX is the handle I use not hAx)
Y1=get(AX(1),'YLim');
Y1(2); %Max value
Y1(1); %Min value
diff=Y1(2)-Y1(1);
Depending on the size of diff, I have different tick marks:
newYTicks = 0:10000:floor(max(get(AX(1),'YTick'))); %default
if (diff<40000)
newYTicks = 0:5000:floor(max(get(AX(1),'YTick')));
end
if (diff<10000)
newYTicks = 0:1000:floor(max(get(AX(1),'YTick')));
end
if (diff<1000)
newYTicks = 0:100:floor(max(get(AX(1),'YTick')));
end
if (diff<100)
newYTicks = 0:10:floor(max(get(AX(1),'YTick')));
end
And then set the axis ticks:
set(AX(1),'YTick',newYTicks,'YTickLabel',num2str(newYTicks')) %Use
set(AX(1),'FontSize',8)
drawnow;
But it seems my newTicks is incorrect:
ans =
171.8599
ans =
127.8709
diff =
43.9890
newYTicks =
0
If I do:
get(AX(1),'YTick')
I get a weird result: ans =
-1.0000 -0.5000 0 0.5000 1.0000

6 Commenti

The above logic executes for every case; use sotoo
yLim=ylim(AX(1));
yDiff=diff(yLim); % don't use diff as variable; it's a builtin
if iswithin(yDiff,0,100)
delt=10;
elseif iswithin(yDiff,100,1000)
delt=100;
elseif iswithin(yDiff,1000,10000)
delt=1000;
elseif iswithin(yDiff,10000,40000)
delt=5000;
else
delt=10000;
end
newYTicks = 0:delt:floor(yLim);
for parsimony. Don't believe that's specifically the problem, however, but I can't reproduce it here w/o full code. It doesn't seem as though the last matches the prior, however, agreed.
I'd also, however, change to
ylim(AX(1),[0 floor(yLim(2))])
set(AX(1),'YTick',newYTicks)
to make the limits consistent with the tick spacing and let the tick labels adjust automagically with the tick values.
You can, if you want the plot to auto-range while building, use
set(AX,'yLimMode','auto')
As a convenience, note that at the command line if you do
axes
set(gca)
you'll get a listing of all axes properties and the current or default values of each to see what there is to piddle with that can be helpful particularly when first learning handle graphics.
Jason
Jason il 19 Feb 2015
Modificato: Jason il 19 Feb 2015
I've decided to auto this with your suggestion:
set(AX,'yLimMode','auto')
This works well, but there are no ticks or values, do I need to also set these, so I tired hard coding the ticks as per your suggestion also. I've done it for both y axes using AX(1) and AX(2).
This has however, raised another issue - the tick marks don't overlap, as observed by the double tick marks seen on the righthand side y-axis.
I really need to ensure the number of grids on the 2nd axis overlaps with the number from first y axis...I think??
Thankyou very much for all your help, I've learned a great technique! Jason
Oh, that's my utility function that is just "syntactic sugar" to replace writing the explicit comparisons...
function flg=iswithin(x,lo,hi)
% returns T for values within range of input
% SYNTAX:
% [log] = iswithin(x,lo,hi)
% returns T for x between lo and hi values, inclusive
flg= (x>=lo) & (x<=hi);
There's another isbetween that is exclusive instead of inclusive and one that has optional parameters to set either bound as [in|ex]clusive as well just for thoroughness.
I've used them so long I tend to forget they're not TMW-supplied.
(Sidebar) They're particular helpful from a clutter-reducing standpoint in cases of returning logical arrays for indexing in selectively computing over ranges; it's much easier to read the function name and grasp the intent that parsing the relation expression so placing it in the lower level away from the higher-level code is a useful abstraction device.
As for the 'Auto' mode, hmmm....I may have to find some additional time to "'spearment"; I didn't think that would prevent/hide the tick values but I've got another commitment at this moment I'm almost late for.
dpb
dpb il 19 Feb 2015
Modificato: dpb il 19 Feb 2015
"...the tick marks don't overlap...need to ensure the number of grids on the 2nd axis overlaps with the number from first y axis...I think??"
Ayup... plotyy goes to a lot of effort to ensure that there are both the same number and "pretty" spacing on the two. Somewhere I've got some sample code (Fortran) that does this; used to be you could see the internal TMW code but they've turned it into a p-file in latest releases instead of the old m-file.
ADDENDUM
I suppose it probably doesn't suit your case building the plots dynamically, but one subterfuge might be if you do know a suitable range for the two axes would be to make an invisible figure with a call to plotyy with only the min/maxes as two points for each axes so it'll do the computations. Then return those ygrid/ylim ranges and delete the figure and set them to yours. Somewhat klunky, but, hey, "any port in a storm"... :)
Jason
Jason il 19 Feb 2015
OK thats very kind of you, please don't this ahead of other work, you have helped a lot already.
dpb
dpb il 19 Feb 2015
Don't worry on that score... :) I'm "retired" from the actual paid consulting gig so commitments are various community things or, when it's time actual farm work as returned to family farm some 15-yr ago, now...

Accedi per commentare.

Categorie

Tag

Richiesto:

il 13 Feb 2015

Modificato:

dpb
il 19 Feb 2015

Community Treasure Hunt

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

Start Hunting!

Translated by