//*-- AUTHOR : B. Spruck
//*-- Modified : 26/10/2005 by B. Spruck
//*-- Modified : 15/nov/2005 by B. Spruck
//_HADES_CLASS_DESCRIPTION
////////////////////////////////////////////////////////////////////////
//
// HHypPPEpEmGammaKine
//
// This is
// i)  an ALGORITHM which updates the momenta using the HypKine Object
// ii) a SELECTOR which removes background using the kine refit
//
////////////////////////////////////////////////////////////////////////

using namespace std;

#include "hhypPPEpEmGammaKine.h"
#include "hypinfodef.h"
#include "hbasetrack.h"

ClassImp(HHypPPEpEmGammaKine)

HHypPPEpEmGammaKine::HHypPPEpEmGammaKine(Char_t *name_i, Option_t par[])
:HHypBaseAlgorithm(name_i,par)
{
	fit=new HHypKineFitPPEpEmGamma();
	kinetest=NULL;
}

HHypPPEpEmGammaKine::~HHypPPEpEmGammaKine()
{
	delete fit;
}

Double_t HHypPPEpEmGammaKine::getMomError(Double_t theta, Double_t phi, Double_t mass, Double_t p,Int_t sec,Bool_t simu)
{
	Double_t res;
	res=HypMomErr.getMomError( theta,  phi,  mass,  p, sec, simu);

	if(kinetest) kinetest->Fill(p,res,mass,sec);
	return(res);
}

