integration of multidimensional data (matlab) - performance

I have a (somewhat complicated expression) in three dimensions, x,y,z. I'm interested in the cumulative integral over one of them. My best solution thus far is to create a 3D grid, evaluate the expression at every point, then integrate over the third dimension with cumtrapz. This is just a scaled down example of what I'm trying to achieve:
%integration
xvec = linspace(-pi,pi,40);
yvec = linspace(-pi,pi,40);
zvec = 1:160;
[x,y,z] = meshgrid(xvec,yvec,zvec);
f = #(x,y,z) sin(x).*cos(y).*exp(z/80).*cos((x-z/20));
output = cumtrapz(f(x,y,z),3);
%(plotting)
for j = 1:length(output(1,1,:));
surf(output(:,:,j));
zlim([-120,120]);
shading interp
pause(.05);
drawnow;
end
Given the sizes of vectors (x,y~100, z~5000), is this a computationally sensible way to do this?

if this is the function form you want to integrate over,#(x,y,z) sin(x).*cos(y).*exp(z/80).*cos((x-z/20)), x,y,z can be separately integrated and the integral can be analytically solved using complex number by replacing sin(x)=(exp(ix)-exp(ix))/2i, and cos(x)=(exp(ix)+exp(ix))/2, which will greatly reduce the time cost of your calculation

Related

Repeatedly interpolating from scattered to regular grid with varying sample values

I want to do scattered interpolation in Matlab, but scatteredInterpolant does not do quite what I want.
scatteredInterpolant allows me to provide a set of input sampling positions and the corresponding sample values. Then I can query the interpolated values by supplying a set of positions:
F = scatteredInterpolant(xpos, ypos, samplevals)
interpvals = F(xgrid, ygrid)
This is sort of the opposite of what I want. I already have a fixed set of sample positions, xpos/ypos, and output grid, xgrid/ygrid, and then I want to vary the sample values. The use case is that I have many quantities sampled at the same sampling positions, that should all be interpolated to the same output grid.
I have an idea how to do this for nearest neighbor and linear interpolation, but not for more general cases, in particular for natural neighbor interpolation.
This is what I want, in mock code:
G = myScatteredInterpolant(xpos, ypos, xgrid, ygrid, interp_method)
interpvals = G(samplevals)
In terms of what this means, I suppose G holds a (presumably sparse) matrix of weights, W, and then G(samplevals) basically does W * samplevals, where the weights in the matrix W depends on the input and output grid, as well as the interpolation method (nearest neighbor, linear, natural neighbor). Calculating the matrix W is probably much more expensive than evaluating the product W * samplevals, which is why I want this to be reused.
Is there any code in Matlab, or in a similar language that I could adapt, that does this? Can it somehow be extracted from scatteredInterpolant in reasonable processing time?

different Solutions for ODE45 Matlab

