Transfer functions
MPIFiles defines the type TransferFunction
which represents the system-properties of a linear time-invariant system in frequency space (see also). In the context of MPIFiles this usually includes the properties of the receive chain of an MPI system, but can also hold information about other parts of the signal chain.
Basic construction and data access
The TransferFunction
object is constructed from samples in frequency space and offers two ways to access the underlying data. The first uses indexing to directly access the underlying data:
julia> f = collect(range(0,1e6,step=1e3)); # TransferFunction of a simple lowpass filter
julia> tf = TransferFunction(f, 1 ./ (1 .+ im*f/1e4 ))
MPIFiles.TransferFunction: 1 channel(s), units of ["NoUnits"] 1001 frequency samples from 0.0 Hz to 1.0e6 Hz
julia> tf[1] # Value of tf at first frequency sample (f = 0 Hz)
1.0 - 0.0im
The second method has to be called on the object itself and uses linear interpolation to access the tf at any frequency:
julia> tf(0) # Value of tf at f = 0 Hz
1.0 - 0.0im
julia> tf(1e4) # Value of tf at f = 10000 Hz
0.5 - 0.5im
A TransferFunction
can have multiple channels, which adds a second index to both data access functions. Directly accessing multiple channels is also possible. The complex array used to construct the TransferFunction
needs to have the shape [number of frequency samples, channels].
julia> tf = TransferFunction(f, [1 ./(1 .+im*f/1e4) 1 ./(1 .+im*f/1e3)])
MPIFiles.TransferFunction: 2 channel(s), units of ["NoUnits", "NoUnits"] 1001 frequency samples from 0.0 Hz to 1.0e6 Hz
julia> tf[11,1]
0.5 - 0.5im
julia> tf[11,2]
0.009900990099009901 - 0.09900990099009901im
julia> tf(1e4,1)
0.5 - 0.5im
julia> tf(1e4,2)
0.009900990099009901 - 0.09900990099009901im
julia> tf(1e4, [1,2])
1×2 Matrix{ComplexF64}: 0.5-0.5im 0.00990099-0.0990099im
julia> tf(1e4,:)
1×2 Matrix{ComplexF64}: 0.5-0.5im 0.00990099-0.0990099im
Units
To attach units to the TransferFunction
the keyword-parameter units
can to be used to give a Unitful
unit to every channel of the tf. This can be useful if the transfer function is not dimensionless but relates two physical quantities, e.g. voltage and current in the form of an impedance. All interpolated accesses to tf data then return a Unitful.Quantity
.
julia> R = 1; # Ohm
julia> L = 10e-6; # Henry
julia> RL = TransferFunction(f, R .+ im*2pi*f*L, units=["V/A"])
MPIFiles.TransferFunction: 1 channel(s), units of ["V/A"] 1001 frequency samples from 0.0 Hz to 1.0e6 Hz
julia> RL([0,100e3])
2-element Vector{Unitful.Quantity{ComplexF64, 𝐋^2 𝐌 𝐈^-2 𝐓^-3, Unitful.FreeUnits{(A^-1, V), 𝐋^2 𝐌 𝐈^-2 𝐓^-3, nothing}}}: (1.0 + 0.0im) V A^-1 (1.0 + 6.283185307179586im) V A^-1
Saving and loading
A TransferFunction
object can be saved to and loaded from a .h5 file.
FileIO.save
— Methodsave(filename::String, tf::TransferFunction)
Save tf
as a h5 file to filename
MPIFiles.TransferFunction
— MethodTransferFunction(
filename::String;
kargs...
) -> TransferFunction
Create a TransferFunction
from a data file at filename
.
The file can be either a h5-File created with this package. Keyword arguments will be passed to load_tf_fromVNA
Additional constructors
In addition to the constructor taking a single (complex) array it is also possible to give two arrays representing amplitude and phase.
It is also possible to construct a TransferFunction
from the transfer function data included in an MPIFile
.
MPIFiles.TransferFunction
— MethodTransferFunction(
freq::Vector{<:Real},
ampdata::Array{<:Real, N},
phasedata::Array{<:Real, N};
kwargs...
) -> TransferFunction
Create a TransferFunction
from separate amplitude and phase arrays at frequencies freq
.
ampdata
and phasedata
should have the following shape: [frequencies, channels]
MPIFiles.TransferFunction
— MethodTransferFunction(file::MPIFile) -> TransferFunction
Create a TransferFunction
from the tf data saved in a MPIFile (see rxTransferFunction
)
Other interesting functions
MPIFiles.TransferFunction
— Typemutable struct TransferFunction
freq::Vector{Float64}
data::Matrix{ComplexF64}
interpolator::Vector{Interpolations.AbstractInterpolation}
inductionFactor::Vector{Float64}
units::Vector{Unitful.FreeUnits}
TransferFunction(freq_::Vector{<:Real}, datain::Array{<:Complex}; inductionFactor::Vector{<:Real}=ones(size(datain, 2)), units::Vector=Unitful.FreeUnits[Unitful.NoUnits for i in 1:size(datain, 2)])
Create a TransferFunction
from a complex data array at frequencies freq_
.
Optional Keyword-Arguments:
inductionFactor::Vector{<:Real}
: induction factor for each channelunits::Vector
: units for each channel, can be either Unitful.FreeUnits or a string that can be parsed as a Unitful unit
MPIFiles.combine
— Methodcombine(
tf1::TransferFunction,
tf2::TransferFunction;
interpolate
) -> TransferFunction
Combine two TransferFunctions
along their channel dimension. If interpolate=false, will only work if the frequency samples are identical.