Bool_t HHypPPEpEmGammaKine::DoTheRefit(TVector3 *momentum,Int_t idx_p1,Int_t idx_p2,Int_t idx_em,Int_t idx_ep,Float_t &prechi2,Float_t &chi2, Float_t *pulls)
{
	input[0]=momentum[0].Mag();
	input[1]=momentum[0].Theta();
	input[2]=momentum[0].Phi();

	input[3]=momentum[1].Mag();
	input[4]=momentum[1].Theta();
	input[5]=momentum[1].Phi();

	input[6]=momentum[2].Mag();
	input[7]=momentum[2].Theta();
	input[8]=momentum[2].Phi();

	input[9]=momentum[3].Mag();
	input[10]=momentum[3].Theta();
	input[11]=momentum[3].Phi();

	HCategory *ptrackcandCat = gHades->getCurrentEvent()->getCategory(catPidTrackCand);

	HPidTrackCand *p1=(HPidTrackCand *) ptrackcandCat->getObject(idx_p1);;
	HPidTrackCand *p2=(HPidTrackCand *) ptrackcandCat->getObject(idx_p2);
	HPidTrackCand *em=(HPidTrackCand *) ptrackcandCat->getObject(idx_em);
	HPidTrackCand *ep=(HPidTrackCand *) ptrackcandCat->getObject(idx_ep);

	HBaseTrack *b;

 Bool_t simuflag;
	simuflag=gHades->getCurrentEvent()->getCategory(catGeantKine);

	// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
	// Input Error calculation and Scaling up/down is
	// still under investigation and code will change in future
	// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
	Double_t FakErrMom, FakErrTheta, FakErrPhi;
	if( simuflag){// sim
//		FakErrMom= 1.37;
//		FakErrTheta=1.11;
//		FakErrPhi=1.11;
		FakErrMom=0.65;
		FakErrTheta=0.95;
		FakErrPhi=0.95 ;
	}else{// exp
		FakErrMom=0.7;// war 1.37;
		FakErrTheta=1.0; // war 1.11;
		FakErrPhi=1.0 ; //war 1.11;
	}

	Double_t momErr;

	//p1
	momErr=getMomError(input[1],input[2],14,input[0],p1->getHitData()->getSector(),simuflag);
	errInput[0]=FakErrMom*momErr;//getMomErr(p1->getHitData()->getSector(),input[0],14);// Proton

	b=(HBaseTrack *)(p1->getTrackData()->getBaseTrack(p1->getTrackData()->getBestMomAlg()));
	errInput[1]=FakErrTheta*b->getErrTheta();
	errInput[2]=FakErrPhi*b->getErrPhi();
	if( momErr<0.0 || b->getErrTheta()>0.1/*TMath::Pi()*/ || b->getErrPhi()>0.1/*TMath::Pi()*/ ){
		cerr << algoName << "MomErr<0, Theta or Phi Error>Pi().. does not make sense to fit! " << endl;
		return kFALSE;
	}

	//p2
	momErr=getMomError(input[4],input[5],14,input[3],p2->getHitData()->getSector(),simuflag);
	errInput[3]=FakErrMom*momErr;//FakErrMom*getMomErr(p2->getHitData()->getSector(),input[3],14);// Proton

	b=(HBaseTrack *)(p2->getTrackData()->getBaseTrack(p2->getTrackData()->getBestMomAlg()));
	errInput[4]=FakErrTheta*b->getErrTheta();
	errInput[5]=FakErrPhi*b->getErrPhi();
	if( momErr<0.0 || b->getErrTheta()>0.1/*TMath::Pi()*/ || b->getErrPhi()>0.1/*TMath::Pi()*/ ){
		cerr << algoName << "MomErr<0, Theta or Phi Error>Pi().. does not make sense to fit! " << endl;
		return kFALSE;
	}

	// e-
	momErr=getMomError(input[7],input[8],3,input[6],em->getHitData()->getSector(),simuflag);
	errInput[6]=FakErrMom*momErr;//FakErrMom*getMomErr(em->getHitData()->getSector(),input[6],3);// e-

	b=(HBaseTrack *)(em->getTrackData()->getBaseTrack(em->getTrackData()->getBestMomAlg()));
	errInput[7]=FakErrTheta*b->getErrTheta();
	errInput[8]=FakErrPhi*b->getErrPhi();
	if( momErr<0.0 || b->getErrTheta()>0.1/*TMath::Pi()*/ || b->getErrPhi()>0.1/*TMath::Pi()*/ ){
		cerr << algoName << "MomErr<0, Theta or Phi Error>Pi().. does not make sense to fit! " << endl;
		return kFALSE;
	}

	// e+
	momErr=getMomError(input[10],input[11],2,input[9],ep->getHitData()->getSector(),simuflag);
	errInput[9]=FakErrMom*momErr;//FakErrMom*getMomErr(ep->getHitData()->getSector(),input[9],2);// e+

	b=(HBaseTrack *)(ep->getTrackData()->getBaseTrack(ep->getTrackData()->getBestMomAlg()));
	errInput[10]=FakErrTheta*b->getErrTheta();
	errInput[11]=FakErrPhi*b->getErrPhi();
	if( momErr<0.0 || b->getErrTheta()>0.1/*TMath::Pi()*/ || b->getErrPhi()>0.1/*TMath::Pi()*/ ){
		cerr << algoName << "MomErr<0, Theta or Phi Error>Pi().. does not make sense to fit! " << endl;
		return kFALSE;
	}

	fit->ResetOutput();
	fit->SetInput(input,errInput);

	Int_t result;
	result=fit->minuitFit();
	if(result==4){// or maybe !=0 ?
		// result==0 means O.K.
		// result==4 : fit not converging
		// thus IMO this combination should be rejected. (Bjoern)
		// Difference: Anars code is not checking for this!
		return kFALSE;
	}

	fit->GetOutput(output,errOutput);

	prechi2=0.;
	for(Int_t ii=0; ii<12; ii++)
	{
		Float_t cs;
		cs=(input[ii]-output[ii])/errInput[ii];
		prechi2+=cs*cs;
	}

	fit->secondIter(input,output,errInput,output2,derOut);

	for(Int_t i=0; i<12; i++)
	{
		output[i]=output2[i];
	}

	momentum[0].SetXYZ(output[0]*sin(output[1])*cos(output[2]),output[0]*sin(output[1])*sin(output[2]),output[0]*cos(output[1]));
	momentum[1].SetXYZ(output[3]*sin(output[4])*cos(output[5]),output[3]*sin(output[4])*sin(output[5]),output[3]*cos(output[4]));
	momentum[2].SetXYZ(output[6]*sin(output[7])*cos(output[8]),output[6]*sin(output[7])*sin(output[8]),output[6]*cos(output[7]));
	momentum[3].SetXYZ(output[9]*sin(output[10])*cos(output[11]),output[9]*sin(output[10])*sin(output[11]),output[9]*cos(output[10]));

	chi2=0.;
	for(Int_t ii=0; ii<12; ii++)
	{
		Float_t cs;
/*		if(ii==3 || ii==6 || ii==9 || ii==0){
			cs=(1/input[ii]-1/output[ii])*(1/input[ii]-1/output[ii])/errInput[ii]/errInput[ii]*input[ii]*input[ii]*input[ii]*input[ii];
		}else{*/
			cs=(input[ii]-output[ii])/errInput[ii];
//		}
		chi2+=cs*cs;
	}

	for(Int_t i=0; i<12; i++){
		// Real Pull is:
		Double_t nom;
		// Preisfrage: ist das der Pull des Impulses oder 1/Impuls???
		// folgender Auskommentierter Code ist ein Test!!!
/*		if(i==0 ||i==3 ||i==6||i==9){
			nom=(input[i]*input[i])/errInput[i]*errInput[i]-(output[i]*output[i])/derOut[i];// derOut already squared
			if(nom>0){
				pulls[i]=(1.0/input[i]-1.0/output[i])/TMath::Sqrt(nom);
			}else{
				pulls[i]=-99.0;// NAN would not be visible in histogramm
			}
		}else*/{
		nom=errInput[i]*errInput[i]-derOut[i];// derOut already squared
		if(nom>0){
			pulls[i]=(input[i]-output[i])/TMath::Sqrt(nom);
		}else{
			pulls[i]=-99.0;// NAN would not be visible in histogramm
		}
	}
	}

	return kTRUE;
}

