物理の研究の備忘録

高エネルギー物理学とかいうマニアックな研究分野の博士課程にいるわたしの備忘録。主にPCの設定とか

c++ でテキストファイルを読み込んでループを回す時のメモ

データ解析においてテキストファイルに書かれたデータを読み込む機会は結構多い。

俺も今までさんざん使ってきたんだけど、結構細かい書き方忘れちゃうし、曖昧な箇所も多いのでこの際ちゃんと覚える。

例えば次のような内容のテキストファイル(test.dat)があったとする。

1  2

3  4

これを読み込んでみよう。

 

書き方その1

 void test(){
    int a,b;
    ifstream ifs;
    ifs.open("test.dat");
    int loop=0;
    ifs>>a>>b;
    while(!ifs.eof()){

    cout<<"loop="<<loop<<endl;
    cout<<"a,b="<<a<<","<<b<<endl;
    ifs>>a>>b;
    loop++;
  }

}

 

出力結果

loop=0

a,b=1,2

loop=1

a,b=3,4

メモ

ヘッダはfstream.hが必要。using name spaceとかは書いてないけどコンパイルするならほんとは必要。ファイルの読み込みはfstreamを通して行う。

ファイルを開くとき、ここでは一度fstreamクラスのオブジェクト(ifs)をつくってから、openという関数を使っているが、ifstream("test.dat")と一気にコンストラクタで開くことも可能。まぁどっちでもいい。

loopはloopの回数数えてるだけので別になくてもいい。ただ、for分と違って無限loopが怖いのでwhile文の場合はloop回数についつい神経質になってしまう。

eof()は読みこむ際に最後の行であるかを判定してtrue(0)かfalse(1)を返す。

うまく読み込めればfalse、最後までいって読み込めなくなったらtrueを返す。

  while文はtrueの時だけ回るので!がついているというわけ。

コードをよくよく見ると、1行目をloopの外で読み込んでからloopに突入し、表示→読み込みの順番でloopを繰り返しているが、これにはちゃんと意味がある。下の悪い例を見てほしい。

 

悪い書き方

 void test(){
    int a,b;
    ifstream ifs;
    ifs.open("test.dat");
    int loop=0;
    while(!ifs.eof()){

   ifs>>a>>b;

    cout<<"loop="<<loop<<endl;
    cout<<"a,b="<<a<<","<<b<<endl;
    loop++;
  }

}

 

出力結果

loop=0

a,b=1,2

loop=1

a,b=3,4

loop=2

a,b=3,4

 

違いはloopの中で読み込み→表示を繰り返してること。見てわかるように最後に一回余分にloopが回ってる。

この不具合は!eof()が最後の行を読み込んだときはtrueでその次の存在しない行を読み込んだ時に初めてfalseを出力するために発生する。

つまり、最後の存在しない行を読み込んで!eof()がfalseになった直後に表示を余分にしてしまうのだ。このへんはなんとなくコードを書いているとやってしまいがちなので注意する。(というかやってしまった)

書き方その2

 void test(){
    int a,b;
    ifstream ifs;
    ifs.open("test.dat");
    int loop=0;
    while(ifs>>a>>b){

    cout<<"loop="<<loop<<endl;
    cout<<"a,b="<<a<<","<<b<<endl;
    loop++;
  }

}

違いはwhile文の中身で、ifs>>a>>bの読み込みがうまくいってる限りloopが回り、読み込めなくなった時点で止まる。さっきよりすっきりしてるし、例の一回余分に読み込んでしまう不具合も発生しない。難点を挙げるとすれば読み込みのifs>>...の部分が長くなったときにwhile文のかっこの中身がごちゃごちゃしてしまって見づらいくらい?いやほんとに難点って言っていいのかわからないけど。

 

ちなみに言うまでもないけど、for文はloopの回数がわかってる時には使えるが、

datファイルの中身が何行あるかわからないときは今回みたいにwhile文を使うしかない

個人的にはfor文のほうが好きだけど致し方ない。

 

まとめ

・テキストファイルの読み込みはfstreamを使いwhile文でloopを回す

・fstream::eof()を使うときは最後の行の振る舞いに注意

 

おわり!

 

 

