サンプルコード#
はじめに#
万葉ライブラリの具体的な使い方を、簡単な使用例やサンプルコードを用いて示す。前章までにElementContainerなどの機能を紹介する際に幾つかのコードを示したが、それらの内容も含め本章にまとめて示す。 基本的にはPythonでの例を示す。また、本文中、あるいはNoteで、本書で必要になるPythonの基礎についても説明する。Pythonの基礎については、本書のAppendix A「Pythonイントロダクション」も参考して欲しい。Keywordでは、そのサンプルで特に覚えてもらいたい言葉を取り上げる。
本章で示すソースコードはわかりやすさを優先しており、速度、メモリ使用量などの最適化についてはここでは述べない。
本章では変数名であることを表すために 斜体 (例: ec_sample )を用いている。
本章でのPythonコードで、字下げ(インデント)は空白4文字としている。
Pythonの文中で#以降はコメントして扱われる。この本書では、例文の操作の結果などをコメントに記すことがある。
サンプルコード#
コマンドのヘルプ機能
ElementContainerのテキストファイル読み書き
ElementContainerの実数配列データの取り出しと表示
MLFモジュールの定義定数
ElementContainerArray、ElementContainerMatrixへのアクセス
EC、ECA、ECMのバイナリファイル読み書き
ヘッダ情報へのアクセス
ElementContainerArrayやMatrix内ElementContainerのヘッダ情報による検索
PythonとC++間のデータ型変換
ElementContainerの横軸の入れ替え
MLFターゲット情報の取得
拡張パッケージ「空蝉」によるヒストグラム化とプロトンカレントによる規格化
コマンドのヘルプ機能#
Pythonは、関数の機能を確認する方法として、help というコマンドが用意されている。この機能は、万葉ライブラリにも適応されており、下記のようにコマンドの機能などが簡単にではあるが表示される。
>>> import Manyo
>>> ec = Manyo.ElementContainer()
>>> help(ec.PutX)
【結果】
Help on method PutX in module Manyo.core:
PutX(self) method of Manyo.core.ElementContainer instance
vector< Double > ElementContainer::PutX()
Return the vector assigned to X-value.
ElementContainerのテキストファイル読み書き#
二つのテキストファイルからデータを読み込んで、それらを引き算して保存する操作を示す。
1import Manyo
2ec_sample = Manyo.ElementContainer()
3ec_sample.LoadTextFile("sample.dat")
4ec_background = Manyo.ElementContainer()
5ec_background.LoadTextFile("background.dat")
6ec_result = ec_sample - ec_background
7ec_result.SaveTextFile("result.dat")
1行目: 万葉ライブラリを使うために必要な命令文。以降では記述を省略するが、これが行われているものとする。
2行目: データコンテナ( ec_sample )を準備する。
3行目: このデータコンテナに"sample.dat"というファイルからデータを読み込む。
4, 5行目: もう一つデータコンテナ( ec_background )を準備して、そこに"background.dat"というファイルからデータを読み込む。
6行目: 二つのデータの引き算をし、その結果を新たなデータコンテナ( ec_result )に入れる。
7行目: この結果をファイルに保存する。
result.datのエラーの列を見て、誤差伝搬がなされていることを確認する。
Keyword#
- ElementContainer
万葉ライブラリのデータを収めるための入れ物、データコンテナ。基本的に実数配列( vector )が入る。万葉ライブラリの根幹の一つ。ElementContainer同士の演算をサポートしている。万葉ライブラリはElementContainerに始まりElementContainerに終わる。本稿ではしばしば EC と略す。HeaderBase も参照。より詳しくは第2章「データコンテナ」を参照。
- vector
C++のデータ型の一種で、C言語での配列を便利にしたようなもの。本書第2章「データコンテナ」に若干の説明を記した。詳しくはC++について書かれた書籍等を参照のこと。
Note#
ファイル形式は、3列(X、強度、エラー)、カンマ区切りを既定としている。
より詳しい説明は「ファイル入出力」の章に示した。
この保存方法ではX、強度、エラー以外の情報は保存されない。それらも含めて保存する方法は「EC、ECA、ECMのバイナリファイル読み書き」に示す。
ElementContainerの実数配列データの取り出しと表示#
ec という ElementContainer から色々なデータを取り出す方法を示す。 ここでは以下の例の前にecにデータが入っているものとする。
1x = ec.PutX()
2intensity = ec.PutY()
3error = ec.PutE()
4header = ec.PutHeader()
5pixel_id = header.PutInt4("PIXELID")
6pixel_position = header.PutDoubleVector("PixelPosition")
7ec.Dump()
1行目: ec から横軸のvectorを取り出し、x に代入する。
2行目: ec から強度のvectorを取り出し、intensity に代入する。
3行目: ec から誤差のvectorを取り出し、error に代入する。
4行目: ec からHeaderBaseを取り出し、header に代入する。
5行目: header からピクセルIDを取り出し、pixel_id に代入する。PXIELIDはピクセルIDを取り出すためのKey。
6行目: header からピクセル位置を取り出し、pixel_position に代入する。PixelPositionはピクセル位置を取り出すためのKey。
7行目: ec の内容全てを表示する。
Keyword#
- HeaderBase
万葉ライブラリのデータを収めるための入れ物。ElementContainerと異なり、様々なデータを入れられる。ElementContainerには必ずHeaderBaseが付加されている。HeaderBaseについても第2章「データコンテナ」でより詳しく述べた。
- Dump
ElementContainerやHeaderBaseについてこれを行うと、それぞれの内容を表示する。
MLFモジュールの定義定数#
MLFモジュールには中性子の質量やボルツマン定数など幾つかの物理定数、および長さや重さなどの変換係数が定義されており、使用することができる。
1import math
2import Manyo.MLF as mm
3
4Neutron_mass = mm.MLF_MASS_NEUTRON
5print("Neutron Math = {}".format(Neutron_mass))
6Neutron_E = 100.0 #[meV]
7Neutron_E = Neutron_E * mm.MLF_MEV2J #[meV]->[J]
8Neutron_v = math.sqrt(Neutron_E / Neutron_mass * 2.0)
9print(" the Neutron speed at 100.0 meV = %g [m/s] "%( Neutron_v ))
4行目: Neutron_mass にMLFモジュールの中性子質量定数(MLF_MASS_NEUTRON)を代入する。
5行目: Neutron_mass を表示する。
6行目: Neutron_E に中性子の速度として100.0を代入する(100.0 meVの意味)。
7行目: Neutron_E の単位を[meV]から[J]に変換する定数(MLF_MEV2J)で変換する。
8行目: 中性子速度を計算し、 Neutron_v に代入する( 1/2*Mn*v*vから)。
9行目: 中性子速度の計算結果を表示する。
その他の定数に関しては、本書のAppendix B「万葉ライブラリ関数リファレンス」を参照のこと。
ElementContainerArray、ElementContainerMatrixへのアクセス#
ecm という ElementContainerMatrix と、 ec_background という ElementContainer があるとしよう。 ecm 中の一つ目の ElementContainerArray に収められている ElementContainer 全てについて、 ec_background を引いた結果を新たに作った eca2 に収め、それを ecm に追加する。
1eca1 = ecm.Put(0)
2n = eca1.PutSize()
3eca2 = Manyo.ElementContainerArray()
4for i in range(n):
5 ec = eca1.Put(i)
6 ec -= ec_background
7 eca2.Add(ec)
8ecm.Add(eca2)
1行目: ecm から一つ目の ElementContainerArray を取り出し、 eca1 に代入する。
2行目: eca1 内の ElementContainer の数を n に代入する。
3行目: eca2 という空の ElementContainerArray を作る。
4行目: n 回のforループ。
5行目: eca1 から i 番の ElementContainer を取り出し、 ec に代入する。
6行目: ec から ec_background を引き、その結果を ec とする。
7行目: eca2 に ec を追加する。
8行目: ecm に eca2 を追加する。
Keyword#
- ElementContainerArray
ElementContainerを収めるためのデータコンテナ。ElementContainerArray自身もHeaderBaseを持つ。本節ではしばしば ECA と略す。第2章「データコンテナ」を参照。
- ElementContainerMatrix
ElementContainerArrayを収めるためのデータコンテナ。ElementContainerMatrix自身もHeaderBaseを持つ。本節ではしばしば ECM と略す。第2章「データコンテナ」を参照。
- range
Pythonの関数。引数に整数を指定することで、整数のリストを返す。例えば次のようになる。
range(3) # [0, 1, 2]
range(2,5) # [2, 3, 4]
range(10, 30, 5) # [10, 15, 20, 25]
Note#
Pythonでのforループの基礎を例を挙げて示す。
1for i in range(2,5):
2 print("i = {}".format(i))
1行めの range(2,5) は、先に示したように、 [2,3,4] を意味する。よってこのコードは
1for i in [2,3,4]:
2 print("i = {}".format(i))
という意味になる。まず1行目の range(2, 5) すなわち [2,3,4] の一つ目が i へ代入され、6行目のブロック( for よりもインデントされた行 )に渡される。ブロック内の処理が終わると再び for の行へ戻ってくるが、次は [2,3,4] の二つ目が i へ代入されてブロックへ流される。これを繰り返し、 [2,3,4] のすべての値が i に代入し終わるまで処理が続く。
このように、いわゆるC言語の for文の for ( int i=0; i<n; i++) と同じことが、この range(n) を用いれば使用できる。 また、あらかじめ与えておいたPythonリストの通りに for 文を実行できるので、不規則な数列でも( [ 2,53,4,100,1,...] )順に処理されるのみならず、文字列の配列すら同様に渡すことができる。
1ll = ["an Apple", "a Banana", "an Orange"]
2for fruit in ll:
3 print("I Love {} too!".format(fruit))
また、配列の長さを知りたい場合、 リスト であればlen(x_list)とすると得られる。
EC、ECA、ECMのバイナリファイル読み書き#
EC、ECA、ECMをバイナリファイルで入出力する方法を示す。
ここでは、filepath_ecm という ECM をバイナリで保存したファイルのパスがあり、これを読み込んでその中の ECA のうちヘッダのPSDIDが16~31のものだけをそれぞれバイナリで保存する処理を示す。
1filepath_ecm = "/home/hogehoge/sample.srlz"
2ecm = Manyo.ElementContainerMatrix()
3read_binary = Manyo.ReadSerializationFileBinary(filepath_ecm)
4read_binary.Load(ecm)
5del read_binary
6filepath_template = "psdid_%04d.srlz"
7for i in range(ecm.PutSize()):
8 eca = ecm.Put(i)
9 psd_id = eca.PutHeader().PutInt4("PSDID")
10 if psd_id in range(16,32):
11 out_filepath= filepath_template%psd_id
12 write_binary= Manyo.WriteSerializationFileBinary(out_filepath)
13 write_binary.Save(eca)
14 del write_binary
1行目: filepath_ecm にバイナリファイルの場所を代入する。
2行目: 空っぽのElementContainerMatrixを作成し、ecm と名付ける。
3行目: バイナリファイル読み込み機能である ReadSerializationFileBinary を作成し、read_binary と名付ける。その時に引数として ecm_filepath を指定する必要があり、これでファイルが開かれる。
4行目: 空っぽの ecm にファイルの中身を代入するコマンドである、 Load コマンドを ecm を引数にして実行する。
5行目: 不要となったバイナリファイル読み込みコマンドを消去する。
6行目: 次に、データを書き出すためのファイル名のテンプレートを用意する。
7行目: ループ処理の開始。ここでは、 i を0から ecm の内部コンテナの数-1 だけ変化させるループとなる。
8行め: i 番目のElementContainerArrayを取り出す。
9行目: 取り出したElementContainerArrayののヘッダを取り出し、"PSDID"の情報を整数で引き出し psd_id に代入する。
10行目: もし、 psd_id の値が、16〜32であれば、次のブロックを実行する。ここで psd_id in range(16,32)はPythonでよく使われる記法で、psd_id in [16,17,18,19,20,...32]と同じ意味であり、すなわちpsd_idがリスト[16,17,18,19,20,...32]に入っていればTrueとなるものである。
11行目: 6行目のファイル名テンプレートを利用して、 psd_id が挿入されたファイル名を out_filepath に代入する。
12行目: バイナリファイル保存機能である WriteSerializationFileBinary を作成し、write_binary という名前をつける。この時に引数として先ほど作成した保存ファイル名 out_filepath 利用している。
13行目: 保存を実行する。 Save コマンドは引数として、ElementContainer、ElementContainerArray、ElementContainerMatrixなどを与えることができるが、今回はElementContainerArrayであり、ecm.Put(i) として ecm の i 番目のElementContainerArrayを保存対象としている。
14行目: 不要なコマンドを消去する。
Note#
- バイナリファイルへの読み書き
このバイナルファイルへの書き出しは、テキストファイルでの入出力より処理が早い。また、テキストファイルの場合と異なり、ヘッダ情報も含めた全情報を保存、読み込みできる。ただし、書き出されたファイルには環境依存性、すなわち、ハードウェア(PCのCPU)やソフトウェア(特にウィンドウズやLinuxなど)の違いによって、互換性がなくなる可能性が高いが、別の環境へ持ち出したり持ち込んだりしないのであれば問題はない。したがって処理の途中経過のデータを一時的にファイルに保存する際に最も力を発揮する。
- Pythonリストの役割
Pythonに置いて、「変数 in リスト」、すなわち
psd_id in [1,2,3,4,5]
という表記は、「変数の値と同じものがリストの中にあるか」のチェックに使用される。これ自体がTrueやFalseという値を持ち、if文なのどの条件に使用される。
- 不要な関数、コマンドは消去
Pythonは、メモリをよく消費する。またC++のコードを使うためにメモリの管理も難しくなっている。よって使い終わった関数やコマンドはできるだけすぐに消去することをお勧めする。
コンテナのヘッダ情報へのアクセス#
ヘッダは、HeaderBaseと呼ばれるデータコンテナが利用されている。ElementContainerには、AddToHeaderという入力用コマンドとPutHeader()もしくはInputHeader()という取り出し・置き換え(上書き)コマンドがある。 コンテナのヘッダに情報を加える、取り出す場合の例を以下に示す。
1import Manyo
2ec = Manyo.ElementContainer()
3ec.AddToHeader("L1", 20.193)
4ec.AddToHeader("NumOfPixels", 100)
5ec.AddToHeader("Sample", "CuGeO3")
6
7hh = ec.PutHeader()
8L1 = hh.PutDouble("L1")
9NumOfPixels = hh.PutInt4("NumOfPixels")
10SampleName = hh.PutString("Sample")
11print("L1 = {}".format(L1))
12print("NumOfPixels = {}".format(NumOfPixels))
13print("Sample Name = {}".format(SampleName))
2行目: 空っぽのElementContainerを作成し、ec と名付ける。
3行目: ec のヘッダに "L1" というキーで実数を収納する。
4行目: 同様に ec のヘッダに "NumOfPixels" というキーで整数を収納する。
5行目: 同様に ec のヘッダに "Sample" というキーで文字列を収納する。
6行目: 空行
7行目: ec のヘッダのコピーを取り出す。
8行目: 取り出したヘッダから "L1" というキーの情報を実数として取り出し L1 に代入する。
9行目: 取り出したヘッダから "NumOfPixels" というキーの情報を整数として取り出し NumOfPixels に代入する。
10行目: 取り出したヘッダから "Sample" というキーの情報を文字列として取り出し SampleName に代入する。
11-13行目: 代入された3つの変数を表示する。
コンテナのヘッダの情報を書き換える場合の例を以下に示す。
1hh = ec.PutHeader()
2if hh.CheckKey("L1") == 1:
3 hh.Remove("L1")
4hh.Add("L1", 30.0)
5ec.InputHeader(hh)
6
7hh_new = ec.PutHeader()
8L1=hh_new.PutDouble("L1")
9NumOfPixels=hh_new.PutInt4("NumOfPixels")
10SampleName=hh_new.PutString("Sample")
11print("L1 = {}".format(L1))
12print("NumOfPixels = {}".format(NumOfPixels))
13print("Sample Name = {}".format(SampleName))
1行目: ec のヘッダを取り出す(一つ前のスクリプトと同じ ec )
2行目: ec のヘッダに "L1" というキーがあるかどうかを確認し、
3行目: もしキーがあれば "L1" の情報を削除する。
4行目: ec のヘッダに "L1" というキーで実数を収める( "L1"の情報の書き換え )。
5行目: ec のヘッダを上で書き換えたヘッダで置き換える。
6行目: 空行
7行目: 改めてec のヘッダのコピーを取り出し、 hh_new とする。
8行目: 取り出したヘッダ hh_new から "L1" というキーの情報を実数として取り出し L1 に代入する。
9行目: 取り出したヘッダ hh_new から "NumOfPixels" というキーの情報を整数として取り出し NumOfPixels に代入する。
10行目: 取り出したヘッダ hh_new から "Sample" というキーの情報を文字列として取り出し SampleName に代入する。
11-12行目: 代入された3つの変数を表示する。
Note#
- PutHeaer()とInputHeader()
AddToHeaderは新しい情報を加えることしかできないため、ヘッダから情報を引き出したり変更したりするには、一旦HeaderBaseを取り出す必要がある。まずPutHeader()にてHeaderBaseのコピーを取り出し、そこからさらに情報を引き出すことになる。あるいはヘッダ情報を編集(追加、置き換え)しいなら、PutHeaer()で取り出した後で編集し、InputHeader( HeaderBase )でElementContainerのヘッダを置き換える必要がある。
- ヘッダ情報の置き換え(上書き)
コマンドの紹介の意味もあり、スクリプトでは CheckKey 及び Remove を使って情報を置き換えたが、そのまま OverWrite というコマンドもある。Appendix Bの「万葉ライブラリ関数リファレンス」を参照のこと。
ElementContainerArrayやMatrix内ElementContainerのヘッダ情報による検索#
ElementContainerArrayやElementContainerMatrixに収められているElementContainerやElementContainerArrayのヘッダ内容に対して検索をかけ、適合するコンテナのみを取り出す方法を示す。例として、以下のようなデータがあるとする。
ElementContainerには位置敏感型検出器(PSD)の検出単位(Pixel)ごとのデータ
ヘッダには PIXELID というキーで検出単位のID番号(整数値)が収められている
ElementContainerArrayには、PSDごとにまとめられた複数のElementContainer
ElementContainerMatrixには複数のElementContainerArray
ElementContainerMatrixは dat という変数名
ここから特定の検出単位のID番号(キーは PIXELID )のElementContainerを取り出し、新しく用意したElementContainerArrayに追加する作業を行う。
Pythonだけを利用したスクリプトを以下に示す。
1target_id = 245
2result_eca = Manyo.ElementContainerArray()
3num_of_array = dat.PutSize()
4for i in range(num_of_array):
5 eca = ecm(i)
6 num_of_hist = eca.PutSize()
7 for j in range(num_of_hist):
8 header = eca(j).PutHeader()
9 if header.CheckKey("PIXELID")==1:
10 pixel_id = header.PutInt4("PIXELID")
11 if pixel_id == target_id:
12 result_eca.Add(eca.Put(j))
13
14if result_eca.PutSize() == 0:
15 print("We cannot found ElementContainer with id = {}".format(target_id))
1行目: target_id に245を代入する(これを目的のIDとする)。
2行目: result_eca に空のElementContainerArrayを代入しておく(これに見つけたElementContainerを入れる)。
3行目: num_of_array にElementContainerMatrixに含まれているElementContainerの個数を代入する。
4行目: ループ処理の開始。ここでは、 i を0から ecm の内部コンテナの数 num_of_array だけ変化させるループとなる。
5行目: eca に ecm の i 番目のコンテナ(そのもの)を取り出す( Put(i) を使わない方法: Noteを参照)。
6行目: num_of_hist に eca に含まれているElementContainerの個数を代入する。
7行目: ループ処理の開始。ここでは、 j を0から eca の内部コンテナの数 num_of_hist だけ変化させるループとなる。
8行目: header に eca の j 番目のコンテナのヘッダを取り出す。
9行目: もし、 header 内に PIXELID と言うキーがあれば
10行目: pixel_id にそのキーの値を整数で取り出して代入する。
11行目: もし pixel_id の値が target_id と同じであれば
12行目: result_eca に、この見つけたコンテナ( eca の j 番目のコンテナ)を加える。
13行目: 空行
14行目: もし result_eca が空であったら(検索に何一つかからなかったら)
15行目: メッセージを表示する。
このようにPythonコードとElementContainerやヘッダの扱いのみでコードを書くことができる。しかしループを行うのはPythonでは遅いし、検索ごとにこのコードを書くのも大変であるので、万葉ライブラリに入っている SearchInHeader 関数を用いることも可能である。その例を示す。
SearchInHeaderを利用したスクリプトを以下に示す。
1target_id = 245
2result_eca = None
3SIH = Manyo.SearchInHeader(dat)
4if SIH.Search("PIXELID", target_id):
5 result_eca = SIH.PutResultAsArray()
6
7if result_eca == None or result_eca.PutSize() == 0:
8 print("We cannot found ElementContainer with id = {}".format(target_id))
1行目: target_id に245を代入する(これを目的のIDとする)。
2行目: result_eca にNoneを代入しておく(これに見つけたElementContainerが入ったElementContainerArraを入れるつもり。見つからなければNoneのまま)。
3行目: SIH に SearchInHeader 関数を準備する(引数に目的のElementContainerMatrixの dat を与える)。
4行目: キー "PIXELID" の値が target_id であるElementContainerの検索を実行し、実行自体に問題がなかったなら
5行目: 検索結果を result_eca に代入する(ElementContainerArrayに見つかったElementContainerが入る)。
6行目: 空行
7行目: もし result_eca が None もしくは、サイズが0だったら(検索にかからなかったら)
8行目: メッセージを表示する。
Note#
- ElementContainerArrayからの高速なElementContainerの取り出し
ElementContainerArrayには Put と言うコマンドがあり、収納しているElementContainerのコピーを取り出すことができる。しかしコピーを取るという作業はそれだけでも時間がかかるため、今回のようにヘッダを見るだけの作業で使用すると大幅に時間がかかる。そこでElementContaierArrayには、コピーではなくそのものを取り出すやり方(C++言語で言うところのポインタ)がある。ただしそのものを取り出す場合、高速ではあるが取り扱いには厳重に注意する必要がある。Table 23にその差を示しておく。
コマンド |
作用 |
速度 |
危険度 |
---|---|---|---|
eca.Put(i) |
i番目のコンテナ(ElementContainer)のコピーを取り出す |
低速 |
低い(取り出したコンテナを消しても大丈夫) |
eca(i) |
i番目のコンテナそのもの(ポインタ)を取り出す |
高速 |
高い(取り出したコンテナを消すと元のElementContainerArrayも壊れる) |
- ElementContainerMatrixからの高速なElementContainer, -Arrayの取り出し
ElementContainerMatrixも Put でElementContainerArrayの取り出しを行うが、そのものを取り出す方法もある。また直接にElementContainerそのものを取り出す方法もある。どちらも高速であるが、大変に危険であるため取り扱いには注意が必要である。その違いをTable 24に示す。
コマンド |
作用 |
速度 |
危険度 |
---|---|---|---|
eca.Put(i).Put(j) |
i番目のElementContainerArrayの j番目のElementContainerのコピーを取り出す |
低速 |
低い(取り出したコンテナを消しても大丈夫) |
eca(i,j) |
i番目のElementContainerArrayの j番目のElementContainerそのもの(ポインタ)を取り出す |
高速 |
高い(取り出したコンテナを消すと 元のElementContainerArrayも壊れる) |
PythonとC++間のデータ型変換#
Pythonで配列を扱うために用いるリストから、C++で配列を扱うために用いるvectorへの変換、及びその逆の変換を行う方法を示す。
事前に、数値のリストである x_list 、数値のvectorである y_vector 、及び、文字列のリストである string_list が用意されているものとする。
1print type(x_list)
2x_vector = Manyo.ListToDoubleVector(x_list)
3print type(x_vector)
4y_list = Manyo.DoubleVectorToList(y_vector)
5string_vector = Manyo.StringVector()
6for s in string_list:
7 string_vector.push_back(s)
8print(type(string_vector))
1行目: x_list のデータ型を表示する。ここでは list と表示される。
2行目: リストをvectorに変換し x_vector に代入する。厳密にはvector<Double>に変換している。
3行目: x_vector のデータ型を表示する。
4行目: vectorをリストに変換し、 y_list に代入する。
5行目: 空のvector<string>を作る。
6, 7行目: string_list から一個ずつ文字列を s に取り出し、 string_vector に追加していく。
8行目: string_vector のデータ型を表示する。
万葉ライブラリはC++で作られており、Python上で作成したデータをそのまま万葉ライブラリで使うことができない場合がある。例えば リスト は本来ならそのままでは ElementContainer に入力できない。これは、list はPythonのデータ型であり、この類のデータは万葉ライブラリでは vector で扱わなければならないからである。それができるのは、ElementContainer内部でリストから vector への変換を行っているからである。そのほか、ElementContainerやヘッダから直接に配列を取り出す場合も リスト ではなく vector で取り出される( Put( KEY ) コマンドなど)。このような場合には、ここにあるような操作でデータ型変換を行う必要がある。
Keyword#
- list
Pythonでのデータ列の入れ物の一種。万葉ライブラリ環境では intensity というvectorに対して、DoubleVectorToList( intensity )とするとlistに変換される。7行目では、vectorのままでは表示できないためにvectorからlistに変換された結果を表示している。
- type
引数のデータ型を文字列で返す関数。なお、ある変数が、あるデータ型であるかを調べるためには、 isinstance という真偽を返す関数がある。これは例えば、 ec が ElementContainer であるかを調べるためには次のように使う。
isinstance(ec, Manyo.ElementContainer)
Note#
第2章「データコンテナ」も参照のこと。
ElementContainerの横軸を入れ替える#
ElementContainerに入っているヒストグラムデータの横軸を取り出して、他の単位への変換を行う。このサンプルでは、以下のような情報が入ったElemnetContianerがすでに ec という名前で存在するものとする。
軸 |
内容 |
---|---|
X軸 |
Time of Flight [micro-sec] |
Y値 |
強度 [counts] |
E値 |
エラー |
このスクリプトでは、X軸の配列を取り出すのに、PutXListやPutXではなく、Putを利用した。これはElementContainerに収められている複数の実数配列(vector<double>)へのアクセスの一つの方法である。計算された新しい横軸もvector<double>を用いて作成し、ElementContainerに加えている。また汎用性を高めるために、用意された ec のヒストグラム情報の キーが具体的にわからなく ても行えるように作成した。
1x_key = ec.PutXKey()
2y_key = ec.PutYKey()
3e_key = ec.PutEKey()
4tof_vector = ec.Put(x_key) # ec.PutX()と同じ
5
6d_list_vec = Manyo.MakeDoubleVector()
7for i in range(tof_vector.size()):
8 d_list_vec.append((tof_vector[i] - 7.7) / 15040.2)
9
10new_x_key = "d-spacing"
11ec.Add(new_x_key, d_list_vec)
12ec.SetKeys(new_x_key, y_key, e_key)
1行目: ec のX軸のキーを取り出して x_key に代入する。
2行目: ec のY軸のキーを取り出して y_key に代入する。
3行目: ec のE軸のキーを取り出して e_key に代入する。
4行目: ec から x_key をキーとする配列(ヒストグラムのX軸)をvector形式で取り出し tof_vector に代入する。
5行目: 空行。
6行目: d_list_vec という空の C++の実数配列であるvector<double>を作る。
7行目: tof_vector のサイズ( tof_vector.size() )を用いて、for文を i を使ってループさせる。
8行目: tof_vector の i 番目の値を取り出し、7.7引いて15040.2で割って d値を計算し、 d_list_vec に追加する。これを tof_vector.size() 回だけ繰り返す。
9行目: 空行。
10行目: 新しく利用するx軸のキーとして、 new_x_key を用意し、d-spacing を代入する。
11行目: ec に new_x_key というキーで d_list_vec を追加する。
10行目: ec のデータを new_x_key, y_key, e_key の配列を用いてヒストグラムとして構成する。
Keyword#
- vectorの作成
C++の配列である vector は、万葉ライブラリでは主に実数配列、整数配列、正の整数配列、文字列の配列に用いられる。表記は vector<double>, vector<Int4>, vector<UInt4>, vector<string> である。
- vectorのサイズ
C++の汎用配列であるvectorのサイズを知るのは .size というコマンドである。
Note#
- ElementContainerをヒストグラムとして使う利点
ElementContainerの構成のうち、どのような配列がどのようなキーで登録されているかは一般的には不明である。しかし、ヒストグラムとして設定する( SetKeys( X-KEY, Y-KEY, E-KEY ) )ことで、特にスクリプト中にキーをあらわに書くことなくヒストグラムデータの要素にアクセスできる。このように ElementContainerを新しく作ったり、処理を行ったら、必ずSetKeysを行うこと 。
- 横軸の問題
サンプルでは、Time of Flight [micro-sec]の値を単にd値に変換しただけであった。よって横軸のbin区切りは等間隔ではないことに注意。ただし強度はヒストグラムの性質上正確なものである。等間隔にしたい場合は、新しい横軸の配列をC++の実数配列 vector<double> で作成して、それを用いて Binning を実行する必要がある。
1import Manyo
2new_x_vec = Manyo.MakeDoubleVector()
3for i in range(1000):
4 new_x_vec.append(float(i) * 0.01)
5ec.Binning(new_x_vec)
MLFターゲット情報の取得#
ここでは中性子源直前の陽子数計測器の積算値を表示する方法を示す。ただしこのコマンドはJ-PARCサイト内のLAN接続を行う必要があり、通常は機能しない。ここではあくまで使用例だけを示し、具体的な使い方などの記述は省く。
1HOST = 'www-cont.j-parc.jp'
2API = Manyo.AcquireNeutronSourceTextInformation(HOST)
3begin = '2011/03/10 12:00:00'
4end = '2011/03/10 13:00:00'
5values = API.PutValueInformation('CT9', begin, end, -1)
6print(values[0]) # valuesはvector<Double>で返ってくる。単位は テラ個。
1行目: 中性子源データベースのホスト名を変数 HOST に代入する。
2行目: MLFターゲット情報取得用のインスタンス( API )を作る。引数は先ほどの HOST を指定する。
3行目: 開始時刻を変数 begin に代入する。
4行目: 終了時刻を変数 end に代入する。
5行目: API のPutValueInformationを使って、陽子数を取り出し values に代入する。'CT9'は中性子源直前の陽子数計測器を示す。最後の引数 -1 は beginからendまでの総和を返すという指示。
6行目: valuesはvector<Double>になっており、今回は中身は一つだけ(0番目)でありそれを表示する。
拡張パッケージ「空蝉」によるヒストグラム化とプロトンカレントによる規格化#
ここでは拡張パッケージ「空蝉」によるヒストグラム化を例として、具体的なスクリプトの実用例を示す。ただし、このスクリプトの実行には「空蝉」のインストールが必要であり本書の範囲を逸脱するため、参考として見ていただきたい。使用するのは万葉ライブラリ0.3と空蝉(リリース0.3.3.0)である。
本スクリプトの主な内容
ヒストグラム化に必要なパラメータファイル(あらかじめ作成済み)を指定し
イベントデータのヒストグラム化を行いElementContainerMatrixに収納し
ElementContainerMatrixのヘッダ情報から測定開始時刻と終了時刻情報を取り出し
それを用いてプロトンカレントを線源のサーバーから取得し、
その値でヒストグラムの強度をノーマライズする。
1import Manyo as mm
2import Manyo.Utsusemi as mu
3
4wfile = "/home/hoge/xml/WiringInfo.xml"
5dfile = "/home/hoge/xml/DetectorInfo.xml"
6runNo = 100
7dd=mu.UtsusemiEventDataConverterNeunet()
8dd.LoadParamFiles(wfile, dfile)
9dd.SetHistAllocation()
10
11ecm = mm.ElementContainerMatrix()
12dd.SetElementContainerMatrix(ecm, runNo, "/data", "")
13
14date_v = ecm.PutHeader().PutDoubleVector("MEASPERIOD")
15HOST = 'www-cont.j-parc.jp'
16API = Manyo.AcquireNeutronSourceTextInformation(HOST)
17begin = "%4d/%02d/%02d %02d:%02d:%02d" % (date_v[0], date_v[1], date_v[2], date_v[3], date_v[4], date_v[5])
18end = "%4d/%02d/%02d %02d:%02d:%02d" % (date_v[7], date_v[8], date_v[9], date_v[10], date_v[11], date_v[12])
19values = API.PutValueInformation('CT9', begin, end, -1)
20
21ecm.MulMySelf(1.0 / values[0])
1行目: 万葉ライブラリのコア関数の読み込み
2行目: 万葉ライブラリの空蝉関数の読み込み
3行目: 空行
4行目: Wiring Info ファイルの場所の指定( wfile に代入)
5行目: Detector Info ファイルの場所の指定( dfile に代入)
6行目: runNo に目的のRun Numberを代入
7行目: ヒストグラム化を行う関数の準備
8行目: WiringInfoとDetectorInfoのファイルを読み込み
9行目: WiringInfoの情報から必要なヒストグラムを内部に準備する。
10行目: 空行
11行目: 空のElementContainerMatrix( ecm )の用意
12行目: 与えられた RunNo やデータの場所の引数( "/data"など)を利用しイベントデータを読み込んで ecm へ代入する。
13行目: 空行
14行目: ElementContainerMatrixのヘッダにはイベントデータから読み出した測定開始時刻と終了時刻が入っているので、それを取り出す(キー: MEASPERIOD )。
15行目: 中性子源データベースのホスト名を変数HOSTに代入する。
16行目: MLFターゲット情報取得用関数(API)を準備する。引数は先ほどのHOSTを指定する。
17行目: 開始時刻を変数beginに代入する。
18行目: 終了時刻を変数endに代入する。
19行目: APIのPutValueInformationを使って、陽子数を取り出し values に代入する。 'CT9'は中性子源直前の陽子数計測器を示す。 最後の引数 -1 は beginからendまでの総和を返すという指示。
20行目: 空行
21行目: ElementContainerMatrixの強度を陽子数(values[0])で割る。valuesはvector<Double>になっている。今回は陽子数だけが必要なため、一つ目の値だけ(values[0])取り出している。