Search code examples
matlabuser-interfaceplotstorebrush

Matlab: Selected data (through brushing) in GUI plot is not being stored


I am plotting these two curves on an axes:

LH(1) = copyobj(T2pb1hLine(2), S.T2pb1Ax(2)); 
LH(2) = copyobj(T2pb1hLine(2), S.T2pb1Ax(2)); 
set(LH(1), 'XData', PressNoOutliers, 'YData', zNoOutliers, 'linestyle',...
            'x', 'Color', 'm');
set(LH(2), 'XData', PressNoOutliers2, 'YData', zNoOutliers2, 'linestyle',...
            's', 'Color', 'b');

Then I am using this callback function to brush the data and store it:

brush on
pause
hBrushLine = findall(S.T2pb1Ax(2), 'tag', 'Brushing');
brushedData = get(hBrushLine, {'Xdata', 'Ydata'});
brushedIdx = ~isnan(brushedData{1});
PSel = brushedData{1}(brushedIdx);
zSel = brushedData{2}(brushedIdx);

I am able to brush the data, however, the data is not being stored which results in empty vectors for PSel and zSel. Apparently, if I were not using copyobj and plotting only single curve then I am able to get the data by brushing for PSel and zSel. Any guesses what can I do to store the data while I am using copyobj to plot the 2 curves together?


Solution

  • Here's what happens:
    Depending on the number of lines in your plot, brushedData will exceed the currently hard-wired size of 1 in your code. So unless you brush data from the first line, Psel and zSel will be empty, because brushedData{1} will only contain NaN - and the data you meant to select was in brushedData{n} (corresponding to the n-th line), but never got processed. Here's a little example (you will have to adjust the gca and such handles, but the logic becomes clear):

    x1 = linspace(1,10,21);
    y1 = rand(1,21);
    
    x2 = x1;
    y2 = rand(1,21);
    
    x3 = x2;
    y3 = rand(1,21);
    
    h(1) = plot(x1,y1,'b');
    
    h(2) = copyobj(h(1),gca); 
    h(3) = copyobj(h(1),gca); 
    
    set(h(2),'XData',x2,'YData',y2,'Color','r')
    set(h(3),'XData',x3,'YData',y3,'Color','g')
    
    brush on
    pause
    hBrushLine = findall(gca, 'tag', 'Brushing');
    brushedData = get(hBrushLine, {'Xdata', 'Ydata'});
    
    for I=1:size(brushedData,1)
        brushedIdx = ~isnan(brushedData{I,1});
        PSel{I} = brushedData{I,1}(brushedIdx);
        zSel{I} = brushedData{I,2}(brushedIdx);
    end
    

    Depending on which line you choose your data from, some cells in Psel and zSel turn up empty. I chose to go with cells, because it allows you to select a different amount of points from different lines.