Drag pattern in uitable matlab - matlab

I want to know if it is possible to drag pattern values in matlab uitable. In a spreadsheet, to enter values from 1 to 50, you need to enter 1,2,3 and select the cells and drag. Please can this be done in matlab uitable? Regards.

It can be done. But not as far as comfortable as with excel.
Play around a bit with the following code, you can try to improve it or change it to your needs. I think it is a good starting point for you.
function fancyTable
defaultData = randi(99,25,2);
h = figure('Position',[300 100 402 455],'numbertitle','off','MenuBar','none');
uitable(h,'Units','normalized','Position',[0 0 1 1],...
'Data', defaultData,...
'Tag','myTable',...
'ColumnName', [],'RowName',[],...
'ColumnWidth', {200 200},...
'CellSelectionCallback',#cellSelect);
end
function cellSelect(src,evt)
try
index = evt.Indices;
data = get(src,'Data');
L = size(index,1);
rows = index(:,1);
column = index(1,2);
start = data(rows(1),column);
newdata = start:(start+L-1);
data(rows,column) = newdata';
set(src,'Data',data);
end
end
It creates a table with two columns:
You can select data and your desired drag pattern is applied immediately according to the first value.
The code is just to insert an increasing series of values at the first point of selection based on the according value. The hardest part will be to detect the pattern! I just evaluated the first data value start = data(rows(1),column); you could also require a minimal selection of 3: start = data(rows(1:3),column);. You probably need to work with a lot of try/catch structures to skip all unexplained cases. Or you use switch/case structures from the beginning to evaluate the length of the selection and evaluate the pattern.
All in all it is a heavy task, I'm not sure if it's worth it. But it can be done.

In uitable you insert data (usually a matrix) to be displayed in a table. So unlike Excel the uitable function is merely a form of displaying your data instead of a tool to manipulate it. See for more information here. However, if you want to set up a row for instance running from 1 until 10 you could use the following steps:
So say one would like to display a matrix of size 10x10, e.g.
A=magic(10);
You can now set up a table t to display this matrix by
t=uitable('Data',A);
In your case if you want a row to be, e.g., 1 till 10, just change the matrix A containing your data to hold this row using
A(1,1:10)=1:10;
And re-execute the former command to bring up your table t.

Related

Assigning arrays to a matrix in a function, syntax problems

I'm having trouble with the syntax in Matlab.
I'm trying to split an audio signal up into different segments (frames).
I would like to return the y-axis values to a matrix (each segment having its own column), and the corresponding time values with each segment having its own row.
I can't even get it to return just one single column and row pair (ie one frame). I just get returned two empty matrices. Here's my code.
function [mFrames, vTimeFrame] = Framing(vSignal,samplingRate,frameLPerc,frameshPerc)
totalTime=size(vSignal,1)/samplingRate
frameLength = totalTime*frameLPerc;
frameShift = totalTime*frameshPerc;
frameNumber =0;
check=frameLPerc;
while check<1
check = check+frameshPerc;
frameNumber=frameNumber+1;
end
start = 1;
% problem part
mFrames = vSignal(round((start:1/samplingRate:frameLength)*samplingRate));
vTimeFrame = round((start:1/samplingRate:frameLength)*samplingRate);
end
In the end I would like to be able to segment my entire signal into mFrames(i) and vTimeFrame(i) with a for-loop, but never mind that I cannot even get my function to return the first one (like I said empty matrix).
I know my segment code should be correct because I've got another script working with the same vSignal (it's a column vector by the way) that works just fine (y==vSignal):
voiced = y(round((1.245:1/Fs:1.608)*Fs));
plot(1.245:1/Fs:1.608,voiced)
I titled this with syntax problems because I'm very new to matlab and am used to Java. It feels very weird not initializing anything, and so I'm unsure whether my code is actually making any sense.
When testing I enter [m1,m2]=Framing(y,16000,0.1,0.05).
I got it.
start was not in the right domain. This is correct:
round((start/samplingRate:1/samplingRate:frameLength)*samplingRate)
When I plot(m2,m1) I now get the correct answer.
I do still have another question though, how can I assign these segments to my matrices?
for i=1:frameNumber
mFrames(:,i) = vSignal(round((start/samplingRate:1/samplingRate:frameLength)*samplingRate));
vTimeFrame(i) = round((start/samplingRate:1/samplingRate:frameLength)*samplingRate);
start=start+frameShift;
frameLength=frameLength+frameShift;
end
I get this error
In an assignment A(I) = B, the number of elements in B and I must be the same.
Like I said I'm trying to get the y-axis numbers in columns next to each other and the x-axis in rows.

Matlab Parse Error with a simple parenthesis?

