@@ -42,6 +45,7 @@ The crucial part here are the individual parts used to build the sequence, defin
...
@@ -42,6 +45,7 @@ The crucial part here are the individual parts used to build the sequence, defin
:gradient2=>g2,
:gradient2=>g2,
nothing,
nothing,
:readout=>readout_event(...),
:readout=>readout_event(...),
nothing
]
]
```
```
...
@@ -49,6 +53,17 @@ We can see that this sequence is built in order by an excitation pulse, some unk
...
@@ -49,6 +53,17 @@ We can see that this sequence is built in order by an excitation pulse, some unk
Some of these components have been given specific names (e.g., `:excitation => ...`). This is optional, but can be useful to refer to individual components. There are [helper functions](@ref helper_functions) available to create these components.
Some of these components have been given specific names (e.g., `:excitation => ...`). This is optional, but can be useful to refer to individual components. There are [helper functions](@ref helper_functions) available to create these components.
After creating the sequence object, we can now add secondary objectives to the cost function (using [`add_cost_function!`](@ref)).
If we check the order of the sequence component, we see that this minimises the sum of the duration of the second gradient and the wait block before this gradient.
This cost function has been added to maximise the time between the second gradient and the readout (and hence minimise the effect of eddy currents on the readout).
Note that this is a secondary cost function that will only take effect if it does not interfere with any user-defined constraints and cost functions (see [sequence optimisation](@ref sequence_optimisation)).
Some secondary cost functions will be automatically defined for you within the individual components (e.g., a trapezoidal gradient has a secondary cost function to maximise the slew rate).
There is even a tertiary cost function, which minimises the total sequence duration.
The next step is to define [summary variables](@ref variables) that the user can constrain when setting up a specific instance of this sequence:
The next step is to define [summary variables](@ref variables) that the user can constrain when setting up a specific instance of this sequence:
@@ -11,6 +11,10 @@ In addition to the user-defined constraints, this optimisation will also take in
...
@@ -11,6 +11,10 @@ In addition to the user-defined constraints, this optimisation will also take in
Internally, MRIBuilder will then optimise the `BuildingBlock` free parameters to match any user-defined constraints and/or objectives.
Internally, MRIBuilder will then optimise the `BuildingBlock` free parameters to match any user-defined constraints and/or objectives.
This optimisation uses the [Ipopt](https://github.com/coin-or/Ipopt) optimiser accessed through the [JuMP.jl](https://jump.dev/JuMP.jl/stable/) library.
This optimisation uses the [Ipopt](https://github.com/coin-or/Ipopt) optimiser accessed through the [JuMP.jl](https://jump.dev/JuMP.jl/stable/) library.
In addition to any user-defined objectives, the developer might also define secondary objectives (e.g., manimise the total sequence duration).
These objective functions will only be considered if they do not affect the result of the user-defined primary objective.
More details on these developer-defined secondary objectives can be found in the section on [defining new sequences](@ref defining_sequences)
## [Summary variables](@id variables)
## [Summary variables](@id variables)
All variables are available as members of the [`variables`](@ref) structure.
All variables are available as members of the [`variables`](@ref) structure.
@@ -462,6 +462,8 @@ Terms added at a lower level will be optimised before any terms with a higher le
...
@@ -462,6 +462,8 @@ Terms added at a lower level will be optimised before any terms with a higher le
By default, the term is added to the `level=2`, which is appropriate for any cost functions added by the developer,
By default, the term is added to the `level=2`, which is appropriate for any cost functions added by the developer,
which will generally only be optimised after any user-defined cost functions (which are added at `level=1` by [`add_simple_constraint!`](@ref) or [`set_simple_constraints!`](@ref).
which will generally only be optimised after any user-defined cost functions (which are added at `level=1` by [`add_simple_constraint!`](@ref) or [`set_simple_constraints!`](@ref).
Any sequence will also have a `level=3` cost function, which minimises the total sequence duration.