Customizing cursor in Matlab - matlab

In Matlab 2012a I have generated a figure from a previous code that is SSI as a function of age.
I want to customize datatip by updating my own function instead of the default one. I know how to change x and y and now I have Age and SSI for them. However, I have another piece of information -subjectID- which I want to add to the display text.
By clicking on each point, I want datatip to show Age, SSI and subject ID of corresponding data point.
This is what I have now:
matlab is a saved work place of my SSI-age.
function output_txt = myupdatefcn(obj,event_obj,...
matlab,labels,SubjectID)
pos = get(event_obj,'Position');
x = pos(1);
y = pos(2);
[~, ~, raw0_0] = xlsread('Data.xlsx','CONTROLS','A2:A106');
raw = [raw0_0];
SubjectID = cell2mat(raw);
output_txt = {['AGE: ',num2str(pos(1),4)],...
['SSI: ',num2str(pos(2),4)],...
['SubjectID: ',SubjectID]};
idx = find(matlab == x,1);
[row,col] = ind2sub(size(matlab),idx);
output_txt{end+1} = cell2mat(labels(row));
Obviously, this is not right. Can somebody please help me out here? Thank you.

If I read your code correctly, I make the following assumptions (which may be incorrect):
* the subjectID is a cell containing a vector of strings
* subjectID is X position of the clicked point
First, a quick digression: getting SubjectID into your plot
I noticed, in your function call, you have SubjectID as one of the input parameters. However, it appears that it would never be used, since the next line that uses it assigns it a value.
As written, this will read from the excel file each and every time that the update function is called. You might wish to move the load-from-excel portion into the same section of code where the data is first loaded. If I assume the SubjectID is text, you can store it in the UserData variable of the timeseries. That would make the following work:
Onward to the answer
So, if you include your SubjectID information in the userdata, when you first plot like so:
% ...not shown: get the ages, SSIs and SubjectIDs ....
plot(ages, SSIs, 'UserData', SubjectIDs); % Store SubjectIDs along with the line...
Then the following should work -- or at least put you on solid ground.
function output_txt = myupdatefcn(obj,event_obj)
pos = get(event_obj,'Position');
x = pos(1);
y = pos(2);
allIDs = get(event_obj.Target,'UserData');
thisSubject = event_obj.UserData{pos(1)};
output_txt = {['AGE: ',num2str(pos(1),4)],...
['SSI: ',num2str(pos(2),4)],...
['SubjectID: ',thisSubject]};
You can probably get rid of the last 3 lines of code, since you know a priori that all 3 values are accessible.
Hope that helps.

Related

Matlab draw line with plot and dynamic values

I am trying to draw line with plot in matlab app designer. But i dont know how to create line. I am just redrawing point on new coordinates.
This is my code (functions runs each second) (format of plot is plot(PlotUI,X,Y))
function function2(app)
app.timeCounter = app.timeCounter + 1;
plot(app.UIAxes,app.timeCounter,app.newValDblPublic);
end
I will be thankful for any help.
At the moment you are just plotting the current set of values, if you want to plot the historic values too, you need to keep them in an array and plot the entire array.
%When the GUI is first created, start with one value in the array
app.time_values = [0];
app.y_values = [0];
%Inside your function
function function2(app)
app.time_values(end+1) = app.time_values(end)+1; % Add a new value to the array, 1 greater than the last value
app.y_values(end+1) = app.newValDblPublic;
plot(app.UIAxes,app.time_values,app.y_values);
end

How can I store multiple point objects in an array or struct?

I am trying to use matlab's drawpoint to capture some points of interest in an image interactively.
The output of the argument is of images.roi.Point object type.
How can I store the selected points in an array or struct, so I can iterate over many points instead of defining a new variable for each point?
This is my code at the moment, it's functional, however I want to be able to loop over a certain number of points instead of defining different variables manually.
img = imread('test.jpg');
imshow(img)
p1 = drawpoint;
p2 = drawpoint;
p3 = drawpoint;
p4 = drawpoint;
disp('Press a key when selection is finalized!')
pause;
p = [p1.Position; p2.Position; p3.Position; p4.Position];
The reason I'm using drawpoint is that I want to select the points, adjust their position without loosing zooming capability and store all points once finalized.
How can I modify the code to enable iteration over a certain number of points?
Any help would be much appreciated
I don’t know if it is possible to create an array of these objects. I suspect it is possible, but I don’t know exactly what the syntax should look like. You can also use a cell array, as follows:
N = 4; % number of points
pts = cell(N,1);
for ii = 1:N
pts{ii} = drawpoint;
end
pause;
coords = zeros(N,2);
for ii = 1:N
coords(ii,:) = pts{ii}.Position;
end

