bugGNU Octave - Bugs: bug #39767, findobj sorts list of returned...

 
 

bug #39767: findobj sorts list of returned handles

Submitter:  Ben Abbott <bpabbott>
Submitted:  Mon 12 Aug 2013 11:57:59 AM UTC
   
 
Category:  Plotting Severity:  3 - Normal
Priority:  5 - Normal Item Group:  Matlab Compatibility
Status:  Fixed Assigned to:  None
Originator Name:  Ben Abbott Open/Closed:  * Closed
Release:  * dev Operating System:  * Any
Fixed Release:  None Planned Release:  None
* Mandatory Fields

Add a New Comment Rich Markup
   

Jump to the original submission

Tue 13 Aug 2013 11:39:45 PM UTC, comment #14: 

I checked in a changeset that doesn't use union() and therefore returns the same ordering of objects as Matlab (http://hg.savannah.gnu.org/hgweb/octave/rev/3fd617363762).  I moved the test about the ordering of axis handles from graphics.cc to findobj.m.

Rik <rik5>
Group administrator
Tue 13 Aug 2013 09:55:12 PM UTC, comment #13: 

Rik,

What code are you suggesting be removed from graphics.cc?

Ben Abbott <bpabbott>
Group Member
Tue 13 Aug 2013 09:54:05 PM UTC, comment #12: 

Without all of Matlab's uimenu/toolbar, etc


h = findobj (hfig)

h =

    1.0000
  175.0068
  173.0068
  176.0073
  174.0073

get (h, 'type')

ans =

    'figure'
    'axes'
    'axes'
    'line'
    'line'


Ben Abbott <bpabbott>
Group Member
Tue 13 Aug 2013 09:39:14 PM UTC, comment #11: 


>> hfig = figure (1);
>> hax1 = subplot (2,1,1); hp1 = plot (rand (10,1));
>> hax2 = subplot (2,1,2); hp2 = plot (rand (10,1));
>> findall (hfig)


ans =

    1.0000
  172.0011
  170.0012
  144.0011
  132.0011
  131.0011
   80.0011
   64.0011
   57.0011
   37.0011
   18.0011
    0.0011
  173.0016
  171.0016
  169.0011
  168.0011
  167.0011
  166.0011
  165.0011
  164.0011
  163.0011
  149.0011
  148.0011
  147.0011
  146.0011
  145.0011
  143.0011
  142.0011
  141.0011
  140.0011
  139.0011
  138.0011
  137.0011
  136.0011
  135.0011
  134.0011
  133.0011
  130.0011
  129.0011
  120.0011
  111.0011
  104.0011
  103.0011
  102.0011
  101.0011
  100.0011
   99.0011
   90.0011
   89.0011
   88.0011
   87.0011
   86.0011
   85.0011
   84.0011
   83.0011
   82.0011
   81.0011
   79.0011
   78.0011
   77.0011
   76.0011
   75.0011
   74.0011
   73.0011
   72.0011
   71.0011
   70.0011
   69.0011
   68.0011
   67.0011
   66.0011
   65.0011
   63.0011
   62.0011
   61.0011
   60.0011
   59.0011
   58.0011
   56.0011
   55.0011
   54.0011
   53.0011
   52.0011
   51.0011
   50.0011
   49.0011
   48.0011
   47.0011
   46.0011
   45.0011
   44.0011
   43.0011
   42.0011
   41.0011
   40.0011
   39.0011
   38.0011
   36.0011
   35.0011
   34.0011
   33.0011
   32.0011
   31.0011
   30.0011
   29.0011
   28.0011
   27.0011
   26.0011
   25.0011
   19.0011
   17.0011
   16.0011
   15.0011
   14.0011
   13.0011
   11.0011
   10.0011
    9.0011
    8.0011
    7.0011
    6.0011
    5.0011
    4.0011
    3.0011
    2.0011
    1.0011
  162.0011
  161.0011
  160.0011
  159.0011
  158.0011
  157.0011
  156.0011
  155.0011
  154.0011
  153.0011
  152.0011
  151.0011
  150.0011
  128.0011
  127.0011
  126.0011
  125.0011
  124.0011
  121.0011
  119.0011
  118.0011
  117.0011
  116.0011
  115.0011
  114.0011
  113.0011
  112.0011
  110.0011
  109.0011
  108.0011
  107.0011
  106.0011
  105.0011
   98.0011
   97.0011
   96.0011
   95.0011
   94.0011
   93.0011
   92.0011
   91.0011
   24.0011
   23.0011
   22.0011
   21.0011
   20.0011
   12.0011
  123.0011
  122.0011

