Interactive brushing across multiple scatter-plots on the same dataset (data relation given not by a common x-axis but just by the dataset)

12 views (last 30 days)
Assume a dataset e.g. of 100 electric devices with each of them having 4 properties stored in an 4x100-array d. The following code below creates some instructive sample data for this.
Now I want to plot the graphical relation of the first two properties as a scatter plot and the graphical relation of the last two properties as a second scatter plot (the two subplots in the code and in the example picture).
In data analysis one is often interested in a certain location of the samples – e.g. the upper right brushed samples in the left d1-d2-subplot. Often one wants to know, in which location the same samples occur in the related d3-d4-data-range (in the right subplot).
The following code realizes this - but only semiautomated and not very flexible. In many data-evaluation programs such functionality is a standard feature, and it is applied by data-analysts and device engineers in daily routine.
clear all, clc
rng(1) % ensure same points created during debugging
% just some visually instructive, artificial sample data
% elliptic shapes with some random scattering
numPts = 100; phiOffs = pi/3; randAmp = 0.35;
phiRand = linspace(0,2*pi, numPts);
d(1,:) = cos(phiRand-2*phiOffs) + randAmp*rand(1,numPts);
d(2,:) = sin(phiRand) + randAmp*rand(1,numPts);
d(3,:) = 1.5*cos(phiRand-phiOffs) + randAmp/2*rand(1,numPts);
d(4,:) = -0.5*sin(phiRand) + randAmp/2*rand(1,numPts);
figure(1), clf
subplot(1,2,1), scatter(d(1,:), d(2,:))
xlabel('d1'), ylabel('d2')
subplot(1,2,2), scatter(d(3,:), d(4,:))
xlabel('d3'), ylabel('d4')
% in the next code line (keyboard) the program might be interrupted
% to brush some 'interesting' d1-d2-data in the left subplot(1,2,1)
% ==> export it as brushedData to base-workspace
keyboard
% this extracts the d3-d4-coordinates (rows [3,4] of full set d)
% corresponding to the brushed d1-d2-points the left subplot (rows [1,2])
d1d2_All = d([1,2],:)';
[~, Locb] = ismember(brushedData, d1d2_All, 'rows');
d3d4_2b_brushed = d([3,4], Locb);
% now overlay the result the right d3-d4-subplot as red symbols to see where they are located
subplot(1,2,2), hold on
scatter(d3d4_2b_brushed(1,:), d3d4_2b_brushed(2,:), 'red')
I guess a similar functionality might be also available in Mathlab to analyze data in multiple plots, that derives from the same dataset as in my example.
I know how to realize it with by exploiting GUI (GUIDE)-programming and its event-functionality – but if I try it the outcome will again be something very specific.
Can anyone please help me with a hint how to realize this with, e.g. with build in functionality of plot-figures and according low coding effort and greater generality.

Accepted Answer

Andreas Apostolatos
Andreas Apostolatos on 20 Dec 2021
Hello,
You can use the following code snippet for your needs,
%% Just some viusally instructive, artificial sample data
numPts = 100;
phiRand = linspace(0,2*pi, numPts);
phiOffs = pi/3;
randAmp = 0.35;
d(1,:) = cos(phiRand) + randAmp*rand(1,numPts);
d(2,:) = sin(phiRand) + randAmp*rand(1,numPts);
d(3,:) = 1.5*cos(phiRand-phiOffs) + randAmp/2*rand(1,numPts);
d(4,:) = -0.5*sin(phiRand) + randAmp/2*rand(1,numPts);
h1 = scatter(d(1,:), d(2,:));
xlabel('d1')
ylabel('d2')
f2 = figure(2);
h2 = scatter(d(3,:), d(4,:));
gch2 = gcf;
xlabel('d3')
ylabel('d4')
%% Customization of the Brush-Option for the first figure
% Get the handle of the Brush-property of the first figure
brush1 = brush(h1);
% Define the Callback function 'ActionPostCallback' of the
% Brush-functionality of the first figure by means of a wrapper that
% receives both handles of the two scatter plots and the handle to the
% second figure in addition
set(brush1, 'ActionPostCallback', @(ohf, s) myCallbackBrush(ohf, s, h1, h2, f2), ...
'enable', 'on')
%% Customized 'ActionPostCallback' callback function
function myCallbackBrush(ohf, s, h1, h2, f2)
% Get the IDs of the points that are brushed in the first figure
idBrush = get(h1, 'BrushData');
% Bring the second figure to the foreground
ax2 = get(f2, 'CurrentAxes');
% Highlight the selected points in the second figure
figure(f2)
hold on;
scatter(ax2, h2.XData, h2.YData, 'MarkerEdgeColor', [0, 0.4470, 0.7410]);
scatter(h2.XData(find(idBrush)), h2.YData(find(idBrush)), 'ro');
hold off;
% Show the coordinates of the brushed points on both figures
disp("Fig. 1: ")
disp([h1.XData(find(idBrush))' h1.YData(find(idBrush))'])
disp(" ")
disp("Fig. 2: ")
disp([h2.XData(find(idBrush))' h2.YData(find(idBrush))'])
end
More information about the latter callback function you can find in the following documentation page,
Kind regards,
Andreas
  1 Comment
Jürgen
Jürgen on 20 Dec 2021
Very clear and convenient solution – very useful for me.
Especially it is solved within Matlab standard-workflow and does not need invoke additional complexity (e.g. solve it in callbacks of GUI/GUIDE framework).
It allows me/us to introduce it in our standard-workflow and it is extendible to may related analysis problems.

Sign in to comment.

More Answers (0)

Categories

Find more on Graphics Performance in Help Center and File Exchange

Products


Release

R2021b

Community Treasure Hunt

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

Start Hunting!