Is there any function for getpts() of MATLAB in Octave? - matlab

I load a data file and plot it in octave. But in the plot, I want to mark the periodic appearance of points on the plot. I used ginput() function for marking. But the problem I see is, if I mark a different point which was not supposed to mark and then immediately realise that i made mistake, now I want to delete my last marked point and then mark the correct point. I'm not able to do it. I found out that there is MATLAB function getpts() which does the same but octave version of getpts() is not there. Can anyone help me out please?
Example:
The sequence i want to mark is 1,2,3,4,5,6,7,8,9,10.
But accidently I mark 1,2,3,5 And realise that I did a mistake and then press delete button on the keyboard which deletes 5 and then I mark 4 and then 5.

While getpts is not implemented per se, producing a small function which gets inputs one by one via ginput and vets them to get the desired behaviour is fairly easy. E.g.
X = []; Y = [];
while true
[x, y, b] = ginput(1);
if b == 8 , X(end)=[]; Y(end)=[]; % backspace key pressed
elseif isempty(b), break; % enter key pressed
else , X(end+1)=x; Y(end+1)=y; % any other key
end
disp([X;Y]); fprintf('\n'); fflush(1); % Optional terminal output
end
This is a very flexible approach which allows you to modify and add functionality as you desire (e.g., add different markers based on specific key pressed, plot as you go, etc).

Related

Update gramm plot matlab crashing

I have a MATLAB GUI that calls an external function to make a plot (make_ethogram_plot).
The idea would be to have an external figure that is constantly updated with the output value from the figure. Every time the data gets updated it should replot the values, it updates at ~10 Hz. I chose gramm (https://github.com/piermorel/gramm/tree/master/%40gramm) because it is really easy to make a raster plot.
This is the function that gets called. I am having issues to
1) Make it only update in the parent figure with specific name, instead of plotting in the GUI(which is the active figure).
2) Make it not crash. It would open many figures or open or close the same figure at 10 Hz until crashing.
In this configuration, it gives error because it doesn't find g after the first plot. Making g , f, and p1 globals makes it crash (opens every time it gets called)
function make_ethogram_plot(datastructure)
% if the figure doesn't exists create it
if(isempty(findobj(0, 'Name', 'My_gramm_ethogram')))
f=figure('Name', 'My_gramm_ethogram');
p1 = uipanel('Parent',f,'BackgroundColor',[1 1 1],'BorderType','none');
g = gramm('x', datastructure.final_data.frameID, 'color', categorical(datastructure.final_data.behavior));
g.geom_raster();
g.set_parent(p1);
g.draw()
else
% defining f,p1, g here (or having them global) works but crashes
% due to refresh rate
g.update()
end
end
I wrote this code to try to replicate your problem:
function animate_random_data
N = 10000;
data = [cumsum(rand(N,1)),randn(N,1)];
for ii=0:1000
% Plot the data
make_ethogram_plot(data);
drawnow
% Compute new data
data(:,1) = cumsum(rand(N,1));
data(:,2) = randn(N,1);
end
function make_ethogram_plot(data)
fig = findobj(0, 'Name', 'My_gramm_ethogram');
if(isempty(fig))
% If the figure doesn't exists create it
fig = figure('Name', 'My_gramm_ethogram');
ax = axes(fig);
plot(ax,data(:,1),data(:,2));
drawnow
set(ax,'xlimmode','manual','ylimmode','manual');
else
% If it does, update it
line = findobj(fig,'type','line');
set(line,'xdata',data(:,1));
set(line,'ydata',data(:,2));
end
Here, I followed your concept of looking for a named figure window, and creating one if it didn't exist. However, if it does exist, I simply replace the XData and YData property of the line that is already there. This is the fastest way of animating a graph, much faster than deleting the existing plot and creating a new one. After plotting, I use drawnow to update the display. I set XLimMode and YLimMode to manual to prevent re-computation of axes limits and consequent re-drawing of the axes.
The function took 17 seconds to draw all 1000 frames, meaning it's drawing about 60 frames a second. It does not (and should not) crash MATLAB.
You can limit the display rate to 20 frames/sec with drawnow limitrate. It will skip updating the display if the frames come too fast.
I don't know what the gramm/update method does, the class is too complicated to quickly see what is going on, but I dare presume it deletes the axes and creates a new plot from scratch. Not that this should crash MATLAB, it might be worth while to submit a bug report. However, you would probably want to update the figure in the more efficient way, following the method I demonstrated above.
Note that this method can be used to update any of the graphical elements in a plot. For example, I have used this method to animate images.

Best way to get out of a for plotting for loop in MATLAB

