How to get subtree from symbolic expression? in ModelingToolkit.jl

My apologies if this has already been addressed.

Let’s say we have

using ModelingToolkit
@variables t x(t) y(t) z(t)
ex = x * y + z

How should I extract the sub-expression x * y from ex? It’s not clear to me how I’d traverse the expression tree in the documentation, nor did I see any way to do this via filtering.

I don’t seek to build a function. I’m fine with the output being an expression or string x * y. I want to extract products to populate nodes in a graph later on. For now, all the expressions would just have sums and products, and I’d want to get all the products.

I could do split(string(ex), ['+', '-']), and use this result, and am currently working on this route. I still wonder if I’m not seeing a better way.

ModelingToolkit is built on Symbolics and SymbolicUtils, that is the place to look for low-level expression manipulation like this. Here is an example (not complete and minimally tested).

using Symbolics

function products(expr)
    ex = Symbolics.unwrap(expr)
    terms = arguments(ex)
    products = filter(terms) do t
        istree(t) && ((operation(t) == *) || (operation(t) == ^))
    end
end
julia> ex = x * y + z + z*x + y*y
z(t) + x(t)*y(t) + x(t)*z(t) + y(t)^2

julia> products(ex)
3-element Vector{Any}:
 x(t)*y(t)
 x(t)*z(t)
 y(t)^2

Thank you; this is helpful. I hadn’t seen Symbolics.unwrap in the symbolics documentation, and I would have never thought of using filter with operation that way!