Clear Filters
Clear Filters

Reloading handle objects from .mat files

3 views (last 30 days)
Matt J
Matt J on 26 May 2023
Edited: Matt J on 31 May 2023
Why does isequal() return false when the reloaded handle is compared to the original handle, in the code below.
h=plot(1:5);
save tst h
h2=load('tst').h;
isequal(h,h2)
ans = logical
0

Accepted Answer

Paul
Paul on 27 May 2023
Hi Matt,
It looks like two of the properties are changed, either on the save or on the load.
h=plot(1:5);
save tst h
h2=load('tst').h;
isequal(h,h2)
ans = logical
0
p = properties(h);
for ii = 1:numel(p)
if ~isequal(h.(p{ii}),h2.(p{ii}))
p{ii}
h.(p{ii})
h2.(p{ii})
disp(' ')
end
end
ans = 'Parent'
ans =
Axes with properties: XLim: [1 5] YLim: [1 5] XScale: 'linear' YScale: 'linear' GridLineStyle: '-' Position: [0.1300 0.1100 0.7750 0.8150] Units: 'normalized' Show all properties
ans =
0×0 empty GraphicsPlaceholder array.
ans = 'DataTipTemplate'
ans =
DataTipTemplate with properties: DataTipRows: [2×1 matlab.graphics.datatip.DataTipTextRow] Interpreter: 'tex' FontSize: 10 FontAngle: 'normal' FontName: 'Helvetica'
ans =
DataTipTemplate with properties: DataTipRows: [2×1 matlab.graphics.datatip.DataTipTextRow] Interpreter: 'tex' FontSize: 10 FontAngle: 'normal' FontName: 'Helvetica'
I guess it makes sense for the Parent property to not be saved because it might not be in existence on the reload?
Not sure what's not isequal between the DataTipTemplates. Didn't drill down into DataTipRows

More Answers (1)

Walter Roberson
Walter Roberson on 26 May 2023
f1 = figure(1);
ax1 = axes('Parent', f1);
h1 = plot(ax1, 1:10);
save tst f1
h1.YData(end) = 5
h1 =
Line with properties: Color: [0 0.4470 0.7410] LineStyle: '-' LineWidth: 0.5000 Marker: 'none' MarkerSize: 6 MarkerFaceColor: 'none' XData: [1 2 3 4 5 6 7 8 9 10] YData: [1 2 3 4 5 6 7 8 9 5] Show all properties
datastruct = load('tst');
f2 = datastruct.f1;
isequal(f1, f2)
ans = logical
0
f1.Number
ans = 1
f2.Number
ans = 2
double(f1)
ans = 1
double(f2)
ans = 2
f1.Children(1).Children(1).YData
ans = 1×10
1 2 3 4 5 6 7 8 9 5
f2.Children(1).Children(1).YData
ans = 1×10
1 2 3 4 5 6 7 8 9 10
Now, under your hypothesis, f1 (the live figure handle) should isequal() f2 (the retrieved saved version of the figure handle). But if they are isequal() then how would you account for the fact that the YData for the two needs to be different, since the plot for f1 was modified after it was saved? Should the retrieved copy have been updated to reflect the changes to f1, or should the active f1 have been regressed to reverse the changes so as to match the restored figure handle?
Or is it your position that when we modified the YData underneath the first figure, that the handle f1 should itself have changed?
  5 Comments
Walter Roberson
Walter Roberson on 28 May 2023
When handle objects are created, are they created with a UUID / GUID ? https://en.wikipedia.org/wiki/Universally_unique_identifier
Suppose I create a figure and axes and h = plot(), and save("tst1.mat","h"); and loop from iteration = 2 to something big
h.YData = rand(1,1);
save("tst"+iteration+".mat", "h");
but first, before changing YData, every once in a while,
if rand() < 0.01
idx_to_restore = randi(iteration, 1, 1);
h2 = load("tst" + idx_to_restore + "mat", "h").h;
idx_to_restore = randi(iteration, 1, 1);
h3 = load("tst" + idx_to_restore + "mat", "h").h;
end
What is the identity that should be associated with h2 and h3? h still exists but with modified value.
Should h become a different handle (different identity) every time its YData is modified? That would be inconsistent with the idea that once you get a handle that it always refers to the current version of the object. If you pass in h to a function that modifies h.MarkerSize and then ask isequal(evalin('caller','h'), h) then the two must be equal even though you did not modify the caller's version of h explicitly. Because handles are effectively pointers, and the pointer stays the same even when the properties pointed to are modified: this is inherent in what handles are
So the handle (pointer) associated with h is not changing as you modify the properties of h.
When you restore h2, then "should" h2 have the same pointer as h? Even though h2 probably has different properties than h ?
When you restore h3, then "should" h3 have the same pointer as h2? Even though h3 probably has different properties than h2 ?
Under hg1 and still under hg2, there is a mapping between handles and double. Even now, double(h) will produce a double precision number that you can set() the properties of, or handle() to get back a handle object. If a loop similar to the above were left to run long enough, on a large enough file system, eventually the same double precision number would end up getting used again for something that "should" be a different handle. If we load() back something that had the same double precision number as an existing handle, "should" it conflict with the existing handle with that double precision number? But that's easy enough to manufacturer:
fig = figure(1);
fig1 = handle(1);
isequal(fig, fig1)
ans =
logical
1
so all figure(1) have the same double precision number as their handle, namely the double precision number 1.0 . If we save two different figure 1 to different files, and load() both of them back in, then should they conflict with each other since they have the same handle?
Or should handle identity only be preserved for objects that do not "contain" other objects? Which is why I pointed out earlier that line() objects contain a series of other object types: line() objects are containers in the object sense just as much as figures are containers in the object sense.
Or... so this be resolved by having handles be associated with UUID / GUID, so that it is the UUID that is recorded in the save file rather than the double precision handle? So that no matter how many times we mix and match storing and retrieving two copies of the same handle, when we eventually load both of them together, that they will compare equal because it would have matched the (hypothetical) UUID ?
Matt J
Matt J on 31 May 2023
Edited: Matt J on 31 May 2023
Which of the following is the mechanism you envision:
I don't have a vision. It was more of a question of what exactly is changing. It certainly isn't observed with general handle objects e.g.,
obj=myclass;
save tst obj
obj2=load('tst').obj;
isa(obj,'handle')
ans = logical
1
isa(obj2,'handle')
ans = logical
1
isequal(obj,obj2)
ans = logical
1

Sign in to comment.

Tags

Products


Release

R2021b

Community Treasure Hunt

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

Start Hunting!