matlab - Put datatip stack on top of axis label and update axes label after a change was done on axes position -
this issue unix matlabs, windows users won't able reproduce it.
i having trouble while trying create datatips in on top of y axis label. following picture illustrate issue:
as can see, datatips created close ylabel bottom ylabel text, while desire effect opposite: datatip on top of axis label.
i generated plot following (not minimal) code, available bellow. may remove lines commented % may removed
, or put datatip on −78 instead of loop in order achieve faster testing script, leave code if 1 day wants create custom datatips (in case, consider seeing http://undocumentedmatlab.com/blog/controlling-plot-data-tips/):
gradientstep = 1e-1; x=-100:gradientstep:100; xsize=numel(x); y=x.^3-x.^2; figh=figure(42); lineh=plot(x,y); ylabel('ylabel (yunits)','fontsize',16) xlabel('xlabel (xunits)','fontsize',16) dch=datacursormode(figh); ntips = 20; % may change loop datatip @ x=-78. pos = round(linspace(2,xsize,ntips)) datatiph=dch.createdatatip(lineh,... struct('position',[x(pos) y(pos)])); orientation = 'top-left'; if pos>1 tiptext{1} = 'the grandient here is: '; tiptext{2} = ['\deltax:',sprintf('%d',x(pos)-x(pos-1)),' xunits']; tiptext{3} = ['\deltay:',sprintf('%d',y(pos)-y(pos-1)),' yunits']; else tiptext = 'cannot calculate gradient here.'; end bkgcolor = [1 1 .5]; % may removed. fontsize = 12; % may removed. set(datatiph,'stringfcn',(@(~,~) tiptext),'orientation',... orientation,'backgroundcolor',bkgcolor,'fontsize',... fontsize,'draggable','on'); % set text , orientation needed. datatiptextboxh=get(datatiph,'textboxhandle'); % may removed. uistack(datatiph,'top'); % unfortunately makes no effect, since ylabel handles not @ axes children list datatiptextboxh=get(datatiph,'textboxhandle'); set(datatiptextboxh,'horizontalalignment','left',... 'verticalalignment','top','margin',0.02,'interpreter',... 'tex','fontname','courier','fontsize',fontsize); % may removed. end uistack(get(gca,'ylabel'),'bottom') % makes no effect, same reason.
i have tried:
- uistack datatips top,
- uistack label bottom (both of them don't work because ylabel handle not in axes children handles).
update: after implementing @horchler' solution, new issue appeared: when zooming , panning axes, axes label move. i've found small fix that, changed following aspects:
- set datatip z-value 1, higher ylabel axis z.
- recreating ylabel afterwards pan or zoom movement occurs. this, implemented
localaxisupdate
function old ylabel properties, replace new one, , them reset settable properties ylabel position. used reference
the resulting code follows:
function test gradientstep = 1e-1; x=-100:gradientstep:100; xsize=numel(x); y=x.^3-x.^2; figh=figure(42); lineh=plot(x,y); ylabel('ylabel (yunits)','fontsize',16) xlabel('xlabel (xunits)','fontsize',16) dch=datacursormode(figh); %ntips = 20; %for pos = round(linspace(2,xsize,ntips)) pos = find(x>-78,1); datatiph=dch.createdatatip(lineh,... struct('position',[x(pos) y(pos) 1])); orientation = 'top-left'; if pos>1 tiptext{1} = 'the grandient here is: '; tiptext{2} = ['\deltax:',sprintf('%d',x(pos)-x(pos-1)),' xunits']; tiptext{3} = ['\deltay:',sprintf('%d',y(pos)-y(pos-1)),' yunits']; else tiptext = 'cannot calculate gradient here.'; end bkgcolor = [1 1 .5]; % light yellow fontsize = 12; set(datatiph,'stringfcn',(@(~,~) tiptext),'orientation',... orientation,'backgroundcolor',bkgcolor,'fontsize',... fontsize,'draggable','on'); datatiptextboxh=get(datatiph,'textboxhandle'); datatiptextboxh=get(datatiph,'textboxhandle'); set(datatiptextboxh,'horizontalalignment','left',... 'verticalalignment','top','margin',0.02,'interpreter',... %end % set changes due zoom , pan use adaptativedateticks: set(zoom(figh),'actionpostcallback',... @(~,~) localaxisupdate(gca)); set(pan(figh),'actionpostcallback',... @(~,~) localaxisupdate(gca)); end function localaxisupdate(ah) % fix axis label on top of datatip: ylh = get(ah,'ylabel'); % original ylabel properties ylstruct = get(ylh); % settable fields: yfieldnames=fieldnames(rmfield(set(ylh),'position'))'; % remove old label: delete(ylh) % create new one: ylh = ylabel(ah,'dummy'); % send bottom: ylpos = get(ylh,'position'); set(ylh, 'position', [ylpos(1:2) 0]); % reset new ylabel old values: field=yfieldnames field = field{1}; set(ylh,field,ylstruct.(field)); end end
this approach creates unwanted effect, ylabel move across figure until mouse button released. how can remove unwanted effect ?
i think solution may more or less done in undocummented matlab solution updating axes ticks, need listener ylabel postset property. knows how that? if windows user, can try help, all need reset position of ylabel after change (pan, zoom or whatever) made on figure.
a workaround uses both linkaxes, useful when zooming/panning multiple plots, , visibilty of plots.
- create axes (hax_1) function plotted, without datatips
- create axes (hax_2) function plotted , datatips without axes labels
- set hax_2 visibility 'off' (this plot datatips above first axes labels)
- link 2 axes linkaxes([hax_1 hax_2],'xy'); (zooming , panning on 1 of axes modify on fly second axes)
this gives first code (not edited one):
gradientstep = 1e-1; x=-100:gradientstep:100; xsize=numel(x); y=x.^3-x.^2; figh=figure(42); plot(x,y); ylabel('ylabel (yunits)','fontsize',16) xlabel('xlabel (xunits)','fontsize',16) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % modification starts hax_1 = gca; hax_2 = axes('position', get(hax_1,'position')); lineh = plot(x,y); linkaxes([hax_1 hax_2],'xy'); set(hax_2,'visible', 'off'); % modification ends %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% dch=datacursormode(figh); ntips = 20; % may change loop datatip @ x=-78. pos = round(linspace(2,xsize,ntips)) datatiph=dch.createdatatip(lineh,struct('position',[x(pos) y(pos)])); orientation = 'top-left'; if pos>1 tiptext{1} = 'the grandient here is: '; tiptext{2} = ['\deltax:',sprintf('%d',x(pos)-x(pos-1)),' xunits']; tiptext{3} = ['\deltay:',sprintf('%d',y(pos)-y(pos-1)),' yunits']; else tiptext = 'cannot calculate gradient here.'; end bkgcolor = [1 1 .5]; % may removed. fontsize = 12; % may removed. set(datatiph,'stringfcn',(@(~,~) tiptext),'orientation',orientation,'backgroundcolor',bkgcolor,'fontsize',fontsize,'draggable','on'); % set text , orientation needed. datatiptextboxh=get(datatiph,'textboxhandle'); set(datatiptextboxh,'horizontalalignment','left','verticalalignment','top','margin',0.02,'interpreter','tex','fontname','courier','fontsize',fontsize); % may removed. end
i on osx 10.8.4, r2012b, , had same issue yours. here, proposed solution plots datatips above axis labels , allow zooming/panning without making use of undocumented features of matlab.
Comments
Post a Comment