// $Id: RecoShowerTrack.cc,v 1.22 2006/03/28 14:26:23 naumov Exp $
// Author: Dmitry.Naumov   2005/10/11

/*****************************************************************************
 * ESAF: Euso Simulation and Analysis Framework                              *
 *                                                                           *
 *  Id: RecoShowerTrack                                                      *
 *  Package: Energy                                                          *
 *  Coordinator: Dmitry.Naumov                                               *
 *                                                                           *
 *****************************************************************************/

//_____________________________________________________________________________
//
// RecoShowerTrack
//
// <extensive class description>
//
//   Config file parameters
//   ======================
//
//   <parameter name>: <parameter description>
//   -Valid options: <available options>
//

#include "RecoShowerTrack.hh"
#include "EConst.hh"
#include "SlastShowerGenerator.hh"
#include "ShowerTrack.hh"
#include "FluoCalculator.hh"
#include "Config.hh"
#include "EsafSpectrum.hh"
#include "LightSourceFactory.hh"
#include "Ground.hh"
#include "O1_ClearSkyPropagator.hh"
#include "DetectorGeometry.hh"
#include "RadiativeFactory.hh"
#include "EnergyModule.hh"
#include "RecoEvent.hh"
#include "EEvent.hh"
#include "ETruth.hh"
#include "Atmosphere.hh"

#include <TMath.h>
#include <TCanvas.h>
#include <TProfile.h>
#include <TList.h>
#include <TPolyMarker3D.h>

using namespace sou;
using namespace TMath;
using namespace EConst;

ClassImp(RecoShowerTrack)

// constructors, destructor
//_____________________________________________________________________________
 RecoShowerTrack::RecoShowerTrack(): EsafMsgSource() {
    //
    // Constructor
    //
    Constructor();
}

//_____________________________________________________________________________
 RecoShowerTrack::RecoShowerTrack(Float_t t, Float_t p, Float_t h, Float_t tfov, Float_t pfov): EsafMsgSource() {
    //
    // Constructor
    //
    Constructor();
    SetThetaPhi(t,p);
    SetThetaPhiFoV(tfov,pfov);
    SetHmax(h);
    
}
//_____________________________________________________________________________
 void RecoShowerTrack::Constructor() {
    //
    // This is default ctor
    fHmax = -100;
    fShowerDir.SetXYZ(0,0,0);
    fEusoDir.SetXYZ(0,0,0);
    string fluoname         = Config::Get()->GetCF("Reco","EnergyModule")->GetStr("EnergyModule.fFluoCalculator");
    fFluoCalculator         = LightSourceFactory::Get()->GetFluoCalculator( fluoname );    
    fEusoAlt                = Config::Get()->GetCF("General","Euso")->GetNum("Euso.fAltitude")*km;
    fEnergyDistributionName = Config::Get()->GetCF("Reco","EnergyModule")->GetStr("EnergyModule.fEnergyDistributionName");
    fEsafSpectrum    = new EsafSpectrum();
    fShowerGenerator = new SlastShowerGenerator(kTRUE);
    fShowerGenerator->SetQuiet();
    fDetectorGeometry = new DetectorGeometry();
    Double_t radius   = Config::Get()->GetCF("Optics","ConicBaffle")->GetNum("ConicBaffle.fTopRadius")*mm;
    fDetectorGeometry->SetRadius(radius);
    fDetectorGeometry->SetPos(TVector3(0,0,fEusoAlt));
    fGround             = RadiativeFactory::Get()->GetGround();
    fClearSkyPropagator = new O1_ClearSkyPropagator(fGround);
    fClearSkyPropagator->CopyDetectorGeometry(fDetectorGeometry,false);
    fEnergyModule = NULL;
    fEnergy = 1.e21;
    fDebugList = new TList;
}