>> version


ans =

7.9.0.529 (R2009b)


Michael Godfrey <godfrey>
Group Member
Tue 13 Aug 2013 09:24:24 PM UTC, comment #10: 

Seems like this should be fixed.  The test for correct ordering can then be moved out of graphics.cc and over to findobj.m.  What is the order of return for Matlab?


hfig = figure (1);
hax1 = subplot (2,1,1); hp1 = plot (rand (10,1));
hax2 = subplot (2,1,2); hp2 = plot (rand (10,1));
findall (hfig)


Is the grouping flat at each level as shown below?

hfig
hax2
hax1
hp2
hp1

or does it intersperse the children like so?

hfig
hax2
hp2
hax1
hp1



Rik <rik5>
Group administrator
Tue 13 Aug 2013 08:07:06 PM UTC, comment #9: 

Rik,

My apologies, I think I've been confusing myself.

I have a simple example which indicates the difference between Octave and Matlab (same conclusion as you) First Matlab,


subplot (2,1,1)
subplot (2,1,2)
findobj (gcf, 'type', 'axes')

ans =

  175.0024
  173.0024

get (gcf, 'children')

ans =

  175.0024
  173.0024


And now Octave


clf
subplot (2,1,1)
subplot (2,1,2)
findobj (gcf, 'type', 'axes')
ans =

  -12.48546
   -7.29506

get (gcf, 'children')
ans =

   -7.29506
  -12.48546


Your observation that the problem is with findobj() looks correct to me.  Should that be fixed?


diff --git a/scripts/plot/findobj.m b/scripts/plot/findobj.m
--- a/scripts/plot/findobj.m
+++ b/scripts/plot/findobj.m
@@ -196,12 +196,16 @@
   idepth = 0;
   h = handles;
   while (numel (handles) && ! (idepth >= depth))
-    children = [];
+    children = []
     for n = 1 : numel (handles)
-      children = union (children, get (handles(n), "children"));
+      newkids = get (handles(n), "children");
+      [~, n1, n2] = union (children, newkids);
+      children = [children(sort(n1,'descend')); newkids(sort(n2,'descend'))];
     endfor
     handles = children;
     h = union (h, children);
+    [~, n1, n2] = union (h, children);
+    h = [h(sort(n1,'descend')); children(sort(n2,'descend'))];
     idepth = idepth + 1;
   endwhile
-verbatim_

Ben Abbott <bpabbott>
Group Member
Tue 13 Aug 2013 07:32:35 PM UTC, comment #8: 

Ben,

I extracted the failing test and put it in its own m-file, tst_findall.m, which is attached.  Now you can run


test tst_findall
test tst_findall


The first time it will pass.  And it will fail on all subsequent times.  The problem is in the findall call.  It does not return the objects in the same order as they are in the figure.  There is a keybard() call I used to debug the test.  If you uncomment it and then run the failing test I get.


test tst_findall
stopped in __test__ at line 10
debug> get (gcf, 'children')
ans =

   -6.13765
  -12.80879

debug> hax
hax =

  -12.80879
   -6.13765


First, we should just be able to run findobj() here.  Second, there is something in findobj.  I suspect it is the call to union().


