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 visualizzazioni (ultimi 30 giorni)
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.

Risposta accettata

Andreas Apostolatos
Andreas Apostolatos il 20 Dic 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 Commento
Jürgen
Jürgen il 20 Dic 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.

Accedi per commentare.

Più risposte (0)

Categorie

Scopri di più su Graphics Object Programming in Help Center e File Exchange

Prodotti


Release

R2021b

Community Treasure Hunt

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

Start Hunting!

Translated by