I have the following code in Matlab:
a = linspace(0,1);
t = linspace(0,10);
x = cos(2*t);
for i = 1:10
z = a(i) *x
plot(z)
pause(0.1)
end
This is just to see how varying the variable "a" will change the plot. This created an animated plot. Question is: If I have a large data set and I have to plot more complicate things than what is above, what is the best way to end the loop? In other words, if I now close the plot figure, it would continue to run until i = 10. Would a "break" statement work? Or do a keyboard input with "keyboard"?
Thanks for your help
You could check for the existence of the figure handle on every loop. If the figure is closed (and thus the figure handle is deleted) then you automatically end the loop.
a = linspace(0,1);
t = linspace(0,10);
x = cos(2*t);
h.fig = figure;
for i = 1:100
z = a(i) *x
plot(z)
pause(0.1)
if ~isvalid(h.fig)
break
end
end
Do you want the users to be able to end the animation when they feel like? Or do you want to end the animation programmatically due to a condition that's verified in every iteration?
If you just want to end the loop from within the code (that is, the second option above), then yes, a break statement will suffice. (You could set a boolean flag just before the break and check for this flag after the loop ends so that you can close the plot if you want to.)
Now, if you want to give the user the ability to stop the animation by clicking a button or something, you could (1) just tell the user to hit Ctrl+C; or (2) find a more structured solution to making an animation in matlab (you might want to check this).

MATLAB: Permanently set "Text Update Function" for Data Cursor in figures