while (numel (handles) && ! (idepth >= depth))
  children = [];
  for n = 1 : numel (handles)
    children = union (children, get (handles(n), "children"));
  endfor
  handles = children;
  h = union (h, children);
  idepth = idepth + 1;
endwhile


union is for set objects which have no ordering, only membership.  It would be better to use ordinary concatenation.  get() will always return column vectors so this isn't a problem.  I changed findobj() to


while (numel (handles) && ! (idepth >= depth))
   children = [];
   for n = 1 : numel (handles)
     children = [children; get(handles(n), "children")];
   endfor
   handles = children;
   h = [h; children];
   idepth = idepth + 1;
endwhile


And the test passes now.

Rik <rik5>
Group administrator
Tue 13 Aug 2013 07:13:32 PM UTC, comment #7: 

position(1,:) is for hax(1) which corresponds to the last axes created -> subplot (2, 1, 2))




Ben Abbott <bpabbott>
Group Member
Tue 13 Aug 2013 06:19:59 PM UTC, comment #6: 

I think the assert statement is wrong.


assert (positions(1,2) > positions(2,2))


The first axes in the list is positioned towards the bottom of the canvas.  Therefore, it's Y value should be smaller, not larger, than the second axes.  If I flip the comparison around


assert (positions(1,2) < positions(2,2))


then the test passes on the first time and now fails repeatably every time after that.  There is still a problem in that axes are ordered incorrectly on all subsequent tests.

Rik <rik5>
Group administrator
Tue 13 Aug 2013 05:37:13 PM UTC, comment #5: 

Ok.  I may have misunderstood what is happening. Running the script below from a file,


subplot(2,1,1); plot(rand(10,1)); subplot(2,1,2); plot(rand(10,1));
hax = findall (gcf (), 'type', 'axes');
positions1 = cell2mat (get (hax, 'position'))
subplot(2,1,1); plot(rand(10,1)); subplot(2,1,2); plot(rand(10,1));
hax = findall (gcf (), 'type', 'axes');
positions2 = cell2mat (get (hax, 'position'))


Matlab gives


positions1 =

    0.1300    0.1100    0.7750    0.3412
    0.1300    0.5838    0.7750    0.3412

positions2 =

    0.1300    0.1100    0.7750    0.3412
    0.1300    0.5838    0.7750    0.3412


and Octave gives


positions1 =

   0.13000   0.12384   0.77500   0.32733
   0.13000   0.58384   0.77500   0.32733

positions2 =

   0.13000   0.12384   0.77500   0.32733
   0.13000   0.58384   0.77500   0.32733


After restarting Octave, the similar test in graphics.cc fails for me.


test graphics.cc
  ***** xtest
 ## Doubling up on subplots results in axes out of order
 hf = figure ("visible", "off");
 graphics_toolkit (hf, "fltk");
 unwind_protect
   subplot(2,1,1); plot(rand(10,1)); subplot(2,1,2); plot(rand(10,1));
   subplot(2,1,1); plot(rand(10,1)); subplot(2,1,2); plot(rand(10,1));
   hax = findall (gcf (), "type", "axes");
   positions = cell2mat (get (hax, "position"));
   assert (positions(1,2) > positions(2,2))
 unwind_protect_cleanup
   close (hf);
 end_unwind_protect
!!!!! known failure
assert (positions (1, 2) > positions (2, 2)) failed
PASSES 22 out of 22 tests (1 expected failure)


However, if I run the test a second time, it passes.


test graphics
PASSES 22 out of 22 tests



Ben Abbott <bpabbott>
Group Member
Tue 13 Aug 2013 05:17:32 PM UTC, comment #4: 

I'm in violent agreement with you.  kids(1) should be the last axes created and it is the last axes created according to


set (kids(1), 'color', 'g');


The %!test you wrote shows that the position value for axes 1 is being assigned to axes 2 and vice versa, but it doesn't seem to show an incorrect ordering of axes.


Rik <rik5>
Group administrator
Tue 13 Aug 2013 04:39:07 PM UTC, comment #3: 

