0

I have a three dimensional array of points. I need to plot them on a 2D [x,z] grid, where every line is based on the value of Y inside a range. es. the first line is made by points with 0 < y < 1, the second with 1 < y < 2, etc..

I can plot points just fine using this script(to have a better looking graph i'm also changing the color for every set of point by moving inside an rgb triplet). set is the range of the line (in my case Y is time and i need to plot every 0.1 seconds). i is the index for my array of points.

w= 0;
yend = 100;
set = 0.1;
numberOfColors = 1/2*(Yinterval)*(1/set);
incrementOfColor = 1/numberOfColors;
red = 0;
green = 0;
blue = 1;
color=[red green blue];

while w < yend

while y(i)>w&&y(i)<w+set

    figure(1)
    hold on        
    plot(x(i),z(i),'.','Color',color);
    hold on
    i=i+1;
end
    w=w+set;

   if red < 1-incrementOfColor && blue > 0
       red = red + incrementOfColor;
       blue = blue - incrementOfColor;

   end
  if red > incrementOfColor && blue < incrementOfColor
      red = red-incrementOfColor;
      green = green + incrementOfColor;
      blue = 0;
  end
   color = [red green blue];


end

And this is the result: https://i.stack.imgur.com/1R4IN.png When there's too much data the plot becomes cumbersome to read, and with too little data isolated points don't really tell much. I've tried converting the points inside a "set" interval into an array but it really didn't work out:

while w < yend

while y(i)>w&&y(i)<w+set
    vX(a,:)=x(i);
    vZ(a,:)=z(i);
    i=i+1;
 a=a+1;
end    


    figure(2)
    hold on        
    plot(vX,vZ,'-','Color',color);

Gave this result: imgur.com/S7OasUn.jpg

Is my conversion wrong or arrays are just not the proper way to handle this? If so, what should I use?

I'm rather new to matlab so if this is really obvious or i'm asking something in the wrong way, please excuse me.

edit: This is the result i want to achieve:
imgur.com/jPZTO8E.png and it was obtained with Origin's contour profile tool. I guess you mean this with functional example:

myPoints[i]: 
i=0, x = 1, y= 0.03, z = 1
i=1, x = 2, y= 0.06, z = 3
i=2, x = 2.5, y = 0.09, z = 4
i=3, x = 1.2, y = 1.01, z = 3.1
i=4, x = 1.3, y = 1.04, z = 1.1
i=5, x = 1.2, y = 1.06, z = 2.5
i=6, x = 2, y = 1.09, z = 3.1
i=7, x = 1.2, y = 2.02, z = 3.1

etc..

i want the points i 0,1,2 plotted as one line, i 3,4,5 as another line and i 7 etc.. plotted as a third line. In my data i have a lot of points.

this is one example of the data i'm using. https://drive.google.com/file/d/0B9GHAkIYepQcRXdBdy03dFJtT1k/view?usp=sharing where:

x = myPoints(:,1);
y = myPoints(:,2);
z = myPoints(:,3);

In this specific case, i only care about the points with y value between 85.85 and 90.85, and i want to "place an edge" (?) every 0.1

x = myPoints(:,1);
y = myPoints(:,2);
z = myPoints(:,3);
ymin = 85.85;
ymax = 90.85;
set = 0.1;
nbins = (ymax-ymin)/set;
binedge = linspace(ymin, ymax, (nbins + 1));
M. Prev
  • 11
  • 4
  • 1
    It's not clear what you want the final result to actually look like. It would also help if you would provide a functional example. – sco1 Sep 09 '15 at 15:18
  • edited the original post – M. Prev Sep 09 '15 at 17:21
  • Before I dive too deep into this, does replacing `plot(x(i),z(i),'.','Color',color);` with `plot(x(i),z(i),'-','Color',color);` in your `while` loop give you the desired result? – sco1 Sep 09 '15 at 18:48
  • It still plots them as points: http://i.imgur.com/W9hT0Tk.jpg Also they are invisible because they have no thickness and you need to use the brush/select data tool to find them http://i.imgur.com/GNYbCQC.png – M. Prev Sep 09 '15 at 21:18
  • Oh, duh, I should have known that was going to happen since you're plotting a single point in each iteration of the loop. I'll have an answer in a few minutes. – sco1 Sep 10 '15 at 12:38

1 Answers1

0

I think I'm understanding what you're attempting to accomplish and I believe you can accomplish your task with a vectorized use of plot rather than having to loop through each of your points.

Given your example data we can give this method a shot:

load('mypoints.mat');
x = myPoints(:,1);
y = myPoints(:,2);
z = myPoints(:,3);

% Bin your data by y values
ymin = 85.85;
ymax = 90.85;
set = 0.1;
nbins = (ymax-ymin)/set;
binedge = linspace(ymin, ymax, (nbins + 1));
[~, ~, binidx] = histcounts(y, binedge);
binloop = unique(binidx);

% Fix for error with unique. If you try to use a for loop with a column
% vector it passes the whole vector as your iterator, so you need to
% transpose it to a row vector.
temp = size(binloop);
if temp(1) ~= 1
    binloop = binloop';
end

% Plot
figure
hold on
for ii = binloop
    if ii == 0
        % These fall outside of our bins, don't plot them
        continue
    else
        dataidx = find(binidx == ii);
        % Plot has its own color cycle, or you can add your color changing logic to this loop
        plot(x(dataidx), z(dataidx), '-', 'LineWidth', 0.25);
    end
end
hold off

What I've done here is to utilize the third output of histcounts to bin your y data and return a bin index for each value in your y vector.


To break the code down a bit:

Define your bin boundaries:

ymin = 85.85;
ymax = 90.85;
set = 0.1;
nbins = (ymax-ymin)/set;
binedge = linspace(ymin, ymax, (nbins + 1));

The linspace call returns the edges of each data bin. Given your example data we get binedge = [86.85, 86.95, 86.05, ..., 90.85]. We then plug in these edges and your y vector to histcounts to obtain our bin indices:

[~, ~, binidx] = histcounts(y, binedge);

Where the bins are defined per the documentation:

The value X(i) is in the kth bin if edges(k) ≤ X(i) < edges(k+1). The last bin also includes the right bin edge, so that it contains X(i) if edges(end-1) ≤ X(i) ≤ edges(end).

We can use unique to loop through all of the bins that are present. We can utilize find with MATLAB's logical indexing to plot all data from a single bin in each loop iteration. I ignore where ii == 0 as it indicates where data does not fall under one of the bins (and 0 index is meaningless in MATLAB).

I also played around a bit with the line sizes to try and make the plot a bit easier to read. There's a lot of data to visualize here but it helps a bit. You'll need to do a bit of pruning of your data since your x values wrap back, but that should be trivial.

A plot

sco1
  • 12,154
  • 5
  • 26
  • 48
  • This is pretty much the approach i wanted to take. The issue is that it connects points based on the Y value as if they were consecutive, while the points are spread around. This is the result: http://i.imgur.com/yhgbPH3.jpg I'll see if i can get it to work by finding the closest point in the set. I've also added a data example in the OP if you feel like trying it out. – M. Prev Sep 10 '15 at 15:49
  • @M.Prev All of the `y` values in your sample data set are >200, how are they supposed to fit into the `[0, 1)`, `[1, 2)`, etc. intervals you specified in your question? It's very difficult to answer a question adequately when things keep changing. – sco1 Sep 11 '15 at 12:47
  • Sorry for the late response and the confusing explanation. My data sample was also incorrect due to an error in its creation. With another method i can find the ymin and ymax, and by knowing the amount of lines delay between each line i can calculate the number of lines nbins and the binedge gets calculated correctly. ii and binidx are also correct yet the find method gives me an error related to the matrix dimension, although (in this case) bindix contains values from 0 to 50 and ii does as well. I've edited the Op to include these informations and a fixed data sample. – M. Prev Sep 14 '15 at 11:52