【问题标题】:Good practices for formatting simulation output格式化模拟输出的良好做法
【发布时间】:2011-06-17 20:36:20
【问题描述】:

这几乎是一个编程问题,但面向物理学家。

假设我正在编写一个软件,它接受一些系统参数作为输入,然后从中计算一些东西,在我的例子中是一个谱函数 $A(k,\omega)$。

当我只想获取输出并将其提供给 gnuplot 时,我应该让程序输出一个简单的表,其中一列用于 $k$ 值,一列用于 $\omega$,一列用于 $A(k ,\omega)$。

但是我不能在那里存储所有附加信息,例如使用了哪些参数。也许我想在该输出中存储一些额外的调试信息,例如中间量。在我的示例中,谱函数是从自身能量中获得的,因此在某些情况下,我可能想直接查看自身能量。

我不想根据我想要的输出不断破解源代码。如果所有“运行”的相关数据都存在于单个文件/实体中会更好,但这样仍然可以轻松提取我可以提供给 gnuplot 的表。

不想重新发明轮子并开发成熟的文件格式,是否有一些“标准”最适合用于创建、处理和存储来自计算或模拟的数据?甚至可能是 SQL 数据库格式?

【问题讨论】:

  • 这是关于尚未制定的computation science提案的主题。
  • 这也是 Stack Overflow 上的话题,因为它本质上是一个编程话题。您希望将元数据与数据一起保留。正如目标工具所见,我总是在 cmets 中发出带有元数据的文件,但格式是我可以解析的。假设以“#”开头的行对两者都是 cmets,但以“##”开头的行是要由我的工具处理的元数据(我认为这适用于 gnuplot)。
  • 我的意图是将其迁移到 SO,但我会为 cmets 留出一些时间。你可以试着改变我的想法。
  • 既然我也有一个 SO 帐户,我不会介意 :)

标签: simulation


【解决方案1】:

有几十种方法,没有一种太好;我将分享两个我的:

  1. 如果该程序值得,我会添加一个配置文件的小型解析器。然后我只做一个配置,比如说SimA.in,模拟器会用相应的数据SimA.pathsSimA.statsSimA.log等生成一堆文件。除非名称是唯一的,否则我添加代码的版本记录,这使得结果完全可重现,并且模拟本身具有足够的便携性,易于管理。
  2. 如果没有,我只需稍微包装一下代码,然后使用R 作为主机。然后我只返回所有数组和标量(R 数据结构非常灵活,很容易转换原生 R 或 C 结构)并使用 R 来管理、保存/加载,当然还有可视化和分析数据。此外,使用 Sweave 和 CacheSweave 可以将整个执行、分析和报告打包成一个优雅的集合,通过一个命令完全可重现。

如果您想要“企业”解决方案,请尝试NetCDFHDF5。但我觉得这里可能有点矫枉过正。

当然,模拟器代码的版本控制是必须的。但这很明显 =)

【讨论】:

    【解决方案2】:

    对于我目前正在处理的使用 Python 和 C++(通过 SWIG)的项目,我计划使用一个简短的 Python 脚本作为输入文件。因此,在某种程度上,我将“破解源代码”来更改参数,但使用的是解释语言,而不是编译语言。

    目前,我计划有一个像parameters.py 这样的输入文件,并像from parameters import params 一样使用它。但这可能过于依赖正确的语法。

    params = {
    "foods" : ["spam", "beans", "eggs"],
    "costs" : [199, 4, 1],
    "customerAge" : 23,
    }
    

    另一种选择可能是在parameters2.py 中的脚本级别定义变量。这失去了漂亮的字典包装,但让用户更难搞砸它。编写一个将这些脚本级变量放入一个不错的字典的“解析器”可能并不难。该方法的一个优点是用户可以参数化最初没有考虑过的东西——from parameters2 import * 会覆盖这些参数的先前定义。当然,如果用户覆盖了重要的内容,这可能会很糟糕。

    foods = ["spam", "beans", "eggs"]
    costs = [199, 4, 1]
    customerAge = 23
    

    parameters3.py 会使用一个类,尽管 Python 对缩进的顽固禁忌它。 from parameters3 import params:

    class params:
        foods = ["spam", "beans", "eggs"]
        costs = [199, 4, 1]
        customerAge = 23
    

    为了完整起见,我还应该提到,我们的 C++ 代码还定义了一个参数类。也就是说,在我们的实际项目中,parameters.py 是对应 C++ 类的 SWIG 包装器。你会使用from parameters4 import params。但是,这仅允许已在 C++ 类中声明的参数。

    import parameters
    params = parameters.Parameters()
    params.foods = ["spam", "beans", "eggs"]
    params.costs = [199, 4, 1]
    params.customerAge = 23
    

    【讨论】:

    • 我刚刚意识到您关心的是输出,而不是输入。我想那时我的想法根本不适用。对不起。
    • 我进一步意识到,无论如何,有一个 configparser 模块在这方面做得更好。我将在下周针对这个特定项目进行此操作。
    猜你喜欢
    • 2016-01-26
    • 1970-01-01
    • 1970-01-01
    • 2023-03-16
    • 1970-01-01
    • 2011-07-13
    • 1970-01-01
    • 2011-02-14
    相关资源
    最近更新 更多