Skip to content

Commit 2441957

Browse files
committed
Add tutorials as tests
1 parent acba471 commit 2441957

18 files changed

Lines changed: 2499 additions & 71 deletions

.github/workflows/CI.yml

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
name: CI
2+
on:
3+
push:
4+
branches:
5+
- master
6+
tags: '*'
7+
pull_request:
8+
jobs:
9+
test:
10+
name: Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ matrix.arch }}
11+
runs-on: ${{ matrix.os }}
12+
strategy:
13+
matrix:
14+
version:
15+
- '1'
16+
os:
17+
- ubuntu-latest
18+
arch:
19+
- x64
20+
steps:
21+
- uses: actions/checkout@v4
22+
- uses: julia-actions/setup-julia@v1
23+
with:
24+
version: ${{ matrix.version }}
25+
arch: ${{ matrix.arch }}
26+
- uses: julia-actions/cache@v1
27+
- run: sudo apt-get update && sudo apt-get install -y xorg-dev mesa-utils xvfb libgl1 freeglut3-dev libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev libxext-dev xsettingsd x11-xserver-utils
28+
- name: Install Julia dependencies
29+
shell: julia {0}
30+
run: |
31+
using Pkg;
32+
# dev mono repo versions
33+
pkg"dev ."
34+
- name: Run the tests
35+
id: referencetests
36+
continue-on-error: true
37+
run: >
38+
DISPLAY=:0 xvfb-run -s '-screen 0 1024x768x24' julia --color=yes -e 'using Pkg; Pkg.test("VPL", coverage=true)'
39+
&& echo "TESTS_SUCCESSFUL=true" >> $GITHUB_ENV
40+
env:
41+
CI: true

.travis.yml

Lines changed: 0 additions & 26 deletions
This file was deleted.

JuliaFormatter.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
style = "sciml"

Project.toml

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,5 @@ PlantGeomTurtle = "0.0.1"
1717
PlantGraphs = "0.0.1"
1818
PlantRayTracer = "0.0.1"
1919
PlantViz = "0.0.1"
20+
Reexport = "1.2.2"
2021
julia = "1.9"
21-
22-
[extras]
23-
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
24-
25-
[targets]
26-
test = ["Test"]

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
# VPL
22