Plotting brownian motion matlab

First of all, I just want to say that I'm not that used to using matlab, but I need for an assignment, I'm supposed to create a "brownian movement". My code is currently looking like this:
clf
hold on
prompt = 'Ge ett input';
size = input(prompt) ;
numParticles = input('Ange antal partiklar');
axis([-size size -size size]);
Part = [];
color = 'brkgmyco';
for i = drange(1:numParticles)
Part = [Part [0;0]];
end
for i = drange(1:200)
dxdy = randn(2,numParticles);
k = Part
Part = Part + dxdy;
My concern is how to print, I would even want like a small delay on every print, so you really can see what's happening for the assignment, is this possible to achieve from the code I've written for now or should anything be changed? Thanks in advance!
Here are some basic problems with your code, regardless of what you are trying to do:
You use size as a variable name. Doing so overrides MATLAB's function size.
The function zeros creates an array initialized by zeros, no need for a loop for that.
Instead of calculating randn for 200 times in a loop, you can do it once, with dxdy = randn(2,numParticles,200) and then simply refer to dxdy(:,:,i) within the loop.
The same holds for summation. Instead of summing within a loop to get the cumulative sum, use cumsum like Part = cumsum(randn(2,numParticles,200),3); and then refer to Part(:,:,i), within the loop.
Now to your task. You said you want to know how to print, but I believe you want to plot because you use some commands like axis, clf and hold, that refer to graphic objects. However, you never really do plot anything.
The basic and general function for plotting in 2D is plot, but there are many other more specific functions. One of them is scatter, and it has a sister function gscatter, that takes triples of x, y and groupand plot each (x(k),y(k)) colored by their group(k).
This code plots the particles on an axes, and animate their movement:
prompt = 'Ge ett input';
scope = input(prompt) ;
numParticles = input('Ange antal partiklar');
N = 500;
Part = cumsum(randn(2,numParticles,N)*scope/100,3);
h = gscatter(Part(1,:,1),Part(2,:,1),1:numParticles);
axis([-scope scope -scope scope]);
legend off
for k = 2:N
for p = 1:numParticles
h(p).XData = Part(1,p,k);
h(p).YData = Part(2,p,k);
end
drawnow
end
Is this what you look for?

Save multiple GUIdata sets to listbox and then load them again in MATLAB