Linuxで自分の使ってるシェルの種類を確認するときのメモ

自分の使ってるシェルを確認

$ echo $SHELL

 

で現在使ってるシェルの種類がわかる。自分の環境だと。

/bin/tcsh

とでた。

cshを拡張、バグ修正したものがtcshらしい

cshtcshcsh系と呼ばれ、

shbashkshsh系と呼ばれる。文法とかも微妙に違う。

zshはどっちもいけるらしい。

 

$ cat /etc/shells で使えるシェルを確認。自分の環境だと

 

/bin/sh

/bin/bash

/sbin/nologin

/bin/ksh

/bin/zsh

/bin/tcsh

/bin/csh

/usr/bin/ksh

/usr/local/bin/tcsh

 

と出てくる。大抵のシェルは使えるみたいだ。cshの文法で適当にスクリプト書いてみる

 

test.csh

 

#! /bin/csh

set a=0

echo $a

 

csh ./test.csh

0が出力される。bashでやりたければ

a=0

echo $a

 

sh ./test.csh とか

bash ./test.csh

 

とかやればbashでもまわる。拡張子が.cshでも中身がbashの文法であれば普通にbashとして

まわった。どゆこと?と思ったが、どうやら拡張子は見やすくするために付けるだけであまり意味を持たないらしい。

まぁでも拡張子が.cshなのに中身がbashなのは混乱を招くので、test.shとかしといたほうがいいな。

ちなみに最初の#! /bin/cshcshで回す時に必要だと思ってたけど、これも別になくてもいいらしい。

 

 

次に実行権限を与える。

$ chmod +x test.csh

 

これで

./test.csh

だけで実行できるようになる。自分の環境がtcshだからcshで実行されたという理解でいいのかな?

今まで理解がなあなあで使ってた部分がちょっとすっきりした。

rootのTProfileで任意の幅でrebinしたりProfileどうしを足したり割ったりする方法

いくつかのTProfileor histogram)同士でrebinしたりProfile同士を足したり割ったりしたい。

今まではGetBinContent()でビンの中身持って来て足したりとか脳筋っぽいことをしてたんだけど、

histogramと違ってProfileの場合はエラーの計算とかがめんどくさい。

ヒストはエントリー数足してルートとればエラーになるけど、profileは誤差伝搬とか面倒だからね。

そんなわけで便利な関数がないか調べてみた。

 

1、TProfile同士を足す。

 

http://www-he.scphys.kyoto-u.ac.jp/member/n.kamo/wiki/doku.php?id=study:software:root:main

このページに書いてあった。

hist->Add(hist1,x);//binの値=現在の値+x*hist1の値

重みとか気にしないならx=1がデフォルトなので引数一個だけ入れれば大丈夫。

例えば BeforeProfile[N] というTProfileのオブジェクトを10個足したい場合

 

TProfile *profile;

for(int i=0;i<N;i++){

  if(i==0)profile = BeforeProfile[i];

  else profile->Add(BeforeProfile[i]);

}

 

みたいな感じで書けばよい。最初のTProfileには何も入ってないのでfor文の一回目は普通に代入して

2回目からAddしてるのがミソ。最初にこれを忘れて見事にbreakした。初期化って大事だね。

 

2、Rebinする

次にRebinする。今回は等間隔じゃなくて自分で任意の幅を決めてrebinしたい。

これもさっきのページに書いてあった。

 

・等分割の場合

TH1D h_rebin* = h1->Rebin(n);         //(1)

TH1D h_rebin* = h1->Rebin(n,"h_rebin"); //第二引数は新しく作るhistoの名前

 

・好きな幅で分割する

double xbins[n+1] = {};

TH1D h_rebin* = h1->Rebin(n,"h_rebin",xbins);

 

3引数に配列をぶっこむことですきな場所でrebinできるらしい。

(1)はn個で1つのbinにするという意味。全体でn個のbinに分けるという意味ではないので注意。

逆に(2)のnは何個に分けるかという意味なのでややこしい。配列の中身がn+1になってるのは最後の値の上限値があるから。

つまり0-1002分割したかったら{0,50,100}3つ値が必要ということ。

(2)の場合、TProfileRebinしても出力はTH1の形式になるので注意。

 

