データコンテナの演算#

マスク#

マスクとは何らかの処理を行う際にその処理に使用しない値に与えるものである。

ElementContainerのヒストグラムを用いて何らかの処理を行う場合、マスクされた値はその処理には使用しないことを意味する。ただし、これはあくまでルールであるため、実際に処理を行う関数を作成する際に、開発者が留意すべきものである。より具体的な例をあげれば、いくつかのElementContainerの平均値を出す場合、マスクされた値は平均値の計算には使用しないように関数を書く、というのがルールとなる。

また、MLFにおける万葉ライブラリの拡張パッケージである「空蝉」などでは、決まり事としてElementContainer, ElementContainerArrayのヘッダにキーとして"MASKED"という情報を与えており、この値が1ならマスクがかかっているデータコンテナである、と定義し、データ処理関数の中で使用している。

マスクのルール#

  1. マスクされた値には負のエラーを与える。

  2. マスクのエラーの絶対値は何でもよいが、通常のエラー計算を行ったと期待される。

  3. マスクはElementContainerのヒストグラムの横軸のbinごとにつけることができる。

  4. 関数を作成する際には、極力マスクを考慮して開発すること。

四則演算におけるマスク#

マスクは、万葉ライブラリにおいてElementContainer同士の演算でも考慮される。

演算時には通常どおりエラーを計算したのち、演算された値のどちらかにマスクがかかっていれば、その計算されたエラー値の符号をマイナスにする仕様となっている。

よってマスク処理が考えられていない関数においても、エラー伝搬・計算において二乗和を計算することで通常のエラーとして扱えるため、マスクのありなしでエラーが変化することはない。

ElementContainer同士の四則演算#

ElementContainer、およびElementContainerArray, ElementContainerMatrix同士で四則演算を行う事ができる。 また、ElementContainerを定数倍、もしくは定数を加算、減算することも可能である。

以下の例では、ec1, ec2にそれぞれ同じ横軸を持つヒストグラム(ElementContainer)が入っているものとする。 横軸が異なる場合の振る舞いについては、3.4節にて述べる。

四則演算#

四則演算はTable 19で示すように行う。

Table 19 ElementContainer同士の四則演算#

演算

フォーマット

足し算

ret_ec = ec1 + ec2

引き算

ret_ec = ec1 - ec2

かけ算

ret_ec = ec1 * ec2

割り算

ret_ec = ec1 / ec2

これら四則演算は、結果を新しいElementContainerを作成して戻す(各演算のret_ecの部分)。 またエラー伝搬も行う。また後述するマスク処理も行われる。

定数演算#

定数演算とは定数倍、もしくは定数加算を行う機能のことである。それらをTable 20に示す。

Table 20 ElementContainerの定数演算#

演算

フォーマット

定数倍(新規コンテナ)

ret_ec = ec1.Mul(val)

定数倍(自分自身の変更)

ec1.MulMySelf(val)

定数加算(新規コンテナ)

ret_ec = ec1.Plus(val)

定数加算(自分自身の変更)

ec1.PlusMySelf(val)

定数倍

ec1の強度を一律val倍する。エラーもval倍される。

定数加算

ec1の強度に一律にvalを加える。エラーは変更なし。

演算結果

これらの関数には、演算結果を新しいコンテナとして作成するもの(新規コンテナ)と、自分自身を書き換えるもの(自分自身の変更)がある。必要に応じて使い分けることができる。

使用例#

以下に、四則演算と定数演算の具体的なサンプルスクリプトを示す。

サンプルデータ作成#

四則演算を行うためのサンプルデータを作成する。

ElementContainer作成#
 1import Manyo
 2
 3# ElementContainer作成1
 4ec1 = Manyo.ElementContainer()
 5ec1.Add("x", [0, 1, 2, 3, 4, 5])
 6ec1.Add("y", [100, 200, 300, 400, 500])
 7ec1.Add("e", [10.0, 14.14, 17.32, 20.0, 22.36])
 8ec1.SetKeys("x", "y", "e")
 9
