Converting MTGs

We can do a lot using the MTG format, but sometimes we want our data in another format.

That's why MultiScaleTreeGraph.jl provides functions to expose an MTG as a Tables.jl source, or convert it into a graph.

MTG to table

To get a unified table view of the MTG, you can use:

tbl = to_table(mtg)
Symbols: Scene  Individual  Axis  Internode  Leaf
Scales:  0      1           2     3          3   
                           Attributes Table (7 x 11)
╭───┬─────────┬────────────┬───────┬───────┬────────┬───────────┬──────────┬────
│    node_id      symbol  scale  index    link  parent_id    XEuler    ⋯
│      Int64      Symbol  Int64  Int64  Symbol     Int64?  Float64?  F ⋯
├───┼─────────┼────────────┼───────┼───────┼────────┼───────────┼──────────┼────
│ 1 │       1 │      Scene │     0 │     0 │      / │   missing │  missing │   ⋯
│ 2 │       2 │ Individual │     1 │     0 │      / │         1 │  missing │   ⋯
│ 3 │       3 │       Axis │     2 │     0 │      / │         2 │  missing │   ⋯
│ 4 │       4 │  Internode │     3 │     0 │      / │         3 │      1.0 │   ⋯
│ 5 │       5 │       Leaf │     3 │     0 │      + │         4 │  missing │   ⋯
│ 6 │       6 │  Internode │     3 │     1 │      < │         4 │    180.0 │   ⋯
│ 7 │       7 │       Leaf │     3 │     0 │      + │         6 │  missing │   ⋯
╰───┴─────────┴────────────┴───────┴───────┴────────┴───────────┴──────────┴────
                                                               4 columns omitted

The unified table reports MTG topology columns plus all attributes:

  • node_id: the unique ID of the node in the whole MTG
  • symbol: the node symbol
  • scale: the node scale
  • index: the node index
  • parent_id: the node's parent id
  • link: the link between the node and its parent

symbols and scales are shown as table metadata in the display header (not as columns).

If you only need a few attributes, you can select them directly:

to_table(mtg, vars=[:Width, :Length])
Symbols: Scene  Individual  Axis  Internode  Leaf
Scales:  0      1           2     3          3   
                            Attributes Table (7 x 8)
╭───┬─────────┬────────────┬───────┬───────┬────────┬───────────┬──────────┬────
│    node_id      symbol  scale  index    link  parent_id     Width    ⋯
│      Int64      Symbol  Int64  Int64  Symbol     Int64?  Float64?  F ⋯
├───┼─────────┼────────────┼───────┼───────┼────────┼───────────┼──────────┼────
│ 1 │       1 │      Scene │     0 │     0 │      / │   missing │  missing │   ⋯
│ 2 │       2 │ Individual │     1 │     0 │      / │         1 │  missing │   ⋯
│ 3 │       3 │       Axis │     2 │     0 │      / │         2 │  missing │   ⋯
│ 4 │       4 │  Internode │     3 │     0 │      / │         3 │     0.02 │   ⋯
│ 5 │       5 │       Leaf │     3 │     0 │      + │         4 │      0.1 │   ⋯
│ 6 │       6 │  Internode │     3 │     1 │      < │         4 │     0.02 │   ⋯
│ 7 │       7 │       Leaf │     3 │     0 │      + │         6 │      0.1 │   ⋯
╰───┴─────────┴────────────┴───────┴───────┴────────┴───────────┴──────────┴────
                                                                1 column omitted

It is also possible to get a per-symbol table:

leaf_tbl = to_table(mtg, symbol=:Leaf)
Symbols: Scene  Individual  Axis  Internode  Leaf
Scales:  0      1           2     3          3   
                            Attributes Table (2 x 5)
╭───┬─────────┬─────────────────────┬─────────────────────┬──────────────────┬──
│    node_id               Length                Width           isAlive │ ⋯
│      Int64  U{Nothing, Float64}  U{Nothing, Float64}  U{Nothing, Bool} │ ⋯
├───┼─────────┼─────────────────────┼─────────────────────┼──────────────────┼──
│ 1 │       5 │                 0.2 │                 0.1 │            false │ ⋯
│ 2 │       7 │                 0.2 │                 0.1 │             true │ ⋯
╰───┴─────────┴─────────────────────┴─────────────────────┴──────────────────┴──
                                                                1 column omitted

Per-symbol tables can also select attributes:

to_table(mtg, symbol=:Leaf, vars=[:Width, :Length])
Symbols: Scene  Individual  Axis  Internode  Leaf
Scales:  0      1           2     3          3   
                 Attributes Table (2 x 3)
╭───┬─────────┬─────────────────────┬─────────────────────╮
│    node_id                Width               Length │
│      Int64  U{Nothing, Float64}  U{Nothing, Float64} │
├───┼─────────┼─────────────────────┼─────────────────────┤
│ 1 │       5 │                 0.1 │                 0.2 │
│ 2 │       7 │                 0.1 │                 0.2 │
╰───┴─────────┴─────────────────────┴─────────────────────╯

You can also materialize directly into a sink when available in your environment:

using DataFrames
df = to_table(mtg, vars=[:Width, :Length], sink=DataFrame)

If you use DataFrames.jl in your own project, DataFrame(mtg) still works because MTGs implement the Tables.jl interface.

using DataFrames
df = DataFrame(mtg)

MTG to MetaGraph

We can convert an MTG into a MetaGraph using MetaGraph():

mg = MetaGraph(mtg)
Meta graph based on a Graphs.SimpleGraphs.SimpleDiGraph{Int64} with vertex labels of type Int64, vertex metadata of type MultiScaleTreeGraph.ColumnarAttrs, edge metadata of type Symbol, graph metadata given by "MTG", and default weight 1.0

This is particularly useful if you want to benefit from the algorithm provided by Graphs.jl and MetaGraphsNext.jl, such as writing into more standard formats such as DOTFormat or MGFormat (or any other available from GraphIO.jl), plotting with GraphPlot.jl or NetworkLayout.jl, or computing e.g. flow with GraphsFlows.jl.