Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
I am given the following data:
and I am asked to calculate the integral of Cp/T dT from 113.7 to 264.4.
I am unsure of how I should solve this. If I want to use the integral command, I need a function, but I don't know how my function should be in that case.
I have tried:
function func = Cp./T
T = [...]
Cp=[...]
end
but that didn't work.
Use the cumtrapz function in MATLAB.
T = [...]
Cp=[...]
CpdivT = Cp./T
I = cumtrapz(T, CpdivT)
You can read more about the function at https://www.mathworks.com/help/matlab/ref/cumtrapz.html
A simple approach using interp1 and integral using plain vanilla settings.
Would only use more sophisticated numerical techniques if required for application. You can examine the 'RelTol' and 'AbsTol' options in the documentation for integral.
Numerical Integration: (w/ linear interpolation)
% MATLAB R2017a
T = [15 20 30 40 50 70 90 110 130 140 160 180 200 220 240 260 270 275 285 298]';
Cp = [5.32 10.54 21.05 30.75 37.15 49.04 59.91 70.04 101.59 103.05 106.78 ...
110.88 114.35 118.70 124.31 129.70 88.56 90.07 93.05 96.82]';
fh =#(t) interp1(T,Cp./T,t,'linear');
t1 = 113.7;
t2 = 264.4;
integral(fh,t1,t2)
ans = 91.9954
Alternate Methods of Interpolation:
Your results will depend on your method of interpolation (see code & graphic below).
% Results depend on method of interpolation
Linear = integral(#(t) interp1(T,Cp./T,tTgts,'linear'),t1,t2) % = 91.9954
Spline = integral(#(t) interp1(T,Cp./T,tTgts,'spline'),t1,t2) % = 92.5332
Cubic = integral(#(t) interp1(T,Cp./T,tTgts,'pchip'),t1,t2) % = 92.0383
Code for graphic:
tTgts = T(1):.01:T(end);
figure, hold on, box on
p(1) = plot(tTgts,interp1(T,Cp./T,tTgts,'linear'),'b-','DisplayName','Linear')
p(2) = plot(tTgts,interp1(T,Cp./T,tTgts,'spline'),'r-','DisplayName','Spline')
p(3) = plot(tTgts,interp1(T,Cp./T,tTgts,'pchip'),'g-','DisplayName','Cubic')
p(4) = plot(T,Cp./T,'ks','DisplayName','Data')
xlim([floor(t1) ceil(t2)])
legend('show')
% Cosmetics
xlabel('T')
ylabel('Cp/T')
for k = 1:4, p(k).LineWidth = 2; end
A poor approximation: (to get rough order of magnitude estimate)
tspace = T(2:end)-T(1:end-1);
midpt = mean([Cp(1:end-1) Cp(2:end)],2);
sum(midpt.*tspace)./sum(tspace)
And you can see we're in the ballpark (makes me feel more comfortable at least).
Other viable MATLAB Functions: quadgk | quad
% interpolation method affects answer if using `interp1()`
quadgk(#(t) interp1(T,Cp./T,t,'linear'),t1,t2)
quad(#(t) interp1(T,Cp./T,t,'linear'),t1,t2)
Functions that would require more work: trapz | cumtrapz
Notice that trapz and cumtrapz both require unit spacing; to use these would require first interpolating with unit spacing.
Related Posts: (found after answer already completed)
Matlab numerical integration
How to numerically integrate vector data in Matlab?
This is probably better for your problem. Take note that I have assumed 2nd order polynomial fits your data well. You may want to get a better model structure if the fit is unsatisfactory.
% Data
T = [15 20 30 40 50 70 90 110 130 140 160 180 200 220 240 260 270 275 285 298];
Cp = [5.32 10.54 21.05 30.75 37.15 49.04 59.91 70.04 101.59 103.05 106.78 110.88 114.35 118.70 124.31 129.70 88.56 90.07 93.05 96.82];
% Fit function using 2nd order polynomial
f = fit(T',Cp'./T','poly2');
% Compare fit to actual data
plot(f,T,Cp./T)
% Create symbolic function
syms x
func = f.p1*x*x + f.p2*x + f.p3;
% Integrate function
I = int(func,113.7,264.4);
% Convert solution from symbolic to numeric value
V = double(I);
The result is 92.7839
Using Octave 4.2.1 on Windows with the qt graphics toolkit (I can't use gnuplot because it crashes in some other part of the code). I have a dataset which is 35x7x4 (35 data points for 7 conditions on 4 channels) - you can use random data for the purpose of this exercise.
I am trying to create 4 subplots (1 for each channel), with 7 bar graphs on each subplot (one per condition) to see how the distribution of data changes with each condition. Each of the 7x4 = 28 distributions has its own set of bins and frequencies, and I can't seem to be able to combine the 7 datasets on one graph (subplot).
Posting the whole of the code would be too complicated, but here's a simplified version:
nb_channels = 4;
nb_conditions = 7;
nbins = 15;
freq = zeros(nbins,nb_conditions,nb_channels);
xbin = zeros(nbins,nb_conditions,nb_channels);
plot_colours = [91 237 165 255 68 112 255;
155 125 165 192 114 173 0;
213 49 165 0 196 71 255];
plot_colours = plot_colours / 255;
for k = 1:nb_channels
for n = 1:nb_conditions
% some complex calculations to generate temp variable
[freq(:,n,k),xbin(:,n,k)] = hist(temp,nbins);
end
end
figure
for k = 1:nb_channels
subplot(2,2,k)
for n = 1:nb_conditions
bar(xbin(:,n,k),freq(:,n,k),'FaceColor',plot_colours(:,n))
hold on
end
hold off
legend('condition #1','condition #2','condition #3','condition #4','condition #5','condition #6','condition #7')
end
which gives something like this:
So you can't really see anything, all the bars are on top of each other. In addition, Octave doesn't support transparency property for patch objects (which is what bar charts use), so I can't overlay the histograms on top of each other, which I would really quite like to do.
Is there a better way to approach this? It seems that bar will only accept a vector for x data and not a matrix, so I am stuck in having to use hold on and loop through the various conditions, instead of using a matrix approach.
OK, so I'll try to answer my own question based on the suggestions made in the comments:
Suggestion 1: make all the bins the same
This does improve the results somewhat but it's still an issue due to the lack of transparency for patch objects.
Code changes:
nbins = 15;
xbin = linspace(5.8,6.5,nbins);
for k = 1:nb_channels
for n = 1:nb_conditions
% some complex calculations to generate temp variable
freq_flow(:,n,k) = hist(temp,xbin);
end
end
figure
for k = 1:nb_channels
subplot(2,2,k)
for n = 1:nb_conditions
bar(xbin,freq_flow(:,n,k),'FaceColor',plot_colours(:,n))
hold on
end
hold off
xlim([5.8 6.3])
legend('condition #1','condition #2','condition #3','condition #4','condition #5','condition #6','condition #7')
end
Which gives the following plot:
Suggestion 2: Use line plots instead of bar charts
This helps a bit more in terms of readability. However, the result is a bit "piece-wise".
Code changes:
figure
for k = 1:nb_channels
subplot(2,2,k)
for n = 1:nb_conditions
plot(xbin,freq_flow(:,n,k),'LineStyle','none','marker','.',...
'markersize',12,'MarkerEdgeColor',plot_colours(:,n),...
'MarkerFaceColor',plot_colours(:,n))
hold on
end
hold off
xlim([5.8 6.3])
legend('condition #1','condition #2','condition #3','condition #4','condition #5','condition #6','condition #7')
end
Which gives the following result:
The legend is a bit screwed but I can probably sort that out.
A variation on this I also tried was to plot just the points as markers, and then a fitted normal distribution on top. I won't post all the code here, but the result looks something like this:
Suggestion 3: transparency workaround with gnuplot
Unfortunately, before I even got to the transparency workaround, gnuplot keeps crashing when trying to plot the figure. There's something it doesn't like with subplots and legends I think (which is why I moved to qt graphics toolkit in the first place, as I had exactly the same issue in other parts of the code).
Solution 4: use 3D bar graph
I found this on SO: 3D histogram with gnuplot or octave
and used it as such:
figure
for k = 1:size(flow_factor,2)
subplot(2,2,k)
h = my_bar3(freq_flow(:,:,k));
fvcd = kron((1:numel(freq_flow(:,:,k)))', ones(6,1));
set(h, 'FaceVertexCData',fvcd, 'FaceColor','flat', 'CDataMapping','scaled')
colormap hsv; axis tight; view(50,25)
ylbl = cell(length(xbin),1);
for k=1:length(xbin)
ylb{k} = num2str(xbin(k));
end
set(gca,'YTick',1:2:nbins);
set(gca,'YTickLabel',ylb(1:2:end));
end
to produce:
Which isn't bad, but probably not as clear as the line plots.
Conclusion
On balance, I will probably end up using one of the line plots approaches, as they tend to be clearer.
Does someone know how to make a graph similar to this one with matlab?
To me it seems like a continuous stacked bar plot.
I did not manage to download the same data so I used other ones.
I tried the following code:
clear all
filename = 'C:\Users\andre\Desktop\GDPpercapitaconstant2000US.xlsx';
sheet = 'Data';
xlRange = 'AP5:AP259'; %for example
A = xlsread(filename,sheet,xlRange);
A(isnan(A))=[]; %remove NaNs
%create four subsets
A1=A(1:70);
A2=A(71:150);
A3=A(151:180);
A4=A(181:end);
edges=80:200:8000; %bins of the distributions
[n_A1,xout_A1] = histc(A1,edges); %distributions of the first subset
[n_A2,xout_A2] = histc(A2,edges);
[n_A3,xout_A3] = histc(A3,edges);
[n_A4,xout_A4] = histc(A4,edges);
%make stacked bar plot
for ii=1:numel(edges)
y(ii,:) = [n_A1(ii) n_A2(ii) n_A3(ii) n_A4(ii)];
end
bar(y,'stacked', 'BarWidth', 1)
and obtained this:
It is not so bad.. Maybe with other data it would look nicer... but I was wondering if someone has better ideas. Maybe it is possible to adapt fitdist in a similar way?
First, define the x axis. If you want it to follow the rules of bar, then use:
x = 0.5:numel(edges)-0.5;
Then use area(x,y), which produces a filled/stacked area plot:
area(x,y)
And if you want the same colors as the example you posted at the top, define the colormap and call colormap as:
map = [
218 96 96
248 219 138
253 249 199
139 217 140
195 139 217
246 221 245
139 153 221]/255;
colormap(map)
(It may not be exactly as the one you posted, but I got it quite close I think. Also, not all colors are shown in the result below as there are only 4 parameters, but all colors are defined)
Result:
I'm trying to unblur the blurred segments of the following picture.
the original PSF was not given, so I proceeded to analyze the blurred part and see whether there was a word I could roughly make out. I found out that I could make out "of" in the blurred section. I cropped out both the the blurred "of" and its counterpart in the clear section, as seen below.
I then thought through lectures in FFT that you divide the blurred (frequency domain) with a particular blurring function (frequency domain) to recreate the original image.
I thought that if I could do Unblurred (frequency domain) \ Blurred(frequency domain), the original PSF could be retrieved. Please advise on how I could do this.
Below is my code:
img = im2double(imread('C:\Users\adhil\Desktop\matlab pics\image1.JPG'));
Blurred = imcrop(img,[205 541 13 12]);
Unblurred = imcrop(img,[39 140 13 12]);
UB = fftshift(Unblurred);
UB = fft2(UB);
UB = ifftshift(UB);
F_1a = zeros(size(B));
for idx = 1 : size(Blurred, 3)
B = fftshift(Blurred(:,:,idx));
B = fft2(B);
B = ifftshift(B);
UBa = UB(:,:,idx);
tmp = UBa ./ B;
tmp = ifftshift(tmp);
tmp = ifft2(tmp);
tmp = fftshift(tmp);
[J, P] = deconvblind(Blurred,tmp);
end
subplot(1,3,1);imshow(Blurred);title('Blurred');
subplot(1,3,2);imshow(Unblurred);title('Original Unblurred');
subplot(1,3,3);imshow(J);title('Attempt at unblurring');
This code, however, does not work, and I'm getting the following error:
Error using deconvblind
Expected input number 2, INITPSF, to be real.
Error in deconvblind>parse_inputs (line 258)
validateattributes(P{1},{'uint8' 'uint16' 'double' 'int16' 'single'},...
Error in deconvblind (line 122)
[J,P,NUMIT,DAMPAR,READOUT,WEIGHT,sizeI,classI,sizePSF,FunFcn,FunArg] = ...
Error in test2 (line 20)
[J, P] = deconvblind(Blurred,tmp);
Is this a good way to recreate the original PSF?
I'm not an expert in this area, but I have played around with deconvolution a little bit and have written a program to compute the point spread function when given a clear image and a blurred image. Once I got the psf function using this program, I verified that it was correct by using it to deconvolve the blurry image and it worked fine. The code is below. I know this post is extremely old, but hopefully it will still be of use to someone.
import numpy as np
import matplotlib.pyplot as plt
import cv2
def deconvolve(normal, blur):
blur_fft = np.fft.rfft2(blur)
normal_fft = np.fft.rfft2(normal)
return np.fft.irfft2(blur_fft/(normal_fft))
img = cv2.imread('Blurred_Image.jpg')
blur = img[:,:,0]
img2 = cv2.imread('Original_Image.jpg')
normal = img2[:,:,0]
psf_real = deconvolve(normal, blur)
fig = plt.figure(figsize=(10,4))
ax1 = plt.subplot(131)
ax1.imshow(blur)
ax2 = plt.subplot(132)
ax2.imshow(normal)
ax3 = plt.subplot(133)
ax3.imshow(psf_real)
plt.gray()
plt.show()
After retrieving image coeffients (both approximate and detailed) in wavelet decomposition, i want quadtree structure for appoximate and detailed coefficients. but every time i am getting same error. Please help.
I tried to make it power of 3 instead of 2 but it coudnt help. may be i am going wrong somehwhere.
code for image decomposition
X=imread('abc.tif');
close all
clf
image(X)
colormap('default')
axis ('image'); set(gca,'XTick',[],'YTick',[]); title('Original')
pause
dwtmode('sym')
wname = 'bior4.4'
t = wtree(X,2,'bior4.4');
plot(t)
pause
close(2)
[wc,s] = wavedec2(X,5,wname);
a1 = appcoef2(wc,s,wname,1);
h1 = detcoef2('h',wc,s,1);
v1 = detcoef2('v',wc,s,1);
d1 = detcoef2('d',wc,s,1);
a2 = appcoef2(wc,s,wname,2);
h2 = detcoef2('h',wc,s,2);
v2 = detcoef2('v',wc,s,2);
d2 = detcoef2('d',wc,s,2);
a3 = appcoef2(wc,s,wname,3);
h3 = detcoef2('h',wc,s,3);
v3 = detcoef2('v',wc,s,3);
d3 = detcoef2('d',wc,s,3);
a4 = appcoef2(wc,s,wname,4);
h4 = detcoef2('h',wc,s,4);
v4 = detcoef2('v',wc,s,4);
d4 = detcoef2('d',wc,s,4);
a5 = appcoef2(wc,s,wname,5);
h5 = detcoef2('h',wc,s,5);
v5 = detcoef2('v',wc,s,5);
d5 = detcoef2('d',wc,s,5);
For quadtree i am using:
S = qtdecomp(I,.27); %I is image in greyscale.
blocks = repmat(uint8(0),size(S));
for dim = [512 256 128 64 32 16 8 4 2 1];
numblocks = length(find(S==dim));
if (numblocks > 0)
values = repmat(uint8(1),[dim dim numblocks]);
values(2:dim,2:dim,:) = 0;
blocks = qtsetblk(blocks,S,dim,values);
end
end
blocks(end,1:end) = 1;
blocks(1:end,end) = 1;
imshow(I), figure, imshow(blocks,[])
the error it is showing is:
??? Error using ==> qtdecomp>ParseInputs at 229
MAXDIM / MINDIM is not a power of 2
Error in ==> qtdecomp at 88
[A, func, params, minDim, maxDim] = ParseInputs(varargin{:});
or
??? Error using ==> qtdecomp>ParseInputs at 145
A must be two-dimensional
Error in ==> qtdecomp at 88
[A, func, params, minDim, maxDim] = ParseInputs(varargin{:});
The error is pretty clear. Your image must have dimensions that belong to a power of two. As such, you need to resize your image so that it follows this. qtdecomp computes the quadtree decomposition algorithm, and a pre-condition for this function is that it NEEDS to have an image that has each dimension as a power of two as input.
You asked something similar in another question that I provided an answer to. What is curious is that this other question you asked was 6 days ago before this one, and you accepted my answer for that other one. The issue that you were experiencing is more or less the same thing.
Quadtree decomposition