//_____________________________________________________________________________
 RecoShowerTrack::~RecoShowerTrack() {
    //
    // Destructor
    //
    SafeDelete(fShowerGenerator);
    SafeDelete(fDetectorGeometry);
    SafeDelete(fFluoCalculator);
    SafeDelete(fClearSkyPropagator);
    SafeDelete(fDebugList);
}
//_____________________________________________________________________________
 void RecoShowerTrack::Clear() {
    //
    //
    //
    for (UInt_t i(0); i < fSteps.size(); i++) {
        RecoShowerStep& rs = fSteps[i];    
        rs.fSpectrum->Delete(); 
    }
    fSteps.clear();
    for (Int_t i(0); i<fDebugList->GetEntries(); i++) {
         TObject* h = (TObject*)fDebugList->At(i);
         SafeDelete(h);
    }
    fDebugList->Clear();
    fDebugList = new TList;
    
}

//______________________________________________________________________________
 const RecoShowerStep& RecoShowerTrack::GetStepThetaPhi(Float_t Theta, Float_t Phi) const {
    // 
    // Return the step of the shower corresponding to the given time

    Int_t index = 0;
    Double_t mmin = -1.;
    TVector3 nFoV;

    nFoV.SetMagThetaPhi(1.,Theta,Phi);

    for (UInt_t i(0); i < fSteps.size(); i++) {
      const RecoShowerStep& rs = fSteps[i];
      EarthVector dir  = (rs.fDir).Unit();
      Double_t mag = dir*nFoV;
      if (mag > mmin) {mmin = mag; index = i;}
    }

    return (fSteps[index]);
}

