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    dateDeath │
│      Int64  Float64?  Float64?    Bool?  Dates.Date? │
├───┼─────────┼──────────┼──────────┼─────────┼─────────────┤
│ 1 │       5 │      0.2 │      0.1 │   false │  2022-08-24 │
│ 2 │       7 │      0.2 │      0.1 │    true │     missing │
╰───┴─────────┴──────────┴──────────┴─────────┴─────────────╯

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  Float64?  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.