Bool_t HHypPPEpEmGammaKine::execute()
{
// 	if (mylist->getNpart() != 4)
// 		return kFALSE;
	//needs 4 particles

	TVector3 momentum[4];

	// The momenta will be modified... if i am the first this
	// is /in principle/ not needed but who knows, am I?
	mylist->initcopyMomentum();

	mylist->CombIteratorReset();
	while (mylist->CombIterator()) {
 		if (mylist->getNvalid() != 4) continue;// p p e+ e-

		Float_t miss_pid;
		if (!mylist->getUserValue(FILLER_MISSING_PID, miss_pid)) miss_pid = -999;

		if(miss_pid!=1){
			Error("HHypPPEpEmGammaKine::execute()","This Fitter fits only missing gamma, but FILLER_MISSING_PID is ",miss_pid);
			continue;
		}

		// Getting the particles
		TLorentzVector proton1 = mylist->getTLorentzVector("p", 1);
		TLorentzVector proton2 = mylist->getTLorentzVector("p", 2);
		TLorentzVector em = mylist->getTLorentzVector("e-", 1);
		TLorentzVector ep = mylist->getTLorentzVector("e+", 1);

		Int_t idxProton1=mylist->getIdxPidTrackCand("p", 1);
		Int_t idxProton2=mylist->getIdxPidTrackCand("p", 2);
		Int_t idxElectron=mylist->getIdxPidTrackCand("e-", 1);
		Int_t idxPositron=mylist->getIdxPidTrackCand("e+", 1);

		if (mylist->getIterStatus() != kTRUE) continue;
		{
		 Bool_t invalid_input=false;
			for(Int_t i=0; i<4; i++){
				HPidTrackCand *pPidTrackCand;
				HPidHitData const *hit;
				pPidTrackCand=mylist->getPidTrackCand(i);
				hit=0;
				if(pPidTrackCand) hit=pPidTrackCand->getHitData();
				if( hit){
					if (hit->fInnerMdcChiSquare < 0){
						invalid_input=true;
						break;
					}
				}else{
					cerr << algoName << "HHypXKine::execute(): Not PidPart or Hit data! " << endl;
					exit(0);
				}
			}
			if(invalid_input){
				mylist->removeComb();
				continue;
			}
		}

		if (mylist->getIterStatus() == kTRUE) {

				Float_t prechi2, chi2;
				Float_t pulls[32];// war 12
				momentum[0]=proton1.Vect();
				momentum[1]=proton2.Vect();
				momentum[2]=em.Vect();
				momentum[3]=ep.Vect();
				if(DoTheRefit(momentum,// order in momentum: proton, proton, e-, e+
						idxProton1,idxProton2,idxElectron,idxPositron,prechi2,chi2,pulls)){

					if (histofile) {
						Float_t tmp[50];
						Int_t ii;
						ii=0;
						tmp[ii++]=chi2;
						tmp[ii++]=prechi2;
						tmp[ii++]=1;// missing gamma

						tmp[ii++]=14;// Proton
						tmp[ii++]=pulls[0];
						tmp[ii++]=pulls[1];
						tmp[ii++]=pulls[2];
						tmp[ii++]=proton1.Vect().Mag();
						tmp[ii++]=proton1.Vect().Theta();
						tmp[ii++]=proton1.Vect().Phi();
						tmp[ii++]=momentum[0].Mag();
						tmp[ii++]=momentum[0].Theta();
						tmp[ii++]=momentum[0].Phi();

						tmp[ii++]=14;// Proton
						tmp[ii++]=pulls[3];
						tmp[ii++]=pulls[4];
						tmp[ii++]=pulls[5];
						tmp[ii++]=proton2.Vect().Mag();
						tmp[ii++]=proton2.Vect().Theta();
						tmp[ii++]=proton2.Vect().Phi();
						tmp[ii++]=momentum[1].Mag();
						tmp[ii++]=momentum[1].Theta();
						tmp[ii++]=momentum[1].Phi();

						tmp[ii++]=2;// e+
						tmp[ii++]=pulls[6];
						tmp[ii++]=pulls[7];
						tmp[ii++]=pulls[8];
						tmp[ii++]=ep.Vect().Mag();
						tmp[ii++]=ep.Vect().Theta();
						tmp[ii++]=ep.Vect().Phi();
						tmp[ii++]=momentum[3].Mag();
						tmp[ii++]=momentum[3].Theta();
						tmp[ii++]=momentum[3].Phi();

						tmp[ii++]=3;// e-
						tmp[ii++]=pulls[9];
						tmp[ii++]=pulls[10];
						tmp[ii++]=pulls[11];
						tmp[ii++]=em.Vect().Mag();
						tmp[ii++]=em.Vect().Theta();
						tmp[ii++]=em.Vect().Phi();
						tmp[ii++]=momentum[2].Mag();
						tmp[ii++]=momentum[2].Theta();
						tmp[ii++]=momentum[2].Phi();

/*					for(Int_t i=0; i<12; i++){
							tmp[ii++]=errInput[i];
						}*/
						qa->Fill(tmp);
					}

					proton1.SetVect(momentum[0]);
					proton2.SetVect(momentum[1]);
					em.SetVect(momentum[2]);
					ep.SetVect(momentum[3]);

					mylist->setMomentum("p", 1, momentum[0]);
					mylist->setMomentum("p", 2, momentum[1]);
					mylist->setMomentum("e-", 1, momentum[2]);
					mylist->setMomentum("e+", 1, momentum[3]);
					if (mylist->getIterStatus() == kFALSE) {
						cout << "!!!!!error HHypPPEpEmGammaKine execute mylist->getIterStatus() == kFALSE!!!!!! " << endl;
						exit(2);
					}
					mylist->resetProbAlg( TMath::Prob(chi2,1));
					mylist->setUserValue(KINEFIT_CHI2, chi2);
					mylist->setUserValue(KINEFIT_PRECHI2, prechi2);
				}else{
					// Fit failed -> Remove Combination
				//	cout << "HHypPPEpEmGammaKine DoTheRefit() == kFALSE"  << endl;
					mylist->removeComb();
			}
		}else{
			cerr << algoName << " got no TLorentzVector " << endl;
		}
	}                             //END Iterator

	if (exitIdx > -1)
		return kTRUE;
	return kFALSE;
}