Problem: I use MATLAB for science, and I often need more than 4 significant digits. Every time I use Data Cursor in a figure's GUI, I need to manually right-click on the point, Select Text Update Function... or Edit Text Update Function..., and navigate to the folder where I saved the function whose callback prints more than 4 (e.g. 8) significant figures. This is annoying and there should be a way to automatically change this.
Ideal answer: I want this done permanently for all figures, e.g. in a function that changes default settings in my startup.m file.
Good enough answer: I want a wrapped function to which I give the figure handle and it fixes this for me.
I humbly await SO's infinite wisdom.
The permanent solution
would be, to edit the default_getDatatipText.m function.
You can find it in:
C:\...\MATLAB\R20xxx\toolbox\matlab\graphics\#graphics\#datacursor
There you will find the line:
DEFAULT_DIGITS = 4; % Display 4 digits of x,y position
Edit it as desired, you can't do much harm, but make a backup before if you want.
Alternative solution:
There is also the possibility of custom data tips: Tutorial at Matlab Central
It could finally look like this:
(additional text outside data-tips was post-processed)
And as you're talking about precision. The data-tip always snaps to the closest data-point. It doesn't show interpolated data at the clicked position.
The permanent answer given by thewaywewalk doesn't work anymore in R2015a, and probably later ones. So here I share my solution for both the temporary and permanent solution
Temporary solution (for a single figure):
The following function contains the update function as a nested function. Call datacursorextra to apply it to the current figure, or datacursorextra(fig) to apply it to some figure fig.
function datacursorextra(fig)
% Use current figure as default
if nargin<1
fig = gcf;
end
% Get the figure's datacursormode, and set the update function
h = datacursormode(fig);
set(h,'UpdateFcn',#myupdatefcn)
% The actual update function
function txt = myupdatefcn(~,event)
% Short-hand to write X, Y and if available Z, with 10 digit precision:
lbl = 'XYZ';
txt = arrayfun(#(s,g)sprintf('%s: %.10g',s,g), lbl(1:length(event.Position)), event.Position,'uniformoutput',false);
% If a DataIndex is available, show that also:
info = getCursorInfo(h);
if isfield(info,'DataIndex')
txt{end+1} = sprintf('Index: %d', info.DataIndex);
end
end
end
Permanent solution (apply to all figures by default):
I have not found a way to set a default UpdateFcn for the data cursor, but it is possible to add some code which will be called every time a new figure is created. Add the following line to your startup.m:
set(0,'defaultFigureCreateFcn',#(s,e)datacursorextra(s))
and make sure the datacursorextra function given above is available in your Matlab path.
#caspar's solution works very well.
You can also update the txt{} part of the solution with
if isfield(info,'DataIndex')
DataIndex = [info.DataIndex];
txt{end+1} = sprintf('Index: %d\n', DataIndex(1));
end
This will enable you to update the Index field when you have multiple pointers in the same figure.

MATLAB uitable row generation from user input

I've got a GUI in MATLAB which uses uitables for input. There are a fixed number columns, and each column has a very specific format which I have stored as a cell array, like so:
columnformat = {'text', 'numeric', {#doSomething, inputArg1}, {'Option1' 'Option2'}};
The number of rows is theoretically unlimited; the user could provide as many they like. The back-end is capable of handling arbitrarily many row inputs. Right now, I'm building a large uitable initially, and just assuming the user won't use it all.
Here's the question: I want to set up the table and associated code such that any time the user has selected the final row and presses enter, it creates a new row with the same format as the rest of the table.
I've tried many different approaches, including dynamically setting 'Data', and they all seem to break the custom formatting dictated by the cell array. I'm sure someone has done this before. Thanks for your help!
This solution works on GUI created using MATLAB GUIDE. I think it's true that MATLAB GUI shows odd behaviour, but I have seen most of the odd behaviour when debugging MATLAB callbacks using something like keyboard and not properly exiting from them using dbquit. So, my advice would be to stay away from using keyboard related commands for MATLAB GUIs created with GUIDE.
Now, back to solving your problem, follow these steps.
Step 1: Add this at the start of GUINAME__OpeningFcn:
handles.row_col_prev = [1 1];
Step 2: Click on the properties of the table in context and click on CellSelectionCallback. Thus, if the tag of the table is uitable1, it would create a function named - uitable1_CellSelectionCallback.
Assuming the figure of the GUI has the tag - addrows_figure
Add these in it:
%%// Detect the current key pressed
currentkey = get(handles.addrows_figure,'CurrentCharacter')
%%// Read in previous row-col combination
prev1 = handles.row_col_prev
%%// Read in current data. We need just the size of it though.
data1 = get(handles.uitable1,'Data');
%%// Main processing where a row is appended if return is pressed
if numel(prev1)~=0
if size(data1,1)==prev1(1) & currentkey==13 %%// currentkey==13 denotes carriage return in ascii
data1(end+1,:) = repmat({''},1,size(data1,2)); %%// Append empty row at the end
set(handles.uitable1,'Data',data1); %%// Save it back to GUI
end
end
%%// Save the current row-col combination for comparison in the next stage
%%// when selected cell changes because of pressing return
handles.row_col_prev = eventdata.Indices;
guidata(hObject, handles);
Hope this works out for you!
I couldn't think of a possibility to achieve what you want with a certain key, I think it would be possible with any key (KeyPressFcn). But I'd rather recommend to introduce a toolbar with a pushbutton:
h = figure(...
u = uitable(h, ...
set(u,'Tag','myTable')
tbar = uitoolbar(h);
uipushtool(tbar,'ClickedCallback',#addRow);
In your callback function then you need to get your data, add a row and write it back:
function addRow(~,~)
u = findobj(0,'Type','uitable','Tag','myTable');
data = get(u,'Data');
%// modify your data, add a row ...
set(src,'Data',data);
end
Sorry if everything is a little simple and untested, but a good answer would require a considerable effort, I don't have time for. The tag matlab-uitable can give you a lot of further ideas.

Ordinary Differential Equations in Matlab

Question -
I am working on some matlab code that solves 2 first degree differentials and 2 second order differentials. I am ok with dsolve() but when I want to plot I am currently using ezplot and it is not giving me what I want. I want to produce 1 window with four graphs. I know I would use subplot but I dont know how, an example would be nice. Also I dont know how to make my plots show the importiant area not just a large area. my code is below:
close all % close all figure windows that are open
clear all % clear all the variables currently stored in memory
clc % clear the commands in the command window
%%Problem 1%%%%%
a = (dsolve('Dv = -500*v+5000','v(0)=5'));
display (a)
b = (dsolve('Dx = -2000*x+100','x(0)=-.02'));
display (b)
%%Problem 2%%%%%
c = (dsolve('D2y+2000*Dy+26000000*y-520000000=0','Dy(0)=0','y(0)=5'));
display(c)
d = (dsolve('D2y+100*Dy+2500*y-520000000=0','Dy(0)=20','y(0)=0'));
display (d)
figure
ezplot(a);
axis([0,.01,4,10])
figure
ezplot(b);
axis([0,.01,0,10])
figure
ezplot(c);
axis([0,.01,4,10])
figure
ezplot(d);
axis([0,.01,4,10])
I didn't know until now, but it seems that ezplot only generates data points for "interesting part" of your plot. So if you specify the x-limit that ezplot does not use, you don't see anything. What you need to do is to specify the x-limits in its second argument of ezplot. Then, you can create subplots with standard suplot function, get axis handle, and specify the axis. The plotting part of your code should be like this.
figure
h1=subplot(2,2,1);
ezplot(a, [0,0.01]);
axis(h1,[0,0.01,4,10])
h2=subplot(2,2,2);
ezplot(b, [0,0.01]);
axis(h2,[0,.01,0,10])
h3=subplot(2,2,3);
ezplot(c, [0,0.01]);
axis(h3,[0,.01,4,10])
h4=subplot(2,2,4);
ezplot(d, [0,0.01]);
axis(h4,[0,.01,4,10])