Z Candidateの質量分布を作る

次の5つのファイルをダウンロードしてください。(code03)

main.cxx
ZZ.h
ZZ.cxx
signal.script
Makefile
ZZ.h,cxxにメンバ関数を若干追加しました。
解析の大きな流れは、もちろん

1. Muon candidatesの選択
2. Z candidatesの再構成

です。
そのために、メンバ関数

1. SelectMuon()
2. MakeZBoson()

を追加しました。また、MakeZBoson()は内部で

MakeZBoson(std::vector &ZBosons, std::vector &Leptons)

をコールしています。これは単純にElectronを追加したときに便利だと思ったからです。
あと、追加したメンバ関数は

- ClearLists()
- DeleteLists()

です。これらはプログラムの上では重要な役割を持っています。- 解析の上ではどうでもいいが、存在しないと解析自体はうまく終らない。
ClearLists()はMuonとZmmという入れ物(std::vector)の中をきれいにしています。
つまり、メンバであるMuonとZmmの中にあるものを入れ物から削除します。
(入れ物から削除するだけで、それ以上のことはしません。)
これをしないと、イベントループで次のイベントのとき前イベントのMuonやZmmが残ってしまいます。
きちんとプログラムの流れを考えて、どこかに必ず必要です。今回はイベントの最初の方におきました。
DeleteListsはZmmの中身を"delete"しています。
Zmmの中身の生成過程を見ると分かりますが"new"で生成しています。
ユーザーが"new"で生成したのだから、"delete"もユーザーの責任で行います。
この関数を呼ばないとメモリーリークが起こります。
これも、きちんとプログラムの流れを考えてどこかに必ず必要です。今回はイベントの最後におきました。
DeleteListsの中から呼ばれているDeleteListは基底クラスのメンバ関数で

void ATHENA_CBNT_Event::DeleteList(std::vector &list) {
  for (std::vector::reverse_iterator i = list.rbegin();
       i != list.rend(); ++i) {
    delete *i;
  }
}

というシンプルな内容です。
よくあることですが、これらはreturnをたくさん入れると呼び忘れることがあります
ここで、若干プログラムの中を見てみます。

int Userana::SelectMuon(void)
{
  int nMuonPlus  = 0;
  int nMuonMinus = 0;

  for (unsigned i=0;i<GetMuonListAtlfast().size();++i) {
    
    // GetMuonListAtlfast()[i]だと長いので短い名前のポインタで受けた。(参照でもいい)
    Particle * trk = GetMuonListAtlfast()[i];
    
    // Isolated Muonかどうかチェックしている。
    // PIDクラス($ATLJ_TOP_DIR/include/particle/PID.h)を利用。
    if (trk->pId().isIsoMuon()) {
      
      // Ptやetaの情報にアクセス。
      // 本来はMomentumクラス($ATLJ_TOP_DIR/include/particle/Momentum.h)の役割だが
      // よく使うものだけはParticleクラス($ATLJ_TOP_DIR/include/particle/Particle.h)にもメンバ関数が準備されている。
      if (trk->pt() > mc_IsoMuonPtCut &&
          fabs(trk->eta()) < mc_IsoMuonEtaCut) {

        Muon.push_back(trk);
        
	// 電荷はPDG idで確認する。
        // Ptypeクラス($ATLJ_TOP_DIR/include/particle/Ptype.h)を利用するが、
        // これもよく使うのでParticleクラスにメンバ関数がある。
        if (trk->pType().pdgid() > 0) {

          ++nMuonMinus;
        } else {
          ++nMuonPlus;
        }
      }
    }
  }
  
  if (nMuonMinus >= 1 && nMuonPlus >= 1 &&
      nMuonMinus+nMuonPlus >= mc_IsoLetponNCut) {
    return 1;
  } else {
    return 0;
  }
}
void Userana::MakeZBoson(std::vector<Particle*> &ZBosons,
                         std::vector<Particle*> &Leptons)
{
  int nL = int(Leptons.size());
  if (nL < 2) return;

  for (int i=0;i<nL-1;++i) {
    for (int j=i+1;j<nL;++j) {
      
      // 電荷が逆であることを要求している。
      if (Leptons[i]->pType().pdgid()*Leptons[j]->pType().pdgid() < 0) {
        
        // CLHEPの4次元運動量を扱うクラス(HepLorentzVector)を利用している。
	// +という演算子があるので簡単。
        HepLorentzVector p = Leptons[i]->p()+Leptons[j]->p();
        
	// Particleオブジェクトを作成している。
	// 引数としては、HepLorentzVectorとPtype。ZのPDG idは23。
        Particle *z = new Particle(p,Ptype(23));
        
	// より詳しい解析のために、Zをどの粒子から再構成したか? という情報を保存しておく。
	// このために、Relationクラス($ATLJ_TOP_DIR/include/particle/Relation.h)を利用する。
        if (Leptons[i]->pType().pdgid() < 0) { // in order: + - of charge
          z->relation().append(Leptons[i]);
          z->relation().append(Leptons[j]);
        } else {
          z->relation().append(Leptons[j]);
          z->relation().append(Leptons[i]);
        }
        ZBosons.push_back(z);
      }
    }
  }
}
これらのプログラムを実行する(10000イベント)とZ candidatesの質量分布は次のようになります。

Go to the next page
Go to the previous page

Go to the index page

jtanaka