I have a matrix consisting of three rows: gene 1, gene 2, Distance.
I want to create a network where each gene is a node and the connecting line is scaled by the distance between the two genes.
How can I do this without using the bioinformatics or neural network toolboxes?
Thanks!
Some Information
It is almost impossible to draw a graph with edge length proportional to edge weight, atleast its very unlikely that the weights allow a graph to be drawn this way, most will be impossible...
See:
P. Eades and N. C. Wormald. Fixed edge-length graph drawing is
NP-hard. Discrete Applied Mathematics, 28(2):111–134, 1990]
or to quote:
"Drawing planar graphs with edge weights as standard node-link
diagram, where edge lengths are proportional to the edge weights, is
an NP-hard problem"
M. Nollenburg, R. Prutkin and I. Rutter, Edge-weighted contact
representations of planar
graphs.
Journal of Graph Algorithms and Applications, 17(4):441–473, 2013
Consider the simple example of the 3 vertices joined as such, in your data format:
[1,2,1;
1,3,1;
2,3,10;]
it's should be immediately obvious that such a graph is impossible to draw with edge length proportional to weight (with straight lines). As such alternatives in MATLAB include using color or line width to represent Weight.
Sorry for the length of this answer but to implement this is not trivial, the process used below for drawing the graph can also be found here (in debth), here (most simple) and in a similar problem here. However these do not address weighted graphs...
So on with implementing line width and color proportional to weight:
Code
Due to the length the code is available without description here
Firstly some test data, consisting of 30 edges randomly assigned between 20 vertices with random weights between 0 and 10.
clear
%% generate testing data
[X,Y] = ndgrid(1:20); testdata = [X(:) Y(:)]; %// all possible edges
data(data(:,1)==data(:,2),:)=[]; %// delete self loops
data=data(randperm(size(data,1),20),:); %// take random sample of edges
data(:,3)=rand(size(data,1),1)*10; %// assign random weights in range 0-10
First some processing of the data to get it into required format;
edges=data(:,1:2);
[Verticies,~,indEdges]=unique(edges); %// get labels & locations of vertices
indEdges=reshape(indEdges,[],2);
weights=data(:,3);
normalisedWeights=weights/max(weights); %// normalise weights (range 0-1)
numeEdge=numel(weights);
numVertex=numel(Verticies);
Now x and y coordinates for each vertex are created on a unit circle:
theta=linspace(0,2*pi,numVertex+1);
theta=theta(1:end-1);
[x,y]=pol2cart(theta,1); % create x,y coordinates for each vertex
As lines in MATLAB plots inherit their color from the axis color order we create a RGB array which corresponds to a colormap, with a entry for each line giving the RGB values for the color assigned to that weight.
The autumn colormap is simple to manually implement as R=1,B=0 for all values and G ranges from 0-1 linearly, so we can make the Cmap variable which is used as the axis color order as follows:
clear Cmap %// to avoid errors due to the way it is created
Cmap(:,2)=normalisedWeights;
Cmap(:,1)=1;
Cmap(:,3)=0;
Now we create a figure, set the colormap to autumn (for the color bar), put hold on so the plot command doesn't reset the color order, and apply the color order
figure
colormap('autumn')
hold on
set(gca,'colororder',Cmap) %// set axis colororder to Cmap
how we plot the edges using the edge indexes generated earlier at locations given by x & y. The handles of the lines (Hline) is stored for later use.
Hline=plot(x(indEdges).',y(indEdges).'); %// plot edges
Now we set the axis to square so the circle of points is displayed properly and turn the axis off to hide them (as they bear no relevance to the plotted graph). The axis color limits (Clim) is then set to match the range of weights and add a colorbar is added.
axis square off
set(gca,'Clim',[0 max(weights)])
colorbar
The final step for plotting the edges, setting the line width to be proportional to weight, The normalised weights are scaled to be in the range 0-5. The linewidths are then set to scalefactor*normalisedWeights..
scalefactor=5; %// scale factor (width of highest weight line)
set(hline, {'LineWidth'}, num2cell(normalisedWeights*scalefactor));
The vertices are now plotted at the x and y coordinates (as black squares here).
The axis limits are increased to allow vertex labels to fit. Finally the vertices are labelled with the values from the original matrix, the labels are placed on a slightly larger circle than the vertices
plot(x,y,'ks')
xlim([-1.1,1.1]) % expand axis to fix labels
ylim([-1.1,1.1])
text(x(:)*1.1, y(:)*1.1, num2str(Verticies),...
'FontSize',8,'HorizontalAlignment','center'); %// add Vertex labels
Results
Related
I have a 3D color image. I wish to plot its principal axis and its centroid. To do that, I have extracted each of the color channels, found the centroid and then proceeded to find the covariance matrix and eigenvalue. I am unsure as to whether this will help me plot the principal axis.
My primary goal is to plot the principal axis so that I can find whether the image is symmetrical about that axis.
This is the algorithm I would like to implement.
Plot the principal axis of the image. The image is then rotated
(clockwise) to align its coordinate (𝑥 and 𝑦) axes with principal
inertia axis of the image. The image is then hypothetically folded
around the 𝑥-axis and the the sum of the absolute grey-level
difference between the corresponding pixels(𝐴 𝑥) between the
overlapping folds was taken as the amount of asymmetry on the 𝑥-axis.
The same procedure was performed for the 𝑦-axis. Two asymmetry
measures were calculated from 𝐴 𝑥 and 𝐴 𝑦 as follows:
A1 = min (𝐴
𝑥
, 𝐴
𝑦
)
𝐴
× 100%
A2 =
(𝐴
𝑥
+ 𝐴
𝑦
)
𝐴
× 100%.
The two asymmetry measures noted above (𝐴 1 and 𝐴 2) are computed
for each image channel, in the RGB colour space, resulting in the
total of six-coefficient (6D) colour asymmetry feature.
How do I plot the principal axis? I tried using regionprops function in MATLAB to plot the major axis, minor axis, centroid and orientation but I am unsure if this is the right approach. Should I use PCA?
Can I overlap the image using the fliplr function?
What do they mean same procedure for y-axis? If an image is asymmetrical over one axis then doesn't it mean its asymmetrical over the y-axis too?
I am unable to implement this algorithm. Please guide on how to code this in MATLAB.
https://in.mathworks.com/matlabcentral/answers/266988-how-to-flip-a-segmented-image-along-the-major-axis#answer_208875
This is a partial answer to my query but I am stuck at the initial part. How do I find the major axis and align in with the axes using imtranslate()?
I would like to draw height lines of a function (represented by matrices, of course), using MATLAB.
I'm familiar with contour, but contour draws lines at even-spaced heights, while I would like to see lines (with height labels), in constant distance from one another when plotted.
This means that if a function grows rapidly in one area, I won't get a plot with dense height lines, but only a few lines, at evenly spaced distances.
I tried to find such an option in the contour help page, but couldn't see anything. Is there a built in function which does it?
There is no built-in function to do this (to my knowledge). You have to realize that in the general case you can't have lines that both represent iso-values and that are spaced with a fixed distance. This is only possible with plots that have special scaling properties, and again, this is not the general case.
This being said, you can imagine to approach your desired plot by using the syntax in which you specify the levels to plots:
...
contour(Z,v) draws a contour plot of matrix Z with contour lines at the data values specified in the monotonically increasing vector v.
...
So all you need is the good vector v of height values. For this we can take the classical Matlab exemple:
[X,Y,Z] = peaks;
contour(X,Y,Z,10);
axis equal
colorbar
and transform it in:
[X,Y,Z] = peaks;
[~, I] = sort(Z(:));
v = Z(I(round(linspace(1, numel(Z),10))));
contour(X,Y,Z,v);
axis equal
colorbar
The result may not be as nice as what you expected, but this is the best I can think of given that what you ask is, again, not possible.
Best,
One thing you could do is, instead of plotting the contours at equally spaces levels (this is what happens when you pass an integer to contour), to plot the contours at fixed percentiles of your data (this requires passing a vector of levels to contour):
Z = peaks(100); % generate some pretty data
nlevel = 30;
subplot(121)
contour(Z, nlevel) % spaced equally between min(Z(:)) and max(Z(:))
title('Contours at fixed height')
subplot(122)
levels = prctile(Z(:), linspace(0, 100, nlevel));
contour(Z, levels); % at given levels
title('Contours at fixed percentiles')
Result:
For the right figure, the lines have somewhat equal spacing for most of the image. Note that the spacing is only approximately equal, and it is impossible to get the equal spacing over the complete image, except in some trivial cases.
I want to plot a text file with 4 columns that first column in longitude,second in latitude, third is depth and forth is amount of displacement in each point.(it's related to a fualt)
-114.903874 41.207504 1.446784 2.323745
I want a plot to show the amount of displacement in each point (like images that we plot with imagesc),unfortunately "imagesc" command doesn't work for it.
how can I plot it?
Thanks for your attention
A simple way would be to use scatter3 and assign your displacements to be the colours. Note that you have to supply a size for this to work - I'm using [] (empty matrix) which will set it to default. If your four sets of values are four vectors of the same size, then it's just something like:
scatter3(lat,lon,depth,[],displacement, 'filled')
Values in displacement will be linearly mapped to the current colormap. 'filled' gives you filled markers rather than open ones (default marker is a circle but can be changed).
You can plot each point using plot3(longitude,latitude,depth). You can color each point according to the displacement in a for loop. The easiest way to do this is create a colormap, e.g. using jet and chosing the color according to the displacement.
figure;
hold on;
cmap = jet(256);
dispRange = [min(displacement),max(displacement)];
for k=1:size(longitude,2)
c = cmap(1+round(size(cmap,1)*(displacement(k)-dispRange(1))/dispRange(2)),:);
plot3(longitude(k),latitude(k),depth(k),'o', ...
'MarkerEdgeColor',c,'MarkerFaceColor',c);
end
I want to visualize 4 vectors of scattered data with a surface plot. 3 vectors should be the coordinates. In addition the 4th vector should represent a surface color.
My first approach was to plot this data (xk,yk,zk,ck) using
scatHand = scatter3(xk,yk,zk,'*');
set(scatHand, 'CData', ck);
caxis([min(ck), max(ck)])
As a result I get scattered points of different color. As these points lie on the surface of a hemisphere it ist possible to get colored faces instead of just points. I replace the scattered points by a surface using griddata to first build an approximation
xk2=sort(unique(xk));
yk2=sort(unique(yk));
[xxk, yyk]=meshgrid(xk2, yk2);
zzk=griddata(xk,yk,zk,xxk,yyk,'cubic');
cck=griddata(xk,yk,clr,xxk,yyk,'cubic');
surf(xxk,yyk,zzk,cck);
shading flat;
This is already nearly what I want except that the bottom of the hemisphere is ragged. Of course if I increase the interpolation point numbers it gets better but than the handling of the plot gets also slow. So I wonder if there is an easy way to force the interpolation function to do a clear break. In addition it seems that the ragged border is because the value of zzk gets 'NaN' outside the circle the hemisphere shares with the z=0-plane.
The red points at the top are the first several entries of the original scattered data.
You can set the ZLim option to slice the plotted values within a certain range.
set(gca, 'Zlim', [min_value max_value])
I would like to plot a sort of "density map" in Matlab, but have not found the right tool yet.
I have "continuous" data with x between (x_min and x_max), and y between (y_min and y_max). At each of these pairs of points (x_i,y_i), there is associated to it a value between 0 and 1.
I would like to plot this information in a 2d graph, such that in each small square containing (x_i,y_i) the plot shades the square black for the value 0, white for the value 1, and the appropriate shade of gray for intermediate values.
Can this be done easily in Matlab?
http://www.mathworks.com/help/images/ref/mat2gray.html seems to do exactly what I need.
If the data is in a matrix A, you can just use
image(255*A); colormap gray(256); axis image;
I'm not sure what you mean by continuous (uniformly spaced?), so my answer won't make too many assumptions other than that there is a reason why you mention the coordinates (if just a regular mesh, then just image or imagesc). So, only assuming your x and y coordinates are possibly non-uniformly spaced, but at least monotonically increasing samples, try surf with view(2):
surf(X,Y,data)
view(2)
colormap gray
By default surf sets the FaceColor property with the 'flat' option:
flat — The values of CData determine the color for each face of the surface. The color data at the first vertex determine the color of the entire face.
In other words, the value will determine the shade.
Assuming your data is in data and your x and y coordinates are in x and y, here is how to do it:
imagesc(x, y, data) % to create a heat map
colormap(gray) % for gray levels
caxis([0 1]) % to set 0 to black and 1 to white
axis xy % if you want the y axis to point up
colorbar % to display the colorbar