I am going to solve the following nonlinear DE:
Code#1:
tspan1 =t0:0.05:TT;
[t1,y1] = ode45(#(t1,T) ((1-alpha)*Q-sigm*(T.^4))/R, tspan1, t0);
h1=(TT-t0)/(size(y1,1)-1);
Tspan1=t0:h1:TT;
figure(55);plot(Tspan1,y1,'b');
Code#2:
tspan=[t0 TT];
[t,y] = ode45(#(t,T) ((1-alpha)*Q-sigm*(T.^4))/R, tspan, t0);
h=(TT-t0)/(size(y,1)-1);
Tspan=t0:h:TT;
figure(5);plot(Tspan,y,'b');
wherein:
R=2.912;
Q = 342;
alpha=0.3;
sigm=5.67*(10^(-8));
TT=20;
t0=0;
why the results are different?
The second result is not equally spaced. It in some way a minimal set of points that represents the solution curve. So if the curve is rather linear, there will be only few points, while at regions of high curvature you get a dense sampling. You can and should use the returned time array, as that contains the times that the solution points are for,
figure(55);plot(t1,y1,'b');
figure(5);plot(t,y,'b');

Automatically choose x locations of scatter plot in front of bar graph

I'd like an algorithm to organize a 2D cloud of points in front of a bar graph so that a viewer could easily see the spread of the data. The y location of the point needs to be equal/scaled/proportional to the value of the data, but the x location doesn't matter and would be determined by the algorithm. I imagine a good strategy would be to minimize overlap among the points and center the points.
Here is an example of such a plot without organizing the points:
I generate my bar graphs with points in front of it with MATLAB, but I'm interested just in the best way to choose the x location values of the points.
I have been organizing the points by hand afterwards in Adobe Illustrator, which is time-consuming. Any recommendations? Is this a sub-problem of an already solved problem? What is this kind of plot called?
For high sample sizes, I imagine something like the following would be better than a cloud of points.
I think, mathematically, starting with some array of y-values, it would maximize the sum of the difference between every element from every other element, inversely scaled by the distance between the elements, by rearranging the order of the elements in the array.
Here is the MATLAB code I used to generate the graph:
y = zeros(20,6);
yMean = zeros(1,6);
for i=1:6
y(:,i) = 5 + (8-5).*rand(20,1);
yMean(i) = mean(y(:,i));
end
figure
hold on
bar(yMean,0.5)
for i=1:6
x = linspace(i-0.3,i+0.3,20);
plot(x,y(:,i),'ro')
end
axis([0,7,0,10])
Here is one way that determines x-locations based on grouping into (histogram) bins. The result is similar to e.g. the plot in https://stackoverflow.com/a/1934882/4720018, but retains the original y-values. For convenience the points are sorted, but they could be displayed in order of appearance using the bin_index. Whether this is "the best way" of choosing the x-coordinates depends on what you are trying to achieve.
% Create some dummy data
dummy_data_y = 1+0.1*randn(10,3);
% Create bar plot (assuming you are interested in the mean)
bar_obj = bar(mean(dummy_data_y));
% Obtain data size info
n = size(dummy_data_y, 2);
% Algorithm that creates an x vector for each data column
sorted_data_y = sort(dummy_data_y, 'ascend'); % for convenience
number_of_bins = 5;
for j=1:n
% Get histogram information
[bin_count, ~, bin_index] = histcounts(sorted_data_y(:, j), number_of_bins);
% Create x-location data for current column
xj = [];
for k = 1:number_of_bins
xj = [xj 0:bin_count(k)-1];
end
% Collect x locations per column, scale and translate
sorted_data_x(:, j) = j + (xj-(bin_count(bin_index)-1)/2)'/...
max(bin_count)*bar_obj.BarWidth;
end
% Plot the individual data points
line(sorted_data_x, sorted_data_y, 'linestyle', 'none', 'marker', '.', 'color', 'r')
Whether this is a good way to display your data remains open to discussion.

Fitting of a sphere using SVD/LMS

I would like to fit a MR binary data of 281*398*104 matrix which is not a perfect sphere, and find out the center and radius of sphere and error also. I know LMS or SVD is a good choice to fit for sphere.
I have tried sphereFit from matlab file exchange but got an error,
>> sphereFit(data)
Warning: Matrix is singular to working precision.
> In sphereFit at 33
ans =
NaN NaN NaN
Would you let me know where is the problem, or any others solution?
If you want to use sphere fitting algorithm you should first extract the boundary points of the object you assume to be a sphere. The result should be represented by a N-by-3 array containing coordinates of the points. Then you can apply sphereFit function.
In order to obtain boundary point of a binary object, there are several methods. One method is to apply morphological erosion (you need the "imerode" function from the image processing toolbox) with small structuring element, then compute set difference between the two images, and finally use the "find" function to transform binary image into a coordinate array.
the idea is as follow:
dataIn = imerode(data, ones([3 3 3]));
bnd = data & ~data2;
inds = find(bnd);
[y, x, z] = ind2sub(size(data), inds); % be careful about x y order
points = [x y z];
sphere = sphereFitting(points);
By the way, the link you gave refers to circle fitting, I suppose you wanted to point to a sphere fitting submission?
regards,

Matlab mode filter for dependent RGB channels

I've been performing a 2D mode filter on an RGB image by running medfilt2 independently on the R,G and B channels. However, splitting the RGB channels like this gives artifacts in the colouring. Is there a way to perform the 2D median filter while keeping RGB values 'together'?
Or, I could explain this more abstractly: Imagine I had a 2D matrix, where each value contained a pair of index coordinates (i.e. a cell matrix of 2X1 vectors). How would I go about performing a median filter on this?
Here's how I can do an independent mode filter (giving the artifacts):
r = colfilt(r0,[5 5],'sliding',#mode);
g = colfilt(g0,[5 5],'sliding',#mode);
b = colfilt(b0,[5 5],'sliding',#mode);
However colfilt won't work on a cell matrix.
Another approach could be to somehow combine my RGB channels into a single number and thus create a standard 2D matrix. Not sure how to implement this, though...
Any ideas?
Thanks for your help.
Cheers,
Hugh
EDIT:
OK, so problem solved. Here's how I did it.
I adapted my question so that I'm no longer dealing with (RGB) vectors, but (UV) vectors. Still essentially the same problem, except that my vectors are 2D not 3D.
So firstly I load the individual U and V channels, arrange them each into a 1D list, then combine them, so I essentially have a list of vectors. Then I reduce it to just those which are unique. Then, I assign each pixel in my matrix the value of the index of that unique vector. After this I can do the mode filter. Then I basically do the reverse, in that I go through the filtered image pixelwise, and read the value at each pixel (i.e. an index in my list), and find the unique vector associated with that index and insert it at that pixel.
% Create index list
img_u = img_iuv(:,:,2);
img_v = img_iuv(:,:,3);
coordlist = unique(cat(2,img_u(:),img_v(:)),'rows');
% Create a 2D matrix of indices
img_idx = zeros(size(img_iuv,1),size(img_iuv,2),2);
for y = 1:length(Y)
for x = 1:length(X)
coords = squeeze(img_iuv(x,y,2:3))';
[~,idx] = ismember(coords,coordlist,'rows');
img_idx(x,y) = idx;
end
end
% Apply the mode filter
img_idx = colfilt(img_idx,[n,n],'sliding',#mode);
% Re-construct the original image using the filtered data
for y = 1:length(Y)
for x = 1:length(X)
idx = img_idx(x,y);
try
coords = coordlist(idx,:);
end
img_iuv(x,y,2:3) = coords(:);
end
end
Not pretty but it gets the job done. I suppose this approach would also work for RGB images, or other similar situations.
Cheers,
Hugh
I don't see how you can define the median of a vector variable. You probably need to reduce the R,G,B components to a single value and then compunte the median on that value. Why not use the intensity level as that single value? You could do it easily with rgb2gray.

Resources