Insert a plot image inside table in MATLAB - matlab

I'm very new in MATLAB and I'm trying to do the following: I've 5 images and I want to create a table with names and some statistics as columns. In addition, I would like to insert one column in which every cell is the histogram of the images.
My code is this:
Type = {'volto';'volto_jpg'; 'volto_jpg_100';'volto_tiff';'volto_tiff_nocompression'}
Sum_of_diff = [NaN;2531547;280391;0;0]
Medie = cellfun(#mean2,y)
Dev_st = cellfun(#std2,y)
x = table(Type; Sum_of_diff; Medie; Dev_st)
I would like to add a final column where i can view the histogram made with imhist() function.
It could be possible? Of course only for exporting and visualising purposes.

Related

Matlab add string variable as column in table

I'm trying to use YOLOv4 in MATLAB R2022b to carry out detections on all images in a directory, and append results to a text file.
I can append just the detection results to each line, but when I try to add the filename I get this error:
You might have intended to create a one-row table with the character vector '000001.jpg' as one of its variables. To store text data in a table, use a string array or a cell array of character vectors rather than character arrays. Alternatively, create a cell array with one row, and convert that to a table using CELL2TABLE.
I understand that the filename is a string, and the values returned by YOLO are a categorical array, but I don't understand the most efficient way to deal with this.
filesDir = dir("/home/ADL-Rundle-1/img1/");
for k=1:length(filesDir)
baseFileName=filesDir(k).name
fullFileName = fullfile(filesDir(k).folder, baseFileName);
if isfile(fullFileName)
img = imread(fullFileName);
[bboxes,scores,labels] = detect(detector,img);
T = table(baseFileName, labels, bboxes, scores);
writetable(T,'/home/tableDataPreTrained.txt','WriteMode','Append','WriteVariableNames',0);
end
end
The format of results from YOLO is
And I'd like a file with
000001.jpg, 1547.3, 347.35, 355.64, 716.94, 0.99729
000001.jpg, 717.81, 370.64, 76.444, 108.92, 0.61191
000002.jpg, 1, 569.5, 246.49, 147.25,0.56831
baseFileName is a char vector.
The error message is telling you to use a cell array of char vectors:
T = table({baseFileName}, labels, bboxes, scores);
or a string array:
T = table(string(baseFileName), labels, bboxes, scores);
I would use the string array, it's the more modern MATLAB, and the table looks prettier when displayed. But both accomplish the same thing.
Given that labels and the other two variables have multiple rows, you need to replicate the file name that number of times:
frame = repmat(string(baseFileName), size(labels,1), 1);
T = table(frame, labels, bboxes, scores);

how can I reorder my data after AgglomerativeClustering?

I want to do a heatmap after clustering my data rows and data columns to 2 clusters.
I used AgglomerativeClustering(), I did that for my data and my transpose data in order to cluster my columns too.
clustering1 = AgglomerativeClustering()
clustering1.fit(dataset)
label1 = clustering1.labels_
dataset_t = dataset.T
clustering2 = AgglomerativeClustering()
clustering2.fit(dataset_t)
label2 = clustering2.labels_
I got 2 vectors of 0,1 (2 clusters). And now how I can reorder my data after the clustering and plot a new heatmap?
Like I want a heatmap that we got from using sns.clustermap(data) but without using it.

Changing Matlab Nested Structures to Matrices Iteratively for histogram plotting

Pretty new to Matlab, so please forgive the poor coding. I have some data for different categories (9 categories) with a different number of data points in each category. I created a structure that holds the data points for the different categories. I believe the categories are themselves structures within the larger structure.
I want to plot a histogram for each category. The first thing I tried was just creating a for-loop and plotting a histogram for each category in the structure, but this failed because the histogram doesn't take in structures. The next thing I tried to do was create another for loop which would change the structure holding each category into a cell array, but this also failed with the error:
if isnumeric(c{1}) || ischar(c{1}) || islogical(c{1}) || isstruct(c{1})
I am able to individually change each category to a cell array and then to a matrix, which allowed me to create one histogram. Is there a way to do this using a loop? My code is below. Thanks.
data = readtable('');
data = table2array(data);
Trial = data(:,1);
dist = data(:,2);
Time = data(:,3);
intstim = data(:,4);
color = data(:,5);
UniqueDist = unique(dist);
for ii = 1.0:length(UniqueDist)
idx = find(dist == UniqueDist(ii));
distTime(ii).data = Time(idx);
distTime(ii).data = distTime(ii).data(distTime(ii).data ~= 0);
end
for jj =1.0:length(distTime)
distTime(jj).data = struct2cell(distTime(jj));
distTime(jj).data = cell2mat(distTime(jj));
end

How to use the index of selected data from one figure, to plot something in another figure?

I have a scatter plot on one figure. I'd like to be able to select possibly multiple data points on the mentioned scatter plot, and plot a (possibly) multi-line timeseries chart on the other figure, based on the indexes of the selected data.
Pseudo code:
data = { x: [1,2,3], y: [1,2,3], time_series: [[1,2,3],[4,5,6],[7,8,9]] }
figure1 = scatter_plot(x, y, select_enabled=True)
figure2 = multi_line_timeseries(figure1.indexes_of_selected_points)
show([figure1, figure2])
So if the [1,1] data point (index 0) is selected on figure 1, then the [1,2,3] timeseries (index 0) is plotted on figure 2. If multiple points are selected, then multiple timeseries are plotted.
A restraint is that the HoloViews library can't be used, due to it not supporting my platform.
How can this be achieved?
Note: I have opted to not support simultaneous multiple timeseries plotting, though that would be a trivial extension of this.
To use selected data point's index to determine what is to be plotted in another figure, you need to:
put the relevant data (i.e. x,y,timeseries in the example) on one or multiple ColumnDataSources;
I put the data to select and data that will be updated on different cds's, because I fear it might create a callback loop, though I've not tested this.
create a ColumnDataSource which will act as source for the second figure that plots the timeseries;
enable a selection tool, for example TapTool ('tap');
add a CustomJS callback to the ColumnDataSource that holds the selectable data points;
parametrize that callback with the ColumnDataSource that holds the timeseries data;
have the callback access indeces of selected data points;
have the callback make required changes to the second figure's ColumnDataSource;
call cds_of_2nd_figure.change.emit() before returning from the callback.
Code to illustrate:
cds = ColumnDataSource(data=dict(x=x,y=y,timeseries=timeseries))
cds2 = ColumnDataSource(x_to_plot=[],u_to_plot=[])
def selection_callback(d=cds,d2=cds2):
last_selected_ix = cb_obj.selected.indices[0]
timeserie = d.data['timeseries'][last_selected_ix]
x_to_plot = timeserie['x']
y_to_plot = timeserie['y']
d2.data['x_to_plot'] = x_to_plot
d2.data['y_to_plot'] = y_to_plot
d2.changes.emit()
# turn above function to js
selection_callback = CustomJS.from_py_func( selection_callback )
cds.callback = selection_callback
When some figure selects data from cds, the timeseries[ix] timeserie will be plotted on the figure/s that plot cds2, where ix is the index of the last selected data point from cds.
Relevant resource that has all the relevant information:
https://docs.bokeh.org/en/latest/docs/user_guide/interaction/callbacks.html#customjs-for-tools

Plotting arrays from a cell list of strings

Suppose I have different rows loaded from a .mat file (using load filename.mat) containing float numbers following the same naming convention, e.g:
file_3try = [ 2.4, 5.2, 7.8 ]
file_4try = [ 8.7, 2.5, 4,2 ]
file_5try = [ 11.2, 9.11 ]
to plot all of these in one plot using automation (I have many more rows than in the example above) I created a cell containing the names of the arrays by using:
name{l} = sprintf('%s%02i%s','file_',num,'try');
inside a for loop with num the numbers in the names and l a counter starting from 1.
But when I try to plot the arrays using for example:
plot(name{1})
I get the error:
Error using plot
Invalid first data argument
Is there a way to solve this, or am I going about this wrong?
There is something built in to solve this
data = load ( 'filename' ); % load data and store in struct
fnames = fieldnames ( data );
for ii=1:length(fnames)
plot ( axHandle, data.(fnames{ii}) );
end
axHandle is a handle to the axes you want to plot on. Its not required but it is good practice to use it. If its not provided then the plot command will plot on the current axes, e.g. gca.
So as mentioned already you need to use eval.
Assuming the file_**X**try rows are different lengths then you could just place all of them in a cell rather than creating a cell of the variable names. So instead of assigning to separate variables the way you are doing you could assign to a cell, so:
file_try{i} = [.....];
You can then cycle through file_try and plot each entry:
for i = 1:length(file_try)
plot(file_try{i});
end
If the rows are not different lengths then stick them in a matrix and plot it.