3、TProfile同士で割る

これもさっきのAddの代わりにDivide()という関数を使ったら値は出たのだが、エラーの値が超でかい。。

よくみるとWarningが出ていて

 

"WARNING!!: The algorithm in TProfile::Divide computing the errors is not accurate

  Instead of Divide(TProfile *h1, TProfile *h2, do:

  TH1D *p1 = h1->ProjectionX();

  TH1D *p2 = h2->ProjectionX();

   p1->Divide(p2);

 

とか出てる。Profile::Divideだと正しくエラー計算できないってこと?どういうこっちゃ。

もともとのソースコード見るとコメントに

//THE ALGORITHM COMPUTING THE ERRORS IS WRONG. HELP REQUIRED

 

help requiredって

どうやらDivide()は使い物にならなそう。GetBinContentとかでビンの値とエラーを持って来て

誤差伝搬とかで計算するしかなさそう。

 

結論、TProfileでもAddしたりRebinしたりする関数はあるが、Divideは使いものにならない。掛け算とかする関数もあるみたいだが、使ってないので使えるかわかんない。

c++でstd::stringを分割する方法のメモ

stringで文字列を定義した時に途中で分割する必要が出てきた。

例えば "8:3"という文字列を:で区切って8と3をそれぞれ取り出したい場合について考える。

調べるとそれっぽいページが出てきたのでやってみる。

C++ 文字列クラス std::string 入門

 

どうやらstdには標準で文字列を分割する関数がないので自分で実装する必要があるらしい。以下コードコピペ

#include <vector>
#include <string>
#include <sstream>      // std::ostringstream
std::vector<std::string> StringSplit(const std::string &str, char sep)
{
    std::vector<std::string> v;
    std::stringstream ss(str);
    std::string buffer;
    while( std::getline(ss, buffer, sep) ) {
        v.push_back(buffer);
    }
    return v;
}

使ってみる。

vector<string> vkey = StringSplit("8:3",':');

const string str_key1= vkey[0];

const string str_key2= vkey[1];

 

とかやれば確かに8と3に分割できた。

 

中身で何をやってるのか

inputの文字列をstringstreamにつっこみ、ある文字sepまでの文字列を

getlineで引っ張ってくる。while文でsepより前とsepより後の文字列を

vectorに順番に突っ込んでvectorを返り値として返す、みたいなことをやってるはず。

getlineは第3引数(sep)が現れるまでの文字を出力する仕様みたい。

 

””と''て何が違うんだっけ?と思ったが、文字列は""だけど一文字の場合は''で囲めばいいんだった。忘れてた。

これで分割し放題だ!

 

 【追記】

このままだと数字はstring型として扱われるので、int型とかに変換したかったら

stoi(str_key1)

とかすれば良い。

 

ラドンって知ってますか?~身近な放射性物質であるラドンのまとめ~

 

放射能の恐怖

 

3.11以降(といってももうずいぶん経ちますが)ニュースや新聞でも放射線を扱う話題が増えてきました。

原発に賛成とか反対とかいろんなことが言われてますが、どうも放射線に対して正しい知識をもってない人が感情論で意見を主張している例が多いように思えます。

「とにかく放射線は危険だから原発廃止すべき」

みたいな意見ですね。放射線は確かにとても恐ろしいですが、正しい知識に基づいて怖がっている人がはたしてどれくらいいるでしょうか?

 

寺田寅彦さんの言葉に

 

ものを怖がらな過ぎたり、怖がり過ぎたりするのはやさしいが、正当に怖がることはなかなか難しい

 

という言葉があります。どのような意見を持つにしろ、正しい知識を持つことは重要です。

 

f:id:hakase73:20160727013051j:plain

事故後の福島第一原発

 

さて、今回はそんな放射性物質の一つであるラドンについて注目して記事をまとめたいと思います。今回ラドンに注目した理由は2つあります。

 

1.放射能放射線について素人にもわかりやすく解説したページは多いが、ラドンにについては一般にあまり知られていないと感じるため。

2.自分が勉強したことをとりあえずまとめたい。

 

の2つです。2については極めて個人的な理由なのでまぁいいでしょう。

1について、、

 

なぜラドンなのか?

放射能放射性物質というとまず何を思い浮かべますか?

多くの人は「セシウム」や「プルトニウム」、「ウラン」、震災以降は「ヨウ素」なんかを思い浮かべる人が多いでしょう。そもそもラドン放射性物質であることを知らない人も多いかもしれません。放射線というとどうしても原爆や原発などをイメージする人が多いですよね。

しかし、被ばくする原因はそれ以外にもたくさんあります。

以下の図を見てください。

f:id:hakase73:20160727002534p:plain

主な被ばくの原因とその際にどれくらい被ばくするか(単位:ミリシーベルト)をまとめたものです

実は地球に住んでいるすべての人は普通に生活しているだけでも様々な要因で被ばくしています

例えばCTスキャンをとったりすると被ばくしますし、食べ物を食べるだけでも被ばくします。CTスキャンのような人工的な放射線を人工放射線、天然のものを自然放射線といいます。

そして自然放射線の中でも被ばくの大きな要素を占めているのがラドンの吸入による被ばくです。

しかもラドンはガスなので、吸い込んだのち体内で被ばくする内部被ばくです。

内部被ばくは外部被ばくに比べて健康へのリスクが高いです。

 

f:id:hakase73:20160727004053g:plain

 

ラドンについて知ることは、身近な放射線放射能を知るということです

放射線は目には見えません。手で触れて確かめることもできません。知識が少ないと恐怖の対象でかありません。

だからこそ、多くの人が放射線について正しい理解を持つべきだと思うのです。

 

最後にもう一つ、ラドンを学ぶ有用性を一つだけ、実験の観点から触れておきましょう。

放射性物質には半減期というものがあります。一言でいえば、放射性物質が半分になるまでにかかる時間です。半減期が長いということはずっと放射線と出し続けるということなので、なかなかやっかいです。では、現在地球に存在している放射性物質半減期はどれくらいでしょうか。

例えば地殻中に含まれるウランウラン238)の半減期はだいたい44億年くらいです。多くの人は