//_____________________________________________________________________________
 Bool_t RecoShowerTrack::MakeTrack() {
    //
    //
    //
    Int_t progress = 0;
    Clear();
    if (fHmax == -100 || !fShowerDir.Mag() || !fEusoDir.Mag()) {
        if (fHmax == -100)     Msg(EsafMsg::Warning) << "Hmax is not setupn" << MsgDispatch;
        if (!fShowerDir.Mag()) Msg(EsafMsg::Warning) << "Shower Direction is not setupn" << MsgDispatch;
        if (!fEusoDir.Mag())   Msg(EsafMsg::Warning) << "Shower Direction is not setupn" << MsgDispatch;
                               Msg(EsafMsg::Panic)   << "Can not do a showern" << MsgDispatch;
    }

    // find 3D point of shower maximum

    Float_t AB = EarthRadius() + fEusoAlt;
    Float_t AC = EarthRadius() + fHmax;
    Float_t cs = Cos(fEusoDir.Theta());
    Float_t sn = Sin(fEusoDir.Theta());
    Float_t z = fEusoAlt - AB*cs*cs + cs*Sqrt(AC*AC - AB*AB*sn*sn);
    Float_t rho = (fEusoAlt-z)*Tan(fEusoDir.Theta());
    Float_t x   = -rho*Cos(fEusoDir.Phi());
    Float_t y   = -rho*Sin(fEusoDir.Phi());

    Float_t tMin = 0, tMax = 0;
    Float_t age, TotalYield, Attenuation;
    EarthVector MaximumPosition(x,y,z);
    fDepthMax = Atmosphere::Get()->Grammage(MaximumPosition,fShowerDir,"dir");
    EarthVector ISS(0,0,fEusoAlt);
    EarthVector fInitPos;
    // estimate for the current energy and assuming GIL parametrization the depth at the shower maximum (should be around 850 g/cm2)
    // and jump from the point of the shower maximum along the track direction for that in the atmosphere which is far by the shower
    // maximum depth
    Double_t depthToMaximum = fShowerGenerator->GetXmax();
    Int_t status = Atmosphere::Get()->InvertGrammage(MaximumPosition,fShowerDir,depthToMaximum,fInitPos,101*km);
    Msg(EsafMsg::Debug) << "<GetFirstPoint> InvertGrammage() status is " << status << MsgDispatch;

    fShowerGenerator->SetShower(fEnergy,fShowerDir.Theta(),fShowerDir.Phi(),fInitPos);
    fShowerGenerator->SetQuiet(kTRUE);
    fShowerGenerator->SetDepthStep(0.2);
    ShowerTrack *fShowerTrack = (ShowerTrack*)fShowerGenerator->Get();

    if (!fShowerTrack->Size()) return kFALSE; // do not process further if shower track object is empty

    // Define tMin and tMax of shower evolution

    {
      const ShowerStep& s = fShowerTrack->GetStep(0);
      Float_t     time = 0.5*(s.GetTimei() + s.GetTimef());
      EarthVector dir  = (ISS - 0.5*(s.GetXYZi() + s.GetXYZf()));
      tMin = (time + dir.Mag()/Clight())*1.e-3; // in microsecond
    }

    {
     const ShowerStep& s = fShowerTrack->GetStep(fShowerTrack->Size()-1);
      Float_t     time = 0.5*(s.GetTimei() + s.GetTimef());
      EarthVector dir  = (ISS - 0.5*(s.GetXYZi() + s.GetXYZf()));
      tMax = (time + dir.Mag()/Clight())*1.e-3; // in microsecond
    }

    Float_t GtuStep = 2.5;
    if (fEnergyModule) 
      GtuStep=fEnergyModule->GetRecoEvent()->GetHeader().GetGtuLength()*1.e-3;

    Int_t Nbins = (Int_t)Floor((tMax - tMin)/GtuStep);

    TH1F* h[10];
    for (Int_t i(0); i < 10; i++) {
         TString title = Form("EnergyModule_Step%d",i);
         TH1F* hh = NULL;
         if ((hh = (TH1F*)gDirectory->FindObject(title))) hh->Delete();
         h[i] = new TH1F(title,"",Nbins,0,tMax - tMin);
    }

    // fill the track, find new Hmax
    Double_t newHmax(-1), fluxMax(0);
    for (UInt_t i(0); i < fShowerTrack->Size(); i++) {
      const ShowerStep& s = fShowerTrack->GetStep(i);

      // get position and compute for it: fluo yield + attenuation + time at EUSO
      EarthVector pos  = 0.5*(s.GetXYZi() + s.GetXYZf());
      Float_t     time = 0.5*(s.GetTimei() + s.GetTimef());
      Float_t     X    = 0.5*(s.GetXi() + s.GetXf());
      EarthVector dir  = ISS - pos;
      Float_t     EusoTime = (time + dir.Mag()/Clight())*1.e-3 - tMin; // in microsecond

      if (!(i % 50)) {
	age = 0.5*(s.GetAgei() + s.GetAgef());
	TF2* EnergyDistribution = (TF2*)ShowerTrack::GetEnergyDistribution(fEnergyDistributionName);
	TF12 EnergyDistributionProj("EDS_name",EnergyDistribution,age,"X");
        Double_t temp = Atmosphere::Get()->Temperature(pos.Zv());
        TotalYield  = 0;
        Attenuation = 0;
        if (temp<=0) continue;
	TotalYield = fFluoCalculator->GetFluoYield(pos.Zv(),&EnergyDistributionProj,fEsafSpectrum);
	Attenuation=fClearSkyPropagator->GoToDetector(*fEsafSpectrum,pos);
      }

      Float_t  Length = (s.GetXYZi() - s.GetXYZf()).Mag();
      Double_t SolidAngle = 1./(4.*Pi()*dir.Mag2());
      Double_t flux  = SolidAngle*s.GetNelectrons()*Attenuation*TotalYield*Length;

      if (flux > fluxMax) {
          newHmax = pos.Zv();
          fluxMax = flux;
      } 

      h[0]->Fill(EusoTime,s.GetNelectrons());
      h[1]->Fill(EusoTime,flux);
      h[2]->Fill(EusoTime,pos.X()*flux);
      h[3]->Fill(EusoTime,pos.Y()*flux);
      h[4]->Fill(EusoTime,pos.Z()*flux);
      h[5]->Fill(EusoTime,EusoTime*flux);
      h[6]->Fill(EusoTime,TotalYield*flux);
      h[7]->Fill(EusoTime,Attenuation*flux);
      h[8]->Fill(EusoTime,age*flux);
      h[9]->Fill(EusoTime,X*flux);
      
      if (100.*(i+1)/fShowerTrack->Size() >= progress) {
	Msg(EsafMsg::Info).SetProgress(progress);
	Msg(EsafMsg::Info) << "MakeTrack():" << MsgCount;
	progress += 10;
      }
    }
    
    if (progress <= 100) Msg(EsafMsg::Info) << MsgDispatch;

    for (Int_t i = 1; i <= Nbins; i++) {
         Double_t flux   = h[1]->GetBinContent(i);
         if (!flux) continue;
         Double_t ne     = h[0]->GetBinContent(i);
	 Double_t x      = h[2]->GetBinContent(i)/flux;
         Double_t y      = h[3]->GetBinContent(i)/flux;
         Double_t z      = h[4]->GetBinContent(i)/flux;
         Double_t time   = h[5]->GetBinContent(i)/flux;
         Double_t yield  = h[6]->GetBinContent(i)/flux;
         Double_t atten  = h[7]->GetBinContent(i)/flux;
         Double_t age    = h[8]->GetBinContent(i)/flux;
	 Double_t X      = h[9]->GetBinContent(i)/flux;
         EarthVector pos(x,y,z);

	 EarthVector dir = ISS - pos;
	 TVector3 nFoV;
	 nFoV.SetMagThetaPhi(1.,dir.Theta(),dir.Phi());
	 Float_t length = 1.*Clight()*GtuStep*1.e+3/(1.+fShowerDir*nFoV);

	 RecoShowerStep rs;
         rs.fEusoTime    = time;
         rs.fPos         = pos;
         rs.fDir         = dir;
         rs.fFluoYield   = yield;
         rs.fAttenuation = atten;
         rs.fNe          = ne;
         rs.fFlux        = flux;
         rs.fLength      = length;
	 rs.fX           = X*cm2/g;

         TF2 *EnergyDistribution = (TF2*)ShowerTrack::GetEnergyDistribution(fEnergyDistributionName);
         TF12 EnergyDistributionProj("EDS_name",EnergyDistribution,age,"X");
         Double_t temp = Atmosphere::Get()->Temperature(pos.Zv());
         if (temp<=0) continue;
         fFluoCalculator->GetFluoYield(pos.Zv(),&EnergyDistributionProj,
				       fEsafSpectrum);
         fClearSkyPropagator->GoToDetector(*fEsafSpectrum,pos.Zv());

	 rs.fSpectrum = new TH1F(Form("RecoShowerTrackSpectrum%d",i),"",
				 100,300*nm,400*nm);

	 for (Int_t nt = 0; nt < 1000; nt++) 
	   rs.fSpectrum->Fill(fEsafSpectrum->GetLambda());

         Add(rs);
    }

    for (Int_t i(0); i < 10; i++) h[i]->Delete();

    fShowerTrack->Reset();
    fShowerGenerator->Reset();

    Msg(EsafMsg::Debug) << "Hmax set up " << fHmax/km << " Hmax found " << newHmax/km << MsgDispatch;
    fHmax = newHmax;

    return kTRUE;
}