I have built a calculation software in MATLAB GUIDE. What I want to do is to fill out all my calculation data in different edit fields and some dropdowns and when I press calculate a "listbox" should be populated with the text "Calculation 1".
If I then change some data in some of the input fields and press calculate again I want to populate the listbox with "Calculation 2" beneath "Calculation 1" etc...
But then I would want to be able to highligt "calculation 1" again in the listbox and press a "load input parameters" button to populate all the edit input fields with the data that was used when "calculation 1" was calculated.
I have looked all over the place for this but can't find anything.
//Robin
Here is some code which is very basic but performs what you are looking for. There are a lot of tweaks possible but I'll let you play around with them. I put explanations as comments. You can copy past into Matlab and change the GUI as you like.
function CalculatorGUI
% Dummy GUI to calculate A*B + C...
clc
clear
close all
global hTestResult hEditA hEditB hEditC CalculationList CalculationStrings
% Set up controls
CalculationList = nan(10,3); % Create array in which we store the parameters. 1st column is A, 2nd is B and 3rd is C.
CalculationStrings = cell(10,1);
ScreenSize = get(0,'ScreenSize');
hFig = figure('Visible','off','Position',[ScreenSize(3)/2,ScreenSize(4)/2,450,285]);
hCalculateButton = uicontrol('Style','Pushbutton','Position',[350,150,80,30],'String','Calculate!','Callback',#CalculateCallback);
hTitle = uicontrol('Style','Text','Position',[100,250,100,25],'String','Calculate (A * B) + C');
hTextA = uicontrol('Style','Text','Position',[125,220,70,25],'String','A');
hEditA = uicontrol('Style','Edit','Position',[125,200,70,25],'String','1');
hTextB = uicontrol('Style','Text','Position',[200,220,70,25],'String','B');
hEditB = uicontrol('Style','Edit','Position',[200,200,70,25],'String','2');
hTextC = uicontrol('Style','Text','Position',[275,220,70,25],'String','C');
hEditC = uicontrol('Style','Edit','Position',[275,200,70,25],'String','3');
hResultHeader = uicontrol('Style','Text','Position',[350,220,70,25],'String','Result');
hTestResult = uicontrol('Style','Text','Position',[350,200,70,25],'String','');
hTextCalcu = uicontrol('Style','Text','Position',[100,140,100,50],'String','Calculations');
hListCalcu = uicontrol('Style','Listbox','String','','Position',[100,120,200,50],'max',10,...
'min',1,'Callback',#ListBox_Callback);
set(hFig,'Visible','on')
%======================================================================
%======================================================================
% Callback of the pushbutton
function CalculateCallback(~,~)
% Get the values in the edit boxes. There is no ckechup to make
% sure the user entered a correct value...
A = str2double(get(hEditA,'String'));
B = str2double(get(hEditB,'String'));
C = str2double(get(hEditC,'String'));
Calculation = A*B+C;
% Display the result.
set(hTestResult,'String',sprintf('The result is %0.2f',Calculation));
% Find how many calculations have been performed and append the
% parameters to the current list
[x,~] = find(~isnan(CalculationList));
CurrentCalc = numel(unique(x)); % Get number of rows which are NOT NaNs.
CurrentValues = [A B C];
CalculationList(CurrentCalc+1,:) = CurrentValues;
CurrentString = sprintf('A = %0.2f B = %0.2f C = %0.2f',A,B,C);
% Assign the parameters to the cell array.
CalculationStrings(CurrentCalc+1) = {CurrentString};
set(hListCalcu,'String',CalculationStrings)
end
% Listbox callback: When the selection changes, the corresponding
% parameters in the edit boxes change.
function ListBox_Callback(~,~)
SelectedCalc = get(hListCalcu,'Value');
CalculationList(SelectedCalc,1)
CalculationList(SelectedCalc,2)
CalculationList(SelectedCalc,3)
set(hEditA,'String',CalculationList(SelectedCalc,1));
set(hEditB,'String',CalculationList(SelectedCalc,2));
set(hEditC,'String',CalculationList(SelectedCalc,3));
end
end
The actual interface looks like this:
Of course you can make it much more complex, but this should help you get started and understand how the different callbacks work together. Have fun!

Plot to highlight selected data

I'd like to create something similar to this. The differences are: my table only has one column, which is the variable I changed to get my data. I have the table set up and working, and most of what I have works, but I only seem to be able to highlight one thing at once. This is what I have:
% Set up plots etc
for a = 1:length(data);
xAxis = data{a,1}(:,X);
yAxis = data{a,1}(:,Y);
plot(graph,xAxis,yAxis);
% Visible data
hilite = plot(graph,xAxis,yAxis,'o-','LineWidth',2,'HandleVisibility','off','Visible','off');
% Invisible data, to be highlighted later
hold all
end
hold off
% Data table callback function
function dataTable_Callback(hObject, eventdata)
set(hilite,'Visible','off')
names = get(hObject,'Data');
select = eventdata.Indices(:,1);
for d = 1:length(select)
group = select(d);
xAxis = [];
% makes sure that previously selected data is removed
yAxis = [];
xAxis(:,d) = data{group,1}(:,X);
% if I remove the semicolon and let MATLAB print this data, I always get
the correct data in the correct columns, adding and subtracting them when
I select them
yAxis(:,d) = data{group,1}(:,Y);
set(hilite,'Visible','on','XData',xAxis(:,d),'YData',yAxis(:,d))
legend(hilite, num2str(names{select,1}(1,1)));
end
end
I've been playing with this for a few hours now, and I really can't work out what my issue is. Any help is obviously much appreciated! :-)