「えぇ。。?長っ」と多くの人は思ったでしょう。なんでこんなに長いのでしょうか。

それは放射性物質とはそもそも不安定な物質だからです。放射性物質は小さな視点で見ると、不安定な原子なので、放射線を出して安定な原子になるのです。一度安定な状態になると、もう放射線は出しません。つまり、半減期の短い物質は放っておいてもすぐに崩壊していなくなるのでなんの問題もないのです。逆にウランなんかは地球が誕生したことからありますが、地球が誕生してから今までの50億年間ずっと放射線を出し続け、ようやく半分になってきたところなのです。つまり最も厄介な放射性物質半減期の長い物質なのです。

原発問題で放射性物質のゴミが問題になっていますが、これは半減期が長く、ずっと放射線を出し続けるため問題なのです。

 

一方で、ウラン系列のラドン半減期は3.8日です。

「あれ、矛盾しているぞ。現在地球に残っている放射性物質はどれも半減期が何億年もある長いものなんじゃないのか?」

という疑問がわいた人は鋭い人です。ではなぜ半減期の短いラドンが地球上に存在していられるのか?

 

それはラドンが3-4日で崩壊しても次々と新しいラドンがわいてくるからです。

以下の図はラドンの崩壊系列です。地殻中にもともと存在するウランが崩壊して、トリウムになって、トリウムがまた崩壊して、、と次々と崩壊を繰り返してラドン(Rn)になるのです。

 

 

f:id:hakase73:20160727010305p:plain

 

大元であるウラン半減期がめちゃくちゃ長いので、ラドンが崩壊してポロニウム(Po)になっても次々と新しいラドンが沸いてくるのです。

つまり、ラドンは身近な放射性物質であるとともに、半減期の測定がほかと比べて用意です。ここから、ラドン放射線物質を使った実験教材としてもすぐれています。

ちなみにもう一つラドンにはトリウム系列という崩壊系列がありますが、トリウムから同様に崩壊を繰り返してラドンまでたどり着きます。

 

ラドンはどこにある?

