How to print comments at the right side of a matlab graph? - matlab-figure

I want to plot only one simple set of data. For example, my plot command could be :
x = (1:10);
y = ones[1,10];
plot(x,y);
In fact, the y data set could have been generated by a previous code, depending on several parameters. I want to print the name of every parameters and there values outside the graph, at the right of it, as if it were a legend. My problem is that I have several parameters to print, but only one set of data.
I tried to do this by the text or legend functions, but it never fit completly my needs.
Could you help me please ?

I think this code should help you out. Its probably easiest to split your figure into two axes, the right one just to hold text:
x = rand(1,10);
y = rand(1,10);
figure % makes your figure
axes('Position', [0.05,0.05,0.45,.9]) % makes axes on left side of your figure
scatter(x,y)
axes('Position', [0.55,0,1,1],'ytick',[],'xtick',[]) %make axes on left side of your figure, turns of ticks
text(0.05,0.85,{'Parameter 1: blah blah';'Parameter 2: bloop bloop';'Parameter 3: ....'},'Interpreter','Latex')
Play around with the numbers in the brackets to resize things as you like.

Related

set's membership seems not to work (python)

I am working on a image search algorithm that finds certain shapes of certain colors; to save time I only register half of the shape's perimeter in 2 distinct sets, one for the rows and one for the columns used by the shape. The idea is that whenever I find a point which has the target color, I then check if this point's row and column are in a master set (which have both the previous sets); if they are I skip it, if they are not then I initialize 2 recursive fuctions that register the first row and the first column of the shape.
Since it's for a school project, my images are specially tailored
and the code would be
for y in range(height):
for x in range(width):
if img[y][x] == target:
if y in master_set and x in master_set:
continue
else:
row = set()
column = set()
flood_fillv2_y(img,x,y,target,column)
flood_fillv2_x(img,x,y,target,row)
row=frozenset(row)
column=frozenset(column)
master_set.add(row)
master_set.add(column)
The idea then is to check the len of master_set to see how many shapes I have, but as I said what I get is that y and x are never in the master set so it keeps doing it for all points of the shape, resulting in a wrong number.
It's hard to give a good answer without seeing the whole code, but I can give a guess:
master_set.add(row) literally adds the frozenset row to the master_set, but you probably want all elements from the set to be added to master_set. Take a look at the update() method of sets.
Does this help?

How to decimate / decrease number of tic labels in gnuplot matrix