10# ElementContainer作成2
11ec2 = Manyo.ElementContainer()
12ec2.Add("x", [0, 1, 2, 3, 4, 5])
13ec2.Add("y", [200, 300, 400, 500, 600])
14ec2.Add("e", [14.14, 17.32, 20.0, 22.36, 24.49])
15ec2.SetKeys("x", "y", "e")

四則演算#

ElementContainerの加減乗除を行う。

ElementContainerの加減乗除#
 1# 四則演算
 2ret_add = ec1 + ec2
 3ret_sub = ec1 - ec2
 4ret_mul = ec1 * ec2
 5ret_div = ec1 / ec2
 6
 7# 結果出力
 8print("ret_add Intensity = ", ret_add.PutYList())
 9print("ret_add Error = ", ret_add.PutEList())
10
11print("ret_sub Intensity = ", ret_sub.PutYList())
12print("ret_sub Error = ", ret_sub.PutEList())
13
14print("ret_mul Intensity = ", ret_mul.PutYList())
15print("ret_mul Error = ", ret_mul.PutEList())
16
17print("ret_div Intensity = ", ret_div.PutYList())
18print("ret_div Error = ", ret_div.PutEList())

【結果】

ret_add Intensity = [300.0, 500.0, 700.0, 900.0, 1100.0]
ret_add Error = [17.318764390105894, 22.358935573948955, 26.457180499818946,
                 29.99949332905474, 33.162172727371164]
ret_sub Intensity = [-100.0, -100.0, -100.0, -100.0, -100.0]
ret_sub Error = [17.318764390105894, 22.358935573948955, 26.457180499818946,
                 29.99949332905474, 33.162172727371164]
ret_mul Intensity = [20000.0, 60000.0, 120000.0, 200000.0, 300000.0]
ret_mul Error = [2449.3664486964785, 5476.665043619155, 9164.997763229405,
                 13416.226593196761, 18163.950038469055]
ret_div Intensity = [0.5, 0.6666666666666666, 0.75, 0.8, 0.8333333333333334]
ret_div Error = [0.061234161217411966, 0.060851833817990614,
                 0.057281236020183784, 0.05366490637278704, 0.05045541677352516]

定数演算#

ElementContainerの定数演算を行う。

ElementContainerの定数演算#
1# 定数演算
2ret_mul2 = ec1.Mul(1.5)
3ec1.MulMySelf(2.6)
4ret_plus = ec2.Plus(100)
5
6# 出力
7print("ret_mul2 Intensity = ", ret_mul2.PutYList())
8print("ec1.MulMySerf(2.6) Intensity = ", ec1.PutYList())
9print("ret_plus Intensity = ", ret_plus.PutYList())

【結果】

ret_mul2 Intensity = [150.0, 300.0, 450.0, 600.0, 750.0]
ec1.MulMySerf(2.6) Intensity = [260.0, 520.0, 780.0, 1040.0, 1300.0]
ret_plus Intensity = [300.0, 400.0, 500.0, 600.0, 700.0]

ElementContainerにおける横軸のbin変換#

横軸のbin変換とは、ヒストグラムのbinの配列を変更することである。例えば一つのbinの強度が弱ければ統計精度を上げるために隣り合う複数のbinをまとめて一つのbinにしたいときがある。または不揃いなbin幅の配列を等しいbin幅の配列にしたい場合、異なる領域のデータとして扱いたい(binの最大値、最小値を変更する)場合もあるだろう。

このbin変換で気をつけないといけないことは、ヒストグラムの性質上「bin幅が変わると見かけの強度(カウント数)も変わる」のが基本である、ということである。もう少し別の言い方をすれば「bin幅を変更しても、binあたりの見かけの強度(カウント数)は変わるが、その総和は変わらない」のがヒストグラムである(Fig.4 を参照)。

ElementContainerには、bin変換を行う関数が存在するので、それを示す。

figure of the difference of "Binning" and "Averaging"

Fig.4 横軸bin変換の関数 BinningAveraging による強度の変化#

Binning, ReBin#

