Most efficient way to distinguish handle parents in an array of handle graphics objects

All, here's what I'm trying to do:
% Preallocate array of handle graphics objects, H, then add various object handles ...
H = gobjects(1,13); % Preallocate array of handle graphics objects
f1 = figure;
H(1) = subplot(2,2,1);
x = linspace(-2*pi,2*pi);
p = plot(x,cos(x),x,sin(x));
l = legend('Plot1','Plot2');
H(2) = subplot(2,2,[2,4]);
s = surf(peaks);
t = title('Yo, this is my title');
H(3) = (2,2,3);
f2 = figure;
H(4) = subplot(2,2,1);
H(5) = subplot(2,2,[2,4]);
H(6) = subplot(2,2,3);
H(7) = f1;
H(8) = f2;
H(9) = l;
H(10) = t;
H(11) = p(1);
H(12) = p(2);
H(13) = s;
As you can see, H may include all sorts of objects: figures, axes, lines, surfs, titles, legends, whatever.
So, to isolate just those objects with a 'Position' property, I do the following:
% Reduce H to eliminate both lines and single surf, then find parent objects:
H = H(isprop(H,'Position'));
H_Parents = get(H,'Parent');
Now, H and H_Parents should return something like the following:
H should give a 1x10 graphics array:
[Axes Axes Axes Axes Axes Axes Figure Figure Legend Text]
H_Parents should give a 10x1 cell array:
[Figure]
[Figure]
[Figure]
[Figure]
[Figure]
[Figure]
[Root]
[Root]
[Figure]
[Axes]
As you can see, the first "6" figures are the parents of the 6 subplots, which are just f1 and f2.
Here's my problem ... I can't seem to find an efficient way of distinguishing, for example, the parent of subplot 1 (i.e., f1) from the parent of subplot 4 (i.e, f2) from any other parent in a generalized way. My ideal solution would look something like this:
[1 1 1 2 2 2 3 3 1 4]
... because ...
... the parents of the first 3 subplots are all f1, so: [1 1 1 ...
... the parents of the next 3 subplots are all f2, so: 2 2 2 ...
... the parents of f1 and f2 are all 'root', so a third parent category is needed: 3 3 ...
... the parent of the legend, l, is f1, which is just category 1 again: 1 ...
... and the parent of the title, t, is subplot 2, which requires a 4th category, so: 4].
I hope my question is clear. My goal is to have an unambiguous identifier for each common parent amongst all of my handle graphics objects. Any help is appreciated.
Thanks in advance, Justin :)

 Accepted Answer

ancestor(TheHandle, 'figure')

5 Comments

Thanks for the speedy reply, Walter! I'll have to try out your suggestion tomorrow, but stay tuned for an update and I'll let you know if I have any luck. Until tomorrow, Justin :)
Hi, Walter :) It seems the ancestor approach left me in a spot similar to where the get() function left me with H_Parents. In a way, I found ancestor() to be a bit more restrictive, because I had to search for a specific type of object when the original handle graphics objects array, H, was comprised of objects of various types having many different parents. Thus, I'd have to call ancestor() with a cell array of prescribed types, and I didn't want to have a non-general prescription and run the risk of identifying for some object in H a non-immediate ancestor (i.e., I want the direct parent each and everytime, no exceptions.)
To this end, I will say: it would be most convenient for the ancestor function to have some sort of '-direct' flag that could be specified to give the immediate ancestor (i.e., parent) of each object in the handle graphics objects array. If this already exists and I'm unaware, please let me know.
I appreciate your response! :)
Go back to the H_Parents you computed by get() of the Parent property, and use
[unique_parents, ~, parent_idx] = unique(H_Parents);
then unique_parents will be the different parents once each, and parent_idx will be the index such that H_Parents(parent_idx(K)) = unique_parents(K) -- so for each original H_Parents it tells you which of the unique_parents it belonged to.
Thanks, again, Walter :) Let me review this response tomorrow, then I'll come back here and accept your answer. Adieu!
Walter, I checked out your suggestion, and it's great :) I should point out one small correction ... to get this to work, I had to start from my addendum's H_Parents_Arr (see addendum reply below) vice the H_Parents as you show. Thus, the code appears as follows:
H_Parent_Arr = [H_Parent{:}]';
[Unique_Parents,~,Parent_Idx] = unique(H_Parent_Arr)
Thanks again, worked like a charm!

Sign in to comment.

More Answers (1)

I suppose my title should have been, "How to best subdivide an array of handle graphics objects into groups based on common parents," or something to this effect. Because I think I found a more ideal solution than the one I requested above.
Starting from H_Parents above:
% Convert cell array 'H_Parent' to an object array:
H_Parent_Arr = [H_Parent{:}]';
% Check equality of each object in 'H_Parent_Arr' with all other objects in 'H_Parent_Arr':
E = arrayfun(@(x) eq(x,H_Parent_Arr),H_Parent_Arr,'UniformOutput',false);
% Convert cell array 'E' to a logical array, then eliminate all non-unique rows of the logical array while preserving row order:
E = unique([E{:}],'rows','stable');
% Create cell array of original objects, grouped by common parent:
G = cell(size(E,1),1);
for ii = 1 : length(G)
G{ii} = H(E(ii,:)');
end
What do y'all think? Is there a better way to do this?

1 Comment

Incidentally, if you did want to achieve the first 'ideal' solution I requested, you could do something like this (in place of the G = cell(...) and for loop block of code above):
I = repmat((1:size(E,1))',1,size(E,2));
G_orig_ideal = I(E);

Sign in to comment.

Categories

Find more on Creating, Deleting, and Querying Graphics Objects in Help Center and File Exchange

Products

Asked:

jH@
on 7 Jul 2016

Edited:

jH@
on 16 Jul 2016

Community Treasure Hunt

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

Start Hunting!