I'm trying to finish a program and for some reason, the matrix I loaded into Matlab is messing with the ability to select the rows inside it. I'm trying to select all the rows in the matrix and see which values match the criteria for a Live setting. However I can select specific values/sections of the matrix in the command window without issue. Why is this happening? Any ideas?
It appears to only happen when in a for loop, I can do it just fine when it's on its own.
The syntax is: for x = start:stop. I think you are trying to do a for to the whole "A" matrix. You can split "A", according to its format (e.g. if is a table split in two variables).
bye
Richardd is right on; you're trying to iterate on a matrix, no good.
If I read you right, you're trying to run through your A matrix one column at a time, and see all the rows in that column? Assuming that is correct...
Your A matrix is 14x3, so you should go through your for loop 3 times, which is the size of your column dimension. Luckily, there is a function that MATLAB gives you to do just that. Try:
for iColumn = 1:size(A,2)
...
end
The size function returns the size of your array in a vector of [rows, columns, depth...] - it will go as many dimensions as your array. Calling size(A,2) returns only the size of your array in the column dimension. Now the for loop is iterating on columns.

Filter on words in Matlab tables (as in Excel)

In Excel you can use the "filter" function to find certain words in your columns. I want to do this in Matlab over the entire table.
Using the Matlab example-table "patients.dat" as example; my first idea was to use:
patients.Gender=={'Female'}
which does not work.
strcmp(patients.Gender,{'Female'})
workd only in one column ("Gender").
My problem: I have a table with different words say 'A','B','bananas','apples',.... spread out in an arbitrary manner in the columns of the table. I only want the rows that contain, say, 'A' and 'B'.
It is strange I did not find this in matlab "help" because it seems basic. I looked in stackedO but did not find an answer there either.
A table in Matlab can be seen as an extended cell array. For example it additionally allows to name columns.
However in your case you want to search in the whole cell array and do not care for any extra functionality of a table. Therefore convert it with table2cell.
Then you want to search for certain words. You could use a regexp but in the examples you mention strcmp also is sufficient. Both work right away on cell arrays.
Finally you only need to find the rows of the logical search matrix.
Here the example that gets you the rows of all patients that are 'Male' and in 'Excellent' conditions from the Matlab example data set:
patients = readtable('patients.dat');
patients_as_cellarray = table2cell(patients);
rows_male = any(strcmp(patients_as_cellarray, 'Male'), 2); % is 'Male' on any column for a specific row
rows_excellent = any(strcmp(patients_as_cellarray, 'Excellent'), 2); % is 'Excellent' on any column for a specific row
rows = rows_male & rows_excellent; % logical combination
patients(rows, :)
which indeed prints out only male patients in excellent condition.
Here is a simpler, more elegant syntax for you:
matches = ((patients.Gender =='Female') & (patients.Age > 26));
subtable_of_matches = patients(matches,:);
% alternatively, you can select only the columns you want to appear,
% and their order, in the new subtable.
subtable_of_matches = patients(matches,{'Name','Age','Special_Data'});
Please note that in this example, you need to make sure that patients.Gender is a categorical type. You can use categorical(variable) to convert the variable to a categorical, and reassign it to the table variable like so:
patients.Gender = categorical(patiens.Gender);
Here is a reference for you: https://www.mathworks.com/matlabcentral/answers/339274-how-to-filter-data-from-table-using-multiple-strings

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.

Plotting multiple time series using VPlotContainers in Chaco. Limit to the number of VPlotContainer objects you can use

I wish to plot multiple time series data stored in a NumPy array, in the same plot but with each time series offset, so effectively it has it's own Y axis. I figured the best way to do this may be to put each series in a separate VPlotContainer, but when I call the configure_traits() call I am just getting a blank window. Is the issue that I have too many time series for the machinery to handle?
class EEGPlot(HasTraits):
plot = Instance(VPlotContainer)
traits_view = View(
Item('plot',editor=ComponentEditor(), show_label=False),
width=1024, height=768, resizable=True, title="EEG Preview")
def __init__(self, eegObject):
super(EEGPlot, self).__init__()
x = xrange(eegObject.windowStart, eegObject.windowEnd)
plotNames = {}
allPlots = []
for idx, column in enumerate(eegObject.data[:,:].transpose()): # only included indexes to indicate array dimensions
y = column
plotdata = ArrayPlotData(x=x, y=y)
myplot = Plot(plotdata)
myplot.plot(("x", "y"), type="line", color="blue")
plotNames["plot{0}".format(idx)] = myplot
allPlots.append(plotNames["plot{0}".format(idx)])
container = VPlotContainer(*allPlots)
container.spacing = 0
self.plot = container
So my EEGObject is a NumPy array with 2 dimensions. Around 1500(row) by 65(col). I am wondering if I getting the blank screen because I am doing something wrong or if I am just giving it too many containers?
The answer appears to be that I was using the wrong tools to try and achieve what I needed. VPlotContainers are for separating distinct plots (most likely from different data sources even) within a main display container.
When I fed a test array into the code in the original question that only had 5 columns, then each column plotted in a separate container, but when I increased the columns to above 6 then the UI window would appear blank.
So I guess the answer is that yes, there would appear to be a limit to the number of VPlotContainers you can use, but I don't know if this limit is absoloute or bound by the space dedicated to the main UI window or what.
Either way, using VPlotContainers is not an appropriate technique to display multiple time series data. The correct object would be a MultiLinePlot if you wish the lines to be separated, or an OverlayPlotContainer.
http://docs.enthought.com/chaco/user_manual/plot_types.html#multi-line-plot
I am also having issues using MultiLinePlot, but have moved this question to a separate thread here:
Chaco MultiLinePlot - unable to get simple plot to display, wondering if package broken?