1

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!

Amro
  • 123,847
  • 25
  • 243
  • 454
user132039
  • 99
  • 6

1 Answers1

14

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

enter image description here

Community
  • 1
  • 1
RTL
  • 3,577
  • 15
  • 24
  • 3
    +1, I think this is one of the cases where [life isn't fair](http://meta.stackexchange.com/questions/202652/life-isnt-fair). Great answer! =) – Stewie Griffin Jul 18 '14 at 12:59
  • @RobertP. Thank you, I can identify with that meta post... I'm just glad at least one other person has seen this! ...Although somehow the paste bin has had 160 hits to this questions 27... – RTL Jul 18 '14 at 13:23
  • 1
    +1 good answer. nitpick: `combvec` comes from the Neural Network Toolbox, the OP specifically wanted a solution without toolboxes. It's easily replaced with `[X,Y] = ndgrid(1:20); testdata = [X(:) Y(:)];` – Amro Jul 18 '14 at 15:15
  • also the `arrayfun` call towards the end can be simplified: `set(hline, {'LineWidth'}, num2cell(normalisedWeights*5))` – Amro Jul 18 '14 at 15:27
  • @Amro excellent points...I'm so used to have the additional licences I forgot to check, also I forgot about passing cell arrays to set, as ever anyone should feel free to add these changes, or I will myself when I'm back infront of a computer... – RTL Jul 18 '14 at 15:51
  • 1
    It seems like sometimes, sand *does* turn into pearls. Great answer! http://blog.stackoverflow.com/2011/06/optimizing-for-pearls-not-sand/ – Cape Code Jul 21 '14 at 17:14
  • @RTL: I hope I helped raise some attention to your answer and made life a bit more fair in the process... Please keep on providing quality answers like this one =) Cheers! – Stewie Griffin Jul 23 '14 at 21:45
  • @RobertP. What can I say, Thank you again! – RTL Jul 24 '14 at 07:57