Skip to content

Commit 9ffaabc

Browse files
committed
to_table is now the reference user API
1 parent dd5281e commit 9ffaabc

11 files changed

Lines changed: 65 additions & 28 deletions

File tree

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,9 @@ write_mtg("test.mtg",mtg)
5656
You can expose an MTG as a `Tables.jl` source:
5757

5858
```julia
59-
mtg_table(mtg)
60-
symbol_table(mtg, :Leaf)
59+
to_table(mtg)
60+
to_table(mtg, symbol=:Leaf)
61+
to_table(mtg, vars=[:Length, :Width])
6162
```
6263

6364
If you use `DataFrames.jl`, `DataFrame(mtg)` works out of the box through the `Tables.jl` interface.

docs/src/api.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ Notable attribute APIs:
77
- `attribute`, `attribute!`, `attributes`, `attribute_names`
88
- `add_column!`, `drop_column!`, `rename_column!`
99
- `descendants_strategy`, `descendants_strategy!` (choose automatic/direct/indexed descendants retrieval)
10-
- `to_table`, `symbol_table`, `mtg_table` (`Tables.jl` sources)
10+
- `to_table` (`Tables.jl` source/sink entry-point)
1111

1212
```@index
1313
```

docs/src/get_started.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,13 @@ descendants(mtg, :length_mm)
5353
Or by getting a tabular view of your MTG:
5454

5555
```@example usepkg
56-
mtg_table(mtg)
56+
to_table(mtg)
5757
```
5858

5959
You can also select only a subset of attributes:
6060

6161
```@example usepkg
62-
mtg_table(mtg, [:Length, :Width])
62+
to_table(mtg, vars=[:Length, :Width])
6363
```
6464

6565
Or directly transforming the MTG into a DataFrame:

docs/src/tutorials/2.descendants_ancestors_filters.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ get_attributes(get_root(node_5))
8787
A simple way to get all nodes and their attributes is to use the unified table view:
8888

8989
```@example usepkg
90-
mtg_table(mtg)
90+
to_table(mtg)
9191
```
9292

9393
## Descendants

docs/src/tutorials/3.transform_mtg.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ descendants(mtg, :length_m)
111111
We can also inspect values through the MTG table view:
112112

113113
```@example usepkg
114-
mtg_table(mtg)
114+
to_table(mtg)
115115
```
116116

