データコンテナ#

データコンテナの概要#

万葉ライブラリでは独自のデータコンテナを通してデータ処理・解析に便利な機能を提供している。主な機能として次のものがある。

  • データ列への名称付け

  • 誤差伝搬、マスクを考慮したデータコンテナの四則演算

  • 様々なデータ補正に向けた測定条件などの情報の付与

  • データのファイル読み込み、書き出し

このデータコンテナをElementContainerと呼ぶ。さらにこのElementContainerを階層的に扱うために、ElementContainerArray、ElementContainerMatrixと呼ぶデータコンテナがある。この章ではこれらのデータコンテナの構造、規則、使用方法を述べる。

なお記述されているスクリプトは、すでに万葉ライブラリがインストールされていることを前提としている。すなわち

>>> import Manyo
Manyo >>>

が実行できているとする。

ElementContainer#

ElementContainerは一つの1次元データを収めるコンテナである。ここで1次元データとは、横軸、強度、エラーの最低3つの配列を用いて表現されるデータのことである。ElementContainerは横軸などの配列を収めるデータ領域と、それに付随した情報を収めておくヘッダ領域から成っている(Fig.1)。

_images/ElementContainerDiagram.png

Fig.1 ElementContainerの模式図#

データ領域は複数の実数配列を入れることができる。ヘッダ領域には整数、実数、文字列、および、それらの配列を複数入れることができる。

データ領域の実数配列には、それぞれに名前(キーと呼ばれる文字列、長さに制限はない)を付けて収める。例えば次のように用いる。

ElementContainerのデータ領域への実数配列の格納#
1import Manyo
2ec = Manyo.ElementContainer()
3
4i = [10.0, 22.0, 33.0, 44.0, 55.0]
5ec.Add("Intensity", i)

ここで"import Manyo"はPythonから万葉ライブラリを呼び出すためのモジュールを読み込むコマンドである。一般にPythonのモジュールのコマンドは、そのモジュール名にピリオドで接続することで実行される。例えば2行目のManyo.ElementContainer()は、ManyoモジュールのElementContainerというコマンド(メソッドともいう)を実行している。なおこのコマンドにより「新しく(空っぽの)ElementContainerを作る」ことができる。

またecはElementContainer、iは強度の実数配列である。収めた配列は、次のようにしてキーを用いて取り出すことができる。

ElementContainerのデータ領域からの実数配列の取得#
1ret = ec.Put("Intensity")

多くの場合、ElementContainerのデータ領域には、物理量、強度、強度エラーの三種類の実数配列からなるヒストグラムデータを収める。 ヒストグラムデータとは、Fig.2 (a)に示すように、ある物理量の軸に沿って区切り(bin:ビン)を設け、その区切り内における強度とエラーを扱うものである。よって、その強度はいわゆる積分値であり、区切り幅(ビン幅)が大きくなるとその強度も大きくなる。

Alternate Text

Fig.2 ヒストグラムデータ(上)と散布データ(下)#

一方、一般に扱われるデータはFig.2 (b)に示したように横軸と縦軸が一対一で対応するものであり、その縦軸の値はその横軸の単位あたりの強度となっているものが大部分である。我々はこれを散布データと呼び、ヒストグラムデータとは区別して扱う。万葉ライブラリのデータコンテナは、ヒストグラムデータを扱うことを基本とする。

データをヒストグラムとして扱うことにより、次のような利点がある。

  • 計測機器との直接的なデータのやりとりが可能

  • 情報の劣化がない

  • 単位変換が容易(ヤコビアンを考慮せずに済む)

このようにヒストグラムデータの場合、当然ながら横軸の区切りの個数は強度、強度エラーよりも一つ多い。次のようにしてElementContainerにヒストグラムデータを収める。

ElementContainerのデータ領域へのヒストグラム型データの格納#
1import Manyo
2ec = Manyo.ElementContainer()
3t = [0, 100, 200, 300, 400, 500]    # tof (強度やエラーより個数が一つ多い)
4i = [10.0, 22.0, 33.0, 44.0, 55.0]  # Intensity (強度)
5e = [5.0, 11.0, 16.5, 22.0, 27.5]   # Error (エラー)
6
7ec.Add("TOF", t)
8ec.Add("Intensity", i)
9ec.Add("Error", e)

ここでecはElementContainer、t、i、eは飛行時間、強度、強度エラーの実数配列とする。ここでは単純にtをTOFというキーで、iをIntensity、eをErrorというキーで収納しただけであり、後述するElementContainerの四則演算機能やその他の関数を利用するには、どの配列が区切りで、どの配列が強度やエラーなのかを指定する必要がある。

ヒストグラム型データとして用いる実数配列の指定#
1ec.SetKeys("TOF", "Intensity", "Error")

