Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improves @icon and adds related docs #2346

Merged
merged 2 commits into from
Nov 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 44 additions & 10 deletions docs/src/basics/MTKModel_Connector.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ equations.
- `@components`: for listing sub-components of the system
- `@equations`: for the list of equations
- `@extend`: for extending a base system and unpacking its states
- `@icon` : for embedding the model icon
- `@parameters`: for specifying the symbolic parameters
- `@structural_parameters`: for specifying non-symbolic parameters
- `@variables`: for specifing the states
Expand All @@ -50,6 +51,7 @@ end
end

@mtkmodel ModelC begin
@icon "https://github.com/SciML/SciMLDocs/blob/main/docs/src/assets/logo.png"
@structural_parameters begin
f = sin
end
Expand All @@ -58,6 +60,7 @@ end
end
@variables begin
v(t) = v_var
v_array(t)[1:2, 1:3]
end
@extend ModelB(; p1)
@components begin
Expand All @@ -69,6 +72,41 @@ end
end
```

#### `@icon`

An icon can be embedded in 3 ways:

- URI
- Path to a valid image-file.<br>
It can be an absolute path. Or, a path relative to an icon directory; which is
`DEPOT_PATH[1]/mtk_icons` by default and can be changed by setting
`ENV["MTK_ICONS_DIR"]`.<br>
Internally, it is saved in the _File URI_ scheme.

```julia
@mtkmodel WithPathtoIcon begin
@icon "/home/user/.julia/dev/mtk_icons/icon.png"
# Rest of the model definition
end
```

- Inlined SVG.

```julia
@mtkmodel WithInlinedSVGIcon begin
@icon """<svg height="100" width="100">
<circle cx="50" cy="50" r="40" stroke="green" fill="none" stroke-width="3"/>
</svg>
"""
# Rest of the model definition
end
```

#### `@structural_parameters` begin block

- This block is for non symbolic input arguements. These are for inputs that usually are not meant to be part of components; but influence how they are defined. One can list inputs like boolean flags, functions etc... here.
- Whenever default values are specified, unlike parameters/variables, they are reflected in the keyword argument list.

#### `@parameters` and `@variables` begin block

- Parameters and variables are declared with respective begin blocks.
Expand All @@ -80,15 +118,10 @@ end
```julia
julia> @mtkbuild model_c1 = ModelC(; v = 2.0);

