The MDDatasets.jl module provides tools to simplify manipulation of multi-dimensional datasets.
→ GitHub - ma-laforge/MDDatasets.jl: Multi-Dimensional Datasets for Parametric Analysis
Insallation:
] add MDDatasets
Grouping (x,y) vectors
MDDatasets also provides a means to group (x,y)
data in a single data structure to simplify calculations (DataF1
structure). For example, we can take the derivative of a dataset (wrt x
) very simply using:
(Using MDDatasets.jl:)
#Assuming f1 has time-domain data y=f(x=t):
slope = deriv(f1)
Note that internally, f1
contains both y
values, and x
values (which represent time, t
). This is much more straightforward than the typical way to do differentiation:
(WITHOUT the help of MDDatasets.jl:)
#Assuming we have f1_x & f1_y data:
deltax = f1_x[2:end] .- f1_x[1:end-1]
deltay = f1_y[2:end] .- f1_y[1:end-1]
slope = deltay ./ deltax
AUTOMATIC INTERPOLATION
Note that operations on DataF1
objects will automatically interpolate intermediate values if the x
sample points don’t match. This is particularly useful if you wish to perform operations on results collected from multiple simulations that have different/non-uniform time steps (or whatever the x-values might represent).
Multi-Dimensional Data & “Parametric Analysis”
MDDatasets.jl
is designed to store values from a “Parametric Analysis”. Basically, you re-run the same experiments with different conditions by “sweeping” the values of different control variables in order to see how they affect results.
For example, you might want to simulate circuit behaviour by “sweeping” the following parameters:
for vSupply in [0.9V, 1V, 1.1V]
for temp in [-40, 0, 100, 125]
for trise in 10e-12:10e-12:100e-12
#Read in data & compute characteristics that might be insighful
end
end
end
With MDDatasets.jl, the procedure is a bit more straightforward…
Step 1: Collect Data in Multi-Dimensional Dataset using DataRS
To build a multi-dimensional dataset, you would “fill” a DataRS
structure:
signal1 = fill(DataRS, PSweep("tbit", [1, 3, 9] * 1e-9)) do tbit
fill(DataRS, PSweep("VDD", 0.9 * [0.9, 1, 1.1])) do vdd
#Inner-most sweep: need to specify element type (DataF1):
fill(DataRS{DataF1}, PSweep("trise", [0.1, 0.15, 0.2] * tbit)) do trise
y = get_ydata(tbit, vdd, trise) #Read in y values
x = get_xdata(tbit, vdd, trise) #Read in x values
return DataF1(x, y) #"Leaf" elements of DataRS structure are DataF1 containers.
end
end
end
This assumes get_xdata()
& get_ydata()
functions retrieve simulation data at certain values of tbit
, vdd
, & trise
.
Indeed, this DOES seem like alot, but you only have to read in data once. Once data is read in, performing the actual calculations becomes much more straightforward and easy to read/write (see below).
Step 2: Run Calculations
Assuming vin
& vout
are DataRS
structures storing the input & output voltages of a closed-loop op-amp time-domain simulation, one could easily compute the gain error over all of the simulated time:
gainideal = 6 #Desired gain of op-amp
#Compute error in gain value, over time:
error = 100 * ((vout/vin) - gainideal) / gainideal
NOTE:
- There is no need for explicit
for
loops. MDDatasets.jl automatically broadcasts operations over all “swept” parameters. - There is no need for the “dot” notation (
.+
,.*
, …). Unlike withArray
objects,DataRS
structures are not meant to natively support matrix operations (matrix multiplication, etc). Consequently, there is no confusion between element-by-element & matrix operations.
Sample Usage
More advanced uses of the MDDatasets.jl
module can be found in the (not-yet-registered) SignalProcessing.jl
module: