データコンテナ#
データコンテナの概要#
万葉ライブラリでは独自のデータコンテナを通してデータ処理・解析に便利な機能を提供している。主な機能として次のものがある。
データ列への名称付け
誤差伝搬、マスクを考慮したデータコンテナの四則演算
様々なデータ補正に向けた測定条件などの情報の付与
データのファイル読み込み、書き出し
このデータコンテナをElementContainerと呼ぶ。さらにこのElementContainerを階層的に扱うために、ElementContainerArray、ElementContainerMatrixと呼ぶデータコンテナがある。この章ではこれらのデータコンテナの構造、規則、使用方法を述べる。
なお記述されているスクリプトは、すでに万葉ライブラリがインストールされていることを前提としている。すなわち
>>> import Manyo
Manyo >>>
が実行できているとする。
ElementContainer#
ElementContainerは一つの1次元データを収めるコンテナである。ここで1次元データとは、横軸、強度、エラーの最低3つの配列を用いて表現されるデータのことである。ElementContainerは横軸などの配列を収めるデータ領域と、それに付随した情報を収めておくヘッダ領域から成っている(Fig.1)。
データ領域は複数の実数配列を入れることができる。ヘッダ領域には整数、実数、文字列、および、それらの配列を複数入れることができる。
データ領域の実数配列には、それぞれに名前(キーと呼ばれる文字列、長さに制限はない)を付けて収める。例えば次のように用いる。
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は強度の実数配列である。収めた配列は、次のようにしてキーを用いて取り出すことができる。
1ret = ec.Put("Intensity")
多くの場合、ElementContainerのデータ領域には、物理量、強度、強度エラーの三種類の実数配列からなるヒストグラムデータを収める。 ヒストグラムデータとは、Fig.2 (a)に示すように、ある物理量の軸に沿って区切り(bin:ビン)を設け、その区切り内における強度とエラーを扱うものである。よって、その強度はいわゆる積分値であり、区切り幅(ビン幅)が大きくなるとその強度も大きくなる。
一方、一般に扱われるデータはFig.2 (b)に示したように横軸と縦軸が一対一で対応するものであり、その縦軸の値はその横軸の単位あたりの強度となっているものが大部分である。我々はこれを散布データと呼び、ヒストグラムデータとは区別して扱う。万葉ライブラリのデータコンテナは、ヒストグラムデータを扱うことを基本とする。
データをヒストグラムとして扱うことにより、次のような利点がある。
計測機器との直接的なデータのやりとりが可能
情報の劣化がない
単位変換が容易(ヤコビアンを考慮せずに済む)
このようにヒストグラムデータの場合、当然ながら横軸の区切りの個数は強度、強度エラーよりも一つ多い。次のようにして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に収めた時に、何が収納されているのかを以下のように表示することができる。
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行がデータ領域の情報である。こちらには先の例で行ったように、
TOF、Intensity、Error のキーを持つ3つの実数配列が収納されている
それらの三つの配列がこのElementContainerの区切り、強度、エラー( x key, y key, e key )として登録されている
ことがわかる。
ElementContainerの複製#
PythonなどでElementContianerを扱うときの注意点の一つが、ElementContainerの複製を作ろうとした時である。例えば以下のようにec1というElementContainerがあったとして、それをec2という名前の複製を作成しようとする。
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は見た目は違うが中身は同じであることを示している。
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を作ることを明示する必要がある。正しくは下記のように行う。
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は不変である。
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に示す。
コマンド |
機能 |
---|---|
ElementContianerの作成 |
Manyo.ElementContainer() |
ElementContianerの複製 |
Manyo.ElementContainer(ec) |
コマンド |
機能 |
---|---|
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)にそれぞれのデータコンテナでの利用例を挙げた。
種類 |
例 |
---|---|
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()コマンドでデータ領域の実数配列と同時に表示される。
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から直接取り出すコマンドはない。 実際には、
ElementContainerからHeaderBaseを取り出し、
そのHeaderBaseから収められた情報を取り出す、
という2段階の手順を踏むことになる。
また収められた情報の形式ごとに取り出しコマンドが異なることに注意すること。 この取り出し方法は、対象がElementContainerArrayやElementContainerMatrixでも同じである。
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が戻ってくる。
形式 |
表現 |
取り出しコマンド |
---|---|---|
実数 |
Double |
PutDouble(key) |
整数 |
Int4 |
PutInt4(key) |
文字列 |
string |
PutString(key) |
実数配列 |
vector<Double> |
PutDoubleVector(key) |
整数配列 |
vector<Int4> |
PutInt4Vector(key) |
文字列の配列 |
vector<string> |
PutStringVector(key) |
コマンド |
形式 |
機能 |
---|---|---|
Add(key, XXX) |
XXXを自動判別 |
新しいキーで値を追加する (既にキーがあるとエラー) |
OverWrite(key, XXX) |
XXXを自動判別 |
既にあるキーを値で置き換える (キーがない場合はAddと同じ) |
基本的にHeaderBaseは単独で用いられることはなく、ElementConainerやElementContainerArray, Matrixから取り出される形で使用されることが多いであろう。
先に述べた PutHeader()では、データコンテナ内のHeaderBaseのコピーが作成される。その意味は、このPutHeader()によるHeaderBaseに対して情報を加えたり変更しても取り出し元のデータコンテナのHeaderBaseには影響を与えない、ということである。
この変更をデータコンテナ内のHeaderBaseに反映させるには、InputHeader()コマンドを利用して変更後のHeaderBaseでElementContainerのヘッダを置き換える必要がある。それらのコマンドをTable 6に示す。
コマンド |
機能 |
---|---|
PutHeader() |
データコンテナ内のHeaderBaseのコピーを取り出す |
InputHeader(XXX) |
データコンテナ内のHeaderBaseをXXXで置き換える |
よって、ElementContainerからヘッダを取り出してその内容を変更する場合のスクリプトは以下のようになる。
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()コマンドを持っており、自身の内容の表示ができる。
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に列挙する。
万葉ライブラリ |
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に示す。
型 |
表記 |
空の配列作成 |
---|---|---|
整数配列 |
vector<Int4> |
MakeInt4Vector() |
正の整数配列 |
vector<UInt4> |
MakeUInt4Vector() |
実数配列 |
vector<Double> |
MakeDoubleVector() |
文字列の配列 |
vector<string> |
MakeStringVector() |
次に、Pythonリストと、vectorの操作の違いをTable 9に示す。
機能 |
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リストを用いると
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を用いると
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>だけ少し異なるので注意)
型 |
表現 |
---|---|
vector<Int4> |
VecInt4 |
vector<UInt4> |
VecUInt4 |
vector<Double> |
VecDouble |
vector<string> |
StringVector |
Pythonリストとvector間の変換#
万葉ライブラリの関数において引数においてvectorを必要とするものもある。そのために万葉ライブラリには、Pythonリストとvectorのデータの変換を行うための関数が用意されている。
用意されている関数は、CppToPythonである。
以下に、実数のPythonリストを C++の実数配列 vector<Double> に変換する様子を示す。
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に簡単に示す。
変換元 |
変換先 |
コマンド |
---|---|---|
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を階層的にまとめることができる。
どちらもElementContainerと同様にデータ領域とヘッダ領域から成っている。ElementContainerArrayの場合のデータ領域は複数のElementContainerであり、ElementContainerMatrixの場合のデータ領域は複数のElementContainerArrayである。それらのヘッダ領域にはElementContainerの場合と同様に様々な情報を収めることができる。
主な用途としては、ElementContainerArrayは一つの検出器(内部に多数の検出部位を含んでいる)分のデータを保持するのに使用され、ElementContainerMatrixは一つの検出器グループ(バンクなど)や、装置全体の検出器のデータを全てまとめて扱いたい時に使用される。
ElementContainerArrayの機能#
ElementContainerArrayは、その内部のデータ領域には複数のElementContainerを同時に収めることができ、ヘッダ領域には一つのHeaderBaseがある。
データ領域へのアクセス#
ElementContainerArrayにElementContainerを追加するには、Add()を用いる。
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()を用いる。
1print("The number of ElementContainers = {}".format(eca.PutSize()))
【結果】
The number of ElementContainers = 3
一方、収められているElementContainerを取り出す場合は、Put()を用いる。
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()を用いてより簡単に書ける。
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で示すコマンドが使用できる。
コマンド |
機能 |
---|---|
PutHeader() |
データコンテナ内のHeaderBaseのコピーを取り出す |
InputHeader(XXX) |
データコンテナ内のHeaderBaseをXXXで置き換える |
ElementContainerArrayの複製#
ElementContianerArrayの複製も、ElementContainerの複製と同様に、作成時に引数として複製を行いたいElementContainerArrayを与える。
1eca_copy = Manyo.ElementContainerArray(eca)
ElementContainerArray関連のコマンドまとめ#
ElementContainerArrayを作成するコマンドをTable 13に、ElementContainerArrayのコマンドをTable 14に示す。
コマンド |
機能 |
---|---|
ElementContianerArrayの作成 |
Manyo.ElementContainerArray() |
ElementContianerArrayの複製 |
Manyo.ElementContainerArray(eca) |
コマンド |
機能 |
---|---|
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に示す。
コマンド |
機能 |
---|---|
ElementContianerMatrixの作成 |
Manyo.ElementContainerMatrix() |
ElementContianerMatrixの複製 |
Manyo.ElementContainerMatrix(ecm) |
コマンド |
機能 |
---|---|
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に入れて返す。
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に対してヘッダ検索をかける場合は以下のように行う。
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に示す。
コマンド |
対象 |
---|---|
Search(Key, 値) |
ElementContainerヘッダ内の整数や実数情報 |
Search(Key, 上限値, 下限値) |
ElementContainerヘッダ内の整数や実数情報 |
Search(Key, 文字列) |
ElementContainerヘッダ内の文字列情報 |
SearchArray(Key, 値) |
ElementContainerArrayヘッダ内の整数や実数情報 |
SearchArray(Key, 上限値, 下限値) |
ElementContainerArrayヘッダ内の整数や実数情報 |
SearchArray(Key, 文字列) |
ElementContainerArrayヘッダ内の文字列情報 |
コマンド |
対象 |
---|---|
PutResultAsArray() |
Search()の結果をElementContainerArrayで返す |
PutResultSearchArray() |
SearchArray()の結果をElementContainerMatrixで返す |
またAppendix B「万葉ライブラリ関数リファレンス」も参照のこと。