I have a matrix of data, which is an output of automatic music transcription program. I want to plot it using gnuplot, assigning appropriate labels. Here's my dropbox with some data, where Intensity.dat is actual data, example.stn is a column of string values, some of which are to be displayed on y axis and example.all is just a result of paste example.stn Intensity.dat > example.all Script:
reset
set title "Intensity detection"
set palette negative grayscale
set cbrange [0.01:1]
set xlabel "Time [s]"
set ylabel "Musical note"
set terminal qt font "Verdana,16"
set logscale cb
xincr=0.04644
yincr=1
plot 'example.all' u (($1+0.5)*xincr):($2*yincr):3 matrix with image
produces
plot produced by script 1. Everything's OK, now just tic labels...
After I change the last line to plot 'example.all' u (($1+0.5)*xincr):($2*yincr):3 matrix rowheaders with image, the y-axis becomes too densly populated (It's plot2.jpg from my dropbox, link on top. Sorry guys, I'm new and it doesn't allow me to post more than 2 links).
What I want is a way to present only the labels I want (or hide others, whatever), not all at a time (because it looks unreadable). I'd also like to be able to quickly change them to the others when I need to do so. Supposingly, I want to display every 12th label, but still keep entire matrix with all rows plotted. Or every 12th starting from 2nd label AND every 12th starting from 6th. I've already tried many ways but I'm stuck. Functions like :ytics() or :yticlabels() can't make it, at least for me. And yes, I need this Verdana 16, and removing labels completely is out of question.
I'll be extra grateful if the method applies also for x-axis, as I have an analogical problem with x-axis in other plot, but I generally appreciate any help.
You can separate plotting the image from plotting the ytics like this:
condition(n) = (ceil(n)%12-2 == 0) || (ceil(n)%12-6 == 0)
plot 'Intensity.dat' u (($1+0.5)*xincr):($2*yincr):3 matrix with image ,\
'example.stn' u (NaN):0:ytic(condition($0) ? strcol(1) : "") notitle
The function condition checks whether the label should be plotted or not. I have used ceil to convert from a real number to an integer which is required by the modulo operator (%). The condition function is called with the linenumber $0. The NaN while plotting 'example.stn' avoids plotting data points while keeping the chance for setting the labels. If the condition is met (12th label starting from 2nd or 12th starting from 6th), we use the actual label, else an empty string is used.

How to overly depth data on 2D image?

All of this is done in Matlab. I have a 2D RGB image, with some depth data for key vertexes. That is, I have three vectors (m x 1): X, Y, Z. Together, [X(i), Y(i)] specifies the point in the image with depth Z(i).
The crux of my problem is this:
I would like to plot the image "warped" with the depth information. But, each time I keep calling functions like 'mesh(X,Y,Z,RGBImage)' and 'surf', I get weird errors like "Z need to be matrix not vector". Also, I haven't even been able to implement the 'warp' function, as I am not sure how to translate my data into a usable format.
Any help would be really appreciated.
EDIT: I finally got it to work the way I would like. The only thing that needed to be changed, that was not answered, was to include the line
s = surf(Xmat,Ymat,Zmat, T1, 'edgecolor', 'none', 'FaceColor', ...
'texturemap');
Where
T1 = rgb2gray(OrignialRGBImage);. Much thanks!
I don't have access to MATLAB right now, so I am giving the outline of the solution.
First, create two matrices using meshgrid: [Xmat,Ymat] = meshgrid(1:imgCols,1:imgRows);. Now, you can find every row of [X,Y] at [Xmat(i,j),Ymat(i,j)] for some (i,j). In the next step, create Zmat such that Zmat(i,j) is the correct depth value for [Ymat(i,j),Xmat(i,j)]. You should be able to do this as follows:
Zmat = zeros(imgRows,imgCols);
for i=1:size(X,1)
Zmat(Y(i),X(i))=Z(i);
end
Now you can do surf with Xmat,Ymat,Zmat as follows. Then overlay image as texture.
s = surf(Xmat,Ymat,Zmat);
set(s, 'faceColor', 'texture','edgecolor', 'none','cdata', subimage); %not tested,
%see if it works
Overlaying part taken from here.
If the above part doesn't work, then you can overlay Zmat in the heatmap style, see this question.

copyobj copies entire image instead of axes only

What I have is a plot showing the area of connected components. What I want to do is to further work on the plot figure such as clean it up a bit or imcomplement it etc. and then be able to apply the axes from the original plot to this image and be able to extract the ylabel.
Let me explain the above issue with my code and some examples.
This is the plot I have, the y-axis represents the object areas. This is the important axis that I want to transfer to the new image.
Since I am interested in the axes only I copy that using
h = findobj(gcf,'type','axes');
So that I can work with the figure without the axes and borders interfering I save it without these attributes
set(gca, 'visible', 'off'); % Hide the axis and borders
hgexport(gcf, 'plot1.jpg', hgexport('factorystyle'), 'Format', 'jpeg');
This is what I get:
So far so good.
Now comes the processing or in other words changing the plot to my needs.
plot_img = rgb2gray(imread('plot1.jpg'));
img_bw_plot = im2bw(plot_img, graythresh(plot_img));
[rows cols] = size(plot_img);
new = zeros(size(plot_img));
for i = 1: rows
for j = 1: cols
if (img_bw_plot(i,j) == 0)
new(i, 1:10) = 255;
end
end
end
f = figure;
imshow(new);
copyobj(h,f)
This produces a weird overlapped image where instead of copying only the axes, the entire image is copied on top of the new. The datacursormode also fails to work beyond the over lapping image.
First of all I'm a little bit confused that if you have the figure in the first place why aren't you extracting your data from it using something like:
lines=findobj(gca,'type','line');
y=zeros(1,length(lines));
for i=1:length(lines)
y(i)=get(lines(i),'ydata');
end
and there you'll have all the data.
But let's say the original figure isn't like a figure figure where you'd have access to the children of the axes object (though all of them being copied together kind of suggests that this is not the case). What you need to realize is that an "axes" object in MATLAB isn't just the axes of the graph, but the whole graph. For example when you have 5 subplots, each of those smaller plots is an axes object and the graph itself is one of its children which is a "line" object (refer to my example above).
So after this long lecture :), one solution is that you could manually create those axes around your newly drawn image instead of copying the axes object as such:
set(gca,'visible','on');
s=size(new);
set(gca,'ytick',linspace(1,s(1),7),'yticklabel',linspace(6000,0,7));
This should do the trick of placing 7 ticks on the y-axis in the same manner as you have on your original figure. The same method would apply to manually creating the labels for the x-axis.
(I tried putting the resulting image here but I don't have the enough reputations to do so. That's on stackoverflow bro!)
Mind you, though, that this creates the labels on the graph giving you the illusion of the same axis while the actual coordinates of the points are actually determined by the size of the image you're saving. So if you want to make sure the image is the same size, you need to work on resizing your original figure to end up being the same size, which given then 0-6000, would be a really big image.

