DM_attribute_handling.py
## @package python.DM_attribute_handling
#
# managing attributes using addinfo layouts and views
#
from __future__ import print_function # print function syntax as in python 3
import sys
from opals import pyDM # for pyDM in release mode
typeNames = {
pyDM.ColumnType.int_: "int",
pyDM.ColumnType.uint_: "uint",
pyDM.ColumnType.char_: "char",
pyDM.ColumnType.uchar_: "uchar",
pyDM.ColumnType.short_: "short",
pyDM.ColumnType.ushort_: "ushort",
pyDM.ColumnType.float_: "float",
pyDM.ColumnType.double_: "double",
pyDM.ColumnType.string_: "string",
pyDM.ColumnType.llong_: "int64",
pyDM.ColumnType.cstr_: "cstr",
pyDM.ColumnType.bit_: "bit"
}
def output_layout(layout):
for i in range(layout.columns()):
print("\t" + layout.name(i) + " (type = " + typeNames[layout.type(i)] + ")")
def DM_attribute_handling(filename):
# create a point without attributes
pt1 = pyDM.Point()
assert pt1.hasInfo() == False # point has no attributes (addinfo object)
# =================================================================================================================
# now create layouts for the addinfo object
f = pyDM.AddInfoLayoutFactory()
f.addColumn(pyDM.ColumnSemantic.Amplitude) # pre-defined attribute "Amplitude"
f.addColumn(pyDM.ColumnSemantic.EchoWidth) # pre-defined attribute "EchoWidth"
f.addColumn(pyDM.ColumnType.uint_, "_testAttr") # user-defined attribute "_testAttr" (type unsigned int)
layout1 = f.getLayout()
f.addColumn(pyDM.ColumnType.uint_, "_testAttr") # user-defined attribute "_testAttr" (type unsigned int)
layout2 = f.getLayout()
print("Layout 1:")
output_layout(layout1)
print("Layout 2:")
output_layout(layout2)
# create a point with 3 attribut columns
pt2 = pyDM.Point(layout1)
assert pt2.hasInfo() == True # point has an attributes
assert pt2.info().columns() == 3 # point has 3 attribute columns
# cloning a point DOES NOT clone the attribute (AddInfo) object!
pt3 = pt2.clone()
assert pt2.info().isNull(0) == True and pt3.info().isNull(0) == True # attribute 0 (Amplitude) is not set yet
assert pt2.getAddInfo() == pt3.getAddInfo() # attribute object is the same for pt2 and pt3
pt2.info().set(0, 10.23) # setting attribute value
amp = pt3.info().get(0)
assert pt2.info().get(0) == pt3.info().get(
0) # since both point use the same AddInfo object the attribute has to be same
# to create a separate attribute object for each point, it is necessary clone it explicitly
pt4 = pt2.clone()
pt4.setAddInfo(pt2.info().clone()) # clone the attribute object
assert pt2.getAddInfo() != pt4.getAddInfo() # p2 and p4 have different attribute objects
pt2.info().set(0, 5.92) # change attribute 0 of p2
assert abs(pt2.info().get(0) - 5.92) < 1e-5 and abs(pt4.info().get(0) - 10.23) < 1e-5
# =================================================================================================================
# using views only the attributes of interest are visible
# since we want to access "_testAttr" only, we can apply a view (layout2)
assert pt2.info().isView() == False
pt2.setAddInfoView(layout2, True)
assert pt2.info().isView() == True
assert layout2.columns() == 1 and pt2.info().columns() == 1
pt2.info().set(0, 15) # set _testAttr to 15
# since pt2 and pt3 point to the same attribute object the view is also applied to pt3
assert pt3.info().columns() == 1 and pt3.info().get(0) == 15
# the view can be removed as well
pt2.restoreAddInfoFullLayout()
assert pt2.info().isView() == False and pt2.info().columns() == 3
value = pt3.info().get(2) # in the real layout "_testAttr" is at index 2
assert value == 15
# it is also possible to create a cloned view object, which still points to the same data object, but a new
# attribute object is created. this allows to create multiple views on the same attribute data object
pt3.cloneAddInfoView(layout2, True)
assert pt2.getAddInfo() != pt3.getAddInfo()
pt3.info().set(0, 35)
value = pt2.info().get(2)
assert pt2.info().get(2) == 35 and pt3.info().get(0) == 35
# =================================================================================================================
# simplified way to access attributes within an ODM by
# list of given attribute names
attributs = ["Amplitude", "EchoWidth", "_testAttr"]
# open the odm / pyDM.Datamanager.load parameters: filename(string), readOnly(bool) threadSafety(bool)
dm = pyDM.Datamanager.load(filename, True, False)
# if the dm wasn't opened successfully exit function
if not dm:
print("Unable to open ODM '" + filename + "'")
return
print("Create layout based on ODM '" + filename + "'")
for attr in attributs:
type, inDM = f.addColumn(dm, attr, True, pyDM.ColumnType.uint_)
if inDM:
print("\t" + attr + " exists in ODM (type = " + typeNames[type] + ")")
else:
print("\t" + attr + " does NOT exist in ODM (type = " + typeNames[type] + ")")
layout3 = f.getLayout()
print("layout3 :")
output_layout(layout3)
if len(sys.argv) == 1:
print("ODM parameter missing")
exit(-1)
DM_attribute_handling(sys.argv[1])