You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
* automation 11 example
* up version and update message
* use Scratch.jl for update messages
* some typos
* correct usage of Scratch.jl
* Add some corrections
* try with init version
* fix double `init` existing.
Co-authored-by: Sebastian Pech <sebastian.pech@me.com>
To install, simply type `] add DrWatson` in your Julia session.
23
22
DrWatson is part of [JuliaDynamics](https://juliadynamics.github.io/JuliaDynamics/), check out our [website](https://juliadynamics.github.io/JuliaDynamics/) for more cool stuff!
Copy file name to clipboardExpand all lines: docs/src/real_world.md
+35-3Lines changed: 35 additions & 3 deletions
Original file line number
Diff line number
Diff line change
@@ -100,12 +100,11 @@ and each file is a dictionary that has my data fields: `:U, :V, :simulation`, bu
100
100
101
101
## Customizing `savename`
102
102
Here is a simple example for customizing [`savename`](@ref). We are using a common struct `Experiment` across different experiments with cats and mice.
103
-
In this example we are also using Parameters.jl for a convenient default constructor.
104
103
105
104
We first define the relevant types.
106
105
```@example customizing
107
106
using DrWatson, Dates
108
-
using Base: @kwdef
107
+
using Base: @kwdef # for defining structs with keyword values
109
108
110
109
# Define a type hierarchy we use at experiments
111
110
abstract type Species end
@@ -126,7 +125,7 @@ e1 = Experiment()
126
125
e2 = Experiment(species = Cat())
127
126
```
128
127
129
-
For analyzing our experiments we need information about the species used, and to use multiple dispatch latter on we decided to make this information associated with a Type. This is why we defined `Species`.
128
+
For analyzing our experiments we need information about the species used, and to use multiple dispatch later on we decided to make this information associated with a Type. This is why we defined `Species`.
130
129
131
130
Now, we want to customize [`savename`](@ref). We start by extending [`DrWatson.default_prefix`](@ref):
2021-05-1919:20:28| n =4| error =0.11| maxrss =326.27 MiB
515
514
2021-05-1919:20:29| n =5| error =0.15| maxrss =326.27 MiB
516
515
```
516
+
517
+
## Taking project input-output automation to 11
518
+
The point of this section is to show how far one can take the interplay between [`savename`](@ref) and [`produce_or_load`](@ref) to **automate project input-to-output and eliminate as many duplicate lines of code as possible**. Read [Customizing `savename`](@ref) first, as knowledge of that section is used here.
519
+
520
+
The key ingredient is that [`produce_or_load`](@ref) was made to work well with [`savename`](@ref). You can use this to automate the input-to-output pipeline of your project by following these steps:
521
+
1. Define a custom struct that represents the input configuration for an experiment or a simulation.
522
+
2. Extend [`savename`](@ref) appropriately for it.
523
+
3. Define a "main" function that takes as input an instance of this configuration type, and returns the output of the experiment or simulation as dictionary (We're not changing here the "default" way to save files in Julia as `.jld2` files. To save files this way you need your data to be in a dictionary with `Symbol` as keys).
524
+
4. All your input-output scripts are simply put together by first defining the input configuration type, and then calling [`produce_or_load`](@ref) with your pre-defined "main" function (Alternatively, this function can internally call `produce_or_load` and return something else that is of special interest to your specific case).
525
+
526
+
An example of where this approach is used in the "real world" is e.g. in our paper [Effortless estimation of basins of attraction](https://arxiv.org/abs/2110.04358). Its codebase is here: https://github.com/Datseris/EffortlessBasinsOfAttraction. Don't worry, you need to know nothing about the topic to follow the rest. The point is that we needed to run some kind of simulations for many different dynamical systems, which have different parameters, different dimensionality, etc. But they did have one thing in common: our output was always coming from the same function, `basins_of_attraction`, which allowed using the pipeline we discuss here using [`produce_or_load`](@ref).
527
+
528
+
So we defined a struct called `BasinConfig` that stored configuration options and system parameters. Then we extended `savename` for it. We defined some function `produce_basins` that takes this configuration file, initializes a dynamical system accordingly, and then makes the output **using `produce_or_load`**. This ensures that we're not running simulations twice if they exist. And keep in mind when you have so many parameters and different possible systems, it is quite easy to unintentionally run the same simulation twice because you "forgot about it". All of this can be found in this file: https://github.com/Datseris/EffortlessBasinsOfAttraction/blob/master/src/produce_basins.jl
529
+
530
+
The benefit? All of our scripts that actually produce what we care about are this short:
and more importantly, the only lines that are genuinely "copy-pasted" from script to script are the last two. All other lines are unique for each script. This minimization of copy-pasting duplicate information makes the workflow robust and makes bugs easier to find.
0 commit comments