このように区切り、強度、エラーとしてどのキーの実数配列を用いるかを明示する。のちに述べるように、ElementContainerを用いた関数ではElementContainerはSetKeysされていることが期待される。また収納できる実数配列の数に制限は無いため、区切り、強度、エラーの実数配列を収納した時は必ずSetKeysを実行しておくことが重要である。

配列の収納と取り出しについて#

ElementContainerにデータ列を収納する時、サンプルコードでは Pythonのリスト形式のデータを収納しているように見える。しかし万葉ライブラリ自体はC++で実装されているため、実際にはC++に対応した別の形式でElementContainer内に収納されている。それはvector<double>と呼ばれる形式(C++の標準ライブラリStandard Template Libraryのコンテナ)であるが、ElementContainerはリスト形式で実数配列を受け取ると内部でこの形式に変換している。収納されている実数配列を取り出すためのコマンドは準備されているが、ほとんどの場合リスト形式ではなく、vector<double>となることに注意すること。 前述した

1ret = ec.Put("Intensity")

として取り出された実数配列もリストではなく、vector<double>である。

唯一リストで取り出せるのは、SetKyesで設定された区切り、強度、エラーである。これらは特別な扱いを受けており、リストで取り出す方法が用意されている。

ヒストグラム型データとして用いる実数配列の取り出し方法#
 1ec.SetKeys("TOF", "Intensity", "Error")
 2# リストで取り出す場合
 3x_list = ec.PutXList()  # x軸をリストで取り出す
 4i_list = ec.PutYList()  # 強度をリストで取り出す
 5e_list = ec.PutEList()  # エラーをリストで取り出す
 6
 7# vector<double>で取り出す場合
 8x_vec = ec.PutX()
 9i_vec = ec.PutY()
10e_vec = ec.PutE()

なお、現在どの実数配列がSetKeysで設定されているかを確認するにはPutXKey、PutYKey、PutEKeyや、PutHistKeyListを用いる。

ヒストグラム型データとして用いる実数配列のキーを得る#
1print("X key = {}".format(ec.PutXKey()))  # Xのキー
2print("Y key = {}".format(ec.PutYKey()))  # Yのキー
3print("E key = {}".format(ec.PutEKey()))  # Eのキー
4print("[X key, Y key, E key] = ",ec.PutHistKeyList())  # リストで取り出す

ElementContainerの内容の表示 (Dump)#

先に述べたように実数配列などをElementContainerに収めた時に、何が収納されているのかを以下のように表示することができる。

ElementContainerの内容表示#
1ec.Dump()

【結果】

*** header object start
***Int4Map***
Index    Key    Value

***DoubleMap***
Index    Key    Value

***StringMap***
Index    Key    Value

***Int4VectorMap***
Index    Key    Size    Value

***DoubleVectorMap***
Index    Key    Size    Value

***StringVectorMap***
Index    Key    Size    Value

*** header object end

The number of vectors is 3

x key = TOF
y key = Intensity
e key = Error

Index    Key    Size    Unit    Values
0    Error    5    None    [5,11,16.5,22,27.5]
1    Intensity    5    None    [10,22,33,44,55]
2    TOF    6    None    [0,100,200,300,400,500]

このDump()コマンドによりヘッダ領域の内容とデータ領域の情報が示される。この例では最初の20行がヘッダ情報部分であるが、何も収納されていないのでタイトルなどが表示されているだけである。一方最後の10行がデータ領域の情報である。こちらには先の例で行ったように、

  1. TOF、Intensity、Error のキーを持つ3つの実数配列が収納されている

  2. それらの三つの配列がこのElementContainerの区切り、強度、エラー( x key, y key, e key )として登録されている

ことがわかる。

ElementContainerの複製#

PythonなどでElementContianerを扱うときの注意点の一つが、ElementContainerの複製を作ろうとした時である。例えば以下のようにec1というElementContainerがあったとして、それをec2という名前の複製を作成しようとする。

ElementContainerの複製失敗#
1ec1 = Manyo.ElementContainer()
2ec1.Add("x", [1, 2, 3, 4])
3ec1.Add("y", [1, 1, 1])
4ec1.Add("e", [1, 1, 1])
5ec1.SetKeys("x", "y", "e")
6
7ec2 = ec1

一見違う名前のデータコンテナに代入したように見えても、それは単に一つのデータコンテナの実体に異なる名前が付けられただけのものである。例えば、ec2に以下のようにヒストグラムの変更を行った場合、その変更がec1にも加えられている、つまりec1とec2は見た目は違うが中身は同じであることを示している。

ElementContainerの複製失敗確認#
1ec2.Add("y2", [2, 2, 2])
2ec2.SetKeys("x", "y2", "e")
3
4ec1.Dump()

【結果】

(省略)
The number of vectors is 4

x key = x
y key = y2
e key = e

Index    Key    Size    Unit    Values
0    e    3    None    [1,1,1]
1    x    4    None    [1,2,3,4]
2    y    3    None    [1,1,1]
3    y2    3    None    [2,2,2]