To make all peaks clearly visible in Matlab

I finally solved my problem here with lennon310.
I have a picture of thousands of thin peaks in Time-Frequency picture.
I cannot see all the same time in one picture.
Depending on the physical width of my time window, some windows appear and some come visible.
Pictures of my data which I plot by imagesc
All pictures are from the same data points T, F, B.
How can you plot all peaks at once in a picture in Matlab?
You need to resize the image using resampling to prevent the aliasing effect (that craigim described as unavoidable).
For example, the MATLAB imresize function can perform anti-aliasing. Don't use the "nearest" resize method, that's what you have now.
Extension to #BenVoigt's answer
My try
B = abs(B);
F1 = filter2(B,T); % you need a different filter kernel because resolution is lower
T = filter2(B,F);
F = F1;
image1 = imagesc(B);
display1 = imresize(image1, [600 600], 'bilinear');
imshow(T*t, F*fs, display1);
where are some problems.
I get again picture where the resolution is not enough
2nd Extension to BenVoigt's answer
My suggestion for one kernel filter is with convolution of relative random error
data(find(data ~= 0)) = sin(pi .* data(find(data ~= 0))) ./ (pi*data(find(data ~= 0)));
data(find(data == 0)) = 1; % removing lastly the discontinuity
data1 = data + 0.0000001 * mean(abs(data(:))) * randn(size(data));
data = conv(data, data1);
Is this what BenVoigt means by the kernel filter for distribution?
This gives results like
where the resolution is still a problem.
The central peaks tend to multiply easily if I resize the window.
I had old code active in the above picture but it did not change the result.
The above code is still not enough for the kernel filter of the display.
Probably, some filter functions has to be applied to the time and frequency axis separately still, something like:
F1 = filter2(B,T); % you need a different kernel filter because resolution is lower
T = filter2(B,F);
F = F1;
These filters mess up the values on the both axis.
I need to understand them better to fix this.
But first to understand if they are the right way to go.
The figure has be resized still.
The size of the data was 5001x1 double and those of F and T 13635x1 double.
So I think I should resize lastly after setting axis, labels and title by
imresize(image, [13635 13635], 'bilinear');
since the distirbution is bilinear.
3rd Extension to BenVoigt's answer
I plot the picture now by
imagesc([0 numel(T)], [0 numel(F)], B);
I have a big aliasing problem in my pictures.
Probably, something like this should be to manipulate the Time-Frequency Representation
T = filter2(B,t); % you need a different filter kernel because resolution is lower
F = filter2(B,fs);
4th extension to BenVoigt's answer and comment
I remove the filters and addition of random relative errors.
I set the size of T,F,B, and run
imagesc([0 numel(T)], [0 numel(F)], B, [0 numel(B)])
I get still with significant aliasing but different picture
This isn't being flippant, but I think the only way is to get a wider monitor with a higher pixel density. MATLAB and your video card can only show so many pixels on the screen, and must decide which to show and which to leave out. The data is still there, it just isn't getting displayed. Since you have a lot of very narrow lines, some of them are going to get skipped when decisions are made as to which pixels to light up. Changing the time window size changes which lines get aliased away and which ones get lucky enough to show up on the screen.
My suggestions are, in no particular order: convolute your lines with a Gaussian along the time axis to broaden them, thus increasing the likelihood that part of the peak will appear on the screen. Print them out on a 600 dpi printer and see if they appear. Make several plots, each zooming in on a separate time window.
3rd Extension to BenVoigt's answer
My attempt to tell imagesc how big to make the image, instead of letting to use the monitor size, so it won't away data.
imagesc(T*t, F*fs, B, [50 50]);
% imagesc(T*t, F*fs, B');
% This must be last
imresize(image, 'bilinear', [64 30],);
I am not sure where I should specify the amount of pixels in x-axis and y-axis, either in the command imagesc or imresize.
What is the correct way of resizing the image here?

Resources