Surface plot using multiple excel files - matlab

I'm just a beginner with MATLAB.
I need to represent my data using a 3D plot. I tried using the surf function but in my case this is a little bit tricky. From the code you will see that I am looping through multiple excel files to extract data from it.
Using a 3-dimensional plot I need to represent my Fv array as the 'X' coordinate, my FTsiga as the 'Y' coordinate and the the third coordinate should be each excel file that I am looping through.
A plot of (Fv,FTsiga) looks like the figure that is attached herewith.
Fv(x-axis) , FTsiga(y-axis)
The code that I have written so far couldn't seem to execute because MATLAB crashed due to insufficient memory or because it got stuck in a loop. The latter is more likely I guess.
% Matlab trial code: Trying to loop through excel files strored in directory
source_dir = 'C:\UTwente\Q4\Structural Health and Condition monitoring\Case Roadbridge (Zwartewaterbrug)\Excel data'
source_files = dir(fullfile(source_dir, '*xlsx'));
len = length(source_files);
matrix = zeros(len,32);
X = zeros(len,32); Y = zeros(len,32); Z = zeros(len,32);
%looping through excel file in directory
for i=1:len
data= xlsread(source_files(i).name,'Measurement data');
for j=1:32
sig = data(:,j);
sig = sig - mean(sig); % Remove d-c Offset
L = length(sig);
Fs = 1000; % Sampling Frequency
Fn = Fs/2; % Nyquist Frequency
FTsig = fft(sig)/L;
Fv = linspace(0, 1, fix(length(FTsig)/2)+1)*Fn; % Frequency Vector
Iv = 1:length(Fv); % Index Vector
FTsiga = double(abs(FTsig(Iv))*2); % Truncate, Magnitude, Convert To Double
sgf_sm = sgolayfilt(FTsiga, 5, 501); % Create ‘sgolayfilt’ Filtered FFT
[~, idx] = max( sgf_sm ); % Getting the value of the modal frequency
peakfreq = Fv( idx );
matrix(i,j) = peakfreq; % Matrix of all peak frequencies
[X,Y,Z] = meshgrid(Fv,FTsiga,i);
end
surf(Fv,FTsiga,i);
end

Related

Producing a histogram in Matlab with out using Hist

