Switching values to plot using keyboard input
Asked Answered
P

2

5

I have sets of data in a matrix. I want to plot on set and then use a keyboard input to move to another one. It's simply possible this way:

for t=1:N
  plot(data(:,t))
  pause
end

but I want to move forward and backward in time t (e.g. using arrows). OK, it could be done like this:

direction = input('Forward or backward?','s')
if direction=='forward'
   plot(data(:,ii+1))
else
   plot(data(:,ii-1))
end

but isn't there something more elegant? (On one click without getting the figure of the sight - it's a big full sreen figure.)

Petrify answered 29/4, 2015 at 15:50 Comment(2)
So did any of our answers help you?Fetid
In fact the really did, I've just been a little busy last couple days so it took me long to implement them. Thank you all very much!Petrify
F
7

You can use mouse clicks combined with ginput. What you can do is put your code in a while loop and wait for the user to click somewhere on the screen. ginput pauses until some user input has taken place. This must be done on the figure screen though. When you're done, check to see which key was pushed then act accordingly. Left click would mean that you would plot the next set of data while right click would mean that you plot the previous set of data.

You'd call ginput this way:

[x,y,b] = ginput(1);

x and y denote the x and y coordinates of where an action occurred in the figure window and b is the button you pushed. You actually don't need the spatial coordinates and so you can ignore them when you're calling the function.

The value of 1 gets assigned a left click and the value of 3 gets assigned a right click. Also, escape (on my computer) gets assigned a value of 27. Therefore, you could have a while loop that keeps cycling and plotting things on mouse clicks until you push escape. When escape happens, quit the loop and stop asking for input.

However, if you want to use arrow keys, on my computer, the value of 28 means left arrow and the value of 29 means right arrow. I'll put comments in the code below if you desire to use arrow keys.

Do something like this:

%// Generate random data
clear all; close all;
rng(123);
data = randn(100,10);

%// Show first set of points
ii = 1;
figure;
plot(data(:,ii), 'b.');   
title('Data set #1');  

%// Until we decide to quit...
while true 
    %// Get a button from the user
    [~,~,b] = ginput(1);

    %// Left click
    %// Use this for left arrow
    %// if b == 28
    if b == 1
        %// Check to make sure we don't go out of bounds
        if ii < size(data,2)
            ii = ii + 1; %// Move to the right
        end                        
    %// Right click
    %// Use this for right arrow
    %// elseif b == 29
    elseif b == 3
        if ii > 1 %// Again check for out of bounds
           ii = ii - 1; %// Move to the left
        end
    %// Check for escape
    elseif b == 27
       break;
    end

    %// Plot new data
    plot(data(:, ii), 'b.');
    title(['Data set #' num2str(ii)]);
end

Here's an animated GIF demonstrating its use:

enter image description here

Fetid answered 29/4, 2015 at 16:0 Comment(5)
Nice I never thought to use the third output from ginput! +1 I'll definitely use that sometimes :)Inflation
@Inflation - It's a nice little thing I use if I want to cycle through an image sequence that I have stored... looking at things like optical flow for example. However, you can totally put this into a movie thing with immovie, but this is a pretty quick and dirty solution.Fetid
@Inflation - Added in an animated GIF as a bonus :)Fetid
@rayryeng. Nice one. I use ginput too to get different options accessible by mouse on my programs. The added gif was a nice touch ;-)Coffer
@Coffer - Thanks for your awesome code with event handlers! I could never get the hang of those but your code makes it very easy to understand. +1 too :)Fetid
C
6

This demo shows you how to use either the left and right arrows of the keyboard to switch data set or even the mouse wheel.

It uses the KeyPressFcn and/or WindowScrollWheelFcn event of the figure.

function h = change_dataset_demo

%// sample data
nDataset = 8 ;
x = linspace(0,2*pi,50).' ;     %'// ignore this comment
data = sin( x*(1:nDataset) ) ;

index.max = nDataset ;
index.current = 1 ;

%// Plot the first one
h.fig = figure ;
h.plot = plot( data(:,index.current) ) ;

%// store data in figure appdata
setappdata( h.fig , 'data',  data )
setappdata( h.fig , 'index', index )

%// set the figure event callbacks
set(h.fig, 'KeyPressFcn', @KeyPressFcn_callback ) ;     %// Set figure KeyPressFcn function
set(h.fig, 'WindowScrollWheelFcn',@mouseWheelCallback)  %// Set figure Mouse wheel function

guidata( h.fig , h )


function mouseWheelCallback(hobj,evt)
    update_display( hobj , evt.VerticalScrollCount )


function KeyPressFcn_callback(hobj,evt)
    if ~isempty( evt.Modifier ) ; return ; end  % Bail out if there is a modifier

    switch evt.Key
        case 'rightarrow'
            increment = +1 ;
        case 'leftarrow'
            increment = -1 ;
        otherwise
            % do nothing
            return ;
    end
    update_display( hobj , increment )


function update_display( hobj , increment )

    h = guidata( hobj ) ;
    index = getappdata( h.fig , 'index' ) ;
    data  = getappdata( h.fig , 'data' ) ;

    newindex = index.current + increment ;
    %// roll over if we go out of bound
    if newindex > index.max
        newindex = 1 ;
    elseif newindex < 1
        newindex = index.max ;
    end
    set( h.plot , 'YData' , data(:,newindex) ) ;
    index.current = newindex ;
    setappdata( h.fig , 'index', index )

This will roll over when the end of the data set is reached.

done a little gif too but it's a lot less impressive because it does not show the keyboard/mouse action, only the graph updates :

animgif

Coffer answered 29/4, 2015 at 16:37 Comment(3)
I used LICEcap to capture my animated GIF: cockos.com/licecap - You place the figure window within the recording area, click start recording and it'll capture everything within there at a specified FPS with mouse clicks showing. It's free and available for both Windows and Mac OS.... also open source!Fetid
@rayryeng. Wow thanks. Great little utility ! I went the old matlab getframe/imwrite way ... tedious. This program will be great for my next GIFs. CheersCoffer
Oh I understand. Though it was great to do it in MATLAB, It's a pain in the butt to write the code for it. This way, it's just a matter of point clicks to get what you want. You're welcome!Fetid

© 2022 - 2024 — McMap. All rights reserved.