Here is the final callback code::

```
function restore_recent_ROIs(IJ,varargin)
if ~nargin
IJ = ij.IJ;
end
try
aImagePlus = IJ.getImage;
catch
% ĺ¦‚ćžść˛ˇćś‰ĺ›ľç‰‡
return
end
recentRois = evalin('base','recentRois');
nRow = size(recentRois,1);
aNewHit = max(find(~cellfun(@isempty,recentRois(:,1))));
if isempty(aNewHit)
% no record, return
disp(['No ROI available to restore @ ',RMDtime]);
return
else
% recover to last non-empty record
aImagePlus.setRoi(recentRois{aNewHit,1});
disp(['RESTORE an Roi record at nRow = ',num2str(aNewHit),' @ ',RMDtime]);
% update
recentRois{aNewHit,1} = [];
% overwrite base workspace
assignin('base','recentRois',recentRois);
end
end
```

```
function memorize_update_ROIs(aImagePlus)
if ~nargin
IJ = ij.IJ;
aImagePlus = IJ.getImage;
end
aRoi = aImagePlus.getRoi;
if isempty(aRoi)
% just in case aimless click on image get empty roi snapshot
return
end
recentRois = evalin('base','recentRois');
nRow = size(recentRois,1);
aNewHit = max(find(~cellfun(@isempty,recentRois(:,1))));
if isempty(aNewHit)
disp(['Empty Roi got by mouseUp,give up @ ',RMDtime]);
aNewHit = 0;
end
if aNewHit < nRow
% if bottom is not full
recentRois{aNewHit+1,1} = aRoi;
disp(['INSERT an Roi record at nRow = ',num2str(aNewHit+1),' @ ',RMDtime]);
else
% if bottom is full
% move 2:n to 1;n-1,discard first line
recentRois(1:nRow-1,:) = recentRois(2:nRow,:);
% update bottom line
recentRois{nRow,1} = aRoi;
disp(['SWAP an Roi record at nRow = ',num2str(aNewHit),' @ ',RMDtime]);
end
% overwrite base workspace
assignin('base','recentRois',recentRois);
end
```