3-
[![Build Status](https://travis-ci.com/VirtualPlantLab/VPL.jl.svg?branch=master)](https://travis-ci.com/VirtualPlantLab/VPL.jl)
4-
[![Coverage](https://codecov.io/gh/VirtualPlantLab/VPL.jl/branch/master/graph/badge.svg)](https://codecov.io/gh/VirtualPlantLab/VPL.jl)
3+
[![Stable](https://img.shields.io/badge/docs-stable-blue.svg)](http://virtualplantlab.com/)
4+
[![CI](https://github.com/VirtualPlantLab/VPL.jl/actions/workflows/CI.yml/badge.svg)](https://github.com/VirtualPlantLab/VPL.jl/actions/workflows/CI.yml)
55
[![SciML Code Style](https://img.shields.io/static/v1?label=code%20style&message=SciML&color=9558b2&labelColor=389826)](https://github.com/SciML/SciMLStyle)
66
[![ColPrac: Contributor's Guide on Collaborative Practices for Community Packages](https://img.shields.io/badge/ColPrac-Contributor's%20Guide-blueviolet)](https://github.com/SciML/ColPrac)
77
[![Aqua QA](https://raw.githubusercontent.com/JuliaTesting/Aqua.jl/master/badge.svg)](https://github.com/JuliaTesting/Aqua.jl)
88

9-
Main package in the VPL ecosystem.
9+
Main package in the [Virtual Plant Lab](http://virtualplantlab.com/).

docs/Project.toml

Lines changed: 0 additions & 3 deletions
This file was deleted.

docs/make.jl

Lines changed: 0 additions & 19 deletions
This file was deleted.

docs/src/index.md

Lines changed: 0 additions & 14 deletions
This file was deleted.

test/Project.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
11
[deps]
22
Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595"
3+
ColorTypes = "3da002f7-5984-5a60-b8a6-cbb66c0b333f"
4+
Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f"
5+
FastGaussQuadrature = "442a2c76-b920-505d-bb47-c5924d526838"
6+
GLMakie = "e9467ef8-e4e7-5192-8a1a-b1aee30e663a"
7+
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
8+
SkyDomes = "1838625c-7cf7-40c6-898b-904883e4b556"
39
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

test/algae.jl

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
#=
2+
Algae growth
3+
4+
Alejandro Morales - May 2023
5+
6+
In this first example, we learn how to create a `Graph` and update it
7+
dynamically with rewriting rules.
8+
9+
The model described here is based on the non-branching model of [algae
10+
growth](https://en.wikipedia.org/wiki/L-system#Example_1:_Algae) proposed by
11+
Lindermayer as one of the first L-systems.
12+
13+
First, we need to load the VPL metapackage, which will automatically load all
14+
the packages in the VPL ecosystem.
15+
=#
16+
using VPL
17+
18+
#=
19+
The rewriting rules of the L-system are as follows:
20+
21+
**axiom**: A
22+
23+
**rule 1**: A $\rightarrow$ AB
24+
25+
**rule 2**: B $\rightarrow$ A
26+
27+
In VPL, this L-system would be implemented as a graph where the nodes can be of
28+
type `A` or `B` and inherit from the abstract type `Node`. It is advised to
29+
include type definitions in a module to avoid having to restart the Julia
30+
session whenever we want to redefine them. Because each module is an independent
31+
namespace, we need to import `Node` from the VPL package inside the module:
32+
=#
33+
module algae
34+
import VPL: Node
35+
struct A <: Node end
36+
struct B <: Node end
37+
end
38+
import .algae
39+
40+
let
41+
#=
42+
Note that in this very example we do not need to store any data or state inside
43+
the nodes, so types `A` and `B` do not require fields.
44+
45+
The axiom is simply defined as an instance of type of `A`:
46+
=#
47+
axiom = algae.A()
48+
49+
#=
50+
The rewriting rules are implemented in VPL as objects of type `Rule`. In VPL, a
51+
rewriting rule substitutes a node in a graph with a new node or subgraph and is
52+
therefore composed of two parts:
53+
54+
1. A condition that is tested against each node in a graph to choose which nodes
55+
to rewrite.
56+
2. A subgraph that will replace each node selected by the condition above.
57+
58+
In VPL, the condition is split into two components:
59+
60+
1. The type of node to be selected (in this example that would be `A` or `B`).
61+
2. A function that is applied to each node in the graph (of the specified type)
62+
to indicate whether the node should be selected or not. This function is
63+
optional (the default is to select every node of the specified type).
64+
65+
The replacement subgraph is specified by a function that takes as input the node
66+
selected and returns a subgraph defined as a combination of node objects.
67+
Subgraphs (which can also be used as axioms) are created by linearly combining
68+
objects that inherit from `Node`. The operation `+` implies a linear
69+
relationship between two nodes and `[]` indicates branching.
70+
71+
The implementation of the two rules of algae growth model in VPL is as follows:
72+
=#
73+
rule1 = Rule(algae.A, rhs = x -> algae.A() + algae.B())
74+
rule2 = Rule(algae.B, rhs = x -> algae.A())
75+
76+
#=
77+
Note that in each case, the argument `rhs` is being assigned an anonymous (aka
78+
*lambda*) function. This is a function without a name that is defined directly
79+
in the assigment to the argument. That is, the Julia expression `x -> A() + B()`
80+
is equivalent to the following function definition:
81+
=#
82+
function rule_1(x)
83+
algae.A() + algae.B()
84+
end
85+
86+
#=
87+
For simple rules (especially if the right hand side is just a line of code) it
88+
is easier to just define the right hand side of the rule with an anonymous
89+
function rather than creating a standalone function with a meaningful name.
90+
However, standalone functions are easier to debug as you can call them directly
91+
from the REPL.
92+
93+
With the axiom and rules we can now create a `Graph` object that represents the
94+
algae organism. The first argument is the axiom and the second is a tuple with
95+
all the rewriting rules:
96+
=#
97+
organism = Graph(axiom = axiom, rules = (rule1, rule2))
98+
99+
#=
100+
If we apply the rewriting rules iteratively, the graph will grow, in this case
101+
representing the growth of the algae organism. The rewriting rules are applied
102+
on the graph with the function `rewrite!()`:
103+
=#
104+
rewrite!(organism)
105+
106+
#=
107+
Since there was only one node of type `A`, the only rule that was applied was
108+
`rule1`, so the graph should now have two nodes of types `A` and `B`,
109+
respectively. We can confirm this by drawing the graph. We do this with the
110+
function `draw()` which will always generate the same representation of the
111+
graph, but different options are available depending on the context where the
112+
code is executed. By default, `draw()` will create a new window where an
113+
interactive version of the graph will be drawn and one can zoom and pan with the
114+
mouse.
115+
=#
116+
import GLMakie
117+
draw(organism)
118+
119+
#=
120+
Notice that each node in the network representation is labelled with the type of
121+
node (`A` or `B` in this case) and a number in parenthesis. This number is a
122+
unique identifier associated to each node and it is useful for debugging
123+
purposes (this will be explained in more advanced examples).
124+
125+
Applying multiple iterations of rewriting can be achieved with a simple loop:
126+
=#
127+
for i = 1:4
128+
rewrite!(organism)
129+
end
130+
131+
# And we can verify that the graph grew as expected:
132+
draw(organism)
133+
134+
# The network is rather boring as the system is growing linearly (no branching)
135+
# but it already illustrates how graphs can grow rapidly in just a few
136+
# iterations. Remember that the interactive visualization allows adjusting the
137+
# zoom, which is handy when graphs become large.
138+
end

0 commit comments

Comments
 (0)