先ほども言ったように、ラドンは天然に存在するガスです。スーハー深呼吸でもすれば簡単に被ばくします。こうやって聞くとやばい物質のような気がしますが、被ばくする量は微量なので問題ないです。被ばくについては「被ばくするかしないか」よりも「少量の被ばくで済むようにするにはどうするか」が重要なのです。

ラドンの場合は地下に多い傾向があるので、地上より地下のほうが被ばくのリスクは高まります。なので、地下に行くときはできるだけ喚起に気を付けたほうがいいでしょう。基本的に被ばくは体に良くないものですが、「少量の被ばくなら体にいい」という考え方もあるようです。少量の酒は体にいい、というのと同じような考え方でしょうか?ホルミシス効果というようです。これを利用したものに「ラドン温泉」なるものがあったり、「ドールストーン」という理容、健康目的で部屋に置くタイプなどいろいろあるみたいです。少量の被ばくは体への影響がわかりづらいため、いろいろは考え方があります。本当に体にいいのかもしれません。しかし、個人的には「被ばくは少量に抑えるに越したことはない」と思っています。あまりその手の情報に踊らされないようにしましょう。(ドールストーンは放射線の測定する実験用の放射線源としては重宝してますが。。)

 

f:id:hakase73:20160727012358j:plain

ドールストーン。公式サイトより。

 

まとめ

・我々は普通に生活しているだけでもある程度被ばくしている

・自然放射線の主な原因の一つにラドンの吸入による内部被ばくがある

ラドン半減期が短く測定が容易

ラドンを商用利用したものもあるが、あまりおすすめはしない

 

以上です。今回は放射線の発生原理などの物理的な現象や被ばくの計算式などについてはあまり触れませんでしたが、その辺についてはわかりやすく解説したサイトや本が多数あるのでよかったら勉強してみてくださいね。

 

わかりやすさを優先して多少正しくない表現も含まれているかもしれませんが、意見や質問などなんでも受け付けています。

 

おわり。

 

誰が原子をみたか『江沢洋』

せっかくブログを始めたので書評でも書く。

書評というか感想だけど。

今回紹介するのはこの本。

 

だれが原子をみたか (岩波現代文庫)

だれが原子をみたか (岩波現代文庫)

 

歴史的にどのような経緯で原子が発見されたのか、というテーマの本。

こうやって書くとテーマを「原子」に絞っているようだけど、実際は「科学史」としても随分ボリュームがあって教養になるし「読み物」としても十分面白い。

僕自身買ったのは2年くらい前なのだけど、時々忘れたころに本棚から引っ張りだして読みたくなるくらいには魅力的な本だと思う。また、もう40年前の本であるにも関わらず、ちょこちょこいろんなところで紹介されていたりする。

(実際僕がこの本を知ったのは田崎晴明さんの統計力学の本で紹介されているのを見たときだ)

いったいこの本のどこが面白いのか、僕の中で考えてみた結果、

科学的に考えることができる

ことが一番の魅力なんじゃないかと思う。僕は科学がすきだ。特に物理学が好きだ。こういうことをいうとたまに「へぇ、勉強が好きなんだ」とか「頭がいいんだねー」とか言われて奇異の目を向けられることがある。おそらくそういう人にとっての科学とは中学生時代の「理科の教科書を読んで暗記して勉強してテストで良い点をとること」とイコールなのだろう。高校に入ってからはそれは「難しい数式をこねくり回す科目」変化する。

前者についてもう少し具体的に考えてみる。例えば中学の理科の教科書では「すべての物質は原子からできています」と習う。そしてそれを暗記してテストで点をとる。これがテストで点をとるための勉強である。

でもよくよく考えると不思議だ。だって、生きている人や動物や、土や金属などの無機物、燃えている火や流れる水がすべて同じ原子からできているなんて納得できるだろうか?しかも原子なんて目には見えない。

僕はこういう疑問をもつことが科学を好きになるの第一歩なのだと思う。理科の教科書には、今では常識になっているものばかりだけど不思議がいっぱいだ。例えば

 

「空気が原子からできているなら、部屋の中の空気は時間が経つと重力で下の方に溜まってしまうのではないのか?」

 

「地球が太陽の周りを回ってるって本当だろうか?地球から見たら明らかに太陽が地球の周りを回っているように見える」

 