そこで実際に複製を作る場合、新しくElementContainerを作ることを明示する必要がある。正しくは下記のように行う。

ElementContainerの複製#
1ec1 = Manyo.ElementContainer()
2ec1.Add("x", [1, 2, 3, 4])
3ec1.Add("y", [1, 1, 1])
4ec1.Add("e", [1, 1, 1])
5ec1.SetKeys("x", "y", "e")
6
7ec2 = Manyo.ElementContainer(ec1)

つまり、今まで使用してきた「新しい(空っぽの)ElementContainerを作る」コマンドに、複製をとりたいElementContainerを引数として与えれば良い。この結果作成されたec2は一見ec1と同じであるがその実体は異なっているので、先に行ったようにec2を書き換えてもec1は不変である。

ElementContainerの複製確認#
1ec2.Add("y2",[2,2,2])
2ec2.SetKeys( "x", "y2", "e" )
3
4ec1.Dump()

【結果】

(省略)
The number of vectors is 3

x key = x
y key = y
e key = e

Index    Key    Size    Unit    Values
0    e    3    None    [1,1,1]
1    x    4    None    [1,2,3,4]
2    y    3    None    [1,1,1]

ElementContainer関連のコマンドまとめ#

ElementContainerを作成するためのコマンドをTable 1に、ElementContainerが持つコマンドをTable 2に示す。

Table 1 ElementContainer作成コマンド#

コマンド

機能

ElementContianerの作成

Manyo.ElementContainer()

ElementContianerの複製

Manyo.ElementContainer(ec)

Table 2 ElementContainerのコマンド#

コマンド

機能

Add(key, XXX)

ElementContainerへの実数配列の追加。 XXXは Python Listか vector<double>

Put(key)

キーの実数配列の取り出し( vector<double> )

SetKeys(xkey, ykey, ekey)

ヒストグラムのX,Y,Eとなる実数配列の指定

PutXList()

Xの実数配列の取り出し(Python List)

PutYList()

Yの実数配列の取り出し(Python List)

PutEList()

Eの実数配列の取り出し(Python List)

PutX()

Xの実数配列の取り出し(vector<double>)

PutY()

Yの実数配列の取り出し(vector<double>)

PutE()

Eの実数配列の取り出し(vector<double>)

PutXKey()

Xの実数配列のキー

PutYKey()

Yの実数配列のキー

PutEKey()

Eの実数配列のキー

PutKeysList()

実数配列のキーのリスト

PutHistKeyList()

ヒストグラムのキーのリスト

PutHeader()

ヘッダ情報の複製の取り出し

InputHeader()

ヘッダ情報の置き換え

SaveTextFile(FileName)

ヒストグラムのテキストファイル保存

LoadTextFile(FileName)

テキストファイルからのヒストグラム読み込み

いくつかのコマンドは次章以降で触れられる。またAppendix B「万葉ライブラリ関数リファレンス」も参照のこと。

ヘッダ#

ヘッダ領域にはデータ領域に収めたデータに関する様々な情報(整数、実数、文字列、および、それらの配列)を名前(キー)を付けて収められる。例えば、データ領域に収めたヒストグラムを観測した検出ピクセルのIDや位置情報を記録することに用いる。ヘッダにこれらの情報を記録することで、データに付随するパラメータの管理が容易になり、また、これらをデータの検索に用いることができるという利点がある。次の表(Table 3)にそれぞれのデータコンテナでの利用例を挙げた。

Table 3 データコンテナのヘッダ利用例#

種類

ElementContainer

ピクセルID、検出器、散乱角、ピクセル位置

ElementContainerArray

検出器ID、マスク情報

ElementContainerMatrix

ラン番号、モニターカウント

ヘッダへの収納の意味(HeaderBase)#

ヘッダ情報はHeaderBaseと呼ばれる形式のコンテナに、実数、整数、文字列といった情報の形式ごとに分けられて保存される。 先にElementContainerはデータ領域とヘッダ領域の二つの領域を持つと述べたが、実際にはヘッダ領域とはこのHeaderBase形式コンテナのことである。

よってElementContaierのヘッダへの収納とは、「ElementContainer内のHeaderBaseコンテナに情報を収める」ということを意味している。 同様に、ElementContainerArrayやElementContainerMatrixのヘッダへの収納も、このHeaderBaseを利用することになる。

ElementContainerのヘッダへの収納#

ElementContainerヘッダへの収納は、実数配列と同様にキーを用いて以下のように、AddToHeader()というコマンドで行うことができる。

ヘッダへの収納#
1import Manyo
2
3ec=Manyo.ElementContainer()
4ec.AddToHeader("L1", 20.193)       # L1というキーで実数を収納
5ec.AddToHeader("NumOfPixels", 100) # NumOfPixelsというキーで整数を収納
6ec.AddToHeader("Sample", "CuGeO3") # Sampleというキーで文字列を収納