ヒストグラムとしてbin変換を行うための関数である。BinningもReBinも全く同一の動作を行う。 引数の与え方は2種類ある。単純にbinをまとめるために正の整数を与える方法と、変換したい配列を直接与える方法である。 変換結果は新しいElementContainerが作成され納められ、それが戻り値となる。したがって関数を実行したElementContainerは何も変化しない。

引数が正の整数#

隣り合うbinをまとめるのに使う。例えば、隣り合う2つのbinを1つにまとめる(強度は2倍)場合は以下のように記述する。

Binning#
 1import Manyo
 2# ElementContainer作成
 3ec = Manyo.ElementContainer()
 4ec.Add("x", [0, 1, 2, 3, 4, 5])
 5ec.Add("y", [100, 200, 300, 400, 500])
 6ec.Add("e", [10.0, 14.14, 17.32, 20.0, 22.36])
 7ec.SetKeys("x", "y", "e")
 8
 9new_ec = ec.Binning(2)
10print("new_ec Intensity = ", new_ec.PutYList())

【結果】

new_ec Intensity = [300.0, 700.0, 500.0]

引数がbinの配列(vector<Double>)#

新しいbin配列を用いたいときに使用する。変更したいbin配列をPythonのリストではなく、C++ で定義されているvector<Double>という形式で与える必要がある。また先に述べたようにbin配列の変更で「強度の総和は変化しない」。

Binning( vector<Double> )#
 1# new_xというvector<Double>を作成
 2new_x = Manyo.MakeDoubleVector()
 3
 4# 0から200まで2.0間隔のList作成
 5v_list = [float(i) * 2.0 for i in range(100)]
 6
 7# v_listの中身をnew_x(vector<Double>)へ入れる
 8for v in v_list:
 9    new_x.append(v)
10
11# bin変更の実行
12new_ec = ec.Binning(new_x)
13
14# 強度の出力
15print("new_ec Intensity = ", new_ec.PutYList())

【結果】

new_ec Intensity = [...]

また、しばしば用いられるのが別のElementContainerのbin配列を用いてbin変換を行うやり方である。

Binning( vector<Double> ) 2#
1new_ec = ec.Binning(ec_sample.PutX())

ここでは、ec_sampleの横軸bin配列を取り出し(PutX()はvector<Double>で取り出す)、それを用いてecをBinningしている。

Averaging#

こちらもbin配列を変更するが、Binningとは異なり、強度は単位あたりの平均値であるとして扱われる。したがってbin幅を変更した場合でも、見た目の強度は変化しない。ただし当然ながら総和は保存されない。ElementContainerの強度が、ヒストグラムのカウント数(ヒストグラムデータ)ではなく、見た目ヒストグラムだが値は単位横軸あたりの強度(散布データ)に変換されている場合に使用できる。(将来、散布データを万葉ライブラリでサポート予定) 引数の与え方や戻り値の扱いは、Binningとまったく同じである。

引数が正の整数#

1new_ec = ec.Averaging(2)

引数がbinの配列(vector<Double>)#

1new_x = Manyo.MakeDoubleVector()
2for v in [float(i) * 2.0 for i in range(100)]:
3    new_x.append(v)
4new_ec = ec.Averaging(new_x)

四則演算するヒストグラムの横軸が異なる場合のルール#

二つのElementContainer間における四則演算において、両者の横軸が異なる場合においては以下のようなルールが適応される。 横軸が異なるというのは、binの幅と範囲の二点において、どちらか、もしくは両方異なることを言う。ヒストグラムの性質上「bin幅が変わると見かけの強度(カウント数)も変わる」ことに注意。

ルールとしては以下の通り。Fig. 5も参照のこと。

  1. bin幅が異なる場合、bin幅の大きなほう(分解能が荒いほう)へ合わせる。(前項の Binning を参照)

  2. 範囲が異なる場合、両者の重なる領域のみを演算し出力する。重複領域以外の演算データは失われる。

  3. bin幅もカバーする範囲も異なる場合、1.かつ2.、すなわち両者が同時にカバーする領域で、かつbin幅の大きなほうにならう。

figure of the operation on diferent bin width

Fig.5-1 bin幅の異なる場合の演算#

figure of the operation on diferent bin width

Fig5-2 範囲の異なる場合の演算#