AnyMath 文档
Notebook

建模数据处理

中我们来看看如何从模型中获取仿真数据,以及如何在AnyMath脚本中正确高效地处理接收到的数据。

导言

有两种方法可以确保在仿真过程中记录的模型信号立即进入工作区。:

  1. [Simout]变形量(https://engee.com/helpcenter/stable/cn/feature/about-simout.html )。
  2. 使用[到现场]https://engee.com/helpcenter/stable/cn/base-lib-sinks/to-workspace.html )。

每个都有自己的优点和缺点,以及具体的使用方法。

1. 我们使用 simout

1.1. 获取变量

以便将来自模型的必要数据写入变量 simout,您需要执行以下操作:

  1. 美信号。
  2. 启用选项"将模拟结果保存到桌面область".

为方便操作,建议为记录的信号定义一个名称。

image.png

现在,在执行模型后,我们在工作区中获得一个变量 simout:

In [ ]:
model1_path = "$(@__DIR__)/simulation1.engee" 
engee.load(model1_path) |> engee.run; # 上传并执行模型
engee.close(engee.gcm(), force=true) # 模型被关闭了

simout
Out[0]:
SimulationResult(
    run_id => 8,
    "simulation1/sin_5Hz" => WorkspaceArray{Float64}("simulation1/sin_5Hz")
,
    "simulation1/sin_2Hz" => WorkspaceArray{Float64}("simulation1/sin_2Hz")
,
    "simulation1/Генератор синусоиды.1" => WorkspaceArray{Float64}("simulation1/Генератор синусоиды.1")
,
    "simulation1/two_sin" => WorkspaceArray{Vector{Float64}}("simulation1/two_sin")

)

1.2. 变量处理 simout

在接收到的变量 simout,在字典中 dict对键(信号名称)=>值(信号时间和值/值的向量)被存储:

In [ ]:
# 我们从simout获取所有信号的名称
dict_keys = simout.dict |> keys |> collect 
Out[0]:
4-element Vector{String}:
 "simulation1/sin_5Hz"
 "simulation1/sin_2Hz"
 "simulation1/Генератор синусоиды.1"
 "simulation1/two_sin"

第一个键的值 - simulation/sin_5Hz 他们会看起来像这样:

In [ ]:
collect(simout.dict["simulation1/sin_5Hz"])
Out[0]:
101×2 DataFrame
76 rows omitted
Rowtimevalue
Float64Float64
10.00.0
20.010.309017
30.020.587785
40.030.809017
50.040.951057
60.051.0
70.060.951057
80.070.809017
90.080.587785
100.090.309017
110.11.22465e-16
120.11-0.309017
130.12-0.587785
⋮⋮⋮
900.890.309017
910.91.10218e-15
920.91-0.309017
930.92-0.587785
940.93-0.809017
950.94-0.951057
960.95-1.0
970.96-0.951057
980.97-0.809017
990.98-0.587785
1000.99-0.309017
1011.0-1.22465e-15

也就是说,在字典的意思 dict 为我们的信号的名称 simulation/sin_5Hz 对象被存储[WorkspaceArray](https://engee.com/helpcenter/stable/cn/guide/workspacearray.html 中带字段 time 和 value. 通过访问这些字段,您可以获取信号的时间戳和值本身并绘制图形。:

In [ ]:
t1 = simout.dict["simulation1/sin_5Hz"].time
val1 = simout.dict["simulation1/sin_5Hz"].value
gr(format=:png)
plot(t1, val1; label="simulation1/sin_5Hz")
Out[0]:
No description has been provided for this image

1.3. 矢量信号在 value

我们在上面构造的信号是标量的--在一个时间点,记录了一个类型的值 Float64.
考虑信号的另一种情况 simulation/two_sin -价值向量 Float64:

In [ ]:
simout.dict["simulation1/two_sin"].value[1] # 我们从simulation/two_sin信号的值数组中获取第一个元素
Out[0]:
2-element Vector{Float64}:
 0.0
 0.0

如您所见,这是两个值的向量。 场会告诉我们同样的事情。 dimension 字典 dict

In [ ]:
simout.dict["simulation1/two_sin"].dimension # 获取存储在维度字段中的值
Out[0]:
(2,)

由此得出:字段值的维度 value - 2×1. 你将无法以与以前相同的方式构建它们。:

In [ ]:
t2 = simout.dict["simulation1/two_sin"].time
val2 = simout.dict["simulation1/two_sin"].value

plot(t2, val2; label="simulation1/two_sin")
Out[0]:
print device already activated
print device already activated

为了获取单个信号的索引数组并构建它们,我们使用 getindex():

In [ ]:
val2_1 = getindex.(val2, 1)
val2_2 = getindex.(val2, 2)

plot(t2, val2_1; label="simulation1/two_sin[1]")
plot!(t2, val2_2; label="simulation1/two_sin[2]")
Out[0]:
No description has been provided for this image
print device already activated

1.4. 未命名信号

如果在仿真过程中没有确定信号线上的信号的名称,则在 simout 它将由块名称和它起源的端口号决定。

In [ ]:
collect(simout.dict["simulation1/Генератор синусоиды.1"])
Out[0]:
101×2 DataFrame
76 rows omitted
Rowtimevalue
Float64Float64
10.00.0
20.010.425779
30.020.770513
40.030.968583
50.040.982287
60.050.809017
70.060.481754
80.070.0627905
90.08-0.368125
100.09-0.728969
110.1-0.951057
120.11-0.992115
130.12-0.844328
⋮⋮⋮
900.890.992115
910.90.951057
920.910.728969
930.920.368125
940.93-0.0627905
950.94-0.481754
960.95-0.809017
970.96-0.982287
980.97-0.968583
990.98-0.770513
1000.99-0.425779
1011.0-1.71451e-15

这个选项当然有效,但与命名信号相比,它不那么美观,更难以识别,也不太方便处理。

1.5. 变薄

我们传递到的数组的维度 plot() 要建立一个图形,它只是:

In [ ]:
simout.dict["simulation1/sin_5Hz"].value |> size # 我们确定simulation1/sin_5Hz信号的值的向量的维数
Out[0]:
(101,)

向量中的101个元素 gr() 后端 Plots,甚至与图像格式 format = :png 它相当快地显示在图表上。

例如,如果您尝试构建映像 svg 在交互式后端 plotlyjs() 对于100,000个元素的向量,您将不得不使用更多的资源和时间。

如果不是每个点对可视化都很重要,则可以使用最简单的选项-懒惰片WorkspaceArray:

In [ ]:
simout.dict["simulation1/sin_5Hz"].value[1:2:end]  |> size # 我们以步骤2获得信号值的向量,并定义一个新的维度
Out[0]:
(51,)

惰性数组切片允许您使用不是所有值进行构造,而是在步骤2([1:2:end])或其他([1:3:end], [1:4:end], [1:5:end] 等等)。

一个懒惰的切片也将有助于突出信号的开始([1:20])或结束([40:end]).

这种方法便于细化恒定的、轻微变化的和谐波信号。 当对后者进行细化时,有必要使用Kotelnikov定理-细化后信号中的最大频率必须小于新采样频率的一半才能满足奈奎斯特条件。

对于具有非周期瞬变的信号,应使用更灵活的抽取方法,估计信号变化并根据其变化的动态进行抽取。

2. 我们使用到工作区块

2.1. 获取变量

为了将来自模型的必要数据记录在工作区中,您需要执行以下操作:

  1. 为一个很好的包装物[toworkspace]?https://engee.com/helpcenter/stable/cn/base-lib-sinks/to-workspace.html )。
  2. 给写在块中的变量命名

中,您需要非常小心-必须考虑到[命名变量的规则]来设置块中的变量名称(https://engee.com/helpcenter/stable/cn/julia/manual/variables.html 中朱莉娅。

image.png

现在,在执行模型后,我们在工作区中获取具有块中指定名称的变量。

In [ ]:
model2_path = "$(@__DIR__)/simulation2.engee" 
engee.load(model2_path) |> engee.run; # 上传并执行模型
engee.close(engee.gcm(), force=true) # 模型被关闭了

sin_2Hz, sin_5Hz, two_sin, Генератор_синусоиды
Out[0]:
(WorkspaceArray{Float64}("sin_2Hz"), WorkspaceArray{Float64}("sin_5Hz"), WorkspaceArray{Vector{Float64}}("two_sin"), WorkspaceArray{Float64}("Генератор_синусоиды"))

2.2. 处理变量

这些变量也有类型 WorspaceArray,以及我们在第1.2和1.3节中使用的相同处理方法适用于它们。

2.3减薄

除了第1.5节中提到的软件抽取方法外,预先使用标准块方法降低采样率也很方便。:

*新的复盖式复盖式复盖式复盖式复盖式复盖式复盖式复盖式复盖式复盖,
*使用[速度萝卜]?https://engee.com/helpcenter/stable/cn/base-lib-signal-attributes/rate-transition.html )(成功的成功时间。

降低采样率(采样时间:-1->0.1)

image.png

采样率之间的转换:

image.png

结论

这两种方法都允许您组织仿真结果的软件处理。 在第二种情况下,更多地使用普通的方法。 在第二种情况下,必须为每个记录的信号安装额外的块。

这里的决定因素是需求、能力和用户方便性。