EPG implementation that mimics the regular implementation from Julien Lamy in Sycomore

# Short description

Regular implementation use a constant positive or negative gradient dephasing. We use a vector Fp, Fn and Z to store the states.

# Initialization

EPG states are stored as a structure :

```
mutable struct EPGStates{T <: Real}
Fp::Vector{Complex{T}}
Fn::Vector{Complex{T}}
Z::Vector{Complex{T}}
end
```

which can be initialized with default parameters Fp = 0, Fn = 0 and Z = 1 states using :

```
using EPGsim
E = EPGStates()
```

```
EPGStates struct with fields : Fp, Fn, Z
```

or by :

`E = EPGStates(0,0,1)`

```
EPGStates struct with fields : Fp, Fn, Z
```

which convert any numbers of the same types in `Vector{ComplexF64}`

or directly by passing `Vector{Complex{T}} where {T <: Real}`

which means it can accept a complex{dual} type :

```
T = ComplexF32
E = EPGStates(T.([0.5+0.5im,1]),T.([0.5-0.5im,0]),T.([1,0]))
```

```
EPGStates struct with fields : Fp, Fn, Z
```

!!! Note Julia is a one based indexing language. Fp[1]/Fn[1]/Z[1] store the echo and correspond to the states commonly named $F_0^+$ / $F_0^-$ $Z_0$

the F+[1] and F-[1] states should be complex conjugate and imag(Z[1])=0

# EPG simulation

3 functions are used to simulate a sequence :

- epgDephasing
- epgRelaxation
- epgRotation

They take an `EPGStates`

struct as first parameter.

```
E = EPGStates()
E = epgRotation(E,deg2rad(60),0)
E = epgDephasing(E,1)
E = epgRotation(E,deg2rad(60),deg2rad(117))
```

Currently, all the EPGstates are stored and used for calculation. The states equal or really close to zero are not deleted

# Accessing states

States can seen directly as a vector :

`E.Fp`

```
1-element Vector{ComplexF64}:
0.0 + 0.0im
```

or by elements :

`E.Fp[2]`

`getStates`

is also available to create a 3xN matrix where 3 corresponds to Fp,Fn,Z and N is the number of states.

`getStates(E)`

```
3×1 Matrix{ComplexF64}:
0.0 + 0.0im
0.0 + 0.0im
1.0 + 0.0im
```