原子核はプラスの陽子と電荷を持たない中性子が集まってできているというけど、なぜプラス同士で反発しないのか?」

 

「熱の正体は分子の運動って本当だろうか?またそれはどうやって確かめられるんだろうか?そもそも電気の正体が『電子』の流れなんだから、熱の正体が『熱素』という目に見えない粒子だと考えても不都合はなさそうである」

 

とかね。これらの疑問にすべて自信を持って答えられるだろうか。これらの疑問を考えることを放棄し、ただ常識として覚えることに注力し始めた時点で、それは科学でなくただの苦痛な暗記科目に成り下がる。

こういう疑問を昔の人はあれこれ仮説を立てたり実験をしたりして確かめたのである。

どのような経緯で科学が始まり、当時の人はどのように考え、どんな実験をして、どのような思考を経て認められていったのか。この本にはそういった経緯が読みやすく文章で記されている。だからこそ様々なドラマがあり、読み物としても面白いのである。そして当時の人の記憶を追体験しているような気分になれるのだ。

 

根底にあるのは「この世界はどのようにできているのだろうか?」という誰もが一度は考えたことがあるであろう純粋な好奇心であり、それをあれこれ考えながら明らかにしていく。わくわくしないわけがないと個人的には思うのだけれど。。

個人的には大気圧の話が面白かった。

 

ちょこちょこ数式が出てくるものの、内容的には中学生が読んでもわかるし、また大人が読んでも学ぶことは多いとおもう。

 

書評ってこんな感じでいいのかな?なんか文章が堅いような気もする。

まぁいいや、おしまい!

 

 

Firefoxをvimのキーバインドで操作する方法〜vimperatorを入れよう〜

動機

vim。言わずと知れたテキストエディタである。

vimを使ってコードや文章を書くときは基本的にキーボードしか使わない。移動もコピペもすべてキーボード上のショートカットで行うのである。例えばカーソルの移動も矢印キーなんか使わず"hjkl"の4つを使って移動する。矢印キーはホームポジションから遠いからあんまり使わないのね。行コピーは"yy"、文字検索は"/"とかまぁ他にも大量のコマンドがある。つまり、基本的にホームポジションから動きたくないのである。vimmerにとってはマウスも矢印キーもテンキーもいらないのだ。

そんな感じでvimの素晴らしさに汚染されてくると、「あーwebブラウザ使うときにいちいちマウス使うのめんどくさいなー」とか「vimのコマンド使わせてくれー」という気持ちが湧き上がって発狂しそうになるのだ。(ほんとか?)

そんなわけで今回はFirefoxのアドオンを利用する。

ブラウザの話

世の中にはたくさんのブラウザがありますね。Windowsに標準で入ってるIEとかgoogleが開発してるgoogle Chromeとか。macのPCやiPhoneにデフォルトで入ってるのsafariとか。そしてlinux系のOSにデフォルトで入ってるのがFirefoxである。

それぞれのブラウザには個性があって、まぁぐぐるといろいろ出てくるのだけど、個人的な印象だと

IEくそ多くの人が使っている

Chrome→はやい

safari→pdfとかの表示が綺麗

Firefox→いろいろ拡張できる

 

といった感じ(個人の感想です)。Firefoxの何が便利かというと、アドオンを追加することでいろんな機能を追加できる点である。

そんなわけで今回はFirefoxvimperatorというアドオンを追加することで、Firefox上でvimっぽい動きができるようにする。やるぞぉ〜

 

vimperatorを入れる

Firefoxでこちらのページを開く

https://addons.mozilla.org/ja/firefox/addon/vimperator/

f:id:hakase73:20160705001256p:plain

ダウンロードを続ける→Firefoxに追加であっさり入る。再起動してくださいねと言われるので再起動。

 

Firefoxを開きなおすとvimperatorが使えるようになっている。

hjklで移動できる!感動。

いろいろとvimっぽい挙動をするのだけど、まだ操作がなれずによくわからない。

ちょこちょこ調べながら使っていこう。

そんなわけで使い方の説明や初期設定の説明は今回はしません。(なぜならまだ使いこなせていないから)

頑張って使いこなすぞー