In Matlab 2011b, I have a multidimensional matrix which is to be initially presented as a 2D plot of 2 of its dimensions. I wish to make the markers clickable with the left mouse button. Clicking on a marker draws a new figure of other dimensions sliced by the clicked value.
This question is related to Matlab: Plot points and make them clickable to display informations about it but I want to run a script, not just pop up data about the clicked point.
Googling hinted that ButtonDownFcn could be used, but examples I found require manually plotting each point and attaching a handler, like so:
hp = plot(x(1), y(1), 'o');
set(hp, 'buttondownfcn', 'disp(1)');
As there are many markers in the main graph, is it possible to just attach a handler to the entire curve and call the subgraph-plotting function with the index (preferable) or coordinates of the marker clicked?
this is an idea of what you need, and should help get you started if I understand your requirements.
In this case, when you select a curve, it will draw it in the bottom subplot preserving the color.
function main
subplot(211)
h = plot (peaks);
set (h,'buttondownfcn', #hitme)
end
function hitme(gcbo,evendata)
subplot (212)
hold on;
col = get (gcbo,'Color');
h2 = plot (get (gcbo,'XData'),get (gcbo,'YData'));
set (h2,'Color', col)
pt = get (gca, 'CurrentPoint');
disp (pt);
end
You can explore your options for get by simply writing get(gcbo) in the hitme function.
Related
Quite a simple question but just couldn't find the answer online... I want to visualise a point cloud gathered from a lidar. I can plot the individual frames but wanted to loop them to create a "animation". I know how to do it for normal plots with drawnow but can't get it working with a scatter3. If I simply call scatter3 again like I have done in the commented code then the frame that I am viewing in the scatter plot jumps around with every update (Very uncomfortable). How do i get the scatter3 plot to update to the new points without changing the UI of the scatter ie. Still be able to pan and zoom around the visualised point cloud while it loops through.
EDIT: The file is a rosbag file, I cannot attach it because it is 170MB. The problem doesn't happen when using scatter3 in a loop with a normal array seems to be something with using scatter3 to call a PointCloud2 type file using frame = readMessages(rawBag, i).
EDIT: The problem does not seem to be with the axis limits but rather with the view of the axis within the figure window. When the scatter is initialised it is viewed with the positive x to the right side, positive y out of the screen and positive z upwards, as shown in view 1. Then after a short while it jumps to the second view, where the axis have changed, positive x is now out of the screen, positive y to the right and positive z upwards (both views shown in figures). This makes it not possible to view in a loop as it is constantly switching. So basically how to update the plot without calling scatter3(pointCloudData)?
rawBag = rosbag('jackwalking.bag');
frame = readMessages(rawBag, 1);
scatter3(frame{1});
hold on
for i = 1:length(readMessages(rawBag))
disp(i)
frame = readMessages(rawBag, i);
% UPDATE the 3D Scatter %
% drawnow does not work?
% Currently using:
scatter3(frame{1})
pause(.01)
end
The trick is to not use functions such as scatter or plot in an animation, but instead modify the data in the plot that is already there. These functions always reset axes properties, which is why you see the view reset. When modifying the existing plot, the axes are not affected.
The function scatter3 (as do all plotting functions) returns a handle to the graphics object that renders the plot. In the case of scatter3, this handle has three properties of interest here: XData, YData, and ZData. You can update these properties to change the location of the points:
N = 100;
data = randn(N,3) * 40;
h = scatter3(data(:,1),data(:,2),data(:,3));
for ii = 1:500
data = data + randn(N,3);
set(h,'XData',data(:,1),'YData',data(:,2),'ZData',data(:,3));
drawnow
pause(1/5)
end
The new data can be totally different too, it doesn't even need to contain the same number of points.
But when modifying these three properties, you will see the XLim, YLim and ZLim properties of the axes change. That is, the axes will rescale to accommodate all the data. If you need to prevent this, set the axes' XLimMode, YLimMode and ZLimMode to 'manual':
set(gca,'XLimMode','manual','YLimMode','manual','ZLimMode','manual')
When manually setting the limits, the limit mode is always set to manual.
As far as I understood what you describe as "plots jumpying around", the reason for this are the automatically adjusted x,y,z limits of the scatter3 plot. You can change the XLimMode, YLimMode, ZLimMode behaviour to manual to force the axis to stay fixed. You have to provide initial axes limits, though.
% Mock data, since you haven't provided a data sample
x = randn(200,50);
y = randn(200,50);
z = randn(200,50);
% Plot first frame before loop
HS = scatter3(x(:,1), y(:,1), z(:,1));
hold on
% Provide initial axes limits (adjust to your data)
xlim([-5,5])
ylim([-5,5])
zlim([-5,5])
% Set 'LimModes' to 'manual' to prevent auto resaling of the plot
set(gca, 'XLimMode', 'manual', 'YLimMode', 'manual', 'ZLimMode', 'manual')
for i=2:len(x,2)
scatter3(x(:,i), y(:,i), z(:,i))
pause(1)
end
This yields an "animation" of plots, where you can pan and zoom into the data while continuous points are added in the loop
I have program code in matlab with GUI. I have there some axes object called "axes1" - there my plot is displayed (simple plot of x, y values).
I want that after point on line there shows value of Y axis in that point. And best if it would display dynamically - after moving curosor the values would automatically show new pointed value.
I saw some tutorials about this, but I couldn't apply their tips to program with GUI.
Here is a very simple example of a way you could use datacursormode, an interactive cursor which enables you to select points on your figure and get their coordinates. You could easily customize the example and store the coordinates in variables and so on, but I'll let this part up to you :).
Here is the code of the GUI with comments. You can copy/paste into a new .m file to test and play around. The GUI is just an axes in which I display random data and a checkbox that you can use to toggle the activation (i.e. on or off) of the datacursormode.
function DispYData
clear
clc
global dcm_obj
%// Create figure and ui controls
hFig = figure('Position',[200 200 500 500]);
handles.Axes = axes('Position',[.2 .2 .7 .7]);
plot(1:20,rand(1,20));
%// Create datacursor. Disable for the moment.
dcm_obj = datacursormode(hFig);
set(dcm_obj,'Enable','off')
handles.checkbox = uicontrol('Style','check','Position',[20 50 120 20],'String','Activate datacursor','Callback',#(s,e) GetPos);
guidata(hFig,handles)
function GetPos
%// If checked, activate datacursor mode
if get(handles.checkbox,'Value')
set(dcm_obj,'Enable','on')
%// If uncheck, disable.
else
set(dcm_obj,'Enable','off')
end
guidata(hFig,handles)
end
end
Sample screenshot of the GUI after enabling the datacursormode and selecting a point on the curve:
Have fun!
I have formed a 2D matrix of 180X360. In fact, it is a LatXLong grid of 1°X1°. Each grid point has a value calculated according to my algorithm.
If I want to plot this LatXLong grid using any contour function, it is easy to do.
Now, what I need to do is to make this grid a clickable/ interactive contour plot in a way that when the user clicks anywhere on my grid plot, he gets an onscreen information or a further plot to be displayed specifically related to that grid point.
In short, I want to make a grid/contour plot in which all grid points are hyperlinks and linked to further background information.
check this answer:
if you don't want to have the variable as title of the plot, you can modify the code as:
function mouseExample()
h = plot(rand(10,1), 'o-');
set(h, 'ButtonDownFcn',#buttonDownCallback)
function out = buttonDownCallback(o,e)
p = get(gca,'CurrentPoint');
out = p(1,1:2);
% title( sprintf('(%g,%g)',p) ) % --> no need this line anymore
end
end
the information is saved in the P variable that you can use later.
To get started, look into ginput and text. ginput will let you click on points in your plot and return the coordinates to some function that can generate information to be displayed in the current plot using text of by opening another figure.
You can use ginput in a loop to display multiple data points as you go:
for t = 1:10
[x,y] = ginput(1);
text(x,y,'some info');
end
I don't know of a way to remove the gird lines. NKN's solution might do that for you.
I want to have a program in matlab with GUI, at run the program, user can draw anythings with mouse on the axes in GUI, and i want to saving created image in a matrix. how can i to do this?
Finally i find a good code and i have changed some parts for customizing for me. with this way, user can drawing anythings in the axes with mouse :
function userDraw(handles)
%F=figure;
%setptr(F,'eraser'); %a custom cursor just for fun
A=handles.axesUserDraw; % axesUserDraw is tag of my axes
set(A,'buttondownfcn',#start_pencil)
function start_pencil(src,eventdata)
coords=get(src,'currentpoint'); %since this is the axes callback, src=gca
x=coords(1,1,1);
y=coords(1,2,1);
r=line(x, y, 'color', [0 .5 1], 'LineWidth', 2, 'hittest', 'off'); %turning hittset off allows you to draw new lines that start on top of an existing line.
set(gcf,'windowbuttonmotionfcn',{#continue_pencil,r})
set(gcf,'windowbuttonupfcn',#done_pencil)
function continue_pencil(src,eventdata,r)
%Note: src is now the figure handle, not the axes, so we need to use gca.
coords=get(gca,'currentpoint'); %this updates every time i move the mouse
x=coords(1,1,1);
y=coords(1,2,1);
%get the line's existing coordinates and append the new ones.
lastx=get(r,'xdata');
lasty=get(r,'ydata');
newx=[lastx x];
newy=[lasty y];
set(r,'xdata',newx,'ydata',newy);
function done_pencil(src,evendata)
%all this funciton does is turn the motion function off
set(gcf,'windowbuttonmotionfcn','')
set(gcf,'windowbuttonupfcn','')
The ginput function gets the coordinates of moueclicks within a figure. You could use these as points of a line, polygon, etc.
If this doesn't fit your needs you need to decribe what exactly you expect the user to draw.
For freehand drawing this might be helpful:
http://www.mathworks.com/matlabcentral/fileexchange/7347-freehanddraw
The only way I know to interact with matlab windows using a mouse is ginput, but this will now let you draw anything with fluidity.
There are ways to use Java Swing components in matlab check http://undocumentedmatlab.com/ for more info.
EDIT: You may want to check this out as well.
http://blogs.mathworks.com/videos/2008/05/27/advanced-matlab-capture-mouse-movement/
I have a problem when i am working with plots in Matlab. Following are my issues with Plots:
How can one select Regions after plotting data using mouse?
After selecting the Regions how to get data from that region?
Any Ideas?
Selecting regions with a mouse is quite easy using the rbbox function.
First you add a ButtonDownFcn to the axes you are drawing rbbox on.
hax = axes( ... , 'ButtonDownFcn', #OnClickAxes);
Then you call rbbox within the callback like this
function OnClickAxes( hax, evt )
point1 = get(hax,'CurrentPoint'); % hax is handle to axes
rbbox;
point2 = get(hax,'CurrentPoint'); % hax is handle to axes
end
Here point1 and point2 will define the two corners of the rectangle drawn by your mouse in data coordinates. Type doc rbbox at matlab prompt for more information
Now to answer your second question for 2-D plots.
This bit of code will extract and return the data within the selected region for all lines within an axes.
https://gist.github.com/3107790