Bool_t HHypPPEpEmGammaKine::init()
{
	// need to get name from channel
	TString output(channel->Get(exitList));

	if (histofile){
		qa = new TNtuple(output + TString("_kine_debug"), "Kine Debug ntuple",
			"chi2:prechi2:miss_pid"

			":pid1:pull_p1:pull_the1:pull_phi1"
			":old_p1:old_the1:old_phi1"
			":new_p1:new_the1:new_phi1"

			":pid2:pull_p2:pull_the2:pull_phi2"
			":old_p2:old_the2:old_phi2"
			":new_p2:new_the2:new_phi2"

			":pid3:pull_p3:pull_the3:pull_phi3"
			":old_p3:old_the3:old_phi3"
			":new_p3:new_the3:new_phi3"

			":pid4:pull_p4:pull_the4:pull_phi4"
			":old_p4:old_the4:old_phi4"
			":new_p4:new_the4:new_phi4"

//			":errin_p_p1:errin_the_p1:errin_phi_p1"
//			":errin_p_p2:errin_the_p2:errin_phi_p2"
//			":errin_p_em:errin_the_em:errin_phi_em"
//			":errin_p_ep:errin_the_ep:errin_phi_ep"
		);
		kinetest = new TNtuple(output + TString("_kine_errors"),
			"Kine DebugErrors ntuple","p:dp:m:sec");
	}

	return kTRUE;
}

Bool_t HHypPPEpEmGammaKine::reinit()
{
	//Here, we set/reset the Momentum Error
	//Resolution could be run-dependent!

// Bool_t simuflag;
//	simuflag=gHades->getCurrentEvent()->getCategory(catGeantKine);

	return kTRUE;
}

Bool_t HHypPPEpEmGammaKine::finalize()
{
	if (histofile) qa->Write();
	if (kinetest) kinetest->Write();
	return kTRUE;
}

Last change: Sat May 22 12:57:55 2010
Last generated: 2010-05-22 12:57

This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.