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:

issue example

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.

  1. create axes (hax_1) function plotted, without datatips
  2. create axes (hax_2) function plotted , datatips without axes labels
  3. set hax_2 visibility 'off' (this plot datatips above first axes labels)
  4. 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

Popular posts from this blog

javascript - Count length of each class -

What design pattern is this code in Javascript? -

hadoop - Restrict secondarynamenode to be installed and run on any other node in the cluster -