117117
We can also provide several input variables if we need:
@@ -125,7 +125,7 @@ Here we provide the input attributes as a Vector of Symbols (could be String als
125125
Let's see the results:
126126

127127
```@example usepkg
128-
mtg_table(mtg)
128+
to_table(mtg)
129129
```
130130

131131
The new name of the attribute (the RHS) is optional though. We could write our first example as:
@@ -241,15 +241,15 @@ mtg_select = deepcopy(mtg)
241241
242242
select!(mtg_select, :Length => (x -> x / 10) => :length_m, :Width, ignore_nothing = true)
243243
244-
mtg_table(mtg_select)
244+
to_table(mtg_select)
245245
```
246246

247247
There is also a copy-returning version of the function (`select`, without `!`):
248248

249249
```@example usepkg
250250
mtg_select = select(mtg, :Length => (x -> x / 10) => :length_m, :Width, ignore_nothing = true)
251251
252-
mtg_table(mtg_select)
252+
to_table(mtg_select)
253253
```
254254

255255
## Traverse an MTG

docs/src/tutorials/4.convert_mtg.md

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ That's why `MultiScaleTreeGraph.jl` provides functions to expose an MTG as a `Ta
1515
To get a unified table view of the MTG, you can use:
1616

1717
```@example usepkg
18-
tbl = mtg_table(mtg)
18+
tbl = to_table(mtg)
1919
```
2020

2121
The unified table reports MTG topology columns plus all attributes:
@@ -30,19 +30,26 @@ The unified table reports MTG topology columns plus all attributes:
3030
If you only need a few attributes, you can select them directly:
3131

3232
```@example usepkg
33-
mtg_table(mtg, [:Width, :Length])
33+
to_table(mtg, vars=[:Width, :Length])
3434
```
3535

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

3838
```@example usepkg
39-
leaf_tbl = symbol_table(mtg, :Leaf)
39+
leaf_tbl = to_table(mtg, symbol=:Leaf)
4040
```
4141

4242
Per-symbol tables can also select attributes:
4343

4444
```@example usepkg
45-
symbol_table(mtg, :Leaf, [:Width, :Length])
45+
to_table(mtg, symbol=:Leaf, vars=[:Width, :Length])
46+
```
47+
48+
You can also materialize directly into a sink when available in your environment:
49+
50+
```julia
51+
using DataFrames
52+
df = to_table(mtg, vars=[:Width, :Length], sink=DataFrame)
4653
```
4754

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

docs/src/tutorials/6.add_remove_nodes.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ mtg
7070
And the attributes:
7171

7272
```@example usepkg
73-
mtg_table(mtg)
73+
to_table(mtg)
7474
```
7575

7676
### Inserting nodes

src/MultiScaleTreeGraph.jl

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,6 @@ export attribute, attribute!, attributes, attribute_names
9696
export add_column!, drop_column!, rename_column!
9797
export descendants_strategy, descendants_strategy!
9898
export columnarize!
99-
export symbol_table, mtg_table
10099
export to_table
101100
export list_nodes
102101
export get_classes

src/conversion/Tables.jl

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -227,18 +227,45 @@ function mtg_table(mtg::Node, vars=nothing)
227227
ColumnTable(names_, cols_)
228228
end
229229

230+
@inline function _materialize_table(source, sink)
231+
sink === nothing && return source
232+
233+
# Preferred path for Tables-compatible sinks (e.g. DataFrame type/instance).
234+
materializer = try
235+
Tables.materializer(sink)
236+
catch
237+
try
238+
Tables.materializer(typeof(sink))
239+
catch
240+
nothing
241+
end
242+
end
243+
materializer !== nothing && return materializer(source)
244+
245+
# Generic fallback for callable sinks, e.g. sink = x -> MyType(x)
246+
applicable(sink, source) && return sink(source)
247+
248+
error(
249+
"Unsupported sink $(sink). ",
250+
"Provide a Tables.jl sink (type or instance, e.g. DataFrame) or a callable that accepts a table."
251+
)
252+
end
253+
230254
"""
231-
to_table(mtg::Node; symbol=nothing, vars=nothing)
255+
to_table(mtg::Node; symbol=nothing, vars=nothing, sink=nothing)
256+
257+
Generic table conversion entry-point.
232258
233-
Convenience helper to get a Tables.jl-compatible view from an MTG.
234-
- `symbol=nothing`: unified traversal-ordered table (`mtg_table`)
235-
- `symbol=<symbol>`: per-symbol table (`symbol_table`)
259+
- `symbol=nothing`: unified traversal-ordered table
260+
- `symbol=<symbol>`: per-symbol table
236261
- `vars`: optional attribute selection (`Symbol`/`String`/vector/tuple)
262+
- `sink`: optional sink materialization (e.g. `sink=DataFrame` if `DataFrames.jl` is loaded)
237263
"""
238-
function to_table(mtg::Node; symbol=nothing, vars=nothing)
239-
symbol === nothing ? mtg_table(mtg, vars) : symbol_table(mtg, symbol, vars)
264+
function to_table(mtg::Node; symbol=nothing, vars=nothing, sink=nothing)
265+
source = symbol === nothing ? mtg_table(mtg, vars) : symbol_table(mtg, symbol, vars)
266+
_materialize_table(source, sink)
240267
end
241268

242269
Tables.istable(::Type{<:Node}) = true
243270
Tables.columnaccess(::Type{<:Node}) = true
244-
Tables.columns(mtg::Node) = mtg_table(mtg)
271+
Tables.columns(mtg::Node) = to_table(mtg)

src/print_MTG/print.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ function Base.print(node::Node; leading::AbstractString="", io::IO=stdout, limit
3131
end
3232

3333
function Base.print(node::Node, vars; leading::AbstractString="", io::IO=stdout)
34-
table = mtg_table(node)
34+
table = to_table(node)
3535
vars_ = vars isa Union{Tuple,AbstractVector} ? Symbol.(vars) : Symbol[Symbol(vars)]
3636
keep = Symbol[:node_id, :symbol, :scale, :index, :link, :parent_id]
3737
append!(keep, vars_)

0 commit comments

Comments
 (0)