Gnuplot how can I draw matrix every nth line - matrix

I have following data
...
10800 42.835282 2.0799322 9.6376456 14.69194 15.74205 16.591997 14.208506 17.036752 16.974312 30.759594 318.69734
10900 59.608134 2.0319971 10.413494 17.136174 18.597465 19.31398 16.78688 19.939459 20.034195 43.809158 470.3118
11000 71.147383 2.3502536 11.098845 19.525944 21.618026 22.255387 19.446565 22.871378 23.265609 60.717349 559.03537
11100 70.844437 2.5290753 11.759208 21.795673 24.63466 25.294785 22.079689 25.788459 26.690083 80.472264 513.94945
...
Data have total 600 lines, 12 columns. I want to plot line-wise data for every 50th line, from 3rd column to 12th column. I used plot data matrix (because [i=3:12] was not working as I intended)
data = "data.dat"
plot data matrix every 1::2 w l
This give me the plot what I want (draw 3rd ~ 12th columns of each lines), but draws the curves for all 600 lines. How can I draw every 50th lines in this matrix every 1::2 command, so only 12 curves are shown?
Thanks
ps) I just solved by myself by using sed command like
plot '<sed -n "0~50p" data.dat' matrix every 1::2 w l

To plot every 50th row, you must make use the block values for every:
plot "data.dat" matrix every :50:2 with lines
That plots every point starting from column 3 in every 50th row.

Related

Remove single cell from a matrix

I am trying to remove single cells which are NA from a matrix data. I need to keep all of the other data in the matrix. All I could do is removing all the rows and colomns if a single cell is NA.
#First I replaced all the data points that are higher than 600,000
adjusted_data<-apply(data, c(1,2), FUN = function(x){ ifelse (x > 600,000, NA, x) })
#now I need to remove these single cells which turned to NA.
adjusted_data<- na.omit(adjusted_data)
However, When I use this code, all the ROWs and COLUMNS are removed even if a single cell is NA.

sorting by x-y-coordinaten

I want to plot results in gnuplot that all lie on a circle. For each value I have the corresponding x-y coordinates and a corresponding ID number (so 4 columns in total), but in an unsorted order. The rows are to be sorted in such a way that the direction of rotation is from -x => -y => +x => +y and end again at -x. So the center of the circle is at 0. How to implement this with "sort" (or alternatively with "awk"?) command (using Linux)?
At Theozh's suggestion, I will formulate my problem a little more precisely.
Imagine the dial of a clock with small dots as minute symbols. The position of the minute points can be determined by polar coordinates or by Cartesian coordinates. My file contains the Cartesian coordinates with an associated value (result). The file contains 60 lines with x - y coordinates and the result in the third column. Depending on the quadrant, the signs of x and y change, of course. Unfortunately, the lines are NOT sorted in such a way that they correspond to the sense of circulation. So the line for the point "minute 30" is not in line 30, but e.g. in line 17. The task is to sort the lines by the coordinates so that they appear in the order from 1 to 60. In the diagram, the x-axis would then simply be defined from 1 to 60 and the y-axis would then contain the results (from the 3rd column)
My unsorted file (coordinates for a unit circle, result values simplified for a better overview)
And this is what I want to have (8 rows (every 45°) sorted counterclockwise):
The angle can be calculated directly from the x/y coordinates using the atan2() function.
You do not say exactly what it is that you want to plot. If it is simply the points themselves (one point per line in the file), then this can be done easily inside gnuplot. I show the output from gnuplot 5.5. In earlier versions, and depending on exactly what you want to plot, it might require additional commands to sort the data in a separate step and then plot the sorted data. If you clarify what exactly is supposed to go into the plot, I will modify the example accordingly.
Example using 100 points with random x and y coordinates:
set print $RANDOM
do for [i=1:100] { print rand(0)-0.5, rand(0)-0.5 }
unset print
set xrange [-1:1]
set yrange [-1:1]
set angle degrees
set cbrange [-180:180]; set cblabel "Angle"
set style data linespoints
plot $RANDOM using 1:2:(atan2($2,$1)):(atan2($2,$1)) smooth zsort lc palette
Updated answer
Revised to show a plot of the sample data as given
$DATA << EOD
X Y Result
-0.707 -0.707 222
-0.707 0.707 888
0.707 -0.707 444
-1 0 111
1 0 555
0.707 0.707 666
0 1 777
0 -1 333
EOD
set datafile columnheader # allow for the line of labels
unset key
# atan2() returns a number between -pi and pi; convert this to 0 -> 1
# You could make it run from 0->60 if you know in advance
# there will be 60 evenly spaced points
xcoord(a) = (a + pi) / (2 * pi)
plot $DATA using (xcoord(atan2($2,$1))):3:(atan2($2,$1)) smooth zsort with points
And actually, if you don't care what order the points are drawn in, only where they end up, the command is even simpler because there is no need to sort!
plot $DATA using (xcoord(atan2($2,$1))):3 with points