I am using histograms in Matlab to look at the distribution of some data from my experiments. I want to find the mean distribution (mean height of the bars) from a group of tests then produce an average histogram.
By using this code:
data = zeros(26,31);
for i = 1:length(files6)
x = csvread(files6(i).name);
x = x(1:end,:);
time = x(:,1);
variable = x(:,3);
thing(:,1) = x(:,1);
thing(:,2) = x(:,3);
figure()
binCenter = {0:tbinstep:tbinend 0:varbinstep:varbinend};
hist3(thing, 'Ctrs', binCenter, 'CDataMode','auto','FaceColor','interp');
colorbar
[N,C] = hist3(thing, 'Ctrs', binCenter);
data = data + N;
clearvars x time variable
end
avedata = data / i;
I can find the mean of N, which will be the Z value for the plot (histogram) I want, and I have X,Y (which are the same for all tests) from:
x = 0:tbinstep:tbinend;
y = 0:varbinstep:varbinend;
But how do I bring these together to make the graphical out that shows the average height of the bars? I can't use hist3 again as that will just calculate the distribution of avedata.
AT THE RISK OF STARTING AN XY PROBLEM using bar3 has been suggested, but that asks the question "how do I go from 2 vectors and a matrix to 1 matrix bar3 can handle? I.e. how do I plot x(1), y(1), avedata(1,1) and so on for all the data points in avedata?"
TIA
By looking at hist3 source code in matlab r2014b, it has his own plotting implemented inside that prepares data and plot it using surf method. Here is a function that reproduce the same output highly inspired from the hist3 function with your options ('CDataMode','auto','FaceColor','interp'). You can put this in a new file called hist3plot.m:
function [ h ] = hist3plot( N, C )
%HIST3PLOT Summary of this function goes here
% Detailed explanation goes here
xBins = C{1};
yBins = C{2};
% Computing edges and width
nbins = [length(xBins), length(yBins)];
xEdges = [0.5*(3*xBins(1)-xBins(2)), 0.5*(xBins(2:end)+xBins(1:end-1)), 0.5*(3*xBins(end)-xBins(end-1))];
yEdges = [0.5*(3*yBins(1)-yBins(2)), 0.5*(yBins(2:end)+yBins(1:end-1)), 0.5*(3*yBins(end)-yBins(end-1))];
xWidth = xEdges(2:end)-xEdges(1:end-1);
yWidth = yEdges(2:end)-yEdges(1:end-1);
del = .001; % space between bars, relative to bar size
% Build x-coords for the eight corners of each bar.
xx = xEdges;
xx = [xx(1:nbins(1))+del*xWidth; xx(2:nbins(1)+1)-del*xWidth];
xx = [reshape(repmat(xx(:)',2,1),4,nbins(1)); NaN(1,nbins(1))];
xx = [repmat(xx(:),1,4) NaN(5*nbins(1),1)];
xx = repmat(xx,1,nbins(2));
% Build y-coords for the eight corners of each bar.
yy = yEdges;
yy = [yy(1:nbins(2))+del*yWidth; yy(2:nbins(2)+1)-del*yWidth];
yy = [reshape(repmat(yy(:)',2,1),4,nbins(2)); NaN(1,nbins(2))];
yy = [repmat(yy(:),1,4) NaN(5*nbins(2),1)];
yy = repmat(yy',nbins(1),1);
% Build z-coords for the eight corners of each bar.
zz = zeros(5*nbins(1), 5*nbins(2));
zz(5*(1:nbins(1))-3, 5*(1:nbins(2))-3) = N;
zz(5*(1:nbins(1))-3, 5*(1:nbins(2))-2) = N;
zz(5*(1:nbins(1))-2, 5*(1:nbins(2))-3) = N;
zz(5*(1:nbins(1))-2, 5*(1:nbins(2))-2) = N;
% Plot the bars in a light steel blue.
cc = repmat(cat(3,.75,.85,.95), [size(zz) 1]);
% Plot the surface
h = surf(xx, yy, zz, cc, 'CDataMode','auto','FaceColor','interp');
% Setting x-axis and y-axis limits
xlim([yBins(1)-yWidth(1) yBins(end)+yWidth(end)]) % x-axis limit
ylim([xBins(1)-xWidth(1) xBins(end)+xWidth(end)]) % y-axis limit
end
You can then call this function when you want to plot outputs from Matlab's hist3 function. Note that this can handle non uniform positionning of bins:
close all; clear all;
data = rand(10000,2);
xBins = [0,0.1,0.3,0.5,0.6,0.8,1];
yBins = [0,0.1,0.3,0.5,0.6,0.8,1];
figure()
hist3(data, {xBins yBins}, 'CDataMode','auto','FaceColor','interp')
title('Using hist3')
figure()
[N,C] = hist3(data, {xBins yBins});
hist3plot(N, C); % The function is called here
title('Using hist3plot')
Here is a comparison of the two outputs:
So if I understand your question and code correctly, you are plotting the distribution of multiple experiments' data as histograms, then you want to calculate the average shape of all the previous histograms.
I usually avoid giving approaches the asker isn't explicitly asking for, but for this one I must comment that it is a very strange thing to do. I've never heard of calculating the average shape of multiple histograms before. So just in case, you could simply append all your experiment's data into a single variable, and plot a normalized histogram of that using histogram2. This code outputs a relative frequency histogram. (Other normalization methods)
% Append all data in a single matrix
x = []
for i = 1:length(files6)
x = [x; csvread(files6(i).name)];
end
% Plot normalized bivariate histogram, normalized
xEdges = 0:tbinstep:tbinend;
yEdges = 0:varbinstep:varbinend;
histogram2(x(:,1), x(:,3), xEdges, yEdges, 'Normalize', 'Probability')
Now, if you really are looking to draw the average shape of multiple histograms, then yes, use bar3. Since bar3 doesn't accept an (x,y) value argument, you can follow the other answer, or modify the XTickLabel and YTickLabel property to match whatever your bin range is, afterwards.
... % data = yourAverageData;
% Save axis handle to `h`
h = bar3(data);
% Set property of axis
h.XTickLabels = 0:tbinstep:tbinend;
h.YTickLabels = 0:varbinstep:varbinend;

How can I generate CDF from a large dataset in MATLAB?

I have 6 datasets each containing 10000 entries.
I want to plot their CDFs for comparison.
In MATLAB I am using the following code:
figure()
ksdensity(dataset1,'Support','positive','Function','cdf',...
'NumPoints',5)
xlabel('Error')
ylabel('CDF')
But I am not sure, is it the right way or wrong?
How can I do that?
I am getting the following figure.
Update:
This has been made even easier with cdfplot().
% MATLAB R2019a
% Example Data
X = wblrnd(2,3,50000,1);
Y = wblrnd(3,2,50000,1);
Z = wblrnd(2.5,2.5,50000,1);
Data = [X Y Z];
figure, hold on
for k = 1:size(Data,2)
h(k) = cdfplot(Data(:,k));
end
legend('show')
It looks like you've got the result you want except for the legend and markers. If you'd like more control of the plotting features, I'd suggest obtaining the necessary elements to plot from ksdensity using [f,xi] = ksdensity(x) then plotting separately.
% MATLAB R2019a
% Example Data
X = wblrnd(2,3,50000,1);
Y = wblrnd(3,2,50000,1);
Z = wblrnd(2.5,2.5,50000,1);
Data = [X Y Z];
NumPointCDF = 5; % Number of points to estimate CDF with
figure, hold on
for ii = 1:size(Data,2) % for each column of Data
[fii, xii] = ksdensity(Data(:,ii),'Support','positive','Function','cdf',...
'NumPoints',NumPointsCDF);
p(ii) = plot(xii,fii,'LineWidth',1.1,'Marker','.','MarkerSize',12);
end
legend('X','Y','Z')
Alternatively, you could just plot each first,
figure, hold on
for ii = 1:size(Data,2) % for each column of Data
[fii, xii] = ksdensity(Data(:,ii),'Support','positive','Function','cdf',...
'NumPoints',NumPointsCDF);
p(ii) = plot(xii,fii);
end
and then change the properties of each line later with p(1).foo (see here).
For example, one at a time: p(1).Marker = 's' % square
Or all at once:
% Update all properties using the object
for ii = 1:size(Data,2)
p(ii).Marker = '.'; % Adjust specific properties of p(ii) as needed
p(ii).LineWidth = 1.2;
end
Reference:
Graphics Object Properties
Access Property Values

Plotting FFT fails due to vectors not having the same length

I have a csv data of time(1st column) and current amplitude(2nd column). I want to plot FFT of the current. This is actually simulation data over 30ns and data step was 1ps. I can plot the current vs Time in MATLAB. But while doing FFT function, It is not plotting at all as it says
Error using plot
Vectors must be the same length.
Error in FFT_Ideal_current_maxstep_1ps (line 25).
plot(f,Y)
Can anyone help me? I have attached the MATLAB code and the CSV file as well.
I also want to plot the power spectral density. It would be nice if anyone can help. I want to get the FFT and psd over 2GHz or more frequency spectrum range
MATLAB code1:
% open data file
fid = fopen('current_maxstep_1ps.csv');
% Read data in from csv file
readData = textscan(fid,'%f %f','Headerlines',1,'Delimiter',',');
% Extract data from readData
t = readData{1,1}(:,1);
x = readData{1,2}(:,1);
N = length(x);
ts = 0.000000000001;
Fs = 1/ts;
tmax = (N-1)*ts;
tm = 0:ts:tmax;
f = 0:Fs/(N-1):Fs/2;
y = fftshift(fft(x));
Y = abs(y);
plot(f,Y)
Also there is another MATLAB code I tried which plots (here is the picture: FFT picture of code 2) but showing in time domain and I want frequency spectrum like spikes of apmlitudes along the frequency spectrum.
MATLAB Code2:
% open data file
fid = fopen('Ideal_current_maxstep_1ps.csv');
% Read data in from csv file
readData = textscan(fid,'%f %f','Headerlines',1,'Delimiter',',');
% Extract data from readData
xData = readData{1,1}(:,1);
yData = readData{1,2}(:,1);
Ts = 1e-12;
Fs = 1/Ts;
%Fs = 1000;
%Ts = 1/Fs;
X = fft(yData);
plot(xData, abs(X))
The problem is that the length of f and Y are not the same. You can check it using length(f) and length(Y). The reason is that fft also calculates the negative frequencies. Therefore, you should define f as follows:
f = -Fs/2:Fs/(N-1):Fs/2;
Note that the fft is conjugate symmetric, because the input data is real.
You can limit the plotted frequency range using the xlim command as follows:
xlim([0 3*10^9]) % limit x range between 0Hz and 3GHz

Fitting Probability distribution function in eac histogram for each bin data using matlab.....?

I have x data and I did binning and created histogram of each bin.Now I want to fit the probability distribution function in each bin so I can see histogram and probability distribution function at the same graph. Here 'X' is in horizontal axis data and 'Y' represent vertical axis data of the same datasets. I have written the code below
X = load data1 ; Y = load data2
topEdge = 10; % upper limit
botEdge = 0;
numBins = 20;
binEdges = linspace(botEdge, topEdge, numBins+1);
[h,whichBin] = histc(X, binEdges)
% Histrogram plot of each bin
for i = 1:numBins
flagBinMembers = (whichBin == i); %Creates vector of the indices of the data entries that are in bin i
BinMean(i) = mean(power_ref(flagBinMembers)); %Calculate mean value in this bin
BinStd(i) = std(power_ref(flagBinMembers));
x = power_ref(flagBinMembers) - BinMean(i);
mu = power_ref(flagBinMembers)- BinMean(i); sigma =power_ref(flagBinMembers)- BinStd(i);
figure();
histogram(x, 'Normalization', 'pdf')
hold on;
Y = normpdf(x,mu,sigma);
plot(x,Y);
hold off
end
After running this code I am not getting the fitted 'pdf' and histogram on same curve. I correctly got histogram but not 'pdf'. Can any one suggest me or help me ....?? Thank you for your such patient for reading this !
I am getting such curve output : output of first bin Output of 2nd bin
As you can see histogram and pdf not fitting. Where I am making mistake...??

Using Optimization algorithm for white matter fiber tracking

Actually I use MATLAB code to implement my work which it's summarize as a following:
I used a program applied the Bayesian approach to solve fiber tracking, I have a problem in load the dataset, which it's Medical Image. I need any hint to help me to open this data set to continue my work. the following code shows the load dataset function:
function data = Load_DMRI_Data(dataset)
% Load diffusion tensor MRI data and return it in
% a structure together with gradients and b-values.
% The data must be stored in a data structure for further
% processing, see code.
% The gradients are stored as a(3xg) matrix, where g is the
% number of acquired DWI volumens (including the b=0 ones).
% The b-values are stored in a corresponding (1xg) vector.
if strcmp(dataset,'gordon')
readdir = '/projects/lmi/data/diffusion/gk-3t/041020-02156-bvalexpr/data/003/';
intensity = zeros(256,256,31,32);
for g = 1:32
for slice = 1:31
fid = fopen(sprintf('%sI.%03d',readdir,(g-1)*31+slice),'r');
im = fread(fid,'int16');
im = im(end-256^2+1:end);
intensity(:,:,slice,g) = reshape(im,[256 256])';
fclose(fid);
end
end
G = load('gradients.mat');
G = [[1;1;1] G.g]; % Add arbitrary gradient direction for b=0
b = [0 1000*ones(1,31)];
data = struct('intensity',intensity,'G',G,'b',b,'FOV',240,'SliceThickness',4);
elseif strcmp(dataset,'pc')
readdir = 'c:\Work\DiffusionData\';
intensity = zeros(256,256,1,32);
for g = 1:32
for slice = 16:16 % Use slice 16 as test slice
fid = fopen(sprintf('%sI.%03d',readdir,(g-1)*31+slice),'r','ieee-be');
im = fread(fid,'int16');
im = im(end-256^2+1:end);
intensity(:,:,slice-15,g) = reshape(im,[256 256])';
fclose(fid);
end
end
G = load(sprintf('%sgradients.mat',readdir));
G = [[1;1;1] G.g]; % Add arbitrary gradient direction for b=0
b = [0 1000*ones(1,31)]; % b-values
data = struct('intensity',intensity,'G',G,'b',b);
end
The website for dataset : http://www.sci.utah.edu/~gk/DTI-data/