3

I have a social network graph that I have made in Matlab using the graph object:

G = graph(weight);
LWidths = 10*G.Edges.Weight/max(G.Edges.Weight);
h = plot(G,'NodeLabel',cellstr(screen_names),'LineWidth',LWidths);
for i = 1:nnodes
    highlight(h,i, 'MarkerSize', counts(i))
end

where weight is an adjacency matrix, and counts is a vector with the node sizes. It looks something like this:

Now, I'm not happy with how this looks, so I want to make it with Tikz instead. So my question is: is it possible to produce this type of graph with Tikz from an adjacency matrix where the edges are of different width taken to be the nonzero elements of the matrix. The size of the nodes should also be different. I'm not very experienced in Tikz, so any guidance in how to proceed would be highly appreciated.

I have read this similar post, but I'm still not sure how to handle different edge widths and node sizes. Also, is it required to explicitly give the coordinates for the nodes or can they be automatically generated, as in Matlab?

Here is the weight matrix:

weight =

     0   741   630   406   325   325   351     0   300   276
   741     0   406   351   276     0     0     0     0     0
   630   406     0   300     0   276   300     0     0     0
   406   351   300     0     0     0     0     0     0     0
   325   276     0     0     0     0     0     0     0     0
   325     0   276     0     0     0   276     0     0     0
   351     0   300     0     0   276     0     0     0     0
     0     0     0     0     0     0     0     0     0     0
   300     0     0     0     0     0     0     0     0     0
   276     0     0     0     0     0     0     0     0     0

and counts vector:

counts = 

    56    42    39    34    32    31    30    29    28    28
joakimj
  • 33
  • 3
    One possible starting point could be to see what matlab2tikz gives you as output TikZ code and tweak that as desired. – Dai Bowen Apr 06 '17 at 13:44
  • I've tried that, and I get this: "I don't know how to handle this object: graph plot" – joakimj Apr 06 '17 at 13:47
  • Ah, that's unfortunate, could you add some example data which you want to plot so we have more to play with? – Dai Bowen Apr 06 '17 at 13:51
  • Can't matlab export to tex? Else you could work with the positioning option of tikz. A possible code would look like: \node (node1) {}; then just positioning relative to it: \node[below left] (node3) at (node1) {};

    Through this you will initialize all your coordinates. Once this is done, just use \draw (node3) circle (radius in mm or cm); or \fill[color=blue] (node3) circle (radius);

    This will fit your graph, except the grid. But this can easily be added.

    – Shalec Apr 06 '17 at 13:58
  • The grid is not necessary, I actually don't want it at all. But it would be good if I could produce the plot from the data in the matrix. Because I want to make more than one plot but for different matrices and it becomes tedious if I would have to manually place all the nodes. But this would work, and it might be what I end up doing, just wanted to check if there is an easier way. – joakimj Apr 06 '17 at 14:03
  • Do you have the pgfplots package in your header when you try matlab2tikz? – Scott Seidman Apr 06 '17 at 14:12
  • @ScottSeidman The error occurs in Matlab when I try to run the matlab2tikz script. This is the full error message: Error using matlab2tikz>handleAllChildren (line 730) I don't know how to handle this object: graphplot – joakimj Apr 06 '17 at 14:19

1 Answers1

4

A bit crude, but sort of works OK and requires lualatex. A simple parser (which just matches on non-whitespace) plus a graph drawing macro.

\RequirePackage{luatex85}
\documentclass[tikz,border=5]{standalone}
\usetikzlibrary{graphs,graphdrawing}
\usegdlibrary{force,trees}
\usepackage{luacode}
\begin{luacode*}
function parseNetwork(nodeWeights, adjacencyMatrix)
  local i, j, n, v, w, str
  n = 0
  weights = {}
  for str in string.gmatch(nodeWeights, "[^%s]+") do
    w = tonumber(str)
        tex.print("n" .. n + 1 .. "/[minimum size=" .. w .. ", label=center:node" .. n  + 1 .. "];")
      n = n + 1
  end
  i = 0
  j = 0
  for str in string.gmatch(adjacencyMatrix, "[^%s]+") do
    v = tonumber(str)
      if v > 0 then
        if j > i then
        tex.print("n" .. i + 1 ..  " --[line width=" .. (v / 100) .. "]" .. "n" .. j + 1 .. ";")
        end
      end
        j = (j + 1) % n
        if j == 0 then i = i + 1 end
  end
end
\end{luacode*}
\tikzgraphsset{%
  node weights/.store in=\nodeweights,
  adjacency matrix/.store in=\adjacencymatrix,
  declare={network}{
  [/utils/exec={%
    \edef\networkspec{\directlua{parseNetwork("\nodeweights","\adjacencymatrix")}}},
    parse/.expanded=\networkspec] 
}}
\begin{document}
\begin{tikzpicture}
\graph [spring electrical layout, 
  edges={draw=blue!50!cyan, shorten >=-1em, shorten <=-1em}, 
  nodes={circle, fill=blue!50!cyan!50},
  electric charge=10]{
    network [
      node weights={
    56    42    39    34    32    31    30    29    28    28
    },
      adjacency matrix={
     0   741   630   406   325   325   351     0   300   276
   741     0   406   351   276     0     0     0     0     0
   630   406     0   300     0   276   300     0     0     0
   406   351   300     0     0     0     0     0     0     0
   325   276     0     0     0     0     0     0     0     0
   325     0   276     0     0     0   276     0     0     0
   351     0   300     0     0   276     0     0     0     0
     0     0     0     0     0     0     0     0     0     0
   300     0     0     0     0     0     0     0     0     0
   276     0     0     0     0     0     0     0     0     0
}]; 
};
\end{tikzpicture}
\end{document}

enter image description here

Mark Wibrow
  • 70,437