//_____________________________________________________________________________
 void RecoShowerTrack::DoDebugHistos() {
    //
    //
    //
    Float_t tMin, tMax;

    // Set tMin and tMax

    {
      RecoShowerStep& rs = fSteps[0];
      tMin = rs.fEusoTime;
    }

    {
      RecoShowerStep& rs = fSteps[fSteps.size()-1];
      tMax = rs.fEusoTime;
    }
    
    TH1* h[12];
    for (Int_t i(0); i < 11; i++) {
         TString title = Form("debug%d",i);
         TProfile* hh = NULL;
         if (( hh = (TProfile*)gDirectory->FindObject(title))) hh->Delete();
	 if (i >= 9)  h[i] = new TProfile(title,"",150,0,30);
         else         h[i] = new TProfile(title,"",150,tMin,tMax);
         fDebugList->Add(h[i]);
    }
    h[11] = new TH1F("debug11","",150,0,30);
    fDebugList->Add(h[11]);

    TPolyMarker3D *track = new TPolyMarker3D;
    fDebugList->Add(track);

    Double_t DetectorRadius = 1250*mm;
    Double_t Area = TMath::Pi()*DetectorRadius*DetectorRadius;
    EEvent  *SimuEvent  = fEnergyModule->GetRecoEvent()->GetSimuEvent();
    Double_t EnergyScale=1;
    if (SimuEvent)
        EnergyScale = SimuEvent->GetTruth()->GetTrueEnergy()/(fEnergy*1.e-6);

    Int_t points(0);
    fXmin=fYmin=fZmin=1.e10; 
    fXmax=fYmax=fZmax=-1.e10; 

    for (UInt_t i(0); i < fSteps.size(); i++) {
        RecoShowerStep& rs = fSteps[i];
        h[0]->Fill(rs.fEusoTime,rs.fNe);
        h[1]->Fill(rs.fEusoTime,rs.fPos.X()/km);
        h[2]->Fill(rs.fEusoTime,rs.fPos.Y()/km);
        h[3]->Fill(rs.fEusoTime,rs.fPos.Z()/km);
        h[4]->Fill(rs.fEusoTime,rs.fFluoYield*m);
        h[5]->Fill(rs.fEusoTime,rs.fAttenuation);
        h[6]->Fill(rs.fEusoTime,rs.fFlux);
        h[7]->Fill(rs.fEusoTime,rs.fLength/km);
        h[8]->Fill(rs.fEusoTime,rs.fX);

        h[9]->Fill(rs.fPos.Zv()/km,rs.fFluoYield*m);
        h[10]->Fill(rs.fPos.Zv()/km,rs.fAttenuation);
        Double_t fluoEP = rs.fFlux*Area*EnergyScale*Cos(rs.fDir.Theta());
        Int_t    nfluoEP = (Int_t)fluoEP;
        h[11]->Fill(rs.fPos.Zv()/km,fluoEP);
        if (nfluoEP) for (Int_t j(0); j<nfluoEP; j++) track->SetPoint(points++,rs.fPos.X()/km,rs.fPos.Y()/km,rs.fPos.Z()/km);
        if (fXmin > rs.fPos.X()/km) fXmin = rs.fPos.X()/km;
        if (fYmin > rs.fPos.Y()/km) fYmin = rs.fPos.Y()/km;
        if (fZmin > rs.fPos.Z()/km) fZmin = rs.fPos.Z()/km;
        if (fXmax < rs.fPos.X()/km) fXmax = rs.fPos.X()/km;
        if (fYmax < rs.fPos.Y()/km) fYmax = rs.fPos.Y()/km;
        if (fZmax < rs.fPos.Z()/km) fZmax = rs.fPos.Z()/km;

    }

}

//_____________________________________________________________________________
 void RecoShowerTrack::Debug(TCanvas *c, Int_t id, Option_t *opt) {
    //
    //
    //
    if (!c) {
        Warning("RecoShowerTrack::Debug","Please specify the pad where I have to draw");
        return;
    }
    
    if (id < 0 || id > 11) {
        Warning("RecoShowerTrack::Debug","Please specify id between 0 and 11");
        return;
    }
    
    TH1* h = (TH1*)fDebugList->At(id);
    h->Draw(opt);
}



ROOT page - Class index - Class Hierarchy - Top of the page

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.