How to detect a portion of an image based upon the matrix values?

I have a simple pcolor plot in Matlab (Version R 2016b) which I have uploaded as shown in the image below. I need to get only the blue sloped line which extends from the middle of the leftmost corner to the rightmost corner without hard-coding the matrix values.
For instance: One can see that the desired slope line has values somewhere approximately between 20 to 45 from the pcolor plot. (From a rough guess just by looking at the graph)
I'm applying the following code on the matrix named Slant which contains the plotted values.
load('Slant.mat');
Slant(Slant<20|Slant>50)=0;
pcolor(Slant); colormap(jet); shading interp; colorbar;
As one can see I hard-coded the values which I don't want to. Is there any method of detecting certain matrix values while making the rest equal to zero?
I used an other small algorithm of taking half the maximum value from the matrix and setting it to zero. But this doesn't work for other images.
[maxvalue, row] = max(Slant);
max_m=max(maxvalue);
Slant(Slant>max_m/2)=0;
pcolor(Slant); colormap(jet); shading interp; colorbar;
Here is another suggestion:
Remove all the background.
Assuming this "line" results in a Bimodal distribution of the data (after removing the zeros), find the lower mode.
Assuming the values of the line are always lower than the background, apply a logic mask that set to zeros all values above the minimum + 2nd_mode, as demonstrated in the figure below (in red circle):
Here is how it works:
A = Slant(any(Slant,2),:); % save in A only the nonzero data
Now we have A that looks like this:
[y,x] = findpeaks(histcounts(A)); % find all the mode in the histogram of A
sorted_x = sortrows([x.' y.'],-2); % sort them by their hight in decendet order
mA = A<min(A(:))+sorted_x(2,1); % mask all values above the second mode
result = A.*mA; % apply the mask on A
And we get the result:
The resulted line has some holes within it, so you might want to interpolate the whole line from the result. This can be done with simple math on the indices:
[y1,x1] = find(mA,1); % find the first nonzero row
[y2,x2] = find(mA,1,'last'); % find the last nonzero row
m = (y1-y2)/(x1-x2); % the line slope
n = y1-m*x1; % the intercept
f_line = #(x) m.*x+n; % the line function
So we get a line function f_line like this (in red below):
Now we want to make this line thicker, like the line in the data, so we take the mode of the thickness (by counting the values in each column, you might want to take max instead), and 'expand' the line by half of this factor to both sides:
thick = mode(sum(mA)); % mode thickness of the line
tmp = (1:thick)-ceil(thick/2); % helper vector for expanding
rows = bsxfun(#plus,tmp.',floor(f_line(1:size(A,2)))); % all the rows for each coloumn
rows(rows<1) = 1; % make sure to not get out of range
rows(rows>size(A,1)) = size(A,1); % make sure to not get out of range
inds = sub2ind(size(A),rows,repmat(1:size(A,2),thick,1)); % convert to linear indecies
mA(inds) = 1; % add the interpolation to the mask
result = A.*mA; % apply the mask on A
And now result looks like this:
Idea: Use the Hough transform:
First of all it is best to create a new matrix with only the rows and columns we are interested in.
In order to apply matlab's built in hough we have to create a binary image: As the line always has lower values than the rest, we could e.g. determine the lowest quartile of the brightnesses present in the picture (using quantile, and set these to white, everything else to black.
Then to find the line, we can use hough directly on that BW image.

Draw a horizontal line on an image whose row corresponds to the largest count of dark pixels

I wish to draw a horizontal line on a binary image in MATLAB which has the maximum amount of black pixels. So in this word for example:
... I have to identify the horizontal line with most pixels.
I understand that I can open the binary image variable editor, and plot a row which has maximum zeroes however that doesn't seem to work.
I have to make a baseline of this word like this:
... as the output assuming that the maximum pixels lie where I drew the line.
Purely going by your definition, you want to figure out the row that has the largest amount of black pixels. Simply sum over all columns of each row and find the maximum. Then when you're done, locate the row with the largest count and set this line to red.
Something like this comes to mind. I'm going to read your image from StackOverflow directly and am going to use the image processing toolbox to help me with this analysis:
%// Read image from SO
im = imread('http://s15.postimg.org/cwg2sxnwr/mathworksss.png');
%// Keep a copy of a binary version
im_bw = im2bw(im);
%// Sum over all of the columns and look for dark pixels
row_sums = sum(~im_bw, 2);
%// Find row with max sum
[~,row_max] = max(row_sums);
%// Draw a red line through the original image as it's in RGB
im(row_max,:,1) = 255;
im(row_max,:,2:3) = 0;
%// Show the image
imshow(im);
The first image reads in the image directly from SO and puts it into the MATLAB workspace. The next line thresholds the image to binary to allow the analysis to be easier. We also keep a copy of the original image so we can mark the baseline with red. The next line after that uses sum and sums over every column of each row individually and adds up the black pixels. This is achieved by inverting the binary image so that dark pixels become bright to facilitate the summing. We then use max to figure out the row with the largest sum and that's done by looking at the second output of max. Once we find this location, we use this row and set all of the pixels in this row to red, or RGB = (255,0,0).
I get this image:
Now the above code draws a line from the left to the right. If you wanted to limit this and only draw a red line where there is text, perhaps find the left most and right most dark pixel and add a bit of breathing room to them, then draw a line through.... something like this comes to mind:
%// Read image from SO
im = imread('http://s15.postimg.org/cwg2sxnwr/mathworksss.png');
%// Keep a copy of a binary version
im_bw = im2bw(im);
%// Sum over all of the columns and look for dark pixels
row_sums = sum(~im_bw, 2);
%// Find row with max sum
[~,row_max] = max(row_sums);
%// Find left most and right most black columns
[~,left_most] = find(~im_bw,1,'first');
[~,right_most] = find(~im_bw,1,'last');
%// Buffer for drawing the line before the first and after the last column
buf = 20;
%// Draw the line
im(row_max,left_most-buf:right_most+buf,1) = 255;
im(row_max,left_most-buf:right_most+buf,2:3) = 0;
%// Show the image
imshow(im);
As you can see, most of the code remains the same (reading in the image, thresholding, column summing and max) but towards the end, I use find to find the first and last instance of a black pixel with respect to the columns. I then use these columns with the same maximum row found earlier, then subtracting the left most black column pixel location and adding the right most black column pixel location by a buffer amount (I chose 20 here), then setting the line of pixels within this region to red.
We get:
Now, it is your wish to find the row with the second highest sum and draw another line through that row. That's not bad to do. However, this will require some post-processing because the outer edges of each character is not a single pixel thick... so the second highest sum may actually still give you a row that is around the first maximum. As such, I would suggest shrinking the text slightly then applying the row sum logic again. You can do this with morphological binary erosion with a small structuring element... say, a 3 x 3 square. This can be done with imerode for the erosion and using strel to specify the square structuring element.
You'd apply the row sum logic to this new image, but then use these results and draw on the original image. You don't want to operate on this new image because it looks like there are some areas of the text that are a single pixel thick and these will be eliminated after erosion.
Something like this comes to mind:
%// Read image from SO
im = imread('http://s15.postimg.org/cwg2sxnwr/mathworksss.png');
%// Keep a copy of a binary version - also invert for ease
im_bw = ~im2bw(im);
%// Slightly erode the text
im_bw = imerode(im_bw, strel('square', 3));
%// Sum over all of the columns and look for dark pixels
row_sums = sum(im_bw, 2);
%// Sort the column sums in descending order and figure out the two highest sums
[~,ind_sort] = sort(row_sums,'descend');
%// First highest sum is the bottom - mark as red
red_row1 = ind_sort(1);
%// Second highest sum is the middle - mark as red too
red_row2 = ind_sort(2);
%// Find left most and right most black columns
[~,left_most] = find(im_bw,1,'first');
[~,right_most] = find(im_bw,1,'last');
%// Buffer for drawing the line before the first and after the last column
buf = 20;
%// Draw the two red lines
im(red_row1,left_most-buf:right_most+buf,1) = 255;
im(red_row1,left_most-buf:right_most+buf,2:3) = 0;
im(red_row2,left_most-buf:right_most+buf,1) = 255;
im(red_row2,left_most-buf:right_most+buf,2:3) = 0;
%// Show the image
imshow(im);
As you can see, most of the logic is the same. The only thing I really changed was that I eroded the image, sorted the row sums in descending order and extracted the first two locations that are the highest. I then repeated the logic to draw a line through the row, but instead of one row, we have two now.
We get:

Plotting of values using heatmap in Matlab: Wrong output attained

I have a 512*512 matrix which contains calculated probabilities. I am trying to plot the ocuucrences of 0s and 1s of these using a heatmap so that my final image is somewhat like an inverted flattened gaussian function;
the problem is my code returns an image where all values are along the 0 only; this is not possible as I have an almost equal probability of 0s and 1s. Is there some problem with my plotting of the values?
X = reshape(prob_to_1,512,512); % prob_to_1 is the matrix of probabilities which
% is reshaped to a 512*512 matrix
colormap('hot');
imagesc(X);
set(gca, 'XTick', [0:0.05:1]*512, 'XTickLabel',[0:0.05:1]) % 10 ticks
set(gca, 'YTick', [0:0.1:1]*512, 'YTickLabel',[0:0.1:1]*100) % 20
colorbar('YTickLabel',{'100%','90%','80%','70%','60%','50%','40%','30%','20%','10%','0%'})
I have attached an image showing my output. As you can see, the black line which shows the no.of 1s should have been at the extreme right on the x-axes (close to prob of 1).
Any suggestions/ideas?
Thanks!
Well, the second image is a histogram of the same data. hist(X,nbins) is sufficient for plotting it.

Resources