kids(1) should always be the last axes created.

When the graphics.cc test fails, the results indicate that the axes are not ordered correctly.

Ben Abbott <bpabbott>
Group Member
Tue 13 Aug 2013 04:22:05 PM UTC, comment #2: 

What is the behavior, i.e. Matlab, that we are looking for?

When I execute


subplot(2,1,1); plot(rand(10,1)); subplot(2,1,2); plot(rand(10,1));
kids = get (gcf, 'children');
set (kids(1), 'color', 'g');
subplot(2,1,1); plot(rand(10,1)); subplot(2,1,2); plot(rand(10,1));
kids = get (gcf, 'children');
set (kids(1), 'color', 'g');


The bottom subplot, the last one plotted, turns green.  This is what I would expect as it was the last plot done so its axes appears first, i.e., on top in the list of children.

Rik <rik5>
Group administrator
Mon 12 Aug 2013 10:11:14 PM UTC, comment #1: 
Ben Abbott <bpabbott>
Group Member
Mon 12 Aug 2013 11:57:59 AM UTC, original submission:  

I'm seeing a failure the first time tests are run on graphics.cc


>> test graphics.cc
  ***** test
 hf = figure ("visible", "off");
 graphics_toolkit (hf, "fltk");
 unwind_protect
   subplot(2,1,1); plot(rand(10,1)); subplot(2,1,2); plot(rand(10,1));
   hax = findall (gcf (), "type", "axes");
   positions = cell2mat (get (hax, "position"));
   outerpositions = cell2mat (get (hax, "outerposition"));
   looseinsets = cell2mat (get (hax, "looseinset"));
   tightinsets = cell2mat (get (hax, "tightinset"));
   subplot(2,1,1); plot(rand(10,1)); subplot(2,1,2); plot(rand(10,1));
   hax = findall (gcf (), "type", "axes");
   assert (cell2mat (get (hax, "position")), positions, 1e-4);
   assert (cell2mat (get (hax, "outerposition")), outerpositions, 1e-4);
   assert (cell2mat (get (hax, "looseinset")), looseinsets, 1e-4);
   assert (cell2mat (get (hax, "tightinset")), tightinsets, 1e-4);
 unwind_protect_cleanup
   close (hf);
 end_unwind_protect
!!!!! test failed
assert (cell2mat (get (hax, "position")),positions,1e-4) expected
   0.13000   0.58384   0.77500   0.32733
   0.13000   0.12384   0.77500   0.32733
but got
   0.13000   0.12384   0.77500   0.32733
   0.13000   0.58384   0.77500   0.32733
maximum absolute error 0.46 exceeds tolerance 0.0001


The test fails due to the axes objects being in the wrong order. Subsequently, all tests pass.


test graphics.cc
PASSES 19 out of 19 tests


Ben Abbott <bpabbott>
Group Member

 

(Note: upload size limit is set to 16384 kB, after insertion of the required escape characters.)

Attach Files:
   
   
Comment:
   

No files currently attached

 

Depends on the following items: None found

Items that depend on this one: None found

 

Carbon-Copy List
  • -email is unavailable- added by godfrey (Posted a comment)
  • -email is unavailable- added by rik5 (Posted a comment)
  • -email is unavailable- added by bpabbott (Submitted the item)
  •  

    There are 0 votes so far. Votes easily highlight which items people would like to see resolved in priority, independently of the priority of the item set by tracker managers.

    Only group members can vote.

     

    Follow 4 latest changes.

    Date Changed by Updated Field Previous Value => Replaced by
    2013-08-13 rik5 Item GroupInaccurate Result Matlab Compatibility
        StatusNone Fixed
        Open/ClosedOpen Closed
    2013-08-13 rik5 Summaryinitial axes are not ordered properly findobj sorts list of returned handles

    Back to the top

    Powered by Savane 3.13-02a9.
    Corresponding source code