収納されたヘッダ情報は、先に示したDump()コマンドでデータ領域の実数配列と同時に表示される。

ヘッダの確認(Dump)#
1ec.Dump()

【結果】

   *** header object start
   ***Int4Map***
   Index       Key     Value
   0   NumOfPixels     100

   ***DoubleMap***
   Index       Key     Value
   0   L1      20.193

   ***StringMap***
   Index       Key     Value
   0   Sample  CuGeO3

   ***Int4VectorMap***
   Index       Key     Size    Value

   ***DoubleVectorMap***
   Index       Key     Size    Value

   ***StringVectorMap***
   Index       Key     Size    Value

   *** header object end

   The number of vectors is 0

   x key = None
   y key = None
   e key = None

   Index       Key     Size    Unit    Values


このように収めた情報が情報の形式(整数、実数、文字列など)に分けて収納されていることがわかる。

ヘッダからの情報の取り出し#

ElementContainerに収納されたヘッダ情報を取り出すこともできる。ただしElementContainerから直接取り出すコマンドはない。 実際には、

  1. ElementContainerからHeaderBaseを取り出し、

  2. そのHeaderBaseから収められた情報を取り出す、

という2段階の手順を踏むことになる。

また収められた情報の形式ごとに取り出しコマンドが異なることに注意すること。 この取り出し方法は、対象がElementContainerArrayやElementContainerMatrixでも同じである。

