Home Ideas for reducing the complexity of a 3D density function for generating a ternary surface plot in Matlab
Reply: 2

Ideas for reducing the complexity of a 3D density function for generating a ternary surface plot in Matlab

Michael Andrew Bentley
1#
Michael Andrew Bentley Published in 2014-10-07 16:35:29Z

I have a 3D density function q(x,y,z) that I am trying to plot in Matlab 8.3.0.532 (R2014a).

The domain of my function starts at a and ends at b, with uniform spacing ds. I want to plot the density on a ternary surface plot, where each dimension in the plot represents the proportion of x,y,z at a given point. For example, if I have a unit of density on the domain at q(1,1,1) and another unit of density on the domain at q(17,17,17), in both cases there is equal proportions of x,y,z and I will therefore have two units of density on my ternary surface plot at coordinates (1/3,1/3,1/3). I have code that works using ternsurf. The problem is that the number of proportion points grows exponentially fast with the size of the domain. At the moment I can only plot a domain of size 10 (in each dimension) with unit spacing (ds = 1). However, I need a much larger domain than this (size 100 in each dimension) and much smaller than unit spacing (ideally as small as 0.1) - this would lead to 100^3 * (1/0.1)^3 points on the grid, which Matlab just cannot handle. Does anyone have any ideas about how to somehow bin the density function by the 3D proportions to reduce the number of points?

My working code with example:

a = 0; % start of domain
b = 10; % end of domain
ds = 1; % spacing

[x, y, z] = ndgrid((a:ds:b)); % generate 3D independent variables
n = size(x);

q = zeros(n); % generate 3D dependent variable with some norm distributed density
for i = 1:n(1)
    for j = 1:n(2)
        for k = 1:n(2)
            q(i,j,k) = exp(-(((x(i,j,k) - 10)^2 + (y(i,j,k) - 10)^2 + (z(i,j,k) - 10)^2) / 20));
        end
    end
end

Total = x + y + z; % calculate the total of x,y,z at every point in the domain
x = x ./ Total; % find the proportion of x at every point in the domain
y = y ./ Total; % find the proportion of y at every point in the domain
z = z ./ Total; % find the proportion of z at every point in the domain
x(isnan(x)) = 0; % set coordinate (0,0,0) to 0
y(isnan(y)) = 0; % set coordinate (0,0,0) to 0
z(isnan(z)) = 0; % set coordinate (0,0,0) to 0

xP = reshape(x,[1, numel(x)]); % create a vector of the proportions of x
yP = reshape(y,[1, numel(y)]); % create a vector of the proportions of y
zP = reshape(z,[1, numel(z)]); % create a vector of the proportions of z

q = reshape(q,[1, numel(q)]);  % create a vector of the dependent variable q

ternsurf(xP, yP, q);  % plot the ternary surface of q against proportions
shading(gca, 'interp');
colorbar
view(2)
Sheljohn
2#
Sheljohn Reply to 2014-10-08 00:25:49Z

I believe you meant n(3) in your innermost loop. Here are a few tips:

1) Loose the loops:

q = exp(- ((x - 10).^2 + (y - 10).^2 + (z - 10).^2) / 20);

2) Loose the reshapes:

xP = x(:); yP = y(:); zP = z(:);

3) Check Total once, instead of doing three checks on x,y,z:

Total = x + y + z; % calculate the total of x,y,z at every point in the domain
Total( abs(Total) < eps ) = 1;
x = x ./ Total; % find the proportion of x at every point in the domain
y = y ./ Total; % find the proportion of y at every point in the domain
z = z ./ Total; % find the proportion of z at every point in the domain

PS: I just recognized your name.. it's Jonathan ;)

Kostya
3#
Kostya Reply to 2014-10-09 09:17:24Z

Discretization method probably depends on use of your plot, maybe it make sense to clarify your question from this point of view. Overall, you probably struggling with an "Out of memory" error, a couple of relevant tricks are described here http://www.mathworks.nl/help/matlab/matlab_prog/resolving-out-of-memory-errors.html?s_tid=doc_12b?refresh=true#brh72ex-52 . Of course, they work only up to certain size of arrays.

A more generic solution is too save parts of arrays on hard drive, it makes processing slower but it'll work. E.g., you can define several q functions with the scale-specific ngrids (e.g. ngridOrder0=[0:10:100], ngridOrder10=[1:1:9], ngridOrder11=[11:1:19], etc... ), and write an accessor function which will load/save the relevant grid and q function depending on the part of the plot you're looking.

You need to login account before you can post.

About| Privacy statement| Terms of Service| Advertising| Contact us| Help| Sitemap|
Processed in 0.394847 second(s) , Gzip On .

© 2016 Powered by mzan.com design MATCHINFO