要在dm-script 和python 在同一实例中运行时同步数据(本例中的线程,也可以针对不同线程进行修改),可以使用持久性标签 .
dm-script 正在设置持久标签。然后python 可以再次读取持久化标签。
更新:Python 模块
由于下面提到的限制以及令人难以置信的增长和不可读的代码,我决定为此编写自己的 python 模块。使用execdmscript,可以非常轻松地从 Digital Micrograph 执行具有变量同步的 dm-script 代码。
查看以下示例:
from execdmscript import exec_dmscript
# some script to execute
dmscript = """
number input;
number s = GetNumber("Enter a number between " + min + " and " + max + ".", init, input);"
"""
# variables that will be defined for the dm-scripts (and readable later on in python)
sv = {"min": 1, "max": 10, "init": 2}
# variables the dm-script defines and that should be readable in the python file
rv = {"input": "number", "s": "number"}
with exec_dmscript(dmscript, readvars=rv, setvars=sv) as script:
if script["s"]:
print(script["input"])
else:
print("User pressed cancel.")
这隐藏了所有与 dm-script 相关的保存和问题(如下所述)。它允许使用list 和dicts 以及bool、str、int 和float 等基本类型。所有类型和值都可以以 Python 方式使用,无需关心 dm-script 类型。 dm 脚本可以移动到一个单独的文件中以进一步清理代码。
请注意,为了调试,有一个exec_dmscript(debug=True, debug_file="path/to/file") 开关将代码保存到给定的debug_file。然后可以在显示错误的 GMS 中手动执行此文件。
免责声明:如前所述,我是execdmscript 模块的作者。我仍然认为这是这种情况下的最佳解决方案。事实上这个问题是我写这个模块的原因。
基本数据类型
对于string 和number 等基本数据类型,可以手动创建和添加代码。下面的例子展示了这个想法:
import DigitalMicrograph as DM
import time
sync_id = "sync-{}".format(int(time.time() * 100))
dmscript = """
number input;
number s = GetNumber("Enter a number between {min} and {max}.", {init}, input);
TagGroup p = GetPersistentTagGroup();
p.TagGroupSetTagAsBoolean("{id}-success", s);
p.TagGroupSetTagAsLong("{id}-input", input);
"""
DM.ExecuteScriptString(dmscript.format(min=1, max=10, init=2, id=sync_id))
# cannot save TagGroups to variables, check below
s, success = DM.GetPersistentTagGroup().GetTagAsBoolean("{}-success".format(sync_id))
if s and success:
# cannot save TagGroups to variables, check below
s, input = DM.GetPersistentTagGroup().GetTagAsLong("{}-input".format(sync_id))
if s:
print(input)
else:
print("Did not find 'input' in persistent tags.")
elif not s:
print("Did not find 'success' in persistent tags.")
else:
print("User clicked cancel.")
# cannot save TagGroups to variables, check below
# delete tag, otherwise the persistent tags gets filled with garbage
DM.GetPersistentTagGroup().DeleteTagWithLabel("{}-success".format(sync_id))
DM.GetPersistentTagGroup().DeleteTagWithLabel("{}-input".format(sync_id))
可以看出这种方法有一些缺点。只需输入一个数字,就有很多代码创建设置和同步。这使代码混乱。也有人可能希望将 dm-script 代码保存在一个单独的文件中,以添加 python 文件打开。在此代码中调试 dm-script 代码也很困难。最后,TagGroup 在 python 端的旅行也有限制(请参阅下文)。
限制
更新:下面提到的python模块可以处理TagGrous和TagLists,因为它将它们线性化并使用单独的键和类型保存。
注意TagGroups 很难同步。 TagGroups 不得分配给变量。一旦它们存在,它们就不再可用了。这可以通过以下非常简单的代码来说明:
import DigitalMicrograph as DM
# create group for the example
group1 = DM.NewTagGroup()
group1.SetTagAsString("test-string", "test content")
print("Group 1 valid:", group1.IsValid(), "(type:", type(group1), ")")
# save to persistent tags
DM.GetPersistentTagGroup().SetTagAsTagGroup("test", group1)
# get the group without assigning to a variable, works
s, group2 = DM.GetPersistentTagGroup().GetTagAsTagGroup("test")
print("Group 2 success:", s, ", valid:", group2.IsValid(), "(type:", type(group2), ")")
# assign one parent group to a variable, doesn't work
tags = DM.GetPersistentTagGroup()
s, group3 = tags.GetTagAsTagGroup("test")
print("Group 3 success:", s, ", valid:", group3.IsValid(), "(type:", type(group3), ")")
这段代码将产生输出
Group 1 valid: True (type: <class 'DigitalMicrograph.Py_TagGroup'> )
Group 2 success: True , valid: True (type: <class 'DigitalMicrograph.Py_TagGroup'> )
Group 3 success: True , valid: False (type: <class 'DigitalMicrograph.Py_TagGroup'> )
这表明您不能将TagGroups 分配给python 变量。
异步想法
这可以扩展为异步应用程序。 dm-script 和python 实现可以设置观察持久标签的线程。 (请注意,您可以使用TagGroupMarkAsChanged() 将TagGroups 标记为已修改),最好使用不同的标签。然后两者都可以向标签添加命令和/或数据。另一个“实例”可以读取和处理它们。
这必须手动编码。这(当前)不包含在 execdmscript 模块中。