julia> ModelingToolkit.getdefault(model_c.v)
julia> ModelingToolkit.getdefault(model_c1.v)
2.0
```

#### `@structural_parameters` begin block

- This block is for non symbolic input arguements. These are for inputs that usually are not meant to be part of components; but influence how they are defined. One can list inputs like boolean flags, functions etc... here.
- Whenever default values are specified, unlike parameters/variables, they are reflected in the keyword argument list.

#### `@extend` begin block

- Partial systems can be extended in a higher system as `@extend PartialSystem(; kwargs)`.
Expand Down Expand Up @@ -209,11 +242,12 @@ For example, the structure of `ModelC` is:

```julia
julia> ModelC.structure
Dict{Symbol, Any} with 6 entries:
Dict{Symbol, Any} with 7 entries:
:components => [[:model_a, :ModelA]]
:variables => Dict{Symbol, Dict{Symbol, Any}}(:v=>Dict(:default=>:v_var), :v_array=>Dict(:size=>(4,)))
:variables => Dict{Symbol, Dict{Symbol, Any}}(:v=>Dict(:default=>:v_var), :v_array=>Dict(:size=>(2, 3)))
:icon => URI("https://github.com/SciML/SciMLDocs/blob/main/docs/src/assets/logo.png")
:kwargs => Dict{Symbol, Any}(:f=>:sin, :v=>:v_var, :v_array=>nothing, :model_a__k_array=>nothing, :p1=>nothing)
:independent_variable => t
:extend => Any[[:p1, :p2], :model_b, :ModelB]
:equations => ["model_a.k1 ~ f(v)"]
:extend => Any[[:p2, :p1], Symbol("#mtkmodel__anonymous__ModelB"), :ModelB]
:equations => ["model_a.k ~ f(v)"]
```
19 changes: 8 additions & 11 deletions src/systems/model_parsing.jl
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,8 @@
elseif mname == Symbol("@equations")
parse_equations!(exprs, eqs, dict, body)
elseif mname == Symbol("@icon")
parse_icon!(icon, dict, mod, body)
isassigned(icon) && error("This model has more than one icon.")
parse_icon!(icon, dict, body)

Check warning on line 263 in src/systems/model_parsing.jl

View check run for this annotation

Codecov / codecov/patch

src/systems/model_parsing.jl#L262-L263

Added lines #L262 - L263 were not covered by tests
else
error("$mname is not handled.")
end
Expand Down Expand Up @@ -471,7 +472,7 @@
dict[:equations] = readable_code.(eqs)
end

function parse_icon!(icon, dict, mod, body::String)
function parse_icon!(icon, dict, body::String)

Check warning on line 475 in src/systems/model_parsing.jl

View check run for this annotation

Codecov / codecov/patch

src/systems/model_parsing.jl#L475

Added line #L475 was not covered by tests
icon_dir = get(ENV, "MTK_ICONS_DIR", joinpath(DEPOT_PATH[1], "mtk_icons"))
dict[:icon] = icon[] = if isfile(body)
URI("file:///" * abspath(body))
Expand All @@ -483,17 +484,13 @@
false
end
URI(body)
elseif (_body = lstrip(body); startswith(_body, r"<\?xml|<svg"))
String(_body) # With Julia-1.10 promoting `SubString{String}` to `String` can be dropped.

Check warning on line 488 in src/systems/model_parsing.jl

View check run for this annotation

Codecov / codecov/patch

src/systems/model_parsing.jl#L487-L488

Added lines #L487 - L488 were not covered by tests
else
error("$body is not a valid icon")
error("\n$body is not a valid icon")

Check warning on line 490 in src/systems/model_parsing.jl

View check run for this annotation

Codecov / codecov/patch

src/systems/model_parsing.jl#L490

Added line #L490 was not covered by tests
end
end

function parse_icon!(icon, dict, mod, body::Expr)
_icon = body.args[end]
dict[:icon] = icon[] = MLStyle.@match _icon begin
::Symbol => get_var(mod, _icon)
::String => _icon
Expr(:call, read, a...) => eval(_icon)
_ => error("$_icon isn't a valid icon")
end
function parse_icon!(icon, dict, body::Expr)
parse_icon!(icon, dict, eval(body))

Check warning on line 495 in src/systems/model_parsing.jl

View check run for this annotation

Codecov / codecov/patch

src/systems/model_parsing.jl#L494-L495

Added lines #L494 - L495 were not covered by tests
end
2 changes: 1 addition & 1 deletion test/icons/resistor.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 3 additions & 7 deletions test/model_parsing.jl
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,7 @@ end
@components begin
g = Pin()
end
@icon begin
read(abspath(ENV["MTK_ICONS_DIR"], "ground.svg"), String)
end
@icon read(abspath(ENV["MTK_ICONS_DIR"], "ground.svg"), String)
@equations begin
g.v ~ 0
end
Expand All @@ -76,10 +74,9 @@ resistor_log = "$(@__DIR__)/logo/resistor.svg"
@parameters begin
R, [unit = u"Ω"]
end
@icon begin
"""<?xml version="1.0" encoding="UTF-8"?>
@icon """<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="80" height="30">
<path d="M10 15
<path d="M10 15
l15 0
l2.5 -5
l5 10
Expand All @@ -91,7 +88,6 @@ l2.5 -5
l15 0" stroke="black" stroke-width="1" stroke-linejoin="bevel" fill="none"></path>
</svg>
"""
end
@equations begin
v ~ i * R
end
Expand Down
Loading