4

我正在使用 CERN 的 pyROOT 模块做一些工作,并且我正在尝试将字符串数组作为叶子存储在二叉树中。为此,我必须向它传递一个数组,显然,不是使用列表或字典,而是使用数组模块。该模块支持标准 C 数组、字符、整数等,但有谁知道我可以嵌套它们以获得字符串数组,或者实际上是字符数组数组?还是我走得太远了,我需要从键盘上退后一段时间:)?

代码:

import ROOT

rowtree = ROOT.TTree("rowstor", "rowtree")

ROOT.gROOT.ProcessLine(
    "struct runLine {\
    Char_t test[20];\
    Char_t test2[20];\
    };" );
from ROOT import runLine
newline = runLine()
rowtree.Branch("test1", newline, "test/C:test2")

newline.test = ["AbcDefgHijkLmnOp","aaaaaaaaaaaaaaaaaaa"]

rowtree.Fill()

错误:

python branchtest
Traceback (most recent call last):
  File "branchtest", line 14, in <module>
    newline.test = ["AbcDefgHijkLmnOp","aaaaaaaaaaaaaaaaaaa"]
TypeError: expected string or Unicode object, list found

我想知道是否可以将此示例中显示的列表转换为字符串数组。

4

2 回答 2

3

char 数组和 Python 字符串的 Python 列表是两个非常不同的东西。

如果你想要一个包含 char 数组(一个字符串)的分支,那么我建议使用 Python 的内置bytearray类型:

import ROOT
# create an array of bytes (chars) and reserve the last byte for null
# termination (last byte remains zero)
char_array = bytearray(21)
# all bytes of char_array are zeroed by default here (all b'\x00')

# create the tree
tree = ROOT.TTree('tree', 'tree')
# add a branch for char_array
tree.Branch('char_array', char_array, 'char_array[21]/C')
# set the first 20 bytes to characters of a string of length 20
char_array[:21] = 'a' * 20
# important to keep the last byte zeroed for null termination!
tree.Fill()
tree.Scan('', '', 'colsize=21')

的输出tree.Scan('', '', 'colsize=21')是:

************************************
*    Row   *            char_array *
************************************
*        0 *  aaaaaaaaaaaaaaaaaaaa *
************************************

所以我们知道树正确地接受了字节。

如果您想存储字符串列表,那么我建议使用std::vector<std::string>

import ROOT

strings = ROOT.vector('string')()

tree = ROOT.TTree('tree', 'tree')
tree.Branch('strings', strings)
strings.push_back('Hello')
strings.push_back('world!')
tree.Fill()
tree.Scan()

的输出tree.Scan()是:

***********************************
*    Row   * Instance *   strings *
***********************************
*        0 *        0 *     Hello *
*        0 *        1 *    world! *
***********************************

在一个循环中,您可能希望strings.clear()在下一个条目中填充新的字符串列表之前。

现在,rootpy包(另见github 上的存储库)提供了一种在 Python 中创建树的更好方法。这是一个示例,说明如何通过 rootpy 以“更友好”的方式使用 char 数组:

from rootpy import stl
from rootpy.io import TemporaryFile
from rootpy.tree import Tree, TreeModel, CharArrayCol

class Model(TreeModel):
    # define the branches you want here
    # with branchname = branchvalue
    char_array = CharArrayCol(21)
    # the dictionary is compiled and cached for later
    # if not already available
    strings = stl.vector('string')

# create the tree inside a temporary file
with TemporaryFile():
    # all branches are created automatically according to your model above
    tree = Tree('tree', model=Model)

    tree.char_array = 'a' * 20
    # attemping to set char_array with a string of length 21 or longer will
    # result in a ValueError being raised.
    tree.strings.push_back('Hello')
    tree.strings.push_back('world!')
    tree.Fill()
    tree.Scan('', '', 'colsize=21')

的输出tree.Scan('', '', 'colsize=21')是:

***********************************************************************
*    Row   * Instance *            char_array *               strings *
***********************************************************************
*        0 *        0 *  aaaaaaaaaaaaaaaaaaaa *                 Hello *
*        0 *        1 *  aaaaaaaaaaaaaaaaaaaa *                world! *
***********************************************************************

在此处查看另一个使用TreeModels 和 rootpy 的示例:

https://github.com/rootpy/rootpy/blob/master/examples/tree/model_simple.py

于 2013-10-31T22:58:09.047 回答
0

您已将 a 的test成员定义runLine为 20 个字符的数组:

Char_t test[20];\

但是随后您尝试将两个字符串的列表传递给它:

newline.test = ["AbcDefgHijkLmnOp","aaaaaaaaaaaaaaaaaaa"]

这在 C(或 CINT)或 Python 中没有任何意义,所以当然它在 PyROOT 中也没有任何意义。

另外,您的问题似乎有很多困惑。你说你需要传递 PyROOT “一个数组,显然,不是使用列表或字典,而是使用数组模块”......但 PyROOT 并不特别关心 Pythonarray模块。您已经标记了您的问题numpy,这意味着您可能正在考虑numpy而不是array作为“数组模块”,但是上次我检查时(诚然,这是很久以前的事了),它们根本没有相互作用;如果你想要一些可以传递给 PyROOT 的东西,你必须明确要求 numpy 导出缓冲区。

于 2013-10-30T19:11:28.973 回答