数字显微摄影中dm脚本与python的通信

数字显微摄影中dm脚本与python的通信,python,synchronization,dm-script,communicate,Python,Synchronization,Dm Script,Communicate,我如何在dm脚本code和python代码之间进行协调,两者都是在数字显微照片中执行的 在我的特殊情况下,我有复杂的对话。因为在python中不支持对话框,但是在dm script中,我在dm script中编写了对话框。现在的问题是从对话框传递到python代码 考虑以下示例: 将数字显微照片作为DM导入 script=“”字符串字段_值=“”; 类按钮对话框:UIFrame{ 无效字段\已更改(对象自身、标记组字段){ field_value=field.DLGGetStringValue

我如何在
dm脚本
code和
python
代码之间进行协调,两者都是在数字显微照片中执行的


在我的特殊情况下,我有复杂的对话。因为在
python
中不支持对话框,但是在
dm script
中,我在
dm script
中编写了对话框。现在的问题是从对话框传递到python代码

考虑以下示例:

将数字显微照片作为DM导入
script=“”字符串字段_值=“”;
类按钮对话框:UIFrame{
无效字段\已更改(对象自身、标记组字段){
field_value=field.DLGGetStringValue();
}
对象初始化(对象自身){
标记组dlg,dlg_项,字段;
dlg=DLGCreateDialog(“键入一个数字”,dlg_项);
dlg.DLGAddElement(DLGCreateLabel(“编号”);
field=DLGCreateIntegerField(0,10,“字段_已更改”);
dlg.DLGAddElement(字段);
self.super.init(dlg);
回归自我;
}
}
objectdialog=alloc(ButtonDialog.init();
dialog.pose();
"""
DM.ExecuteScriptString(脚本)
#我怎么得到这个?
字段_值=“”

要在
dm script
python
之间同步数据,同时两者都在同一个实例中运行(在本例中,线程也可以针对不同的线程进行修改),可以使用持久标记

dm脚本
正在设置持久标记
python
然后可以再次读取持久标记


更新:Python模块 由于下面提到的限制以及不断增长且不可读的代码,我决定为此编写自己的python模块。有了它,就可以很容易地从数字显微照片执行带有变量同步的dm脚本代码

请查看以下示例:

从execdmscript导入exec\u dmscript
#一些要执行的脚本
dmscript=“”
数字输入;
数字s=GetNumber(“输入一个介于“+min+”和“+max+”之间的数字”,初始化,输入);”
"""
#将为dm脚本定义的变量(稍后在python中可读)
sv={“最小”:1,“最大”:10,“初始”:2}
#dm脚本定义的变量,在python文件中应该是可读的
rv={“输入”:“编号”,“s”:“编号”}
使用exec_dmscript(dmscript,readvars=rv,setvars=sv)作为脚本:
如果脚本[“s”]:
打印(脚本[“输入”])
其他:
打印(“用户按取消”)
这隐藏了所有与dm脚本相关的保存和问题(如下所述)。它允许使用
list
dict
以及基本类型,如
bool
str
int
float
。所有类型和值都可以以pythonic方式使用,而无需关心dm脚本类型。dm脚本可以移动到单独的文件中,以进一步清理代码

请注意,对于调试,有一个
exec\u dmscript(debug=True,debug\u file=“path/to/file”)
开关将代码保存到给定的
debug\u文件
。然后可以在GMS中手动执行该文件,其中显示错误

免责声明:如前所述,我是该模块的作者。但我认为这是解决该案例的最佳方案。事实上,这个问题就是我编写该模块的原因


基本数据类型 对于基本数据类型,如
string
number
,可以手动创建和添加代码。下面的示例说明了这一想法:

将数字显微照片作为DM导入
导入时间
sync_id=“sync-{}”.format(int(time.time()*100))
dmscript=“”
数字输入;
数字s=GetNumber(“输入一个介于{min}和{max}之间的数字,{init},输入);
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))
#无法将标记组保存到变量,请检查以下内容
s、 success=DM.GetPersistentTagGroup().GetTagAsBoolean(“{}-success.format(sync_id))
如果成功与否:
#无法将标记组保存到变量,请检查以下内容
s、 input=DM.GetPersistentTagGroup().GetTagAsLong(“{}-input.format(sync_id))
如果是:
打印(输入)
其他:
打印(“在永久性标记中未找到“输入”。)
elif不是s:
打印(“在持久标记中未找到“成功”。)
其他:
打印(“用户单击取消”)
#无法将标记组保存到变量,请检查以下内容
#删除标记,否则持久性标记将被垃圾填充
DM.GetPersistentTagGroup().DeleteTagWithLabel(“{}-success.”格式(sync_id))
DM.GetPersistentTagGroup().DeleteTagWithLabel(“{}-input.”格式(sync_id))
正如我们可以看到的那样,这种方法有一些缺点。只需输入一个数字,就有大量代码创建设置和同步。这使得代码混乱。此外,可能需要将dm脚本代码保存在单独的文件中,添加python文件打开。在这段代码中调试dm脚本代码也很困难。最后还有标记组在python端的移动有一些限制(请查看下面的内容)


局限性 更新:下面提到的python模块可以处理
TagGrou
s和
TagList
s,因为它将它们线性化并使用单独的键和类型保存

请注意,
TagGroup
s很难同步。
TagGroup
s不得分配给变量。变量一旦分配给变量,就不再可用。这可以通过以下非常简单的代码来说明:

将数字显微照片作为DM导入
#为示例创建一个组
group1=DM.NewTagGroup()
group1.SetTagaString(“测试字符串”、“测试内容”)
打印(“组1有效:”,组1.IsValid(),“(类型:”,类型(组1),”)
#保存到永久性标记
DM.GetPersistentTagGroup().SetTagAsTagGroup(“测试”,组1)
#获取组而不指定变量wor
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'> )
// //////////////////////////////////////////////////
// Helper methods 
// Build the DM-String representing the PythonScript
// which is then called
// //////////////////////////////////////////////////
string AddPythonValueIN( number val, string valName, string valType )
{
    string py
    py += "\n#Get value DM->Python via global tags" + "\n"
    py += "success, " + valName + " = DM.GetPersistentTagGroup().GetTagAs" + valType + "('Python_temp:in:" + valName + "')" + "\n"
    py += "if False == success:" + "\n"
    py += "    print( 'Error. No value passed in by DM-script sucessfully.' )" + "\n"
    py += "    exit(0)" + "\n"
    return py
}

string AddPythonValueIN( string val, string valName, string valType )
{
    string py
    py += "\n#Get value DM->Python via global tags" + "\n"
    py += "success, " + valName + " = DM.GetPersistentTagGroup().GetTagAs" + valType + "('Python_temp:in:" + valName + "')" + "\n"
    py += "if False == success:" + "\n"
    py += "    print( 'Error. No value passed in by DM-script sucessfully.' )" + "\n"
    py += "    exit(0)" + "\n"
    return py
}

string AddPythonValueOut( string valName, string valType )
{
    string py
    py += "\n#Get value Python->DM via global tags" + "\n"
    py += "DM.GetPersistentTagGroup().SetTagAs" + valType + "('Python_temp:out:" + valName + "'," + valName + ")" + "\n"
    return py
}

string AddPythonPrintModifyPrint()
{
    string py
    py += "\n#Print InValue, modify, print OutValue" + "\n"
    py += "print('InValue',InValue)"+ "\n"
    py += "OutValue = InValue * 2" + "\n"
    py += "print('OutValue',OutValue)"+ "\n"
    return py
}

// //////////////////////////////////////////////////
// Example calls 
// Demonstrating value passing from DM script to a 
// called Python snippet. TagTypes need to be 
// explicit in Python.
// //////////////////////////////////////////////////
void PythonValueInAndOut_Float()
{
    number value = 13.2
    GetPersistentTagGroup().TagGroupSetTagAsFloat("Python_temp:in:InValue",value)
    
    Result( " DM-Script passed value in: " + value + "\n")
    
    string py = "#Script to demonstrate value passing in Hybrid scripts. DM calling Python." + "\n"
    py += AddPythonValueIN( value, "InValue", "Float" )
    py += AddPythonPrintModifyPrint() 
    py += AddPythonValueOut( "OutValue", "Float" )
    
    Result( "\n PYTHON CODE EXECUTES\n --------------------- \n\n" )
    ExecutePythonScriptString( py, 1 )
    Result( "\n --------------------- \n PYTHON CODE FINISHED \n\n" )
    
    if ( !GetPersistentTagGroup().TagGroupGetTagAsFloat("Python_temp:out:OutValue",value))
        Throw("Python value passed out not found.")
        
    Result( "DM-Script received value: " + value + "\n")
    
    GetPersistentTagGroup().TagGroupDeleteTagWithLabel("Python_temp")
}

void PythonValueInAndOut_Double()
{
    number value = 13.2
    GetPersistentTagGroup().TagGroupSetTagAsDouble("Python_temp:in:InValue",value)
    
    Result( " DM-Script passed value in: " + value + "\n")
    
    string py = "#Script to demonstrate value passing in Hybrid scripts. DM calling Python." + "\n"
    py += AddPythonValueIN( value, "InValue", "Double" )
    py += AddPythonPrintModifyPrint() 
    py += AddPythonValueOut( "OutValue", "Double" )
    
    Result( "\n PYTHON CODE EXECUTES\n --------------------- \n\n" )
    ExecutePythonScriptString( py, 1 )
    Result( "\n --------------------- \n PYTHON CODE FINISHED \n\n" )
    
    if ( !GetPersistentTagGroup().TagGroupGetTagAsDouble("Python_temp:out:OutValue",value))
        Throw("Python value passed out not found.")
        
    Result( "DM-Script received value: " + value + "\n")
    
    GetPersistentTagGroup().TagGroupDeleteTagWithLabel("Python_temp")
}

void PythonValueInAndOut_String()
{
    string value = "hallo"
    GetPersistentTagGroup().TagGroupSetTagAsString("Python_temp:in:InValue",value)
    
    Result( " DM-Script passed value in: " + value + "\n")
    
    string py = "#Script to demonstrate value passing in Hybrid scripts. DM calling Python." + "\n"
    py += AddPythonValueIN( value, "InValue", "String" )
    py += AddPythonPrintModifyPrint() 
    py += AddPythonValueOut( "OutValue", "String" )
    
    Result( "\n PYTHON CODE EXECUTES\n --------------------- \n\n" )
    ExecutePythonScriptString( py, 1 )
    Result( "\n --------------------- \n PYTHON CODE FINISHED \n\n" )
    
    if ( !GetPersistentTagGroup().TagGroupGetTagAsString("Python_temp:out:OutValue",value))
        Throw("Python value passed out not found.")
        
    Result( "DM-Script received value: " + value + "\n")
    
    GetPersistentTagGroup().TagGroupDeleteTagWithLabel("Python_temp")
}

ClearResults()
PythonValueInAndOut_float()
PythonValueInAndOut_double()
PythonValueInAndOut_string()
// Images and other objects which are in memory can be most easily passed
// by passing their ID value and then finding them by ID.
// However, this does not work if the object would go out of scope at the 
// end of a script (like an image which is not displayed)
//
// To pass a NumpyArray out of Python without showing an image, one can
// instead write the array to the global tags directly, together with the
// information needed to read the tags out into a DM-image
void PythonImageInOut( )
{
    image img := RealImage("test",4,5,5)
    img = icol
    
    Result( " DM-Script passed image ["+img.ImageGetLabel()+"] in.\n")
        
    string py
    py += "\n#Get image DM->Python via imageLabel" + "\n"
    py += "img = DM.FindImageByID("+ img.ImageGetID()+")" + "\n"
    py += "if None == img:" + "\n"
    py += "    print( 'Error.No image passed in by DM-script sucessfully.' )" + "\n"
    py += "    exit(0)" + "\n"
    py += "\n"
    py += "print('Image from DM: Label = ', img.GetLabel())" + "\n"
    py += "print('Image from DM: Name  = ', img.GetName())" + "\n"
    py += "print('Image from DM: Value = \\n', img.GetNumArray())" + "\n"
    py += "del img #ALWAYS delete DM objects in Python scripts" + "\n"
    py += "\n"
    py += "\n#Create DM image in Python and pass out as ID via global tags" + "\n"
    py += "import numpy as np" + "\n"
    py += "data = np.arange(48).reshape(6,8)" + "\n"
    py += "outImg = DM.CreateImage(data.copy(order='C'))" + "\n"
    py += "DM.GetPersistentTagGroup().SetTagAsLong('Python_temp:out:ID',outImg.GetID())" + "\n"
    py += "print('Create new image with ID:',outImg.GetID())"+"\n"
    py += "outImg.ShowImage()    #Image needs to be shown or it will not stay in memory" + "\n"
    py += "del outImg #ALWAYS delete DM objects in Python scripts" + "\n"
    
    Result( "\n PYTHON CODE EXECUTES\n --------------------- \n\n" )
    ExecutePythonScriptString( py, 1 )
    Result( "\n --------------------- \n PYTHON CODE FINISHED \n\n" )
    
    number imgID
    if ( !GetPersistentTagGroup().TagGroupGetTagAsLong("Python_temp:out:ID",imgID))
        Throw("Python imageID value passed out not found.")
        
    image outImg := FindImageByID(imgID)
    if ( !outImg.ImageIsValid()  )
        Throw("Python imageID value passed out but no matching image found.")
        
        
    Result( "DM-Script received image: " + outImg.ImageGetLabel()+ "\n")
    
    GetPersistentTagGroup().TagGroupDeleteTagWithLabel("Python_temp")
    
}


void PythonArrayOut( )
{
    string py
    py += "#Passing Numpy array values via global tags" + "\n"
    py += "import numpy as np" + "\n"
    py += "data = np.arange(6*8*3).reshape(6,8,3)" + "\n"
    py += "outImg = DM.CreateImage(data.copy(order='C'))" + "\n"
    py += "DM.GetPersistentTagGroup().SetTagAsArray('Python_temp:out:array',outImg)" + "\n"
    py += "DM.GetPersistentTagGroup().SetTagAsLong('Python_temp:out:type',outImg.GetDataType())" + "\n"
    py += "for i in range(data.ndim,0,-1):" + "\n"
    py += "    DM.GetPersistentTagGroup().SetTagAsLong('Python_temp:out:dim:' + str(i-1),data.shape[i-1])" + "\n"   
    py += "\n"
    py += "del outImg #ALWAYS delete DM objects in Python scripts" + "\n"
    
    Result( "\n PYTHON CODE EXECUTES\n --------------------- \n\n" )
    ExecutePythonScriptString( py, 1 )
    Result( "\n --------------------- \n PYTHON CODE FINISHED \n\n" )

    number dataType
    if ( !GetPersistentTagGroup().TagGroupGetTagAsLong("Python_temp:out:type",dataType))
        Throw("Python dataType value passed out not found.")
    
    TagGroup dimTG
    if ( !GetPersistentTagGroup().TagGroupGetTagAsTagGroup("Python_temp:out:dim",dimTG))
        Throw("Python dimensions passed out not found.")
    
    number nDim = dimTG.TagGroupCountTags()
    number n0, n1, n2, n3, n4
    dimTG.TagGroupGetIndexedTagAsLong(0,n0) 
    dimTG.TagGroupGetIndexedTagAsLong(1,n1)
    dimTG.TagGroupGetIndexedTagAsLong(2,n2)
    dimTG.TagGroupGetIndexedTagAsLong(3,n3)
    dimTG.TagGroupGetIndexedTagAsLong(4,n4)
    
    image outImg 
    if ( 1 == nDim  )
        outImg := NewImage("Test", dataType, n0 )
    else if ( 2 == nDim  )
        outImg := NewImage("Test", dataType, n0, n1 )
    else if ( 3 == nDim  )
        outImg := NewImage("Test", dataType, n0, n1, n2 )
    else if ( 4 == nDim  )
        outImg := NewImage("Test", dataType, n0, n1, n2, n3 )
    else if ( 5 == nDim  )
        outImg := NewImage("Test", dataType, n0, n1, n2, n3, n4 )
        
    if ( !GetPersistentTagGroup().TagGroupGetTagAsArray("Python_temp:out:array",outImg))
        Throw("Python array data passed out not found.")
    
    Result("\n DM recreated image from array values: " + outImg.ImageGetLabel()+ "\n")
        
    GetPersistentTagGroup().TagGroupDeleteTagWithLabel("Python_temp")
}

clearresults()
Result("\n\nEXAMPLE Python<->DM image passing\n")
PythonImageInOut()
Result("\n\nEXAMPLE Python-->DM array passing\n")
PythonArrayOut( )