ElementContainerヘッダからの取り出し#
 1hh = ec.PutHeader()  # ElementContainerからhhという名前でHeaderBaseを取り出す
 2
 3L1=hh.PutDouble("L1")  # HeaderBaseからL1というキーの実数を取り出す
 4NumOfPixels=hh.PutInt4("NumOfPixels") # NumOfPixelsキーの整数を取り出す
 5SampleName=hh.PutString("Sample")     # SampleNameキーの文字列を取り出す
 6
 7print("L1 = {}".sormat(L1))
 8print("NumOfPixels = {}".format(NumOfPixels))
 9print("Sample Name = {}".format(SampleName)
10
11hh.Dump()

【結果】

L1 =  20.193
NumOfPixels = 100
Sample Name= CuGeO3

***Int4Map***
Index       Key     Value
0   NumOfPixels     100

***DoubleMap***
Index       Key     Value
0   L1      20.193

***StringMap***
Index       Key     Value
0   Sample  CuGeO3

***Int4VectorMap***
Index       Key     Size    Value

***DoubleVectorMap***
Index       Key     Size    Value

***StringVectorMap***
Index       Key     Size    Value

ここで、Dump()はElementContainerの時と同様に、HeaderBaseの内容を書き出すコマンドである。

HeaderBaseの扱い方#

HeaderBaseは、下に示すTable 4にあるような形式の情報が保持されている。いずれも名前(キー)と情報の組み合わせで収められている。 取り出しコマンドもTable 5に示しておく。なお、取り出す時の形式が、情報をAddした時の形式(整数、実数、文字列)と異なっていても、自動的に変換される。ただし、文字列を数値(整数、実数)に変換する場合、変換が明らかに不可能な場合はワーニングメッセージとともに、0または0.0が戻ってくる。

Table 4 HeaderBaseからの情報取り出しコマンド#

形式

表現

取り出しコマンド

実数

Double

PutDouble(key)

整数

Int4

PutInt4(key)

文字列

string

PutString(key)

実数配列

vector<Double>

PutDoubleVector(key)

整数配列

vector<Int4>

PutInt4Vector(key)

文字列の配列

vector<string>

PutStringVector(key)

Table 5 HeaderBaseへの情報収納コマンド#

コマンド

形式

機能

Add(key, XXX)

XXXを自動判別

新しいキーで値を追加する (既にキーがあるとエラー)

OverWrite(key, XXX)

XXXを自動判別

既にあるキーを値で置き換える (キーがない場合はAddと同じ)

基本的にHeaderBaseは単独で用いられることはなく、ElementConainerやElementContainerArray, Matrixから取り出される形で使用されることが多いであろう。

先に述べた PutHeader()では、データコンテナ内のHeaderBaseのコピーが作成される。その意味は、このPutHeader()によるHeaderBaseに対して情報を加えたり変更しても取り出し元のデータコンテナのHeaderBaseには影響を与えない、ということである。

この変更をデータコンテナ内のHeaderBaseに反映させるには、InputHeader()コマンドを利用して変更後のHeaderBaseでElementContainerのヘッダを置き換える必要がある。それらのコマンドをTable 6に示す。

Table 6 ElementContainerのHeaderBase取り出し・置き換え#

コマンド

機能

PutHeader()

データコンテナ内のHeaderBaseのコピーを取り出す

InputHeader(XXX)

データコンテナ内のHeaderBaseをXXXで置き換える

よって、ElementContainerからヘッダを取り出してその内容を変更する場合のスクリプトは以下のようになる。

ElementContainerヘッダからの取り出し2#
 1ec = Manyo.ElementContainer()
 2
 3ec.AddToHeader("SampleName", "Cupper")
 4ec.AddToHeader("Temperature", 20.0)
 5ec.AddToHeader("Pressure", 1.0)
 6
 7ec.Dump()
 8
 9head = ec.PutHeader()
10head.OverWrite("SampleName", "Gold")
11head.OverWrite("Temperature", 300.0)
12head.OverWrite("Pressure", 0.5)
13
14ec.InputHeader(head)
15
16ec.Dump()

ここでは、まず新しく作成したElementContainerのヘッダに、"SampleName"として"Cupper"を、"Temperature"として 20.0 を、"Pressure"として 1.0を、与えている。その内容を確認するために Dump を行っている。その後、取り出したHeaderBaseに対して、先ほどのキーの値をそれぞれ"Gold"、300.0、0.5に置き換えている。最後にその編集したHeaderBaseでElementContainerのヘッダを上書きして、その Dump を行っている。

【結果】

*** header object start
***Int4Map***
Index       Key     Value

***DoubleMap***
Index       Key     Value
0   Temperature     20
1   Pressure        1

***StringMap***
Index       Key     Value
0   SampleName      Cupper

***Int4VectorMap***
Index       Key     Size    Value

(中略)

*** header object start
***Int4Map***
Index       Key     Value

***DoubleMap***
Index       Key     Value
0   Temperature     300
1   Pressure        0.5

***StringMap***
Index       Key     Value
0   SampleName      Gold

***Int4VectorMap***
Index       Key     Size    Value

(以下略)

確かに、"SampleName"が"Cupper"から"Gold"に、"Temperature"が20.0から300.0に、"Pressure"が1.0から0.5へ変更されていることがわかる。

HeaderBaseの内容の確認#

HeaderBase自体もDump()コマンドを持っており、自身の内容の表示ができる。

HeaderBaseのDump#
1head1 = ec.PutHeader()
2head1.Dump()

【結果】

*** header object start
***Int4Map***
Index       Key     Value

***DoubleMap***
Index       Key     Value
0   Info    2

(以下略)

このように実はElementContainerのDump()は、まさにこのHeaderBaseのDump()も表示していることがわかる。

万葉ライブラリの変数・配列について#

ここまで万葉ライブラリの基本機能であるElementContainerやヘッダを見てきたが、いずれも測定データなどの数値や文字列、及びそれらの配列といった情報をPython上で与えたり受け取ったりすることが必要である。

しかしながら万葉ライブラリ自体はC++で作成されているため、データコンテナや関数の引数及び戻り値にはしばしばC++の変数のタイプ(型)が使用されている。

そのため万葉ライブラリの関数がPython上で簡単に扱えるように、一部の関数はPythonの変数を半自動的にC++の変数に変換する、もしくはその逆を行うように実装されている。しかし、特に数値配列を扱う場合、直接の変換ができない場合も多い。

そこで本節では万葉ライブラリ(C++)とPythonの間で型の違いがどのように扱われているのか、Python上でそれらを扱う場合の特徴と注意点を述べておく。

変数のタイプ#

万葉ライブラリで使用される数値や文字列など単純な変数(配列や特殊なコンテナを省く)の型は、少し独特な表現が用いられる。よく使用されるものをTable 7に列挙する。

Table 7 万葉ライブラリで使用される変数#

万葉ライブラリ

Python

C言語

Int4

int

整数(符号あり)

int

UInt4

intに変換

正の整数(符号なし)

unsigned int

Int8

int

長整数(符号あり)

long long

UInt8

intに変換

正の長整数(符号なし)

unsigned long long

Double

float

実数

double

string

str

文字列

string

本書のAppendix B「万葉ライブラリ関数リファレンス」にあるように、万葉ライブラリの関数における引数や戻り値は、Int4, UInt4, Double, stringなど万葉ライブラリやC++の型で定義・表現されている。しかしながら、Pythonから見ればすべてintやfloat, strで置き換えることができる。

また「Pythonと万葉ライブラリ間のこれらの変換は自動的に行われる」ので、使用時には特に気にしなくていよい。

ただし次節で述べるように、これら変数の型を用いた配列は少し異なるので注意が必要である。

配列#

一般にPythonでは、数値の配列を扱うのにPythonのリストが使用される。Pythonのリストは汎用的・高機能であり、非常に簡便に使えるが、万葉ライブラリのベースであるC++ではそれをそのまま利用することはできないため、別の入れ物(コンテナ)で置き換えている。

万葉ライブラリでの数値や文字列などの配列を扱う枠組みとして、標準テンプレートライブラリ(Standard Template Library : STL)と呼ばれるものが用いられている。そのSTLの中で定義されているvectorと呼ばれるコンテナを積極的に利用している。

万葉ライブラリはPython上でこのvectorをある程度Pythonリストとかなり近い形で扱えるように実装されている。使用できるvectorとPython上での作成方法をTable 8に示す。

Table 8 万葉ライブラリで使用するvector#

表記

空の配列作成

整数配列

vector<Int4>

MakeInt4Vector()

正の整数配列

vector<UInt4>

MakeUInt4Vector()

実数配列

vector<Double>

MakeDoubleVector()

文字列の配列

vector<string>

MakeStringVector()

次に、Pythonリストと、vectorの操作の違いをTable 9に示す。

Table 9 Pythonリストとvectorの違い#

機能

Pythonリストでの操作

万葉ライブラリvector<XXX> での操作

空の配列作成

AA=[]

AA=Manyo.MakeXXXVector()

配列追加

AA.append(m)

AA.append(m) (ただしXXXと同じ型)

値取り出し

AA[n]

AA[n]

値代入

AA[n] = m

AA[n] = m (ただしXXXと同じ型)

配列の大きさ

len(AA)

AA.size()

配列最後の値

AA[-1]

AA[AA.size() - 1], AA.back()

配列ソート

AA.sort()

単独では不可

配列逆順

AA.reverse()

単独では不可

このように、配列追加や値の出し入れなどの単純な操作に関しては、両者ほぼ同じ仕様で扱うことができる。

例えば for ループで配列の文字を取り出す場合、Pythonリストを用いると

Pythonリストのループ例#
1for word in word_list:
2    print("word = {}".format(word))
3
4もしくは
5
6for i in range(len(word_list)):
7    print("word = ".format(word_list[i]))

となり、vectorを用いると

vectorのループ例#
1for i in range(word_vect.size()):
2    print("word = {}".format(word_vect[i]))

となる。特にrangeを用いて利用する場合は非常に似通っている。ただし変数だけだと実際にどちらなのかわかりづらいのでコード作成時には注意すること。 なお、変数が目的の型かどうかを確認するのにisinstanceというPythonコマンドがあるので利用するのも良い。

>>> import Manyo
>>> vv = Manyo.MakeDoubleVector()
>>> ll = []
>>>
>>> isinstance(ll, list)
True
>>> isinstance(vv, Manyo.VecDouble)
True

なお、型の確認に使用されているVecDoubleは万葉ライブラリ内で定義されている型の表現であり、他のものはTable 10で示したようになる。(vector<string>だけ少し異なるので注意)

Table 10 万葉ライブラリ内で定義されるvector型の表現#

表現

vector<Int4>

VecInt4

vector<UInt4>

VecUInt4

vector<Double>

VecDouble

vector<string>

StringVector

Pythonリストとvector間の変換#

万葉ライブラリの関数において引数においてvectorを必要とするものもある。そのために万葉ライブラリには、Pythonリストとvectorのデータの変換を行うための関数が用意されている。

用意されている関数は、CppToPythonである。

以下に、実数のPythonリストを C++の実数配列 vector<Double> に変換する様子を示す。

CppToPythonの使い方#
1>>> import Manyo
2>>> ll = [1.0, 2.0, 3.0, 4.0]
3>>> ctp = Manyo.CppToPython()
4>>> vec = ctp.ListToDoubleVector(ll)
5>>> isinstans(vec, Manyo.VecDouble)
6True
7>>> ll_from_vec = ctp.VectorToList(vec)
8>>> print ll_from_vec
9[1.0, 2.0, 3.0, 4.0]
  • 1行目: 万葉ライブラリモジュールを読み込む

  • 2行目: Pythonリスト ll を用意する

  • 3行目: CppToPython 関数を呼び出し、 ctp とする

  • 4行目: ll を vector<Double> に変換し結果を vec に入れる

  • 5行目: vec が vector<Double> かどうかを確認する

  • 6行目: True と戻ってきたので vec は vector<Double>である

  • 7行目: 次に vec を引数として、Pythonリストに逆変換し、結果を ll_from_vec に入れる

  • 8行目: 結果を表示して Pythonリストであることを確認する

他の変換についてもTable 11に簡単に示す。

Table 11 Pythonリストとvectorの変換コマンド#

変換元

変換先

コマンド

Pythonリスト

vector<Int4>

ListToInt4Vector

vector<UInt4>

ListToUInt4Vector

vector<Double>

ListToDoubleVector

vector<string>

ListToStringVector

vector<Int4>

Pythonリスト

VectorToList

vector<UInt4>

vector<Double>

vector<string>

VectorStringToList

このTable 11にあるように、

  • Pythonリストから、それぞれの型のvectorへは独立したコマンド

  • vectorから、Pythonリストへは文字列以外は一つのコマンド

となっている。

ElementContainerArrayとElementContainerMatrix#

ElementContainerArray、ElementContainerMatrixを用いるとFig. 3に示すようにElementContainerを階層的にまとめることができる。

_images/ElementContainerMatrixDiagram.png

Fig.3 ElementContainerArray、ElementContainerMatrixの模式図#

どちらもElementContainerと同様にデータ領域とヘッダ領域から成っている。ElementContainerArrayの場合のデータ領域は複数のElementContainerであり、ElementContainerMatrixの場合のデータ領域は複数のElementContainerArrayである。それらのヘッダ領域にはElementContainerの場合と同様に様々な情報を収めることができる。

主な用途としては、ElementContainerArrayは一つの検出器(内部に多数の検出部位を含んでいる)分のデータを保持するのに使用され、ElementContainerMatrixは一つの検出器グループ(バンクなど)や、装置全体の検出器のデータを全てまとめて扱いたい時に使用される。

ElementContainerArrayの機能#

ElementContainerArrayは、その内部のデータ領域には複数のElementContainerを同時に収めることができ、ヘッダ領域には一つのHeaderBaseがある。

データ領域へのアクセス#

ElementContainerArrayにElementContainerを追加するには、Add()を用いる。

ElementContainerArrayへ追加#
 1# ElementContainerの作成
 2ec1 = Manyo.ElementContainer()
 3ec1.Add("x",[1, 2, 3, 4])
 4ec1.Add("y",[1, 1, 1])
 5ec1.Add("e",[1, 1, 1])
 6ec1.SetKeys("x", "y", "e")
 7
 8# ElementContainerの複製
 9ec2 = Manyo.ElementContainer(ec1)
10ec3 = Manyo.ElementContainer(ec1)
11
12# ElementContainer区別用にヘッダへ登録
13ec1.AddToHeader("Name", "ec1")
14ec2.AddToHeader("Name", "ec2")
15ec3.AddToHeader("Name", "ec3")
16
17# ElementContainerArrayの作成
18eca = Manyo.ElementContainerArray()
19
20# ElementContainerArrayへec1,ec2.ec3を追加
21eca.Add(ec1)
22eca.Add(ec2)
23eca.Add(ec3)

ここで、ElementContainerArrayにAdd()によって収められたElementContainerは、ec1やec2, ec3の複製であるので、ec1やec2を変更したり、消去( del )したりしてもElementContainerArray内のElementContainerは変更されない。

追加したElementContainerの総数を知りたい場合、PutSize()を用いる。

ElementContainerArrayに含まれるElementContainer数#
1print("The number of ElementContainers = {}".format(eca.PutSize()))

【結果】

The number of ElementContainers = 3

一方、収められているElementContainerを取り出す場合は、Put()を用いる。

ElementContainerArrayからの取り出し#
1ec = eca.Put(0)
2print("ElementContainer name = {}".format(ec.PutHeader().Put("Name")))
3
4ec = eca.Put(1)
5print("ElementContainer name = {}".format(ec.PutHeader().Put("Name")))
6
7ec = eca.Put(3)
8print("ElementContainer name = {}".format(ec.PutHeader().Put("Name")))

これはPythonのfor文と、PutSize()を用いてより簡単に書ける。

ElementContainerArrayからの取り出し2#
1for i in range(eca.PutSize()):
2    ec = eca.Put(i)
3    print("ElementContainer name = {}".format(ec.PutHeader().Put("Name")))

【結果】

ElementContainer name = ec1
ElementContainer name = ec2
ElementContainer name = ec3

ここで注意するのは、 Put()によって取り出されたElementContainerはElementContainerArray内のデータの複製であることであり、取り出されたElementContainerに変更を加えたり消去してもElementContainerArray内のデータには影響がないということである。 もしElementContainerArray内のデータそのものを取り出したい場合、PutPointer()もしくはeca( )などのコマンドで取り出すことが可能であるが、これは万が一取り出したデータを消去するとElementContainerArrayの中身も消去され、整合性が取れなくなり、エラーが起きたり最悪の場合、実行が停止(落ちる)ことになるため、扱いには注意が必要である。よって特に必要でなければPut()を用いるべきである。

ヘッダ領域へのアクセス#

ElementContainerにおけるヘッダ領域の情報の取り出し、置き換えと全く同じである。 すなわち、Table 12で示すコマンドが使用できる。

Table 12 ElementContainerのHeaderBase取り出し・置き換え#

コマンド

機能

PutHeader()

データコンテナ内のHeaderBaseのコピーを取り出す

InputHeader(XXX)

データコンテナ内のHeaderBaseをXXXで置き換える

ElementContainerArrayの複製#

ElementContianerArrayの複製も、ElementContainerの複製と同様に、作成時に引数として複製を行いたいElementContainerArrayを与える。

ElementContainerArrayの複製#
1eca_copy = Manyo.ElementContainerArray(eca)

ElementContainerArray関連のコマンドまとめ#

ElementContainerArrayを作成するコマンドをTable 13に、ElementContainerArrayのコマンドをTable 14に示す。

Table 13 ElementContainerArray作成コマンド#

コマンド

機能

ElementContianerArrayの作成

Manyo.ElementContainerArray()

ElementContianerArrayの複製

Manyo.ElementContainerArray(eca)

Table 14 ElementContainerArrayのコマンド#

コマンド

機能

Add(ec)

ElementContainerの追加

Put(i)

i番目のElementContainerの取り出し

PutSize()

含まれているElementContainerの個数

PutHeader()

ヘッダ情報の取り出し

InputHeader()

ヘッダ情報の置き換え

またAppendix B「万葉ライブラリ関数リファレンス」も参照のこと。

ElementContainerMatrixの機能#

ElementContainerMatrixは、その内部のデータ領域には複数のElementContainerArrayを同時に収めることができ、ヘッダ領域には一つのHeaderBaseがある。

それ以外のコマンドなどは、全くElementContainerMatrixとほぼ同じである。

ElementContainerMatrixのコマンドまとめ#

ElementContainerMarixを作成するコマンドをTable 15に、ElementContainerMatrixのコマンドをTable 16に示す。

Table 15 ElementContainerMatrix作成コマンド#

コマンド

機能

ElementContianerMatrixの作成

Manyo.ElementContainerMatrix()

ElementContianerMatrixの複製

Manyo.ElementContainerMatrix(ecm)

Table 16 ElementContainerMatrixのコマンド#

コマンド

機能

Add(eca)

ElementContainerArrayの追加

Put(i)

i番目のElementContainerArrayの取り出し

PutSize()

含まれているElementContainerArrayの個数

PutHeader()

ヘッダ情報の取り出し

InputHeader()

ヘッダ情報の置き換え

またAppendix B「万葉ライブラリ関数リファレンス」も参照のこと。

ヘッダ情報による検索#

先に述べたようにElementContainerArrayの主な用途としては、複数の検出単位を持つ検出器のデータをまるごと保持するのに使用されるが、その検出単位の情報で検索をかけ必要な検出単位のヒストグラムデータだけ取り出したい時がある。またElmentContainerMatrixに対してもそこに含まれるElementContainerやElementContainerArrayに対して検索をかけたいこともある。 そのためにヘッダ情報で検索を行うコマンドが用意されている。万葉ライブラリのコマンドのSearchInHeaderである。

簡単に使い方を示す。以下に示すスクリプトは、すでにヘッダ情報として"PIXELID"(整数)が入ったElementContainerが複数含まれているElementContainerArrayやElementContainerMatrixに対して、特定の範囲の"PIXELID"を持つElementContainerだけ取り出すというものである。この例では、検索結果をElementContainerArrayに入れて返す。

SearchInHeader使用例#
 1# SearchInHeaderを作成する
 2# この時に検索対象のElementContainerArray
 3# もしくは ElementContainerMatrixを与える
 4import Manyo
 5SIH = Manyo.SearchInHeader(dat)
 6
 7# "PIXELID"が 10〜20のものを検索する
 8# 正しく検索できればTrueが戻る
 9isFound = SIH.Search("PIXELID", 10, 20)
10
11# もしTrueだったら検索結果を取り出す
12ret_eca = None
13if isFound:
14    ret_eca = SIH.PutResultAsArray()
15
16del SIH  # 使い終わったらdeleteする

また、ElementContainerMatrixに含まれているElementContainerArrayに対してヘッダ検索をかける場合は以下のように行う。

SearchInHeader使用例2#
 1# SearchInHeaderを作成する
 2# この時に検索対象のElementContainerMatrixを与える
 3import Manyo
 4SIH = Manyo.SearchInHeader(dat)
 5
 6# "DETID"が 10〜20のものを検索する
 7# 正しく検索できればTrueが戻る
 8isFound = SIH.SearchArray("DETID", 10, 20)
 9
10# もしTrueだったら検索結果を取り出す
11ret_ecm = None
12if isFound:
13    ret_ecm = SIH.PutResultAsArray()
14
15del SIH  # 使い終わったらdeleteする

その他の主なコマンドをTable 17, Table 18に示す。

Table 17 SearchInHeaderの主な検索コマンド#

コマンド

対象

Search(Key, 値)

ElementContainerヘッダ内の整数や実数情報

Search(Key, 上限値, 下限値)

ElementContainerヘッダ内の整数や実数情報

Search(Key, 文字列)

ElementContainerヘッダ内の文字列情報

SearchArray(Key, 値)

ElementContainerArrayヘッダ内の整数や実数情報

SearchArray(Key, 上限値, 下限値)

ElementContainerArrayヘッダ内の整数や実数情報

SearchArray(Key, 文字列)

ElementContainerArrayヘッダ内の文字列情報

Table 18 SearchInHeaderの主な検索結果取り出しコマンド#

コマンド

対象

PutResultAsArray()

Search()の結果をElementContainerArrayで返す

PutResultSearchArray()

SearchArray()の結果をElementContainerMatrixで返す

またAppendix B「万葉ライブラリ関数リファレンス」も参照のこと。