diff --git a/.gitignore b/.gitignore old mode 100644 new mode 100755 diff --git a/CMakeLists.txt b/CMakeLists.txt index 54a2592..364584b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,6 +12,9 @@ option (BUILD_DOC "Build documentation using Doxygen" OFF) option (BUILD_ONLY_DOC "Build only the documentation" OFF) +option (WITH_GENIE "Build Genie generator interface" OFF) +option (WITH_GENFIT "Build GenFit generator interface" OFF) + if(BUILD_DOC) find_package(Doxygen) if (DOXYGEN_FOUND) @@ -147,7 +150,7 @@ find_package(Geant4) find_package(GEANT4) find_package(GEANT4DATA) find_package(GEANT4VMC) -#find_package(CLHEP) +find_package(CLHEP) find_package(HEPMC) Set(Boost_NO_SYSTEM_PATHS TRUE) @@ -194,8 +197,6 @@ SET(FAIRROOT_LIBRARY_PROPERTIES ${FAIRROOT_LIBRARY_PROPERTIES} SET(_LIBDIR ${CMAKE_BINARY_DIR}/lib) SET(LD_LIBRARY_PATH ${_LIBDIR} ${LD_LIBRARY_PATH}) - - # Check if the compiler support specific C++11 features # Up to now this is only a check since the code does not use # any of the features of the new standard @@ -205,24 +206,95 @@ IF(HAS_CXX11_SHAREDPOINTER) Add_Definitions(-DHAS_SHAREDPOINTER) ENDIF(HAS_CXX11_SHAREDPOINTER) +if(WITH_GENIE) + message("Searching for Genie") + + if(NOT DEFINED ENV{GENIE}) + message(FATAL_ERROR "GENIE environment variable not found") + endif() + set(GENIE_DIR $ENV{GENIE}) + + if(NOT EXISTS ${GENIE_DIR}/lib/libGenie.so) + message(FATAL_ERROR ${GENIE_DIR}/lib/libGenie.so" not found.") + endif() + set(GENIE_LIB_DIR ${GENIE_DIR}/lib/) + + if(NOT EXISTS ${GENIE_DIR}/src) + message(FATAL_ERROR ${GENIE_DIR}/src" not found.") + endif() + set(GENIE_INC_DIR ${GENIE_DIR}/src/) + + list(APPEND LD_LIBRARY_PATH ${GENIE_LIB_DIR}) + + #Definition for rootcling + list(APPEND DEFINITIONS -DWITH_GENIE) + + #Definition for gcc + add_definitions(-DWITH_GENIE) +endif(WITH_GENIE) + + +if(WITH_GENFIT) + message("Searching for Genfit") + + if(NOT DEFINED ENV{GENFIT_HOME}) + message(FATAL_ERROR "GENFIT_HOME environment variable not found") + endif() + + if(NOT DEFINED ENV{GENFIT_BUILD}) + message(FATAL_ERROR "GENFIT_BUILD environment variable not found") + endif() + + set(GENFIT_LIBRARY $ENV{GENFIT_BUILD}) + set(GENFIT_INCLUDE $ENV{GENFIT_HOME}) + + list(APPEND LD_LIBRARY_PATH ${GENFIT_LIBRARY}) + list(APPEND LD_LIBRARY_PATH ${GENFIT_LIBRARY}/lib) + + message("GENFIT environment variables are set") + + + if(NOT DEFINED ENV{PATHFINDER_HOME}) + message(FATAL_ERROR "PATHFINDER_HOME environment variable not found") + endif() + + if(NOT DEFINED ENV{PATHFINDER_BUILD}) + message(FATAL_ERROR "PATHFINDER_BUILD environment variable not found") + endif() + + set(PATHFINDER_LIB $ENV{PATHFINDER_BUILD}/lib) + set(PATHFINDER_INC $ENV{PATHFINDER_HOME}/include) + + message("PATHFINDER environment variables are set") + + + #Definition for rootcling + list(APPEND DEFINITIONS -DWITH_GENFIT) + + #Definition for gcc + add_definitions(-DWITH_GENFIT) +endif(WITH_GENFIT) + # Recurse into the given subdirectories. This does not actually # cause another cmake executable to run. The same process will walk through # the project's entire directory structure. add_subdirectory (EsbData) add_subdirectory (EsbGeometry) +add_subdirectory (EsbGenerators) add_subdirectory (EsbDigitizer) add_subdirectory (EsbTools) -#add_subdirectory (EsbGenerators) -#add_subdirectory (esb) -#add_subdirectory (passive) -#add_subdirectory (field) + +if(WITH_GENFIT) + message("Source diretcory is ${PROJECT_SOURCE_DIR}") + add_subdirectory (EsbReconstruction) +endif(WITH_GENFIT) SET(ROOT_INCLUDE_PATH "${ROOT_INCLUDE_PATH}:${CMAKE_SOURCE_DIR}") SET(GEOPATH "${CMAKE_SOURCE_DIR}/EsbGeometry") -WRITE_CONFIG_FILE(config.sh) +WRITE_CONFIG_FILE(fairroot_config.sh) -configure_file(${CMAKE_SOURCE_DIR}/CTestCustom.cmake - ${CMAKE_BINARY_DIR}/CTestCustom.cmake +configure_file(${CMAKE_SOURCE_DIR}/config.sh.in + ${CMAKE_BINARY_DIR}/config.sh ) diff --git a/Doxyfile.in b/Doxyfile.in index 6257ba3..50fd42f 100644 --- a/Doxyfile.in +++ b/Doxyfile.in @@ -32,7 +32,7 @@ DOXYFILE_ENCODING = UTF-8 # title of most generated pages and in a few other places. # The default value is: My Project. -PROJECT_NAME = "EsbSoft" +PROJECT_NAME = "EsbRoot" # The PROJECT_NUMBER tag can be used to enter a project or revision number. This # could be handy for archiving the generated documentation or if some version @@ -152,7 +152,7 @@ FULL_PATH_NAMES = YES # will be relative from the directory where doxygen is started. # This tag requires that the tag FULL_PATH_NAMES is set to YES. -STRIP_FROM_PATH = +STRIP_FROM_PATH = @CMAKE_SOURCE_DIR@ # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the # path mentioned in the documentation of a class, which tells the reader which @@ -161,7 +161,7 @@ STRIP_FROM_PATH = # specify the list of include paths that are normally passed to the compiler # using the -I flag. -STRIP_FROM_INC_PATH = +STRIP_FROM_INC_PATH = @CMAKE_SOURCE_DIR@ # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but # less readable) file names. This can be useful is your file systems doesn't @@ -422,7 +422,7 @@ EXTRACT_ALL = YES # be included in the documentation. # The default value is: NO. -EXTRACT_PRIVATE = NO +EXTRACT_PRIVATE = YES # If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal # scope will be included in the documentation. diff --git a/EsbData/CMakeLists.txt b/EsbData/CMakeLists.txt index afec6cd..b2fb234 100644 --- a/EsbData/CMakeLists.txt +++ b/EsbData/CMakeLists.txt @@ -1,18 +1,22 @@ # Create a library called "libEsbData" set(INCLUDE_DIRECTORIES -${BASE_INCLUDE_DIRECTORIES} -#${CMAKE_SOURCE_DIR}/EsbData -${CMAKE_SOURCE_DIR} + ${BASE_INCLUDE_DIRECTORIES} + #${CMAKE_SOURCE_DIR}/EsbData + ${CMAKE_SOURCE_DIR} + ${CLHEP_INCLUDE_DIR} + $ENV{GENIE}/src ) include_directories( ${INCLUDE_DIRECTORIES}) include_directories(${SYSTEM_INCLUDE_DIRECTORIES}) set(LINK_DIRECTORIES -${ROOT_LIBRARY_DIR} -${FAIRROOT_LIBRARY_DIR} -#${CMAKE_SOURCE_DIR}/EsbData + ${ROOT_LIBRARY_DIR} + ${FAIRROOT_LIBRARY_DIR} + #${CMAKE_SOURCE_DIR}/EsbData + ${CLHEP_LIB_DIR} + $ENV{GENIE}/lib ) link_directories( ${LINK_DIRECTORIES}) @@ -22,6 +26,8 @@ set(SRCS MCTrack.cxx WCDetectorPoint.cxx PMTubeHit.cxx + EsbSuperFGD/FgdDetectorPoint.cxx + EsbSuperFGD/FgdHit.cxx ) Set(HEADERS @@ -29,6 +35,8 @@ Set(HEADERS ${CMAKE_SOURCE_DIR}/EsbData/MCTrack.h ${CMAKE_SOURCE_DIR}/EsbData/WCDetectorPoint.h ${CMAKE_SOURCE_DIR}/EsbData/PMTubeHit.h + ${CMAKE_SOURCE_DIR}/EsbData/EsbSuperFGD/FgdDetectorPoint.h + ${CMAKE_SOURCE_DIR}/EsbData/EsbSuperFGD/FgdHit.h ) Set(LINKDEF ${CMAKE_SOURCE_DIR}/EsbData/DataLinkDef.h) diff --git a/EsbData/DataLinkDef.h b/EsbData/DataLinkDef.h index dc48266..6dc4105 100755 --- a/EsbData/DataLinkDef.h +++ b/EsbData/DataLinkDef.h @@ -15,11 +15,15 @@ #pragma link C++ nestedtypedef; #pragma link C++ namespace esbroot; +#pragma link C++ namespace esbroot::data+; +#pragma link C++ namespace esbroot::data::superfgd+; #pragma link C++ class esbroot::data::Stack+; #pragma link C++ class esbroot::data::MCTrack+; #pragma link C++ class esbroot::data::WCDetectorPoint+; #pragma link C++ class esbroot::data::PMTubeHit+; +#pragma link C++ class esbroot::data::superfgd::FgdDetectorPoint+; +#pragma link C++ class esbroot::data::superfgd::FgdHit+; #endif diff --git a/EsbData/EsbSuperFGD/FgdDetectorPoint.cxx b/EsbData/EsbSuperFGD/FgdDetectorPoint.cxx new file mode 100644 index 0000000..d74d453 --- /dev/null +++ b/EsbData/EsbSuperFGD/FgdDetectorPoint.cxx @@ -0,0 +1,76 @@ +/******************************************************************************** + * Copyright (C) 2014 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH * + * * + * This software is distributed under the terms of the * + * GNU Lesser General Public Licence (LGPL) version 3, * + * copied verbatim in the file "LICENSE" * + ********************************************************************************/ +#include "EsbData/EsbSuperFGD/FgdDetectorPoint.h" + +#include +using std::cout; +using std::endl; + +namespace esbroot { + +namespace data { + +namespace superfgd { + +// ----- Default constructor ------------------------------------------- +FgdDetectorPoint::FgdDetectorPoint() + : FairMCPoint() +{ +} +// ------------------------------------------------------------------------- + +// ----- Standard constructor ------------------------------------------ +FgdDetectorPoint::FgdDetectorPoint(Int_t trackID, Int_t detID, + TVector3 detectorPos, + TVector3 pos, TVector3 posExit, TVector3 mom, TVector3 momExit, + Double_t tof, Double_t edep, Double_t trackLenght, + Int_t pdg , Double_t trackLenghtFromOrigin) + : FairMCPoint(trackID, detID, pos, mom, tof, 0 , edep /* eLoss*/) + ,fposExit(posExit), fdetectorPos(detectorPos), ftrackLenght(trackLenght) + ,fpdg(pdg), fmomExit(momExit), ftrackLenghtFromOrigin(trackLenghtFromOrigin) +{ + SetPosition(pos); +} +// ------------------------------------------------------------------------- + +// ----- Destructor ---------------------------------------------------- +FgdDetectorPoint::~FgdDetectorPoint() { } +// ------------------------------------------------------------------------- + +Int_t FgdDetectorPoint::Compare(const TObject *obj) const { + + FgdDetectorPoint* photonObj = (FgdDetectorPoint*)obj; + if(photonObj == 0) + return 0; + + if(fZ > photonObj->GetZ()) + return 1; + else if(fZ < photonObj->GetZ()) + return -1; + else + return 0; +} + +// ----- Public method Print ------------------------------------------- +void FgdDetectorPoint::Print(const Option_t* /*opt*/) const +{ + cout << "-I- FgdDetectorPoint: FgdDetector point for track " << fTrackID + << " in detector " << fDetectorID << endl; + cout << " Position (" << fX << ", " << fY << ", " << fZ + << ") cm" << endl; + cout << " Momentum (" << fPx << ", " << fPy << ", " << fPz + << ") GeV" << endl; + cout << " Time " << fTime << " ns" << endl; +} +// ------------------------------------------------------------------------- + +}//namespace superfgd + +}//namespace data + +}//namespace esbroot diff --git a/EsbData/EsbSuperFGD/FgdDetectorPoint.h b/EsbData/EsbSuperFGD/FgdDetectorPoint.h new file mode 100644 index 0000000..d89415b --- /dev/null +++ b/EsbData/EsbSuperFGD/FgdDetectorPoint.h @@ -0,0 +1,101 @@ +/******************************************************************************** + * Copyright (C) 2014 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH * + * * + * This software is distributed under the terms of the * + * GNU Lesser General Public Licence (LGPL) version 3, * + * copied verbatim in the file "LICENSE" * + ********************************************************************************/ +#ifndef ESBROOT_FGDDETECTOR_POINT_H +#define ESBROOT_FGDDETECTOR_POINT_H 1 + + +#include "FairMCPoint.h" + +#include "TObject.h" +#include "TVector3.h" + +namespace esbroot { + +namespace data { + +namespace superfgd { + +class FgdDetectorPoint : public FairMCPoint +{ + + public: + + /** Default constructor **/ + FgdDetectorPoint(); + + + /** Constructor with arguments + *@param trackID Index of MCTrack + *@param detID Detector ID + *@param detectorPos Coordinates of the detector [cm] + *@param pos Coordinates at entrance to active volume [cm] + *@param posExit Coordinates at exit of active volume [cm] + *@param mom Momentum of track at entrance [GeV] + *@param momExit Momentum of track at exit [GeV] + *@param tof Time since event start [ns] + *@param edep total energy loss [GeV] + *@param trackLenght tracklenght till the active volume + *@param pdg pdg code of particle + *@param trackLenghtFromOrigin tracklength from origin of track + **/ + FgdDetectorPoint(Int_t trackID, Int_t detID, TVector3 detectorPos, TVector3 pos, TVector3 posExit, TVector3 mom + , TVector3 momExit, Double_t tof, Double_t edep, Double_t trackLenght, Int_t pdg + , Double_t trackLenghtFromOrigin); + + /** Destructor **/ + virtual ~FgdDetectorPoint(); + + + Bool_t IsSortable() const { return kTRUE; } + + /// To be able to sort the photon hits according to their z position + Int_t Compare(const TObject *obj) const; + + /// Get the total momentum to easily calculate the wavelength + Double_t GetP() const { return TMath::Sqrt(fPx*fPx + fPy*fPy + fPz*fPz);} + + // Get a copy of the exit position + TVector3 GetposExit(){return fposExit;}; + + TVector3 GetMomExit(){return fmomExit;}; + + // Get the detector position + TVector3 GetDetectorpos(){return fdetectorPos;}; + + Int_t GetPdg(){return fpdg;} + + // Get the track lenght + Double_t GetTrackLenght(){return ftrackLenght;} + + Double_t GetTrackLengthOrigin(){return ftrackLenghtFromOrigin;} + + /** Output to screen **/ + virtual void Print(const Option_t* opt) const; + + private: + /** Copy constructor **/ + FgdDetectorPoint(const FgdDetectorPoint& point); + FgdDetectorPoint operator=(const FgdDetectorPoint& point); + + TVector3 fposExit; // Member to hold the position of the particle when it exits the sensitive volume + TVector3 fdetectorPos; + TVector3 fmomExit; + Double_t ftrackLenght; + Double_t ftrackLenghtFromOrigin; + Int_t fpdg; + + ClassDef(FgdDetectorPoint,2) +}; + +} //namespace superfgd + +} //namespace data + +} //namespace esbroot + +#endif diff --git a/EsbData/EsbSuperFGD/FgdHit.cxx b/EsbData/EsbSuperFGD/FgdHit.cxx new file mode 100644 index 0000000..cb154c9 --- /dev/null +++ b/EsbData/EsbSuperFGD/FgdHit.cxx @@ -0,0 +1,62 @@ +/******************************************************************************** + * Copyright (C) 2014 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH * + * * + * This software is distributed under the terms of the * + * GNU Lesser General Public Licence (LGPL) version 3, * + * copied verbatim in the file "LICENSE" * + ********************************************************************************/ +#include "EsbData/EsbSuperFGD/FgdHit.h" + +#include + +#include +using std::cout; +using std::endl; + +namespace esbroot { +namespace data { +namespace superfgd { + +// ----- Default constructor ------------------------------------------- +FgdHit::FgdHit() + : FairHit() +{ +} +// ------------------------------------------------------------------------- + +// ----- Standard constructor ------------------------------------------ +FgdHit::FgdHit(Double_t x, Double_t y, Double_t z, TVector3 mppcLoc + , TVector3 photoE, TVector3 dpos, Double_t time, TVector3 mom, TVector3 momExit + , Double_t trackLength, Double_t trackLengthOrigin , TVector3 photoE_direction1, TVector3 distance_to_mppcLoc1 + , TVector3 photoE_direction2, TVector3 distance_to_mppcLoc2 + , Int_t pdg, Int_t trackId, Double_t edep) + : FairHit(),fmppcLoc(mppcLoc),fphotoE(photoE), fdpos(dpos), ftime(time), fmom(mom) + , fphotoE_dist1(photoE_direction1), fmppcLoc_dist1(distance_to_mppcLoc1) + , fphotoE_dist2(photoE_direction2), fmppcLoc_dist2(distance_to_mppcLoc2) + , fpdg(pdg), ftrackId(trackId), fmomExit(momExit), ftrackLength(trackLength) + , fedep(edep), ftrackLengthOrigin(trackLengthOrigin) +{ + SetX(x); + SetY(y); + SetZ(z); +} +// ------------------------------------------------------------------------- + +// ----- Destructor ---------------------------------------------------- +FgdHit::~FgdHit() { } +// ------------------------------------------------------------------------- + +// ----- Public method Print ------------------------------------------- +void FgdHit::Print(const Option_t* /*opt*/) const +{ + cout << "-I- FgdHit: " << " [cm] Position (" << fX << ", " << fY << ", " << fZ + << ") cm" << endl; + cout << "Mppc: " << "x: " << fmppcLoc.X() << " y: " << fmppcLoc.Y() << " z: " << fmppcLoc.Z() << endl; + cout << "Total photons in each direction: " << " x: " << fphotoE.X() << " y: " << fphotoE.Y() + << " z: " << fphotoE.Z() << endl; +} +// ------------------------------------------------------------------------- + +} +} +} diff --git a/EsbData/EsbSuperFGD/FgdHit.h b/EsbData/EsbSuperFGD/FgdHit.h new file mode 100644 index 0000000..bb18bc2 --- /dev/null +++ b/EsbData/EsbSuperFGD/FgdHit.h @@ -0,0 +1,122 @@ +/******************************************************************************** + * Copyright (C) 2014 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH * + * * + * This software is distributed under the terms of the * + * GNU Lesser General Public Licence (LGPL) version 3, * + * copied verbatim in the file "LICENSE" * + ********************************************************************************/ + + +#ifndef ESBROOT_ESBDATA_SUPERFGD_FGD_HIT_H +#define ESBROOT_ESBDATA_SUPERFGD_FGD_HIT_H + +#include + +namespace esbroot { +namespace data { +namespace superfgd { + +/// \class FgdHit +/// This is the definition of the Fgd digit class. +/// The data is transformed from energy deposited inside a cube into +/// number of photons generated +class FgdHit : public FairHit +{ + public: + + /** Default constructor **/ + FgdHit(); + + /** Constructor with arguments + *@param x X coordinates of cube in absolute coordinates + *@param y Y coordinates of cube in absolute coordinates + *@param z Z coordinates of cube in absolute coordinates + *@param mppcLoc bin locations for the mppcs + *@param photoE number of generated photons along each direction + *@param dpos coordinate of the hit relative to the detector + *@param time time of entering of the particle inside the cube + *@param mom particle momentum + *@param momExit particle exit momentum + *@param trackLength tracklength till this moment in steps + *@param trackLengthOrigin tracklength till this moment from origin of track + *@param photoE_direction1 generated photons on +x,+y,+z direction + *@param distance_to_mppcLoc1 distance to mppc to +x,+y,+z direction + *@param photoE_direction2 generated photons on -x,-y, z direction + *@param distance_to_mppcLoc1 distance to mppc to -x,-y,-z direction + *@param pdg pdg codes of particles + *@param trackId trackId + *@param edep energy loss + **/ + FgdHit(Double_t x, Double_t y, Double_t z, TVector3 mppcLoc + , TVector3 photoE, TVector3 dpos, Double_t time, TVector3 mom, TVector3 momExit + , Double_t trackLength, Double_t trackLengthOrigin , TVector3 photoE_direction1, TVector3 distance_to_mppcLoc1 + , TVector3 photoE_direction2, TVector3 distance_to_mppcLoc2 + , Int_t pdg, Int_t trackId, Double_t edep); + + /** Destructor **/ + virtual ~FgdHit(); + + /** Accessors **/ + TVector3 GetMppcLoc(){return fmppcLoc;} + TVector3 GetPhotoE(){return fphotoE;} + TVector3 GetDpos(){return fdpos;} + Double_t GetTime(){return ftime;} + TVector3 GetMomentum(){return fmom;} + TVector3 GetExitMomentum(){return fmomExit;} + + TVector3 GetPhotoDist1(){return fphotoE_dist1;} + TVector3 GetMppcDist1(){return fmppcLoc_dist1;} + TVector3 GetPhotoDist2(){return fphotoE_dist2;} + TVector3 GetMppcDist2(){return fmppcLoc_dist2;} + Int_t GetPgd(){return fpdg;} + Int_t GetTrackId(){return ftrackId;} + Double_t GetTrackLenght(){return ftrackLength;} + Double_t GetTrackLengthOrigin(){return ftrackLengthOrigin;} + Double_t GetEdep() {return fedep;} + + /** Modifiers **/ + void SetMppcLoc(TVector3 mppcLoc){fmppcLoc = mppcLoc;} + void SetPhotoE(TVector3 p){fphotoE = p;} + void SetDpos(TVector3 dpos){fdpos = dpos;} + void SetTime(Double_t time){ftime=time;} + void SetMomentum(TVector3 m){fmom = m;} + + void SetPhotoDist1(TVector3 photo1){fphotoE_dist1 = photo1;} + void SetMppcDist1(TVector3 mppc1){fmppcLoc_dist1 = mppc1;} + void SetPhotoDist2(TVector3 photo2){fphotoE_dist2 = photo2;} + void SetMppcDist2(TVector3 mppc2){fmppcLoc_dist2 = mppc2;} + void SetPgd(Int_t pdg){fpdg = pdg;} + void SetTrackId(Int_t trackId){ftrackId = trackId;} + void SetEdep(Double_t edep){fedep = edep;} + + /** Output to screen **/ + virtual void Print(const Option_t* opt) const; + + private: + /** Private variables to hold the position and number of generated photons in the cube **/ + TVector3 fmppcLoc; + TVector3 fphotoE; + TVector3 fdpos; + Double_t ftime; + TVector3 fmom; + TVector3 fmomExit; + Double_t ftrackLength; + Double_t ftrackLengthOrigin; + + TVector3 fphotoE_dist1; + TVector3 fmppcLoc_dist1; + TVector3 fphotoE_dist2; + TVector3 fmppcLoc_dist2; + + Int_t fpdg; + Int_t ftrackId; + Double_t fedep; + + ClassDef(FgdHit, 2); +}; + +} +} +} + +#endif // ESBROOT_ESBDATA_SUPERFGD_FGD_HIT_H \ No newline at end of file diff --git a/EsbData/PMTubeHit.cxx b/EsbData/PMTubeHit.cxx index 0df518e..e96f003 100644 --- a/EsbData/PMTubeHit.cxx +++ b/EsbData/PMTubeHit.cxx @@ -16,6 +16,9 @@ using std::endl; namespace esbroot { namespace data { +// Sortoption = 0 (time, default), 1 (charge) +Int_t PMTubeHit::sortOption = 0; + // ----- Default constructor ------------------------------------------- PMTubeHit::PMTubeHit() : FairHit(), @@ -48,6 +51,32 @@ PMTubeHit::PMTubeHit(Double_t x, Double_t y, Double_t z, Double_t r, PMTubeHit::~PMTubeHit() { } // ------------------------------------------------------------------------- +// ------------------------------------------------------------------------- +Int_t PMTubeHit::Compare(const TObject *obj) const { + + PMTubeHit* pmt_obj = (PMTubeHit*)obj; + if(pmt_obj == 0) + return 0; + + if(sortOption == 0) { + + if(fTime > pmt_obj->GetTime()) + return 1; + else if(fTime < pmt_obj->GetTime()) + return -1; + else + return 0; + } else { + + if(fCharge < pmt_obj->GetCharge()) + return 1; + else if(fCharge > pmt_obj->GetCharge()) + return -1; + else + return 0; + } +} + // ----- Public method Print ------------------------------------------- void PMTubeHit::Print(const Option_t* /*opt*/) const { diff --git a/EsbData/PMTubeHit.h b/EsbData/PMTubeHit.h index e12de24..01dbfba 100644 --- a/EsbData/PMTubeHit.h +++ b/EsbData/PMTubeHit.h @@ -26,6 +26,9 @@ namespace data { class PMTubeHit : public FairHit { public: + + /** @param sortOption 0 (time, default), 1 (charge) **/ + static Int_t sortOption; /** Default constructor **/ PMTubeHit(); @@ -56,6 +59,12 @@ class PMTubeHit : public FairHit /** Output to screen **/ virtual void Print(const Option_t* opt) const; + + /// Make ROOT aware that the class is sortable + Bool_t IsSortable() const { return kTRUE; } + + /// To be able to sort the PMT hits according to their time or charge + Int_t Compare(const TObject *obj) const; protected: diff --git a/EsbData/WCDetectorPoint.h b/EsbData/WCDetectorPoint.h index da92b9f..e76b7eb 100755 --- a/EsbData/WCDetectorPoint.h +++ b/EsbData/WCDetectorPoint.h @@ -46,6 +46,9 @@ class WCDetectorPoint : public FairMCPoint /// To be able to sort the photon hits according to their z position Int_t Compare(const TObject *obj) const; + /// Get the total momentum to easily calculate the wavelength + Double_t GetP() const { return TMath::Sqrt(fPx*fPx + fPy*fPy + fPz*fPz);} + /** Output to screen **/ virtual void Print(const Option_t* opt) const; diff --git a/EsbDigitizer/CMakeLists.txt b/EsbDigitizer/CMakeLists.txt index 6fc2291..caf316c 100644 --- a/EsbDigitizer/CMakeLists.txt +++ b/EsbDigitizer/CMakeLists.txt @@ -1,28 +1,34 @@ # Create a library called "libEsbDigitizer" set(INCLUDE_DIRECTORIES -${BASE_INCLUDE_DIRECTORIES} -#${CMAKE_SOURCE_DIR}/EsbDigitizer -${CMAKE_SOURCE_DIR} + ${BASE_INCLUDE_DIRECTORIES} + #${CMAKE_SOURCE_DIR}/EsbDigitizer + ${CMAKE_SOURCE_DIR} + ${CLHEP_INCLUDE_DIR} ) include_directories( ${INCLUDE_DIRECTORIES}) include_directories(${SYSTEM_INCLUDE_DIRECTORIES}) set(LINK_DIRECTORIES -${ROOT_LIBRARY_DIR} -${FAIRROOT_LIBRARY_DIR} -#${CMAKE_SOURCE_DIR}/EsbDigitizer + ${ROOT_LIBRARY_DIR} + ${FAIRROOT_LIBRARY_DIR} + #${CMAKE_SOURCE_DIR}/EsbDigitizer + ${CLHEP_LIB_DIR} ) link_directories( ${LINK_DIRECTORIES}) set(SRCS WCDigitizer.cxx + EsbSuperFGD/FgdDigitizer.cxx + EsbSuperFGD/FgdMppcDisplay.cxx ) Set(HEADERS ${CMAKE_SOURCE_DIR}/EsbDigitizer/WCDigitizer.h + ${CMAKE_SOURCE_DIR}/EsbDigitizer/EsbSuperFGD/FgdDigitizer.h + ${CMAKE_SOURCE_DIR}/EsbDigitizer/EsbSuperFGD/FgdMppcDisplay.h ) Set(LINKDEF ${CMAKE_SOURCE_DIR}/EsbDigitizer/DigitizerLinkDef.h) diff --git a/EsbDigitizer/DigitizerLinkDef.h b/EsbDigitizer/DigitizerLinkDef.h index 39bf4ad..99e4d11 100755 --- a/EsbDigitizer/DigitizerLinkDef.h +++ b/EsbDigitizer/DigitizerLinkDef.h @@ -15,8 +15,12 @@ #pragma link C++ nestedtypedef; #pragma link C++ namespace esbroot; +#pragma link C++ namespace esbroot::digitizer; +#pragma link C++ namespace esbroot::digitizer::superfgd; #pragma link C++ class esbroot::digitizer::WCDigitizer+; +#pragma link C++ class esbroot::digitizer::superfgd::FgdDigitizer+; +#pragma link C++ class esbroot::digitizer::superfgd::FgdMppcDisplay+; #endif diff --git a/EsbDigitizer/EsbSuperFGD/FgdDigitizer.cxx b/EsbDigitizer/EsbSuperFGD/FgdDigitizer.cxx new file mode 100644 index 0000000..085553b --- /dev/null +++ b/EsbDigitizer/EsbSuperFGD/FgdDigitizer.cxx @@ -0,0 +1,349 @@ +#include "EsbDigitizer/EsbSuperFGD/FgdDigitizer.h" +#include "EsbData/EsbSuperFGD/FgdDetectorPoint.h" + +#include +#include +#include + +#include +#include "FairLogger.h" + +#include "EsbData/WCDetectorPoint.h" +#include "EsbGeometry/PMTube.h" +#include "EsbData/PMTubeHit.h" + +#include +using std::cout; +using std::endl; + +namespace esbroot { +namespace digitizer { +namespace superfgd { + +// ----- Default constructor ------------------------------------------- +FgdDigitizer::FgdDigitizer() : + FairTask(), fX(0), fY(0), fZ(0), fdPoints(nullptr), fHitArray(nullptr) +{ +} +// ------------------------------------------------------------------------- + +// ----- Constructor ------------------------------------------- +FgdDigitizer::FgdDigitizer(const char* name + ,const char* geoConfigFile + ,double x, double y, double z + , Int_t verbose) : + FairTask(name, verbose), fX(x), fY(y), fZ(z), + fdPoints(nullptr), fHitArray(nullptr) +{ + fParams.LoadPartParams(geoConfigFile); +} +// ------------------------------------------------------------------------- + + + +// ----- Destructor ---------------------------------------------------- +FgdDigitizer::~FgdDigitizer() +{ + if(fHitArray) { + fHitArray->Delete(); + delete fHitArray; + } +} +// ------------------------------------------------------------------------- + + + +// ----- Public method Init -------------------------------------------- +InitStatus FgdDigitizer::Init() +{ + flunit = fParams.GetLenghtUnit(); // [cm] + + f_step_X = fParams.ParamAsDouble(esbroot::geometry::superfgd::DP::length_X) * flunit; + f_step_Y = fParams.ParamAsDouble(esbroot::geometry::superfgd::DP::length_Y) * flunit; + f_step_Z = fParams.ParamAsDouble(esbroot::geometry::superfgd::DP::length_Z) * flunit; + + f_bin_X = fParams.ParamAsInt(esbroot::geometry::superfgd::DP::number_cubes_X); + f_bin_Y = fParams.ParamAsInt(esbroot::geometry::superfgd::DP::number_cubes_Y); + f_bin_Z = fParams.ParamAsInt(esbroot::geometry::superfgd::DP::number_cubes_Z); + + f_total_X = f_step_X * f_bin_X; + f_total_Y = f_step_Y * f_bin_Y; + f_total_Z = f_step_Z * f_bin_Z; + + // Get RootManager + FairRootManager* manager = FairRootManager::Instance(); + if ( !manager ) { + LOG(error) << "-E- FgdDigitizer::Init: " << "FairRootManager not instantised!"; + return kFATAL; + } + + fdPoints = (TClonesArray*) manager->GetObject(geometry::superfgd::DP::FGD_BRANCH.c_str()); + if (!fdPoints) + { + LOG(fatal) << "Exec", "No fgd points array"; + return kFATAL; + } + + // Create and register output array + fHitArray = new TClonesArray(data::superfgd::FgdHit::Class(), 1000); + manager->Register(geometry::superfgd::DP::FGD_HIT.c_str() + , geometry::superfgd::DP::FGD_DETECTOR_NAME.c_str() + , fHitArray, kTRUE); + + return kSUCCESS; +} + + +// ------------------------------------------------------------------------- + + + +// ----- Public method Exec -------------------------------------------- +void FgdDigitizer::Exec(Option_t* opt) +{ + // Reset output array + fHitArray->Delete(); + + const Int_t points = fdPoints->GetEntries(); + int nextPoint(0); + for(Int_t i =0; i < points; i++) + { + data::superfgd::FgdDetectorPoint* point = (data::superfgd::FgdDetectorPoint*)fdPoints->At(i); + + TVector3 dpos = point->GetDetectorpos(); // Get the detector position + //============================================= + //==== Position =============== + //============================================= + double pos_x = point->GetX() - dpos.X(); + double pos_y = point->GetY() - dpos.Y(); + double pos_z = point->GetZ() - dpos.Z(); + + // calculate the bin position + // pos_x,y,z -> relative from the center of the solid (half l,h,w) + // to normalize add half l,h,w and divide by the step in each direction + int bin_pos_x = (pos_x + f_total_X/2)/f_step_X; + int bin_pos_y = (pos_y + f_total_Y/2)/f_step_Y; + int bin_pos_z = (pos_z + f_total_Z/2)/f_step_Z; + + //============================================= + //==== MPPC =============== + //============================================= + // Calculate the distance from the center of the cube to the MPPC + double mppcX = bin_pos_x*f_step_X + f_step_X/2; + double mppcX_2ndSide = f_total_X - mppcX; // along the opposite direction + + double mppcY = bin_pos_y*f_step_Y + f_step_Y/2; + double mppcY_2ndSide = f_total_Y - mppcY; // along the opposite direction + + double mppcZ = bin_pos_z*f_step_Z + f_step_Z/2; + double mppcZ_2ndSide = f_total_Z - mppcZ; // along the opposite direction + + //============================================= + //==== Scintilation Response ======== + //============================================= + double pe = ApplyScintiResponse(point->GetEnergyLoss()*1e3 // EnergyLoss is returned in [GeV], we use [MeV] + ,point->GetTrackLenght() // TrackLength + ,1.0 // Charge, for the moment it is not used + ); + double time = point->GetTime(); + + // Calculate the # of p.e. that reach the MPPC (X,Y,Z). For the moment it is just considered that + // the part of the photons that go to x,y,z are taken into + // account in the coefficients when applying the scintillation response. + // -> light collection + attenuation + double peX1=pe/2.; + double peX2=pe/2.; + double timepeX=time; + ApplyFiberResponse(peX1,timepeX,mppcX); // along X fiber + ApplyFiberResponse(peX2,timepeX,mppcX_2ndSide); // along -X fiber + double peX = peX1 + peX2; // pe along fiber X + + double peY1=pe/2.; + double peY2=pe/2.; + double timepeY=time; + ApplyFiberResponse(peY1,timepeY,mppcY); // along Y fiber + ApplyFiberResponse(peY2,timepeY,mppcY_2ndSide); // along -Y fiber + double peY = peY1 + peY2; // pe along fiber Y + + double peZ1=pe/2.; + double peZ2=pe/2.; + double timepeZ=time; + ApplyFiberResponse(peZ1,timepeZ,mppcZ); // along Z fiber + ApplyFiberResponse(peZ2,timepeZ,mppcZ_2ndSide); // along -Z fiber + double peZ = peZ1 + peZ2; // pe along fiber Z + + ApplyMPPCResponse(peX); + ApplyMPPCResponse(peY); + ApplyMPPCResponse(peZ); + TVector3 photoElectrons(peX,peY,peZ); + + // Write the mppc location in terms of cube number position in x,y,z + if(peX!=0 || peY!=0 || peZ!=0) + { + TVector3 mppcLocalPosition(bin_pos_x,bin_pos_y,bin_pos_z); + TVector3 cubeCoordinatesRelToDetector(pos_x, pos_y ,pos_z); + + double center_coor_x = (bin_pos_x*f_step_X - f_total_X/2 + f_step_X/2) + dpos.X(); + double center_coor_y = (bin_pos_y*f_step_Y - f_total_Y/2 + f_step_Y/2) + dpos.Y(); + double center_coor_z = (bin_pos_z*f_step_Z - f_total_Z/2 + f_step_Z/2) + dpos.Z(); + + TVector3 mom(point->GetPx(), point->GetPy(), point->GetPz()); + + new((*fHitArray)[nextPoint++]) data::superfgd::FgdHit(center_coor_x, center_coor_y, center_coor_z + , mppcLocalPosition + , photoElectrons + , cubeCoordinatesRelToDetector + , point->GetTime() + , mom + , point->GetMomExit() + , point->GetTrackLenght() + , point->GetTrackLengthOrigin() + , TVector3(peX1, peY1, peZ1), TVector3(mppcX, mppcY, mppcZ) + , TVector3(peX2, peY2, peZ2), TVector3(mppcX_2ndSide, mppcY_2ndSide, mppcZ_2ndSide) + , point->GetPdg(), point->GetTrackID(), point->GetEnergyLoss()); + } + } +} +// ------------------------------------------------------------------------- + + + +// ----- Private methods -------------------------------------------- +const double FgdDigitizer::CBIRKS = 0.0208 * CLHEP::cm/CLHEP::MeV; // used in SciBooNE MC +const double FgdDigitizer::EdepToPhotConv_FGD = 70.8 / CLHEP::MeV; // contains both collection in fiber and edep->gamma conversion +const double FgdDigitizer::EdepToPhotConv_SuperFGD = EdepToPhotConv_FGD * 1.3; + +double FgdDigitizer::ApplyScintiResponse(double edep, double trackLength, double charge) +{ + // Calculated as in + // geant4/examples/advanced/amsEcal/src/SteppingAction.cc + // G4double SteppingAction::BirksAttenuation(const G4Step* aStep) + // light attenuation (Birks' formula) + double dedx = edep/trackLength; + double edep_birk = edep/(1. + CBIRKS*dedx); + // Calculate edep to photons + return edep_birk * EdepToPhotConv_SuperFGD; +} + +double FgdDigitizer::RevertScintiResponse(double edep, double trackLength, double charge, double pe) +{ + double dedx = edep/trackLength; + double edep_birk = (pe/EdepToPhotConv_SuperFGD); + double rec_Edep = edep_birk * (1. + CBIRKS*dedx); + + return rec_Edep; +} + +void FgdDigitizer::ApplyFiberResponse(double& numPhotons, double& time, double distance) +{ + double temp_np = numPhotons; + numPhotons = ApplyFiberAttenuation(temp_np, distance); + + double temp_time = time; + time = ApplyFiberTime(temp_time, distance); +} + +void FgdDigitizer::RevertFiberResponse(double &numPhotons, double &time, double distance) +{ + double temp_np = numPhotons; + numPhotons = RevertFiberAttenuation(temp_np, distance); +} + +const double FgdDigitizer::DistMPPCscint_FGD = 41*CLHEP::mm; +const double FgdDigitizer::LongCompFrac_FGD = 0.816; +const double FgdDigitizer::LongAtt_FGD = 11926.*CLHEP::mm; +const double FgdDigitizer::ShortAtt_FGD = 312.*CLHEP::mm; +const double FgdDigitizer::DecayLength_FGD = 0.0858 / CLHEP::mm; +const double FgdDigitizer::Lbar_FGD = 1864.3 * CLHEP::mm; + +double FgdDigitizer::ApplyFiberAttenuation(double Nphot0,double x) +{ + // Apply the light attenuation to the collected photons + // Used for official FGD reconstruction: Eq. (4) in TN-103 + + double a=0.; // long attenuation component fraction + double d=0.; // distance MPPC-scint outside the bar + double LongAtt=0.; // long attenuation length + double ShortAtt=0.; // short attenuation length + double Ldecay=0.; // decay length + double Lbar=0.; // bar length + + a = LongCompFrac_FGD; + d = DistMPPCscint_FGD; + LongAtt = LongAtt_FGD; + ShortAtt = ShortAtt_FGD; + Ldecay= DecayLength_FGD; + Lbar = Lbar_FGD; + + double Nphot = Nphot0; + Nphot *= ( a*exp((-x-d)/LongAtt) + (1-a)*exp((-x-d)/ShortAtt) ); + + return Nphot; +} + +double FgdDigitizer::RevertFiberAttenuation(double Nphot0,double x) +{ + double a=0.; // long attenuation component fraction + double d=0.; // distance MPPC-scint outside the bar + double LongAtt=0.; // long attenuation length + double ShortAtt=0.; // short attenuation length + double Ldecay=0.; // decay length + double Lbar=0.; // bar length + + a = LongCompFrac_FGD; + d = DistMPPCscint_FGD; + LongAtt = LongAtt_FGD; + ShortAtt = ShortAtt_FGD; + Ldecay= DecayLength_FGD; + Lbar = Lbar_FGD; + + double Nphot = Nphot0; + Nphot /= ( a*exp((-x-d)/LongAtt) + (1-a)*exp((-x-d)/ShortAtt) ); + + return Nphot; +} + +const double FgdDigitizer::TransTimeInFiber = 1./28.; // 1cm/2.8e10[cm/s] * 1e9 [ns] + +double FgdDigitizer::ApplyFiberTime(double& time, double x) +{ + double fiberTime = time + TransTimeInFiber*x; + return fiberTime; +} + +double FgdDigitizer::RevertFiberTime(double &time, double x) +{ + double fiberTime = time - TransTimeInFiber*x; + return fiberTime; +} + +const double FgdDigitizer::MPPCEff_SuperFGD = 0.38; + +void FgdDigitizer::ApplyMPPCResponse(double& npe) +{ + double rndunif =0.; + double npe_passed = 0.; + int npe_integer = (int) (npe+0.5); + + for (int i=0;i +#include +#include "TRandom3.h" + +#include "EsbGeometry/EsbSuperFGD/EsbFgdDetectorParameters.h" +#include "EsbData/EsbSuperFGD/FgdHit.h" + +namespace esbroot { +namespace digitizer { +namespace superfgd { + + +class FgdDigitizer : public FairTask +{ + + public: + + /** Default constructor **/ + FgdDigitizer(); + + /** Constructor with argument + *@param name Name of task + *@param geoConfigFile Configuration file detector + *@param x - X coordinate of the detector + *@param y - Y coordinate of the detector + *@param z - Z coordinate of the detector + *@param verbose Verbosity level + **/ + FgdDigitizer(const char* name + ,const char* geoConfigFile + ,double x, double y, double z + ,Int_t verbose = 1); + + /** Destructor **/ + ~FgdDigitizer(); + + + /** Virtual method Init **/ + virtual InitStatus Init(); + + + /** Virtual method Exec **/ + virtual void Exec(Option_t* opt) override; + + /** Methods to calculate the revert response from detector physical characteristics **/ + static double RevertScintiResponse(double edep, double trackLength, double charge, double pe); + static void RevertFiberResponse(double &numPhotons, double &time, double distance); + static double RevertFiberAttenuation(double Nphot0,double x); + static double RevertFiberTime(double &time, double x); + static double RevertyMPPCResponse(double npe); + + +private: + + /** Constants used when digitalizing the energy loss in the detector to photons **/ + static const double CBIRKS; + static const double EdepToPhotConv_FGD; + static const double MPPCEff_SuperFGD; + static const double EdepToPhotConv_SuperFGD; + static const double DistMPPCscint_FGD; + static const double LongCompFrac_FGD; + static const double LongAtt_FGD; + static const double ShortAtt_FGD; + static const double DecayLength_FGD; + static const double Lbar_FGD; + static const double TransTimeInFiber; + + /** Class to hold the Detector parameters read from external file **/ + esbroot::geometry::superfgd::FgdDetectorParameters fParams; + + /** Coordinates of the detector **/ + double fX; + double fY; + double fZ; + + /** Detector dimentions **/ + Double_t flunit; + double f_step_X; + double f_step_Y; + double f_step_Z; + int f_bin_X; + int f_bin_Y; + int f_bin_Z; + double f_total_X; + double f_total_Y; + double f_total_Z; + + TRandom3 rand; // random varible generator + + + /** Methods to calculate the response from detector physical characteristics **/ + double ApplyScintiResponse(double edep, double trackLength, double charge); + void ApplyFiberResponse(double &numPhotons, double &time, double distance); + double ApplyFiberAttenuation(double Nphot0,double x); + double ApplyFiberTime(double &time, double x); + void ApplyMPPCResponse(double &npe); + + /** Input array of FgdDetectorPoint(s)**/ + TClonesArray* fdPoints; //! + + /** Output array with Fgdhit(s) **/ + TClonesArray* fHitArray; //! + + ClassDef(FgdDigitizer, 2); + +}; + +} //superfgd +} //digitizer +} //esbroot + +#endif // ESBROOT_ESBDIGITIZER_FGD_DIGITIZER_H diff --git a/EsbDigitizer/EsbSuperFGD/FgdMppcDisplay.cxx b/EsbDigitizer/EsbSuperFGD/FgdMppcDisplay.cxx new file mode 100644 index 0000000..9da1e55 --- /dev/null +++ b/EsbDigitizer/EsbSuperFGD/FgdMppcDisplay.cxx @@ -0,0 +1,175 @@ +#include "EsbDigitizer/EsbSuperFGD/FgdMppcDisplay.h" +#include "EsbData/EsbSuperFGD/FgdDetectorPoint.h" + +#include +#include +#include +#include + +#include +#include "FairLogger.h" + +#include "EsbData/WCDetectorPoint.h" +#include "EsbGeometry/PMTube.h" +#include "EsbData/PMTubeHit.h" + +#include +#include +using std::cout; +using std::endl; + +namespace esbroot { +namespace digitizer { +namespace superfgd { + +// ----- Default constructor ------------------------------------------- +FgdMppcDisplay::FgdMppcDisplay() : + FairTask(), fX(0), fY(0), fZ(0),fevNum(0), + f_xy_hist(nullptr), f_yz_hist(nullptr), f_xz_hist(nullptr), fHitArray(nullptr) + , f_photo_ave(0.),f_photo_count(0) +{ +} +// ------------------------------------------------------------------------- + +// ----- Constructor ------------------------------------------- +FgdMppcDisplay::FgdMppcDisplay(const char* name + ,const char* geoConfigFile + ,double x, double y, double z + , Int_t verbose) : + FairTask(name, verbose), fX(x), fY(y), fZ(z),fevNum(0), + f_xy_hist(nullptr), f_yz_hist(nullptr), f_xz_hist(nullptr), fHitArray(nullptr) + , f_photo_ave(0.), f_photo_count(0) +{ + fParams.LoadPartParams(geoConfigFile); +} +// ------------------------------------------------------------------------- + + + +// ----- Destructor ---------------------------------------------------- +FgdMppcDisplay::~FgdMppcDisplay() +{ + if(fHitArray) { + fHitArray->Delete(); + delete fHitArray; + } +} +// ------------------------------------------------------------------------- + + + +// ----- Public method Init -------------------------------------------- +InitStatus FgdMppcDisplay::Init() +{ + flunit = fParams.GetLenghtUnit(); // [cm] + + f_step_X = fParams.ParamAsDouble(esbroot::geometry::superfgd::DP::length_X) * flunit; + f_step_Y = fParams.ParamAsDouble(esbroot::geometry::superfgd::DP::length_Y) * flunit; + f_step_Z = fParams.ParamAsDouble(esbroot::geometry::superfgd::DP::length_Z) * flunit; + + f_bin_X = fParams.ParamAsInt(esbroot::geometry::superfgd::DP::number_cubes_X); + f_bin_Y = fParams.ParamAsInt(esbroot::geometry::superfgd::DP::number_cubes_Y); + f_bin_Z = fParams.ParamAsInt(esbroot::geometry::superfgd::DP::number_cubes_Z); + + f_total_X = f_step_X * f_bin_X; + f_total_Y = f_step_Y * f_bin_Y; + f_total_Z = f_step_Z * f_bin_Z; + + // Get RootManager + FairRootManager* manager = FairRootManager::Instance(); + if ( !manager ) { + LOG(error) << "-E- FgdDigitizer::Init: " << "FairRootManager not instantised!"; + return kFATAL; + } + + fHitArray = (TClonesArray*) manager->GetObject(geometry::superfgd::DP::FGD_HIT.c_str()); + if (!fHitArray) + { + LOG(fatal) << "Exec", "No fgd hits array"; + return kFATAL; + } + + fcanvas = new TCanvas(); + f_xy_hist = new TH2F("hist_xy","XY histogram",f_bin_X,0,f_bin_X,f_bin_Y,0,f_bin_Y); + f_yz_hist = new TH2F("hist_yz","YZ histogram",f_bin_Y,0,f_bin_Y,f_bin_Z,0,f_bin_Z); + f_xz_hist = new TH2F("hist_zx","XZ histogram",f_bin_X,0,f_bin_X,f_bin_Z,0,f_bin_Z); + + return kSUCCESS; +} + + +// ------------------------------------------------------------------------- + + + +// ----- Public methods -------------------------------------------- +void FgdMppcDisplay::FinishEvent() +{ + if(f_xy_hist) + { + f_xy_hist->Draw("colz"); + WriteCanvas("XY"); + f_xy_hist->Reset(); + } + + if(f_yz_hist) + { + f_yz_hist->Draw("colz"); + WriteCanvas("YZ"); + f_yz_hist->Reset(); + } + + if(f_xz_hist) + { + f_xz_hist->Draw("colz"); + WriteCanvas("XZ"); + f_xz_hist->Reset(); + } + + if(fcanvas) + { + fcanvas->ResetDrawn(); + } + fevNum++; +} + +void FgdMppcDisplay::FinishTask() +{ + fevNum = 0; +} + + +void FgdMppcDisplay::Exec(Option_t* opt) +{ + const Int_t hits = fHitArray->GetEntries(); + for(Int_t i =0; i < hits; i++) + { + data::superfgd::FgdHit* hit = (data::superfgd::FgdHit*)fHitArray->At(i); + TVector3 photoE = std::move(hit->GetPhotoE()); //returns a temp obj + TVector3 mppcLoc = std::move(hit->GetMppcLoc()); //returns a temp obj + + if(f_xy_hist) f_xy_hist->Fill(mppcLoc.X(), mppcLoc.Y(), photoE.Z()); + if(f_yz_hist) f_yz_hist->Fill(mppcLoc.Y(), mppcLoc.Z(), photoE.X()); + if(f_xz_hist) f_xz_hist->Fill(mppcLoc.X(), mppcLoc.Z(), photoE.Y()); + + } + cout << endl; + cout << endl; +} +// ------------------------------------------------------------------------- + + +void FgdMppcDisplay::WriteCanvas(string hist) +{ + fcanvas->Update(); + fcanvas->Draw(); + fcanvas->Write(); + std::ostringstream strb; + strb<< "hist_" << hist << fevNum << ".gif"; + fcanvas->SaveAs((strb.str()).c_str()); + fcanvas->ResetDrawn(); +} + +}// namespace superfgd +}// namespace digitizer +}// namespace esbroot diff --git a/EsbDigitizer/EsbSuperFGD/FgdMppcDisplay.h b/EsbDigitizer/EsbSuperFGD/FgdMppcDisplay.h new file mode 100644 index 0000000..fcfb69b --- /dev/null +++ b/EsbDigitizer/EsbSuperFGD/FgdMppcDisplay.h @@ -0,0 +1,98 @@ +#ifndef ESBROOT_ESBDIGITIZER_FGD_MPPC_DISPLAY_H +#define ESBROOT_ESBDIGITIZER_FGD_MPPC_DISPLAY_H + +#include +#include +#include "TRandom3.h" +#include + +#include "EsbGeometry/EsbSuperFGD/EsbFgdDetectorParameters.h" +#include "EsbData/EsbSuperFGD/FgdHit.h" + +namespace esbroot { +namespace digitizer { +namespace superfgd { + + +class FgdMppcDisplay : public FairTask +{ + + public: + + /** Default constructor **/ + FgdMppcDisplay(); + + /** Constructor with argument + *@param name Name of task + *@param geoConfigFile Configuration file detector + *@param x - X coordinate of the detector + *@param y - Y coordinate of the detector + *@param z - Z coordinate of the detector + *@param verbose Verbosity level + **/ + FgdMppcDisplay(const char* name + ,const char* geoConfigFile + ,double x, double y, double z + ,Int_t verbose = 1); + + /** Destructor **/ + ~FgdMppcDisplay(); + + + /** Virtual method Init **/ + virtual InitStatus Init(); + virtual void FinishEvent() override; + virtual void FinishTask() override; + + + /** Virtual method Exec **/ + virtual void Exec(Option_t* opt) override; + + +private: + + /** Class to hold the Detector parameters read from external file **/ + esbroot::geometry::superfgd::FgdDetectorParameters fParams; + + /** Coordinates of the detector **/ + double fX; + double fY; + double fZ; + + /** Detector dimentions **/ + Double_t flunit; + double f_step_X; + double f_step_Y; + double f_step_Z; + int f_bin_X; + int f_bin_Y; + int f_bin_Z; + double f_total_X; + double f_total_Y; + double f_total_Z; + + std::shared_ptr xyz;// array pointer to total energy deposited in cubes + + TH2F* f_xy_hist; + TH2F* f_yz_hist; + TH2F* f_xz_hist; + double f_photo_ave; + int f_photo_count; + + /** Input array of FgdHit(s)**/ + TClonesArray* fHitArray; //! + + // Export hist to gif + TCanvas* fcanvas; + int fevNum; + void WriteCanvas(string hist); + + ClassDef(FgdMppcDisplay, 2); + +}; + +} //superfgd +} //digitizer +} //esbroot + +#endif // ESBROOT_ESBDIGITIZER_FGD_MPPC_DISPLAY_H diff --git a/EsbDigitizer/WCDigitizer.cxx b/EsbDigitizer/WCDigitizer.cxx index 414854e..423daa2 100644 --- a/EsbDigitizer/WCDigitizer.cxx +++ b/EsbDigitizer/WCDigitizer.cxx @@ -1,7 +1,11 @@ #include "WCDigitizer.h" #include +#include +#include + #include + #include "EsbData/WCDetectorPoint.h" #include "EsbGeometry/PMTube.h" #include "EsbData/PMTubeHit.h" @@ -18,7 +22,8 @@ WCDigitizer::WCDigitizer() : FairTask(), fPhotonArray(nullptr), fPMTubeArray(nullptr), - fHitArray(nullptr) + fHitArray(nullptr), + fQEffSpline(nullptr) { } // ------------------------------------------------------------------------- @@ -28,7 +33,8 @@ WCDigitizer::WCDigitizer(const char* name, TClonesArray* pmt_array, Int_t i_verb FairTask(name, i_verbose), fPhotonArray(nullptr), fPMTubeArray(pmt_array), - fHitArray(nullptr) + fHitArray(nullptr), + fQEffSpline(nullptr) { fPMTubeArray->Sort(); } @@ -72,6 +78,22 @@ InitStatus WCDigitizer::Init() { // Create and register output array fHitArray = new TClonesArray(data::PMTubeHit::Class(), 1000); manager->Register("PMTubeHit", "WCDetector", fHitArray, kTRUE); + + // Create the MEMPHYS spline if no other spline is given + if(!fQEffSpline) { + + // Taken from MEMPHYS code StackingAction.cpp: + const Int_t nPoints = 20; + Double_t wavelength[nPoints] = + { 280., 300., 320., 340., 360., 380., 400., 420., 440., 460., + 480., 500., 520., 540., 560., 580., 600., 620., 640., 660.}; + + Double_t qEfficiency[nPoints] = + { 0.00, .0139, .0854, .169, .203, .206, .211, .202, .188, .167, + .140, .116, .0806, .0432, .0265, .0146, .00756, .00508, .00158, 0.00}; + + fQEffSpline = new TSpline3("q_eff", wavelength, qEfficiency, nPoints); + } cout << "-I- WCDigitizer: Intialisation successfull " << kSUCCESS<< endl; return kSUCCESS; @@ -133,29 +155,73 @@ void WCDigitizer::Exec(Option_t* opt) { if(d_x*d_x + d_y*d_y + d_z*d_z > r*r) continue; // photon id not hit PMT - - // Here we should check that the photon produces a hit (to be done) - - // Now we know that we have a hit - pmt_charge++; - pmt_time += photon->GetTime(); - cout << pmt_charge << ", " << pmt_time << endl; + if(kFALSE) { // Old primitive diitization + + // Now we know that we have a hit + pmt_charge++; + pmt_time += photon->GetTime(); + } else { + // MEMPHYS like digitization, inspired/Taken from WCDigitizer.cpp + + // First check that the photon produces a photo electron + + // Calculate wavelength: + // lambda = hc/E ~ 2*pi*200eV*nm / E (in eV) + const Double_t E = photon->GetP() * 1e9; // [eV] + const Double_t wavelength = TMath::TwoPi()*197.33/E; // [nm] + if(wavelengthGetXmin() || + wavelength>fQEffSpline->GetXmax()) + continue; // no photo electron + if(gRandom->Rndm()>fQEffSpline->Eval(wavelength)) + continue; // no photo electron + + // Now we know that we have a photo electron + pmt_charge++; + if(pmt_charge==1) { // first photo electron + + pmt_time = photon->GetTime(); + } else { + if(pmt_time > photon->GetTime()) + pmt_time = photon->GetTime(); + } + } } // end loop over photons - // decide if we make a hit or not - if(pmt_time > 0) { + // decide if we make a digit or not + if(pmt_charge == 0) + continue; + + if(kFALSE) { // primitive weighted average digitization pmt_time /= pmt_charge; + } else { // MEMPHYS Like digitization - new((*fHitArray)[n_pmt_hits]) - data::PMTubeHit(pmt->GetX(), pmt->GetY(), pmt->GetZ(), - pmt->GetRadius(), pmt_charge, pmt_time); - n_pmt_hits++; + { // Smear the charge + // Peter: I modified the code here to require that the final signal is + // > 0.1. One could instead have some threshold. + Double_t pmt_charge_smeared = 0; + do { + pmt_charge_smeared = + gRandom->Gaus(pmt_charge, TMath::Sqrt(pmt_charge)); + } while (pmt_charge_smeared < 0.1 ); + pmt_charge = pmt_charge_smeared; + } + + const Double_t timingConstant = 1.890; // MEMPHYS (12"?) + const Double_t Q = (pmt_charge > 0.5) ? pmt_charge : 0.5; + Double_t timingResolution = 0.33 + TMath::Sqrt(timingConstant / Q); + if (timingResolution < 0.58) + timingResolution=0.58; + pmt_time += gRandom->Gaus(0, timingResolution); } - + + new((*fHitArray)[n_pmt_hits]) + data::PMTubeHit(pmt->GetX(), pmt->GetY(), pmt->GetZ(), + pmt->GetRadius(), pmt_charge, pmt_time); + n_pmt_hits++; } // end loop over PMTs } -// ------------------------------------------------------------------------- - + // ------------------------------------------------------------------------- + } } diff --git a/EsbDigitizer/WCDigitizer.h b/EsbDigitizer/WCDigitizer.h index 33a3bc4..d5e9e56 100644 --- a/EsbDigitizer/WCDigitizer.h +++ b/EsbDigitizer/WCDigitizer.h @@ -7,6 +7,7 @@ #include #include +#include namespace esbroot { namespace digitizer { @@ -36,6 +37,12 @@ class WCDigitizer : public FairTask ~WCDigitizer(); + /// Setter for Quantum Efficiency spline + void SetQEffSpline(TSpline* spline) { fQEffSpline = spline; } + + /// Getter for Quantum Efficiency spline + TSpline* GetQEffSpline() { return fQEffSpline; } + /** Virtual method Init **/ virtual InitStatus Init(); @@ -54,6 +61,7 @@ class WCDigitizer : public FairTask /** Output array with EsbPMThit(s) **/ TClonesArray* fHitArray; //! + TSpline* fQEffSpline; //! Quantum Efficiency Spline /* Is this needed? WCDigitizer(const WCDigitizer&); diff --git a/EsbDoc/Programming_guidelines.txt b/EsbDoc/Programming_guidelines.txt index e1b578e..610229b 100644 --- a/EsbDoc/Programming_guidelines.txt +++ b/EsbDoc/Programming_guidelines.txt @@ -19,7 +19,7 @@ Const-correctness: Try to make things const if possible. Function parameters -All input parameters are const&, with the exception of built-in types that may be passed by value. If there is more than one output, or it is a complex class, pass it as reference argument. In that case, function returns true if output is successfull, else it's false. Define empty OUT macro. +All input parameters are const&, with the exception of built-in types that may be passed by value. If there is more than one output, or it is a complex class, pass it as reference argument. In that case, function returns true if output is successfull, else it's false. Use OUT comment for output variables. Example: bool CalculateThings(int const& start, int end, /*OUT*/ double& result1, /*OUT*/ double& result2) Pointers @@ -67,8 +67,8 @@ Class names: CamelCase for class names. Words *always* start with capital letter e.g. EsbMCTrack -> MCTrack (but in esbroot::data namespace). Method names: CamelCase starting with capital letters Class member names start with f (e.g. int fMyInt) (f is "field") -Standalone functions use CamelCase -Local names use snake case (e.g. my_local_variable) radius +Standalone functions use snake_case +Local names use snake_case (e.g. my_local_variable) radius Getters and setters: Variable name: int fVar; @@ -88,6 +88,15 @@ global: esbroot local: foldername without Esb (EsbData -> data) e.g: esbroot::data::MCTrack +using namespace somenamespace; +directive is **forbidden** in headers and highly discouraged elsewhere. It can lead to poor code readability and unintentional shadowing of identifiers (i.e. there could be esbroot::SomeClass and std::SomeClass). If you must, please use *using* directive like this (this **must** all be in the body of a function).: +using std::cout; +using std::endl; +cout << "I don't feel like writing std:: every time" << endl; + +The only explicitly allowed usage of "using namespace" directive is this (if used inside the body of a function): +using namespace std::placeholders; + Headerguards: #ifndef ESBROOT_DIRNAME_CLASSNAME_H #define ESBROOT_DIRNAME_CLASSNAME_H diff --git a/EsbGenerators/CMakeLists.txt b/EsbGenerators/CMakeLists.txt index d46a0cc..0d20ec7 100644 --- a/EsbGenerators/CMakeLists.txt +++ b/EsbGenerators/CMakeLists.txt @@ -3,33 +3,63 @@ # The extension is already found. Any number of sources could be listed here. set(INCLUDE_DIRECTORIES -${PYTHIA8_INCLUDE_DIR} -${SIMPATH}/include -${BASE_INCLUDE_DIRECTORIES} -${CMAKE_SOURCE_DIR}/EsbGenerators -${CMAKE_SOURCE_DIR}/generators - + ${PYTHIA8_INCLUDE_DIR} + ${SIMPATH}/include + ${BASE_INCLUDE_DIRECTORIES} + ${CMAKE_SOURCE_DIR} + ${CLHEP_INCLUDE_DIR} ) -include_directories(${INCLUDE_DIRECTORIES}) -include_directories(${SYSTEM_INCLUDE_DIRECTORIES}) - set(LINK_DIRECTORIES -${ROOT_LIBRARY_DIR} -${FAIRROOT_LIBRARY_DIR} -${SIMPATH}/lib + ${ROOT_LIBRARY_DIR} + ${FAIRROOT_LIBRARY_DIR} + ${SIMPATH}/lib + ${CLHEP_LIB_DIR} ) -link_directories( ${LINK_DIRECTORIES}) - set(SRCS -Pythia6Generator.cxx -Pythia8Generator.cxx ) -set(LINKDEF GenLinkDef.h) +set(HEADERS +) + +set(DEPENDENCIES Base EsbData EsbGeometry) + +if(WITH_GENIE) + list(APPEND SRCS + GenieGenerator.cxx + GenieNtpFluxV1.cxx + SimpleGenieGenerator.cxx + EsbSuperFGD/GenieFluxDriver.cxx + EsbSuperFGD/FgdGeomAnalyzer.cxx + EsbSuperFGD/FgdGenieGenerator.cxx + ) + + list(APPEND HEADERS + ${CMAKE_SOURCE_DIR}/EsbGenerators/GenieGenerator.h + ${CMAKE_SOURCE_DIR}/EsbGenerators/SimpleGenieGenerator.h + ${CMAKE_SOURCE_DIR}/EsbGenerators/GenieNtpFluxV1.h + ${CMAKE_SOURCE_DIR}/EsbGenerators/EsbSuperFGD/GenieFluxDriver.h + ${CMAKE_SOURCE_DIR}/EsbGenerators/EsbSuperFGD/FgdGeomAnalyzer.h + ${CMAKE_SOURCE_DIR}/EsbGenerators/EsbSuperFGD/FgdGenieGenerator.h + ) + + #~ message(FATAL_ERROR "Genie include directory "${GENIE_INC_DIR}) + + list(APPEND INCLUDE_DIRECTORIES ${GENIE_INC_DIR}) + list(APPEND LINK_DIRECTORIES ${GENIE_LIB_DIR}) + + list(APPEND DEPENDENCIES + Genie + ) +endif(WITH_GENIE) + +set(LINKDEF ${CMAKE_SOURCE_DIR}/EsbGenerators/GenLinkDef.h) set(LIBRARY_NAME EsbGen) -set(DEPENDENCIES Base EsbData pythia8 Pythia6) +include_directories(${INCLUDE_DIRECTORIES}) +include_directories(${SYSTEM_INCLUDE_DIRECTORIES}) + +link_directories( ${LINK_DIRECTORIES}) GENERATE_LIBRARY() diff --git a/EsbGenerators/EsbSuperFGD/FgdGenieGenerator.cxx b/EsbGenerators/EsbSuperFGD/FgdGenieGenerator.cxx new file mode 100644 index 0000000..5c85add --- /dev/null +++ b/EsbGenerators/EsbSuperFGD/FgdGenieGenerator.cxx @@ -0,0 +1,243 @@ +#include "EsbGenerators/EsbSuperFGD/FgdGenieGenerator.h" +#include "EsbGenerators/EsbSuperFGD/GenieFluxDriver.h" +#include "EsbGenerators/EsbSuperFGD/FgdGeomAnalyzer.h" +#include "EsbGeometry/EsbSuperFGD/Names.h" + +#include "FairLogger.h" +#include +#include "Framework/GHEP/GHepParticle.h" +#include "Framework/Interaction/ProcessInfo.h" +#include "Framework/Interaction/Interaction.h" +#include "Framework/Interaction/InitialState.h" + +#include + +namespace esbroot { +namespace generators { +namespace superfgd { + +FgdGenieGenerator::FgdGenieGenerator() + : GenieGenerator() +{ +} + +FgdGenieGenerator::~FgdGenieGenerator() +{ +} + +FgdGenieGenerator::FgdGenieGenerator(const char* geoConfigFile + , const char* nuFluxFile + , unsigned int seed + , TVector3 detPos + , Int_t numEvents + , genie::GFluxI* extFlux + , TGeoManager* gm) + : GenieGenerator() + , fgeoConfigFile(geoConfigFile) + , fnuFluxFile(nuFluxFile) + , fseed(seed) + , fdetPos(detPos) + , fnumEvents(numEvents) + , fgm(gm) + , fExtFlux(extFlux) + , fCurrentEvent(0) + , fUseRandomVertex(false) +{ +} + + +void FgdGenieGenerator::PostProcessEvent(/*IN OUT*/ genie::GHepRecord* event) +{ + +} + + +Bool_t FgdGenieGenerator::Configure() +{ + if(fgm==nullptr) + { + fgm = gGeoManager; + } + + FgdGeomAnalyzer* geomAnalyzer = nullptr; + bool useDefaultFlux = (fExtFlux==nullptr); + + + if(useDefaultFlux) + { + LOG(info) << "Using flux driver - GenieFluxDriver [Fdg implementation], with top volume : " + << esbroot::geometry::superfgd::fgdnames::superFGDName; + + SetGeomI(std::make_shared(fgm)); + SetFluxI(std::make_shared(fgeoConfigFile.c_str(), fnuFluxFile.c_str(), fseed, fdetPos)); + + geomAnalyzer = dynamic_cast(GetGeomI().get()); + geomAnalyzer->SetScannerFlux(GetFluxI().get()); // Force to use MaxPathLengthsFluxMethod, otherwise it uses MaxPathLengthsBoxMethod + } + else + { + LOG(info) << "Using external flux driver with top volume : " << (fgm->GetTopVolume())->GetName(); + + SetGeomI(std::make_shared(fgm)); + SetFluxI(shared_ptr(fExtFlux)); + } + + GenieGenerator::Configure(); + GenerateEvents(); + + if(useDefaultFlux && geomAnalyzer!=nullptr) + { + geomAnalyzer->Reset(); // Revert initial Top Volume Geometry + } + + return true; +} + +Bool_t FgdGenieGenerator::ReadEvent(FairPrimaryGenerator* primGen) +{ + if(fCurrentEvent>=fnumEvents) return false; + + genie::EventRecord& event = fGenieEvents[fCurrentEvent++]; + + event.Print(std::cout); + TLorentzVector* v = event.Vertex(); + + // Fire other final state particles + int nParticles = event.GetEntries(); + for (int i = 0; i < nParticles; i++) + { + genie::GHepParticle *p = event.Particle(i); + // kIStStableFinalState - Genie documentation: generator-level final state + // particles to be tracked by the detector-level MC + if ((p->Status() == genie::EGHepStatus::kIStStableFinalState)) + { + if(IsPdgAllowed(p->Pdg())) + { + primGen->AddTrack(p->Pdg(), p->Px(), p->Py(), p->Pz(), v->X(), v->Y(), v->Z()); + } + } + } + + if(!GlobalState.fOutputFileName.empty()) + { + WriteToOutputFile(&event, false /* flaGkeepThrowing - check made in GenerateEvents*/); + } + + return true; +} + +void FgdGenieGenerator::GenerateEvents() +{ + for(Int_t eventId = 0; eventId < fnumEvents; ++eventId) + { + while(true) + { + genie::EventRecord* event = fmcj_driver->GenerateEvent(); + if(event != nullptr) + { + PostProcessEvent(event); + int nParticles = event->GetEntries(); + std::vector eventParticles; + for (int i = 0; i < nParticles; i++) + { + genie::GHepParticle *p = event->Particle(i); + // kIStStableFinalState - Genie documentation: generator-level final state + // particles to be tracked by the detector-level MC + if ((p->Status() == genie::EGHepStatus::kIStStableFinalState)) + { + if(IsPdgAllowed(p->Pdg())) + { + eventParticles.push_back(p); + } + } + } + if(!KeepThrowing(eventParticles) && !eventParticles.empty()) + { + fGenieEvents.emplace_back(*event); + delete event; + break; + } + } + else + { + --eventId; // try again + break; + } + + delete event; + } + + } +} + +Bool_t FgdGenieGenerator::KeepThrowing(std::vector& eventParticles ) +{ + static int count = 0; + Bool_t throwAgain(false); + + if(eventParticles.empty() && count <5 /* try only 5 times */) + { + ++count; + throwAgain = true; + } + else + { + count = 0; + } + + + return throwAgain; +} + +void FgdGenieGenerator::WriteToOutputFile(const genie::EventRecord* event, Bool_t flaGkeepThrowing ) +{ + static int eventCounter = 0; + std::ofstream outputFile(GlobalState.fOutputFileName, std::ios::app); + if(outputFile.is_open()) + { + const Interaction* inter = event->Summary(); + const ProcessInfo& procInfo = inter->ProcInfo(); + LOG(debug) << "IsWeakCC " << procInfo.IsWeakCC() << "; IsWeakNC " << procInfo.IsWeakNC(); + + const InitialState& initSt = inter->InitState(); + + // Write the interaction info to be used in alter analysis + outputFile << initSt.ProbePdg() + << " " << initSt.ProbeE(kRfLab) + << " " << procInfo.IsWeakCC() + << " " << procInfo.IsWeakNC() + << " " << procInfo.IsQuasiElastic() + << " " << procInfo.IsDeepInelastic() + << " " << procInfo.IsResonant() + << " " << procInfo.IsCoherent() + << " " << procInfo.IsMEC() + << " " << procInfo.IsNuElectronElastic() + << " " << procInfo.IsElectronScattering(); + + TLorentzVector* v = event->Vertex(); + + outputFile << " " << v->X() << " " << v->Y()<< " " << v->Z(); + + int nParticles = event->GetEntries(); + for (int i = 0; i < nParticles; i++) + { + genie::GHepParticle *p = event->Particle(i); + // kIStStableFinalState - Genie documentation: generator-level final state + // particles to be tracked by the detector-level MC + if ((p->Status() == genie::EGHepStatus::kIStStableFinalState)) + { + if(IsPdgAllowed(p->Pdg())) + { + outputFile << " " << p->Pdg() << " " << p->Px() << " " << p->Py() << " " << p->Pz(); + } + } + } + //outputFile << "EndEvent " << eventCounter++ << "=====================" << endl; + outputFile << endl; + } + outputFile.close(); +} + +} //namespace superfgd +} //namespace generators +} //namespace esbroot diff --git a/EsbGenerators/EsbSuperFGD/FgdGenieGenerator.h b/EsbGenerators/EsbSuperFGD/FgdGenieGenerator.h new file mode 100644 index 0000000..3f04b91 --- /dev/null +++ b/EsbGenerators/EsbSuperFGD/FgdGenieGenerator.h @@ -0,0 +1,77 @@ +#ifndef ESBROOT_GENERATOR_FGD_GENIE_GENERATOR_H +#define ESBROOT_GENERATOR_FGD_GENIE_GENERATOR_H 1 + +#include "EsbGenerators/GenieGenerator.h" + +#include + +#include +#include "TGeoManager.h" +#include + +class TVector3; +class TLorentzVector; + +namespace esbroot { +namespace generators { +namespace superfgd { + + +class FgdGenieGenerator : public GenieGenerator +{ +public: + + //! Default constructor + FgdGenieGenerator(); + + // ! Basic constructor + FgdGenieGenerator(const char* geoConfigFile + , const char* nuFluxFile + , unsigned int seed + , TVector3 detPos + , Int_t numEvents + , genie::GFluxI* extFlux = nullptr + , TGeoManager* gm = nullptr); + + //! Destructor + ~FgdGenieGenerator(); + + //! Implementation of GenieGenerator::Init() which calls the Configure() function. + virtual Bool_t Init() {return(Configure());}; + + //! Post processes Genie events to choose vertex position + virtual void PostProcessEvent(/*IN OUT*/ genie::GHepRecord* event) override; + + //! Overrides initial implementation, reads from pregenerated events + virtual Bool_t ReadEvent(FairPrimaryGenerator* primGen) override; + + virtual Bool_t Configure() override; + + void SetRandomVertex(Bool_t rndVertex) {fUseRandomVertex = rndVertex;} + +protected: + virtual Bool_t KeepThrowing(std::vector& eventParticles ) override; + virtual void WriteToOutputFile(const genie::EventRecord* event, Bool_t flaGkeepThrowing ) override; + +private: + TGeoManager* fgm;//! fGenieEvents;//! +#include + +#include "FairLogger.h" + +#include "Framework/ParticleData/PDGCodeList.h" +#include "Framework/EventGen/GFluxI.h" + +#include +#include + +namespace esbroot { +namespace generators { +namespace superfgd { + +FgdGeomAnalyzer::FgdGeomAnalyzer(TGeoManager* gm) + : ROOTGeomAnalyzer(gm), fTopVol(nullptr) +{ + fTopVol = gm->GetTopVolume(); + + //ROOTGeomAnalyzer::SetLengthUnits(genie::units::centimeter); + ROOTGeomAnalyzer::SetTopVolName((esbroot::geometry::superfgd::fgdnames::superFGDName)); +} + + +FgdGeomAnalyzer::~FgdGeomAnalyzer() +{ + Reset(); +} + +void FgdGeomAnalyzer::Reset() +{ + if(fTopVol!=nullptr) + { + //ROOTGeomAnalyzer::SetLengthUnits(genie::units::meter); + ROOTGeomAnalyzer::SetTopVolName(fTopVol->GetName()); + } +} + +const genie::PathLengthList & FgdGeomAnalyzer::ComputePathLengths(const TLorentzVector & x, const TLorentzVector & p) +{ + return ROOTGeomAnalyzer::ComputePathLengths(x, p); +} + + +} //namespace superfgd +} //namespace generators +} //namespace esbroot \ No newline at end of file diff --git a/EsbGenerators/EsbSuperFGD/FgdGeomAnalyzer.h b/EsbGenerators/EsbSuperFGD/FgdGeomAnalyzer.h new file mode 100644 index 0000000..a28361a --- /dev/null +++ b/EsbGenerators/EsbSuperFGD/FgdGeomAnalyzer.h @@ -0,0 +1,48 @@ +#ifndef ESBROOT_GENERATOR_FGD_ROOTGEOM_ANALYZER_H +#define ESBROOT_GENERATOR_FGD_ROOTGEOM_ANALYZER_H 1 + +#include "CLHEP/Units/SystemOfUnits.h" +#include "CLHEP/Units/PhysicalConstants.h" + +#include +#include +#include + +#include "TGeoManager.h" +#include +#include +#include + +#include "EsbGeometry/EsbSuperFGD/EsbFgdDetectorParameters.h" + +namespace esbroot { +namespace generators { +namespace superfgd { + +using namespace std; + +// Use ROOTGeomAnalyzer since it has implemented the methods +// overwrite only the ComputeMaxPathLength method +class FgdGeomAnalyzer : public genie::geometry::ROOTGeomAnalyzer + , public TObject { + +public: + + FgdGeomAnalyzer(TGeoManager* gm); + ~FgdGeomAnalyzer(); + + virtual const genie::PathLengthList& ComputePathLengths(const TLorentzVector & x, const TLorentzVector & p) override; + + void Reset(); + +private: + TGeoVolume* fTopVol; + + ClassDef(FgdGeomAnalyzer,6) +}; + +} //namespace superfgd +} //namespace generators +} //namespace esbroot + +#endif \ No newline at end of file diff --git a/EsbGenerators/EsbSuperFGD/GenieFluxDriver.cxx b/EsbGenerators/EsbSuperFGD/GenieFluxDriver.cxx new file mode 100644 index 0000000..6484079 --- /dev/null +++ b/EsbGenerators/EsbSuperFGD/GenieFluxDriver.cxx @@ -0,0 +1,322 @@ +#include "EsbGenerators/EsbSuperFGD/GenieFluxDriver.h" + +#include "Framework/ParticleData/PDGCodes.h" +#include + +#include "FairLogger.h" + +#include + +using namespace std; + +namespace esbroot { +namespace generators { +namespace superfgd { + +GenieFluxDriver::GenieFluxDriver(const char* geoConfigFile + , const char* nuFluxFile + , unsigned int seed + , TVector3 detPos + , Int_t maxEvents + , Double_t maxEnergy) + : fnuFluXFile(nuFluxFile) + , fdetPos(detPos) + , frndGen(seed) + , fdis(0.0, 1.0) + , fpdgCode(0) + , fMaxEv(maxEnergy) + , fcurrentEvent(0) + , fmaxEvents(maxEvents) +{ + InitDetectorParams(geoConfigFile); + InitPDGList(); + Init4Momentum(); + Init4Position(); + + ReadNuFluxFile(fnuFluXFile.c_str()); + CalculateProbability(); +} + +GenieFluxDriver::GenieFluxDriver(const GenieFluxDriver& gf) +{ + this->fnuFluXFile = gf.fnuFluXFile; + this->fdetPos = gf.fdetPos; + this->frndGen = gf.frndGen; + this->fdis = gf.fdis; + + this->fMaxEv = gf.fMaxEv; + this->fpdgCode = gf.fpdgCode; + this->fcurrentEvent = gf.fcurrentEvent; + + this->fdetectorParams = const_cast(gf.fdetectorParams); + this->fPdgCList = gf.fPdgCList; + this->f4momentum = gf.f4momentum; + this->f4position = gf.f4position; + + this->f_total_X = gf.f_total_X; + this->f_total_Y = gf.f_total_Y; + this->f_total_Z = gf.f_total_Z; + this->fnuFluXFile = gf.fnuFluXFile; + this->fFlux = gf.fFlux; + this->fmaxEvents = fmaxEvents; +} + +GenieFluxDriver& GenieFluxDriver::operator=(const GenieFluxDriver& gf) +{ + this->fnuFluXFile = gf.fnuFluXFile; + this->fdetPos = gf.fdetPos; + this->frndGen = gf.frndGen; + this->fdis = gf.fdis; + + this->fMaxEv = gf.fMaxEv; + this->fpdgCode = gf.fpdgCode; + this->fcurrentEvent = gf.fcurrentEvent; + + this->fdetectorParams = const_cast(gf.fdetectorParams); + this->fPdgCList = gf.fPdgCList; + this->f4momentum = gf.f4momentum; + this->f4position = gf.f4position; + + this->f_total_X = gf.f_total_X; + this->f_total_Y = gf.f_total_Y; + this->f_total_Z = gf.f_total_Z; + this->fnuFluXFile = gf.fnuFluXFile; + this->fFlux = gf.fFlux; + this->fmaxEvents = fmaxEvents; +} + +bool GenieFluxDriver::GenerateNext(void) +{ + int nuPdg(0); + Double_t nuEnergy(0.); + int ret = 0; + Double_t nextNu = fdis(frndGen); + + for(size_t i = 0; i < fFlux.size(); ++i) + { + GenieFluxDriver::FLuxNeutrino& neutrino = fFlux[i]; + + if(neutrino.GetNeutrino(nextNu, nuPdg, nuEnergy)) + { + CalculateNext4position(); + CalculateNext4Momentum(nuEnergy); + fpdgCode = nuPdg; + + fcurrentEvent++; + + return true; + } + } + + return false; +} + +//------------------------------------------------------- +// Private methods +//------------------------------------------------------- + +// Calculate the starting position of the neutrino +void GenieFluxDriver::CalculateNext4position() +{ + static std::uniform_real_distribution ldis(-0.5,0.5); + Double_t x_det = f_total_X * ldis(frndGen); + Double_t y_det = f_total_Y * ldis(frndGen); + Double_t z_det = f_total_Z * ldis(frndGen); + + // Set the Position of the event + Double_t rndm_X = fdetPos.X() + x_det; + Double_t rndm_Y = fdetPos.Y() + y_det; + Double_t rndm_Z = fdetPos.Z() + z_det; + + f4position.SetX(rndm_X); + f4position.SetY(rndm_Y); + f4position.SetZ(fdetPos.Z() - f_total_Z/2 - 10); + f4position.SetT(0.); +} + +void GenieFluxDriver::CalculateNext4Momentum(Double_t energyOfNeutrino) +{ + // calculate only pZ since beam is parallel to Z axis + // neutrino is massless so p=E/c + Double_t pZ = energyOfNeutrino;///CLHEP::c_light; + Double_t pX = 0; + Double_t pY = 0; + + f4momentum.SetPxPyPzE(pX,pY,pZ,energyOfNeutrino); +} + +void GenieFluxDriver::InitPDGList(void) +{ + /* The neutrinos are added in the list in the order in which they are expected to appear in the flux file*/ + + // Matter neutrinos + fPdgCList.push_back(genie::kPdgNuE); // Electron neutrino pdgCode = 12 + fPdgCList.push_back(genie::kPdgNuMu); // Muon neutrino pdgCode = 14 + fPdgCList.push_back(genie::kPdgNuTau); // Electron tau pdgCode = 16 + + + // Antimatter neutrinos + fPdgCList.push_back(genie::kPdgAntiNuE); // Electron antineutrino pdgCode = -12 + fPdgCList.push_back(genie::kPdgAntiNuMu); // Muon antineutrino pdgCode = -14 + fPdgCList.push_back(genie::kPdgAntiNuTau); // Tau antineutrino pdgCode = -16 +} + +void GenieFluxDriver::InitDetectorParams(const char* configFile) +{ + fdetectorParams.LoadPartParams(configFile); + + Double_t lunit = fdetectorParams.GetLenghtUnit(); // [cm] + + Double_t step_X = fdetectorParams.ParamAsDouble(esbroot::geometry::superfgd::DP::length_X) * lunit; + Double_t step_Y = fdetectorParams.ParamAsDouble(esbroot::geometry::superfgd::DP::length_Y) * lunit; + Double_t step_Z = fdetectorParams.ParamAsDouble(esbroot::geometry::superfgd::DP::length_Z) * lunit; + + Int_t bin_X = fdetectorParams.ParamAsInt(esbroot::geometry::superfgd::DP::number_cubes_X); + Int_t bin_Y = fdetectorParams.ParamAsInt(esbroot::geometry::superfgd::DP::number_cubes_Y); + Int_t bin_Z = fdetectorParams.ParamAsInt(esbroot::geometry::superfgd::DP::number_cubes_Z); + + f_total_X = step_X * bin_X; + f_total_Y = step_Y * bin_Y; + f_total_Z = step_Z * bin_Z; +} + +void GenieFluxDriver::Init4Momentum(void) +{ + f4momentum.SetX(0.); + f4momentum.SetY(0.); + f4momentum.SetZ(0.); + f4momentum.SetT(0); +} + +void GenieFluxDriver::Init4Position(void) +{ + f4position.SetX(0.); + f4position.SetY(0.); + f4position.SetZ(0.); + f4position.SetT(0); +} + +void GenieFluxDriver::ReadNuFluxFile(const char* fluxFile) +{ + std::string nufluxFile(fluxFile); + + if(!nufluxFile.empty()) + { + const char spaceChar(' '); + std::ifstream fluxFileStream; + + try + { + fluxFileStream.open(nufluxFile.c_str(), std::ios::in); + + if(fluxFileStream.is_open()) + { + std::string line; + while(std::getline(fluxFileStream,line)) + { + Double_t arr[] = {0,0,0,0,0,0,0}; + int arrInd(0); + + std::istringstream ss(line); + std::string token; + while( (arrInd<7) && std::getline(ss, token, spaceChar)) + { + if(!token.empty()) + { + Double_t parsedVal = std::stod(token); + arr[arrInd++] = parsedVal; + } + } + + /* The first value is the energy value for all neutrinos on the line */ + Double_t energy = arr[0]; + + /* The neutrinos are added in the list in the order in which they are expected to appear in the flux file*/ + for(size_t i = 1; i < 7; ++i) + { + if(arr[i] != 0) + { + fFlux.emplace_back(fPdgCList[i-1], energy, arr[i]); + } + } + } + } + } + catch(const std::exception& e) + { + LOG(fatal) << e.what(); + } + + if(fluxFileStream.is_open()) + { + fluxFileStream.close(); + } + } +} + +void GenieFluxDriver::CalculateProbability() +{ + Double_t totalFlux(0.); + for(size_t i = 0; i < fFlux.size(); ++i) + { + GenieFluxDriver::FLuxNeutrino* neutrino = &fFlux[i]; + totalFlux+= neutrino->GetFlux(); + } + + Double_t currentLowerFluxVal(0.); + for(size_t i = 0; i < fFlux.size(); ++i) + { + GenieFluxDriver::FLuxNeutrino& neutrino = fFlux[i]; + neutrino.SetLowerVal(currentLowerFluxVal); + Double_t uppVal = currentLowerFluxVal + neutrino.GetFlux()/totalFlux; + neutrino.SetUpperVal(uppVal); + currentLowerFluxVal = uppVal; + } +} + + +GenieFluxDriver::FLuxNeutrino::FLuxNeutrino(int pdg , Double_t energy, Double_t flux) + : fpdg(pdg), fEnergy(energy), fFluxValue(flux), fLowerVal(0.) , fUpperVal(0.) +{ +} + +GenieFluxDriver::FLuxNeutrino::~FLuxNeutrino() +{ +} + +GenieFluxDriver::FLuxNeutrino::FLuxNeutrino(const FLuxNeutrino& fn) +{ + fpdg = fn.fpdg; + fEnergy = fn.fEnergy; + fFluxValue = fn.fFluxValue; + + fLowerVal = fn.fLowerVal; + fUpperVal = fn.fUpperVal; +} + +GenieFluxDriver::FLuxNeutrino& GenieFluxDriver::FLuxNeutrino::operator=(const FLuxNeutrino& fn) +{ + fpdg = fn.fpdg; + fEnergy = fn.fEnergy; + fFluxValue = fn.fFluxValue; + + fLowerVal = fn.fLowerVal; + fUpperVal = fn.fUpperVal; + + return *this; +} + +Bool_t GenieFluxDriver::FLuxNeutrino::GetNeutrino(Double_t val, int& pdg, Double_t& energy) +{ + if(val>=fLowerVal && val +#include +#include +#include + +#include "Framework/EventGen/GFluxI.h" +#include "Framework/ParticleData/PDGCodeList.h" + +#include "CLHEP/Units/SystemOfUnits.h" +#include "CLHEP/Units/PhysicalConstants.h" + +#include "TLorentzVector.h" +#include "TRandom3.h" +#include "TVector3.h" + +#include "EsbGeometry/EsbSuperFGD/EsbFgdDetectorParameters.h" + + +namespace esbroot { +namespace generators { +namespace superfgd { + +using namespace genie; + +class GenieFluxDriver : public GFluxI + , public TObject + +{ +public: + // ~ctor + GenieFluxDriver(const char* geoConfigFile + , const char* nuFluxFile + , unsigned int seed + , TVector3 detPos + , Int_t maxEvents = 1 + , Double_t maxEnergy = 2. /* GeV */); + + GenieFluxDriver(const GenieFluxDriver& gf); + + class FLuxNeutrino + { + public: + FLuxNeutrino(int pdg , Double_t energy, Double_t flux); + ~FLuxNeutrino(); + + FLuxNeutrino(const FLuxNeutrino& fn); + FLuxNeutrino& operator=(const FLuxNeutrino& fn); + + void SetLowerVal(Double_t lv){fLowerVal = lv;} + void SetUpperVal(Double_t uv){fUpperVal = uv;} + + Bool_t GetNeutrino(Double_t val, int& pdg, Double_t& energy); + + int GetPdg(){return fpdg;} + Double_t GetEnergy(){return fEnergy;} + Double_t GetFlux(){return fFluxValue;} + + private: + int fpdg; + Double_t fEnergy; + Double_t fFluxValue; + + Double_t fLowerVal; + Double_t fUpperVal; + }; + + // Methods implementing the GENIE GFluxI interface + const PDGCodeList & FluxParticles (void) { return fPdgCList;} ///< declare list of flux neutrinos that can be generated (for init. purposes) + double MaxEnergy (void) { return fMaxEv;} ///< declare the max flux neutrino energy that can be generated (for init. purposes) + + + virtual bool GenerateNext (void) override; ///< generate the next flux neutrino (return false in err) + int PdgCode (void) { return fpdgCode;} ///< returns the flux neutrino pdg code + double Weight (void) { return 1.0;/* No idea what this is */} ///< returns the flux neutrino weight (if any) + const TLorentzVector& Momentum (void) { return f4momentum;} ///< returns the flux neutrino 4-momentum + const TLorentzVector& Position (void) { return f4position;} ///< returns the flux neutrino 4-position (note: expect SI rather than physical units) + virtual bool End (void) { return false;} ///< true if no more flux nu's can be thrown (eg reaching end of beam sim ntuples) + virtual long int Index (void){return fcurrentEvent;} ///< returns corresponding index for current flux neutrino (e.g. for a flux ntuple returns the current entry number) + virtual void Clear (Option_t * opt ) {fcurrentEvent = 0; } ///< reset state variables based on opt + virtual void GenerateWeighted (bool gen_weighted) {} ///< set whether to generate weighted or unweighted neutrinos + + void SetMaxEnergy (Double_t eMax) {fMaxEv = eMax;} + void SetMaxEvents(Int_t e){fmaxEvents = e;} + + GenieFluxDriver& operator=(const GenieFluxDriver& gf); + +protected: + virtual void CalculateNext4Momentum(Double_t energyOfNeutrino); + virtual void CalculateNext4position(); + + virtual void InitPDGList(void); + virtual void InitDetectorParams(const char* configFile); + virtual void Init4Momentum(void); + virtual void Init4Position(void); + + virtual void ReadNuFluxFile(const char* fluxFile); + virtual void CalculateProbability(); + + /* Detector parameters */ + esbroot::geometry::superfgd::FgdDetectorParameters fdetectorParams; + + /* Uniform random number generators for neutrino flux calculations */ + std::mt19937 frndGen;//! fdis;//! fFlux;//! +#include +#include +#include + +//~ using namespace esbroot::generators; +namespace esbroot { +namespace generators { + +/*static*/ GenieGenerator::GlobalState_t GenieGenerator::GlobalState; +/*static*/ bool GenieGenerator::fGlobalStateInit = false; + +//! Constructor which takes user defined Genie flux and geometry drivers. +//! The Genie backend is not configured until a call to Configure() +//! @param fluxI user supplied Genie flux driver +//! @param geomI user supplied Genie geometry driver +GenieGenerator::GenieGenerator(genie::GFluxI *fluxI, genie::GeomAnalyzerI *geomI) { + SetFluxI(std::shared_ptr(fluxI)); + SetGeomI(std::shared_ptr(geomI)); +} + +//! Initializes the state of Genie backend using GenieGenerator::GlobalState variable. +//! Called automatically from Configure(). +/*static*/ void GenieGenerator::InitGlobalState() +{ + assert(fGlobalStateInit == false); + + auto xspl = genie::XSecSplineList::Instance(); + xspl->LoadFromXml(GlobalState.fXsecSplineFileName, false); + + genie::RunOpt::Instance()->SetTuneName(GlobalState.fGenieTune); + genie::RunOpt::Instance()->BuildTune(); + + // Clear content of previous file + if(!GlobalState.fOutputFileName.empty()) + { + std::ofstream outFile; + outFile.open(GlobalState.fOutputFileName, std::ios::trunc); + if(outFile.is_open()) + { + outFile.close(); + } + } + + fGlobalStateInit = true; +} + +//!This function actually initializes the Genie generator backend using +//!supplied geometry and flux drivers. Calls InitGlobalState(). +/*virtual*/ Bool_t GenieGenerator::Configure() +{ + assert(IsConfigured() == false); + + InitGlobalState(); + + fmcj_driver = std::make_shared(); + + fmcj_driver->UseFluxDriver(GetFluxI().get()); + fmcj_driver->UseGeomAnalyzer(GetGeomI().get()); + fmcj_driver->Configure(); + + fIsConfigured = true; + + return true; // No initialization checks done, return true +} + + +/*! Override the FairGenerator::ReadEvent: +* Reads the events from the genie::GMCJDriver +* instead of a passed in file. +*/ +/*virtual*/ Bool_t GenieGenerator::ReadEvent(FairPrimaryGenerator* primGen) +{ + //!Budimir: this function is not entirely correct. The vertex position is + //!always at (0,0,0). However, each track starts at the position + //!genie::EventRecord::Vertex() relative + //!to FairRoot's "vertex coordinate (0,0,0)", so in the end simulation works as required. + //!This is due to limitations of FairRoot. We can live with this for now, + //!but it definitely needs to be fixed in the future. + + Bool_t flaGkeepThrowing(true); // Flag to indicate when to stop generating events if there is a condition for the generated particles + + while(flaGkeepThrowing) + { + genie::EventRecord* event = fmcj_driver->GenerateEvent(); + if(event == nullptr) return false; + + PostProcessEvent(event); + + std::vector eventParticles; + + event->Print(std::cout); + TLorentzVector* v = event->Vertex(); + + // Fire other final state particles + int nParticles = event->GetEntries(); + for (int i = 0; i < nParticles; i++) + { + genie::GHepParticle *p = event->Particle(i); + // kIStStableFinalState - Genie documentation: generator-level final state + // particles to be tracked by the detector-level MC + if ((p->Status() == genie::EGHepStatus::kIStStableFinalState)) + { + if(IsPdgAllowed(p->Pdg())) + { + primGen->AddTrack(p->Pdg(), p->Px(), p->Py(), p->Pz(), v->X(), v->Y(), v->Z()); + eventParticles.push_back(p); + } + } + } + + flaGkeepThrowing = KeepThrowing(eventParticles); + + if(!GlobalState.fOutputFileName.empty()) + { + WriteToOutputFile(event, flaGkeepThrowing); + } + + delete event; + } + + + return true; +} + + +Bool_t GenieGenerator::IsPdgAllowed(int pdg) +{ + + // Workaround for GENIE bug (or "feature") that treats nuclear energy as trackable particle + if(pdg >= 2000000000) + { + return false; + } + + // If there are no codes to filter any valid pdg is allowed to be tracked + if(fpdgCodesAllowed.empty()) + { + return true; + } + + Bool_t isAllowed = std::find(fpdgCodesAllowed.begin(), fpdgCodesAllowed.end(), pdg) != fpdgCodesAllowed.end(); + return isAllowed; +} + +Bool_t GenieGenerator::KeepThrowing(std::vector& eventParticles ) +{ + // No implementation - decendent should decide + return false; +} + +void GenieGenerator::WriteToOutputFile(const genie::EventRecord* event, Bool_t flaGkeepThrowing ) +{ + // No implementation required in base class +} + +FairGenerator* GenieGenerator::CloneGenerator() const +{ + // Clone for worker (used in MT mode only) + // TODO: check that this actually works + return new GenieGenerator(*this); +} + +} +} diff --git a/EsbGenerators/GenieGenerator.h b/EsbGenerators/GenieGenerator.h new file mode 100644 index 0000000..81b3008 --- /dev/null +++ b/EsbGenerators/GenieGenerator.h @@ -0,0 +1,154 @@ +#ifndef ESBROOT_GENERATOR_GENIEGENERATOR_H +#define ESBROOT_GENERATOR_GENIEGENERATOR_H 1 + +//! @file EsbGenerators/GenieGenerator.h +//! @copyright ESSnuSB consortium. Released under GPLv3 . + +/* FairRoot headers */ +#include "FairGenerator.h" +#include "FairPrimaryGenerator.h" + +/* Genie framework classes and tools headers */ +#include "Framework/EventGen/GMCJDriver.h" +#include "Framework/EventGen/EventRecord.h" +#include "Tools/Flux/GMonoEnergeticFlux.h" +#include "Tools/Geometry/PointGeomAnalyzer.h" +#include "Tools/Geometry/ROOTGeomAnalyzer.h" + +#include + +//~ using namespace std; +//~ using namespace genie; +//~ using namespace genie::geometry; +//~ using namespace genie::flux; + +namespace esbroot { + +namespace generators { + +//! @brief Basic Genie generator class +//! +//! This class wraps Genie MC generator interface. It provides functionality to configure Genie global state +//! and to configure Genie generator backend using user provided Genie flux and geometry interfaces. +//! +//! It implements the FairGenerator::ReadEvent(FairPrimaryGenerator* primGen) function +//! which makes it usable within the FairRoot framework. +//! +//! @authors Budimir Kliček +//! @authors Georgi Petkov +//! @copyright ESSnuSB consortium. Released under GPLv3 (). +class GenieGenerator : public FairGenerator +{ + +public: + + static struct GlobalState_t { + std::string fGenieTune = ""; //!< Genie tune to be used + std::string fXsecSplineFileName = ""; //!< Path to XML file with GENIE cross sections + std::string fOutputFileName = ""; //!< Path to file used by genie generators if they want to write data output + long int fRandomSeed = -1; //!< Random seed for GENIE (NOT IMPLEMENTED YET) + } GlobalState; //!< Global state of Genie generator + + static void InitGlobalState(); //!< Initialize the state of Genie backend + + //! Empty constructor + GenieGenerator() {}; + + //! Basic constructor + GenieGenerator(genie::GFluxI *fluxI, genie::GeomAnalyzerI *geomI); + + //! Empty destructor + virtual ~GenieGenerator() {}; + + //Setters + //! Set Genie flux driver. Can't set if object already configured. + void SetFluxI(std::shared_ptr FluxI) {assert(IsConfigured() == false); fFluxI = FluxI;}; + //! Set Genie geometry driver. Can't set if object already configured. + void SetGeomI(std::shared_ptr GeomI) {assert(IsConfigured() == false); fGeomI = GeomI;}; + + //Getters + //! Get Genie flux driver + std::shared_ptr const& GetFluxI() const {return(fFluxI);}; + //! Get Genie geometry driver + std::shared_ptr const& GetGeomI() const {return(fGeomI);}; + + //!Method which initializes the Genie generator + + //!FairRoot runs this from FairRunSim::Init(). + //!Empty because we might want to init Genie after FairRunSim::Init() + //!e.g to pass the geometry + virtual Bool_t Init(void) {return true;}; + + //!Configure the Genie backend + virtual Bool_t Configure(); + + //!Check if Genie backend is configured + Bool_t IsConfigured() const {return fIsConfigured;}; + + //!Implementation of the base method which generates the vertex particles + virtual Bool_t ReadEvent(FairPrimaryGenerator* primGen); + + //!Method to post process the genie event record + virtual void PostProcessEvent(/*IN OUT*/ genie::GHepRecord* event) {}; + + /** Clone this object (used in MT mode only) */ + virtual FairGenerator* CloneGenerator() const; + + + void AddPdgCode(int pdg){fpdgCodesAllowed.push_back(pdg);} + void AddPdgCode(std::vector pdgCodes){fpdgCodesAllowed.insert(fpdgCodesAllowed.end(), pdgCodes.begin(), pdgCodes.end());} + void ClearPfgCodes(){fpdgCodesAllowed.clear();} + + +protected: + + //These static members are initialized in the .cxx file so that + //RootCint does not complain + //! Tracks if global state has been initialized + static bool fGlobalStateInit; + + //! Driver for generating neutrino events + //! NOTE: DO NOT remove the //! fmcj_driver;//! fFluxI;//! fGeomI;//! fpdgCodesAllowed;//!& eventParticles ); + + //!Write data from the event for further analysis if required + //! *@param event generated event + //! *@param flaGkeepThrowing flag indicating if this event is rejected and a new one will be generated + virtual void WriteToOutputFile(const genie::EventRecord* event, Bool_t flaGkeepThrowing ); + + ClassDef(GenieGenerator,6) +}; + +} //namespace generators + +} //namespace esbroot +#endif diff --git a/EsbGenerators/GenieNtpFluxV1.cxx b/EsbGenerators/GenieNtpFluxV1.cxx new file mode 100644 index 0000000..3189aef --- /dev/null +++ b/EsbGenerators/GenieNtpFluxV1.cxx @@ -0,0 +1,88 @@ +#include "EsbGenerators/GenieNtpFluxV1.h" + +#include +#include +#include + +#include +#include + +namespace esbroot { +namespace generators { + +GenieNtpFluxV1::GenieNtpFluxV1(TTree *in_tree, int pdg_code, + esbroot::geometry::CoordinateSystem const& TSCS, + esbroot::geometry::CoordinateSystem const& DTCS +) : fInTree(in_tree), fCurrIndex(0), fTSCS(TSCS), fDTCS(DTCS) +{ + fFluxParticles.push_back(pdg_code); + ConnectTree(); + fMaxEnergy = FindMaxEnergy(); +} + +GenieNtpFluxV1::GenieNtpFluxV1( + const char* file_name, + const char* tree_name, + int pdg_code, + esbroot::geometry::CoordinateSystem const& TSCS, + esbroot::geometry::CoordinateSystem const& DTCS +) : fInFile(file_name), fCurrIndex(0), fTSCS(TSCS), fDTCS(DTCS) +{ + fInFile.GetObject(tree_name, fInTree); + assert(fInTree != nullptr); + + fFluxParticles.push_back(pdg_code); + ConnectTree(); + fMaxEnergy = FindMaxEnergy(); +} + + +/*virtual*/ bool GenieNtpFluxV1::GenerateNext(void) /*override*/ +{ + if(End()) return false; + fInTree->GetEntry(fCurrIndex); + + TVector3 mom(fPx, fPy, fPz); + mom = esbroot::geometry::cstransforms::l2l_vec(mom, fTSCS, fDTCS); + + TVector3 pos(fX , fY, fZ); + pos = esbroot::geometry::cstransforms::l2l_pos(pos, fTSCS, fDTCS); + //pos *= 1.0/100.0; //Genie wants SI units for coordinates + + fMomentum.SetVect(mom); + fMomentum.SetT(TMath::Sqrt(fPx*fPx + fPy*fPy + fPz*fPz)); + + fPosition.SetVect(pos); + fPosition.SetT(0.0); + + std::cout << " X " << pos.X() << " Y " << pos.Y()<< " Z " << pos.Z() << std::endl; + + ++fCurrIndex; + return(true); +} + +void GenieNtpFluxV1::ConnectTree() +{ + fInTree->SetBranchAddress("Xp", &fX); + fInTree->SetBranchAddress("Yp", &fY); + fInTree->SetBranchAddress("Zp", &fZ); + + fInTree->SetBranchAddress("Pxp", &fPx); + fInTree->SetBranchAddress("Pyp", &fPy); + fInTree->SetBranchAddress("Pzp", &fPz); +} + +double GenieNtpFluxV1::FindMaxEnergy() +{ + double max_e = -HUGE_VAL; + + for(long int a = 0; a < fInTree->GetEntries(); ++a) { + fInTree->GetEntry(a); + double e = TMath::Sqrt(fPx*fPx + fPy*fPy + fPz*fPz); + if(e > max_e) max_e = e; + } + return(max_e); +} + +} +} diff --git a/EsbGenerators/GenieNtpFluxV1.h b/EsbGenerators/GenieNtpFluxV1.h new file mode 100644 index 0000000..1b0ef99 --- /dev/null +++ b/EsbGenerators/GenieNtpFluxV1.h @@ -0,0 +1,91 @@ +#ifndef ESBROOT_GENERATOR_GENIENTPFLUXV1_H +#define ESBROOT_GENERATOR_GENIENTPFLUXV1_H + +//EsbRoot includes +#include "EsbGeometry/CoordinateSystem.h" + +//GENIE includes +#include +#include + +//ROOT includes +#include +#include +#include + +//STD includes +#include + +//This class reads files available at: +// https://essnusb.eu/DocDB/private/ShowDocument?docid=342 + +namespace esbroot { +namespace generators { + +class GenieNtpFluxV1 : public genie::GFluxI +{ + public: + GenieNtpFluxV1( + TTree *in_tree, + int pdg_code, + esbroot::geometry::CoordinateSystem const& TSCS, + esbroot::geometry::CoordinateSystem const& DTCS + ); + + GenieNtpFluxV1( + const char* file_name, + const char* tree_name, + int pdg_code, + esbroot::geometry::CoordinateSystem const& TSCS, + esbroot::geometry::CoordinateSystem const& DTCS + ); + + virtual ~GenieNtpFluxV1() {}; + + virtual const genie::PDGCodeList& FluxParticles(void) override {return fFluxParticles;}; ///< declare list of flux neutrinos that can be generated (for init. purposes) + virtual double MaxEnergy(void) override {return fMaxEnergy;}; ///< declare the max flux neutrino energy that can be generated (for init. purposes) + virtual bool GenerateNext(void) override; ///< generate the next flux neutrino (return false in err) + virtual int PdgCode(void) override {return(fFluxParticles.front());}; ///< returns the flux neutrino pdg code + virtual double Weight(void) override {return(1.0);}; ///< returns the flux neutrino weight (if any) + virtual const TLorentzVector& Momentum(void) override {return(fMomentum);}; ///< returns the flux neutrino 4-momentum + virtual const TLorentzVector& Position(void) override {return(fPosition);}; ///< returns the flux neutrino 4-position (note: expect SI rather than physical units) + virtual bool End(void) override {return(fCurrIndex == fInTree->GetEntries());}; ///< true if no more flux nu's can be thrown (eg reaching end of beam sim ntuples) + virtual long int Index(void) override {return(fCurrIndex);}; ///< returns corresponding index for current flux neutrino (e.g. for a flux ntuple returns the current entry number) + virtual void Clear(Option_t * opt) override { fCurrIndex = 0; }; ///< reset state variables based on opt + virtual void GenerateWeighted(bool gen_weighted) override {}; ///< set whether to generate weighted or unweighted neutrinos + + protected: + void ConnectTree(); + double FindMaxEnergy(); + + private: + TFile fInFile; //In case the class opens the file itself + + TTree *fInTree = nullptr; + long int fCurrIndex = -1; //Curent tree entry + + genie::PDGCodeList fFluxParticles; + double fMaxEnergy = std::nan("ni"); + + //Definition of Target Station CS + esbroot::geometry::CoordinateSystem fTSCS; + //Definition of Detector CS + esbroot::geometry::CoordinateSystem fDTCS; + + //Vertex coordinates (TSCS), to be connected to tree + float fX = std::nan("ni"), fY = std::nan("ni"), fZ = std::nan("ni"); + //Momentum coordinates (TSCS), to be connected to tree + float fPx = std::nan("ni"), fPy = std::nan("ni"), fPz = std::nan("ni"); + + //Momentum DTCS + TLorentzVector fMomentum; + //Position DTCS + TLorentzVector fPosition; + + ClassDef(GenieNtpFluxV1, 2) +}; + +} +} + +#endif diff --git a/EsbGenerators/README.md b/EsbGenerators/README.md deleted file mode 100644 index 3af424a..0000000 --- a/EsbGenerators/README.md +++ /dev/null @@ -1 +0,0 @@ -This directory contains ESSnuSB interaction generators, i.e. implementations of FairGenerator abstract class. Pythia generators are left as an example. diff --git a/EsbGenerators/ROOTGeomGenieGenerator.cxx b/EsbGenerators/ROOTGeomGenieGenerator.cxx new file mode 100644 index 0000000..404ab36 --- /dev/null +++ b/EsbGenerators/ROOTGeomGenieGenerator.cxx @@ -0,0 +1,32 @@ +#include "EsbGenerators/ROOTGeomGenieGenerator.h" + +namespace esbroot{ +namespace generators{ + ROOTGeomGenieGenerator::ROOTGeomGenieGenerator(int pdg_nu, double e_nu, TGeoManager* geom, std::string top_vol_name) + { + auto mono_flux = std::make_shared(e_nu, pdg_nu); + SetFluxI(std::move(mono_flux)); + + fGeom = geom; + fTopVolumeName = top_vol_name; + } + + Bool_t ROOTGeomGenieGenerator::LateInit() { + fOrigTopVolume = fGeom->GetTopVolume(); + auto root_geom = std::make_shared(fGeom); + root_geom->SetTopVolName(fTopVolumeName); + Configure(); + fTopVolume = fGeom->GetTopVolume(); + fGeom->SetTopVolume(fTopVolume); + + return(true); + } + + /* virtual */ Bool_t ROOTGeomGenieGenerator::ReadEvent(FairPrimaryGenerator* primGen) { + fGeom->SetTopVolume(fTopVolume); + GenieGenerator::ReadEvent(primGen); + fGeom->SetTopVolume(fOrigTopVolume); + } + +} +} diff --git a/EsbGenerators/ROOTGeomGenieGenerator.h b/EsbGenerators/ROOTGeomGenieGenerator.h new file mode 100644 index 0000000..e91c78d --- /dev/null +++ b/EsbGenerators/ROOTGeomGenieGenerator.h @@ -0,0 +1,37 @@ +#ifndef ESBROOT_GENERATOR_ROOTGEOMGENIEGENERATOR_H +#define ESBROOT_GENERATOR_ROOTGEOMGENIEGENERATOR_H + +#include "EsbGenerators/GenieGenerator.h" + +#include + +#include +#include + +namespace esbroot{ +namespace generators{ + +class ROOTGeomGenieGenerator : public GenieGenerator +{ + public: + ROOTGeomGenieGenerator(int pdg_nu, double e_nu, TGeoManager* geom, std::string top_vol); + + virtual Bool_t ReadEvent(FairPrimaryGenerator* primGen); + + Bool_t LateInit(); + + private: + TGeoManager* fGeom; + std::string fTopVolumeName; + std::string fOrigTopVolumeName; + + TGeoVolume *fTopVolume; + TGeoVolume *fOrigTopVolume; + + ClassDef(ROOTGeomGenieGenerator, 2); +}; + +} +} + +#endif diff --git a/EsbGenerators/SimpleGenieGenerator.cxx b/EsbGenerators/SimpleGenieGenerator.cxx new file mode 100644 index 0000000..32f0c53 --- /dev/null +++ b/EsbGenerators/SimpleGenieGenerator.cxx @@ -0,0 +1,31 @@ +#include "EsbGenerators/SimpleGenieGenerator.h" + +namespace esbroot { +namespace generators { + +//! @param[in] pdg_tgt PDG code of the target +//! @param[in] pdg_nu PDG code of neutrino +//! @param[in] e_nu Energy of neutrino (GeV) +//! @param[in] dir_nu Direction of incoming neutrino (normalization of this vector does not matter) +//! @param[in] x4_nu 4-position of neutrino interaction vertex (cm) +SimpleGenieGenerator::SimpleGenieGenerator(int pdg_tgt, int pdg_nu, double e_nu, + TVector3 const& dir_nu, TLorentzVector const& x4_nu) : GenieGenerator(), fVertexX4(x4_nu) +{ + auto mono_flux = std::make_shared(e_nu, pdg_nu); + mono_flux->SetDirectionCos(dir_nu.X(), dir_nu.Y(), dir_nu.Z()); + SetFluxI(std::move(mono_flux)); + + SetGeomI(std::make_shared(pdg_tgt)); +} + +//! @bug This if to be considered quick&dirty implementation. +/*virtual*/ void SimpleGenieGenerator::PostProcessEvent(/*IN OUT*/ genie::GHepRecord* event) +{ + TLorentzVector* v = event->Vertex(); //TODO: each track has its own origin + + *v += fVertexX4; + event->SetVertex(*v); +} + +} +} diff --git a/EsbGenerators/SimpleGenieGenerator.h b/EsbGenerators/SimpleGenieGenerator.h new file mode 100644 index 0000000..98412e1 --- /dev/null +++ b/EsbGenerators/SimpleGenieGenerator.h @@ -0,0 +1,48 @@ +#ifndef ESBROOT_GENERATOR_SIMPLEGENIEGENERATOR_H +#define ESBROOT_GENERATOR_SIMPLEGENIEGENERATOR_H + +#include "EsbGenerators/GenieGenerator.h" + +#include + +class TVector3; +class TLorentzVector; + +namespace esbroot { +namespace generators { + +//! @brief Generates monoenergetic neutrino interactions on a single target material +//! +//! Generates interaction vertices of a single species of neutrino with a specified +//! energy and on a target which composes of a single isotope. Meant to be used as an example +//! and for debugging of the detector simulation. +//! +//! @authors Budimir Kliček +//! @copyright ESSnuSB consortium (). Released under GPLv3 (). +class SimpleGenieGenerator : public GenieGenerator +{ + public: + //! Empty constructor + SimpleGenieGenerator(): GenieGenerator() {}; + + //! Basic constructor + SimpleGenieGenerator(int pdg_tgt, int pdg_nu, double e_nu, + TVector3 const& dir_nu, TLorentzVector const& x4_nu); + + //! Implementation of GenieGenerator::Init() which calls the Configure() function. + virtual Bool_t Init() {return(Configure());}; + + //! Post processes Genie events to choose vertex position + virtual void PostProcessEvent(/*IN OUT*/ genie::GHepRecord* event); + + private: + //! 4-position of neutrino interaction vertex + TLorentzVector fVertexX4 = {std::nan("ni"), std::nan("ni"), std::nan("ni"), std::nan("ni")}; + + ClassDef(SimpleGenieGenerator,2) +}; + +} +} + +#endif diff --git a/EsbGeometry/CMakeLists.txt b/EsbGeometry/CMakeLists.txt index defe781..5e40c08 100644 --- a/EsbGeometry/CMakeLists.txt +++ b/EsbGeometry/CMakeLists.txt @@ -10,37 +10,56 @@ # The extension is already found. Any number of sources could be listed here. set(INCLUDE_DIRECTORIES -${BASE_INCLUDE_DIRECTORIES} -#put here all directories where header files are located -${CMAKE_SOURCE_DIR} -#${CMAKE_SOURCE_DIR}/EsbGeometry -#${CMAKE_SOURCE_DIR}/EsbData -#${CMAKE_SOURCE_DIR}/esb + ${BASE_INCLUDE_DIRECTORIES} + #put here all directories where header files are located + ${CMAKE_SOURCE_DIR} + #${CMAKE_SOURCE_DIR}/EsbGeometry + #${CMAKE_SOURCE_DIR}/EsbData + #${CMAKE_SOURCE_DIR}/esb + ${CLHEP_INCLUDE_DIR} + $ENV{GENIE}/src ) include_directories(${INCLUDE_DIRECTORIES}) include_directories(${SYSTEM_INCLUDE_DIRECTORIES}) set(LINK_DIRECTORIES -${ROOT_LIBRARY_DIR} -${FAIRROOT_LIBRARY_DIR} + ${ROOT_LIBRARY_DIR} + ${FAIRROOT_LIBRARY_DIR} + ${CLHEP_LIB_DIR} + $ENV{GENIE}/lib ) link_directories( ${LINK_DIRECTORIES}) set(SRCS -#Put here your sourcefiles -WCDetector.cxx -Cave.cxx -GeoCave.cxx -PMTube.cxx + #Put here your sourcefiles + WCDetector.cxx + Cave.cxx + GeoCave.cxx + PMTube.cxx + CoordinateSystem.cxx + OnAxisCS.cxx + FgdDetector.cxx + EsbSuperFGD/EsbCubeScintilatorConstructor.cxx + EsbSuperFGD/EsbSuperFGDConstructor.cxx + EsbSuperFGD/EsbSuperFGDDetectorConstruction.cxx + EsbSuperFGD/EsbFgdDetectorParameters.cxx ) Set(HEADERS + ${CMAKE_SOURCE_DIR}/EsbGeometry/OnAxisCS.h + ${CMAKE_SOURCE_DIR}/EsbGeometry/CoordinateSystem.h ${CMAKE_SOURCE_DIR}/EsbGeometry/WCDetector.h ${CMAKE_SOURCE_DIR}/EsbGeometry/Cave.h ${CMAKE_SOURCE_DIR}/EsbGeometry/GeoCave.h ${CMAKE_SOURCE_DIR}/EsbGeometry/PMTube.h + ${CMAKE_SOURCE_DIR}/EsbGeometry/FgdDetector.h + ${CMAKE_SOURCE_DIR}/EsbGeometry/EsbSuperFGD/EsbCubeScintilatorConstructor.h + ${CMAKE_SOURCE_DIR}/EsbGeometry/EsbSuperFGD/EsbSuperFGDConstructor.h + ${CMAKE_SOURCE_DIR}/EsbGeometry/EsbSuperFGD/EsbSuperFGDDetectorConstruction.h + ${CMAKE_SOURCE_DIR}/EsbGeometry/EsbSuperFGD/EsbFgdDetectorParameters.h + ${CMAKE_SOURCE_DIR}/EsbGeometry/EsbSuperFGD/Materials.h ) Set(LINKDEF ${CMAKE_SOURCE_DIR}/EsbGeometry/GeometryLinkDef.h) diff --git a/EsbGeometry/CoordinateSystem.cxx b/EsbGeometry/CoordinateSystem.cxx new file mode 100644 index 0000000..0f52eec --- /dev/null +++ b/EsbGeometry/CoordinateSystem.cxx @@ -0,0 +1,52 @@ +#include "EsbGeometry/CoordinateSystem.h" + +#include + +#include +#include + +namespace esbroot { +namespace geometry { + +//Budimir: is this function standard somewhere in ROOT? +inline static bool EqErr(double lhs, double rhs, double err) +{ + return( std::abs(lhs-rhs) < err ); +} + +/* static */ bool CoordinateSystem::IsProperRotation(ROOT::Math::Rotation3D const& rotation,double delta) +{ + using SMatrix33 = ROOT::Math::SMatrix; + + SMatrix33 rot; + rotation.GetRotationMatrix(rot); + + double det; + int det_status = rot.Det2(det); + + //Is determinant == 1? + if(!(det_status == 1 && EqErr(det, 1.0, delta) )) return(false); + + //Is transpose*rot == 1? + SMatrix33 zero_cand = (rot*ROOT::Math::Transpose(rot)) - SMatrix33(ROOT::Math::SMatrixIdentity()); + for(auto elem : zero_cand) { + if( !EqErr(elem, 0.0, delta) ) { + return(false); + } + } + + return(true); +} + +void CoordinateSystem::IsProperOrDie() const { + if( !IsProperRotation(GetRotation(), fFloatDelta) ) { + std::cerr << "FATAL: (" << __PRETTY_FUNCTION__ + << ") Attempting to create CoordinateSystem object with a matrix which is not a proper rotation. Aborting." + << std::endl; + std::exit(1); + } +} + + +} //namespace geometry +} //namespace esbroot diff --git a/EsbGeometry/CoordinateSystem.h b/EsbGeometry/CoordinateSystem.h new file mode 100644 index 0000000..cb3efe6 --- /dev/null +++ b/EsbGeometry/CoordinateSystem.h @@ -0,0 +1,152 @@ +#ifndef ESBROOT_ESBGEOMETRY_COORDINATESYSTEM_H +#define ESBROOT_ESBGEOMETRY_COORDINATESYSTEM_H + +#include "Math/GenVector/Rotation3D.h" +#include "Math/Vector3D.h" + +#include "TObject.h" +#include "Rtypes.h" + +namespace esbroot { +namespace geometry { + +//! @brief Class which defines ESSnuSB coordinate system +//! +//! This class contains the rotation and translation part of the ESSnuSB +//! coordinate system definition described in https://essnusb.eu/DocDB/private/ShowDocument?docid=102 +//! version v3. It is used by static functions of cstransforms class to transform +//! vectors and positions from one CS to another. +//! +//! The class automatically checks that the supplied matrix is an element of proper +//! orthonormal group. +class CoordinateSystem : public TObject +{ + public: + //!Empty constructor for ROOT I/O + CoordinateSystem() {}; + + //! Basic constructor + template + CoordinateSystem(Matrix_t const& rot, Vector_t const& vec, double float_delta = 1e-6) : + fRotation(rot), fInverseRotation(rot.Inverse()), fTranslation(vec), + fFloatDelta(float_delta) {IsProperOrDie();} + + //! Empty virtual destructor + virtual ~CoordinateSystem() {}; + + //! Get rotation matrix + ROOT::Math::Rotation3D const& GetRotation() const {return(fRotation);} + //! Get inverse rotation matrix + ROOT::Math::Rotation3D const& GetInverseRotation() const {return(fInverseRotation);} + + //! Get translation vector + ROOT::Math::XYZVector const& GetTranslation() const {return(fTranslation);} + + //! Static function which checks whether the matrix is a proper rotation + static bool IsProperRotation(ROOT::Math::Rotation3D const& rotation, double delta); + + protected: + //! Function which terminates the program if rotation is not proper. + void IsProperOrDie() const; + + private: + //! Rotation matrix + ROOT::Math::Rotation3D fRotation; + //! Inverse of rotation matrix + ROOT::Math::Rotation3D fInverseRotation; + + //! Translation vector + ROOT::Math::XYZVector fTranslation; + + //! @brief Delta when checking doubles for equality. + //! + //! Two doubles a and b are considered equal if |a - b| < delta. + double fFloatDelta = 1e-6; + + ClassDef(CoordinateSystem, 2) +}; + +//! @brief Coordinate system transformation functions +//! +//! This class contains static templated functions to transform vectors and +//! positions from one coordinate system to another. In principle, it should be +//! a namespace, but it is a class because of ROOT. +class cstransforms +{ + public: + //! @brief Local to global position transformation + //! + //! @tparam V Vector-like class which must have V::x(), V::y(), and V::z() functions + //! @param pos Position vector in LCS + //! @param lcs LCS definition + template + static V l2g_pos(V const& pos, CoordinateSystem lcs) + { + return( add_vec(lcs.GetRotation()*pos, lcs.GetTranslation()) ); + } + + //! @brief Global to local position transformation + //! + //! @tparam V Vector-like class which must have V::x(), V::y(), and V::z() functions + //! @param pos Position vector in GCS + //! @param lcs LCS definition + template + static V g2l_pos(V const& pos, CoordinateSystem lcs) + { + return( lcs.GetInverseRotation() * ( add_vec(pos, -lcs.GetTranslation()) ) ); + } + + //! @brief Local to local position transformation + //! + //! @tparam V Vector-like class which must have V::x(), V::y(), and V::z() functions + //! @param pos Position vector in LCS + //! @param lcs_src Definition of source LCS + //! @param lcs_dest Definition of destination LCS + template + static V l2l_pos(V const& pos, CoordinateSystem const& lcs_src, CoordinateSystem const& lcs_dest) + { + return( lcs_dest.GetInverseRotation() * + add_vec(add_vec(lcs_src.GetRotation()*pos, lcs_src.GetTranslation()), -lcs_dest.GetTranslation()) ); + } + + //! Local to global vector transformation + template + static V l2g_vec(V const& pos, CoordinateSystem lcs) + { + return( lcs.GetRotation()*pos ); + } + + //! Global to local vector transformation + template + static V g2l_vec(V const& pos, CoordinateSystem lcs) + { + return( lcs.GetInverseRotation() * pos ); + } + + //! Local to local vector transformation + template + static V l2l_vec(V const& pos, CoordinateSystem const& lcs_src, CoordinateSystem const& lcs_dest) + { + return( (lcs_dest.GetInverseRotation() * lcs_src.GetRotation()) * pos ); + } + + + private: + //! @brief Template to add two vectors. + //! + //! @tparam V1 Vector-like class which needs to have defined + //! - Constructor accepting 3 coordinates V1::V1(x, y, z) + //! - V1::x(), V1::y(), and V1::z() functions + //! @tparam V2 Vector-like class which needs to have V1::x(), V1::y(), and V1::z() functions + template + static V1 add_vec(V1 const& v1, V2 const& v2) + { + return( V1(v1.x() + v2.x(), v1.y() + v2.y(), v1.z() + v2.z()) ); + } + +}; + +} //namespace geometry +} //namespace esbroot + +#endif //ESBROOT_ESBGEOMETRY_COORDINATESYSTEM_H diff --git a/EsbGeometry/EsbSuperFGD/EsbConfig/fgdconfig b/EsbGeometry/EsbSuperFGD/EsbConfig/fgdconfig new file mode 100644 index 0000000..c641cdc --- /dev/null +++ b/EsbGeometry/EsbSuperFGD/EsbConfig/fgdconfig @@ -0,0 +1,56 @@ +#Lenght is given in dimetion of meters [cm] +#for cube all should have the same value!!! +length_X=1 +length_Y=1 +length_Z=1 + +#number of cubes +number_cubes_X=100 +number_cubes_Y=100 +number_cubes_Z=100 + +#magnetic field [1 kGauss = 0.1 T] +magField_X=0 #in [kG] +magField_Y=10 #in [kG] +magField_Z=0 #in [kG] + +#visualization +visdetail=0 #1 is for true + +# Settings for PATHFINDER desy package +# Please refer to the PATHFINDER documentation for more detail explanation of the below settings +use_vertex=0 +vertexX=0 +vertexY=0 +maxdistxy=2 +maxdistsz=2 +maxdistxyfit=1.5 +maxdistszfit=1.5 +minhitnumber=15 +xythetabins=1000 +xyd0bins=1000 +xyomegabins=300 +szthetabins=1000 +szd0bins=1000 +searchneighborhood=0 + +# setting for lower photon limit +errPhotoLimit=0 + +#exclude tracks below minimum track Lenght +min_track_lenght=15 + +# The belog settings for graph traversal + +# The grad in angle is calculated as the angle between two vectors. +# 1st vector is the vector distance between 2 cubes at gradDist apart +# 2nd vector is the vector distance between 2 cubes shifter gradIntervalDist number of cubes from the 1st one +gradDist=6 # Distance in number of cubes for track to calculate the grad +gradIntervalDist=3 # Interval between two distance vectors to calculate grad +gradDiff=25 # Allowable difference between grad to consider a different track + +# Calculate momentum from the segment with length 'momTrackSegment' by averaging the calculated momentum from 3 points (the 1st of the segment, +# the second and for each point in between). Since the are energy losses and the momentum decreases, take the particle momentum from as the average from the +# first'avgTrackMomentum' points +momTrackSegment=11 +avgTrackMomentum=5 diff --git a/EsbGeometry/EsbSuperFGD/EsbCubeScintilatorConstructor.cxx b/EsbGeometry/EsbSuperFGD/EsbCubeScintilatorConstructor.cxx new file mode 100644 index 0000000..b665006 --- /dev/null +++ b/EsbGeometry/EsbSuperFGD/EsbCubeScintilatorConstructor.cxx @@ -0,0 +1,216 @@ + #include "EsbGeometry/EsbSuperFGD/EsbCubeScintilatorConstructor.h" +#include "EsbGeometry/EsbSuperFGD/EsbSuperFGDConstructor.h" + +#include "EsbGeometry/EsbSuperFGD/EsbFgdDetectorParameters.h" +#include "EsbGeometry/EsbSuperFGD/Materials.h" +#include "EsbGeometry/EsbSuperFGD/Names.h" + +#include "TGeoBBox.h" +#include "TGeoCone.h" +#include "TGeoCompositeShape.h" + +namespace esbroot { +namespace geometry { +namespace superfgd { + +CubeScintConstructor::CubeScintConstructor() : fLength(0.), fBase(0.), fHeight(0.), fHoleRadius(0.) + , fHolePositionX(0.,0.,0.), fHolePositionY(0.,0.,0.), fHolePositionZ(0.,0.,0.) + , fHoleRotX(0.,0.,0.), fHoleRotY(0.,0.,0.), fHoleRotZ(0.,0.,0.) + , fCoatingThickness(0.), fGap(0.), fIsVisible(false), fCoatingMaterial("") + , fScintillatorMaterial(""), fUseFGDScint(false), fFiberMaterial(""), fFiberRadius(0.) + , fcubeTVol(nullptr), fcubeScntVol(nullptr) +{ +} + +CubeScintConstructor::~CubeScintConstructor() +{ +} + + +TGeoVolume* CubeScintConstructor::Construct() +{ + // Base is X direction + // Height is Y direction + // Lenght is Z direction + using namespace esbroot::geometry::superfgd; + + // The Box shape from which the holes for the fiber will be subtracted + TGeoBBox* cubeWithCoating = new TGeoBBox("CubeCoating",GetBase()/2, GetHeight()/2, GetLength()/2); + + // The Box shape from which the holes for the fiber will be subtracted + double coatingThickness = GetCoatingThickness(); // coating thickness in cm (root default length dimention) + TGeoBBox* cube = new TGeoBBox("Cube", + GetBase()/2 - coatingThickness, + GetHeight()/2 - coatingThickness, + GetLength()/2 - coatingThickness); + + + + TGeoMedium *tiO2 = gGeoManager->GetMedium(materials::titaniumDioxide); + TGeoMedium *c8H8 = gGeoManager->GetMedium(materials::polystyrene); + + TGeoMixture *scintillatorCoating = new TGeoMixture(materials::scintillatorCoating,2, 1.164); + scintillatorCoating->AddElement(tiO2->GetMaterial(), 0.15); + scintillatorCoating->AddElement(c8H8->GetMaterial(), 0.85); + TGeoMedium* coatingMedium = new TGeoMedium("coatingMedium", materials::GetNextIndex(), scintillatorCoating); + + //======================================================================================= + // Create the fiber hole along X + //----------------------------------- + TGeoCone* fiberHoleX = new TGeoCone("FX", GetBase()/2, 0, GetHoleRadius(),0 ,GetHoleRadius()); + + TGeoRotation* rotX = new TGeoRotation("rotX", + fHoleRotX.rotateX, + fHoleRotX.rotateY, + fHoleRotX.rotateZ); + rotX->RegisterYourself(); + + TGeoCombiTrans* locationX = new TGeoCombiTrans("locationX", + fHolePositionX.X, + fHolePositionX.Y, + fHolePositionX.Z, + rotX); + locationX->RegisterYourself(); + + // Create the fiber shape - the fiber shape is the contained within the fiber coating + TGeoCone* fiberShapeX = new TGeoCone("fiberShapeX", GetBase()/2, 0, GetFiberRadius(),0 ,GetFiberRadius()); + + // Create the fiber coating-> this is the hole minus the fiber itself + TGeoCompositeShape* fiberXShapeCoat = new TGeoCompositeShape("fiberXShapeCoat","FX - fiberShapeX"); + + // Create fiber coating + TGeoVolume* fiberXCoatVolume = new TGeoVolume("fiberXCoatVolume",fiberXShapeCoat, gGeoManager->GetMedium(materials::fiberCladding)); + + // Create fiber core volume + TGeoVolume* fiberXVolume = new TGeoVolume("fiberXVolume",fiberShapeX, gGeoManager->GetMedium(materials::fiberCore)); + + // Place the fiber core inside its coating + fiberXCoatVolume->AddNode(fiberXVolume, 1 /* One copy*/); + + //----------------------------------- + //======================================================================================= + + //======================================================================================= + // Create the fiber hole along Y + //----------------------------------- + TGeoCone* fiberHoleY = new TGeoCone("FY", GetHeight()/2, 0, GetHoleRadius(),0 ,GetHoleRadius()); + + TGeoRotation* rotY = new TGeoRotation("rotY", + fHoleRotY.rotateX, + fHoleRotY.rotateY, + fHoleRotY.rotateZ); + rotY->RegisterYourself(); + + TGeoCombiTrans* locationY = new TGeoCombiTrans("locationY", + fHolePositionY.X, + fHolePositionY.Y, + fHolePositionY.Z, + rotY); + locationY->RegisterYourself(); + + // Create the fiber shape - the fiber shape is the contained within the fiber coating + TGeoCone* fiberShapeY = new TGeoCone("fiberShapeY", GetHeight()/2, 0, GetFiberRadius(),0 ,GetFiberRadius()); + + // Create the fiber coating-> this is the hole minus the fiber itself + TGeoCompositeShape* fiberYShapeCoat = new TGeoCompositeShape("fiberYShapeCoat","FY - fiberShapeY"); + + // Create fiber coating + TGeoVolume* fiberYCoatVolume = new TGeoVolume("fiberYCoatVolume",fiberYShapeCoat, gGeoManager->GetMedium(materials::fiberCladding)); + + // Create fiber core volume + TGeoVolume* fiberYVolume = new TGeoVolume("fiberYVolume",fiberShapeY, gGeoManager->GetMedium(materials::fiberCore)); + + // Place the fiber core inside its coating + fiberYCoatVolume->AddNode(fiberYVolume, 1 /* One copy*/); + + //----------------------------------- + //======================================================================================= + + //======================================================================================= + // Create the fiber hole along Z + //----------------------------------- + TGeoCone* fiberHoleZ = new TGeoCone("FZ", GetLength()/2, 0, GetHoleRadius(),0 ,GetHoleRadius()); + + TGeoRotation* rotZ = new TGeoRotation("rotY", + fHoleRotZ.rotateX, + fHoleRotZ.rotateY, + fHoleRotZ.rotateZ); + rotZ->RegisterYourself(); + + TGeoCombiTrans* locationZ = new TGeoCombiTrans("locationZ", + fHolePositionZ.X, + fHolePositionZ.Y, + fHolePositionZ.Z, + rotZ); + locationZ->RegisterYourself(); + + + // Create the fiber shape - the fiber shape is the contained within the fiber coating + TGeoCone* fiberShapeZ = new TGeoCone("fiberShapeZ", GetLength()/2, 0, GetFiberRadius(),0 ,GetFiberRadius()); + + // Create the fiber coating-> this is the hole minus the fiber itself + TGeoCompositeShape* fiberZShapeCoat = new TGeoCompositeShape("fiberZShapeCoat","FZ - fiberShapeZ"); + + // Create fiber coating + TGeoVolume* fiberZCoatVolume = new TGeoVolume("fiberZCoatVolume",fiberZShapeCoat, gGeoManager->GetMedium(materials::fiberCladding)); + + // Create fiber core volume + TGeoVolume* fiberZVolume = new TGeoVolume("fiberZVolume",fiberShapeZ, gGeoManager->GetMedium(materials::fiberCore)); + + // Place the fiber core inside its coating + fiberZCoatVolume->AddNode(fiberZVolume, 1 /* One copy*/); + + //----------------------------------- + //======================================================================================= + + // Create scintilator cube shape + TGeoCompositeShape* cubeComp = new TGeoCompositeShape("cubeComp","Cube - FX:locationX - FY:locationY - FY:locationZ"); + + + // Define Scintilator mix + TGeoMedium *scnt = gGeoManager->GetMedium(materials::scintillator); + TGeoMedium *prt = gGeoManager->GetMedium(materials::paraterphnyl); + + TGeoMixture *scintillatorMixMat = new TGeoMixture(materials::scintilatorMix,2, 1.050); + scintillatorMixMat->AddElement(scnt->GetMaterial(), 0.985); + scintillatorMixMat->AddElement(prt->GetMaterial(), 0.015); + + TGeoMedium* scintillatorMixMedium = new TGeoMedium("scintillatorMixMat", materials::GetNextIndex(), scintillatorMixMat); + + + // Create the mother cube volume + TGeoMedium *vacuum = gGeoManager->GetMedium(materials::vacuum); + TGeoVolume* cubeWithCoatingVolume = new TGeoVolume(fgdnames::cubeName,cubeWithCoating, vacuum); + + // Place the coating + TGeoCompositeShape* coating = new TGeoCompositeShape("coating","CubeCoating - Cube - FX:locationX - FY:locationY - FY:locationZ"); + TGeoVolume* coatingVolume = new TGeoVolume(fgdnames::coatingVolume,coating, coatingMedium); + cubeWithCoatingVolume->AddNode(coatingVolume, 1 /* One Element*/ /*, Identity matrix is by default used for location*/); + + // Place the scintilator cube into the cube coating + TGeoVolume* cubeScntVol = new TGeoVolume(fgdnames::scintilatorVolume, cubeComp, scintillatorMixMedium); + fcubeScntVol = cubeScntVol; + // NOTE: using AddNodeOverlap may lead to exception when using materialInterface_->findNextBoundary + // in genfit::MaterialEffects::stepper + cubeWithCoatingVolume->AddNode(cubeScntVol, 1 /* One Element*/ /*, Identity matrix is by default used for location*/); + + // Place the fiber coatings with fiber core + // NOTE: using AddNodeOverlap may lead to exception when using materialInterface_->findNextBoundary + // in genfit::MaterialEffects::stepper + cubeWithCoatingVolume->AddNode(fiberXCoatVolume, 1 /* One Element*/, locationX); + cubeWithCoatingVolume->AddNode(fiberYCoatVolume, 1 /* One Element*/, locationY); + cubeWithCoatingVolume->AddNode(fiberZCoatVolume, 1 /* One Element*/, locationZ); + + fcubeTVol = cubeWithCoatingVolume; + return fcubeTVol; + + // NOTE: adding the volume with gGeoManager->AddVolume + // Causes segmentation fault later on in fairroot + // not a showstopper, but can lead to unexpected results + // Add the cube volume with coating to the list of the geoManager + //gGeoManager->AddVolume(cubeWithCoatingVolume); +} + +} //superfgd +} //geometry +} //esbroot \ No newline at end of file diff --git a/EsbGeometry/EsbSuperFGD/EsbCubeScintilatorConstructor.h b/EsbGeometry/EsbSuperFGD/EsbCubeScintilatorConstructor.h new file mode 100644 index 0000000..a032018 --- /dev/null +++ b/EsbGeometry/EsbSuperFGD/EsbCubeScintilatorConstructor.h @@ -0,0 +1,289 @@ +#ifndef ESBROOT_ESBGEOMETRY_SUPERFGD_CUBE_SCINTILATOR_CONSTRUCTION_H +#define ESBROOT_ESBGEOMETRY_SUPERFGD_CUBE_SCINTILATOR_CONSTRUCTION_H 1 + +#include "TObject.h" +#include "TGeoVolume.h" +#include "TGeoManager.h" +#include "TGeoMaterial.h" +#include "TGeoMedium.h" + +/// +/// This class is taken and adapted from /nd280mc/ND280ExtrudedScintConstructor +/// +/// Construct a cubic extruded scintillator cube. The cube +/// are constructed as rectangular bars with edges of same size +/// with the Z axis along the length of the bar, the base is +/// along the X axis, and the height along the Y axis. +/// +/// By default, the bars are made with polystyrene, and have "coextruded" +/// TiO2+Polystyrene outer coating. If the coating thickness can be set to +/// zero with SetCoatingThickness() but will still be constructed. The bars +/// have a hole for the fiber (default: 0.9 mm), and a fiber (default: 0.5 mm). +/// If the hole radius is less than the fiber radius then neither the fiber +/// nor the hole are constructed. +/// +/// NOTE: The geometry has been rewritten to use ROOT geometry classes + + +namespace esbroot { +namespace geometry { +namespace superfgd { + + struct ThreeVector{ + + ThreeVector():X(0),Y(0),Z(0) {} + + ThreeVector(double x, double y, double z):X(x),Y(y),Z(z) {} + + ~ThreeVector(){} + + double X; + double Y; + double Z; + }; + +struct RotMatrix{ + + RotMatrix():rotateX(0),rotateY(0),rotateZ(0) {} + + RotMatrix(double rotx, double roty, double rotz):rotateX(rotx),rotateY(roty),rotateZ(rotz) {} + + ~RotMatrix(){} + + double rotateX; + double rotateY; + double rotateZ; + }; + +class CubeScintConstructor : public TObject +{ + +public: + + /** Constructor **/ + CubeScintConstructor(); + + /** Destructor **/ + virtual ~CubeScintConstructor(); + + /** Get the length of the bar to be constructed. **/ + double GetLength(void) {return fLength;}; + + /** Set the length of the bar to be constructed. + *@param len - lenght + **/ + void SetLength(double len) {fLength = len;}; + + /** Get the base width of the extruded bar. **/ + double GetBase(void) {return fBase;}; + + /** Set the base width of the extruded bar. + *@param base - width + **/ + void SetBase(double base) {fBase = base;} + + /** Set the radius of the hole. + *@param radius - radius + **/ + void SetHoleRadius(double radius) {fHoleRadius = radius;}; + + /** Get the radius of the hole. **/ + double GetHoleRadius(void) {return fHoleRadius;}; + + /** Set the Fiber Hole position along X axis + *@param pos - position along X axis + **/ + void SetHolePosition_X(const ThreeVector& pos) {fHolePositionX = pos;}; + + /** Get the Fiber Hole position along X axis **/ + const ThreeVector& GetHolePosition_X(void) {return fHolePositionX;}; + + /** Set the Fiber Hole position along Y axis + *@param pos - position along Y axis + **/ + void SetHolePosition_Y(const ThreeVector& pos) {fHolePositionY = pos;}; + + /** Get the Fiber Hole position along Y axis **/ + const ThreeVector& GetHolePosition_Y(void) {return fHolePositionY;}; + + /** Set the Fiber Hole position along Z axis + *@param pos - position along Z axis + **/ + void SetHolePosition_Z(const ThreeVector& pos) {fHolePositionZ = pos;}; + + /** Get the Fiber Hole position along Z axis **/ + const ThreeVector& GetHolePosition_Z(void) {return fHolePositionZ;}; + + + /** Set the WLS fiber radius + *@param rad - radius + **/ + void SetFiberRadius(double rad){fFiberRadius = rad;}; + + /** Get the WLS fiber radius **/ + double GetFiberRadius(){return fFiberRadius;}; + + /** Set the WLS fiber material + *@param mat - material + **/ + void SetFiberMaterial(std::string mat){fFiberMaterial = mat;}; + + /** Get the WLS fiber material **/ + std::string GetFiberMaterial(){return fFiberMaterial;}; + + + /** Set rotation for the Fiber Hole along X axis + *@param rot - rotation along X axis + **/ + void SetHoleRot_X(const RotMatrix& rot) {fHoleRotX = rot;}; + /** Get rotation for the Fiber Hole along X axis **/ + RotMatrix GetHoleRot_X(void) {return fHoleRotX;}; + + /** Set rotation for the Fiber Hole along Y axis + *@param rot - rotation along Y axis + **/ + void SetHoleRot_Y(const RotMatrix& rot) {fHoleRotY = rot;}; + /** Get rotation for the Fiber Hole along Y axis **/ + RotMatrix GetHoleRot_Y(void) {return fHoleRotY;}; + + /** Set rotation for the Fiber Hole along Z axis + *@param rot - rotation along Z axis + **/ + void SetHoleRot_Z(const RotMatrix& rot) {fHoleRotZ = rot;}; + /** Get rotation for the Fiber Hole along Z axis **/ + RotMatrix GetHoleRot_Z(void) {return fHoleRotZ;}; + + + /** Get the thickness of the reflective coating.**/ + double GetCoatingThickness(void) {return fCoatingThickness;} + + /** Set the thickness of the reflective coating. + *@param t - thickness + **/ + void SetCoatingThickness(double t) {fCoatingThickness=t;} + + + /** Set the gap between the bars which corresponds to the space taken by + * whatever material is around the extrusion. E.G. This is the space + * taken by the glue that is holding the bars together. + *@param g - gap + **/ + void SetGap(double g) {fGap = g;}; + + /** Get the gap between the bars which corresponds to the space taken by + whatever material is around the extrusion. **/ + double GetGap(void) {return fGap;}; + + + /** Get the height of the extruded bar. The default value will be by a + call to SetBase(). **/ + double GetHeight(void) {return fHeight;}; + + /** Set the height of the extruded bar. + *@param height - height + **/ + void SetHeight(double height) { fHeight=height;}; + + + /** The name of the material to use for the scintillator coating. + * [Default: ScintillatorCoating] + *@param mat - coating material + **/ + void SetCoatingMaterial(const char* mat) {fCoatingMaterial = mat;} + /** Get the coating material **/ + const char* GetCoatingMaterial() const {return fCoatingMaterial.c_str();} + + /** The name of the material to use for the scintillator. + * [Default: ScintillatorCoating] + *@param mat - scintilator material + **/ + void SetScintillatorMaterial(const char* mat) {fScintillatorMaterial = mat;} + /** Get the scintilator material **/ + const char* GetScintillatorMaterial() const {return fScintillatorMaterial.c_str();} + + /** Set Geant4 visibility + *@param vis - visibility + **/ + void SetVisibility(bool vis) {fIsVisible = vis;} + + /** Get current visibility **/ + bool GetVisibility(void) {return false; /*fIsVisible;*/} + + /** Construct the TGeoVolume geometry for the cube **/ + TGeoVolume* Construct(void); + + /** Return a pointer to the cube geometry **/ + TGeoVolume* GetCubeVolume() {return fcubeTVol;} + + /** Return a pointer to the sensitive volume of the cube**/ + TGeoVolume* GetSensitiveVolume(){return fcubeScntVol;} + +private: + + /// The length of the scintillator bar. + double fLength; + + /// The width of the base of the scintillator. The base is along the X + /// axis. + double fBase; + + /// The height of the scintillator. If the bar is triangular this will be + /// calculated when the base is set, but may be overridden. + double fHeight; + + /// The radius of the hole. + double fHoleRadius; + + // Fiber Hole position along X, Y and Z axes + ThreeVector fHolePositionX; + ThreeVector fHolePositionY; + ThreeVector fHolePositionZ; + + // Rotation for the Fiber Hole along X, Y and Z axes + RotMatrix fHoleRotX; + RotMatrix fHoleRotY; + RotMatrix fHoleRotZ; + + /// The thickness of the material that is wrapping the scintillator (this + /// may be extruded). + double fCoatingThickness; + + /// The inner corner radius of the extruded wrapping for square FGD + /// scintillators + //double fCoatingRadius; + + /// Space outside of the bar to allow for glueing and mounting. + double fGap; + + /// Flag if the created bar should be set to visible for G4 visualization. + bool fIsVisible; + + /// The name of the material to use for the coating. + std::string fCoatingMaterial; + + /// The name of the material to use for the scintillator. + std::string fScintillatorMaterial; + + /// Flag if we want to use FGD scintillator material for this bar. + bool fUseFGDScint; + + /// The WLS fiber material + std::string fFiberMaterial; + + /// The WLS fiber radius + double fFiberRadius; + + //! pointer to the constructed cubeVolume + TGeoVolume* fcubeTVol; + + //! pointer to the scintilator (sensitive) volume of the cube + TGeoVolume* fcubeScntVol; + + ClassDef(CubeScintConstructor,2) +}; + +} //superfgd +} //geometry +} //esbroot + +#endif diff --git a/EsbGeometry/EsbSuperFGD/EsbFgdDetectorParameters.cxx b/EsbGeometry/EsbSuperFGD/EsbFgdDetectorParameters.cxx new file mode 100644 index 0000000..8b47aa2 --- /dev/null +++ b/EsbGeometry/EsbSuperFGD/EsbFgdDetectorParameters.cxx @@ -0,0 +1,100 @@ +#include "EsbGeometry/EsbSuperFGD/EsbFgdDetectorParameters.h" +#include "EsbGeometry/EsbSuperFGD/Materials.h" +#include + +#include "FairLogger.h" // for FairLogger, etc + +using namespace std; + +namespace esbroot { + +namespace geometry { + +namespace superfgd { + + +#define CHECK_PARAM(param) \ + if(!ExistsParam(paramName))\ + {\ + LOG(fatal) << "Parameter not found in map " << paramName;\ + throw paramName;\ + }\ + +// ----- Default constructor ------------------------------------------- +FgdDetectorParameters::FgdDetectorParameters(void) +{ +} +// ------------------------------------------------------------------------- + +// ----- Destructor ---------------------------------------------------- +FgdDetectorParameters::~FgdDetectorParameters(void) +{ +} +// ------------------------------------------------------------------------- + + +/* + Add all values from the file in format: + key = value; This will be easier for maintenance + if more values are required. +*/ +#include +void FgdDetectorParameters::LoadPartParams(string fullfilePathName) +{ + std::ifstream file(fullfilePathName); + std::string line; + while(std::getline(file,line)) + { + size_t indSep = line.find(DP::SEPERATOR); + if(indSep!=-1) + { + string key = line.substr(0,indSep); + indSep++; // the value is after the seperator + string value = line.substr(indSep,std::string::npos); + fparamsMap.emplace(key,value); + } + } +} + + +string FgdDetectorParameters::ParamAsString(const string& paramName) const +{ + CHECK_PARAM(paramName); + return fparamsMap[paramName]; +} + +Int_t FgdDetectorParameters::ParamAsInt(const string& paramName) const +{ + CHECK_PARAM(paramName); + std::string val = fparamsMap[paramName]; + return std::stoi(val); +} + +Bool_t FgdDetectorParameters::ParamAsBool(const string& paramName) const +{ + Int_t val = ParamAsInt(paramName); + return (val>0); +} + +Double_t FgdDetectorParameters::ParamAsDouble(const string& paramName) const +{ + CHECK_PARAM(paramName); + std::string val = fparamsMap[paramName]; + return std::stod(val); +} + +FgdDetectorParameters& FgdDetectorParameters::operator=(FgdDetectorParameters& newDp) +{ + SetParamsMap(newDp.GetParamsMap()); +}; + +Bool_t FgdDetectorParameters::ExistsParam(const string& paramName) const +{ + bool exists(false); + exists = (fparamsMap.find(paramName) != fparamsMap.end()); + return exists; +} + +} // superfgd +} // geometry +} // esbroot \ No newline at end of file diff --git a/EsbGeometry/EsbSuperFGD/EsbFgdDetectorParameters.h b/EsbGeometry/EsbSuperFGD/EsbFgdDetectorParameters.h new file mode 100644 index 0000000..0ced110 --- /dev/null +++ b/EsbGeometry/EsbSuperFGD/EsbFgdDetectorParameters.h @@ -0,0 +1,124 @@ +#ifndef ESBROOT_DATA_SUPERFGD_FGD_DETECTOR_PARAMETERS_H +#define ESBROOT_DATA_SUPERFGD_FGD_DETECTOR_PARAMETERS_H 1 + +#include "CLHEP/Units/SystemOfUnits.h" +#include "CLHEP/Units/PhysicalConstants.h" + +#include "TGeoManager.h" +#include +#include + +#include "TObject.h" + +using namespace std; + +namespace esbroot { + +namespace geometry { + +namespace superfgd { + + +namespace DP +{ + static const string length_X = "length_X"; + static const string length_Y = "length_Y"; + static const string length_Z = "length_Z"; + + static const string number_cubes_X = "number_cubes_X"; + static const string number_cubes_Y = "number_cubes_Y"; + static const string number_cubes_Z = "number_cubes_Z"; + + static const string visdetail = "visdetail"; + + static const string magField_X = "magField_X"; + static const string magField_Y = "magField_Y"; + static const string magField_Z = "magField_Z"; + + static const char SEPERATOR='='; + + static const string FGD_BRANCH = "EsbFgdDetectorPoint"; + static const string FGD_DETECTOR_NAME = "EsbFgdDetector"; + static const string FGD_HIT = "FgdHit"; + static const string FGD_BRANCH_FIT = "FgdGenFitBranch"; + static const string FGD_FIT_TRACK = "FgdGenFitTrack"; + + static const string FGD_MC_LEPTON_RECONSTRUCTION_TTREE = "FgdMCLeptonStatsReconstructionData"; + static const string FGD_MC_LEPTON_RECONSTRUCTION_BRANCH = "FgdMCLeptonStatsBranch"; + static const string FGD_MC_LEPTON_RECONSTRUCTION_ROOT_FILE = "FgdMCLeptonStatsRootFile"; + + static const string FGD_MIN_TRACK_LENGTH = "min_track_lenght"; + + static const string FGD_GRAD_DIST = "gradDist"; + static const string FGD_GRAD_INTERVAL_DIST = "gradIntervalDist"; + static const string FGD_GRAD_ALLOWABLE_DIFF = "gradDiff"; + + static const string FGD_TRACK_MOMENTUM_SEGMENT = "momTrackSegment"; + static const string FGD_INITIAL_TRACK_POINTS_MOMENTUM = "avgTrackMomentum"; + + static const string FGD_ERR_PHOTO_LIMIT = "errPhotoLimit"; + + static const string PF_USE_VERTEX = "use_vertex"; + static const string PF_VERTEXX = "vertexX"; + static const string PF_VERTEXY = "vertexY"; + static const string PF_MAXDISTXY = "maxdistxy"; + static const string PF_MAXDISTSZ = "maxdistsz"; + static const string PF_MAXDISTXYFIT = "maxdistxyfit"; + static const string PF_MAXDISTSZFIT = "maxdistszfit"; + static const string PF_MINHITNUMBER = "minhitnumber"; + static const string PF_XYTHETABINS = "xythetabins"; + + static const string PF_XYD0BINS = "xyd0bins"; + static const string PF_XYOMEGABINS = "xyomegabins"; + static const string PF_SZTHETABINS = "szthetabins"; + static const string PF_SZD0BINS = "szd0bins"; + static const string PF_SEACHINTHENEIGHBORHOOD = "searchneighborhood"; +} + +class FgdDetectorParameters : public TObject +{ +public: + /** Default constructor **/ + FgdDetectorParameters(); + + /** Destructor **/ + ~FgdDetectorParameters(); + + /** Read the detector parameters from file + *@param fullfilePathName - full path of the file + **/ + void LoadPartParams(string fullfilePathName); + + /** Return the dimentions used for the detector **/ + static Double_t GetLenghtUnit() {return 1.0; /* Default length unit in Root is in 'cm' */} + + /** Return the existing map parameter as std::string **/ + string ParamAsString(const string& paramName) const; + /** Return the existing map parameter as Int_t **/ + Int_t ParamAsInt( const string& paramName) const; + /** Return the existing map parameter as bool **/ + Bool_t ParamAsBool(const string& paramName) const; + /** Return the existing map parameter as Double_t **/ + Double_t ParamAsDouble( const string& paramName) const; + /** Check if parameters exists in the map **/ + Bool_t ExistsParam(const string& paramName) const; + + /** Return the existing parameters **/ + map& GetParamsMap() {return fparamsMap;} + /** Set the parameter map **/ + void SetParamsMap(const map& newMap){fparamsMap = newMap;} + + FgdDetectorParameters& operator=(FgdDetectorParameters& newDp); + +private: + + mutable map fparamsMap; + + ClassDef(FgdDetectorParameters,2) +}; + +} // superfgd +} // geometry +} // esbroot + +#endif diff --git a/EsbGeometry/EsbSuperFGD/EsbSuperFGDConstructor.cxx b/EsbGeometry/EsbSuperFGD/EsbSuperFGDConstructor.cxx new file mode 100644 index 0000000..bd0a751 --- /dev/null +++ b/EsbGeometry/EsbSuperFGD/EsbSuperFGDConstructor.cxx @@ -0,0 +1,125 @@ +#include "EsbGeometry/EsbSuperFGD/EsbSuperFGDConstructor.h" +#include "EsbGeometry/EsbSuperFGD/EsbCubeScintilatorConstructor.h" +#include "EsbGeometry/EsbSuperFGD/EsbFgdDetectorParameters.h" +#include "EsbGeometry/EsbSuperFGD/Materials.h" +#include "EsbGeometry/EsbSuperFGD/Names.h" + +#include "FairLogger.h" // for FairLogger, etc + +#include "TGeoMaterial.h" + +namespace esbroot { +namespace geometry { +namespace superfgd { + + +const char* SuperFGDConstructor::SuperFgdName = fgdnames::superFGDName; + +SuperFGDConstructor::SuperFGDConstructor() : fWidth(0.),fHeight(0.),fLength(0.),fIsVisible(false),fEdge(0.) + ,fCubeNumX(0),fCubeNumY(0),fCubeNumZ(0),fPosX(0.),fPosY(0.),fPosZ(0.) + ,fFiberRadius(0.),fFiberMaterial(""), fSuperGVol(nullptr), fSensVol(nullptr) +{ +} + +SuperFGDConstructor::~SuperFGDConstructor() +{ +} + + +TGeoVolume* SuperFGDConstructor::Construct() +{ + // All dimentions are in cm (root default dimention length) + + double TotWidth = fCubeNumX * fEdge; + double TotLength = fCubeNumY * fEdge; + double TotHeight = fCubeNumZ * fEdge; + + SetWidth(TotWidth); + SetLength(TotLength); + SetHeight(TotHeight); + + // Build the plastic scintillator cube + CubeScintConstructor cube; + cube.SetVisibility(true); + + cube.SetBase(fEdge); + cube.SetLength(fEdge); + cube.SetHeight(fEdge); + cube.SetHoleRadius(0.07); + cube.SetFiberRadius(0.05); + cube.SetCoatingThickness(0.025); + cube.SetGap(0.0); + + double shift = 0.15; + ThreeVector HolePosAlongX = ThreeVector(-shift, shift, 0); // hole along X + ThreeVector HolePosAlongY = ThreeVector(shift, 0, -shift); // hole along Y + ThreeVector HolePosAlongZ = ThreeVector(0, -shift, shift); // hole along Z + cube.SetHolePosition_X(HolePosAlongX); + cube.SetHolePosition_Y(HolePosAlongY); + cube.SetHolePosition_Z(HolePosAlongZ); + + RotMatrix rotXX(0,0,0); + RotMatrix rotYY(0,90,0); + RotMatrix rotZZ(90,90,0); + + cube.SetHoleRot_X(rotXX); + cube.SetHoleRot_Y(rotYY); + cube.SetHoleRot_Z(rotZZ); + + cube.Construct(); + fSensVol = cube.GetSensitiveVolume(); + + TGeoMedium *air = gGeoManager->GetMedium(esbroot::geometry::superfgd::materials::air); + //======================================== + // Repeat the volume in X + TGeoBBox* rowX = new TGeoBBox("rowX", TotWidth/2, fEdge/2, fEdge/2); + TGeoVolume* rowXVol = new TGeoVolume("rowXVol",rowX,air); + + //TGeoVolume* cube_vol = gGeoManager->GetVolume(fgdnames::cubeName); + TGeoVolume* cube_vol = cube.GetCubeVolume(); + double startPosX = -TotWidth/2 + fEdge/2; + + for(int i=0; i < fCubeNumX; i++) + { + int copyNo = i+1; + rowXVol->AddNode(cube_vol,copyNo,new TGeoTranslation((startPosX + i*fEdge),0,0)); + } + //======================================== + + //======================================== + // Repeat the volume in XY + TGeoBBox* rowXY = new TGeoBBox("rowXY", TotWidth/2, TotLength/2, fEdge/2); + TGeoVolume* rowXYVol = new TGeoVolume("rowXYVol",rowXY, air); + + double startPosXY = -TotLength/2 + fEdge/2; + + for(int i=0; i < fCubeNumY; i++) + { + int copyNo = i+1; + rowXYVol->AddNode(rowXVol,copyNo,new TGeoTranslation(0,(startPosXY + i*fEdge),0)); + } + //======================================== + + //======================================== + // Repeat the volume in XYZ + TGeoBBox* rowXYZ = new TGeoBBox("rowXYZ", TotWidth/2, TotLength/2, TotHeight/2); + TGeoVolume* nameSuperFGD = new TGeoVolume(SuperFgdName,rowXYZ, air); // nameSuperFGD == "rowXYZVol" + + double startPosXYZ = -TotHeight/2 + fEdge/2; + + for(int i=0; i < fCubeNumZ; i++) + { + int copyNo = i+1; + nameSuperFGD->AddNode(rowXYVol,copyNo,new TGeoTranslation(0,0,(startPosXYZ + i*fEdge))); + } + //======================================== + + fSuperGVol = nameSuperFGD; + return fSuperGVol; + //gGeoManager->AddVolume(nameSuperFGD); +} + + +} //superfgd +} //geometry +} //esbroot \ No newline at end of file diff --git a/EsbGeometry/EsbSuperFGD/EsbSuperFGDConstructor.h b/EsbGeometry/EsbSuperFGD/EsbSuperFGDConstructor.h new file mode 100644 index 0000000..8f19b47 --- /dev/null +++ b/EsbGeometry/EsbSuperFGD/EsbSuperFGDConstructor.h @@ -0,0 +1,176 @@ +#ifndef ESBROOT_ESBGEOMETRY_SUPERFGD_FGD_CONSTRUCTION_H +#define ESBROOT_ESBGEOMETRY_SUPERFGD_FGD_CONSTRUCTION_H 1 + +#include "TObject.h" +#include "TGeoVolume.h" +#include "TGeoManager.h" +#include "TGeoMaterial.h" +#include "TGeoMedium.h" + +/// Create a bounding box to contain the geometry of the detector + +namespace esbroot { +namespace geometry { +namespace superfgd { + +class SuperFGDConstructor : public TObject +{ +public: + + /** Constructor **/ + SuperFGDConstructor(); + + /** Destructor **/ + ~SuperFGDConstructor(); + + /** Set size of cube edges + *@param w - width + **/ + void SetEdge(double w) {fEdge = w;} + /** Get size of cube edge **/ + double GetEdge(void) {return fEdge;} + + /** Set the width of the SuperFGD detector bounding box "along" the X axis + *@param w - width + **/ + void SetWidth(double w) {fWidth = w;} + /** Get the width of the SuperFGD detector **/ + double GetWidth(void) {return fWidth;} + + /** Set the width of the SuperFGD detector bounding box "along" the Y axis + *@param h - Height + **/ + void SetHeight(double h) {fHeight = h;} + /** Get the height of the SuperFGD detector **/ + double GetHeight(void) {return fHeight;} + + /** Set the length of the SuperFGD detector bounding box "along" the beam axis (the + * Z axis + *@param l - Length + **/ + void SetLength(double l) {fLength = l;} + /** Get the length of the SuperFGD detector **/ + double GetLength(void) {return fLength;} + + /** Set number of cubes along X + *@param num - number of cubes along X + **/ + void SetCubeNumX(int num) {fCubeNumX = num;} + /** Get number of cubes along X **/ + int GetCubeNumX() {return fCubeNumX;} + + /** Set number of cubes along Y + *@param num - number of cubes along Y + **/ + void SetCubeNumY(int num) {fCubeNumY = num;} + /** Get number of cubes along Y **/ + int GetCubeNumY() {return fCubeNumY;} + + /** Set number of cubes along Z + *@param num - number of cubes along Z + **/ + void SetCubeNumZ(int num) {fCubeNumZ = num;} + /** Get number of cubes along Z **/ + int GetCubeNumZ() {return fCubeNumZ;} + + + /** Set the X position of the SuperFGD detector + *@param pos - position along X + **/ + void SetPosX(double pos) {fPosX = pos;} + /** Get the X position of the SuperFGD detector **/ + double GetPosX(void) {return fPosX;} + + /** Set the Y position of the SuperFGD detector + *@param pos - position along Y + **/ + void SetPosY(double pos) {fPosX = pos;} + /** Get the Y position of the SuperFGD detector **/ + double GetPosY(void) {return fPosY;} + + /** Set the Z position of the SuperFGD detector + *@param pos - position along Z + **/ + void SetPosZ(double pos) {fPosZ = pos;} + /** Get the Z position of the SuperFGD detector **/ + double GetPosZ(void) {return fPosZ;} + + /** Set the radius of the WLS fiber. + *@param radius - radius + **/ + virtual void SetFiberRadius(double radius) {fFiberRadius = radius;}; + + /** Get the radius of the WLS fiber. **/ + virtual double GetFiberRadius(void) {return fFiberRadius;}; + + + /** The name of the material to use for the fiber. + * [Default: FiberCore] + *@param mat - fiber material + **/ + virtual void SetFiberMaterial(const char* mat) {fFiberMaterial = mat;} + /** Get the fiber material **/ + const char* GetFiberMaterial() const { return fFiberMaterial.c_str();} + + /** Set Geant4 visibility + *@param vis - visibility + **/ + virtual void SetVisibility(bool vis) {fIsVisible = vis;} + + /** Get current visibility **/ + virtual bool GetVisibility(void) {return fIsVisible;} + + /** Name of the TGeoVolume of the Fgd whole detector **/ + static const char* SuperFgdName; + + /** Constructs the TgeoVolume of the detector**/ + TGeoVolume* Construct(); + + /** Return the pointer to the SuperFGD volume **/ + TGeoVolume* GetSuperFGDVolume(){return fSuperGVol;} + + /** Return the pointer to sensitive volume of the detector **/ + TGeoVolume* GetSensitiveVolume(){return fSensVol;} + +private: + + // Size of the SuperFGD + double fWidth; + double fHeight; + double fLength; + + bool fIsVisible; + + /// The edge of a cube of the SuperFGD detector + double fEdge; + + // Number of cubes along each axis + int fCubeNumX; + int fCubeNumY; + int fCubeNumZ; + + // Position of the center of the SuperFGD detector + double fPosX; + double fPosY; + double fPosZ; + + /// The radius of the WLS fiber. + double fFiberRadius; + + /// The name of the material to use for the fiber. + std::string fFiberMaterial; + + //! Pointer to the constructed SuperFgd volume + TGeoVolume* fSuperGVol; + + //! Pointer to the sensitive volume in the cube + TGeoVolume* fSensVol; + + ClassDef(SuperFGDConstructor,2) +}; + +} //superfgd +} //geometry +} //esbroot + +#endif diff --git a/EsbGeometry/EsbSuperFGD/EsbSuperFGDDetectorConstruction.cxx b/EsbGeometry/EsbSuperFGD/EsbSuperFGDDetectorConstruction.cxx new file mode 100644 index 0000000..7eaa131 --- /dev/null +++ b/EsbGeometry/EsbSuperFGD/EsbSuperFGDDetectorConstruction.cxx @@ -0,0 +1,62 @@ +#include "EsbGeometry/EsbSuperFGD/EsbSuperFGDDetectorConstruction.h" +#include "EsbGeometry/EsbSuperFGD/EsbSuperFGDConstructor.h" +#include "EsbGeometry/EsbSuperFGD/Names.h" + +#include "FairLogger.h" + +namespace esbroot { +namespace geometry { +namespace superfgd { + + +SuperFGDDetectorConstruction::SuperFGDDetectorConstruction(std::string detectorFile) + : fSuperVol(nullptr), fSensVolume(nullptr) +{ + fParams.LoadPartParams(detectorFile); +} + +SuperFGDDetectorConstruction::~SuperFGDDetectorConstruction() +{ +} + +TGeoVolume* SuperFGDDetectorConstruction::Construct() +{ + SuperFGDConstructor fSuperFGDConstructor; + fSuperFGDConstructor.SetVisibility(fParams.ParamAsBool(DP::visdetail)); + + Double_t lunit = fParams.GetLenghtUnit(); + // Detector is made of cubes + // length_X == length_Y ==length_Z + Double_t edge = fParams.ParamAsDouble(DP::length_X) * lunit; + + Int_t cube_X_N = fParams.ParamAsInt(DP::number_cubes_X); + Int_t cube_Y_N = fParams.ParamAsInt(DP::number_cubes_Y); + Int_t cube_Z_N = fParams.ParamAsInt(DP::number_cubes_Z); + + fSuperFGDConstructor.SetEdge(edge); + fSuperFGDConstructor.SetCubeNumX(cube_X_N); + fSuperFGDConstructor.SetCubeNumY(cube_Y_N); + fSuperFGDConstructor.SetCubeNumZ(cube_Z_N); + + fSuperVol = fSuperFGDConstructor.Construct(); + fSensVolume = fSuperFGDConstructor.GetSensitiveVolume(); + return fSuperVol; +} + +TVector3 SuperFGDDetectorConstruction::GetMagneticField() +{ + Double_t Bx = fParams.ParamAsInt(DP::magField_X); + Double_t By = fParams.ParamAsInt(DP::magField_Y); + Double_t Bz = fParams.ParamAsInt(DP::magField_Z); + + TVector3 magField; + magField.SetX(Bx); + magField.SetY(By); + magField.SetZ(Bz); + + return magField; +} + +} //superfgd +} //geometry +} //esbroot \ No newline at end of file diff --git a/EsbGeometry/EsbSuperFGD/EsbSuperFGDDetectorConstruction.h b/EsbGeometry/EsbSuperFGD/EsbSuperFGDDetectorConstruction.h new file mode 100644 index 0000000..03be904 --- /dev/null +++ b/EsbGeometry/EsbSuperFGD/EsbSuperFGDDetectorConstruction.h @@ -0,0 +1,70 @@ +#ifndef ESBROOT_ESBGEOMETRY_SUPERFGD_FGD_DETECTOR_CONSTRUCTION_H +#define ESBROOT_ESBGEOMETRY_SUPERFGD_FGD_DETECTOR_CONSTRUCTION_H 1 + +#include "CLHEP/Units/SystemOfUnits.h" +#include "CLHEP/Units/PhysicalConstants.h" + +#include "EsbGeometry/EsbSuperFGD/Materials.h" +#include "EsbGeometry/EsbSuperFGD/Names.h" +#include "EsbGeometry/EsbSuperFGD/EsbFgdDetectorParameters.h" + +#include "TVector3.h" +#include "TObject.h" +#include "TGeoManager.h" + +class FgdDetectorParameters; + +namespace esbroot { +namespace geometry { +namespace superfgd { + +class SuperFGDDetectorConstruction : public TObject +{ +public: + + /** Constructor + *@param detectorFile - name (fullpath) of file from which to read the detector parameters + **/ + SuperFGDDetectorConstruction(std::string detectorFile); + + /** Destructor **/ + virtual ~SuperFGDDetectorConstruction(); + + /** Constructs the TgeoVolume of the detector**/ + TGeoVolume* Construct(); + + /** Returns the last construcetd volume **/ + TGeoVolume* GetConstuctedVolume(){return fSuperVol;} + + /** Returns the sensitive volume of the last constructed detector **/ + TGeoVolume* GetSensitiveVolume(){return fSensVolume;} + + /** Returns the magnetic field read from the file **/ + TVector3 GetMagneticField(); + + Double_t GetLengthUnit() {return fParams.GetLenghtUnit();} + Double_t GetEdge() {return fParams.ParamAsDouble(DP::length_X);} + + Int_t GetCubeNX(){return fParams.ParamAsInt(DP::number_cubes_X);} + Int_t GetCubeNY(){return fParams.ParamAsInt(DP::number_cubes_Y);} + Int_t GetCubeNZ(){return fParams.ParamAsInt(DP::number_cubes_Z);} + +private: + /** Class to hold the Detector parameters read from external file **/ + FgdDetectorParameters fParams; + + /** Pointer to the last constructed volume **/ + TGeoVolume* fSuperVol; + + /** Pointer to the sensitive volume of the detector **/ + TGeoVolume* fSensVolume; + + ClassDef(SuperFGDDetectorConstruction,2) +}; + +} //superfgd +} //geometry +} //esbroot + + +#endif \ No newline at end of file diff --git a/EsbGeometry/EsbSuperFGD/Materials.h b/EsbGeometry/EsbSuperFGD/Materials.h new file mode 100644 index 0000000..2ebaef3 --- /dev/null +++ b/EsbGeometry/EsbSuperFGD/Materials.h @@ -0,0 +1,52 @@ +#ifndef ESBROOT_DATA_SUPERFGD_DETECTOR_MATERIALS_H +#define ESBROOT_DATA_SUPERFGD_DETECTOR_MATERIALS_H 1 + +#include "CLHEP/Units/SystemOfUnits.h" +#include "CLHEP/Units/PhysicalConstants.h" + + +using namespace CLHEP; + +namespace esbroot { + +namespace geometry { + +namespace superfgd { + +namespace materials +{ + static const char* vacuum = "vacuum"; + static const char* air = "air"; + static const char* brass = "brass"; + static const char* bronze = "bronze"; + static const char* stainlessSteel = "stainlessSteel"; + static const char* methane = "methane"; + static const char* carbonDioxide = "CO2"; + static const char* carbontetraFloride = "CF4"; + static const char* titaniumDioxide = "TiO2"; + static const char* polystyrene = "polystyrene"; + static const char* scintillator = "scintillator"; + static const char* paraterphnyl = "paraterphnyl"; + static const char* scintilatorMix = "scintilatorMix"; + static const char* podscintillator = "podscintillator"; + static const char* polyethylene = "polyethylene"; + static const char* poduleEpoxy = "poduleEpoxy"; + static const char* polycarbonate = "polycarbonate"; + static const char* carbonFiber = "carbonFiber"; + static const char* fiberCore = "fiberCore"; + static const char* fiberCladding = "fiberCladding"; + static const char* scintillatorCoating = "scintillatorCoating"; + + static int GetNextIndex() + { + static int index=10000; + index++; + return index; + } + +} // materials +} // superfgd +} // geometry +} // esbroot + +#endif \ No newline at end of file diff --git a/EsbGeometry/EsbSuperFGD/Names.h b/EsbGeometry/EsbSuperFGD/Names.h new file mode 100644 index 0000000..460b7cf --- /dev/null +++ b/EsbGeometry/EsbSuperFGD/Names.h @@ -0,0 +1,26 @@ +#ifndef ESBROOT_DATA_SUPERFGD_DETECTOR_NAMES_H +#define ESBROOT_DATA_SUPERFGD_DETECTOR_NAMES_H 1 + +#include "CLHEP/Units/SystemOfUnits.h" +#include "CLHEP/Units/PhysicalConstants.h" + +using namespace CLHEP; + +namespace esbroot { + +namespace geometry { + +namespace superfgd { + +namespace fgdnames +{ + static const char* cubeName = "CubeWithCoatingWhole"; // The name of the hole Cube - with scintilator, coating, fibers + static const char* superFGDName = "Esb/SuperFGD"; // name of the constructed detector volume + static const char* scintilatorVolume = "cubeScntVol"; // name of just the scintilator volume in the cube + static const char* coatingVolume = "cubeCoatingVol"; // name of just the scintilator volume in the cube +} // fgdnames +} // superfgd +} // geometry +} // esbroot + +#endif \ No newline at end of file diff --git a/EsbGeometry/FgdDetector.cxx b/EsbGeometry/FgdDetector.cxx new file mode 100644 index 0000000..1219925 --- /dev/null +++ b/EsbGeometry/FgdDetector.cxx @@ -0,0 +1,387 @@ +/******************************************************************************** + * Copyright (C) 2014 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH * + * * + * This software is distributed under the terms of the * + * GNU Lesser General Public Licence (LGPL) version 3, * + * copied verbatim in the file "LICENSE" * + ********************************************************************************/ +#include "EsbGeometry/FgdDetector.h" +#include "EsbGeometry/EsbSuperFGD/Materials.h" +#include "EsbGeometry/EsbSuperFGD/Names.h" +#include "EsbGeometry/EsbSuperFGD/EsbFgdDetectorParameters.h" + +#include "FairLogger.h" +#include "FairGenericStack.h" +#include "FairGeoLoader.h" +#include "FairGeoInterface.h" +#include "FairGeoBuilder.h" +#include "FairGeoMedia.h" +#include "FairRootManager.h" +#include "FairStack.h" +#include "FairVolume.h" + +#include "TClonesArray.h" +#include "TVirtualMC.h" +#include "TGeoManager.h" +#include "TGeoMaterial.h" +#include "TGeoMedium.h" +#include "TGraph.h" + +#include "Geant4GM/volumes/Factory.h" +#include "RootGM/volumes/Factory.h" +#include "TGeoManager.h" + +#include +using std::cout; +using std::endl; + + +#include "TGeoTube.h" + +namespace esbroot { + +namespace geometry { +// PC: work around +static const Int_t kFgdDetector = 1; + +//___________________________________________________________________ +FgdDetector::FgdDetector() + : FairDetector("FgdDetector", kTRUE, kFgdDetector), + fgdConstructor(""), + fTrackID(-1), + fVolumeID(-1), + fPos(), + fMom(), + fTime(-1.), + fLength(-1.), + fELoss(-1), + fposX(0), + fposY(0), + fposZ(0), + isDefinedMaterials(false), + fFgdDetectorPointCollection(new TClonesArray(data::superfgd::FgdDetectorPoint::Class())), + fsuperFgdVol(nullptr) +{ +} + +FgdDetector::FgdDetector(const char* geoConfigFile, double posX, double posY, double posZ, Bool_t Active) + : FairDetector("FgdDetector", kTRUE, kFgdDetector), + fgdConstructor(geoConfigFile), + fTrackID(-1), + fVolumeID(-1), + fPos(), + fMom(), + fMomExit(), + fTime(-1.), + fLength(-1.), + fELoss(-1), + fposX(posX), + fposY(posY), + fposZ(posZ), + isDefinedMaterials(false), + fFgdDetectorPointCollection(new TClonesArray(data::superfgd::FgdDetectorPoint::Class())), + fsuperFgdVol(nullptr) +{ +} + +//___________________________________________________________________ + FgdDetector::FgdDetector(const char* name, const char* geoConfigFile, double posX, double posY, double posZ, Bool_t active) + : FairDetector(name, active, kFgdDetector), + fgdConstructor(geoConfigFile), + fTrackID(-1), + fVolumeID(-1), + fPos(), + fMom(), + fMomExit(), + fTime(-1.), + fLength(-1.), + fELoss(-1), + fposX(posX), + fposY(posY), + fposZ(posZ), + isDefinedMaterials(false), + fFgdDetectorPointCollection(new TClonesArray(data::superfgd::FgdDetectorPoint::Class())) +{ +} + +//___________________________________________________________________ +FgdDetector::~FgdDetector() +{ + if (fFgdDetectorPointCollection) { + fFgdDetectorPointCollection->Delete(); + delete fFgdDetectorPointCollection; + } +} + +//___________________________________________________________________ +void FgdDetector::Initialize() +{ + FairDetector::Initialize(); + fpdgCodes.clear(); +} + +//___________________________________________________________________ +Bool_t FgdDetector::ProcessHits(FairVolume* vol) +{ + if ( TVirtualMC::GetMC()->IsTrackEntering() ) { + fELoss = 0.; + fLength = 0.; + fTime = TVirtualMC::GetMC()->TrackTime() * 1.0e09; + TVirtualMC::GetMC()->TrackPosition(fPos); + TVirtualMC::GetMC()->TrackMomentum(fMom); + } + + // Sum energy loss for all steps in the active volume + fELoss += TVirtualMC::GetMC()->Edep(); + fLength += TVirtualMC::GetMC()->TrackStep(); + + // Create FairTutorialDet1Point at exit of active volume + if ( TVirtualMC::GetMC()->IsTrackExiting() || + TVirtualMC::GetMC()->IsTrackStop() || + TVirtualMC::GetMC()->IsTrackDisappeared() ) { + + fTrackID = TVirtualMC::GetMC()->GetStack()->GetCurrentTrackNumber(); + fVolumeID = vol->getMCid(); + + //~ if (fELoss == 0. ) { return kFALSE; } + TVirtualMC::GetMC()->TrackPosition(fPosExit); + TVirtualMC::GetMC()->TrackMomentum(fMomExit); + + LOG(debug) << " TrackPid " << TVirtualMC::GetMC()->TrackPid(); + LOG(debug) << " TrackCharge " << TVirtualMC::GetMC()->TrackCharge(); + LOG(debug) << " Is track entering " << TVirtualMC::GetMC()->IsTrackEntering(); + LOG(debug) << " Is track exiting " << TVirtualMC::GetMC()->IsTrackExiting(); + LOG(debug) << " Is track disappearing " << TVirtualMC::GetMC()->IsTrackDisappeared(); + LOG(debug) << " vol->getCopyNo() " << vol->getCopyNo(); + LOG(debug) << " vol->getVolumeId() " << vol->getVolumeId(); + LOG(debug) << " fPos.X() " << fPos.X(); + LOG(debug) << " fPos.Y() " << fPos.Y(); + LOG(debug) << " fPos.Z() " << fPos.Z(); + LOG(debug) << " TrackLength " << TVirtualMC::GetMC()->TrackLength(); + LOG(debug) << " GetCurrentTrackNumber " << TVirtualMC::GetMC()->GetStack()->GetCurrentTrackNumber(); + LOG(debug) << " TrackPid " << TVirtualMC::GetMC()->TrackPid(); + + AddHit(fTrackID, fVolumeID + ,TVector3(fposX, fposY, fposZ) + ,TVector3(fPos.X(), fPos.Y(), fPos.Z()) + ,TVector3(fPosExit.X(), fPosExit.Y(), fPosExit.Z()) + ,TVector3(fMom.Px(), fMom.Py(), fMom.Pz()) + ,TVector3(fMomExit.Px(), fMomExit.Py(), fMomExit.Pz()) + ,fTime, fELoss, fLength, TVirtualMC::GetMC()->TrackPid() + , TVirtualMC::GetMC()->TrackLength()); + + fpdgCodes.clear(); + } + + return kTRUE; +} + +void FgdDetector::EndOfEvent() +{ + fFgdDetectorPointCollection->Clear(); +} + + + +void FgdDetector::Register() +{ + + /** This will create a branch in the output tree called + EsbFgdDetectorPoint, setting the last parameter to kFALSE means: + this collection will not be written to the file, it will exist + only during the simulation. + */ + + FairRootManager::Instance()->Register(superfgd::DP::FGD_BRANCH.c_str() + ,superfgd::DP::FGD_DETECTOR_NAME.c_str() + ,fFgdDetectorPointCollection, kTRUE); + +} + + +TClonesArray* FgdDetector::GetCollection(Int_t iColl) const +{ + if (iColl == 0) { return fFgdDetectorPointCollection; } + else { return NULL; } +} + +void FgdDetector::Reset() +{ + fFgdDetectorPointCollection->Clear(); +} + +void FgdDetector::ConstructGeometry() +{ + using namespace geometry::superfgd; + + DefineMaterials(); + // Create the real Fgd geometry + TGeoVolume* superFgdVol = fgdConstructor.Construct(); + fsuperFgdVol = superFgdVol; + // Retrieve the sensitive volume + TGeoVolume* cubeScnintilatorVol = fgdConstructor.GetSensitiveVolume(); + + if(!superFgdVol || !cubeScnintilatorVol) + { + throw "SuperFGD was not constructed successfully!"; + } + + // Register sensitive volume + AddSensitiveVolume(cubeScnintilatorVol); + + TGeoVolume *top = gGeoManager->GetTopVolume(); + top->AddNode(superFgdVol, 1, new TGeoTranslation(fposX, fposY, fposZ)); +} + +//___________________________________________________________________ +data::superfgd::FgdDetectorPoint* FgdDetector::AddHit(Int_t trackID, Int_t detID, + TVector3 detectorPos, TVector3 pos , TVector3 posExit, TVector3 mom, + TVector3 momExit , Double32_t time, Double32_t edep, Double32_t trackLength, Int_t pdg + , Double32_t trackLengthFromOrigin ) +{ + LOG(debug) << "FgdDetector::AddHit"; + LOG(debug) << "trackID " << trackID; + LOG(debug) << "detID " << detID; + LOG(debug) << "pos.X() " << pos.X() << "; pos.Y() " << pos.Y()<< "; pos.Z() " << pos.Z(); + LOG(debug) << "mom.Px() " << mom.Px() << "; mom.Py() " << mom.Py() << "; mom.Pz() " << mom.Pz(); + LOG(debug) << "time " << time; + LOG(debug) << "edep " << edep; + LOG(debug) << "pdg " << pdg; + + TClonesArray& clref = *fFgdDetectorPointCollection; + Int_t size = clref.GetEntriesFast(); + + return new(clref[size]) data::superfgd::FgdDetectorPoint(trackID, detID, detectorPos, pos, posExit, mom, + momExit, time, edep, trackLength, pdg, trackLengthFromOrigin); +} + +void FgdDetector::SetSpecialPhysicsCuts() +{ + // DRAY - delta ray production. The variable DRAY controls this process. + // 0 - No delta rays production. + // 1 - delta rays production with generation of . Default setting. + // 2 - delta rays production without generation of . + // LOSS - Continuous energy loss. The variable LOSS controls this process. + // 0 - No continuous energy loss, DRAY is set to 0. + // 1 - Continuous energy loss with generation of delta rays above DCUTE and restricted Landau fluctuations below DCUTE. + // 2 - Continuous energy loss without generation of delta rays and full Landau-Vavilov-Gauss fluctuations. In this case the variable DRAY is forced to 0 to avoid double counting of fluctuations. Default setting. + // 3 - Same as 1, kept for backward compatibility. + // 4 - Energy loss without fluctuation. The value obtained from the tables is used directly. + TVirtualMC::GetMC()->SetProcess("LOSS",2); /**energy loss*/ + TVirtualMC::GetMC()->SetProcess("DRAY",0); /**delta-ray*/ + + Double_t cut_delta = 1.0E4; // GeV --> 10 TeV + TVirtualMC::GetMC()->SetCut("DCUTE", cut_delta); /** delta-rays by electrons */ + TVirtualMC::GetMC()->SetCut("DCUTM", cut_delta); /** delta-rays by muons */ +} + +void FgdDetector::DefineMaterials() +{ + if(isDefinedMaterials) return; // Define materials only once + + isDefinedMaterials = true; + + FairGeoLoader *geoLoad = FairGeoLoader::Instance(); + FairGeoInterface *geoFace = geoLoad->getGeoInterface(); + + FairGeoMedia *geoMedia = geoFace->getMedia(); + FairGeoBuilder* geoBuild = geoLoad->getGeoBuilder(); + + // FairGeoMedium* brass = geoMedia->getMedium(esbroot::geometry::superfgd::materials::brass); + // geoBuild->createMedium(brass); + + // FairGeoMedium* bronze = geoMedia->getMedium(esbroot::geometry::superfgd::materials::bronze); + // geoBuild->createMedium(bronze); + + // FairGeoMedium* stainlessSteel = geoMedia->getMedium(esbroot::geometry::superfgd::materials::stainlessSteel); + // geoBuild->createMedium(stainlessSteel); + + // FairGeoMedium* methane = geoMedia->getMedium(esbroot::geometry::superfgd::materials::methane); + // geoBuild->createMedium(methane); + + // FairGeoMedium* carbonDioxide = geoMedia->getMedium(esbroot::geometry::superfgd::materials::carbonDioxide); + // geoBuild->createMedium(carbonDioxide); + + // FairGeoMedium* carbontetraFloride = geoMedia->getMedium(esbroot::geometry::superfgd::materials::carbontetraFloride); + // geoBuild->createMedium(carbontetraFloride); + + // FairGeoMedium* titaniumDioxide = geoMedia->getMedium(esbroot::geometry::superfgd::materials::titaniumDioxide); + // geoBuild->createMedium(titaniumDioxide); + + // FairGeoMedium* polystyrene = geoMedia->getMedium(esbroot::geometry::superfgd::materials::polystyrene); + // geoBuild->createMedium(polystyrene); + + FairGeoMedium* scintillator = geoMedia->getMedium(esbroot::geometry::superfgd::materials::scintillator); + scintillator->setMediumIndex(esbroot::geometry::superfgd::materials::GetNextIndex()); + geoBuild->createMedium(scintillator); + scintillator->Print(); + + FairGeoMedium* paraterphnyl = geoMedia->getMedium(esbroot::geometry::superfgd::materials::paraterphnyl); + geoBuild->createMedium(paraterphnyl); + + // FairGeoMedium* podscintillator = geoMedia->getMedium(esbroot::geometry::superfgd::materials::podscintillator); + // geoBuild->createMedium(podscintillator); + + // FairGeoMedium* polyethylene = geoMedia->getMedium(esbroot::geometry::superfgd::materials::polyethylene); + // geoBuild->createMedium(polyethylene); + + // FairGeoMedium* poduleEpoxy = geoMedia->getMedium(esbroot::geometry::superfgd::materials::poduleEpoxy); + // geoBuild->createMedium(poduleEpoxy); + + // FairGeoMedium* polycarbonate = geoMedia->getMedium(esbroot::geometry::superfgd::materials::polycarbonate); + // geoBuild->createMedium(polycarbonate); + + // FairGeoMedium* carbonFiber = geoMedia->getMedium(esbroot::geometry::superfgd::materials::carbonFiber); + // geoBuild->createMedium(carbonFiber); + + FairGeoMedium* fiberCore = geoMedia->getMedium(esbroot::geometry::superfgd::materials::fiberCore); + geoBuild->createMedium(fiberCore); + + FairGeoMedium* fiberCladding = geoMedia->getMedium(esbroot::geometry::superfgd::materials::fiberCladding); + geoBuild->createMedium(fiberCladding); + + FairGeoMedium* fairTiO2 = geoMedia->getMedium(esbroot::geometry::superfgd::materials::titaniumDioxide); + geoBuild->createMedium(fairTiO2); + + FairGeoMedium* fairPolystyrene = geoMedia->getMedium(esbroot::geometry::superfgd::materials::polystyrene); + geoBuild->createMedium(fairPolystyrene); + + FairGeoMedium* fairAir = geoMedia->getMedium(esbroot::geometry::superfgd::materials::air); + geoBuild->createMedium(fairAir); + + FairGeoMedium* vacuum = geoMedia->getMedium(esbroot::geometry::superfgd::materials::vacuum); + geoBuild->createMedium(vacuum); +} + + +void FgdDetector::GetMagneticField(Double_t& Bx,Double_t& By, Double_t& Bz) +{ + TVector3 magField = fgdConstructor.GetMagneticField(); + Bx = magField.X(); + By = magField.Y(); + Bz = magField.Z(); +} + + +void FgdDetector::GetMagneticFieldRegion(Double_t& xMin, Double_t& xMax, + Double_t& yMin, Double_t& yMax, + Double_t& zMin, Double_t& zMax) +{ + Double_t edge = fgdConstructor.GetEdge() * fgdConstructor.GetLengthUnit(); + Double_t totalX = fgdConstructor.GetCubeNX() * edge; + Double_t totalY = fgdConstructor.GetCubeNY() * edge; + Double_t totalZ = fgdConstructor.GetCubeNZ() * edge; + + xMin = fposX - totalX/2; + xMax = fposX + totalX/2; + + yMin = fposY - totalY/2; + yMax = fposY + totalY/2; + + zMin = fposZ - totalZ/2; + zMax = fposZ + totalZ/2; +} + +} +} + diff --git a/EsbGeometry/FgdDetector.h b/EsbGeometry/FgdDetector.h new file mode 100644 index 0000000..0444f5b --- /dev/null +++ b/EsbGeometry/FgdDetector.h @@ -0,0 +1,144 @@ +/******************************************************************************** + * Copyright (C) 2014 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH * + * * + * This software is distributed under the terms of the * + * GNU Lesser General Public Licence (LGPL) version 3, * + * copied verbatim in the file "LICENSE" * + ********************************************************************************/ +#ifndef ESBROOT_ESBGEOMETRY_FGDDETECTOR_H +#define ESBROOT_ESBGEOMETRY_FGDDETECTOR_H + +#include "FairDetector.h" + +#include "TVector3.h" +#include "TLorentzVector.h" + +#include "EsbGeometry/EsbSuperFGD/EsbSuperFGDDetectorConstruction.h" +#include "EsbData/EsbSuperFGD/FgdDetectorPoint.h" + +class FairVolume; +class TClonesArray; + +namespace esbroot { + +namespace geometry { + class FgdDetector: public FairDetector + { + + public: + + /** Default constructor **/ + FgdDetector(); + + /** Name : Detector Name + * Active: kTRUE for active detectors (ProcessHits() will be called) + * kFALSE for inactive detectors + * geoConfigFile: Full path to the configuration file for the Superfgd geometry + */ + FgdDetector(const char* Name, const char* geoConfigFile, double posX, double posY, double posZ, Bool_t Active = true); + + /** Constructor using default name + * geoConfigFile: Full path to the configuration file for the Superfgd geometry + */ + FgdDetector(const char* geoConfigFile, double posX, double posY, double posZ, Bool_t Active = true); + + /** destructor */ + virtual ~FgdDetector(); + + /** Initialization of the detector is done here */ + virtual void Initialize(); + + /** this method is called for each step during simulation + * (see FairMCApplication::Stepping()) + */ + virtual Bool_t ProcessHits( FairVolume* v=0); + + /** Registers the produced collections in FAIRRootManager. */ + virtual void Register(); + + /** Gets the produced collections */ + virtual TClonesArray* GetCollection(Int_t iColl) const ; + + /** has to be called after each event to reset the containers */ + virtual void Reset(); + + /** Create the detector geometry */ + void ConstructGeometry(); + + /** Initializes a magnetic field for the volume and detector position */ + void GetMagneticField(Double_t& Bx,Double_t& By, Double_t& Bz); + void GetMagneticFieldRegion(Double_t& xMin, Double_t& xMax, + Double_t& yMin, Double_t& yMax, + Double_t& zMin, Double_t& zMax); + + + /** This method is an example of how to add your own point + * of type EsbFgdDetectorPoint to the clones array + */ + data::superfgd::FgdDetectorPoint* AddHit(Int_t trackID, Int_t detID, + TVector3 detectorPos, + TVector3 pos, TVector3 posExit, TVector3 mom, TVector3 momExit, + Double32_t time, Double32_t edep, Double32_t trackLength, Int_t pdg + ,Double32_t trackLengthFromOrigin ); + + /** The following methods can be implemented if you need to make + * any optional action in your detector during the transport. + */ + + virtual void SetSpecialPhysicsCuts() override; + virtual void EndOfEvent(); + virtual void FinishPrimary() {;} + virtual void FinishRun() {;} + virtual void BeginPrimary() {;} + virtual void PostTrack() {;} + virtual void PreTrack() {;} + virtual void BeginEvent() {;} + + TGeoVolume* GetVolume(){return fsuperFgdVol;} + + + private: + + /** Initialize amterials used in the detector construction **/ + void DefineMaterials(); + + //** indicate that the materials have already been defined + bool isDefinedMaterials; + + /** Track information to be stored until the track leaves the + active volume. + */ + Int_t fTrackID; //! track index + Int_t fVolumeID; //! volume id + TLorentzVector fPos; //! position at entrance + TLorentzVector fPosExit; //! position at exit + TLorentzVector fMom; //! momentum at entrance + TLorentzVector fMomExit; //! momentum at entrance + Double32_t fTime; //! time + Double32_t fLength; //! length + Double32_t fELoss; //! energy loss + + // Detector position + double fposX; + double fposY; + double fposZ; + + std::set fpdgCodes;//! +#include +#include + +namespace esbroot { +namespace geometry { + +/*static*/ CoordinateSystem OnAxisCS::BuildECS(double theta_E) +{ + return( + CoordinateSystem( + ROOT::Math::Rotation3D + ( + -TMath::Cos(theta_E), 0, TMath::Sin(theta_E), + TMath::Sin(theta_E), 0, TMath::Cos(theta_E), + 0.0, 1.0, 0.0 + ), + ROOT::Math::XYZVector(0.0, 0.0, 0.0) + ) + ); +} + +/*static*/ CoordinateSystem OnAxisCS::BuildTSCS(double theta_E, + double theta_N, ROOT::Math::XYZVector const& T_TS) +{ + return( + CoordinateSystem( + ROOT::Math::Rotation3D( + -TMath::Cos(theta_E + theta_N), 0, TMath::Sin(theta_E + theta_N), + TMath::Sin(theta_E + theta_N), 0, TMath::Cos(theta_E + theta_N), + 0.0, 1.0, 0.0 + ), + T_TS + ) + ); +} + +/*static*/ CoordinateSystem OnAxisCS::BuildNDCS(double theta_E, + double theta_N, ROOT::Math::XYZVector const& T_TS, double L_ND, double gamma) +{ + return( + CoordinateSystem( + ROOT::Math::Rotation3D( + -TMath::Cos(theta_E + theta_N), 0, TMath::Sin(theta_E + theta_N), + TMath::Sin(theta_E + theta_N), 0, TMath::Cos(theta_E + theta_N), + 0.0, 1.0, 0.0 + ), + ROOT::Math::XYZVector( + L_ND*TMath::Cos(gamma)*TMath::Sin(theta_E+theta_N) + T_TS.x(), + L_ND*TMath::Cos(gamma)*TMath::Cos(theta_E+theta_N) + T_TS.y(), + -L_ND*TMath::Sin(gamma) + T_TS.z() + ) + ) + ); +} + +/*static*/ CoordinateSystem OnAxisCS::BuildFDCS(double theta_E, + double theta_N, ROOT::Math::XYZVector const& T_TS, double L_ND, double gamma, double L_FD) +{ + return( + CoordinateSystem( + ROOT::Math::Rotation3D( + -TMath::Cos(theta_E + theta_N), + TMath::Sin(2*gamma)*TMath::Sin(theta_E+theta_N), + TMath::Cos(2*gamma)*TMath::Sin(theta_E+theta_N), //end first row + TMath::Sin(theta_E + theta_N), + TMath::Sin(2*gamma)*TMath::Cos(theta_E+theta_N), + TMath::Cos(2*gamma)*TMath::Cos(theta_E+theta_N), //end second row + 0.0, + TMath::Cos(2*gamma), + -TMath::Sin(2*gamma) //end third row + ), + ROOT::Math::XYZVector( + L_FD*TMath::Cos(gamma)*TMath::Sin(theta_E+theta_N) + T_TS.x(), + L_FD*TMath::Cos(gamma)*TMath::Cos(theta_E+theta_N) + T_TS.y(), + -L_FD*TMath::Sin(gamma) + T_TS.z() + ) + ) + ); +} + + +} //namespace geometry +} //namespace esbroot diff --git a/EsbGeometry/OnAxisCS.h b/EsbGeometry/OnAxisCS.h new file mode 100644 index 0000000..1b7ff9c --- /dev/null +++ b/EsbGeometry/OnAxisCS.h @@ -0,0 +1,80 @@ +#ifndef ESBROOT_ESBGEOMETRY_ONAXISCS_H +#define ESBROOT_ESBGEOMETRY_ONAXISCS_H + +#include "EsbGeometry/CoordinateSystem.h" + +#include +#include +#include + +#include + +namespace esbroot { +namespace geometry { + +//! @brief On-axis coordinate system construction class +class OnAxisCS : public TObject +{ + public: + + //! Constant conecting ECS with TCS + static constexpr double StdTheta_E = 28.5 * TMath::DegToRad(); + + //! Empty constructor for ROOT I/O + OnAxisCS() {}; + + //! Constructor from parameters + template + OnAxisCS(double theta_E, double theta_N, vec T_TS, double L_ND, double gamma, double L_FD) : + ftheta_E(theta_E), ftheta_N(theta_N), fT_TS(T_TS), fL_ND(L_ND), fgamma(gamma), fL_FD(L_FD), + fECS(BuildECS(ftheta_E)), + fTSCS(BuildTSCS(ftheta_E, ftheta_N, fT_TS)), + fNDCS(BuildNDCS(ftheta_E, ftheta_N, fT_TS, fL_ND, fgamma)), + fFDCS(BuildFDCS(ftheta_E, ftheta_N, fT_TS, fL_ND, fgamma, fL_FD)) + {}; + + //! Empty destructor + virtual ~OnAxisCS() {}; + + //Getters + double GetTheta_E() const {return ftheta_E;}; + double GetTheta_N() const {return ftheta_N;}; + ROOT::Math::XYZVector const& GetT_TS() const {return fT_TS;}; + double GetL_ND() const {return fL_ND;}; + double GetGamma() const {return fgamma;}; + double GetL_FD() const {return fL_FD;}; + + CoordinateSystem const& GetECS() const {return fECS;} //!getMedia(); FairGeoBuilder* geoBuild = geoLoad->getGeoBuilder(); - FairGeoMedium* mWC = geoMedia->getMedium("H2O_ESSnuSB"); + FairGeoMedium* mWC = geoMedia->getMedium("WCSim_Water"); geoBuild->createMedium(mWC); - TGeoMedium *WC_med = gGeoManager->GetMedium("H2O_ESSnuSB"); + TGeoMedium *WC_med = gGeoManager->GetMedium("WCSim_Water"); //TODO: Change this to use media.geo file TGeoMaterial *Al_mat = new TGeoMaterial("Al", 26.98, 13, 2.7); @@ -213,6 +213,7 @@ void WCDetector::ConstructGeometry() AddSensitiveVolume(wall); //From FairModule AddSensitiveVolume(endwall); //From FairModule + //TODO: Top volume should be a parameter in the constructor TGeoVolume *top = gGeoManager->GetTopVolume(); top->AddNode(wc, 1); top->AddNode(wall, 1); diff --git a/EsbGeometry/WCDetector.h b/EsbGeometry/WCDetector.h index 5a04d86..7138c24 100644 --- a/EsbGeometry/WCDetector.h +++ b/EsbGeometry/WCDetector.h @@ -96,8 +96,8 @@ namespace geometry { Double32_t fLength; //! length Double32_t fELoss; //! energy loss - Double_t fWCradius; // radius of WC cylinder - Double_t fWChalflength; // halflength of WC cylinder + Double_t fWCradius; //! radius of WC cylinder + Double_t fWChalflength; //! halflength of WC cylinder /** container for data points */ diff --git a/EsbMacro/EsbSuperFGD/Readme.md b/EsbMacro/EsbSuperFGD/Readme.md new file mode 100644 index 0000000..71ee6fd --- /dev/null +++ b/EsbMacro/EsbSuperFGD/Readme.md @@ -0,0 +1,15 @@ +# How to use + +Since the macros create quite a lot of files, not +to clutter the macro folder follow these steps: + +1. Create a folder "test" located under the EsbMacro folder. + +2. Execute the macros as + +``` +root -l ../EsbSuperFGD/.C +``` + +where is e.g. simulate_1_fgd_genie_generator.C +root -l ../EsbSuperFGD/simulate_1_fgd_genie_generator.C \ No newline at end of file diff --git a/EsbMacro/EsbSuperFGD/muon_only_1_simulate_genie.C b/EsbMacro/EsbSuperFGD/muon_only_1_simulate_genie.C new file mode 100644 index 0000000..69ff8eb --- /dev/null +++ b/EsbMacro/EsbSuperFGD/muon_only_1_simulate_genie.C @@ -0,0 +1,113 @@ +/* + + Macro that shows how to run a WC simulation. + +*/ + +void muon_only_1_simulate_genie(TString outFileName = "evetest_mu_only.root", + Int_t nStartEvent = 0, + Int_t nEvents = 25) +{ + using namespace esbroot; + + + FairRunSim* fRun = new FairRunSim(); // create the FairRun Class + // Peter: SetStoreTraj seems to be needed for the official Eve + // visualization. It creates the branch GeoTracks in the output tree. + fRun->SetStoreTraj(); + + // Choose the Geant Navigation System + fRun->SetName("TGeant4"); // TGeant3/4 + //~ fRun->SetIsMT(true); + + // Set Material Definition file + fRun->SetMaterials("media.geo"); + + // Add Passive Modules + FairModule *cave= new geometry::Cave("CAVE"); + //~ FairModule *Cave= new FairCave("CAVE"); + cave->SetGeometryFileName("cave.geo"); + fRun->AddModule(cave); + + // Add Detectors + // FairDetector *nearWc = new geometry::WCDetector("NearWcDetector", 300, 500, kTRUE); + // fRun->AddModule(nearWc); + + TVector3 fgdPosition(0,0,-550); + + FairDetector* fgd = new geometry::FgdDetector("Granular Detector","../../EsbGeometry/EsbSuperFGD/EsbConfig/fgdconfig" + ,fgdPosition.X() + ,fgdPosition.Y() + ,fgdPosition.Z() + , kTRUE); + fRun->AddModule(fgd); + + double Bx(0), By(0), Bz(0); + ((geometry::FgdDetector*)fgd)->GetMagneticField(Bx, By, Bz); + double xMin(0), xMax(0), yMin(0), yMax(0), zMin(0), zMax(0); + ((geometry::FgdDetector*)fgd)->GetMagneticFieldRegion(xMin, xMax, yMin, yMax, zMin, zMax); + FairConstField* fgdField = new FairConstField(); + fgdField->SetField(Bx, By, Bz); + fgdField->SetFieldRegion(xMin, xMax, yMin, yMax, zMin, zMax); + fRun->SetField(fgdField); + + // Far Detector + //FairDetector *farWc = new EsbWCDetector("FarWcDetector", 300, 500, kTRUE); + //fRun->AddModule(farWc); + + // Create and Set Event Generator + FairPrimaryGenerator* primGen = new FairPrimaryGenerator(); + fRun->SetGenerator(primGen); + + // *** Set global genie parameters *** + //Genie tune, this is the recommended one + generators::GenieGenerator::GlobalState.fGenieTune = "G18_10a_00_000"; + //File with cross-section splines (see: http://scisoft.fnal.gov/scisoft/packages/genie_xsec/) + generators::GenieGenerator::GlobalState.fXsecSplineFileName = "../../EsbGenerators/xsec/xsec_essnusb.xml"; + // File containing interaction data + generators::GenieGenerator::GlobalState.fOutputFileName = "../../EsbMacro/tests/eventsData.dat"; + + unsigned int seed = 42; + + fair::Logger::SetConsoleSeverity(fair::Severity::info); + fair::Logger::SetConsoleColor(true); + + auto partGen = new generators::superfgd::FgdGenieGenerator( + "../../EsbGeometry/EsbSuperFGD/EsbConfig/fgdconfig" //File with detector configuration + ,"../../EsbMacro/tests/nuFlux/muOnly.txt" //File with neutrino flux + , seed // uniform random number generator seed + , fgdPosition + , nEvents + ); + + partGen->AddPdgCode(13); + partGen->AddPdgCode(-13); + partGen->SetRandomVertex(true); + + + //Add to list of generators + primGen->AddGenerator(partGen); + + fRun->SetOutputFile(outFileName.Data()); // set output file + + // skip magnetic field + + fRun->Init(); + //~ cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! " << nearWc->svList->GetEntries() << endl; + + // Transport nEvents + + // Peter: for the event display to work one need to create a "parameter" + // file. The code is taken from the example from Konstantin Gertsenberger. + // Peter: this is also needed for the reconstruction. + FairRuntimeDb *rtdb = fRun->GetRuntimeDb(); + Bool_t kParameterMerged = kTRUE; + FairParRootFileIo* output = new FairParRootFileIo(kParameterMerged); + output->open("params_mu_only.root"); + rtdb->setOutput(output); + rtdb->saveOutput(); + + fRun->Run(nEvents); + + fRun->CreateGeometryFile("geo_full_mu_only.root"); // for additional full geometry file +} diff --git a/EsbMacro/EsbSuperFGD/muon_only_2_digitize.C b/EsbMacro/EsbSuperFGD/muon_only_2_digitize.C new file mode 100644 index 0000000..32b397c --- /dev/null +++ b/EsbMacro/EsbSuperFGD/muon_only_2_digitize.C @@ -0,0 +1,43 @@ +/* + + Macro that shows how to run the WC digitization on an existing simulation + (e.g., produced with ess_sim.C). + + Based on the example in the presentation from + Konstantin Gertsenberger + + .L ess_dig_fgd.C + ess_dig_fgd() + +*/ + +void muon_only_2_digitize(TString inFile = "evetest_mu_only.root", + TString parFile = "params_mu_only.root", + TString outFile = "fgd_dig_mu_only.root", + Int_t nStartEvent = 0, Int_t nEvents = 25) +{ + using namespace esbroot; + + FairRunAna *fRun= new FairRunAna(); + // Set Input Source and Output file + FairFileSource *fFileSource = new FairFileSource(inFile); + fRun->SetSource(fFileSource); + + fRun->SetSink(new FairRootFileSink(outFile)); + + // ----- Parameter database -------------------------------------------- + FairRuntimeDb* rtdb = fRun->GetRuntimeDb(); + + FairParRootFileIo* parIo1 = new FairParRootFileIo(); + parIo1->open(parFile); + rtdb->setFirstInput(parIo1); + + rtdb->setOutput(parIo1); + rtdb->saveOutput(); + + // Set Tasks for Reconstruction + FairTask* digitizer = new digitizer::superfgd::FgdDigitizer("Granular Task","../../EsbGeometry/EsbSuperFGD/EsbConfig/fgdconfig",0,0,0); + fRun->AddTask(digitizer); + fRun->Init(); // initializing + fRun->Run(nStartEvent, nStartEvent + nEvents); +} diff --git a/EsbMacro/EsbSuperFGD/muon_only_3_reconstruction.C b/EsbMacro/EsbSuperFGD/muon_only_3_reconstruction.C new file mode 100644 index 0000000..56b4377 --- /dev/null +++ b/EsbMacro/EsbSuperFGD/muon_only_3_reconstruction.C @@ -0,0 +1,61 @@ +/* + + Macro that shows how to run the WC digitization on an existing simulation + (e.g., produced with ess_sim.C). + + Based on the example in the presentation from + Konstantin Gertsenberger + + .L ess_dig_fgd.C + ess_dig_fgd() + +*/ + +void muon_only_3_reconstruction(TString inFile = "fgd_dig_mu_only.root", + TString parFile = "params_mu_only.root", + TString outFile = "fgd_recon_mu_only.root", + Int_t nStartEvent = 0, + Int_t nEvents = 25) +{ + using namespace esbroot; + + FairRunAna *fRun= new FairRunAna(); + // Set Input Source and Output file + FairFileSource *fFileSource = new FairFileSource(inFile); + fRun->SetSource(fFileSource); + + fRun->SetSink(new FairRootFileSink(outFile)); + + // ----- Parameter database -------------------------------------------- + FairRuntimeDb* rtdb = fRun->GetRuntimeDb(); + + FairParRootFileIo* parIo1 = new FairParRootFileIo(); + parIo1->open(parFile); + rtdb->setFirstInput(parIo1); + + rtdb->setOutput(parIo1); + rtdb->saveOutput(); + + double debugLvl = 0.0; + + fair::Logger::SetConsoleSeverity(fair::Severity::debug2); + fair::Logger::SetConsoleColor(true); + + FairTask* recon = new reconstruction::superfgd::FgdMuonRecon( + "Reconstruction MC Task" // name of the task + ,"../../EsbGeometry/EsbSuperFGD/EsbConfig/fgdconfig" //File with detector configuration + ,"../../geometry/media.geo" // Media file with defined materials + ,"muOnlyMC.root" // path to output root file + ,"eventsData.dat" // Media file with defined materials + , 1 // Verbose level + , debugLvl // debug level of genfit (0 - little, 1 - debug info, 2 - detailed) + , false // To visualize the tracks using genfit::Eventdisplay + , "D"); // Option to be passed for genfit::Eventdisplay if used + + ((reconstruction::superfgd::FgdMuonRecon*)recon)->SetMinHits(3); + + fRun->AddTask(recon); + fRun->Init(); // initializing + fRun->Run(nStartEvent, nStartEvent + nEvents); + fRun->CreateGeometryFile("geo_recon.root"); // for additional full geometry file +} diff --git a/EsbMacro/EsbSuperFGD/muon_only_5_generate_pics.C b/EsbMacro/EsbSuperFGD/muon_only_5_generate_pics.C new file mode 100644 index 0000000..d682e3e --- /dev/null +++ b/EsbMacro/EsbSuperFGD/muon_only_5_generate_pics.C @@ -0,0 +1,43 @@ +/* + + Macro that shows how to run the WC digitization on an existing simulation + (e.g., produced with ess_sim.C). + + Based on the example in the presentation from + Konstantin Gertsenberger + + .L ess_dig_gen_pics.C + ess_dig_gen_pics() + +*/ + +void muon_only_5_generate_pics(TString inFile = "fgd_dig_mu_only.root", + TString parFile = "params_mu_only.root", + TString outFile = "fgd_dig_gen_pics.root", + Int_t nStartEvent = 0, Int_t nEvents = 25) +{ + using namespace esbroot; + + FairRunAna *fRun= new FairRunAna(); + // Set Input Source and Output file + FairFileSource *fFileSource = new FairFileSource(inFile); + fRun->SetSource(fFileSource); + + fRun->SetSink(new FairRootFileSink(outFile)); + + // ----- Parameter database -------------------------------------------- + FairRuntimeDb* rtdb = fRun->GetRuntimeDb(); + + FairParRootFileIo* parIo1 = new FairParRootFileIo(); + parIo1->open(parFile); + rtdb->setFirstInput(parIo1); + + rtdb->setOutput(parIo1); + rtdb->saveOutput(); + + // Set Tasks for Reconstruction + FairTask* digitizer = new digitizer::superfgd::FgdMppcDisplay("Granular Task","../../EsbGeometry/EsbSuperFGD/EsbConfig/fgdconfig",0,0,0); + fRun->AddTask(digitizer); + fRun->Init(); // initializing + fRun->Run(nStartEvent, nStartEvent + nEvents); +} diff --git a/EsbMacro/EsbSuperFGD/readMCStats.C b/EsbMacro/EsbSuperFGD/readMCStats.C new file mode 100644 index 0000000..1eefd4f --- /dev/null +++ b/EsbMacro/EsbSuperFGD/readMCStats.C @@ -0,0 +1,28 @@ +void readMCStats() +{ + TFile* tf = new TFile("statsRoot.root"); + TTree *tr = (TTree*)tf->Get("FgdMCLeptonStatsReconstructionData"); + + esbroot::reconstruction::superfgd::FgdMCEventRecord* dat = nullptr; + tr->SetBranchAddress("FgdMCLeptonStatsBranch", &dat); + + int entries = tr->GetEntries(); + for(int i=0; i < entries; ++i) + { + cout << " Event " << i << " "<< endl; + tr->GetEntry(i); + dat->ReadEventData(); + const std::vector>& primPars = dat->GetPrimaryParticles(); + cout << " Muon Momentum " << dat->GetMuonMom().Mag() << endl; + cout << " Neutrino Energy " << dat->GetNuE() << endl; + cout << " IsPrimaryLeptonMuon " << dat->IsPrimaryLeptonMuon() << endl; + cout << " IsWeakCC " << dat->IsWeakCC() << endl; + cout << " IsWeakNC " << dat->IsWeakNC() << endl; + cout << " IsQuasiElastic " << dat->IsQuasiElastic() << endl; + for(int j = 0; j < primPars.size(); ++j) + { + cout << " Pdg " << primPars[j].first << endl; + } + cout << "=======================================" << endl; + } +} diff --git a/EsbMacro/EsbSuperFGD/simulate_1_fairgenerator.C b/EsbMacro/EsbSuperFGD/simulate_1_fairgenerator.C new file mode 100644 index 0000000..c9bada3 --- /dev/null +++ b/EsbMacro/EsbSuperFGD/simulate_1_fairgenerator.C @@ -0,0 +1,85 @@ +/* + + Macro that shows how to run a WC simulation. + +*/ + +void simulate_1_fairgenerator(TString outFileName = "evetest.root", + Int_t nStartEvent = 0, + Int_t nEvents = 1) +{ + using namespace esbroot; + + + FairRunSim* fRun = new FairRunSim(); // create the FairRun Class + // Peter: SetStoreTraj seems to be needed for the official Eve + // visualization. It creates the branch GeoTracks in the output tree. + fRun->SetStoreTraj(); + + // Choose the Geant Navigation System + fRun->SetName("TGeant4"); // TGeant3/4 + //~ fRun->SetIsMT(true); + + // Set Material Definition file + fRun->SetMaterials("media.geo"); + + // Add Passive Modules + FairModule *cave= new geometry::Cave("CAVE"); + //~ FairModule *Cave= new FairCave("CAVE"); + cave->SetGeometryFileName("cave.geo"); + fRun->AddModule(cave); + + // Add Detectors + //FairDetector *nearWc = new geometry::WCDetector("NearWcDetector", 300, 500, kTRUE); + //fRun->AddModule(nearWc); + + FairDetector* fgd = new geometry::FgdDetector("Granular Detector","../../EsbGeometry/EsbSuperFGD/EsbConfig/fgdconfig",0,0,0, kTRUE); + fRun->AddModule(fgd); + + double Bx(0), By(0), Bz(0); + ((geometry::FgdDetector*)fgd)->GetMagneticField(Bx, By, Bz); + double xMin(0), xMax(0), yMin(0), yMax(0), zMin(0), zMax(0); + ((geometry::FgdDetector*)fgd)->GetMagneticFieldRegion(xMin, xMax, yMin, yMax, zMin, zMax); + FairConstField* fgdField = new FairConstField(); + fgdField->SetField(Bx, By, Bz); + fgdField->SetFieldRegion(xMin, xMax, yMin, yMax, zMin, zMax); + fRun->SetField(fgdField); + + + // Far Detector + // FairDetector *farWc = new EsbWCDetector("FarWcDetector", 1000, 2000, kTRUE); + // fRun->AddModule(farWc); + + // Create and Set Event Generator + FairPrimaryGenerator* primGen = new FairPrimaryGenerator(); + fRun->SetGenerator(primGen); + + //~ FairParticleGenerator* partGen = new FairParticleGenerator(2212, 1, 0, 0, 1, 0, 0, 0); + //FairParticleGenerator* partGen = new FairParticleGenerator(13, 1, 0, 0, 0.4, 0, 0, 150); + //FairParticleGenerator* partGen = new FairParticleGenerator(2212, 1, 0.1, 0.1, 0.4, 0.5, 0.5, -50); // Initial + FairParticleGenerator* partGen = new FairParticleGenerator(2212, 1, 0., 0., 1.606, 0.5, 0.5, -50); + primGen->AddGenerator(partGen); + + fRun->SetOutputFile(outFileName.Data()); // set output file + + // skip magnetic field + + fRun->Init(); + //~ cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! " << nearWc->svList->GetEntries() << endl; + + // Transport nEvents + + // Peter: for the event display to work one need to create a "parameter" + // file. The code is taken from the example from Konstantin Gertsenberger. + // Peter: this is also needed for the reconstruction. + FairRuntimeDb *rtdb = fRun->GetRuntimeDb(); + Bool_t kParameterMerged = kTRUE; + FairParRootFileIo* output = new FairParRootFileIo(kParameterMerged); + output->open("params.root"); + rtdb->setOutput(output); + rtdb->saveOutput(); + + fRun->Run(nEvents); + + fRun->CreateGeometryFile("geo_full.root"); // for additional full geometry file +} diff --git a/EsbMacro/EsbSuperFGD/simulate_1_fgd_genie_generator.C b/EsbMacro/EsbSuperFGD/simulate_1_fgd_genie_generator.C new file mode 100644 index 0000000..c2a1e0a --- /dev/null +++ b/EsbMacro/EsbSuperFGD/simulate_1_fgd_genie_generator.C @@ -0,0 +1,131 @@ +/* + + Macro that shows how to run a WC simulation. + +*/ + +void simulate_1_fgd_genie_generator(TString outFileName = "evetest.root", + Int_t nStartEvent = 0, + Int_t nEvents = 250) +{ + using namespace esbroot; + + + FairRunSim* fRun = new FairRunSim(); // create the FairRun Class + // Peter: SetStoreTraj seems to be needed for the official Eve + // visualization. It creates the branch GeoTracks in the output tree. + fRun->SetStoreTraj(); + + // Choose the Geant Navigation System + fRun->SetName("TGeant4"); // TGeant3/4 + //~ fRun->SetIsMT(true); + + // Set Material Definition file + fRun->SetMaterials("media.geo"); + + // Add Passive Modules + FairModule *cave= new geometry::Cave("CAVE"); + //~ FairModule *Cave= new FairCave("CAVE"); + cave->SetGeometryFileName("cave.geo"); + fRun->AddModule(cave); + + // Add Detectors + //FairDetector *nearWc = new geometry::WCDetector("NearWcDetector", 300, 500, kTRUE); + //fRun->AddModule(nearWc); + + TVector3 fgdPosition(0,0,-550); + + FairDetector* fgd = new geometry::FgdDetector("Granular Detector","../../EsbGeometry/EsbSuperFGD/EsbConfig/fgdconfig" + ,fgdPosition.X() + ,fgdPosition.Y() + ,fgdPosition.Z() + , kTRUE); + fRun->AddModule(fgd); + + double Bx(0), By(0), Bz(0); + ((geometry::FgdDetector*)fgd)->GetMagneticField(Bx, By, Bz); + double xMin(0), xMax(0), yMin(0), yMax(0), zMin(0), zMax(0); + ((geometry::FgdDetector*)fgd)->GetMagneticFieldRegion(xMin, xMax, yMin, yMax, zMin, zMax); + FairConstField* fgdField = new FairConstField(); + fgdField->SetField(Bx, By, Bz); + fgdField->SetFieldRegion(xMin, xMax, yMin, yMax, zMin, zMax); + fRun->SetField(fgdField); + + // Far Detector + //FairDetector *farWc = new EsbWCDetector("FarWcDetector", 300, 500, kTRUE); + //fRun->AddModule(farWc); + + // Create and Set Event Generator + FairPrimaryGenerator* primGen = new FairPrimaryGenerator(); + fRun->SetGenerator(primGen); + + // *** Set global genie parameters *** + //Genie tune, this is the recommended one + generators::GenieGenerator::GlobalState.fGenieTune = "G18_10a_00_000"; + //File with cross-section splines (see: http://scisoft.fnal.gov/scisoft/packages/genie_xsec/) + generators::GenieGenerator::GlobalState.fXsecSplineFileName = "../../EsbGenerators/xsec/xsec_essnusb.xml"; + // File containing interaction data + generators::GenieGenerator::GlobalState.fOutputFileName = "../../EsbMacro/tests/eventsData.dat"; + + unsigned int seed = 42; + + fair::Logger::SetConsoleSeverity(fair::Severity::info); + fair::Logger::SetConsoleColor(true); + + + //Define TS coordinate system, here it is at a centre of global CS + esbroot::geometry::CoordinateSystem tscs( + ROOT::Math::Rotation3D(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0), + ROOT::Math::XYZVector(0,0,0) + ); + + //Define ND coordinate system + //No rotation, just translation 250m from the proton target + esbroot::geometry::CoordinateSystem ndcs( + ROOT::Math::Rotation3D(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0), + ROOT::Math::XYZVector(0,0, 4500) + ); + + //Create GenieNtpFlux object + //Parameters: name of the file with the flux, name of the tree within the file, neutrino PDG, + // TS coordinate system, ND coordinate system + auto external_fluxDriver = new esbroot::generators::GenieNtpFluxV1("nuData_4x10e6_plus.root", "numuVtx", 14, tscs, ndcs); + + + auto partGen = new generators::superfgd::FgdGenieGenerator( + "../../EsbGeometry/EsbSuperFGD/EsbConfig/fgdconfig" //File with detector configuration + //,"../../EsbMacro/tests/nuFlux/nuFlux100km_250kAm.txt" // File with neutrino flux to use if the external flux driver is not passed + ,"../../EsbMacro/tests/nuFlux/nuFluxTest.txt" // File with neutrino flux to use if the external flux driver is not passed + , seed // uniform random number generator seed + , fgdPosition + , nEvents + , external_fluxDriver + ); + partGen->SetRandomVertex(true); + + //Add to list of generators + primGen->AddGenerator(partGen); + + fRun->SetOutputFile(outFileName.Data()); // set output file + + // skip magnetic field + + fRun->Init(); + //~ cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! " << nearWc->svList->GetEntries() << endl; + + // Transport nEvents + + // Peter: for the event display to work one need to create a "parameter" + // file. The code is taken from the example from Konstantin Gertsenberger. + // Peter: this is also needed for the reconstruction. + FairRuntimeDb *rtdb = fRun->GetRuntimeDb(); + Bool_t kParameterMerged = kTRUE; + FairParRootFileIo* output = new FairParRootFileIo(kParameterMerged); + output->open("params.root"); + rtdb->setOutput(output); + rtdb->saveOutput(); + + fRun->Run(nEvents); + + fRun->CreateGeometryFile("geo_full.root"); // for additional full geometry file +} diff --git a/EsbMacro/EsbSuperFGD/simulate_1_simple_genie_generator.C b/EsbMacro/EsbSuperFGD/simulate_1_simple_genie_generator.C new file mode 100644 index 0000000..1c31798 --- /dev/null +++ b/EsbMacro/EsbSuperFGD/simulate_1_simple_genie_generator.C @@ -0,0 +1,96 @@ +/* + + Macro that shows how to run a WC simulation. + +*/ + +void simulate_1_simple_genie_generator(TString outFileName = "evetest.root", + Int_t nStartEvent = 0, + Int_t nEvents = 25) +{ + using namespace esbroot; + + + FairRunSim* fRun = new FairRunSim(); // create the FairRun Class + // Peter: SetStoreTraj seems to be needed for the official Eve + // visualization. It creates the branch GeoTracks in the output tree. + fRun->SetStoreTraj(); + + // Choose the Geant Navigation System + fRun->SetName("TGeant4"); // TGeant3/4 + //~ fRun->SetIsMT(true); + + // Set Material Definition file + fRun->SetMaterials("media.geo"); + + // Add Passive Modules + FairModule *cave= new geometry::Cave("CAVE"); + //~ FairModule *Cave= new FairCave("CAVE"); + cave->SetGeometryFileName("cave.geo"); + fRun->AddModule(cave); + + // Add Detectors + // FairDetector *nearWc = new geometry::WCDetector("NearWcDetector", 300, 500, kTRUE); + // fRun->AddModule(nearWc); + + FairDetector* fgd = new geometry::FgdDetector("Granular Detector","../../EsbGeometry/EsbSuperFGD/EsbConfig/fgdconfig",0,0,-550, kTRUE); + fRun->AddModule(fgd); + + double Bx(0), By(0), Bz(0); + ((geometry::FgdDetector*)fgd)->GetMagneticField(Bx, By, Bz); + double xMin(0), xMax(0), yMin(0), yMax(0), zMin(0), zMax(0); + ((geometry::FgdDetector*)fgd)->GetMagneticFieldRegion(xMin, xMax, yMin, yMax, zMin, zMax); + FairConstField* fgdField = new FairConstField(); + fgdField->SetField(Bx, By, Bz); + fgdField->SetFieldRegion(xMin, xMax, yMin, yMax, zMin, zMax); + fRun->SetField(fgdField); + + // Far Detector + //FairDetector *farWc = new EsbWCDetector("FarWcDetector", 300, 500, kTRUE); + //fRun->AddModule(farWc); + + // Create and Set Event Generator + FairPrimaryGenerator* primGen = new FairPrimaryGenerator(); + fRun->SetGenerator(primGen); + + // *** Set global genie parameters *** + //Genie tune, this is the recommended one + generators::GenieGenerator::GlobalState.fGenieTune = "G18_10a_00_000"; + //File with cross-section splines (see: http://scisoft.fnal.gov/scisoft/packages/genie_xsec/) + generators::GenieGenerator::GlobalState.fXsecSplineFileName = "../../EsbGenerators/xsec/xsec_essnusb.xml"; + + //Create simple genie generator + auto partGen = new generators::SimpleGenieGenerator( + 1000080160, //Target PDG (O16) + 14, //Neutrino PDG (nu_mu) + 0.6, //Neutrino energy (GeV) + TVector3(0.0,0.0,1.0), //Neutrino directon (normalization of this vector is not important) + TLorentzVector(0.0, 0.0, -550., 0.0) //4-position of the neutrino vertex (x, y, z, t) (cm, s) + ); + + //Add to list of generators + primGen->AddGenerator(partGen); + + fRun->SetOutputFile(outFileName.Data()); // set output file + + // skip magnetic field + + fRun->Init(); + //~ cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! " << nearWc->svList->GetEntries() << endl; + + // Transport nEvents + + // Peter: for the event display to work one need to create a "parameter" + // file. The code is taken from the example from Konstantin Gertsenberger. + // Peter: this is also needed for the reconstruction. + FairRuntimeDb *rtdb = fRun->GetRuntimeDb(); + Bool_t kParameterMerged = kTRUE; + FairParRootFileIo* output = new FairParRootFileIo(kParameterMerged); + output->open("params.root"); + rtdb->setOutput(output); + rtdb->saveOutput(); + + fRun->Run(nEvents); + + fRun->CreateGeometryFile("geo_full.root"); // for additional full geometry file +} diff --git a/EsbMacro/EsbSuperFGD/simulate_2_digitize.C b/EsbMacro/EsbSuperFGD/simulate_2_digitize.C new file mode 100644 index 0000000..8eaa0e3 --- /dev/null +++ b/EsbMacro/EsbSuperFGD/simulate_2_digitize.C @@ -0,0 +1,43 @@ +/* + + Macro that shows how to run the WC digitization on an existing simulation + (e.g., produced with ess_sim.C). + + Based on the example in the presentation from + Konstantin Gertsenberger + + .L ess_dig_fgd.C + ess_dig_fgd() + +*/ + +void simulate_2_digitize(TString inFile = "evetest.root", + TString parFile = "params.root", + TString outFile = "fgd_dig.root", + Int_t nStartEvent = 0, Int_t nEvents = 25) +{ + using namespace esbroot; + + FairRunAna *fRun= new FairRunAna(); + // Set Input Source and Output file + FairFileSource *fFileSource = new FairFileSource(inFile); + fRun->SetSource(fFileSource); + + fRun->SetSink(new FairRootFileSink(outFile)); + + // ----- Parameter database -------------------------------------------- + FairRuntimeDb* rtdb = fRun->GetRuntimeDb(); + + FairParRootFileIo* parIo1 = new FairParRootFileIo(); + parIo1->open(parFile); + rtdb->setFirstInput(parIo1); + + rtdb->setOutput(parIo1); + rtdb->saveOutput(); + + // Set Tasks for Reconstruction + FairTask* digitizer = new digitizer::superfgd::FgdDigitizer("Granular Task","../../EsbGeometry/EsbSuperFGD/EsbConfig/fgdconfig",0,0,0); + fRun->AddTask(digitizer); + fRun->Init(); // initializing + fRun->Run(nStartEvent, nStartEvent + nEvents); +} diff --git a/EsbMacro/EsbSuperFGD/simulate_3_MC_lepton_stats.C b/EsbMacro/EsbSuperFGD/simulate_3_MC_lepton_stats.C new file mode 100644 index 0000000..65bef8d --- /dev/null +++ b/EsbMacro/EsbSuperFGD/simulate_3_MC_lepton_stats.C @@ -0,0 +1,60 @@ +/* + + Macro that shows how to run the WC digitization on an existing simulation + (e.g., produced with ess_sim.C). + + Based on the example in the presentation from + Konstantin Gertsenberger + + .L ess_dig_fgd.C + ess_dig_fgd() + +*/ + +void simulate_3_MC_lepton_stats(TString inFile = "fgd_dig.root", + TString parFile = "params.root", + TString outFile = "fgd_mc_recon_stats.root", + Int_t nStartEvent = 0, Int_t nEvents = 50) +{ + using namespace esbroot; + + FairRunAna *fRun= new FairRunAna(); + // Set Input Source and Output file + FairFileSource *fFileSource = new FairFileSource(inFile); + fRun->SetSource(fFileSource); + + fRun->SetSink(new FairRootFileSink(outFile)); + + // ----- Parameter database -------------------------------------------- + FairRuntimeDb* rtdb = fRun->GetRuntimeDb(); + + FairParRootFileIo* parIo1 = new FairParRootFileIo(); + parIo1->open(parFile); + rtdb->setFirstInput(parIo1); + + rtdb->setOutput(parIo1); + rtdb->saveOutput(); + + double debugLvl = 0.0; + + fair::Logger::SetConsoleSeverity(fair::Severity::debug2); + fair::Logger::SetConsoleColor(true); + + FairTask* recon = new reconstruction::superfgd::FgdMCLeptonStats( + "Reconstruction MC Task" // name of the task + ,"../../EsbGeometry/EsbSuperFGD/EsbConfig/fgdconfig" //File with detector configuration + ,"../../geometry/media.geo" // Media file with defined materials + ,"../../EsbMacro/tests/eventsData.dat" // events data file + ,"../../EsbMacro/tests/statsRoot.root" // output root file + , 1 // Verbose level + , debugLvl // debug level of genfit (0 - little, 1 - debug info, 2 - detailed) + ); + + ((reconstruction::superfgd::FgdMCLeptonStats*)recon)->SetMinHits(3); + + + fRun->AddTask(recon); + fRun->Init(); // initializing + fRun->Run(nStartEvent, nStartEvent + nEvents); + fRun->CreateGeometryFile("geo_recon_mc_lepton.root"); // for additional full geometry file +} diff --git a/EsbMacro/EsbSuperFGD/simulate_3_MC_reconstruction.C b/EsbMacro/EsbSuperFGD/simulate_3_MC_reconstruction.C new file mode 100644 index 0000000..16d8856 --- /dev/null +++ b/EsbMacro/EsbSuperFGD/simulate_3_MC_reconstruction.C @@ -0,0 +1,59 @@ +/* + + Macro that shows how to run the WC digitization on an existing simulation + (e.g., produced with ess_sim.C). + + Based on the example in the presentation from + Konstantin Gertsenberger + + .L ess_dig_fgd.C + ess_dig_fgd() + +*/ + +void simulate_3_MC_reconstruction(TString inFile = "fgd_dig.root", + TString parFile = "params.root", + TString outFile = "fgd_recon.root", + Int_t nStartEvent = 7, Int_t nEvents = 1) +{ + using namespace esbroot; + + FairRunAna *fRun= new FairRunAna(); + // Set Input Source and Output file + FairFileSource *fFileSource = new FairFileSource(inFile); + fRun->SetSource(fFileSource); + + fRun->SetSink(new FairRootFileSink(outFile)); + + // ----- Parameter database -------------------------------------------- + FairRuntimeDb* rtdb = fRun->GetRuntimeDb(); + + FairParRootFileIo* parIo1 = new FairParRootFileIo(); + parIo1->open(parFile); + rtdb->setFirstInput(parIo1); + + rtdb->setOutput(parIo1); + rtdb->saveOutput(); + + double debugLvl = 0.0; + + fair::Logger::SetConsoleSeverity(fair::Severity::debug2); + fair::Logger::SetConsoleColor(true); + + FairTask* recon = new reconstruction::superfgd::FgdMCGenFitRecon( + "Reconstruction MC Task" // name of the task + ,"../../EsbGeometry/EsbSuperFGD/EsbConfig/fgdconfig" //File with detector configuration + ,"../../geometry/media.geo" // Media file with defined materials + , 1 // Verbose level + , debugLvl // debug level of genfit (0 - little, 1 - debug info, 2 - detailed) + , true // To visualize the tracks using genfit::Eventdisplay + , "D"); // Option to be passed for genfit::Eventdisplay if used + + ((reconstruction::superfgd::FgdMCGenFitRecon*)recon)->SetMinHits(3); + + + fRun->AddTask(recon); + fRun->Init(); // initializing + fRun->Run(nStartEvent, nStartEvent + nEvents); + fRun->CreateGeometryFile("geo_recon.root"); // for additional full geometry file +} diff --git a/EsbMacro/EsbSuperFGD/simulate_3_reconstruction.C b/EsbMacro/EsbSuperFGD/simulate_3_reconstruction.C new file mode 100644 index 0000000..def1be5 --- /dev/null +++ b/EsbMacro/EsbSuperFGD/simulate_3_reconstruction.C @@ -0,0 +1,69 @@ +/* + + Macro that shows how to run the WC digitization on an existing simulation + (e.g., produced with ess_sim.C). + + Based on the example in the presentation from + Konstantin Gertsenberger + + .L ess_dig_fgd.C + ess_dig_fgd() + +*/ + +void simulate_3_reconstruction(TString inFile = "fgd_dig.root", + TString parFile = "params.root", + TString outFile = "fgd_recon.root", + Int_t nStartEvent = 0, Int_t nEvents = 1) +{ + using namespace esbroot; + + FairRunAna *fRun= new FairRunAna(); + // Set Input Source and Output file + FairFileSource *fFileSource = new FairFileSource(inFile); + fRun->SetSource(fFileSource); + + fRun->SetSink(new FairRootFileSink(outFile)); + + // ----- Parameter database -------------------------------------------- + FairRuntimeDb* rtdb = fRun->GetRuntimeDb(); + + FairParRootFileIo* parIo1 = new FairParRootFileIo(); + parIo1->open(parFile); + rtdb->setFirstInput(parIo1); + + rtdb->setOutput(parIo1); + rtdb->saveOutput(); + + double debugLvl = 0.0; + + fair::Logger::SetConsoleSeverity(fair::Severity::debug2); + fair::Logger::SetConsoleColor(true); + + FairTask* recon = new reconstruction::superfgd::FgdGenFitRecon( + "Reconstruction Task" // name of the task + ,"../../EsbGeometry/EsbSuperFGD/EsbConfig/fgdconfig" //File with detector configuration + ,"../../geometry/media.geo" // Media file with defined materials + , 1 // Verbose level + , debugLvl // debug level of genfit (0 - little, 1 - debug info, 2 - detailed) + , false // To visualize the tracks using genfit::Eventdisplay + , "D"); // Option to be passed for genfit::Eventdisplay if used + + ((reconstruction::superfgd::FgdGenFitRecon*)recon)->SetMinHits(3); + // ((reconstruction::superfgd::FgdGenFitRecon*)recon)->SetUseTracker(reconstruction::superfgd::FgdGenFitRecon::TrackFinder::HOUGH_PATHFINDER_LINE); + // ((reconstruction::superfgd::FgdGenFitRecon*)recon)->SetUseTracker(reconstruction::superfgd::FgdGenFitRecon::TrackFinder::HOUGH_PATHFINDER_HELIX); + // ((reconstruction::superfgd::FgdGenFitRecon*)recon)->SetUseTracker(reconstruction::superfgd::FgdGenFitRecon::TrackFinder::HOUGH_PATHFINDER_CURL); + ((reconstruction::superfgd::FgdGenFitRecon*)recon)->SetUseTracker(reconstruction::superfgd::FgdGenFitRecon::TrackFinder::GRAPH); + // ((reconstruction::superfgd::FgdGenFitRecon*)recon)->SetUseTracker(reconstruction::superfgd::FgdGenFitRecon::TrackFinder::GRAPH_HOUGH_PATHFINDER); + + + ((reconstruction::superfgd::FgdGenFitRecon*)recon)->AddPdgMomLoss(11, 9. , 6.); + ((reconstruction::superfgd::FgdGenFitRecon*)recon)->AddPdgMomLoss(13, 21. , 5.); + ((reconstruction::superfgd::FgdGenFitRecon*)recon)->AddPdgMomLoss(211, 28. , 1.); + ((reconstruction::superfgd::FgdGenFitRecon*)recon)->AddPdgMomLoss(2212, 148. , 63.); + + fRun->AddTask(recon); + fRun->Init(); // initializing + fRun->Run(nStartEvent, nStartEvent + nEvents); + fRun->CreateGeometryFile("geo_recon.root"); // for additional full geometry file +} diff --git a/EsbMacro/EsbSuperFGD/simulate_4_eventDisplay.C b/EsbMacro/EsbSuperFGD/simulate_4_eventDisplay.C new file mode 100644 index 0000000..34eadb3 --- /dev/null +++ b/EsbMacro/EsbSuperFGD/simulate_4_eventDisplay.C @@ -0,0 +1,57 @@ +/******************************************************************************** + * Copyright (C) 2014 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH * + * * + * This software is distributed under the terms of the * + * GNU Lesser General Public Licence (LGPL) version 3, * + * copied verbatim in the file "LICENSE" * + ********************************************************************************/ + +/* + + How to use: + .L eventDisplay.C + FairEventManager* man = eventDisplay(); + man->NextEvent(); + + */ + +FairEventManager* simulate_4_eventDisplay(Bool_t addTracks=kTRUE, + Bool_t addPoints=kTRUE /* kFALSE*/ ) +{ + + using namespace esbroot; + + TString inFile = "evetest.root"; + TString parFile = "params.root"; + TString outFile = "out.root"; + + // ----- Reconstruction run ------------------------------------------- + FairRunAna *fRun= new FairRunAna(); + FairFileSource *fFileSource = new FairFileSource(inFile); + fRun->SetSource(fFileSource); + + fRun->SetSink(new FairRootFileSink(outFile)); + + // ----- Parameter database -------------------------------------------- + FairRuntimeDb* rtdb = fRun->GetRuntimeDb(); + + FairParRootFileIo* parIo1 = new FairParRootFileIo(); + parIo1->open(parFile); + rtdb->setFirstInput(parIo1); + // ------------------------------------------------------------------------ + + + + FairEventManager *fMan = new FairEventManager (); + FairMCTracks *Track = new FairMCTracks ("MCTrack"); + FairMCPointDraw *EsbPoints = new FairMCPointDraw ("FgdDetectorPoint",kBlue , kFullSquare); + + if(addTracks) + fMan->AddTask(Track); + if(addPoints) + fMan->AddTask(EsbPoints); + + + fMan->Init(); + return fMan; +} diff --git a/EsbMacro/EsbSuperFGD/simulate_5_generate_pics.C b/EsbMacro/EsbSuperFGD/simulate_5_generate_pics.C new file mode 100644 index 0000000..46fbe41 --- /dev/null +++ b/EsbMacro/EsbSuperFGD/simulate_5_generate_pics.C @@ -0,0 +1,43 @@ +/* + + Macro that shows how to run the WC digitization on an existing simulation + (e.g., produced with ess_sim.C). + + Based on the example in the presentation from + Konstantin Gertsenberger + + .L ess_dig_gen_pics.C + ess_dig_gen_pics() + +*/ + +void simulate_5_generate_pics(TString inFile = "fgd_dig.root", + TString parFile = "params.root", + TString outFile = "fgd_dig_gen_pics.root", + Int_t nStartEvent = 0, Int_t nEvents = 25) +{ + using namespace esbroot; + + FairRunAna *fRun= new FairRunAna(); + // Set Input Source and Output file + FairFileSource *fFileSource = new FairFileSource(inFile); + fRun->SetSource(fFileSource); + + fRun->SetSink(new FairRootFileSink(outFile)); + + // ----- Parameter database -------------------------------------------- + FairRuntimeDb* rtdb = fRun->GetRuntimeDb(); + + FairParRootFileIo* parIo1 = new FairParRootFileIo(); + parIo1->open(parFile); + rtdb->setFirstInput(parIo1); + + rtdb->setOutput(parIo1); + rtdb->saveOutput(); + + // Set Tasks for Reconstruction + FairTask* digitizer = new digitizer::superfgd::FgdMppcDisplay("Granular Task","../../EsbGeometry/EsbSuperFGD/EsbConfig/fgdconfig",0,0,0); + fRun->AddTask(digitizer); + fRun->Init(); // initializing + fRun->Run(nStartEvent, nStartEvent + nEvents); +} diff --git a/EsbMacro/EsbSuperFGD/simulate_7_graph_analyze.C b/EsbMacro/EsbSuperFGD/simulate_7_graph_analyze.C new file mode 100644 index 0000000..2a7a66f --- /dev/null +++ b/EsbMacro/EsbSuperFGD/simulate_7_graph_analyze.C @@ -0,0 +1,60 @@ +/* + + Macro that shows how to run the WC digitization on an existing simulation + (e.g., produced with ess_sim.C). + + Based on the example in the presentation from + Konstantin Gertsenberger + + .L simulate_7_graph_analyze.C + simulate_7_graph_analyze() + +*/ + +void simulate_7_graph_analyze(TString inFile = "fgd_dig.root", + TString parFile = "params.root", + TString outFile = "fgd_mc_recon_stats.root", + Int_t nStartEvent = 0, Int_t nEvents = 5) +{ + using namespace esbroot; + + FairRunAna *fRun= new FairRunAna(); + // Set Input Source and Output file + FairFileSource *fFileSource = new FairFileSource(inFile); + fRun->SetSource(fFileSource); + + fRun->SetSink(new FairRootFileSink(outFile)); + + // ----- Parameter database -------------------------------------------- + FairRuntimeDb* rtdb = fRun->GetRuntimeDb(); + + FairParRootFileIo* parIo1 = new FairParRootFileIo(); + parIo1->open(parFile); + rtdb->setFirstInput(parIo1); + + rtdb->setOutput(parIo1); + rtdb->saveOutput(); + + double debugLvl = 0.0; + + fair::Logger::SetConsoleSeverity(fair::Severity::info); + fair::Logger::SetConsoleColor(true); + + reconstruction::superfgd::FgdGraphStats* recon = new reconstruction::superfgd::FgdGraphStats( + "Reconstruction Graph Analyzer" // name of the task + ,"../../EsbGeometry/EsbSuperFGD/EsbConfig/fgdconfig" //File with detector configuration + ,"../../geometry/media.geo" // Media file with defined materials + ,"../../EsbMacro/tests/eventsData.dat" // events data file + ,"../../EsbMacro/tests/statsRoot.root" // output root file + , 1 // Verbose level + , debugLvl // debug level of genfit (0 - little, 1 - debug info, 2 - detailed) + ); + + ((reconstruction::superfgd::FgdMCLeptonStats*)recon)->SetMinHits(3); + + + fRun->AddTask(recon); + fRun->Init(); // initializing + fRun->Run(nStartEvent, nStartEvent + nEvents); + fRun->CreateGeometryFile("geo_recon_mc_lepton.root"); // for additional full geometry file +} diff --git a/EsbMacro/GenieNtpFluxV1Test.C b/EsbMacro/GenieNtpFluxV1Test.C new file mode 100644 index 0000000..02df049 --- /dev/null +++ b/EsbMacro/GenieNtpFluxV1Test.C @@ -0,0 +1,118 @@ +int GenieNtpFluxV1Test(void) +{ + using namespace esbroot; + + //~ int nEvents = 100; + int nEvents = 10; + const char* out_file_name = "GenieNtpFluxV1Test.root"; + + FairRunSim* fRun = new FairRunSim(); // create the FairRun Class + // Peter: SetStoreTraj seems to be needed for the official Eve + // visualization. It creates the branch GeoTracks in the output tree. + fRun->SetStoreTraj(); + + // Choose the Geant Navigation System + fRun->SetName("TGeant4"); // TGeant3/4 + + // Set Material Definition file + fRun->SetMaterials("media.geo"); + + // Add Passive Modules + FairModule *cave= new geometry::Cave("CAVE"); + cave->SetGeometryFileName("cave.geo"); + fRun->AddModule(cave); + + // Add Detectors + FairDetector *nearWc = new geometry::WCDetector("NearWcDetector", 300, 500, kTRUE); + fRun->AddModule(nearWc); + + FairDetector* fgd = new geometry::FgdDetector( + "Granular Detector", + "../EsbGeometry/EsbSuperFGD/EsbConfig/geometry", + 0,0,-550, kTRUE + ); + fRun->AddModule(fgd); + + double Bx(0), By(0), Bz(0); + ((geometry::FgdDetector*)fgd)->GetMagneticField(Bx, By, Bz); + double xMin(0), xMax(0), yMin(0), yMax(0), zMin(0), zMax(0); + ((geometry::FgdDetector*)fgd)->GetMagneticFieldRegion(xMin, xMax, yMin, yMax, zMin, zMax); + FairConstField* fgdField = new FairConstField(); + fgdField->SetField(Bx, By, Bz); + fgdField->SetFieldRegion(xMin, xMax, yMin, yMax, zMin, zMax); + fRun->SetField(fgdField); + + + // Create and Set Event Generator + FairPrimaryGenerator* primGen = new FairPrimaryGenerator(); + fRun->SetGenerator(primGen); + + // *** Set global genie parameters *** + //Genie tune, this is the recommended one + generators::GenieGenerator::GlobalState.fGenieTune = "G18_10a_00_000"; + //File with cross-section splines (see: http://scisoft.fnal.gov/scisoft/packages/genie_xsec/) + generators::GenieGenerator::GlobalState.fXsecSplineFileName = + "/home/bklicek/sync/ESSnuSB/soft/genie_xsec/genie_xsec/v3_00_06/NULL/G1810a00000-k250-e1000/data/gxspl-FNALsmall.xml"; + + //Define TS coordinate system, here it is at a centre of global CS + esbroot::geometry::CoordinateSystem tscs( + ROOT::Math::Rotation3D(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0), + ROOT::Math::XYZVector(0,0,0) + ); + + //Define ND coordinate system + //No rotation, just translation 250m from the proton target + esbroot::geometry::CoordinateSystem ndcs( + ROOT::Math::Rotation3D(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0), + ROOT::Math::XYZVector(0,0,25000) + ); + + //Create GenieNtpFlux object + //Parameters: name of the file with the flux, name of the tree within the file, neutrino PDG, + // TS coordinate system, ND coordinate system + auto test_flux = new esbroot::generators::GenieNtpFluxV1("nuData_4x10e6_plus.root", "numuVtx", 14, tscs, ndcs); + + //Point geometry just for testing, can be replaced by real geometry + auto geomI = new genie::geometry::PointGeomAnalyzer(1000080160); + + //Create an instance of the generator and configure it + auto partGen = new generators::GenieGenerator(test_flux, geomI); + partGen->Configure(); + + //Set it as a primary generator + primGen->AddGenerator(partGen); + + + fRun->SetOutputFile(out_file_name); // set output file + + fRun->Init(); + + fRun->GetSink()->WriteObject(gGeoManager, "geometry"); + + // Peter: for the event display to work one need to create a "parameter" + // file. The code is taken from the example from Konstantin Gertsenberger. + // Peter: this is also needed for the reconstruction. + FairRuntimeDb *rtdb = fRun->GetRuntimeDb(); + Bool_t kParameterMerged = kTRUE; + FairParRootFileIo* output = new FairParRootFileIo(kParameterMerged); + output->open("params.root"); + rtdb->setOutput(output); + rtdb->saveOutput(); + + fRun->Run(nEvents); + + + //~ fRun->CreateGeometryFile("geo_full.root"); // for additional full geometry file + + //~ while( test_flux.GenerateNext() ) { + //~ test_flux.Momentum().Print(); + //~ test_flux.Position().Print(); + //~ cout << endl; + //~ } + + //~ test_flux.Clear(); + + return(0); +} + + diff --git a/EsbMacro/ess_near_genie.C b/EsbMacro/ess_near_genie.C new file mode 100644 index 0000000..6ff1a1f --- /dev/null +++ b/EsbMacro/ess_near_genie.C @@ -0,0 +1,92 @@ +/* + + Macro that shows how to run a WC simulation. + +*/ + +void ess_near_genie(TString outFileName = "ess_near_genie.root", + Int_t nStartEvent = 0, + Int_t nEvents = 10) +{ + using namespace esbroot; + + FairRunSim* fRun = new FairRunSim(); // create the FairRun Class + // Peter: SetStoreTraj seems to be needed for the official Eve + // visualization. It creates the branch GeoTracks in the output tree. + fRun->SetStoreTraj(); + + // Choose the Geant Navigation System + fRun->SetName("TGeant4"); // TGeant3/4 + + // Set Material Definition file + fRun->SetMaterials("media.geo"); + + // Add Passive Modules + FairModule *cave= new geometry::Cave("CAVE"); + cave->SetGeometryFileName("cave.geo"); + fRun->AddModule(cave); + + // Add Detectors + FairDetector *nearWc = new geometry::WCDetector("NearWcDetector", 300, 500, kTRUE); + fRun->AddModule(nearWc); + + FairDetector* fgd = new geometry::FgdDetector( + "Granular Detector", + "../EsbGeometry/EsbSuperFGD/EsbConfig/geometry", + 0,0,-550, kTRUE + ); + fRun->AddModule(fgd); + + double Bx(0), By(0), Bz(0); + ((geometry::FgdDetector*)fgd)->GetMagneticField(Bx, By, Bz); + double xMin(0), xMax(0), yMin(0), yMax(0), zMin(0), zMax(0); + ((geometry::FgdDetector*)fgd)->GetMagneticFieldRegion(xMin, xMax, yMin, yMax, zMin, zMax); + FairConstField* fgdField = new FairConstField(); + fgdField->SetField(Bx, By, Bz); + fgdField->SetFieldRegion(xMin, xMax, yMin, yMax, zMin, zMax); + fRun->SetField(fgdField); + + + // Create and Set Event Generator + FairPrimaryGenerator* primGen = new FairPrimaryGenerator(); + fRun->SetGenerator(primGen); + + // *** Set global genie parameters *** + //Genie tune, this is the recommended one + generators::GenieGenerator::GlobalState.fGenieTune = "G18_10a_00_000"; + //File with cross-section splines (see: http://scisoft.fnal.gov/scisoft/packages/genie_xsec/) + generators::GenieGenerator::GlobalState.fXsecSplineFileName = "../../xsec/xsec_essnusb.xml"; + + //Create simple genie generator + auto partGen = new generators::SimpleGenieGenerator( + 1000080160, //Target PDG (O16) + 14, //Neutrino PDG (nu_mu) + 0.6, //Neutrino energy (GeV) + TVector3(1.0,0.0,0.0), //Neutrino directon (normalization of this vector is not important) + TLorentzVector(0.0, 0.0, -550, 0.0) //4-position of the neutrino vertex (x, y, z, t) (cm, s) + ); + + //Add to list of generators + primGen->AddGenerator(partGen); + + fRun->SetOutputFile(outFileName.Data()); // set output file + + fRun->Init(); + + fRun->GetSink()->WriteObject(gGeoManager, "geometry"); + + // Peter: for the event display to work one need to create a "parameter" + // file. The code is taken from the example from Konstantin Gertsenberger. + // Peter: this is also needed for the reconstruction. + FairRuntimeDb *rtdb = fRun->GetRuntimeDb(); + Bool_t kParameterMerged = kTRUE; + FairParRootFileIo* output = new FairParRootFileIo(kParameterMerged); + output->open("params.root"); + rtdb->setOutput(output); + rtdb->saveOutput(); + + fRun->Run(nEvents); + + + //~ fRun->CreateGeometryFile("geo_full.root"); // for additional full geometry file +} diff --git a/EsbMacro/ess_sim_genie.C b/EsbMacro/ess_sim_genie.C new file mode 100644 index 0000000..9db5c4b --- /dev/null +++ b/EsbMacro/ess_sim_genie.C @@ -0,0 +1,75 @@ +/* + + Macro that shows how to run a WC simulation. + +*/ + +void ess_sim_genie(TString outFileName = "evetest.root", + Int_t nStartEvent = 0, + Int_t nEvents = 1) +{ + using namespace esbroot; + + FairRunSim* fRun = new FairRunSim(); // create the FairRun Class + // Peter: SetStoreTraj seems to be needed for the official Eve + // visualization. It creates the branch GeoTracks in the output tree. + fRun->SetStoreTraj(); + + // Choose the Geant Navigation System + fRun->SetName("TGeant4"); // TGeant3/4 + + // Set Material Definition file + fRun->SetMaterials("media.geo"); + + // Add Passive Modules + FairModule *cave= new geometry::Cave("CAVE"); + cave->SetGeometryFileName("cave.geo"); + fRun->AddModule(cave); + + // Add Detectors + FairDetector *nearWc = new geometry::WCDetector("NearWcDetector", 300, 500, kTRUE); + fRun->AddModule(nearWc); + + + // Create and Set Event Generator + FairPrimaryGenerator* primGen = new FairPrimaryGenerator(); + fRun->SetGenerator(primGen); + + // *** Set global genie parameters *** + //Genie tune, this is the recommended one + generators::GenieGenerator::GlobalState.fGenieTune = "G18_10a_00_000"; + //File with cross-section splines (see: http://scisoft.fnal.gov/scisoft/packages/genie_xsec/) + generators::GenieGenerator::GlobalState.fXsecSplineFileName = "../../xsec/xsec_essnusb.xml"; + + //Create simple genie generator + auto partGen = new generators::SimpleGenieGenerator( + 1000080160, //Target PDG (O16) + 14, //Neutrino PDG (nu_mu) + 0.6, //Neutrino energy (GeV) + TVector3(1.0,0.0,0.0), //Neutrino directon (normalization of this vector is not important) + TLorentzVector(0.0, 0.0, 0.0, 0.0) //4-position of the neutrino vertex (x, y, z, t) (cm, s) + ); + + //Add to list of generators + primGen->AddGenerator(partGen); + + + fRun->SetOutputFile(outFileName.Data()); // set output file + + fRun->Init(); + + + // Peter: for the event display to work one need to create a "parameter" + // file. The code is taken from the example from Konstantin Gertsenberger. + // Peter: this is also needed for the reconstruction. + FairRuntimeDb *rtdb = fRun->GetRuntimeDb(); + Bool_t kParameterMerged = kTRUE; + FairParRootFileIo* output = new FairParRootFileIo(kParameterMerged); + output->open("params.root"); + rtdb->setOutput(output); + rtdb->saveOutput(); + + fRun->Run(nEvents); + + fRun->CreateGeometryFile("geo_full.root"); // for additional full geometry file +} diff --git a/EsbMacro/find_ring_pmts.C b/EsbMacro/find_ring_pmts.C new file mode 100644 index 0000000..25b7641 --- /dev/null +++ b/EsbMacro/find_ring_pmts.C @@ -0,0 +1,408 @@ +/* + + Macro that can display the WC digits + (e.g., produced by ess_reco.C) + +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +TGraph* get_cone_projection(TVector3 pos, + TVector3 dir, + const Double_t theta, + const Int_t n_steps = 100, + const Double_t r_d = 300, // cm + const Double_t l_d = 1000); // cm + +void find_ring_pmts(const Char_t* file_name="dst.root", + Int_t event=0, + const Double_t r_accept = 0, + const Int_t n_min_pmts_in_ring = 50, + const Int_t max_n_rings = 2, + const Double_t r_d = 300, // cm + const Double_t l_d = 1000) // cm +{ + + using namespace esbroot; + + gStyle->SetOptStat(0); + + TFile* file = new TFile(file_name); + TTree* tree = (TTree*)file->Get("cbmsim"); + + Int_t n_event = (Int_t)tree->GetEntries(); + cout << " Number of events = " << n_event << endl; + + TClonesArray* pmt_array = 0; + tree->SetBranchAddress("PMTubeHit", &pmt_array); + + tree->GetEntry(event); + + data::PMTubeHit::sortOption = 1; + + pmt_array->Sort(); + + Int_t n_pmt = (Int_t)pmt_array->GetEntries(); + + cout << "Number of PMT signals: " << n_pmt << endl; + + if(n_pmt <= 0) + return; + + // RefIndex is used to assign clusters to a ring. Start by "unsetting" it + for (Int_t n = 0; n < n_pmt; n++) { + + auto pmt = (data::PMTubeHit*)pmt_array->At(n); + pmt->SetRefIndex(0); + } + + Int_t n_ring = 0; + Bool_t more_rings = kTRUE; + + while(n_ring < max_n_rings && more_rings) { + + // Find first pmt to be checked + TObjArray* ring_array = new TObjArray(100); + more_rings = kFALSE; + Int_t n_pmt_in_ring = 0; + for (Int_t n = 0; n < n_pmt; n++) { + + auto pmt = (data::PMTubeHit*)pmt_array->At(n); + if(pmt->GetRefIndex() == 0) { + + more_rings = kTRUE; + ring_array->Add(pmt); + pmt->SetRefIndex(1); + n_pmt_in_ring = 1; + break; + } + } + + Int_t n_checked = 0; + Double_t mean_x = 0; + Double_t mean_y = 0; + Double_t mean_z = 0; + Double_t mean_t = 0; + + while (n_checked < n_pmt_in_ring) { + + auto pmt_check = (data::PMTubeHit*)ring_array->At(n_checked); + const Double_t x_check = pmt_check->GetX(); + const Double_t y_check = pmt_check->GetY(); + const Double_t z_check = pmt_check->GetZ(); + const Double_t t_check = pmt_check->GetTime(); + + mean_x += x_check; + mean_y += y_check; + mean_z += z_check; + mean_t += t_check; + + for (Int_t n = 0; n < n_pmt; n++) { + + auto pmt = (data::PMTubeHit*)pmt_array->At(n); + + if(pmt->GetRefIndex() == 1) + continue; + + // cout << pmt->GetCharge() << endl; + + if(pmt == pmt_check) { + cout << "Skip " << n_checked << endl; + } + + const Double_t dx = pmt->GetX() - x_check; + const Double_t dy = pmt->GetY() - y_check; + const Double_t dz = pmt->GetZ() - z_check; + const Double_t cdt = 30*(pmt->GetTime() - t_check); // c=30cm/ns + + if(dx*dx + dy*dy + dz*dz + cdt*cdt < r_accept*r_accept) { + // if(dx*dx + dy*dy + dz*dz < r_accept*r_accept) { + + ring_array->Add(pmt); + pmt->SetRefIndex(1); + n_pmt_in_ring++; + } + } + + n_checked++; + } + + mean_x /= n_checked; + mean_y /= n_checked; + mean_z /= n_checked; + mean_t /= n_checked; + + cout << "N PMTs in ring: " << n_pmt_in_ring << endl; + + if(n_pmt_in_ring >= n_min_pmts_in_ring) { + + // Ring found + n_ring++; + + TH2D* h_ring_charge = + new TH2D(Form("h_ring_charge_%d", n_ring), + Form("Event #%d: ring %d charge dist", event, n_ring), + 100, -r_d-50, r_d + l_d + 2*r_d + 50, + 100, -r_d*TMath::Pi()-50, r_d*TMath::Pi()+300); + + TProfile2D* h_ring_time = + new TProfile2D(Form("h_ring_time_%d", n_ring), + Form("Event #%d: ring %d time dist", event, n_ring), + 100, -r_d-50, r_d + l_d + 2*r_d + 50, + 100, -r_d*TMath::Pi()-50, r_d*TMath::Pi()+300); + + + // visualize ring + for (Int_t n = 0; n < n_pmt_in_ring; n++) { + + auto pmt = (data::PMTubeHit*)ring_array->At(n); + + const Double_t x_pmt = pmt->GetX(); + const Double_t y_pmt = pmt->GetY(); + const Double_t z_pmt = pmt->GetZ(); + const Double_t r_pmt = TMath::Sqrt(x_pmt*x_pmt + y_pmt*y_pmt); + + // Find the location of the pmt hit + Int_t location = -1; + if(TMath::Abs(z_pmt - l_d/2.0) < 1) { // front + location = 1; + } + else if(TMath::Abs(z_pmt + l_d/2) < 1) { // back + location = 3; + } + else if (TMath::Abs(r_pmt - r_d) < 1) { // side + + location = 2; + } else { + + cout << "Warning: hit was not on detector edge" << endl; + continue; + } + + // Now we need to find out where to fill the hit + Double_t x=0, y=0; + + if(location == 3) { // back + + x = -x_pmt; + y = y_pmt; + } else if (location == 1) { // front + + x = x_pmt + l_d + 2*r_d; + y = y_pmt; + } else if (location == 2) { // frontside + + x = z_pmt + r_d + l_d/2.0; + y = TMath::ATan2(y_pmt, -x_pmt) * r_d; + } + + const Double_t q_pmt = pmt->GetCharge(); + h_ring_charge->Fill(x, y, q_pmt); + + const Double_t t_pmt = pmt->GetTime(); + h_ring_time->Fill(x, y, t_pmt); + } + + TCanvas* c_charge = new TCanvas(Form("c_charge_%d", n_ring), + "PMTube charge distribution", + 900, 600); + c_charge->Draw(); + h_ring_charge->Draw("COLZ"); + + TCanvas* c_time = new TCanvas(Form("c_time_%d", n_ring), + "PMTube arrival time distribution", + 900, 600); + c_time->Draw(); + h_ring_time->Draw("COLZ"); + + TEllipse* ellipse = new TEllipse(); + ellipse->SetLineWidth(2); + ellipse->SetFillStyle(0); + c_charge->cd(); + ellipse->DrawEllipse(0, 0, r_d, 0, 0, 360, 0); + ellipse->DrawEllipse(r_d+l_d+r_d, 0, r_d, 0, 0, 360, 0); + c_time->cd(); + ellipse->DrawEllipse(0, 0, r_d, 0, 0, 360, 0); + ellipse->DrawEllipse(r_d+l_d+r_d, 0, r_d, 0, 0, 360, 0); + + TBox* box = new TBox(); + box->SetLineWidth(2); + box->SetFillStyle(0); + c_charge->cd(); + box->DrawBox(r_d, -r_d*TMath::Pi(), r_d+l_d, r_d*TMath::Pi()); + c_time->cd(); + box->DrawBox(r_d, -r_d*TMath::Pi(), r_d+l_d, r_d*TMath::Pi()); + + TLatex* latex = new TLatex(); + latex->SetTextSize(0.06); + latex->SetTextAlign(22); + c_charge->cd(); + latex->DrawLatex(0 , r_d*TMath::Pi()+200, "BACK"); + latex->DrawLatex(r_d+l_d/2 , r_d*TMath::Pi()+200, "SIDE"); + latex->DrawLatex(r_d+l_d+r_d, r_d*TMath::Pi()+200, "FRONT"); + c_time->cd(); + latex->DrawLatex(0 , r_d*TMath::Pi()+200, "BACK"); + latex->DrawLatex(r_d+l_d/2 , r_d*TMath::Pi()+200, "SIDE"); + latex->DrawLatex(r_d+l_d+r_d, r_d*TMath::Pi()+200, "FRONT"); + + // Try to estimate start fit parameters + // visualize ring + + Double_t mean_r = 0; + for (Int_t n = 0; n < n_pmt_in_ring; n++) { + + auto pmt = (data::PMTubeHit*)ring_array->At(n); + + const Double_t dx = pmt->GetX() - mean_x; + const Double_t dy = pmt->GetY() - mean_y; + const Double_t dz = pmt->GetZ() - mean_z; + + mean_r += TMath::Sqrt(dx*dx + dy*dy + dz*dz); + } + + mean_r /= n_pmt_in_ring; + + + // calculate cone guess + TVector3 p_0(mean_x, mean_y, mean_z); + const Double_t p_mag = p_0.Mag(); + p_0.SetMag(1); + + const Double_t cone_theta = TMath::ACos(1.0/1.33); + const Double_t L = mean_r / TMath::Sin(cone_theta); + + const Double_t dL = p_mag - L; + + TVector3 x_0 = dL * p_0; + + cout << "(x, y, z) = (" << x_0.X() << ", " << x_0.Y() << ", " << x_0.Z() << ")" << endl; + cout << "(px, py, pz) = (" << p_0.X() << ", " << p_0.Y() << ", " << p_0.Z() << ")" << endl; + + c_charge->cd(); + TGraph* graph = get_cone_projection(x_0, p_0, cone_theta, 100, r_d, l_d); + graph->SetLineWidth(3); + graph->Draw("L"); + } + } +} + +//__________________________________________________________________________ +TGraph* get_cone_projection(TVector3 pos, + TVector3 dir, + const Double_t theta, + const Int_t n_steps, + const Double_t r_d, + const Double_t l_d) +{ + TVector3 p_perp_1 = dir.Orthogonal(); + TVector3 p_perp_2 = dir.Cross(p_perp_1); + p_perp_1.SetMag(TMath::Sin(theta)); + p_perp_2.SetMag(TMath::Sin(theta)); + + TGraph* graph = new TGraph(n_steps); + + for(Int_t n = 0; n < n_steps; n++) { + + // we want to create an ensemble of unit vectors that will all lie on the + // cone + const Double_t phi = n * TMath::TwoPi() / n_steps; + TVector3 p_line = dir + TMath::Cos(phi)*p_perp_1 + + TMath::Sin(phi)*p_perp_2; + p_line.SetMag(1); + + // Find the location (front, side, back) and distance (steps) of the + // intersect + Int_t location = -1; + Double_t steps = 0; + { + const Double_t x = pos.X(); + const Double_t y = pos.Y(); + const Double_t z = pos.Z(); + const Double_t px = p_line.X(); + const Double_t py = p_line.Y(); + const Double_t pz = p_line.Z(); + + // cout << "(px, py, pz) = (" << px << ", " << py << ", " << pz << ")" << endl; + + Double_t steps_front_back = kMaxLong; + if(TMath::Abs(pz) > 0.000001) { + if(pz > 0) + steps_front_back = (l_d/2.0 - z) / pz; + else + steps_front_back = (-l_d/2.0 - z) / pz; + } + R__ASSERT(steps_front_back >= 0); + + Double_t steps_side = kMaxLong; + if(1-TMath::Abs(pz) > 0.000001) { + + const Double_t pt_norm_sq = px*px + py*py; + const Double_t help_1 = (px*x + py*y)/pt_norm_sq; + const Double_t help_2 = help_1*help_1 + + (r_d*r_d -x*x - y*y)/pt_norm_sq; + R__ASSERT(help_2 >= 0); + // This should always be the correct solution as help_2 >= |help_1| + const Double_t steps_side_1 = -help_1 + TMath::Sqrt(help_2); + R__ASSERT(steps_side_1 >= 0); + const Double_t steps_side_2 = -help_1 - TMath::Sqrt(help_2); + R__ASSERT(steps_side_1*steps_side_2 <= 0); + steps_side = steps_side_1; + } + + + // Find the location of the pmt hit + if(steps_front_back <= steps_side) { + steps = steps_front_back; + if(pz > 0) { // front + location = 1; + } else { // back + location = 3; + } + } else { + steps = steps_side; + location = 2; + } + } + + TVector3 pos_hit = pos + steps * p_line; + const Double_t x_hit = pos_hit.X(); + const Double_t y_hit = pos_hit.Y(); + const Double_t z_hit = pos_hit.Z(); + + // cout << location << ", (x_hit, y_hit, z_hit) = (" << x_hit << ", " << y_hit << ", " << z_hit << ")" << endl; + + + Double_t x = 0, y = 0; + if(location == 3) { // back + + x = -x_hit; + y = y_hit; + } else if (location == 1) { // front + + x = x_hit + l_d + 2*r_d; + y = y_hit; + } else if (location == 2) { // frontside + + x = z_hit + r_d + l_d/2.0; + y = TMath::ATan2(y_hit, -x_hit) * r_d; + } + + graph->SetPoint(n, x, y); + } + + return graph; + } diff --git a/EsbReconstruction/CMakeLists.txt b/EsbReconstruction/CMakeLists.txt new file mode 100644 index 0000000..36ff0bf --- /dev/null +++ b/EsbReconstruction/CMakeLists.txt @@ -0,0 +1,93 @@ + ################################################################################ + # Copyright (C) 2014 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH # + # # + # This software is distributed under the terms of the # + # GNU Lesser General Public Licence (LGPL) version 3, # + # copied verbatim in the file "LICENSE" # + ################################################################################ +# Create a library called "libEsbRecon" which includes the source files given in +# the array . +# The extension is already found. Any number of sources could be listed here. + +FIND_PACKAGE(Eigen3 REQUIRED) + +set(INCLUDE_DIRECTORIES + ${BASE_INCLUDE_DIRECTORIES} + #put here all directories where header files are located + ${CMAKE_SOURCE_DIR} + ${CLHEP_INCLUDE_DIR} + $ENV{GENIE}/src + ${GENFIT_INCLUDE} + ${GENFIT_INCLUDE}/include + ${PATHFINDER_INC} + SYSTEM ${EIGEN3_INCLUDE_DIR} +) + +set( $ENV{ROOT_INCLUDE_PATH} ${EIGEN3_INCLUDE_DIR} ) + +include_directories(${INCLUDE_DIRECTORIES}) +include_directories(${SYSTEM_INCLUDE_DIRECTORIES}) + +set(LINK_DIRECTORIES + ${ROOT_LIBRARY_DIR} + ${FAIRROOT_LIBRARY_DIR} + ${CLHEP_LIB_DIR} + $ENV{GENIE}/lib + ${GENFIT_LIBRARY} + ${GENFIT_LIBRARY}/lib + ${PATHFINDER_LIB} +) + +link_directories( ${LINK_DIRECTORIES}) + +set(SRCS + EsbSuperFGD/FgdGenFitRecon.cxx + EsbSuperFGD/FgdMCGenFitRecon.cxx + EsbSuperFGD/FgdMCLeptonStats.cxx + EsbSuperFGD/FgdMCEventRecord.cxx + EsbSuperFGD/FgdGraphStats.cxx + EsbSuperFGD/FgdReconHit.cxx + EsbSuperFGD/FgdReconTemplate.cxx + EsbSuperFGD/PdgFromMomentumLoss.cxx + EsbSuperFGD/FgdMuonRecon.cxx +) + +Set(HEADERS + ${CMAKE_SOURCE_DIR}/EsbReconstruction/EsbSuperFGD/FgdGenFitRecon.h + ${CMAKE_SOURCE_DIR}/EsbReconstruction/EsbSuperFGD/FgdMCGenFitRecon.h + ${CMAKE_SOURCE_DIR}/EsbReconstruction/EsbSuperFGD/FgdMCLeptonStats.h + ${CMAKE_SOURCE_DIR}/EsbReconstruction/EsbSuperFGD/FgdMCEventRecord.h + ${CMAKE_SOURCE_DIR}/EsbReconstruction/EsbSuperFGD/FgdGraphStats.h + ${CMAKE_SOURCE_DIR}/EsbReconstruction/EsbSuperFGD/FgdReconHit.h + ${CMAKE_SOURCE_DIR}/EsbReconstruction/EsbSuperFGD/FgdReconTemplate.h + ${CMAKE_SOURCE_DIR}/EsbReconstruction/EsbSuperFGD/PdgFromMomentumLoss.h + ${CMAKE_SOURCE_DIR}/EsbReconstruction/EsbSuperFGD/FgdMuonRecon.h +) + +Set(LINKDEF ${CMAKE_SOURCE_DIR}/EsbReconstruction/ReconLinkDef.h) +Set(LIBRARY_NAME EsbReconstruction) +Set(DEPENDENCIES + Base EsbData EsbGeometry EsbDigitizer +) + +file(GLOB genfit_libs ${GENFIT_LIBRARY}/lib/*.so) + +#Add shared library to be run in root interpreter (macro files) +FOREACH(glib ${genfit_libs}) + #message("Adding genfit libs as dependency: ${glib}") + list(APPEND DEPENDENCIES + ${glib} + ) +ENDFOREACH() + +file(GLOB pathfind_libs ${PATHFINDER_LIB}/*) + +#Add shared library to be run in root interpreter (macro files) +FOREACH(pflib ${pathfind_libs}) + #message("Adding pathfinder libs as dependency: ${pflib}") + list(APPEND DEPENDENCIES + ${pflib} + ) +ENDFOREACH() + +GENERATE_LIBRARY() diff --git a/EsbReconstruction/EsbSuperFGD/FgdGenFitRecon.cxx b/EsbReconstruction/EsbSuperFGD/FgdGenFitRecon.cxx new file mode 100644 index 0000000..17c2834 --- /dev/null +++ b/EsbReconstruction/EsbSuperFGD/FgdGenFitRecon.cxx @@ -0,0 +1,1447 @@ +#include "EsbReconstruction/EsbSuperFGD/FgdGenFitRecon.h" +#include "EsbReconstruction/EsbSuperFGD/FgdReconTemplate.h" +#include "EsbData/EsbSuperFGD/FgdDetectorPoint.h" + +// FairRoot headers +#include "FairGeoBuilder.h" +#include "FairGeoInterface.h" +#include "FairGeoLoader.h" +#include "FairGeoMedia.h" +#include "FairLogger.h" +#include +#include "FairVolume.h" + + +// Root headers +#include +#include +#include +#include +#include + + +// Genfit headers +#include "AbsBField.h" +#include "AbsMeasurement.h" +#include "ConstField.h" +#include +#include +#include +#include "FitStatus.h" +#include +#include "MaterialEffects.h" +#include "MeasuredStateOnPlane.h" +#include +#include +#include "SpacepointMeasurement.h" +#include +#include "TDatabasePDG.h" +#include +#include +#include +#include +#include +#include + + +// PathFinder headers +#include "FinderParameter.h" +#include "HoughTrafoTrackFinder.h" +#include "TrackParameterFull.h" + + +// STL headers +#include +#include +#include +#include +#include +#include +#include + +namespace esbroot { +namespace reconstruction { +namespace superfgd { + +// ----- Default constructor ------------------------------------------- +FgdGenFitRecon::FgdGenFitRecon() : + FairTask(), fsuperFgdVol(nullptr) + , fgdConstructor("") + , fHitArray(nullptr) + , isDefinedMaterials(false) + , fDebuglvl_genfit(0) + , fmediaFile("") + , fTracksArray(nullptr) + , fdisplay(nullptr) + , isGenFitVisualization(false) + , fGenFitVisOption("") + , fminGenFitInterations(2) + , fmaxGenFitIterations(4) + , fminHits(25) + , ffinder(TrackFinder::HOUGH_PATHFINDER_CURL) +{ +} +// ------------------------------------------------------------------------- + +// ----- Constructor ------------------------------------------- +FgdGenFitRecon::FgdGenFitRecon(const char* name + , const char* geoConfigFile + , const char* mediaFile + , Int_t verbose + , double debugLlv + , bool visualize + , std::string visOption) : + FairTask(name, verbose) + , fsuperFgdVol(nullptr) + , fgdConstructor(geoConfigFile) + , fHitArray(nullptr) + , isDefinedMaterials(false) + , fDebuglvl_genfit(debugLlv) + , fmediaFile(mediaFile) + , fTracksArray(nullptr) + , fdisplay(nullptr) + , isGenFitVisualization(visualize) + , fGenFitVisOption(visOption) + , fminGenFitInterations(2) + , fmaxGenFitIterations(4) + , fminHits(25) + , ffinder(TrackFinder::HOUGH_PATHFINDER_CURL) +{ + fParams.LoadPartParams(geoConfigFile); +} +// ------------------------------------------------------------------------- + + + +// ----- Destructor ---------------------------------------------------- +FgdGenFitRecon::~FgdGenFitRecon() +{ + if(fHitArray) { + fHitArray->Delete(); + delete fHitArray; + } + + if(fTracksArray) { + fTracksArray->Delete(); + delete fTracksArray; + } +} +// ------------------------------------------------------------------------- + + + +// ----- Public method Init -------------------------------------------- +InitStatus FgdGenFitRecon::Init() +{ + // Create the real Fgd geometry + DefineMaterials(); + fsuperFgdVol = fgdConstructor.Construct(); + gGeoManager->SetTopVolume(fsuperFgdVol); + + // Get dimentions from geometry file + flunit = fParams.GetLenghtUnit(); // [cm] + + f_step_X = fParams.ParamAsDouble(esbroot::geometry::superfgd::DP::length_X) * flunit; + f_step_Y = fParams.ParamAsDouble(esbroot::geometry::superfgd::DP::length_Y) * flunit; + f_step_Z = fParams.ParamAsDouble(esbroot::geometry::superfgd::DP::length_Z) * flunit; + + f_bin_X = fParams.ParamAsInt(esbroot::geometry::superfgd::DP::number_cubes_X); + f_bin_Y = fParams.ParamAsInt(esbroot::geometry::superfgd::DP::number_cubes_Y); + f_bin_Z = fParams.ParamAsInt(esbroot::geometry::superfgd::DP::number_cubes_Z); + + f_total_X = f_step_X * f_bin_X; + f_total_Y = f_step_Y * f_bin_Y; + f_total_Z = f_step_Z * f_bin_Z; + + // Get RootManager + FairRootManager* manager = FairRootManager::Instance(); + if ( !manager ) { + LOG(fatal) << "-E- FgdGenFitRecon::Init: " << "FairRootManager not instantised!"; + return kFATAL; + } + + fHitArray = (TClonesArray*) manager->GetObject(geometry::superfgd::DP::FGD_HIT.c_str()); + if (!fHitArray) + { + LOG(fatal) << "Exec", "No fgd hits array"; + return kFATAL; + } + + OutputFileInit(manager); + + if(isGenFitVisualization) + { + fdisplay = genfit::EventDisplay::getInstance(); + } + + if(fdisplay!=nullptr && !fGenFitVisOption.empty()) + { + fdisplay->setOptions(fGenFitVisOption); + } + + + return kSUCCESS; +} + +void FgdGenFitRecon::OutputFileInit(FairRootManager* manager) +{ + // Create and register output array + fTracksArray = new TClonesArray(genfit::Track::Class(), 1000); + manager->Register(geometry::superfgd::DP::FGD_FIT_TRACK.c_str() + , geometry::superfgd::DP::FGD_BRANCH_FIT.c_str() + , fTracksArray, kTRUE); +} + + +// ------------------------------------------------------------------------- + + + +// ----- Public methods -------------------------------------------- +void FgdGenFitRecon::FinishEvent() +{ + +} + +void FgdGenFitRecon::FinishTask() +{ + if(isGenFitVisualization) + { + fdisplay->open(); + } +} + +void FgdGenFitRecon::Exec(Option_t* opt) +{ + try + { + std::vector allhits; + std::vector> foundTracks; + std::vector points; + + bool rc = GetHits(allhits); + if(rc) + { + LOG(debug) <<" Hits to retrieve tracks from " << allhits.size(); + switch(ffinder) + { + case TrackFinder::HOUGH_PATHFINDER_LINE: + ConvertHitToVec(points, allhits); + rc = FindUsingHough(points, allhits, foundTracks, FindTrackType::STRAIGHT_LINE); + break; + case TrackFinder::HOUGH_PATHFINDER_HELIX: + ConvertHitToVec(points, allhits); + rc = FindUsingHough(points, allhits, foundTracks, FindTrackType::HELIX); + break; + case TrackFinder::HOUGH_PATHFINDER_CURL: + ConvertHitToVec(points, allhits); + rc = FindUsingHough(points, allhits, foundTracks, FindTrackType::CURL); + break; + case TrackFinder::GRAPH: + rc = FindUsingGraph(allhits, foundTracks); + break; + + case TrackFinder::GRAPH_HOUGH_PATHFINDER: + rc = FindUsingGraphHough(allhits, foundTracks); + break; + default: + rc = false; + break; + } + } + + if(rc) + { + LOG(debug) <<" Tracks found " << foundTracks.size(); + FitTracks(foundTracks); + } + else + { + LOG(error) << " Could not find clean hits or tracks! "; + } + } + catch(genfit::Exception& e) + { + LOG(fatal) << "Exception, when tryng to fit track"; + LOG(fatal) << e.what(); + } +} +// ------------------------------------------------------------------------- + + +// ----- Protected methods -------------------------------------------- + +Bool_t FgdGenFitRecon::GetHits(std::vector& allHits) +{ + Double_t errPhotoLimit = fParams.ParamAsDouble(esbroot::geometry::superfgd::DP::FGD_ERR_PHOTO_LIMIT); + + LOG(debug) << "fHitArray->GetEntries() " << fHitArray->GetEntries(); + + std::map visited; + + Int_t numVis(0); + + for(Int_t i =0; i < fHitArray->GetEntries() ; i++) + { + data::superfgd::FgdHit* hit = (data::superfgd::FgdHit*)fHitArray->At(i); + TVector3 photoE = hit->GetPhotoE(); + TVector3 mppcLoc = hit->GetMppcLoc(); + + Int_t&& x = mppcLoc.X(); + Int_t&& y = mppcLoc.Y(); + Int_t&& z = mppcLoc.Z(); + + LOG(debug) << "TrackId " << hit->GetTrackId(); + LOG(debug) << "GetPgd " << hit->GetPgd(); + LOG(debug) << "GetTrackLengthOrigin " << hit->GetTrackLengthOrigin(); + LOG(debug) << "GetTrackLenght " << hit->GetTrackLenght(); + + Int_t ind = ArrInd(x,y,z); + if(visited[ind]) + { + // If already exists, add the photons + ReconHit toFind; + toFind.fmppcLoc = mppcLoc; + std::vector::iterator recHit = find(allHits.begin(), allHits.end(), toFind); + ReconHit& foundHit = *recHit; + foundHit.fphotons = foundHit.fphotons + photoE; + continue; + } + visited[ind] = true; + + Double_t totalPhotons = photoE.X() + photoE.Y() + photoE.Z(); + if(totalPhotons >= errPhotoLimit) + { + TVectorD hitPos(3); + hitPos(0) = -f_total_X/2 + f_step_X*mppcLoc.X() +f_step_X/2; + hitPos(1) = -f_total_Y/2 + f_step_Y*mppcLoc.Y() +f_step_Y/2; + hitPos(2) = -f_total_Z/2 + f_step_Z*mppcLoc.Z() +f_step_Z/2; + + allHits.emplace_back(ReconHit( + mppcLoc + , TVector3(hitPos(0),hitPos(1),hitPos(2)) + , photoE + , hit->GetTime() + , hit->GetMomentum() + , hit->GetExitMomentum() + , hit->GetTrackLenght() + , hit->GetTrackLengthOrigin() + , hit->GetPgd() + , hit->GetTrackId() + , hit->GetEdep() + , hit->GetPhotoDist1() + , hit->GetMppcDist1() + , hit->GetPhotoDist2() + , hit->GetMppcDist2() + )); + } + } + + LOG(debug) << "allHits.size() " << allHits.size(); + + return (allHits.size() > 0); +} + +Bool_t FgdGenFitRecon::FindUsingHough(std::vector& points + , std::vector& hits + , std::vector>& foundTracks + , FindTrackType trackType) +{ + LOG(debug) << "hits " << hits.size(); + + unsigned int use_vertex = fParams.ParamAsDouble(esbroot::geometry::superfgd::DP::PF_USE_VERTEX); + double vertexX = fParams.ParamAsDouble(esbroot::geometry::superfgd::DP::PF_VERTEXX); + double vertexY = fParams.ParamAsDouble(esbroot::geometry::superfgd::DP::PF_VERTEXY); + double maxdistxy = fParams.ParamAsDouble(esbroot::geometry::superfgd::DP::PF_MAXDISTXY); + double maxdistsz = fParams.ParamAsDouble(esbroot::geometry::superfgd::DP::PF_MAXDISTSZ); + double maxdistxyfit = fParams.ParamAsDouble(esbroot::geometry::superfgd::DP::PF_MAXDISTXYFIT); + double maxdistszfit = fParams.ParamAsDouble(esbroot::geometry::superfgd::DP::PF_MAXDISTSZFIT); + unsigned int minhitnumber = fParams.ParamAsDouble(esbroot::geometry::superfgd::DP::PF_MINHITNUMBER); + unsigned int xythetabins = fParams.ParamAsDouble(esbroot::geometry::superfgd::DP::PF_XYTHETABINS); + unsigned int xyd0bins = fParams.ParamAsDouble(esbroot::geometry::superfgd::DP::PF_XYD0BINS); + unsigned int xyomegabins = fParams.ParamAsDouble(esbroot::geometry::superfgd::DP::PF_XYOMEGABINS); + unsigned int szthetabins = fParams.ParamAsDouble(esbroot::geometry::superfgd::DP::PF_SZTHETABINS); + unsigned int szd0bins = fParams.ParamAsDouble(esbroot::geometry::superfgd::DP::PF_SZD0BINS); + double maxdxy = f_total_X + f_total_Y; + double maxdsz = f_total_Z; + unsigned int searchneighborhood = fParams.ParamAsDouble(esbroot::geometry::superfgd::DP::PF_SEACHINTHENEIGHBORHOOD); + + pathfinder::FinderParameter* newFinderParameter = nullptr; + switch(trackType) + { + case FindTrackType::HELIX: + newFinderParameter= new pathfinder::FinderParameter(false, true); + newFinderParameter -> setFindCurler(false); + break; + case FindTrackType::CURL: + newFinderParameter= new pathfinder::FinderParameter(false, true); + newFinderParameter -> setFindCurler(true); + break; + case FindTrackType::STRAIGHT_LINE: + default: + newFinderParameter= new pathfinder::FinderParameter(true, false); + newFinderParameter -> setFindCurler(false); + break; + } + + + // if(use_vertex == 0) newFinderParameter -> setUseVertex(false); + // if(use_vertex == 1) newFinderParameter->setUseVertex(true); + + if(use_vertex == 1) + { + std::pair vertex(vertexX, vertexY); + newFinderParameter -> setVertex(vertex); + } + + newFinderParameter -> setMaxXYDistance(maxdistxy); + newFinderParameter -> setMaxSZDistance(maxdistsz); + newFinderParameter -> setMaxXYDistanceFit(maxdistxyfit); + newFinderParameter -> setMaxSZDistanceFit(maxdistszfit); + newFinderParameter -> setMinimumHitNumber(minhitnumber); + newFinderParameter -> setNumberXYThetaBins(xythetabins); + newFinderParameter -> setNumberXYDzeroBins(xyd0bins); + newFinderParameter -> setNumberXYOmegaBins(xyomegabins); + newFinderParameter -> setNumberSZThetaBins(szthetabins); + newFinderParameter -> setNumberSZDzeroBins(szd0bins); + newFinderParameter -> setMaxDxy(maxdxy); + newFinderParameter -> setMaxDsz(maxdsz); + + if(searchneighborhood == 0) + { + newFinderParameter -> setSearchNeighborhood(false); + } + else + { + newFinderParameter -> setSearchNeighborhood(true); + } + newFinderParameter -> setSaveRootFile(false); + + std::vector allHits; + for(size_t i=0; i< points.size(); ++i) + { + allHits.emplace_back(pathfinder::basicHit( points[i].X() + , points[i].Y() + , points[i].Z() + ) + ); + } + + pathfinder::HoughTrafoTrackFinder newTrackFinder; + + //setting steering parameter + newTrackFinder.setFinderParameter(*newFinderParameter); + + // If there is not time interval include all hits + newTrackFinder.setInitialHits(allHits); + + //do the actual track finding + Bool_t found = newTrackFinder.find(); + if(found) + { + std::vector pfTracks = newTrackFinder.getTracks(); + for(Int_t i =0; i < pfTracks.size() ; i++) + { + pathfinder::TrackFinderTrack& trFinder = pfTracks[i]; + const std::vector& hitsOnTrack = trFinder.getHitsOnTrack(); + std::vector track; + for(size_t j =0; j< hitsOnTrack.size(); ++j) + { + track.emplace_back(hitsOnTrack[j].getX(),hitsOnTrack[j].getY(),hitsOnTrack[j].getZ()); + } + foundTracks.push_back(track); + } + } + + return found; +} + +Bool_t FgdGenFitRecon::FindUsingGraph(std::vector& hits + , std::vector>& foundTracks) +{ + if(hits.empty()) + { + return false; + } + + BuildGraph(hits); + + // Print out the build graph + for(Int_t i=0; ifmppcLoc - localHit->fmppcLoc; + LOG(debug) << " Local Id "<< hits[i].fAllHits[j]->fLocalId << " \t X " << diff.X() << " \t Y " << diff.Y() << " \t Z " << diff.Z(); + } + LOG(debug) << "X " << hits[i].fmppcLoc.X() << " Y " << hits[i].fmppcLoc.Y()<< " Z " << hits[i].fmppcLoc.Z(); + LOG(debug) << "Photons "<< " X " << hits[i].fphotons.X() << " Y " << hits[i].fphotons.Y()<< " Z " << hits[i].fphotons.Z(); + LOG(debug) << "====="; + } + + + FgdReconTemplate reconTemplates; + + std::vector> tracks; + + ReconHit* currentHit = nullptr; + ReconHit* nextHit = nullptr; + ReconHit* previousHit = nullptr; + for(size_t i=0; i track; + track.push_back(&hits[i]); + + hits[i].fIsLeaf = true; + currentHit = &hits[i]; + + while(reconTemplates.GetNextHit(previousHit, currentHit, nextHit)) + { + if(nextHit->fIsLeaf || nextHit->fIsVisited) + { + break; + } + track.push_back(nextHit); + currentHit->fIsVisited = true; + previousHit = currentHit; + currentHit = nextHit; + } + + tracks.push_back(track); + } + } + + LOG(debug) <<"Leaves found " << tracks.size(); // Initially leaves are equal to the number of tracks + + CalculateGrad(tracks); + + std::vector> splitTracks; + + SplitTrack(tracks, splitTracks); + + Int_t totalHitsInTracks(0); + for(size_t i = 0; i& track = splitTracks[i]; + std::vector currentTrack; + LOG(debug2) << "=============================== "; + LOG(debug2) << "Track " << i; + + totalHitsInTracks+=track.size(); + + for(size_t j = 0; jfHitPos.X() + , trackHit->fHitPos.Y() + , trackHit->fHitPos.Z()); + + LOG(debug2) << " \tX " << trackHit->fmppcLoc.X() << " \tY " << trackHit->fmppcLoc.Y() << " \tZ " << trackHit->fmppcLoc.Z(); + } + LOG(debug2) << "=============================== "; + + foundTracks.push_back(currentTrack); + } + + LOG(debug) << "Total hits in tracks " << totalHitsInTracks; + + return !foundTracks.empty(); +} + +Bool_t FgdGenFitRecon::FindUsingGraphHough(std::vector& hits + , std::vector>& foundTracks) +{ + + Bool_t rc(false); + + std::vector> graphTracks; + rc = FindUsingGraph(hits, graphTracks); + + if(rc) + { + // Traverse through the found graph tracks and use hough transform for each track + // add the found hough track with the biggest number of found hits + for(size_t i = 0; i < graphTracks.size(); ++i) + { + size_t biggestSize(0); + std::vector* trackToAdd = nullptr; + + // 1. Line hough ======================== + std::vector> hough_Line; + if(FindUsingHough(graphTracks[i], hits, hough_Line, FindTrackType::STRAIGHT_LINE) + && !hough_Line.empty()) + { + size_t localBiggest(0); + size_t ind(0); + for(size_t j = 0; j < hough_Line.size(); ++j) + { + if(localBiggest < hough_Line[j].size()) + { + localBiggest = hough_Line[j].size(); + ind = j; + } + } + + if(localBiggest > biggestSize) + { + biggestSize = hough_Line[ind].size(); + trackToAdd = &hough_Line[ind]; + LOG(debug) << "Hough transform from graph [line] size of track is: " << hough_Line[ind].size(); + } + } + LOG(debug)<< "Hough transform [line] " << hough_Line.size(); + + // ====================================== + + // 2. Helix hough ======================== + std::vector> hough_Helix; + if(FindUsingHough(graphTracks[i], hits, hough_Helix, FindTrackType::HELIX) + && !hough_Line.empty()) + { + size_t localBiggest(0); + size_t ind(0); + for(size_t j = 0; j < hough_Helix.size(); ++j) + { + if(localBiggest < hough_Helix[j].size()) + { + localBiggest = hough_Helix[j].size(); + ind = j; + } + } + + if(localBiggest > biggestSize) + { + biggestSize = hough_Helix[ind].size(); + trackToAdd = &hough_Helix[ind]; + LOG(debug) << "Hough transform from graph [helix] size of track is: " << hough_Helix[ind].size(); + } + } + LOG(debug)<< "Hough transform [helix] " << hough_Helix.size(); + + // ====================================== + + // 3. Curl hough ======================== + std::vector> hough_Curl; + if(FindUsingHough(graphTracks[i], hits, hough_Curl, FindTrackType::CURL) + && !hough_Line.empty()) + { + size_t localBiggest(0); + size_t ind(0); + for(size_t j = 0; j < hough_Curl.size(); ++j) + { + if(localBiggest < hough_Curl[j].size()) + { + localBiggest = hough_Curl[j].size(); + ind = j; + } + } + + if(localBiggest > biggestSize) + { + biggestSize = hough_Curl[ind].size(); + trackToAdd = &hough_Curl[ind]; + LOG(debug) << "Hough transform from graph [helix] size of track is: " << hough_Curl[ind].size(); + } + } + LOG(debug)<< "Hough transform [curl] " << hough_Curl.size(); + + // ====================================== + + if(trackToAdd!=nullptr) + { + foundTracks.emplace_back(*trackToAdd); + } + else + { + foundTracks.push_back(graphTracks[i]); + LOG(debug)<< "Hough transform could not find track, adding initial graph track. "; + } + + } + } + + return rc; +} + +void FgdGenFitRecon::BuildGraph(std::vector& hits) +{ + // Create the position to which index in the vector it is pointing + std::map positionToId; + for(Int_t i=0; i>& tracks) +{ + const Int_t distToCalc = fParams.ParamAsInt(esbroot::geometry::superfgd::DP::FGD_GRAD_DIST); + const Int_t intervalToCal = fParams.ParamAsInt(esbroot::geometry::superfgd::DP::FGD_GRAD_INTERVAL_DIST); + const Double_t radToDeg = 180/TMath::Pi(); + TVector3 zAxisVec(0,0,1); + + for(Int_t i=0; i& track = tracks[i]; + LOG(debug2) << "=================================== "; + LOG(debug2) << "Track " << i; + + for(Int_t j=0; j=1) + { + ReconHit* previous = track[j-1]; + diffVec = currentHit->fmppcLoc - previous->fmppcLoc; + } + + // 2.Calculate cosine change beween 2 consecutive vectors - gradient + Double_t diffAngle(0); // Difference angle between two vectors - the vectors are the difference in position (grad (position)) + // between two hits distToCalc cubes apart. The angles measures the angle change of the track + // from hit to hit. distToCalc distance is selected to smooth out the change in angle. + + Double_t zAxisAngle(0); // Vector angle between the z axis and the vector difference between the current hit and the hit distToCalc + // poisitions back. + + TVector3 diffVec1(0,0,0); + TVector3 diffVec2(0,0,0); + + Int_t indOne = j - distToCalc + 1; + Int_t indTwo = j; // current hit + + if(j>= (distToCalc -1) ) + { + ReconHit* one = track[indOne]; + ReconHit* two = track[indTwo]; + diffVec1 = two->fmppcLoc - one->fmppcLoc; + zAxisAngle = radToDeg * zAxisVec.Angle(diffVec1); + + // The z angle is calculated for the current hit + currentHit->fZaxisAngle = zAxisAngle; + } + + Int_t indOneP = indOne - intervalToCal; + Int_t indTwoP = indTwo - intervalToCal; + if(j>= (distToCalc + intervalToCal -1) ) + { + ReconHit* oneP = track[indOneP]; + ReconHit* twoP = track[indTwoP]; + diffVec2 = twoP->fmppcLoc - oneP->fmppcLoc; + + diffAngle = radToDeg * diffVec1.Angle(diffVec2); + + // The angle is calculated for the current hit + currentHit->fChangeAngle = diffAngle; + } + + LOG(debug2) << "Id " << currentHit->fLocalId + << " \tX " << currentHit->fmppcLoc.X() + << " \tY " << currentHit->fmppcLoc.Y() + << " \tZ " << currentHit->fmppcLoc.Z() + << " \tPhotons " << "(" << currentHit->fphotons.X() << "," << currentHit->fphotons.Y() << "," << currentHit->fphotons.Z() << ")" + << " \tChange " << "(" << diffVec.X() << "," << diffVec.Y() << "," << diffVec.Z() << ")" + // << " \t(" << diffVec1.X() << "," << diffVec1.Y() << "," << diffVec1.Z() << ") " + // << " \t(" << diffVec2.X() << "," << diffVec2.Y() << "," << diffVec2.Z() << ") " + << " \tAngle (dist = " << distToCalc << ", interval =" << intervalToCal << ") " << diffAngle + << " \tZ axis Angle (dist = " << distToCalc << ", interval =" << intervalToCal << ") " << zAxisAngle; + } + + LOG(debug2) << "=================================== "; + } +} + +void FgdGenFitRecon::SplitTrack(std::vector>& originalTracks, std::vector>& splitTracks) +{ + const Double_t gradAllowedDiff = fParams.ParamAsDouble(esbroot::geometry::superfgd::DP::FGD_GRAD_ALLOWABLE_DIFF); + LOG(debug) << "Initial tracks size " << originalTracks.size(); + + for(Int_t i=0; i& track = originalTracks[i]; + + if(track.empty()) + { + continue; + } + + std::vector trackToAdd; + trackToAdd.push_back(track[0]); // Add the first hit to start the track + + for(Int_t j=1; jfChangeAngle == 0) + { + // If there is no change add the track + // Also '0' indicates that the track hit is too short to calculate the + // the change. + // Only compare if both the current and previous angle is not zero. + trackToAdd.push_back(currentHit); + } + else if( (currentHit->fChangeAngle != 0) && (previousHit->fChangeAngle != 0) ) + { + Double_t differenceInAngle = currentHit->fChangeAngle - previousHit->fChangeAngle; + Double_t absDiff = std::fabs(differenceInAngle); + if(absDiff >= gradAllowedDiff) + { + // If the difference is not allowed add the current track hit points + // and reset it to start a new track. + splitTracks.emplace_back(trackToAdd); + trackToAdd.clear(); + } + trackToAdd.push_back(currentHit); + } + } + + splitTracks.emplace_back(trackToAdd); + } + + LOG(debug) << "Split tracks size " << splitTracks.size(); +} + + +Bool_t FgdGenFitRecon::CalculateInitialMomentum(const std::vector& track,const TVector3& magField, TVector3& momentum , TVector3& momentumLoss) +{ + if(track.empty()) + { + momentum.SetXYZ(0.,0.,0); + momentumLoss.SetXYZ(0.,0.,0); + return false; + } + + Int_t segment = fParams.ParamAsInt(esbroot::geometry::superfgd::DP::FGD_TRACK_MOMENTUM_SEGMENT); + Int_t avgInitialPoints = fParams.ParamAsInt(esbroot::geometry::superfgd::DP::FGD_INITIAL_TRACK_POINTS_MOMENTUM); + + const Int_t defaultSegment = 3; + segment = (segment<=0) ? defaultSegment : segment; + avgInitialPoints = (avgInitialPoints<=0) ? defaultSegment : avgInitialPoints; + + // If the track lenght is less than the set segment, calculate the momentum from the arc of the whole track + // using for the 3 points the begin, end and all the middle points between them + Int_t lengthSize = (track.size() < segment ) ? (track.size() -1) : (segment -1) ; + + std::vector trackMomentums; + std::vector tarckMomentumLosses; + + for(size_t i = lengthSize; i< track.size() ; ++i) + { + size_t p1_pos = i - lengthSize; + TVector3 p1 = track[p1_pos]; + TVector3 p3 = track[i]; + + size_t p2_pos = p1_pos + 1; + std::vector segmentMomentums; + + while(p2_pos::infinity(); + + return (!std::isnan(momentum.Mag()) && momentum.Mag()!=inf && trackMomentums.size() > 0 ); +} + +Bool_t FgdGenFitRecon::CalculateMomentum(const TVector3& p1, const TVector3& p2, const TVector3& p3 , const TVector3& magField, TVector3& momentum) +{ + // + // p [Gev/c] = e [1.6 x 10^-19 coulumb] * B [T] * R [m] + // + + Bool_t rc(false); + + // For calculation charge is taken as 1 unit of 'e' + const Double_t charge = 1.; + + Double_t inf = std::numeric_limits::infinity(); + + TVector3 x_axis(1,0,0); + TVector3 y_axis(0,1,0); + TVector3 z_axis(0,0,1); + + TVector3 length = p3 - p1; + Double_t x_angle = x_axis.Angle(length); + Double_t y_angle = y_axis.Angle(length); + Double_t z_angle = z_axis.Angle(length); + + // For each magnetic field plane calculate it for the perpendicular projections + if(magField.X()!=0) + { + TVector3 mag_point1(0,p1.Y(), p1.Z()); + TVector3 mag_point2(0,p2.Y(), p2.Z()); + TVector3 mag_point3(0,p3.Y(), p3.Z()); + Double_t radius = GetRadius(mag_point1,mag_point2,mag_point3); // radius is returned in [cm] + + if(!std::isnan(radius) && radius!=inf) + { + Double_t R = radius/100.; // convert in meters + Double_t magField_T = magField.X() / 10.; // convert from kGauss to Tesla units + Double_t mom = charge * R * magField_T; + + Double_t mom_x = std::cos(x_angle) * mom; + Double_t mom_y = std::cos(y_angle) * mom; + Double_t mom_z = std::cos(z_angle) * mom; + + momentum.SetX(mom_x); + momentum.SetY(mom_y); + momentum.SetZ(mom_z); + rc = true; + } + } + + if(magField.Y()!=0) + { + TVector3 mag_point1(p1.X(), 0. , p1.Z()); + TVector3 mag_point2(p2.X(), 0. , p2.Z()); + TVector3 mag_point3(p3.X(), 0. , p3.Z()); + Double_t radius = GetRadius(mag_point1,mag_point2,mag_point3); // radius is returned in [cm] + + if(!std::isnan(radius) && radius!=inf) + { + Double_t R = radius/100.; // convert in meters + Double_t magField_T = magField.Y() / 10.; // convert from kGauss to Tesla units + Double_t mom = charge * R * magField_T; + + Double_t mom_x = std::cos(x_angle) * mom + momentum.X(); + Double_t mom_y = std::cos(y_angle) * mom + momentum.Y(); + Double_t mom_z = std::cos(z_angle) * mom + momentum.Z(); + + momentum.SetX(mom_x); + momentum.SetY(mom_y); + momentum.SetZ(mom_z); + rc = true; + } + } + + if(magField.Z()!=0) + { + TVector3 mag_point1(p1.X(), p1.Y() , 0.); + TVector3 mag_point2(p2.X(), p2.Y() , 0.); + TVector3 mag_point3(p3.X(), p3.Y() , 0.); + Double_t radius = GetRadius(mag_point1,mag_point2,mag_point3); // radius is returned in [cm] + + if(!std::isnan(radius) && radius!=inf) + { + Double_t R = radius/100.; // convert in meters + Double_t magField_T = magField.Z() / 10.; // convert from kGauss to Tesla units + Double_t mom = charge * R * magField_T; + + Double_t mom_x = std::cos(x_angle) * mom + momentum.X(); + Double_t mom_y = std::cos(y_angle) * mom + momentum.Y(); + Double_t mom_z = std::cos(z_angle) * mom + momentum.Z(); + + momentum.SetX(mom_x); + momentum.SetY(mom_y); + momentum.SetZ(mom_z); + rc = true; + } + } + + return rc; +} + + +// Calculate the radius from 3 points using the "Menger curvature" theorem +Double_t FgdGenFitRecon::GetRadius(const TVector3& p1, const TVector3& p2, const TVector3& p3) +{ + // + // p1 + // /\\ + // y / \\ x + // / \\ + // /______\\ + // p2 p3 + // z + // + // 2 sin (Angle(xyz)) + // c(x,y,z) = ------------------------ + // |x - z| + // + // where Angle(xyz) is the angle from point p2 to point p1 and p3 + // and |x - z| is the magnitude of the line connecting points p2 and p3 + + TVector3 x = p3 - p1; + TVector3 y = p2 - p1; + TVector3 z = p2 - p3; + + Double_t angle = y.Angle(x); + Double_t x_z_Mag = z.Mag(); + + Double_t c = (2*std::sin(angle))/x_z_Mag; + Double_t R = 1./c; + + LOG(debug3) << "Radius is -> " << R << " [cm]"; + + return R; +} + +Int_t FgdGenFitRecon::GetPdgCode(const TVector3& momentum, const TVector3& momentumLoss) +{ + Int_t pdgCode = 13; // Muon pdg code + + for(size_t k=0; k& points, std::vector& hits) +{ + for(size_t i=0; i< hits.size(); ++i) + { + points.emplace_back(hits[i].fHitPos.X() + , hits[i].fHitPos.Y() + , hits[i].fHitPos.Z()); + } +} + +void FgdGenFitRecon::FitTracks(std::vector>& foundTracks) +{ + fTracksArray->Delete(); + + // init geometry and mag. field + TVector3 magField = fgdConstructor.GetMagneticField(); // values are in kGauss + genfit::FieldManager::getInstance()->init(new genfit::ConstField(magField.X(),magField.Y(), magField.Z())); + genfit::MaterialEffects::getInstance()->init(new genfit::TGeoMaterialInterface()); + genfit::MaterialEffects::getInstance()->setDebugLvl(fDebuglvl_genfit); + + // init fitter + std::shared_ptr fitter = make_shared(); + fitter->setMinIterations(fminGenFitInterations); + fitter->setMaxIterations(fmaxGenFitIterations); + fitter->setDebugLvl(fDebuglvl_genfit); + + std::vector genTracks; + int detId(1); // Detector id, it is the same, we only have one detector + + // If the track could not be fitted because of Bette-bloch calculations + // try to double the momentum + Bool_t isMomentumLow(false); + Int_t momCoef = 1; + Int_t limitCoeff = 4; + + + for(size_t i = 0; i < foundTracks.size() ; ++i) + { + if(momCoef>=limitCoeff) + { + isMomentumLow = false; + momCoef = 1; + } + + if(isMomentumLow) + { + momCoef = momCoef * 2; + --i; + isMomentumLow = false; + LOG(debug) << "Momentum too low, doubling momentum estimate"; + } + std::vector& hitsOnTrack = foundTracks[i]; + + // Set lower limit on track size + if(hitsOnTrack.size() measurements{measurement}; + + toFitTrack->insertPoint(new genfit::TrackPoint(measurements, toFitTrack)); + } + + try + { + //check + toFitTrack->checkConsistency(); + + // do the fit + fitter->processTrack(toFitTrack, true); + + //check + toFitTrack->checkConsistency(); + + PrintFitTrack(*toFitTrack); + + LOG(debug) <<"******************************************* "; + genfit::FitStatus* fiStatuStatus = toFitTrack->getFitStatus(); + + if(fiStatuStatus->isFitted()) + { + genTracks.push_back(toFitTrack); + } + + isMomentumLow = fiStatuStatus->isFitted() && !fiStatuStatus->isFitConverged(); + + } + catch(genfit::Exception& e) + { + LOG(error) <<"Exception, when tryng to fit track"; + LOG(error) << e.what(); + LOG(error) << e.getExcString(); + + isMomentumLow = (e.getExcString().find("KalmanFitterInfo::getFittedState") != std::string::npos); + } + } + + if(isGenFitVisualization) + { + fdisplay->addEvent(genTracks); + } +} + +void FgdGenFitRecon::DefineMaterials() +{ + if(isDefinedMaterials) return; // Define materials only once + + isDefinedMaterials = true; + + new FairGeoLoader("TGeo","Geo Loader"); + FairGeoLoader *geoLoad = FairGeoLoader::Instance(); + if(geoLoad==nullptr) + { + LOG(error)<< "geoLoad is null"; + std::cout << "geoLoad is null" << endl; + throw; + } + + FairGeoInterface *geoFace = geoLoad->getGeoInterface(); + + geoFace->setMediaFile(fmediaFile.c_str()); + geoFace->readMedia(); + + FairGeoMedia *geoMedia = geoFace->getMedia(); + FairGeoBuilder* geoBuild = geoLoad->getGeoBuilder(); + + // FairGeoMedium* brass = geoMedia->getMedium(esbroot::geometry::superfgd::materials::brass); + // geoBuild->createMedium(brass); + + // FairGeoMedium* bronze = geoMedia->getMedium(esbroot::geometry::superfgd::materials::bronze); + // geoBuild->createMedium(bronze); + + // FairGeoMedium* stainlessSteel = geoMedia->getMedium(esbroot::geometry::superfgd::materials::stainlessSteel); + // geoBuild->createMedium(stainlessSteel); + + // FairGeoMedium* methane = geoMedia->getMedium(esbroot::geometry::superfgd::materials::methane); + // geoBuild->createMedium(methane); + + // FairGeoMedium* carbonDioxide = geoMedia->getMedium(esbroot::geometry::superfgd::materials::carbonDioxide); + // geoBuild->createMedium(carbonDioxide); + + // FairGeoMedium* carbontetraFloride = geoMedia->getMedium(esbroot::geometry::superfgd::materials::carbontetraFloride); + // geoBuild->createMedium(carbontetraFloride); + + // FairGeoMedium* titaniumDioxide = geoMedia->getMedium(esbroot::geometry::superfgd::materials::titaniumDioxide); + // geoBuild->createMedium(titaniumDioxide); + + // FairGeoMedium* polystyrene = geoMedia->getMedium(esbroot::geometry::superfgd::materials::polystyrene); + // geoBuild->createMedium(polystyrene); + + FairGeoMedium* scintillator = geoMedia->getMedium(esbroot::geometry::superfgd::materials::scintillator); + scintillator->setMediumIndex(esbroot::geometry::superfgd::materials::GetNextIndex()); + geoBuild->createMedium(scintillator); + scintillator->Print(); + + FairGeoMedium* paraterphnyl = geoMedia->getMedium(esbroot::geometry::superfgd::materials::paraterphnyl); + geoBuild->createMedium(paraterphnyl); + + // FairGeoMedium* podscintillator = geoMedia->getMedium(esbroot::geometry::superfgd::materials::podscintillator); + // geoBuild->createMedium(podscintillator); + + // FairGeoMedium* polyethylene = geoMedia->getMedium(esbroot::geometry::superfgd::materials::polyethylene); + // geoBuild->createMedium(polyethylene); + + // FairGeoMedium* poduleEpoxy = geoMedia->getMedium(esbroot::geometry::superfgd::materials::poduleEpoxy); + // geoBuild->createMedium(poduleEpoxy); + + // FairGeoMedium* polycarbonate = geoMedia->getMedium(esbroot::geometry::superfgd::materials::polycarbonate); + // geoBuild->createMedium(polycarbonate); + + // FairGeoMedium* carbonFiber = geoMedia->getMedium(esbroot::geometry::superfgd::materials::carbonFiber); + // geoBuild->createMedium(carbonFiber); + + FairGeoMedium* fiberCore = geoMedia->getMedium(esbroot::geometry::superfgd::materials::fiberCore); + geoBuild->createMedium(fiberCore); + + FairGeoMedium* fiberCladding = geoMedia->getMedium(esbroot::geometry::superfgd::materials::fiberCladding); + geoBuild->createMedium(fiberCladding); + + FairGeoMedium* fairTiO2 = geoMedia->getMedium(esbroot::geometry::superfgd::materials::titaniumDioxide); + geoBuild->createMedium(fairTiO2); + + FairGeoMedium* fairPolystyrene = geoMedia->getMedium(esbroot::geometry::superfgd::materials::polystyrene); + geoBuild->createMedium(fairPolystyrene); + + FairGeoMedium* fairAir = geoMedia->getMedium(esbroot::geometry::superfgd::materials::air); + geoBuild->createMedium(fairAir); + + FairGeoMedium* vacuum = geoMedia->getMedium(esbroot::geometry::superfgd::materials::vacuum); + geoBuild->createMedium(vacuum); +} + +void FgdGenFitRecon::PrintFitTrack(genfit::Track& fitTrack) +{ + const genfit::MeasuredStateOnPlane& me = fitTrack.getFittedState(); + //LOG(debug)<< "Momentum " << (me.getMom()).Mag(); + //LOG(debug)<< " X " << (me.getMom()).X()<< " Y " << (me.getMom()).Y()<< " Z " << (me.getMom()).Z(); + LOG(debug)<< "\tFitted Momentum [" << (me.getMom()).Mag() <<"]" << "(" << (me.getMom()).X() << "," << (me.getMom()).Y() << "," << (me.getMom()).Z() << ")"; + + genfit::FitStatus* fiStatuStatus = fitTrack.getFitStatus(); + fiStatuStatus->Print(); + + LOG(debug)<< "fiStatuStatus->isFitted() " << fiStatuStatus->isFitted(); + LOG(debug)<< "fiStatuStatus->isFitConverged() " << fiStatuStatus->isFitConverged(); + LOG(debug)<< "fiStatuStatus->isFitConvergedFully() " << fiStatuStatus->isFitConvergedFully(); + LOG(debug)<< "fiStatuStatus->isFitConvergedPartially() " << fiStatuStatus->isFitConvergedPartially(); + LOG(debug)<< "fitTrack.getNumPoints() " << fitTrack.getNumPoints(); +} + +Long_t FgdGenFitRecon::ArrInd(int x, int y, int z) +{ + return (x*f_bin_Y*f_bin_Z + y*f_bin_Z+z); +} + +// ------------------------------------------------------------------------- + +}// namespace superfgd +}// namespace reconstruction +}// namespace esbroot diff --git a/EsbReconstruction/EsbSuperFGD/FgdGenFitRecon.h b/EsbReconstruction/EsbSuperFGD/FgdGenFitRecon.h new file mode 100644 index 0000000..92625a1 --- /dev/null +++ b/EsbReconstruction/EsbSuperFGD/FgdGenFitRecon.h @@ -0,0 +1,183 @@ +#ifndef ESBROOT_ESBDRECONSTRUCTION_FGD_GENFIT_H +#define ESBROOT_ESBDRECONSTRUCTION_FGD_GENFIT_H + +// EsbRoot headers +#include "EsbData/EsbSuperFGD/FgdHit.h" +#include "EsbGeometry/EsbSuperFGD/EsbFgdDetectorParameters.h" +#include "EsbGeometry/EsbSuperFGD/EsbSuperFGDDetectorConstruction.h" +#include "EsbReconstruction/EsbSuperFGD/FgdReconHit.h" +#include "EsbReconstruction/EsbSuperFGD/PdgFromMomentumLoss.h" + +// FairRoot headers +#include + +// ROOT headers +#include + +// Pathfinder headers +#include "basicHit.h" +#include "TrackFinderTrack.h" + +namespace esbroot { +namespace reconstruction { +namespace superfgd { + +class FgdGenFitRecon : public FairTask +{ + + public: + + enum TrackFinder{ + HOUGH_PATHFINDER_LINE, + HOUGH_PATHFINDER_HELIX, + HOUGH_PATHFINDER_CURL, + GRAPH, + GRAPH_HOUGH_PATHFINDER + }; + + /** Default constructor **/ + FgdGenFitRecon(); + + /** Constructor with argument + *@param name Name of task + *@param geoConfigFile - Configuration file detector + *@param mediaFile - Configuration file for the used mediums + *@param verbose - Verbosity level + *@param debugLlv - debug level for genfit + *@param visualize - to visualize the event using genfit::EventDisplay + *@param visOption - option to be passed to genfit::EventDisplay + **/ + FgdGenFitRecon(const char* name + , const char* geoConfigFile + , const char* mediaFile + , Int_t verbose = 1 + , double debugLlv = 0 + , bool visualize = false + , std::string visOption ="D"); + + /** Destructor **/ + virtual ~FgdGenFitRecon(); + + void SetMinInterations(Int_t minIterations) {fminGenFitInterations = minIterations;} + void SetMaxInterations(Int_t maxIterations) {fmaxGenFitIterations = maxIterations;} + void SetMinHits(Int_t minHits) {fminHits = minHits;} + void SetUseTracker(FgdGenFitRecon::TrackFinder finder){ffinder=finder;} + void AddPdgMomLoss(Int_t pdg, Double_t momLoss, Double_t allowDiff){ fpdgFromMomLoss.emplace_back(pdg, momLoss, allowDiff);} + + /** Virtual method Init **/ + virtual InitStatus Init() override; + virtual void OutputFileInit(FairRootManager* manager); // Create virtual method for output file creation + virtual void FinishEvent() override; + virtual void FinishTask() override; + + + /** Virtual method Exec **/ + virtual void Exec(Option_t* opt) override; + +protected: + + enum FindTrackType{ + STRAIGHT_LINE, + HELIX, + CURL + }; + + /** Get all hits **/ + Bool_t GetHits(std::vector& allHits); + + /** Extrack tracks from the hit using Hough Transform **/ + Bool_t FindUsingHough(std::vector& points + , std::vector& hits + , std::vector>& foundTracks + , FindTrackType trackType); + + /** Extrack tracks using graph traversal and track gradient **/ + Bool_t FindUsingGraph(std::vector& hits + , std::vector>& foundTracks); + + /** Extrack tracks using graph traversal and track gradient and then apply Hough transform for each track **/ + Bool_t FindUsingGraphHough(std::vector& hits + , std::vector>& foundTracks); + + void BuildGraph(std::vector& hits); + void CalculateGrad(std::vector>& tracks); + void SplitTrack(std::vector>& originalTracks, std::vector>& splitTracks); + Bool_t CalculateInitialMomentum(const std::vector& track,const TVector3& magField, TVector3& momentum, TVector3& momentumLoss); + Bool_t CalculateMomentum(const TVector3& p1, const TVector3& p2, const TVector3& p3 , const TVector3& magField, TVector3& momentum); + Double_t GetRadius(const TVector3& p1, const TVector3& p2, const TVector3& p3); + Int_t GetPdgCode(const TVector3& momentum, const TVector3& momentumLoss); + void ConvertHitToVec(std::vector& points, std::vector& hits); + + /** Fit the found tracks using genfit **/ + void FitTracks(std::vector>& foundTracks); + + /** Define materials used in the reconstruction phase **/ + void DefineMaterials(); + + /** Print information for fitted grack **/ + void PrintFitTrack(genfit::Track& track); + + Long_t ArrInd(int i, int j, int k); + + /** Class to hold the Detector parameters read from external file **/ + esbroot::geometry::superfgd::FgdDetectorParameters fParams; + + /** Class containing the TGeometry for reconstruction of the tracks **/ + esbroot::geometry::superfgd::SuperFGDDetectorConstruction fgdConstructor; //! SuperFgd Detector Constructor + + /** Detector geometry pointer**/ + TGeoVolume* fsuperFgdVol; + + /** Input array of FgdDetectorPoint(s)**/ + TClonesArray* fHitArray; //! + + /** Output array with genfit::Track(s) **/ + TClonesArray* fTracksArray; //! + + /** Detector dimentions **/ + Double_t flunit; + double f_step_X; + double f_step_Y; + double f_step_Z; + int f_bin_X; + int f_bin_Y; + int f_bin_Z; + double f_total_X; + double f_total_Y; + double f_total_Z; + + /** Start position and momentum **/ + // 0 - no additional info + // 1 - debug info + // 2- detail info + double fDebuglvl_genfit; + + FgdGenFitRecon::TrackFinder ffinder; + + /** Path to the used media.geo file - containing definitions of materials **/ + std::string fmediaFile; + + Int_t fminGenFitInterations; + Int_t fmaxGenFitIterations; + Int_t fminHits; + + /** Are materials already defined **/ + bool isDefinedMaterials; + + /** local Members for genfit visualization **/ + genfit::EventDisplay* fdisplay;//! fpdgFromMomLoss;//! +#include "FairVolume.h" + + +// Root headers +#include +#include +#include +#include +#include +#include +#include +#include + +// Genie headers +#include "Framework/ParticleData/PDGCodes.h" +#include "Framework/ParticleData/PDGUtils.h" + +// Genfit headers +#include "AbsBField.h" +#include "AbsMeasurement.h" +#include "ConstField.h" +#include +#include +#include +#include "FitStatus.h" +#include +#include "MaterialEffects.h" +#include "MeasuredStateOnPlane.h" +#include +#include +#include "SpacepointMeasurement.h" +#include +#include "TDatabasePDG.h" +#include +#include +#include +#include +#include +#include + + + +// STL headers +#include +#include +#include +#include +#include +#include +#include + +namespace esbroot { +namespace reconstruction { +namespace superfgd { + +// ----- Default constructor ------------------------------------------- +FgdGraphStats::FgdGraphStats() : + FairTask() + , fgdConstructor("") +{ +} +// ------------------------------------------------------------------------- + +// ----- Constructor ------------------------------------------- +FgdGraphStats::FgdGraphStats(const char* name + , const char* geoConfigFile + , const char* mediaFile + , const char* eventData + , const char* outputRootFile + , Int_t verbose + , double debugLlv) : + FairTask(name, verbose) + , fgdConstructor(geoConfigFile) + , fMinTrackLenght(0) +{ + fpdgDB = make_shared(); + fParams.LoadPartParams(geoConfigFile); +} +// ------------------------------------------------------------------------- + + + +// ----- Destructor ---------------------------------------------------- +FgdGraphStats::~FgdGraphStats() +{ + if(fHitArray) + { + fHitArray->Delete(); + } + delete fHitArray; +} +// ------------------------------------------------------------------------- + + +InitStatus FgdGraphStats::Init() +{ + DefineMaterials(); + fsuperFgdVol = fgdConstructor.Construct(); + gGeoManager->SetTopVolume(fsuperFgdVol); + + // Get dimentions from geometry file + flunit = fParams.GetLenghtUnit(); // [cm] + + f_step_X = fParams.ParamAsDouble(esbroot::geometry::superfgd::DP::length_X) * flunit; + f_step_Y = fParams.ParamAsDouble(esbroot::geometry::superfgd::DP::length_Y) * flunit; + f_step_Z = fParams.ParamAsDouble(esbroot::geometry::superfgd::DP::length_Z) * flunit; + + f_bin_X = fParams.ParamAsInt(esbroot::geometry::superfgd::DP::number_cubes_X); + f_bin_Y = fParams.ParamAsInt(esbroot::geometry::superfgd::DP::number_cubes_Y); + f_bin_Z = fParams.ParamAsInt(esbroot::geometry::superfgd::DP::number_cubes_Z); + + f_total_X = f_step_X * f_bin_X; + f_total_Y = f_step_Y * f_bin_Y; + f_total_Z = f_step_Z * f_bin_Z; + + fMinTrackLenght = fParams.ParamAsInt(esbroot::geometry::superfgd::DP::FGD_MIN_TRACK_LENGTH); + + // Get RootManager + FairRootManager* manager = FairRootManager::Instance(); + if ( !manager ) { + LOG(fatal) << "-E- FgdGenFitRecon::Init: " << "FairRootManager not instantised!"; + return kFATAL; + } + + fHitArray = (TClonesArray*) manager->GetObject(geometry::superfgd::DP::FGD_HIT.c_str()); + if (!fHitArray) + { + LOG(fatal) << "Exec", "No fgd hits array"; + return kFATAL; + } + + return kSUCCESS; +} + +void FgdGraphStats::FinishTask() +{ + +} + + +void FgdGraphStats::Exec(Option_t* opt) +{ + static int event = 0; + try + { + LOG(info) << " Event " << event++; + LOG(info) << " ======================== "; + std::vector allMChits; + std::vector> foundMCTracks; + + bool rc = GetMCHits(allMChits); + + if(!rc) LOG(info) << " Could not get MC hits"; + + std::vector allGRhits; + std::vector> foundGRTracks; + + rc = rc && GetGraphHits(allGRhits); + + + if(!rc) LOG(info) << " Could not get graph hits"; + + if(rc) + { + LOG(debug) <<" MC Hits to retrieve stats from " << allMChits.size(); + //SplitMCTrack(allMChits, foundMCTracks); + SplitMCTrack(allGRhits, foundMCTracks); + } + + + if(rc) + { + LOG(debug) <<" GR Hits to retrieve stats from " << allGRhits.size(); + rc = FindUsingGraph(allGRhits, foundGRTracks); + } + + if(!rc) LOG(info) << " Could not Find graph hits"; + + if(rc) + { + LOG(info) << "=============================="; + LOG(info) <<" MC tracks found " << foundMCTracks.size(); + LOG(info) <<" Graph tracks found " << foundGRTracks.size(); + CompareTracks(foundMCTracks, foundGRTracks); + } + else + { + LOG(error) << " Could not find clean hits or tracks! "; + } + } + catch(genfit::Exception& e) + { + LOG(fatal) << "Exception, when tryng to fit track"; + LOG(fatal) << e.what(); + } +} + +void FgdGraphStats::CompareTracks(std::vector>& mcTracks, std::vector>& grTracks) +{ + // 1. Calculate number of trakcs in Graph + int numOfGRTracksBigThanLimit = 0; + for(Int_t grInd = 0 ; grInd < grTracks.size(); ++grInd) + { + std::vector& track = grTracks[grInd]; + if(track.size() > fMinTrackLenght) numOfGRTracksBigThanLimit++; + } + + // 2. Calculate number of tracks in MC (charged particles only) + int numOfMCTracksBigThanLimit = 0; + for(Int_t mcInd = 0 ; mcInd < mcTracks.size(); ++mcInd) + { + std::vector track = mcTracks[mcInd]; + if(track.size() > fMinTrackLenght + && IsChargedParticle(track[0])) + { + numOfMCTracksBigThanLimit++; + } + } + + LOG(info) << "+++++++++++++++++++++++++++++++++"; + LOG(info) << " Graph tracks ["<< fMinTrackLenght <<" cubes at least] = " << numOfGRTracksBigThanLimit; + LOG(info) << " MC tracks ["<< fMinTrackLenght <<" cubes at least/ charge is not zero of the particle] = " << numOfMCTracksBigThanLimit; + LOG(info) << " Number of Graph tracks / Number of MC tracks = " << (1.0 * numOfGRTracksBigThanLimit) / numOfMCTracksBigThanLimit; + LOG(info) << "+++++++++++++++++++++++++++++++++"; + + // 3. Calculate the best match for GR track to MC track + for(Int_t grInd = 0 ; grInd < grTracks.size(); ++grInd) + { + std::vector& grtrack = grTracks[grInd]; + if(grtrack.size() <= fMinTrackLenght) continue; + + Double_t maxFit = 0; + Int_t indOfMcMaxFit = 0; + + for(Int_t mcInd = 0 ; mcInd < mcTracks.size(); ++mcInd) + { + std::vector mctrack = mcTracks[mcInd]; + if(mctrack.size() > fMinTrackLenght + && IsChargedParticle(mctrack[0])) + { + Double_t res = CmpGrToMCTrack(mctrack, grtrack); + if(res > maxFit) + { + maxFit = res; + indOfMcMaxFit = mcInd; + } + } + } + + LOG(info) << "+++++++++++++++++++++++++++++++++"; + LOG(info) << " Graph track" << "[ " << grInd << " (size " << grtrack.size() << ")] best fit is " << maxFit; + LOG(info) << " MC trakc length for best fit = " << mcTracks[indOfMcMaxFit].size(); + LOG(info) << "+++++++++++++++++++++++++++++++++"; + } +} + +Double_t FgdGraphStats::CmpGrToMCTrack(std::vector& mc, std::vector& gr) +{ + Int_t isInMC = 0; + for(Int_t i = 0; i < gr.size(); ++i) + { + if(ContainsHit(mc, *gr[i])) + { + ++isInMC; + } + } + return (1.0 * isInMC) / mc.size(); +} + +Bool_t FgdGraphStats::ContainsHit(std::vector& mctrack, ReconHit& hit) +{ + bool rc(false); + for(Int_t i = 0 ; !rc && (i < mctrack.size()); ++i) + { + rc = (mctrack[i] == hit); + } + + return rc; +} + +Bool_t FgdGraphStats::GetMCHits(std::vector& allHits) +{ + Double_t errPhotoLimit = fParams.ParamAsDouble(esbroot::geometry::superfgd::DP::FGD_ERR_PHOTO_LIMIT); + + LOG(debug) << "fHitArray->GetEntries() " << fHitArray->GetEntries(); + + std::map visited; + + Int_t numVis(0); + + for(Int_t i =0; i < fHitArray->GetEntries() ; i++) + { + data::superfgd::FgdHit* hit = (data::superfgd::FgdHit*)fHitArray->At(i); + TVector3 photoE = hit->GetPhotoE(); + TVector3 mppcLoc = hit->GetMppcLoc(); + + Int_t&& x = mppcLoc.X(); + Int_t&& y = mppcLoc.Y(); + Int_t&& z = mppcLoc.Z(); + + Double_t totalPhotons = photoE.X() + photoE.Y() + photoE.Z(); + if(totalPhotons >= errPhotoLimit) + { + TVectorD hitPos(3); + hitPos(0) = -f_total_X/2 + f_step_X*mppcLoc.X() +f_step_X/2; + hitPos(1) = -f_total_Y/2 + f_step_Y*mppcLoc.Y() +f_step_Y/2; + hitPos(2) = -f_total_Z/2 + f_step_Z*mppcLoc.Z() +f_step_Z/2; + + allHits.emplace_back(ReconHit( + mppcLoc + , TVector3(hitPos(0),hitPos(1),hitPos(2)) + , photoE + , hit->GetTime() + , hit->GetMomentum() + , hit->GetExitMomentum() + , hit->GetTrackLenght() + , hit->GetTrackLengthOrigin() + , hit->GetPgd() + , hit->GetTrackId() + , hit->GetEdep() + , hit->GetPhotoDist1() + , hit->GetMppcDist1() + , hit->GetPhotoDist2() + , hit->GetMppcDist2() + )); + } + } + + LOG(debug) << "allHits.size() " << allHits.size(); + + return (allHits.size() > 0); +} + +Bool_t FgdGraphStats::GetGraphHits(std::vector& allHits) +{ + Double_t errPhotoLimit = fParams.ParamAsDouble(esbroot::geometry::superfgd::DP::FGD_ERR_PHOTO_LIMIT); + + LOG(debug) << "fHitArray->GetEntries() " << fHitArray->GetEntries(); + + std::map visited; + + Int_t numVis(0); + + for(Int_t i =0; i < fHitArray->GetEntries() ; i++) + { + data::superfgd::FgdHit* hit = (data::superfgd::FgdHit*)fHitArray->At(i); + + TVector3 photoE = hit->GetPhotoE(); + TVector3 mppcLoc = hit->GetMppcLoc(); + + Int_t&& x = mppcLoc.X(); + Int_t&& y = mppcLoc.Y(); + Int_t&& z = mppcLoc.Z(); + + LOG(debug) << "TrackId " << hit->GetTrackId(); + LOG(debug) << "GetPgd " << hit->GetPgd(); + LOG(debug) << "GetTrackLengthOrigin " << hit->GetTrackLengthOrigin(); + LOG(debug) << "GetTrackLenght " << hit->GetTrackLenght(); + + Int_t ind = ArrInd(x,y,z); + if(visited[ind]) + { + // If already exists, add the photons + continue; + } + visited[ind] = true; + + Double_t totalPhotons = photoE.X() + photoE.Y() + photoE.Z(); + if(totalPhotons >= errPhotoLimit) + { + TVectorD hitPos(3); + hitPos(0) = -f_total_X/2 + f_step_X*mppcLoc.X() +f_step_X/2; + hitPos(1) = -f_total_Y/2 + f_step_Y*mppcLoc.Y() +f_step_Y/2; + hitPos(2) = -f_total_Z/2 + f_step_Z*mppcLoc.Z() +f_step_Z/2; + + allHits.emplace_back(ReconHit( + mppcLoc + , TVector3(hitPos(0),hitPos(1),hitPos(2)) + , photoE + , hit->GetTime() + , hit->GetMomentum() + , hit->GetExitMomentum() + , hit->GetTrackLenght() + , hit->GetTrackLengthOrigin() + , hit->GetPgd() + , hit->GetTrackId() + , hit->GetEdep() + , hit->GetPhotoDist1() + , hit->GetMppcDist1() + , hit->GetPhotoDist2() + , hit->GetMppcDist2() + )); + } + } + + LOG(debug) << "allHits.size() " << allHits.size(); + + return (allHits.size() > 0); +} + +void FgdGraphStats::SplitMCTrack(std::vector& allHits, std::vector>& foundTracks) +{ + std::map> tracks; + for(size_t i = 0; i < allHits.size(); ++i) + { + ReconHit& rh = allHits[i]; + + if(tracks.find(rh.ftrackId)!=tracks.end()) + { + tracks[rh.ftrackId].push_back(rh); + } + else + { + tracks[rh.ftrackId] = std::vector {rh}; + LOG(debug2) << rh.ftrackId << " " << rh.fpdg << "[pdg]"; + } + } + + for(auto iter = tracks.begin(); iter!=tracks.end(); ++iter) + { + LOG(debug2) << iter->first << " track size " << (iter->second).size(); + foundTracks.emplace_back(iter->second); + } +} + + +void FgdGraphStats::DefineMaterials() +{ + if(isDefinedMaterials) return; // Define materials only once + + isDefinedMaterials = true; + + new FairGeoLoader("TGeo","Geo Loader"); + FairGeoLoader *geoLoad = FairGeoLoader::Instance(); + if(geoLoad==nullptr) + { + LOG(error)<< "geoLoad is null"; + std::cout << "geoLoad is null" << endl; + throw; + } + + FairGeoInterface *geoFace = geoLoad->getGeoInterface(); + + geoFace->setMediaFile(fmediaFile.c_str()); + geoFace->readMedia(); + + FairGeoMedia *geoMedia = geoFace->getMedia(); + FairGeoBuilder* geoBuild = geoLoad->getGeoBuilder(); + + // FairGeoMedium* brass = geoMedia->getMedium(esbroot::geometry::superfgd::materials::brass); + // geoBuild->createMedium(brass); + + // FairGeoMedium* bronze = geoMedia->getMedium(esbroot::geometry::superfgd::materials::bronze); + // geoBuild->createMedium(bronze); + + // FairGeoMedium* stainlessSteel = geoMedia->getMedium(esbroot::geometry::superfgd::materials::stainlessSteel); + // geoBuild->createMedium(stainlessSteel); + + // FairGeoMedium* methane = geoMedia->getMedium(esbroot::geometry::superfgd::materials::methane); + // geoBuild->createMedium(methane); + + // FairGeoMedium* carbonDioxide = geoMedia->getMedium(esbroot::geometry::superfgd::materials::carbonDioxide); + // geoBuild->createMedium(carbonDioxide); + + // FairGeoMedium* carbontetraFloride = geoMedia->getMedium(esbroot::geometry::superfgd::materials::carbontetraFloride); + // geoBuild->createMedium(carbontetraFloride); + + // FairGeoMedium* titaniumDioxide = geoMedia->getMedium(esbroot::geometry::superfgd::materials::titaniumDioxide); + // geoBuild->createMedium(titaniumDioxide); + + // FairGeoMedium* polystyrene = geoMedia->getMedium(esbroot::geometry::superfgd::materials::polystyrene); + // geoBuild->createMedium(polystyrene); + + FairGeoMedium* scintillator = geoMedia->getMedium(esbroot::geometry::superfgd::materials::scintillator); + scintillator->setMediumIndex(esbroot::geometry::superfgd::materials::GetNextIndex()); + geoBuild->createMedium(scintillator); + scintillator->Print(); + + FairGeoMedium* paraterphnyl = geoMedia->getMedium(esbroot::geometry::superfgd::materials::paraterphnyl); + geoBuild->createMedium(paraterphnyl); + + // FairGeoMedium* podscintillator = geoMedia->getMedium(esbroot::geometry::superfgd::materials::podscintillator); + // geoBuild->createMedium(podscintillator); + + // FairGeoMedium* polyethylene = geoMedia->getMedium(esbroot::geometry::superfgd::materials::polyethylene); + // geoBuild->createMedium(polyethylene); + + // FairGeoMedium* poduleEpoxy = geoMedia->getMedium(esbroot::geometry::superfgd::materials::poduleEpoxy); + // geoBuild->createMedium(poduleEpoxy); + + // FairGeoMedium* polycarbonate = geoMedia->getMedium(esbroot::geometry::superfgd::materials::polycarbonate); + // geoBuild->createMedium(polycarbonate); + + // FairGeoMedium* carbonFiber = geoMedia->getMedium(esbroot::geometry::superfgd::materials::carbonFiber); + // geoBuild->createMedium(carbonFiber); + + FairGeoMedium* fiberCore = geoMedia->getMedium(esbroot::geometry::superfgd::materials::fiberCore); + geoBuild->createMedium(fiberCore); + + FairGeoMedium* fiberCladding = geoMedia->getMedium(esbroot::geometry::superfgd::materials::fiberCladding); + geoBuild->createMedium(fiberCladding); + + FairGeoMedium* fairTiO2 = geoMedia->getMedium(esbroot::geometry::superfgd::materials::titaniumDioxide); + geoBuild->createMedium(fairTiO2); + + FairGeoMedium* fairPolystyrene = geoMedia->getMedium(esbroot::geometry::superfgd::materials::polystyrene); + geoBuild->createMedium(fairPolystyrene); + + FairGeoMedium* fairAir = geoMedia->getMedium(esbroot::geometry::superfgd::materials::air); + geoBuild->createMedium(fairAir); + + FairGeoMedium* vacuum = geoMedia->getMedium(esbroot::geometry::superfgd::materials::vacuum); + geoBuild->createMedium(vacuum); +} + +Bool_t FgdGraphStats::FindUsingGraph(std::vector& hits + , std::vector>& foundTracks) +{ + if(hits.empty()) + { + return false; + } + + BuildGraph(hits); + + // Print out the build graph + for(Int_t i=0; ifmppcLoc - localHit->fmppcLoc; + LOG(debug) << " Local Id "<< hits[i].fAllHits[j]->fLocalId << " \t X " << diff.X() << " \t Y " << diff.Y() << " \t Z " << diff.Z(); + } + LOG(debug) << "X " << hits[i].fmppcLoc.X() << " Y " << hits[i].fmppcLoc.Y()<< " Z " << hits[i].fmppcLoc.Z(); + LOG(debug) << "Photons "<< " X " << hits[i].fphotons.X() << " Y " << hits[i].fphotons.Y()<< " Z " << hits[i].fphotons.Z(); + LOG(debug) << "====="; + } + + + FgdReconTemplate reconTemplates; + + std::vector> tracks; + + ReconHit* currentHit = nullptr; + ReconHit* nextHit = nullptr; + ReconHit* previousHit = nullptr; + for(size_t i=0; i track; + track.push_back(&hits[i]); + + hits[i].fIsLeaf = true; + currentHit = &hits[i]; + + while(reconTemplates.GetNextHit(previousHit, currentHit, nextHit)) + { + if(nextHit->fIsLeaf || nextHit->fIsVisited) + { + break; + } + track.push_back(nextHit); + currentHit->fIsVisited = true; + previousHit = currentHit; + currentHit = nextHit; + } + + tracks.push_back(track); + } + } + + LOG(debug) <<"Leaves found " << tracks.size(); // Initially leaves are equal to the number of tracks + + CalculateGrad(tracks); + + SplitGRTrack(tracks, foundTracks); + + return !foundTracks.empty(); +} + + +void FgdGraphStats::BuildGraph(std::vector& hits) +{ + // Create the position to which index in the vector it is pointing + std::map positionToId; + for(Int_t i=0; i>& tracks) +{ + const Int_t distToCalc = fParams.ParamAsInt(esbroot::geometry::superfgd::DP::FGD_GRAD_DIST); + const Int_t intervalToCal = fParams.ParamAsInt(esbroot::geometry::superfgd::DP::FGD_GRAD_INTERVAL_DIST); + const Double_t radToDeg = 180/TMath::Pi(); + TVector3 zAxisVec(0,0,1); + + for(Int_t i=0; i& track = tracks[i]; + LOG(debug2) << "=================================== "; + LOG(debug2) << "Track " << i; + + for(Int_t j=0; j=1) + { + ReconHit* previous = track[j-1]; + diffVec = currentHit->fmppcLoc - previous->fmppcLoc; + } + + // 2.Calculate cosine change beween 2 consecutive vectors - gradient + Double_t diffAngle(0); // Difference angle between two vectors - the vectors are the difference in position (grad (position)) + // between two hits distToCalc cubes apart. The angles measures the angle change of the track + // from hit to hit. distToCalc distance is selected to smooth out the change in angle. + + Double_t zAxisAngle(0); // Vector angle between the z axis and the vector difference between the current hit and the hit distToCalc + // poisitions back. + + TVector3 diffVec1(0,0,0); + TVector3 diffVec2(0,0,0); + + Int_t indOne = j - distToCalc + 1; + Int_t indTwo = j; // current hit + + if(j>= (distToCalc -1) ) + { + ReconHit* one = track[indOne]; + ReconHit* two = track[indTwo]; + diffVec1 = two->fmppcLoc - one->fmppcLoc; + zAxisAngle = radToDeg * zAxisVec.Angle(diffVec1); + + // The z angle is calculated for the current hit + currentHit->fZaxisAngle = zAxisAngle; + } + + Int_t indOneP = indOne - intervalToCal; + Int_t indTwoP = indTwo - intervalToCal; + if(j>= (distToCalc + intervalToCal -1) ) + { + ReconHit* oneP = track[indOneP]; + ReconHit* twoP = track[indTwoP]; + diffVec2 = twoP->fmppcLoc - oneP->fmppcLoc; + + diffAngle = radToDeg * diffVec1.Angle(diffVec2); + + // The angle is calculated for the current hit + currentHit->fChangeAngle = diffAngle; + } + + LOG(debug2) << "Id " << currentHit->fLocalId + << " \tX " << currentHit->fmppcLoc.X() + << " \tY " << currentHit->fmppcLoc.Y() + << " \tZ " << currentHit->fmppcLoc.Z() + << " \tPhotons " << "(" << currentHit->fphotons.X() << "," << currentHit->fphotons.Y() << "," << currentHit->fphotons.Z() << ")" + << " \tChange " << "(" << diffVec.X() << "," << diffVec.Y() << "," << diffVec.Z() << ")" + // << " \t(" << diffVec1.X() << "," << diffVec1.Y() << "," << diffVec1.Z() << ") " + // << " \t(" << diffVec2.X() << "," << diffVec2.Y() << "," << diffVec2.Z() << ") " + << " \tAngle (dist = " << distToCalc << ", interval =" << intervalToCal << ") " << diffAngle + << " \tZ axis Angle (dist = " << distToCalc << ", interval =" << intervalToCal << ") " << zAxisAngle; + } + + LOG(debug2) << "=================================== "; + } +} + +void FgdGraphStats::SplitGRTrack(std::vector>& originalTracks, std::vector>& splitTracks) +{ + const Double_t gradAllowedDiff = fParams.ParamAsDouble(esbroot::geometry::superfgd::DP::FGD_GRAD_ALLOWABLE_DIFF); + LOG(debug) << "Initial tracks size " << originalTracks.size(); + + for(Int_t i=0; i& track = originalTracks[i]; + + if(track.empty()) + { + continue; + } + + std::vector trackToAdd; + trackToAdd.push_back(track[0]); // Add the first hit to start the track + + for(Int_t j=1; jfChangeAngle == 0) + { + // If there is no change add the track + // Also '0' indicates that the track hit is too short to calculate the + // the change. + // Only compare if both the current and previous angle is not zero. + trackToAdd.push_back(currentHit); + } + else if( (currentHit->fChangeAngle != 0) && (previousHit->fChangeAngle != 0) ) + { + Double_t differenceInAngle = currentHit->fChangeAngle - previousHit->fChangeAngle; + Double_t absDiff = std::fabs(differenceInAngle); + if(absDiff >= gradAllowedDiff) + { + // If the difference is not allowed add the current track hit points + // and reset it to start a new track. + splitTracks.emplace_back(trackToAdd); + trackToAdd.clear(); + } + trackToAdd.push_back(currentHit); + } + } + + splitTracks.emplace_back(trackToAdd); + } + + LOG(debug) << "Split tracks size " << splitTracks.size(); +} + + +Bool_t FgdGraphStats::CalculateInitialMomentum(const std::vector& track,const TVector3& magField, TVector3& momentum , TVector3& momentumLoss) +{ + if(track.empty()) + { + momentum.SetXYZ(0.,0.,0); + momentumLoss.SetXYZ(0.,0.,0); + return false; + } + + Int_t segment = fParams.ParamAsInt(esbroot::geometry::superfgd::DP::FGD_TRACK_MOMENTUM_SEGMENT); + Int_t avgInitialPoints = fParams.ParamAsInt(esbroot::geometry::superfgd::DP::FGD_INITIAL_TRACK_POINTS_MOMENTUM); + + const Int_t defaultSegment = 3; + segment = (segment<=0) ? defaultSegment : segment; + avgInitialPoints = (avgInitialPoints<=0) ? defaultSegment : avgInitialPoints; + + // If the track lenght is less than the set segment, calculate the momentum from the arc of the whole track + // using for the 3 points the begin, end and all the middle points between them + Int_t lengthSize = (track.size() < segment ) ? (track.size() -1) : (segment -1) ; + + std::vector trackMomentums; + std::vector tarckMomentumLosses; + + for(size_t i = lengthSize; i< track.size() ; ++i) + { + size_t p1_pos = i - lengthSize; + TVector3 p1 = track[p1_pos]; + TVector3 p3 = track[i]; + + size_t p2_pos = p1_pos + 1; + std::vector segmentMomentums; + + while(p2_pos::infinity(); + + return (!std::isnan(momentum.Mag()) && momentum.Mag()!=inf && trackMomentums.size() > 0 ); +} + +Bool_t FgdGraphStats::CalculateMomentum(const TVector3& p1, const TVector3& p2, const TVector3& p3 , const TVector3& magField, TVector3& momentum) +{ + // + // p [Gev/c] = e [1.6 x 10^-19 coulumb] * B [T] * R [m] + // + + Bool_t rc(false); + + // For calculation charge is taken as 1 unit of 'e' + const Double_t charge = 1.; + + Double_t inf = std::numeric_limits::infinity(); + + TVector3 x_axis(1,0,0); + TVector3 y_axis(0,1,0); + TVector3 z_axis(0,0,1); + + TVector3 length = p3 - p1; + Double_t x_angle = x_axis.Angle(length); + Double_t y_angle = y_axis.Angle(length); + Double_t z_angle = z_axis.Angle(length); + + // For each magnetic field plane calculate it for the perpendicular projections + if(magField.X()!=0) + { + TVector3 mag_point1(0,p1.Y(), p1.Z()); + TVector3 mag_point2(0,p2.Y(), p2.Z()); + TVector3 mag_point3(0,p3.Y(), p3.Z()); + Double_t radius = GetRadius(mag_point1,mag_point2,mag_point3); // radius is returned in [cm] + + if(!std::isnan(radius) && radius!=inf) + { + Double_t R = radius/100.; // convert in meters + Double_t magField_T = magField.X() / 10.; // convert from kGauss to Tesla units + Double_t mom = charge * R * magField_T; + + Double_t mom_x = std::cos(x_angle) * mom; + Double_t mom_y = std::cos(y_angle) * mom; + Double_t mom_z = std::cos(z_angle) * mom; + + momentum.SetX(mom_x); + momentum.SetY(mom_y); + momentum.SetZ(mom_z); + rc = true; + } + } + + if(magField.Y()!=0) + { + TVector3 mag_point1(p1.X(), 0. , p1.Z()); + TVector3 mag_point2(p2.X(), 0. , p2.Z()); + TVector3 mag_point3(p3.X(), 0. , p3.Z()); + Double_t radius = GetRadius(mag_point1,mag_point2,mag_point3); // radius is returned in [cm] + + if(!std::isnan(radius) && radius!=inf) + { + Double_t R = radius/100.; // convert in meters + Double_t magField_T = magField.Y() / 10.; // convert from kGauss to Tesla units + Double_t mom = charge * R * magField_T; + + Double_t mom_x = std::cos(x_angle) * mom + momentum.X(); + Double_t mom_y = std::cos(y_angle) * mom + momentum.Y(); + Double_t mom_z = std::cos(z_angle) * mom + momentum.Z(); + + momentum.SetX(mom_x); + momentum.SetY(mom_y); + momentum.SetZ(mom_z); + rc = true; + } + } + + if(magField.Z()!=0) + { + TVector3 mag_point1(p1.X(), p1.Y() , 0.); + TVector3 mag_point2(p2.X(), p2.Y() , 0.); + TVector3 mag_point3(p3.X(), p3.Y() , 0.); + Double_t radius = GetRadius(mag_point1,mag_point2,mag_point3); // radius is returned in [cm] + + if(!std::isnan(radius) && radius!=inf) + { + Double_t R = radius/100.; // convert in meters + Double_t magField_T = magField.Z() / 10.; // convert from kGauss to Tesla units + Double_t mom = charge * R * magField_T; + + Double_t mom_x = std::cos(x_angle) * mom + momentum.X(); + Double_t mom_y = std::cos(y_angle) * mom + momentum.Y(); + Double_t mom_z = std::cos(z_angle) * mom + momentum.Z(); + + momentum.SetX(mom_x); + momentum.SetY(mom_y); + momentum.SetZ(mom_z); + rc = true; + } + } + + return rc; +} + + +// Calculate the radius from 3 points using the "Menger curvature" theorem +Double_t FgdGraphStats::GetRadius(const TVector3& p1, const TVector3& p2, const TVector3& p3) +{ + // + // p1 + // /\\ + // y / \\ x + // / \\ + // /______\\ + // p2 p3 + // z + // + // 2 sin (Angle(xyz)) + // c(x,y,z) = ------------------------ + // |x - z| + // + // where Angle(xyz) is the angle from point p2 to point p1 and p3 + // and |x - z| is the magnitude of the line connecting points p2 and p3 + + TVector3 x = p3 - p1; + TVector3 y = p2 - p1; + TVector3 z = p2 - p3; + + Double_t angle = y.Angle(x); + Double_t x_z_Mag = z.Mag(); + + Double_t c = (2*std::sin(angle))/x_z_Mag; + Double_t R = 1./c; + + LOG(debug3) << "Radius is -> " << R << " [cm]"; + + return R; +} + +Bool_t FgdGraphStats::IsChargedParticle(ReconHit& hit) +{ + bool rc(false); + + TParticlePDG* tPdg = fpdgDB->GetParticle(hit.fpdg); + rc = (tPdg!=nullptr) && (tPdg->Charge()!=0); + + return rc; +} + +Bool_t FgdGraphStats::isParticleNeutral(Int_t pdg) +{ + Bool_t isNeutral = (pdg == genie::kPdgNeutron) || + (pdg == genie::kPdgPi0) || + (pdg == genie::kPdgGamma) || + genie::pdg::IsNeutralLepton(pdg); + + return isNeutral; +} + +Long_t FgdGraphStats::ArrInd(int x, int y, int z) +{ + return (x*f_bin_Y*f_bin_Z + y*f_bin_Z+z); +} + +}// namespace superfgd +}// namespace reconstruction +}// namespace esbroot \ No newline at end of file diff --git a/EsbReconstruction/EsbSuperFGD/FgdGraphStats.h b/EsbReconstruction/EsbSuperFGD/FgdGraphStats.h new file mode 100644 index 0000000..c2e7590 --- /dev/null +++ b/EsbReconstruction/EsbSuperFGD/FgdGraphStats.h @@ -0,0 +1,138 @@ +#ifndef ESBROOT_ESBDRECONSTRUCTION_FGD_GRAPH_STATS_H +#define ESBROOT_ESBDRECONSTRUCTION_FGD_GRAPH_STATS_H + +// Root headers +#include "TDatabasePDG.h" + +// FairRoot headers +#include + +// EsbRoot headers +#include "EsbData/EsbSuperFGD/FgdHit.h" +#include "EsbGeometry/EsbSuperFGD/EsbFgdDetectorParameters.h" +#include "EsbGeometry/EsbSuperFGD/EsbSuperFGDDetectorConstruction.h" +#include "EsbReconstruction/EsbSuperFGD/FgdReconHit.h" +#include "EsbReconstruction/EsbSuperFGD/PdgFromMomentumLoss.h" + +namespace esbroot { +namespace reconstruction { +namespace superfgd { + +class FgdGraphStats : public FairTask +{ + + public: + + /** Default constructor **/ + FgdGraphStats(); + + /** Constructor with argument + *@param name Name of task + *@param geoConfigFile - Configuration file detector + *@param mediaFile - Configuration file for the used mediums + *@param eventData - events data file (generated from fgd generator) + *@param outputRootFile - full path to the output root file + *@param verbose - Verbosity level + *@param debugLlv - debug level for genfit + **/ + FgdGraphStats(const char* name + , const char* geoConfigFile + , const char* mediaFile + , const char* eventData + , const char* outputRootFile + , Int_t verbose = 1 + , double debugLlv = 0); + + /** Destructor **/ + virtual ~FgdGraphStats(); + + /** Virtual method Init **/ + virtual InitStatus Init() override; + + /** Virtual method Exec **/ + virtual void Exec(Option_t* opt) override; + + virtual void FinishTask() override; + +protected: + + void CompareTracks(std::vector>& mcTracks, std::vector>& grTracks); + /** Get all hits **/ + Bool_t GetMCHits(std::vector& allHits); + Bool_t GetGraphHits(std::vector& allHits); + + void SplitMCTrack(std::vector& allHits, std::vector>& splitTracks); + + Bool_t FindUsingGraph(std::vector& hits + , std::vector>& foundTracks); + + void BuildGraph(std::vector& hits); + void CalculateGrad(std::vector>& tracks); + void SplitGRTrack(std::vector>& originalTracks, std::vector>& splitTracks); + Bool_t CalculateInitialMomentum(const std::vector& track,const TVector3& magField, TVector3& momentum, TVector3& momentumLoss); + Bool_t CalculateMomentum(const TVector3& p1, const TVector3& p2, const TVector3& p3 , const TVector3& magField, TVector3& momentum); + Double_t GetRadius(const TVector3& p1, const TVector3& p2, const TVector3& p3); + + Bool_t IsChargedParticle(ReconHit& hit); + Double_t CmpGrToMCTrack(std::vector& mc, std::vector& gr); + Bool_t ContainsHit(std::vector& mctrack, ReconHit& hit); + + /** Define materials used in the reconstruction phase **/ + void DefineMaterials(); + + Long_t ArrInd(int i, int j, int k); + + Bool_t isParticleNeutral(Int_t pdg); + + /** Class to hold the Detector parameters read from external file **/ + esbroot::geometry::superfgd::FgdDetectorParameters fParams;//! fpdgDB;//! +#include +#include +#include +#include +#include +#include + +namespace esbroot { +namespace reconstruction { +namespace superfgd { + + +// ----- Constructors and Destructors ----------------------------------- + +FgdMCEventRecord::FgdMCEventRecord(std::string eventData) + : TObject(), feventData(eventData), fnuPdg(0) + , fNuEnergy(0.), fvertex(TVector3(0,0,0)), fIsWeakCC(false) + , fIsWeakNC(false), fIsQuasiElastic(false), fIsDeepInElastic(false) + , fIsResonant(false), fIsCoherentProduction(false), fIsMEC(false) + , fIsNuElectronElastic(false), fIsElectronScattering(false) + , fIsPrimaryMuon(false) + , fIsPrimaryElectron(false), fPrimaryMuonMom(TVector3(0,0,0)) + , fPrimaryElectronMom(TVector3(0,0,0)), fMuonTrackLength(0.) + , fIsMuonExiting(false), fMuonExitMomentum(TVector3(0,0,0)) + , fMuonPolarAngle(0.), fMuonAzumAngle(0.), fElectronNumOfExitingParticles(0) + , fGenfitMom(TVector3(0,0,0)), fMC_GentFitError(0.), fProtonEdep(0.) + , fHasHits(false) +{ + Init(); +} + +FgdMCEventRecord::FgdMCEventRecord() + : feventData("") +{ +} + +FgdMCEventRecord::FgdMCEventRecord(const FgdMCEventRecord& c) +{ + this->feventData = c.feventData; + + this->fMuonTrackLength = c.fMuonTrackLength; + this->fIsMuonExiting = c.fIsMuonExiting; + this->fMuonExitMomentum = c.fMuonExitMomentum; + this->fMuonPolarAngle = c.fMuonPolarAngle; + this->fMuonAzumAngle = c.fMuonAzumAngle; + this->fHadronEdep = c.fHadronEdep; + this->fElectronNumOfExitingParticles = c.fElectronNumOfExitingParticles; + this->fGenfitMom = c.fGenfitMom; + this->fMC_GentFitError = c.fMC_GentFitError; + this->fProtonEdep = c.fProtonEdep; + this->fHasHits = c.fHasHits; + + this->Init(); +} + +FgdMCEventRecord::~FgdMCEventRecord() +{ +} +// ------------------------------------------------------------------------- + +// ----- Public methods ------------------------------------------------ + +void FgdMCEventRecord::SetEventData(std::string data) +{ + feventData = data; + + Init(); +} + +Int_t FgdMCEventRecord::GetNuPdg(void) +{ + return fnuPdg; +} + +Double_t FgdMCEventRecord::GetNuE(void) +{ + return fNuEnergy; +} + +TVector3 FgdMCEventRecord::GetVertex(void) +{ + return fvertex; +} + +Bool_t FgdMCEventRecord::IsWeakCC(void) +{ + return fIsWeakCC; +} + +Bool_t FgdMCEventRecord::IsWeakNC(void) +{ + return fIsWeakNC; +} + +Bool_t FgdMCEventRecord::IsQuasiElastic(void) +{ + return fIsQuasiElastic; +} + +Bool_t FgdMCEventRecord::IsDeepInElastic(void) +{ + return fIsDeepInElastic; +} + +Bool_t FgdMCEventRecord::IsResonant(void) +{ + return fIsResonant; +} + +Bool_t FgdMCEventRecord::IsCoherentProduction(void) +{ + return fIsCoherentProduction; +} + +Bool_t FgdMCEventRecord::IsMEC(void) +{ + return fIsMEC; +} + +Bool_t FgdMCEventRecord::IsNuElectronElastic(void) +{ + return fIsNuElectronElastic; +} + +Bool_t FgdMCEventRecord::IsElectronScattering(void) +{ + return fIsElectronScattering; +} + +Bool_t FgdMCEventRecord::HasHits(void) +{ + return fHasHits; +} + + +Bool_t FgdMCEventRecord::IsPrimaryLeptonMuon() +{ + return fIsPrimaryMuon; +} + +TVector3 FgdMCEventRecord::GetMuonMom() +{ + return fPrimaryMuonMom; +} + +Double_t FgdMCEventRecord::GetMuonTrackLength() +{ + return fMuonTrackLength; +} + + +Double_t FgdMCEventRecord::GetMuonTrackLengthOrigin() +{ + return fMuonTrackLengthOrigin; +} + +Bool_t FgdMCEventRecord::IsPrimaryLeptonElectron() +{ + return fIsPrimaryElectron; +} + +TVector3 FgdMCEventRecord::GetElectronMom() +{ + return fPrimaryElectronMom; +} + +Double_t FgdMCEventRecord::GetMuonPolarAngle() +{ + return fMuonPolarAngle; +} + +Double_t FgdMCEventRecord::GetMuonAzumuteAngle() +{ + return fMuonAzumAngle; +} + +void FgdMCEventRecord::SetMuonExitMom(TVector3 exitMom) +{ + fMuonExitMomentum = exitMom; + + Double_t radToAngle = 180/TMath::Pi(); + fMuonPolarAngle = fMuonExitMomentum.Theta() * radToAngle; + fMuonAzumAngle = fMuonExitMomentum.Phi() * radToAngle; +} + + +FgdMCEventRecord& FgdMCEventRecord::operator=(const FgdMCEventRecord& c) +{ + this->feventData = c.feventData; + + this->fMuonTrackLength = c.fMuonTrackLength; + this->fIsMuonExiting = c.fIsMuonExiting; + this->fMuonExitMomentum = c.fMuonExitMomentum; + this->fMuonPolarAngle = c.fMuonPolarAngle; + this->fMuonAzumAngle = c.fMuonAzumAngle; + this->fHadronEdep = c.fHadronEdep; + this->fElectronNumOfExitingParticles = c.fElectronNumOfExitingParticles; + this->fGenfitMom = c.fGenfitMom; + this->fMC_GentFitError = c.fMC_GentFitError; + this->fProtonEdep = c.fProtonEdep; + this->fHasHits = c.fHasHits; + + this->Init(); + return *this; +} + +const std::vector>& FgdMCEventRecord::GetPrimaryParticles() +{ + Init(); + + return fPrimaryParticles; +} + +void FgdMCEventRecord::PrintData(std::ostream & stream) +{ + stream << feventData; +} + +void FgdMCEventRecord::ReadEventData() +{ + this->Init(); +} + +// ------------------------------------------------------------------------- + + +// ----- Protected methods --------------------------------------------- +void FgdMCEventRecord::Init() +{ + fDataTokens.clear(); + + try + { + const char spaceChar(' '); + + std::istringstream ss(feventData); + std::string token; + while(std::getline(ss, token, spaceChar)) + { + if(!token.empty()) + { + fDataTokens.push_back(token); + } + } + InitMembers(); + } + catch(const std::exception& e) + { + LOG(fatal) << e.what(); + } +} + +void FgdMCEventRecord::InitMembers() +{ + fnuPdg = std::stoi(fDataTokens[Data::NEUTRINO_PDG]); + fNuEnergy = std::stod(fDataTokens[Data::NEUTRINO_ENERGY]); + + Double_t x = std::stod(fDataTokens[Data::VERTEX_POSTION_X]); + Double_t y = std::stod(fDataTokens[Data::VERTEX_POSTION_Y]); + Double_t z = std::stod(fDataTokens[Data::VERTEX_POSTION_Z]); + + fvertex = TVector3(x,y,z); + + Int_t isWeakCC = std::stoi(fDataTokens[Data::IS_WEAK_CC]); + fIsWeakCC = (isWeakCC==1); + + Int_t isWeakNC = std::stoi(fDataTokens[Data::IS_WEACK_NC]); + fIsWeakNC = (isWeakNC==1); + + Int_t isQuasiElastic = std::stoi(fDataTokens[Data::IS_QUASI_ELASTIC]); + fIsQuasiElastic = (isQuasiElastic==1); + + Int_t isDIS = std::stoi(fDataTokens[Data::IS_DEEP_INELASRIC]); + fIsDeepInElastic = (isDIS==1); + + Int_t isResonant = std::stoi(fDataTokens[Data::IS_RESONANT]); + fIsResonant = (isResonant==1); + + Int_t isCohPro = std::stoi(fDataTokens[Data::IS_COHERENT_PRODUCTION]); + fIsCoherentProduction = (isCohPro==1); + + Int_t isMec = std::stoi(fDataTokens[Data::IS_MEC]); + fIsMEC = (isMec==1); + + Int_t isNuElEl = std::stoi(fDataTokens[Data::IS_NuElectron_Elastic]); + fIsNuElectronElastic = (isNuElEl==1); + + Int_t isElEl = std::stoi(fDataTokens[Data::IS_ELECTRON_SCATTERING]); + fIsElectronScattering = (isElEl==1); + + // Initalize primary particles + size_t particleDataSize = 4; + + size_t particlePdg = 0; + size_t particleMomX = 1; + size_t particleMomY = 2; + size_t particleMomZ = 3; + + fPrimaryParticles.clear(); + for(size_t i = Data::PRIMARY_PARTICLES; i < fDataTokens.size(); i+=particleDataSize) + { + Int_t pdg = std::stoi(fDataTokens[i + particlePdg]); + Double_t momX = std::stod(fDataTokens[i + particleMomX]); + Double_t momY = std::stod(fDataTokens[i + particleMomY]); + Double_t momZ = std::stod(fDataTokens[i + particleMomZ]); + + fPrimaryParticles.push_back( + std::pair( pdg, TVector3(momX , momY, momZ) ) + ); + } + + for(size_t i = 0; i< fPrimaryParticles.size(); ++i) + { + std::pair& particle = fPrimaryParticles[i]; + if(particle.first == genie::kPdgMuon || particle.first == genie::kPdgAntiMuon) + { + fIsPrimaryMuon = true; + fPrimaryMuonMom = particle.second; + break; + } + + if(particle.first == genie::kPdgElectron || particle.first == genie::kPdgPositron) + { + fIsPrimaryElectron = true; + fPrimaryElectronMom = particle.second; + break; + } + } +} + +// ------------------------------------------------------------------------- + +}// namespace superfgd +}// namespace reconstruction +}// namespace esbroot \ No newline at end of file diff --git a/EsbReconstruction/EsbSuperFGD/FgdMCEventRecord.h b/EsbReconstruction/EsbSuperFGD/FgdMCEventRecord.h new file mode 100644 index 0000000..6f9590f --- /dev/null +++ b/EsbReconstruction/EsbSuperFGD/FgdMCEventRecord.h @@ -0,0 +1,166 @@ +#ifndef ESBROOT_ESBDRECONSTRUCTION_FGD_MC_EVENT_RECORDT_H +#define ESBROOT_ESBDRECONSTRUCTION_FGD_MC_EVENT_RECORDT_H + +#include +#include + +#include +#include + +namespace esbroot { +namespace reconstruction { +namespace superfgd { + +class FgdMCEventRecord : public TObject +{ +public: + + FgdMCEventRecord(std::string eventData); + + FgdMCEventRecord(); + + /* Copy constructor */ + FgdMCEventRecord(const FgdMCEventRecord& c); + + virtual ~FgdMCEventRecord(); + + /* Operators */ + FgdMCEventRecord& operator=(const FgdMCEventRecord& c); + + void SetEventData(std::string data); + + Int_t GetNuPdg(void); + Double_t GetNuE(void); + TVector3 GetVertex(void); + Bool_t IsWeakCC(void); + Bool_t IsWeakNC(void); + Bool_t IsQuasiElastic(void); + + Bool_t IsDeepInElastic(void); + Bool_t IsResonant(void); + Bool_t IsCoherentProduction(void); + Bool_t IsMEC(void); + Bool_t IsNuElectronElastic(void); + Bool_t IsElectronScattering(void); + + + const std::vector>& GetPrimaryParticles(); + + Bool_t HasHits(void); + void SetHasHits(Bool_t h){fHasHits = h;} + + Bool_t IsPrimaryLeptonMuon(); + Bool_t IsMuonExiting(){return fIsMuonExiting;} + void SetMuonExiting(Bool_t muonExit) {fIsMuonExiting = muonExit;} + TVector3 GetMuonExitMom() {return fMuonExitMomentum;} + void SetMuonExitMom(TVector3 exitMom); + Double_t GetHadronEdep() {return fHadronEdep;} + void SetHadronEdep(Double_t edep) {fHadronEdep = edep;} + + Double_t GetMuonPolarAngle(); + Double_t GetMuonAzumuteAngle(); + + TVector3 GetMuonMom(); + Double_t SetMuonTrackLength(Double_t ml) {fMuonTrackLength = ml;} + Double_t GetMuonTrackLength(); + Double_t SetMuonTrackLengthOrigin(Double_t ml) {fMuonTrackLengthOrigin = ml;} + Double_t GetMuonTrackLengthOrigin(); + TVector3 GetGenfitMom(){return fGenfitMom;} + void SetGenfitMom(TVector3 genfitMom){fGenfitMom = genfitMom;} + void SetMomError(Double_t err){fMC_GentFitError = err;} + Double_t GetMomError(){return fMC_GentFitError;} + + void SetProtonEdep(Double_t e){fProtonEdep = e;} // in [MeV] + Double_t GetProtonEdep(){return fProtonEdep;} + + Bool_t IsPrimaryLeptonElectron(); + TVector3 GetElectronMom(); + Int_t GetNumOfExitingPar(){return fElectronNumOfExitingParticles;} + void SetNumOfExitingPar(Int_t numPar){fElectronNumOfExitingParticles = numPar;} + const std::vector GetPdgOfExitingPars(){return fElectronExitingPdg;} + void SetPdgOfExitingPars(const std::vector pars){fElectronExitingPdg = pars;} + + std::string GetEventData(){return feventData; } + + void PrintData(std::ostream & stream); + void ReadEventData(); + +protected: + + enum Data : int // Position in the fDataTokens which value represents which data + { + NEUTRINO_PDG = 0, + NEUTRINO_ENERGY = 1, + IS_WEAK_CC = 2, + IS_WEACK_NC = 3, + IS_QUASI_ELASTIC = 4, + + IS_DEEP_INELASRIC = 5, + IS_RESONANT = 6, + IS_COHERENT_PRODUCTION = 7, + IS_MEC = 8, + IS_NuElectron_Elastic = 9, + IS_ELECTRON_SCATTERING = 10, + + VERTEX_POSTION_X = 11, + VERTEX_POSTION_Y = 12, + VERTEX_POSTION_Z = 13, + PRIMARY_PARTICLES = 14 // The primary particles are written as 4 values - 1st pdg then momentum X, momentum Y, momentum Z + // all data above 14th position are primary particle data + }; + + void Init(); + void InitMembers(); + std::string feventData; + + + Int_t fnuPdg; + Double_t fNuEnergy; + TVector3 fvertex; + Bool_t fIsWeakCC; + Bool_t fIsWeakNC; + Bool_t fIsQuasiElastic; + + Bool_t fIsDeepInElastic; + Bool_t fIsResonant; + Bool_t fIsCoherentProduction; + Bool_t fIsMEC; + Bool_t fIsNuElectronElastic; + Bool_t fIsElectronScattering; + + Bool_t fHasHits; + + Bool_t fIsPrimaryMuon; + Bool_t fIsMuonExiting; + TVector3 fMuonExitMomentum; + Double_t fMuonPolarAngle; + Double_t fMuonAzumAngle; + Double_t fHadronEdep; + TVector3 fGenfitMom; + Double_t fMC_GentFitError; + + Bool_t fIsPrimaryElectron; + std::vector fElectronExitingPdg;//! fDataTokens; + std::vector> fPrimaryParticles;//! +#include "FairVolume.h" + + +// Root headers +#include +#include +#include +#include + +// Genie headers +#include "Framework/ParticleData/PDGCodes.h" +#include "Framework/ParticleData/PDGUtils.h" + +// Genfit headers +#include "AbsBField.h" +#include "AbsMeasurement.h" +#include "ConstField.h" +#include +#include +#include +#include "FitStatus.h" +#include +#include "MaterialEffects.h" +#include "MeasuredStateOnPlane.h" +#include +#include +#include "SpacepointMeasurement.h" +#include +#include "TDatabasePDG.h" +#include +#include +#include +#include +#include +#include + + +// PathFinder headers +#include "FinderParameter.h" +#include "HoughTrafoTrackFinder.h" +#include "TrackParameterFull.h" + + +// STL headers +#include +#include +#include +#include +#include +#include +#include + +namespace esbroot { +namespace reconstruction { +namespace superfgd { + +// ----- Default constructor ------------------------------------------- +FgdMCGenFitRecon::FgdMCGenFitRecon() : + FairTask(), fsuperFgdVol(nullptr) + , fgdConstructor("") + , fHitArray(nullptr) + , isDefinedMaterials(false) + , fDebuglvl_genfit(0) + , fmediaFile("") + , fTracksArray(nullptr) + , fdisplay(nullptr) + , isGenFitVisualization(false) + , fGenFitVisOption("") + , fminGenFitInterations(2) + , fmaxGenFitIterations(4) + , fminHits(25) +{ +} +// ------------------------------------------------------------------------- + +// ----- Constructor ------------------------------------------- +FgdMCGenFitRecon::FgdMCGenFitRecon(const char* name + , const char* geoConfigFile + , const char* mediaFile + , Int_t verbose + , double debugLlv + , bool visualize + , std::string visOption) : + FairTask(name, verbose) + , fsuperFgdVol(nullptr) + , fgdConstructor(geoConfigFile) + , fHitArray(nullptr) + , isDefinedMaterials(false) + , fDebuglvl_genfit(debugLlv) + , fmediaFile(mediaFile) + , fTracksArray(nullptr) + , fdisplay(nullptr) + , isGenFitVisualization(visualize) + , fGenFitVisOption(visOption) + , fminGenFitInterations(2) + , fmaxGenFitIterations(4) + , fminHits(25) +{ + fParams.LoadPartParams(geoConfigFile); +} +// ------------------------------------------------------------------------- + + + +// ----- Destructor ---------------------------------------------------- +FgdMCGenFitRecon::~FgdMCGenFitRecon() +{ + if(fHitArray) { + fHitArray->Delete(); + delete fHitArray; + } + + if(fTracksArray) { + fTracksArray->Delete(); + delete fTracksArray; + } +} +// ------------------------------------------------------------------------- + + + +// ----- Public method Init -------------------------------------------- +InitStatus FgdMCGenFitRecon::Init() +{ + // Create the real Fgd geometry + DefineMaterials(); + fsuperFgdVol = fgdConstructor.Construct(); + gGeoManager->SetTopVolume(fsuperFgdVol); + + // Get dimentions from geometry file + flunit = fParams.GetLenghtUnit(); // [cm] + + f_step_X = fParams.ParamAsDouble(esbroot::geometry::superfgd::DP::length_X) * flunit; + f_step_Y = fParams.ParamAsDouble(esbroot::geometry::superfgd::DP::length_Y) * flunit; + f_step_Z = fParams.ParamAsDouble(esbroot::geometry::superfgd::DP::length_Z) * flunit; + + f_bin_X = fParams.ParamAsInt(esbroot::geometry::superfgd::DP::number_cubes_X); + f_bin_Y = fParams.ParamAsInt(esbroot::geometry::superfgd::DP::number_cubes_Y); + f_bin_Z = fParams.ParamAsInt(esbroot::geometry::superfgd::DP::number_cubes_Z); + + f_total_X = f_step_X * f_bin_X; + f_total_Y = f_step_Y * f_bin_Y; + f_total_Z = f_step_Z * f_bin_Z; + + // Get RootManager + FairRootManager* manager = FairRootManager::Instance(); + if ( !manager ) { + LOG(fatal) << "-E- FgdGenFitRecon::Init: " << "FairRootManager not instantised!"; + return kFATAL; + } + + fHitArray = (TClonesArray*) manager->GetObject(geometry::superfgd::DP::FGD_HIT.c_str()); + if (!fHitArray) + { + LOG(fatal) << "Exec", "No fgd hits array"; + return kFATAL; + } + + OutputFileInit(manager); + + if(isGenFitVisualization) + { + fdisplay = genfit::EventDisplay::getInstance(); + } + + if(fdisplay!=nullptr && !fGenFitVisOption.empty()) + { + fdisplay->setOptions(fGenFitVisOption); + } + + + return kSUCCESS; +} + +void FgdMCGenFitRecon::OutputFileInit(FairRootManager* manager) +{ + // Create and register output array + fTracksArray = new TClonesArray(genfit::Track::Class(), 1000); + manager->Register(geometry::superfgd::DP::FGD_FIT_TRACK.c_str() + , geometry::superfgd::DP::FGD_BRANCH_FIT.c_str() + , fTracksArray, kTRUE); +} + + +// ------------------------------------------------------------------------- + + + +// ----- Public methods -------------------------------------------- +void FgdMCGenFitRecon::FinishEvent() +{ + if(isGenFitVisualization && !fgenTracks.empty()) + { + fdisplay->addEvent(fgenTracks); + fgenTracks.clear(); + } + fTracksArray->Delete(); +} + +void FgdMCGenFitRecon::FinishTask() +{ + if(isGenFitVisualization) + { + fdisplay->open(); + } +} + +void FgdMCGenFitRecon::Exec(Option_t* opt) +{ + try + { + std::vector allhits; + std::vector> foundTracks; + + bool rc = GetHits(allhits); + + if(rc) + { + LOG(debug) <<" Hits to retrieve tracks from " << allhits.size(); + SplitTrack(allhits, foundTracks); + } + + if(rc) + { + LOG(debug) <<" Found tracks to fit " << foundTracks.size(); + FitTracks(foundTracks); + } + else + { + LOG(error) << " Could not find clean hits or tracks! "; + } + } + catch(genfit::Exception& e) + { + LOG(fatal) << "Exception, when tryng to fit track"; + LOG(fatal) << e.what(); + } +} +// ------------------------------------------------------------------------- + + +// ----- Protected methods -------------------------------------------- + +Bool_t FgdMCGenFitRecon::GetHits(std::vector& allHits) +{ + Double_t errPhotoLimit = fParams.ParamAsDouble(esbroot::geometry::superfgd::DP::FGD_ERR_PHOTO_LIMIT); + + LOG(debug) << "fHitArray->GetEntries() " << fHitArray->GetEntries(); + + std::map visited; + + Int_t numVis(0); + + for(Int_t i =0; i < fHitArray->GetEntries() ; i++) + { + data::superfgd::FgdHit* hit = (data::superfgd::FgdHit*)fHitArray->At(i); + TVector3 photoE = hit->GetPhotoE(); + TVector3 mppcLoc = hit->GetMppcLoc(); + + Int_t&& x = mppcLoc.X(); + Int_t&& y = mppcLoc.Y(); + Int_t&& z = mppcLoc.Z(); + + // LOG(debug2) << "TrackId " << hit->GetTrackId(); + // LOG(debug2) << "GetPgd " << hit->GetPgd(); + // LOG(debug2) << "GetTrackLengthOrigin " << hit->GetTrackLengthOrigin(); + // LOG(debug2) << "GetTrackLenght " << hit->GetTrackLenght(); + // LOG(debug2) << "Photons " <<"(errLimit = " << errPhotoLimit << ") " << photoE.X() << " " << photoE.Y()<< " " << photoE.Z(); + // LOG(debug2) << "Pos " << x << " " << y << " " << z; + + // Int_t ind = ArrInd(x,y,z); + // LOG(debug2) << "ArrInd " << ind; + // if(visited[ind]) + // { + // // TODO: fix, causes "free(): invalid next size (fast)"" + // // If already exists, add the photons + // // ReconHit toFind; + // // toFind.fmppcLoc = mppcLoc; + // // std::vector::iterator recHit = find(allHits.begin(), allHits.end(), toFind); + // // ReconHit& foundHit = *recHit; + // // foundHit.fphotons = foundHit.fphotons + photoE; + // LOG(debug) << "isvisited "; + // continue; + // } + // visited[ind] = true; + + Double_t totalPhotons = photoE.X() + photoE.Y() + photoE.Z(); + if(totalPhotons >= errPhotoLimit) + { + TVectorD hitPos(3); + hitPos(0) = -f_total_X/2 + f_step_X*mppcLoc.X() +f_step_X/2; + hitPos(1) = -f_total_Y/2 + f_step_Y*mppcLoc.Y() +f_step_Y/2; + hitPos(2) = -f_total_Z/2 + f_step_Z*mppcLoc.Z() +f_step_Z/2; + + allHits.emplace_back(ReconHit( + mppcLoc + , TVector3(hitPos(0),hitPos(1),hitPos(2)) + , photoE + , hit->GetTime() + , hit->GetMomentum() + , hit->GetExitMomentum() + , hit->GetTrackLenght() + , hit->GetTrackLengthOrigin() + , hit->GetPgd() + , hit->GetTrackId() + , hit->GetEdep() + , hit->GetPhotoDist1() + , hit->GetMppcDist1() + , hit->GetPhotoDist2() + , hit->GetMppcDist2() + )); + } + } + + LOG(debug) << "allHits.size() " << allHits.size(); + + return (allHits.size() > 0); +} + + +void FgdMCGenFitRecon::SplitTrack(std::vector& allHits, std::vector>& foundTracks) +{ + std::map> tracks; + for(size_t i = 0; i < allHits.size(); ++i) + { + ReconHit& rh = allHits[i]; + + if(tracks.find(rh.ftrackId)!=tracks.end()) + { + tracks[rh.ftrackId].push_back(rh); + } + else + { + tracks[rh.ftrackId] = std::vector {rh}; + LOG(debug2) << rh.ftrackId << " " << rh.fpdg << "[pdg]"; + } + } + + for(auto iter = tracks.begin(); iter!=tracks.end(); ++iter) + { + LOG(debug2) << iter->first << " track size " << (iter->second).size(); + foundTracks.emplace_back(iter->second); + } + + LOG(info) << "Found tracks " << foundTracks.size(); +} + + +void FgdMCGenFitRecon::FitTracks(std::vector>& foundTracks) +{ + // init geometry and mag. field + TVector3 magField = fgdConstructor.GetMagneticField(); // values are in kGauss + genfit::FieldManager::getInstance()->init(new genfit::ConstField(magField.X(),magField.Y(), magField.Z())); + genfit::MaterialEffects::getInstance()->init(new genfit::TGeoMaterialInterface()); + genfit::MaterialEffects::getInstance()->setDebugLvl(fDebuglvl_genfit); + + // init fitter + std::shared_ptr fitter = make_shared(); + fitter->setMinIterations(fminGenFitInterations); + fitter->setMaxIterations(fmaxGenFitIterations); + fitter->setDebugLvl(fDebuglvl_genfit); + + int detId(1); // Detector id, it is the same, we only have one detector + + for(size_t i = 0; i < foundTracks.size() ; ++i) + { + std::vector& hitsOnTrack = foundTracks[i]; + // Sort by time, the 1st hit in time is the start of the track + std::sort(hitsOnTrack.begin(), hitsOnTrack.end(), [](ReconHit& bh1, ReconHit& bh2){return bh1.ftime& hitsOnTrack = foundTracks[i]; + + // Set lower limit on track size + if(hitsOnTrack.size() measurements{measurement}; + + toFitTrack->insertPoint(new genfit::TrackPoint(measurements, toFitTrack)); + } + + try + { + //check + toFitTrack->checkConsistency(); + + // do the fit + fitter->processTrack(toFitTrack, true); + + //check + toFitTrack->checkConsistency(); + + PrintFitTrack(*toFitTrack); + genfit::FitStatus* fiStatuStatus = toFitTrack->getFitStatus(); + + WriteOutput( pdg + , (*toFitTrack).getFittedState().getMom() + , momM + , *toFitTrack + , fiStatuStatus); + + if(fiStatuStatus->isFitted()) + { + fgenTracks.push_back(toFitTrack); + } + LOG(debug) <<"******************************************* "; + } + catch(genfit::Exception& e) + { + LOG(error) <<"Exception, when tryng to fit track"; + LOG(error) << e.what(); + LOG(error) << e.getExcString(); + } + } +} + +void FgdMCGenFitRecon::DefineMaterials() +{ + if(isDefinedMaterials) return; // Define materials only once + + isDefinedMaterials = true; + + new FairGeoLoader("TGeo","Geo Loader"); + FairGeoLoader *geoLoad = FairGeoLoader::Instance(); + if(geoLoad==nullptr) + { + LOG(error)<< "geoLoad is null"; + std::cout << "geoLoad is null" << endl; + throw; + } + + FairGeoInterface *geoFace = geoLoad->getGeoInterface(); + + geoFace->setMediaFile(fmediaFile.c_str()); + geoFace->readMedia(); + + FairGeoMedia *geoMedia = geoFace->getMedia(); + FairGeoBuilder* geoBuild = geoLoad->getGeoBuilder(); + + // FairGeoMedium* brass = geoMedia->getMedium(esbroot::geometry::superfgd::materials::brass); + // geoBuild->createMedium(brass); + + // FairGeoMedium* bronze = geoMedia->getMedium(esbroot::geometry::superfgd::materials::bronze); + // geoBuild->createMedium(bronze); + + // FairGeoMedium* stainlessSteel = geoMedia->getMedium(esbroot::geometry::superfgd::materials::stainlessSteel); + // geoBuild->createMedium(stainlessSteel); + + // FairGeoMedium* methane = geoMedia->getMedium(esbroot::geometry::superfgd::materials::methane); + // geoBuild->createMedium(methane); + + // FairGeoMedium* carbonDioxide = geoMedia->getMedium(esbroot::geometry::superfgd::materials::carbonDioxide); + // geoBuild->createMedium(carbonDioxide); + + // FairGeoMedium* carbontetraFloride = geoMedia->getMedium(esbroot::geometry::superfgd::materials::carbontetraFloride); + // geoBuild->createMedium(carbontetraFloride); + + // FairGeoMedium* titaniumDioxide = geoMedia->getMedium(esbroot::geometry::superfgd::materials::titaniumDioxide); + // geoBuild->createMedium(titaniumDioxide); + + // FairGeoMedium* polystyrene = geoMedia->getMedium(esbroot::geometry::superfgd::materials::polystyrene); + // geoBuild->createMedium(polystyrene); + + FairGeoMedium* scintillator = geoMedia->getMedium(esbroot::geometry::superfgd::materials::scintillator); + scintillator->setMediumIndex(esbroot::geometry::superfgd::materials::GetNextIndex()); + geoBuild->createMedium(scintillator); + scintillator->Print(); + + FairGeoMedium* paraterphnyl = geoMedia->getMedium(esbroot::geometry::superfgd::materials::paraterphnyl); + geoBuild->createMedium(paraterphnyl); + + // FairGeoMedium* podscintillator = geoMedia->getMedium(esbroot::geometry::superfgd::materials::podscintillator); + // geoBuild->createMedium(podscintillator); + + // FairGeoMedium* polyethylene = geoMedia->getMedium(esbroot::geometry::superfgd::materials::polyethylene); + // geoBuild->createMedium(polyethylene); + + // FairGeoMedium* poduleEpoxy = geoMedia->getMedium(esbroot::geometry::superfgd::materials::poduleEpoxy); + // geoBuild->createMedium(poduleEpoxy); + + // FairGeoMedium* polycarbonate = geoMedia->getMedium(esbroot::geometry::superfgd::materials::polycarbonate); + // geoBuild->createMedium(polycarbonate); + + // FairGeoMedium* carbonFiber = geoMedia->getMedium(esbroot::geometry::superfgd::materials::carbonFiber); + // geoBuild->createMedium(carbonFiber); + + FairGeoMedium* fiberCore = geoMedia->getMedium(esbroot::geometry::superfgd::materials::fiberCore); + geoBuild->createMedium(fiberCore); + + FairGeoMedium* fiberCladding = geoMedia->getMedium(esbroot::geometry::superfgd::materials::fiberCladding); + geoBuild->createMedium(fiberCladding); + + FairGeoMedium* fairTiO2 = geoMedia->getMedium(esbroot::geometry::superfgd::materials::titaniumDioxide); + geoBuild->createMedium(fairTiO2); + + FairGeoMedium* fairPolystyrene = geoMedia->getMedium(esbroot::geometry::superfgd::materials::polystyrene); + geoBuild->createMedium(fairPolystyrene); + + FairGeoMedium* fairAir = geoMedia->getMedium(esbroot::geometry::superfgd::materials::air); + geoBuild->createMedium(fairAir); + + FairGeoMedium* vacuum = geoMedia->getMedium(esbroot::geometry::superfgd::materials::vacuum); + geoBuild->createMedium(vacuum); +} + +void FgdMCGenFitRecon::PrintFitTrack(genfit::Track& fitTrack) +{ + const genfit::MeasuredStateOnPlane& me = fitTrack.getFittedState(); + LOG(debug)<< "\tFitted Momentum [" << (me.getMom()).Mag() <<"]" << "(" << (me.getMom()).X() << "," << (me.getMom()).Y() << "," << (me.getMom()).Z() << ")"; + //LOG(debug)<< " X " << (me.getMom()).X()<< " Y " << (me.getMom()).Y()<< " Z " << (me.getMom()).Z(); + + genfit::FitStatus* fiStatuStatus = fitTrack.getFitStatus(); + fiStatuStatus->Print(); + + LOG(debug)<< "fiStatuStatus->isFitted() " << fiStatuStatus->isFitted(); + LOG(debug)<< "fiStatuStatus->isFitConverged() " << fiStatuStatus->isFitConverged(); + LOG(debug)<< "fiStatuStatus->isFitConvergedFully() " << fiStatuStatus->isFitConvergedFully(); + LOG(debug)<< "fiStatuStatus->isFitConvergedPartially() " << fiStatuStatus->isFitConvergedPartially(); + LOG(debug)<< "fitTrack.getNumPoints() " << fitTrack.getNumPoints(); +} + +void FgdMCGenFitRecon::WriteOutput( Int_t pdg + , const TVector3& fitMom + , const TVector3& mcMom + , const genfit::Track& fitTrack + , genfit::FitStatus*& fiStatuStatus) +{ + // TODO nothing to do in base class +} + +Bool_t FgdMCGenFitRecon::isParticleNeutral(Int_t pdg) +{ + Bool_t isNeutral = (pdg == genie::kPdgNeutron) || + (pdg == genie::kPdgPi0) || + (pdg == genie::kPdgGamma) || + genie::pdg::IsNeutralLepton(pdg); + + return isNeutral; +} + +Long_t FgdMCGenFitRecon::ArrInd(int x, int y, int z) +{ + return (x*f_bin_Y*f_bin_Z + y*f_bin_Z+z); +} + +// ------------------------------------------------------------------------- + +}// namespace superfgd +}// namespace reconstruction +}// namespace esbroot diff --git a/EsbReconstruction/EsbSuperFGD/FgdMCGenFitRecon.h b/EsbReconstruction/EsbSuperFGD/FgdMCGenFitRecon.h new file mode 100644 index 0000000..1985d25 --- /dev/null +++ b/EsbReconstruction/EsbSuperFGD/FgdMCGenFitRecon.h @@ -0,0 +1,155 @@ +#ifndef ESBROOT_ESBDRECONSTRUCTION_FGD_MC_GENFIT_H +#define ESBROOT_ESBDRECONSTRUCTION_FGD_MC_GENFIT_H + +// EsbRoot headers +#include "EsbData/EsbSuperFGD/FgdHit.h" +#include "EsbGeometry/EsbSuperFGD/EsbFgdDetectorParameters.h" +#include "EsbGeometry/EsbSuperFGD/EsbSuperFGDDetectorConstruction.h" +#include "EsbReconstruction/EsbSuperFGD/FgdReconHit.h" +#include "EsbReconstruction/EsbSuperFGD/PdgFromMomentumLoss.h" + +// FairRoot headers +#include + +// ROOT headers +#include + +// Pathfinder headers +#include "basicHit.h" +#include "TrackFinderTrack.h" + +namespace esbroot { +namespace reconstruction { +namespace superfgd { + +class FgdMCGenFitRecon : public FairTask +{ + + public: + + /** Default constructor **/ + FgdMCGenFitRecon(); + + /** Constructor with argument + *@param name Name of task + *@param geoConfigFile - Configuration file detector + *@param mediaFile - Configuration file for the used mediums + *@param verbose - Verbosity level + *@param debugLlv - debug level for genfit + *@param visualize - to visualize the event using genfit::EventDisplay + *@param visOption - option to be passed to genfit::EventDisplay + **/ + FgdMCGenFitRecon(const char* name + , const char* geoConfigFile + , const char* mediaFile + , Int_t verbose = 1 + , double debugLlv = 0 + , bool visualize = false + , std::string visOption ="D"); + + /** Destructor **/ + virtual ~FgdMCGenFitRecon(); + + void SetMinInterations(Int_t minIterations) {fminGenFitInterations = minIterations;} + void SetMaxInterations(Int_t maxIterations) {fmaxGenFitIterations = maxIterations;} + void SetMinHits(Int_t minHits) {fminHits = minHits;} + + /** Virtual method Init **/ + virtual InitStatus Init() override; + virtual void OutputFileInit(FairRootManager* manager); // Create virtual method for output file creation + virtual void FinishEvent() override; + virtual void FinishTask() override; + + + /** Virtual method Exec **/ + virtual void Exec(Option_t* opt) override; + + /** For decendents who want to write some data to output file */ + virtual void WriteOutput( Int_t pdg + , const TVector3& fitMom + , const TVector3& mcMom + , const genfit::Track& fitTrack + , genfit::FitStatus*& fiStatuStatus); + +protected: + + /** Get all hits **/ + Bool_t GetHits(std::vector& allHits); + + void SplitTrack(std::vector& allHits, std::vector>& splitTracks); + + /** Fit the found tracks using genfit **/ + void FitTracks(std::vector>& foundTracks); + + /** Define materials used in the reconstruction phase **/ + void DefineMaterials(); + + /** Print information for fitted grack **/ + void PrintFitTrack(genfit::Track& track); + + Long_t ArrInd(int i, int j, int k); + + Bool_t isParticleNeutral(Int_t pdg); + + /** Class to hold the Detector parameters read from external file **/ + esbroot::geometry::superfgd::FgdDetectorParameters fParams;//! fgenTracks;//! +#include "FairVolume.h" + + +// Root headers +#include +#include +#include +#include +#include +#include +#include +#include + +// Genie headers +#include "Framework/ParticleData/PDGCodes.h" +#include "Framework/ParticleData/PDGUtils.h" + +// Genfit headers +#include "AbsBField.h" +#include "AbsMeasurement.h" +#include "ConstField.h" +#include +#include +#include +#include "FitStatus.h" +#include +#include "MaterialEffects.h" +#include "MeasuredStateOnPlane.h" +#include +#include +#include "SpacepointMeasurement.h" +#include +#include "TDatabasePDG.h" +#include +#include +#include +#include +#include +#include + + + +// STL headers +#include +#include +#include +#include +#include +#include +#include + +namespace esbroot { +namespace reconstruction { +namespace superfgd { + +// ----- Default constructor ------------------------------------------- +FgdMCLeptonStats::FgdMCLeptonStats() : FgdMCGenFitRecon(), feventNum(0) +{ +} +// ------------------------------------------------------------------------- + +// ----- Constructor ------------------------------------------- +FgdMCLeptonStats::FgdMCLeptonStats(const char* name + , const char* geoConfigFile + , const char* mediaFile + , const char* eventData + , const char* outputRootFile + , Int_t verbose + , double debugLlv) : + FgdMCGenFitRecon(name, geoConfigFile, mediaFile, verbose, + debugLlv, false /* no visualization */, "D") + , feventData(eventData), foutputRootFile(outputRootFile) + , feventNum(0) +{ + fpdgDB = make_shared(); +} +// ------------------------------------------------------------------------- + + + +// ----- Destructor ---------------------------------------------------- +FgdMCLeptonStats::~FgdMCLeptonStats() +{ + if(fTracksArray) + { + fTracksArray->Delete(); + delete fTracksArray; + } +} +// ------------------------------------------------------------------------- + + + +// ----- Public method Init -------------------------------------------- +InitStatus FgdMCLeptonStats::Init() +{ + FgdMCGenFitRecon::Init(); + + std::ifstream eventFileStream; + try + { + eventFileStream.open(feventData.c_str(), std::ios::in); + + if(eventFileStream.is_open()) + { + std::string line; + while(std::getline(eventFileStream,line)) + { + feventRecords.emplace_back(FgdMCEventRecord(line)); + } + } + } + catch(const std::exception& e) + { + LOG(fatal) << e.what(); + } + + if(eventFileStream.is_open()) + { + eventFileStream.close(); + } + + // for(size_t i =0 ; i < feventRecords.size(); i++) + // { + // LOG(info) << " =========== event " << i << " =========== "; + // LOG(info) << feventRecords[i].GetNuPdg() + // << " " << feventRecords[i].GetNuE() + // << " " << feventRecords[i].IsWeakCC() + // << " " << feventRecords[i].IsWeakNC() + // << " " << feventRecords[i].IsQuasiElastic(); + + // auto par = feventRecords[i].GetPrimaryParticles(); + // for(size_t j = 0; j < par.size(); ++j) + // { + // LOG(info) << par[j].first << " " << par[j].second.X() << " " << par[j].second.Y()<< " " << par[j].second.Z(); + // } + // LOG(info) << " ====================== "; + // } + + + return kSUCCESS; +} + +void FgdMCLeptonStats::OutputFileInit(FairRootManager* manager) +{ + FgdMCGenFitRecon::OutputFileInit(manager); + // Create and register output array + // fEventsArray = new TClonesArray(esbroot::reconstruction::superfgd::FgdMCEventRecord::Class(), 1000); + // manager->Register(esbroot::geometry::superfgd::DP::FGD_MC_LEPTON_RECONSTRUCTION_ROOT_FILE.c_str() + // , esbroot::geometry::superfgd::DP::FGD_MC_LEPTON_RECONSTRUCTION_BRANCH.c_str() + // , fEventsArray, kTRUE); +} + +// ------------------------------------------------------------------------- + + + +// ----- Public methods -------------------------------------------- + +void FgdMCLeptonStats::Exec(Option_t* opt) +{ + try + { + std::vector allhits; + std::vector> foundTracks; + + bool rc = GetHits(allhits); + + if(rc) + { + LOG(debug) <<" Hits to retrieve stats from " << allhits.size(); + SplitTrack(allhits, foundTracks); + } + + if(rc) + { + LOG(debug) <<" Found tracks to process " << foundTracks.size(); + ProcessStats(foundTracks); + } + else + { + LOG(error) << " Could not find clean hits or tracks! "; + ++feventNum; + } + } + catch(genfit::Exception& e) + { + LOG(fatal) << "Exception, when tryng to fit track"; + LOG(fatal) << e.what(); + } +} + +Bool_t FgdMCLeptonStats::ProcessStats(std::vector>& foundTracks) +{ + if(feventNum >= feventRecords.size()) + { + LOG(fatal) << "EventData reconrds are less than the passed events!"; + throw "EventData reconrds are less than the passed events!"; + } + + FgdMCEventRecord& mcEventRecord = feventRecords[feventNum]; + mcEventRecord.ReadEventData(); + + + for(size_t i = 0; i < foundTracks.size() ; ++i) + { + std::vector& hitsOnTrack = foundTracks[i]; + // Sort by time, the 1st hit in time is the start of the track + std::sort(hitsOnTrack.begin(), hitsOnTrack.end(), [](ReconHit& bh1, ReconHit& bh2){return bh1.ftime& hitsOnTrack = foundTracks[i]; + if(hitsOnTrack.empty()) continue; + if(hitsOnTrack[0].fpdg == genie::kPdgMuon || hitsOnTrack[0].fpdg == genie::kPdgAntiMuon) + { + Double_t sumTrackLenght = 0; + for(size_t j = 0; j < hitsOnTrack.size(); ++j) + { + ReconHit& hit = hitsOnTrack[j]; + sumTrackLenght += hit.ftrackLength; + } + mcEventRecord.SetMuonTrackLength(sumTrackLenght); + Double_t trOrg = hitsOnTrack[hitsOnTrack.size()-1].ftrackLengthOrigin; + mcEventRecord.SetMuonTrackLengthOrigin(trOrg); + break; + } + } + } + + // 2. Determine if the muon is exiting the detector + if(mcEventRecord.IsPrimaryLeptonMuon()) + { + for(size_t i = 0; i < foundTracks.size() ; ++i) + { + std::vector& hitsOnTrack = foundTracks[i]; + if(hitsOnTrack.empty()) continue; + if(hitsOnTrack[0].fpdg == genie::kPdgMuon || hitsOnTrack[0].fpdg == genie::kPdgAntiMuon) + { + ReconHit& lastHit = hitsOnTrack[hitsOnTrack.size() -1 ]; + // LOG(info) << "Muon is exiting " << lastHit.fmppcLoc.Z() << " f_bin_Z " << f_bin_Z << " lastHit.fmomExit.Mag() " << lastHit.fmomExit.Mag(); + if(IsHitExiting(lastHit) && lastHit.fmomExit.Mag()!=0) + { + LOG(debug2) << "Muon is exiting"; + mcEventRecord.SetMuonExiting(true); + mcEventRecord.SetMuonExitMom(lastHit.fmomExit); + } + break; + } + } + } + + + // 3. Sum the total energy deposited by hadrons if is a muon event + if(mcEventRecord.IsPrimaryLeptonMuon()) + { + Double_t totalEdepInChargedHadrons = 0; + for(size_t i = 0; i < foundTracks.size() ; ++i) + { + std::vector& hitsOnTrack = foundTracks[i]; + if(hitsOnTrack.empty()) continue; + + Bool_t isChargedHadronInTrack = IsChargedHadron(hitsOnTrack[0]); + if(!isChargedHadronInTrack) continue; + + for(size_t j = 0; j < hitsOnTrack.size(); ++j) + { + ReconHit& hit = hitsOnTrack[j]; + totalEdepInChargedHadrons += hit.fEdep; + } + } + mcEventRecord.SetHadronEdep(totalEdepInChargedHadrons); + } + + //4. Is it is an electron, count the total charge particles exiting the detector + if(mcEventRecord.IsPrimaryLeptonElectron()) + { + Int_t numOfExitingChargedParticles = 0; + std::vector pdgCodes; + for(size_t i = 0; i < foundTracks.size() ; ++i) + { + std::vector& hitsOnTrack = foundTracks[i]; + if(hitsOnTrack.empty()) continue; + + Bool_t isChargedParticleInTrack = IsChargedParticle(hitsOnTrack[0]); + if(!isChargedParticleInTrack) continue; + + Bool_t isParExiting = IsHitExiting(hitsOnTrack[hitsOnTrack.size() - 1]); + if(isParExiting) + { + ++numOfExitingChargedParticles; + pdgCodes.push_back(hitsOnTrack[0].fpdg); + } + } + mcEventRecord.SetNumOfExitingPar(numOfExitingChargedParticles); + mcEventRecord.SetPdgOfExitingPars(pdgCodes); + } + + // 5. Fit the muon momentum + if(mcEventRecord.IsPrimaryLeptonMuon()) + { + for(size_t i = 0; i < foundTracks.size() ; ++i) + { + std::vector& hitsOnTrack = foundTracks[i]; + if(hitsOnTrack.empty()) continue; + if(hitsOnTrack[0].fpdg == genie::kPdgMuon || hitsOnTrack[0].fpdg == genie::kPdgAntiMuon) + { + TVector3 fitMom; + if(FitTrack(hitsOnTrack, fitMom)) + { + mcEventRecord.SetGenfitMom(fitMom); + + TVector3 mcMom = mcEventRecord.GetMuonMom(); + Double_t err = mcMom.Mag() - fitMom.Mag(); + mcEventRecord.SetMomError(err); + } + break; + } + } + } + + // 6. Calculate proton energy loss from the generated photons + if(mcEventRecord.IsPrimaryLeptonMuon() || mcEventRecord.IsPrimaryLeptonElectron()) + { + for(size_t i = 0; i < foundTracks.size() ; ++i) + { + std::vector& hitsOnTrack = foundTracks[i]; + if(hitsOnTrack.empty()) continue; + + Int_t& pdgPar = hitsOnTrack[0].fpdg; + if(genie::pdg::IsProton(pdgPar)) + { + Double_t sumEdep = 0; + for(size_t j = 0; j < hitsOnTrack.size(); ++j) + { + ReconHit& hit = hitsOnTrack[j]; + sumEdep += CalculatePhotoEdep(hit); + } + mcEventRecord.SetProtonEdep(sumEdep); + break; + } + } + } + + feventRecords[feventNum].SetHasHits(true); + ++feventNum; // Increment to next event from eventData read from simulation`s genie export +} + +Bool_t FgdMCLeptonStats::IsHitExiting(ReconHit& hit) +{ + Int_t lastMppc = f_bin_Z - 1; + return (hit.fmppcLoc.Z() == lastMppc); +} + +Bool_t FgdMCLeptonStats::IsChargedHadron(ReconHit& hit) +{ + bool rc(false); + + if(genie::pdg::IsHadron(hit.fpdg)) + { + TParticlePDG* tPdg = fpdgDB->GetParticle(hit.fpdg); + rc = (tPdg!=nullptr) && (tPdg->Charge()!=0); + } + + return rc; +} + +Bool_t FgdMCLeptonStats::IsChargedParticle(ReconHit& hit) +{ + bool rc(false); + + TParticlePDG* tPdg = fpdgDB->GetParticle(hit.fpdg); + rc = (tPdg!=nullptr) && (tPdg->Charge()!=0); + + return rc; +} + +Double_t FgdMCLeptonStats::CalculatePhotoEdep(ReconHit& hit) +{ + using namespace esbroot::digitizer::superfgd; + + TVector3& pe_1_dir = hit.fph1; + TVector3& dist_1 = hit.fmppc1; + TVector3& pe_2_dir = hit.fph2; + TVector3& dist_2 = hit.fmppc2; + + double& time = hit.ftime; + double charge = 1.0; // not used, but is a parameter from legacy + + + double pe_1_x = FgdDigitizer::RevertyMPPCResponse(pe_1_dir.X()); + double pe_1_y = FgdDigitizer::RevertyMPPCResponse(pe_1_dir.Y()); + double pe_1_Z = FgdDigitizer::RevertyMPPCResponse(pe_1_dir.Z()); + + double pe_2_x = FgdDigitizer::RevertyMPPCResponse(pe_2_dir.X()); + double pe_2_y = FgdDigitizer::RevertyMPPCResponse(pe_2_dir.Y()); + double pe_2_z = FgdDigitizer::RevertyMPPCResponse(pe_2_dir.Z()); + + FgdDigitizer::RevertFiberResponse(pe_1_x, time, dist_1.X()); + FgdDigitizer::RevertFiberResponse(pe_1_y, time, dist_1.Y()); + FgdDigitizer::RevertFiberResponse(pe_1_Z, time, dist_1.Z()); + + FgdDigitizer::RevertFiberResponse(pe_2_x, time, dist_2.X()); + FgdDigitizer::RevertFiberResponse(pe_2_y, time, dist_2.Y()); + FgdDigitizer::RevertFiberResponse(pe_2_z, time, dist_2.Z()); + + // Deposited energy hit.fEdep and tracklength hit.ftrackLength + // are used to calculate the CBIRKS coefficients together with dedx (energy losses) + // to be able to revert from the photons + + Double_t x_1 = FgdDigitizer::RevertScintiResponse(hit.fEdep, hit.ftrackLength, charge, pe_1_x); + Double_t y_1 = FgdDigitizer::RevertScintiResponse(hit.fEdep, hit.ftrackLength, charge, pe_1_y); + Double_t z_1 = FgdDigitizer::RevertScintiResponse(hit.fEdep, hit.ftrackLength, charge, pe_1_Z); + + Double_t x_2 = FgdDigitizer::RevertScintiResponse(hit.fEdep, hit.ftrackLength, charge, pe_2_x); + Double_t y_2 = FgdDigitizer::RevertScintiResponse(hit.fEdep, hit.ftrackLength, charge, pe_2_y); + Double_t z_2 = FgdDigitizer::RevertScintiResponse(hit.fEdep, hit.ftrackLength, charge, pe_2_z); + + Double_t x = x_1 + x_2; + Double_t y = y_1 + y_2; + Double_t z = z_1 + z_2; + + Double_t totalEdep = x + y + z; + return totalEdep; +} + +Bool_t FgdMCLeptonStats::FitTrack(std::vector& hitsOnTrack, TVector3& fitMom) +{ + bool rc(true); + + // init geometry and mag. field + TVector3 magField = fgdConstructor.GetMagneticField(); // values are in kGauss + genfit::FieldManager::getInstance()->init(new genfit::ConstField(magField.X(),magField.Y(), magField.Z())); + genfit::MaterialEffects::getInstance()->init(new genfit::TGeoMaterialInterface()); + genfit::MaterialEffects::getInstance()->setDebugLvl(fDebuglvl_genfit); + + // init fitter + std::shared_ptr fitter = make_shared(); + fitter->setMinIterations(fminGenFitInterations); + fitter->setMaxIterations(fmaxGenFitIterations); + fitter->setDebugLvl(fDebuglvl_genfit); + + int detId(1); // Detector id, it is the same, we only have one detector + + const int pdg = hitsOnTrack[0].fpdg; + TVector3 posM(hitsOnTrack[0].fHitPos); + TVector3 momM(hitsOnTrack[0].fmom); + + if(isParticleNeutral(pdg)) + { + LOG(debug) << "Track is of neutral particle ["<< pdg << "] continue with next track."; + return false; + } + + // approximate covariance + double resolution = 0.1; + TMatrixDSym hitCov(3); + hitCov(0,0) = resolution*resolution; + hitCov(1,1) = resolution*resolution; + hitCov(2,2) = resolution*resolution; + + TMatrixDSym covM(6); + for (int ci = 0; ci < 3; ++ci) + covM(ci,ci) = resolution*resolution; + for (int ci = 3; ci < 6; ++ci) + covM(ci,ci) = covM(ci,ci) = pow( ((resolution / hitsOnTrack.size()) / sqrt(3)), 2); + + // trackrep + genfit::AbsTrackRep* rep = new genfit::RKTrackRep(pdg); + + // smeared start state + genfit::MeasuredStateOnPlane stateSmeared(rep); + stateSmeared.setPosMomCov(posM, momM, covM); + + // create track + TVectorD seedState(6); + TMatrixDSym seedCov(6); + stateSmeared.get6DStateCov(seedState, seedCov); + + genfit::Track* toFitTrack = new genfit::Track(rep, seedState, seedCov); + + LOG(debug) << "******************************************* "; + LOG(debug) << " \tPdg code " << pdg; + LOG(debug) << " \tHits in track "<< hitsOnTrack.size(); + LOG(debug) << " \tTrack Momentum [" << momM.Mag() << "]" << "(" << momM.X() << "," << momM.Y() << "," << momM.Z() << ")"; + + for(Int_t bh = 0; bh < hitsOnTrack.size(); ++bh) + { + TVectorD hitPos(3); + hitPos(0) = hitsOnTrack[bh].fHitPos.X(); + hitPos(1) = hitsOnTrack[bh].fHitPos.Y(); + hitPos(2) = hitsOnTrack[bh].fHitPos.Z(); + + genfit::AbsMeasurement* measurement = new genfit::SpacepointMeasurement(hitPos, hitCov, detId, 0, nullptr); + std::vector measurements{measurement}; + + toFitTrack->insertPoint(new genfit::TrackPoint(measurements, toFitTrack)); + } + + try + { + //check + toFitTrack->checkConsistency(); + + // do the fit + fitter->processTrack(toFitTrack, true); + + //check + toFitTrack->checkConsistency(); + + PrintFitTrack(*toFitTrack); + genfit::FitStatus* fiStatuStatus = toFitTrack->getFitStatus(); + + // WriteOutput( pdg + // , (*toFitTrack).getFittedState().getMom() + // , momM + // , *toFitTrack + // , fiStatuStatus); + + fitMom = (*toFitTrack).getFittedState().getMom(); + + LOG(debug) <<"******************************************* "; + } + catch(genfit::Exception& e) + { + LOG(error) <<"Exception, when tryng to fit track"; + LOG(error) << e.what(); + LOG(error) << e.getExcString(); + rc = false; + } + + return rc; +} + +void FgdMCLeptonStats::FinishTask() +{ + TFile * outFile = new TFile(foutputRootFile.c_str(), "RECREATE", "Reconstruction data from Fgd Detector"); + outFile->SetCompressionLevel(9); + + FgdMCEventRecord* data = nullptr; + TTree * outTree = new TTree(esbroot::geometry::superfgd::DP::FGD_MC_LEPTON_RECONSTRUCTION_TTREE.c_str() + ,esbroot::geometry::superfgd::DP::FGD_MC_LEPTON_RECONSTRUCTION_ROOT_FILE.c_str()); + outTree->Branch(esbroot::geometry::superfgd::DP::FGD_MC_LEPTON_RECONSTRUCTION_BRANCH.c_str(), &data); + + + // TClonesArray& clref = *fEventsArray; + + for(size_t ind = 0 ; ind < feventRecords.size(); ind++) + { + // LOG(info) << "writing to output file " << ind; + // auto test = new(clref[clref.GetEntries()]) esbroot::reconstruction::superfgd::FgdMCEventRecord(feventRecords[ind]); + // LOG(info) << "Is null " << (test == nullptr); + + data = &feventRecords[ind]; + outTree->Fill(); + } + + outFile->WriteTObject(outTree); + outFile->Close(); + + delete outFile; + + FgdMCGenFitRecon::FinishTask(); + + + // int zeroLenghtMuionTracks = 0; + // double z_min = 100000.f; + // double z_max = -100000.f; + // for(size_t i =0; i< feventRecords.size();++i) + // { + // if(feventRecords[i].IsPrimaryLeptonMuon() && feventRecords[i].GetMuonTrackLengthOrigin() == 0) + // { + // ++zeroLenghtMuionTracks; + // } + // LOG(info) << feventRecords[i].IsPrimaryLeptonMuon(); + // LOG(info) << feventRecords[i].GetMuonTrackLength(); + // LOG(info) << feventRecords[i].GetMuonTrackLengthOrigin(); + // LOG(info) << feventRecords[i].IsMuonExiting(); + // LOG(info) << feventRecords[i].HasHits(); + // LOG(info) << "X " << feventRecords[i].GetVertex().X() << " Y " << feventRecords[i].GetVertex().Y() << " Z " << feventRecords[i].GetVertex().Z(); + // LOG(info) << " ==================== "; + + // if(z_min > feventRecords[i].GetVertex().Z()) z_min = feventRecords[i].GetVertex().Z(); + // if(z_max < feventRecords[i].GetVertex().Z()) z_max = feventRecords[i].GetVertex().Z(); + // } + // LOG(info) << "Zero length muons tracks " << zeroLenghtMuionTracks; +} +// ------------------------------------------------------------------------- + + +// ----- Protected methods -------------------------------------------- + +// ------------------------------------------------------------------------- + +}// namespace superfgd +}// namespace reconstruction +}// namespace esbroot diff --git a/EsbReconstruction/EsbSuperFGD/FgdMCLeptonStats.h b/EsbReconstruction/EsbSuperFGD/FgdMCLeptonStats.h new file mode 100644 index 0000000..1d15d06 --- /dev/null +++ b/EsbReconstruction/EsbSuperFGD/FgdMCLeptonStats.h @@ -0,0 +1,78 @@ +#ifndef ESBROOT_ESBDRECONSTRUCTION_FGD_MC_LEPTON_STATS_H +#define ESBROOT_ESBDRECONSTRUCTION_FGD_MC_LEPTON_STATS_H + +// EsbRoot headers +#include "EsbReconstruction/EsbSuperFGD/FgdMCGenFitRecon.h" +#include "EsbReconstruction/EsbSuperFGD/FgdMCEventRecord.h" + +namespace esbroot { +namespace reconstruction { +namespace superfgd { + +class FgdMCLeptonStats : public FgdMCGenFitRecon +{ + + public: + + /** Default constructor **/ + FgdMCLeptonStats(); + + /** Constructor with argument + *@param name Name of task + *@param geoConfigFile - Configuration file detector + *@param mediaFile - Configuration file for the used mediums + *@param eventData - events data file (generated from fgd generator) + *@param outputRootFile - full path to the output root file + *@param verbose - Verbosity level + *@param debugLlv - debug level for genfit + **/ + FgdMCLeptonStats(const char* name + , const char* geoConfigFile + , const char* mediaFile + , const char* eventData + , const char* outputRootFile + , Int_t verbose = 1 + , double debugLlv = 0); + + /** Destructor **/ + virtual ~FgdMCLeptonStats(); + + /** Virtual method Init **/ + virtual InitStatus Init() override; + virtual void OutputFileInit(FairRootManager* manager) override; + + /** Virtual method Exec **/ + virtual void Exec(Option_t* opt) override; + + virtual void FinishTask() override; + +protected: + + Bool_t ProcessStats(std::vector>& foundTracks); + + Bool_t IsHitExiting(ReconHit& hit); + Bool_t IsChargedHadron(ReconHit& hit); + Bool_t IsChargedParticle(ReconHit& hit); + Bool_t FitTrack(std::vector& hitsOnTrack, TVector3& fitMom); + Double_t CalculatePhotoEdep(ReconHit& hit); + + std::string feventData;//! feventRecords;//! fpdgDB;//! +#include + +// Fair headers +#include "FairLogger.h" + +// Genie headers +#include "Framework/ParticleData/PDGCodes.h" + +// STL headers +#include +#include +#include +#include +#include + +namespace esbroot { +namespace reconstruction { +namespace superfgd { + +// ----- Default constructor ------------------------------------------- +FgdMuonRecon::FgdMuonRecon() : FgdMCGenFitRecon() + , foutputFile("") + , fnuEFile("") + , fEventCount(0) + , fTfile(nullptr) + , fTtree(nullptr) + , fx(0.), fy(0.), fz(0.), fp(0.) + , fx_fit(0.), fy_fit(0.), fz_fit(0.), fp_fit(0.) + , fpMC_min_pFit(0.), fE_mu(0.), fxy(0.) + , fzMC_min_zFit(0.) + , fshouldCOnvergeToExport(false) + , fcosTheta(0) +{ +} +// ------------------------------------------------------------------------- + +// ----- Constructor ------------------------------------------- +FgdMuonRecon::FgdMuonRecon(const char* name + , const char* geoConfigFile + , const char* mediaFile + , const char* outputFile + , const char* nuEFile + , Int_t verbose + , double debugLlv + , bool visualize + , std::string visOption) + : FgdMCGenFitRecon(name, geoConfigFile, mediaFile, verbose, debugLlv, visualize, visOption) + , foutputFile(outputFile) + , fnuEFile(nuEFile) + , fEventCount(0) + , fTfile(nullptr) + , fTtree(nullptr) + , fx(0.), fy(0.), fz(0.), fp(0.) + , fx_fit(0.), fy_fit(0.), fz_fit(0.), fp_fit(0.) + , fpMC_min_pFit(0.), fE_mu(0.), fxy(0.) + , fzMC_min_zFit(0.) + , fshouldCOnvergeToExport(false) + , fcosTheta(0) +{ + +} +// ------------------------------------------------------------------------- + + + +// ----- Destructor ---------------------------------------------------- +FgdMuonRecon::~FgdMuonRecon() +{ + if(fTfile) + { + delete fTfile; + } + + if(fTtree) + { + delete fTtree; + } +} +// ------------------------------------------------------------------------- + + + +// ----- Public method Init -------------------------------------------- +InitStatus FgdMuonRecon::Init() +{ + FgdMCGenFitRecon::Init(); + + if(!foutputFile.empty()) + { + fTfile = new TFile(foutputFile.c_str(), "RECREATE", "Fgd Muon only fit momentums"); + fTtree = new TTree("momentums", "Fitted momentums"); + + // Set Monte carlo momentum + fTtree->Branch("x_MC_momentum", &fx); + fTtree->Branch("y_MC_momentum", &fy); + fTtree->Branch("z_MC_momentum", &fz); + fTtree->Branch("total_MC_momentum", &fp); + + // Set Genfit momentum + fTtree->Branch("x_Fit_momentum", &fx_fit); + fTtree->Branch("y_Fit_momentum", &fy_fit); + fTtree->Branch("z_Fit_momentum", &fz_fit); + fTtree->Branch("total_Fit_momentum", &fp_fit); + + fTtree->Branch("XY_MC_minus_XY_FIt", &fxy); + fTtree->Branch("Z_MC_minus_Z_FIt", &fzMC_min_zFit); + + // Set statistics + fTtree->Branch("P_monte_carlo_minus_P_genfit", &fpMC_min_pFit); + fTtree->Branch("E_fit_subtract_nu_momentum", &fE_mu); + + // Set cos (Thetha) + fTtree->Branch("cos_theta", &fcosTheta); + } + + ReadEnuFile(); + + return kSUCCESS; +} + + +// ------------------------------------------------------------------------- + + + + +// ----- Public methods -------------------------------------------- + +void FgdMuonRecon::FinishEvent() +{ + FgdMCGenFitRecon::FinishEvent(); + LOG(debug) << "Neutrino energy for event[" << fEnu[fEventCount]<<" GeV]"; + ++fEventCount; +} + +void FgdMuonRecon::FinishTask() +{ + FgdMCGenFitRecon::FinishTask(); + if(!foutputFile.empty()) + { + fTfile->WriteTObject(fTtree); + fTfile->Close(); + } +} +// ------------------------------------------------------------------------- + +void FgdMuonRecon::WriteOutput( Int_t pdg + , const TVector3& fitMom + , const TVector3& mcMom + , const genfit::Track& fitTrack + , genfit::FitStatus*& fiStatuStatus) +{ + Bool_t isMUon = (pdg==genie::kPdgMuon) || (pdg == genie::kPdgAntiMuon); + static Double_t radToDeg = 180./TMath::Pi(); + + if(fiStatuStatus->isFitConverged() && isMUon && fTtree!=nullptr && fEventCount< fEnu.size()) + { + // Set Monte Carlo momentum + fx = mcMom.X(); + fy = mcMom.Y(); + fz = mcMom.Z(); + fp = mcMom.Mag(); + + // Set Genfit momentum + fx_fit = fitMom.X(); + fy_fit = fitMom.Y(); + fz_fit = fitMom.Z(); + fp_fit = fitMom.Mag(); + + double tempXY_mc = sqrt(fx*fx + fy*fy); + double tempXY_fit = sqrt(fx_fit*fx_fit + fy_fit*fy_fit); + fxy = tempXY_mc - tempXY_fit; + + fzMC_min_zFit = fz - fz_fit; + + fpMC_min_pFit = mcMom.Mag() - fitMom.Mag(); + fE_mu = sqrt( + 0.106*0.106 /* mass of muon */ + + fp_fit*fp_fit /* fitted momentum of muon */ + ) + - fEnu[fEventCount]; /* Initial energy of neutrino */ + + TVector3 muMom(0,0,1); + fcosTheta = radToDeg * muMom.Angle(muMom); + + fTtree->Fill(); + } +} + +// ----- Private methods -------------------------------------------- +void FgdMuonRecon::ReadEnuFile() +{ + std::string nuEfile(fnuEFile); + + if(!nuEfile.empty()) + { + const char spaceChar(' '); + std::ifstream nuFileStream; + + try + { + nuFileStream.open(nuEfile.c_str(), std::ios::in); + + if(nuFileStream.is_open()) + { + std::string line; + while(std::getline(nuFileStream,line)) + { + std::istringstream ss(line); + std::string token; + Int_t lineCount = 1; + while(std::getline(ss, token, spaceChar)) + { + // Write only the neutrino energy + if(lineCount==2 && !token.empty()) + { + Double_t&& neutrinoEnergy = std::stod(token); + fEnu.push_back(neutrinoEnergy); + } + ++lineCount; + } + } + } + } + catch(const std::exception& e) + { + LOG(fatal) << e.what(); + } + + if(nuFileStream.is_open()) + { + nuFileStream.close(); + } + } +} + + +// ------------------------------------------------------------------------- + +}// namespace superfgd +}// namespace reconstruction +}// namespace esbroot diff --git a/EsbReconstruction/EsbSuperFGD/FgdMuonRecon.h b/EsbReconstruction/EsbSuperFGD/FgdMuonRecon.h new file mode 100644 index 0000000..0598e1b --- /dev/null +++ b/EsbReconstruction/EsbSuperFGD/FgdMuonRecon.h @@ -0,0 +1,96 @@ +#ifndef ESBROOT_ESBDRECONSTRUCTION_FGD_MUON_RECON_H +#define ESBROOT_ESBDRECONSTRUCTION_FGD_MUON_RECON_H + +// EsbRoot headers +#include "EsbReconstruction/EsbSuperFGD/FgdMCGenFitRecon.h" + + +namespace esbroot { +namespace reconstruction { +namespace superfgd { + +class FgdMuonRecon : public FgdMCGenFitRecon +{ + + public: + + /** Default constructor **/ + FgdMuonRecon(); + + /** Constructor with argument + *@param name Name of task + *@param geoConfigFile - Configuration file detector + *@param mediaFile - Configuration file for the used mediums + *@param outputFile - path to the root file to write the output to + *@param nuEFile - path to the file generated from the Fgd generatr containing neutrino energy per event + *@param verbose - Verbosity level + *@param debugLlv - debug level for genfit + *@param visualize - to visualize the event using genfit::EventDisplay + *@param visOption - option to be passed to genfit::EventDisplay + **/ + FgdMuonRecon(const char* name + , const char* geoConfigFile + , const char* mediaFile + , const char* outputFile + , const char* nuEFile + , Int_t verbose = 1 + , double debugLlv = 0 + , bool visualize = false + , std::string visOption ="D"); + + /** Destructor **/ + virtual ~FgdMuonRecon(); + + virtual InitStatus Init() override; + virtual void FinishEvent() override; + virtual void FinishTask() override; + + /** For decendents who want to write some data to output file */ + virtual void WriteOutput( Int_t pdg + , const TVector3& fitMom + , const TVector3& mcMom + , const genfit::Track& fitTrack + , genfit::FitStatus*& fiStatuStatus) override; + +protected: + + void ReadEnuFile(); + + /** Path to be used to write an output root file **/ + std::string foutputFile;//! fEnu;//!fHitPos.X() == c.fHitPos.X() + && this->fHitPos.Y() == c.fHitPos.Y() + && this->fHitPos.Z() == c.fHitPos.Z()); +} + + +TVector3 ReconHit::operator-(const ReconHit& c) +{ + Int_t&& x = this->fmppcLoc.X()-c.fmppcLoc.X(); + Int_t&& y = this->fmppcLoc.Y()-c.fmppcLoc.Y(); + Int_t&& z = this->fmppcLoc.Z()-c.fmppcLoc.Z(); + return TVector3(x,y,z); +} + +} //superfgd +} //reconstruction +} //esbroot \ No newline at end of file diff --git a/EsbReconstruction/EsbSuperFGD/FgdReconHit.h b/EsbReconstruction/EsbSuperFGD/FgdReconHit.h new file mode 100644 index 0000000..a6b26d2 --- /dev/null +++ b/EsbReconstruction/EsbSuperFGD/FgdReconHit.h @@ -0,0 +1,86 @@ +#ifndef ESBROOT_ESBDRECONSTRUCTION_FGD_RECONHIT_H +#define ESBROOT_ESBDRECONSTRUCTION_FGD_RECONHIT_H + +#include "TObject.h" +#include +#include +#include + +namespace esbroot { +namespace reconstruction { +namespace superfgd { + +class ReconHit : public TObject +{ + +public: + + /** Default constructor **/ + ReconHit(); + + ReconHit(TVector3 mppcLoc + , TVector3 hitPosition + , TVector3 photons + , Double_t time + , TVector3 mom + , TVector3 momExit + , Double_t trackLength + , Double_t trackLengthOrigin + , Int_t pdg + , Int_t trackId + , Double_t edep + , TVector3 ph1 + , TVector3 mppc1 + , TVector3 ph2 + , TVector3 mppc2); + + ~ReconHit(); + + ReconHit(const ReconHit& c); + + ReconHit& operator=(const ReconHit& c); + + Bool_t operator==(const ReconHit& c); + + TVector3 operator-(const ReconHit& c); + + Bool_t IsAlone() + { + return fAllHits.empty(); + } + + + TVector3 fmppcLoc; + TVector3 fHitPos; + TVector3 fphotons; + TVector3 fph1; + TVector3 fmppc1; + TVector3 fph2; + TVector3 fmppc2; + Double_t ftime; + TVector3 fmom; + TVector3 fmomExit; + Double_t ftrackLength; + Double_t ftrackLengthOrigin; + Double_t fEdep; + Int_t fpdg; + Int_t ftrackId; + Bool_t fIsLeaf; + + Double_t fZaxisAngle; + Double_t fChangeAngle; + + Int_t fLocalId; + Bool_t fIsVisited; + std::vector fAllHits;//! +#include +#include +#include + +namespace esbroot { +namespace reconstruction { +namespace superfgd { + +using namespace std; + +#define PERMUTATIONS 23 + +FgdReconTemplate::FgdReconTemplate() +{ + LoadTemplates(); +} + +FgdReconTemplate::~FgdReconTemplate() +{ +} + +Bool_t FgdReconTemplate::IsLeaf(ReconHit* hit) +{ + Bool_t isHitLeaf(false); + + if(hit->fAllHits.size()==1) + { + LOG(debug)<< "Single leaf " << hit->fLocalId; + isHitLeaf = true; + } + else + { + Int_t permutation(0); + std::vector vecs; + GetHitVectors(hit, vecs); + for(size_t temp=0; !isHitLeaf && temp < fLeafVectors.size(); ++temp) + { + if(fLeafVectors[temp].hitVectors.size() == hit->fAllHits.size()) + { + std::vector& tempVecs = fLeafVectors[temp].hitVectors; + isHitLeaf = AreVectorsEqual(tempVecs, vecs, permutation); + } + } + + if(isHitLeaf) + { + LOG(debug) << "Leaf " << hit->fLocalId << " with local hits " << hit->fAllHits.size() << endl; + } + } + + return isHitLeaf; +} + + + +Bool_t FgdReconTemplate::GetNextHit(ReconHit* previous, ReconHit* current, ReconHit*& next) +{ + Bool_t nextFound(false); + next = nullptr; + + if(current==nullptr) + { + throw "Invalid current hit"; + } + + if(current->fAllHits.empty()) + { + return nextFound; + } + + Int_t previousId = (previous==nullptr) ? -1 : previous->fLocalId; + size_t nearestId(0); + Double_t min_dist = std::numeric_limits::max(); + + for(size_t nid = 0; nid< current->fAllHits.size(); ++nid) + { + ReconHit* candidateHit = current->fAllHits[nid]; + + if(!candidateHit->fIsVisited + && candidateHit->fLocalId != previousId + && !candidateHit->fIsLeaf) + { + TVector3 vecPosition = current->fmppcLoc - candidateHit->fmppcLoc; + Double_t dist = vecPosition.X()*vecPosition.X() + vecPosition.Y()*vecPosition.Y() + vecPosition.Z()*vecPosition.Z(); + + if(dist < min_dist) + { + min_dist = dist; + nearestId = nid; + } + } + } + + next = current->fAllHits[nearestId]; + nextFound = (min_dist!=std::numeric_limits::max()); + + return nextFound; +} + +void FgdReconTemplate::LoadTemplates() +{ + // ============================== + // 1. Single leaf templates + // ============================== + // Leaf + // --- --- --- + // --- -C- -X- + // --- --- --- + TVector3 leaf1_1(0,0,-1); + FgdReconTemplate::HitTemplate leaf1_1_temp; + leaf1_1_temp.hitVectors.emplace_back(leaf1_1); + + fLeafVectors.push_back(leaf1_1_temp); + + // Leaf + // --- --- -X- + // --- -C- --- + // --- --- --- + TVector3 leaf1_2(0,-1,-1); + FgdReconTemplate::HitTemplate leaf1_2_temp; + leaf1_2_temp.hitVectors.emplace_back(leaf1_2); + + fLeafVectors.push_back(leaf1_2_temp); + + // Leaf + // --- --- --X + // --- -C- --- + // --- --- --- + TVector3 leaf1_3(1,-1,-1); + FgdReconTemplate::HitTemplate leaf1_3_temp; + leaf1_3_temp.hitVectors.emplace_back(leaf1_3); + + fLeafVectors.push_back(leaf1_3_temp); + + + // ============================== + // 2. Two hits leaf templates + // ============================== + + // Leaf + // --- --- -X- + // --- -C- -X- + // --- --- --- + TVector3 leaf2_1_1(0,-1,-1); + TVector3 leaf2_1_2(0,0,-1); + FgdReconTemplate::HitTemplate leaf2_1_temp; + leaf2_1_temp.hitVectors.emplace_back(leaf2_1_1); + leaf2_1_temp.hitVectors.emplace_back(leaf2_1_2); + + fLeafVectors.push_back(leaf2_1_temp); + + // Leaf + // --- --- --X + // --- -C- -X- + // --- --- --- + TVector3 leaf2_2_1(1,-1,-1); + TVector3 leaf2_2_2(0,0,-1); + FgdReconTemplate::HitTemplate leaf2_2_temp; + leaf2_2_temp.hitVectors.emplace_back(leaf2_2_1); + leaf2_2_temp.hitVectors.emplace_back(leaf2_2_2); + + fLeafVectors.push_back(leaf2_2_temp); + + // Leaf + // --- --- X-- + // --- -C- X-- + // --- --- --- + TVector3 leaf2_3_1(-1,-1,-1); + TVector3 leaf2_3_2(-1,0,-1); + FgdReconTemplate::HitTemplate leaf2_3_temp; + leaf2_3_temp.hitVectors.emplace_back(leaf2_3_1); + leaf2_3_temp.hitVectors.emplace_back(leaf2_3_2); + + fLeafVectors.push_back(leaf2_3_temp); + + // Leaf + // --- --- --X + // --- -C- --X + // --- --- --- + TVector3 leaf2_4_1(1,-1,-1); + TVector3 leaf2_4_2(1,0,-1); + FgdReconTemplate::HitTemplate leaf2_4_temp; + leaf2_4_temp.hitVectors.emplace_back(leaf2_4_1); + leaf2_4_temp.hitVectors.emplace_back(leaf2_4_2); + + fLeafVectors.push_back(leaf2_4_temp); + + // ============================== + // 3. Three hits leaf templates + // ============================== + + // Leaf + // --- --- -XX + // --- -C- -X- + // --- --- --- + TVector3 leaf3_1_1(0,-1,-1); + TVector3 leaf3_1_2(1,-1,-1); + TVector3 leaf3_1_3(0,0,-1); + FgdReconTemplate::HitTemplate leaf3_1_temp; + leaf3_1_temp.hitVectors.emplace_back(leaf3_1_1); + leaf3_1_temp.hitVectors.emplace_back(leaf3_1_2); + leaf3_1_temp.hitVectors.emplace_back(leaf3_1_3); + + fLeafVectors.push_back(leaf3_1_temp); + + + // Leaf + // --- --- XX- + // --- -C- -X- + // --- --- --- + TVector3 leaf3_2_1(-1,-1,-1); + TVector3 leaf3_2_2(0,-1,-1); + TVector3 leaf3_2_3(0,0,-1); + FgdReconTemplate::HitTemplate leaf3_2_temp; + leaf3_2_temp.hitVectors.emplace_back(leaf3_2_1); + leaf3_2_temp.hitVectors.emplace_back(leaf3_2_2); + leaf3_2_temp.hitVectors.emplace_back(leaf3_2_3); + + fLeafVectors.push_back(leaf3_2_temp); + + LOG(debug) << " Leaf templates found " << fLeafVectors.size(); +} + +void FgdReconTemplate::GetHitVectors(ReconHit* hit , std::vector& vecs) +{ + for(size_t i=0; i< hit->fAllHits.size(); ++i) + { + ReconHit& neightbourHit = *hit->fAllHits[i]; + TVector3 result = hit->fmppcLoc - neightbourHit.fmppcLoc; + vecs.emplace_back(result); + } +} + +// Compares if the two vectors are equal +// This also includes rotational symmetry +// Make a copy of the template since it will be modified +Bool_t FgdReconTemplate::AreVectorsEqual(const std::vector& tempVecs, const std::vector& vecs, Int_t& foundPermutation ) +{ + Bool_t areEqual(false); + + if(tempVecs.size()!=vecs.size()) + { + return areEqual; + } + + std::vector tempVecPermut = tempVecs; + + Int_t permutation(0); + Int_t limitPermutations = PERMUTATIONS; + + while(!areEqual && permutation<=limitPermutations) + { + for(size_t i=0; iPERMUTATIONS) + { + throw "Invalid permutation"; + } + + switch(numPermutation) + { + case 0: + // No rotation + break; + case 1: + vec.RotateZ(rot90deg); + break; + case 2: + vec.RotateZ(2*rot90deg); + break; + case 3: + vec.RotateZ(3*rot90deg); + break; + case 4: + vec.RotateY(rot90deg); + break; + case 5: + vec.RotateY(rot90deg); + vec.RotateX(rot90deg); + break; + case 6: + vec.RotateY(rot90deg); + vec.RotateX(2*rot90deg); + break; + case 7: + vec.RotateY(rot90deg); + vec.RotateX(3*rot90deg); + break; + case 8: + vec.RotateY(2*rot90deg); + break; + case 9: + vec.RotateY(2*rot90deg); + vec.RotateZ(rot90deg); + break; + case 10: + vec.RotateY(2*rot90deg); + vec.RotateZ(2*rot90deg); + break; + case 11: + vec.RotateY(2*rot90deg); + vec.RotateZ(3*rot90deg); + break; + case 12: + vec.RotateY(3*rot90deg); + break; + case 13: + vec.RotateY(3*rot90deg); + vec.RotateX(rot90deg); + break; + case 14: + vec.RotateY(3*rot90deg); + vec.RotateX(2*rot90deg); + break; + case 15: + vec.RotateY(3*rot90deg); + vec.RotateX(3*rot90deg); + break; + case 16: + vec.RotateX(rot90deg); + break; + case 17: + vec.RotateX(rot90deg); + vec.RotateY(rot90deg); + break; + case 18: + vec.RotateX(rot90deg); + vec.RotateY(2*rot90deg); + break; + case 19: + vec.RotateX(rot90deg); + vec.RotateY(3*rot90deg); + break; + case 20: + vec.RotateX(-rot90deg); + break; + case 21: + vec.RotateX(-rot90deg); + vec.RotateY(rot90deg); + break; + case 22: + vec.RotateX(-rot90deg); + vec.RotateY(2*rot90deg); + break; + case 23: + vec.RotateX(-rot90deg); + vec.RotateY(3*rot90deg); + break; + default: + break; + } + + Double_t&& x = std::round(vec.X()); + Double_t&& y = std::round(vec.Y()); + Double_t&& z = std::round(vec.Z()); + + return TVector3(x,y,z); +} + +} //superfgd +} //reconstruction +} //esbroot \ No newline at end of file diff --git a/EsbReconstruction/EsbSuperFGD/FgdReconTemplate.h b/EsbReconstruction/EsbSuperFGD/FgdReconTemplate.h new file mode 100644 index 0000000..eca0493 --- /dev/null +++ b/EsbReconstruction/EsbSuperFGD/FgdReconTemplate.h @@ -0,0 +1,78 @@ +#ifndef ESBROOT_ESBDRECONSTRUCTION_FGD_RECON_TEMPLATE_H +#define ESBROOT_ESBDRECONSTRUCTION_FGD_RECON_TEMPLATE_H + + +#include "EsbReconstruction/EsbSuperFGD/FgdReconHit.h" + +#include "TObject.h" +#include + +#include +#include + +namespace esbroot { +namespace reconstruction { +namespace superfgd { + +class FgdReconTemplate : public TObject +{ + +public: + + /** Default constructor **/ + FgdReconTemplate(); + + ~FgdReconTemplate(); + + Bool_t IsLeaf(ReconHit* hit); + + Bool_t GetNextHit(ReconHit* previous, ReconHit* current, ReconHit*& next); + +private: + + /** Class Containing the vectors for each template found**/ + class HitTemplate + { + public: + HitTemplate(){} + + ~HitTemplate(){} + + HitTemplate(const HitTemplate& c) + { + this->previousHit = c.previousHit; + this->nextHit = c.nextHit; + this->hitVectors = c.hitVectors; + } + + HitTemplate& operator=(const HitTemplate& c) + { + this->previousHit = c.previousHit; + this->nextHit = c.nextHit; + this->hitVectors = c.hitVectors; + return *this; + } + + size_t Length(){return hitVectors.size();} + + TVector3 nextHit; + TVector3 previousHit; + std::vector hitVectors; + }; + + void LoadTemplates(); + void GetHitVectors(ReconHit* hit, std::vector& vecs); + + Bool_t AreVectorsEqual(const std::vector& tempVecs, const std::vector& vecs, Int_t& foundPermutation ); + TVector3 GetPermutation(TVector3 vec, Int_t numPermutation); + + std::vector fLeafVectors;//!=lower && val<=upper) + { + + pdgCode = fpdg; + result = true; + } + return result; +} + + +} //superfgd +} //reconstruction +} //esbroot \ No newline at end of file diff --git a/EsbReconstruction/EsbSuperFGD/PdgFromMomentumLoss.h b/EsbReconstruction/EsbSuperFGD/PdgFromMomentumLoss.h new file mode 100644 index 0000000..1449749 --- /dev/null +++ b/EsbReconstruction/EsbSuperFGD/PdgFromMomentumLoss.h @@ -0,0 +1,45 @@ +#ifndef ESBROOT_ESBDRECONSTRUCTION_FGD_PDG_FROM_MOMENTUM_LOSS_H +#define ESBROOT_ESBDRECONSTRUCTION_FGD_PDG_FROM_MOMENTUM_LOSS_H + +#include "TObject.h" +#include +#include +#include + +namespace esbroot { +namespace reconstruction { +namespace superfgd { + + +class PdgFromMomentumLoss : public TObject +{ +public: + + /** Default constructor **/ + PdgFromMomentumLoss(); + PdgFromMomentumLoss(Int_t p, Double_t momLoss, Double_t diff); + + ~PdgFromMomentumLoss(); + + PdgFromMomentumLoss(const PdgFromMomentumLoss& p); + + PdgFromMomentumLoss& operator=(const PdgFromMomentumLoss& p); + + Bool_t operator==(const PdgFromMomentumLoss& p); + + Bool_t GetPdg(Double_t val, Int_t& pdgCode); + + Int_t fpdg; + Double_t favgMomLoss; + Double_t fallowedDiff; + +private: + + ClassDef(PdgFromMomentumLoss, 2); +}; + +} //superfgd +} //reconstruction +} //esbroot + +#endif \ No newline at end of file diff --git a/EsbReconstruction/ReconLinkDef.h b/EsbReconstruction/ReconLinkDef.h new file mode 100644 index 0000000..1e1ea44 --- /dev/null +++ b/EsbReconstruction/ReconLinkDef.h @@ -0,0 +1,30 @@ +/******************************************************************************** + * Copyright (C) 2014 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH * + * * + * This software is distributed under the terms of the * + * GNU Lesser General Public Licence (LGPL) version 3, * + * copied verbatim in the file "LICENSE" * + ********************************************************************************/ +#ifdef __CINT__ + +#pragma link off all globals; +#pragma link off all classes; +#pragma link off all functions; +#pragma link C++ nestedclasses; +#pragma link C++ nestedtypedef; + +#pragma link C++ namespace esbroot+; +#pragma link C++ namespace esbroot::reconstruction+; +#pragma link C++ namespace esbroot::reconstruction::superfgd+; + +#pragma link C++ class esbroot::reconstruction::superfgd::FgdGenFitRecon+; +#pragma link C++ class esbroot::reconstruction::superfgd::FgdMCGenFitRecon+; +#pragma link C++ class esbroot::reconstruction::superfgd::FgdMCLeptonStats+; +#pragma link C++ class esbroot::reconstruction::superfgd::FgdMCEventRecord+; +#pragma link C++ class esbroot::reconstruction::superfgd::FgdGraphStats+; +#pragma link C++ class esbroot::reconstruction::superfgd::ReconHit+; +#pragma link C++ class esbroot::reconstruction::superfgd::FgdReconTemplate+; +#pragma link C++ class esbroot::reconstruction::superfgd::PdgFromMomentumLoss+; +#pragma link C++ class esbroot::reconstruction::superfgd::FgdMuonRecon+; + +#endif diff --git a/EsbTools/CMakeLists.txt b/EsbTools/CMakeLists.txt index 765473f..616fc87 100644 --- a/EsbTools/CMakeLists.txt +++ b/EsbTools/CMakeLists.txt @@ -19,10 +19,16 @@ link_directories( ${LINK_DIRECTORIES}) set(SRCS PMTubeGeoCreator.cxx + THStackPlus.cxx + GenieAnaEventData.cxx + fiTQunAnaEventData.cxx ) Set(HEADERS ${CMAKE_SOURCE_DIR}/EsbTools/PMTubeGeoCreator.h + ${CMAKE_SOURCE_DIR}/EsbTools/THStackPlus.h + ${CMAKE_SOURCE_DIR}/EsbTools/GenieAnaEventData.h + ${CMAKE_SOURCE_DIR}/EsbTools/fiTQunAnaEventData.h ) Set(LINKDEF ${CMAKE_SOURCE_DIR}/EsbTools/ToolsLinkDef.h) diff --git a/EsbTools/GenieAnaEventData.cxx b/EsbTools/GenieAnaEventData.cxx new file mode 100644 index 0000000..ae9c291 --- /dev/null +++ b/EsbTools/GenieAnaEventData.cxx @@ -0,0 +1,57 @@ +#include "EsbTools/GenieAnaEventData.h" + +#include +#include + +#include +#include + +namespace esbroot { +namespace tools { + +void GenieAnaEventData::ConnectToTree(TTree* gtrac_tree) +{ + gtrac_tree->SetBranchAddress("EvtNum", &EvtNum); + gtrac_tree->SetBranchAddress("EvtCode", &EvtCode); + gtrac_tree->SetBranchAddress("StdHepN", &StdHepN); //Number of particles in event + gtrac_tree->SetBranchAddress("StdHepPdg", StdHepPdg); //PDG codes of particles + gtrac_tree->SetBranchAddress("StdHepStatus", StdHepStatus); //GENIE status of particles + gtrac_tree->SetBranchAddress("StdHepP4", StdHepP4); //Four-momentum of particles (px, py, pz, E) + gtrac_tree->SetBranchAddress("StdHepFd", StdHepFd); //First daughter index + gtrac_tree->SetBranchAddress("StdHepLd", StdHepLd); //Last daughter index + gtrac_tree->SetBranchAddress("StdHepFm", StdHepFm); //First mother index + gtrac_tree->SetBranchAddress("StdHepLm", StdHepLm);//Last mother index +} + +void GenieAnaEventData::PrintEvent() +{ + using namespace std; + + cout << endl << "**** Event " << EvtNum << " ****" << endl; + cout << "Event code: " << EvtCode->GetString() << endl; + cout << "Number of Hep particles: " << StdHepN << endl; + + cout << right << setw(3) << "In" << setw(12) << "PDG Code" + << setw(4) << "St" + << setw(4) << "Fd" << setw(4) << "Ld" + << setw(4) << "Fm" << setw(4) << "Lm" + << setw(10) << "Px (GeV)" << setw(10) << "Py (GeV)" + << setw(10) << "Pz (Gev)" << setw(10) << "E (GeV)" + << endl; + + cout << "---------------------------------------------------------------------------" << endl; + + for(int part = 0; part < StdHepN; ++part) { + cout << right << setw(3) << part << setw(12) << StdHepPdg[part] + << setw(4) << StdHepStatus[part] + << setw(4) << StdHepFd[part] << setw(4) << StdHepLd[part] + << setw(4) << StdHepFm[part] << setw(4) << StdHepLm[part] + << setprecision(3) + << setw(10) << StdHepP4[part][0] << setw(10) << StdHepP4[part][1] + << setw(10) << StdHepP4[part][2] << setw(10) << StdHepP4[part][3] + << endl; + } +} + +} +} diff --git a/EsbTools/GenieAnaEventData.h b/EsbTools/GenieAnaEventData.h new file mode 100644 index 0000000..8ea2a82 --- /dev/null +++ b/EsbTools/GenieAnaEventData.h @@ -0,0 +1,37 @@ +#ifndef ESBROOT_ESBTOOLS_GENIEANAEVENTDATA_H +#define ESBROOT_ESBTOOLS_GENIEANAEVENTDATA_H + +#include +#include "Rtypes.h" + +class TObjString; +class TTree; + +namespace esbroot { +namespace tools { + +struct GenieAnaEventData +{ + static constexpr size_t npmax = 1000; + + int EvtNum; + TObjString* EvtCode = nullptr; + int StdHepN; + int StdHepPdg[npmax]; + int StdHepStatus[npmax]; + double StdHepP4[npmax][4]; + int StdHepFd[npmax]; + int StdHepLd[npmax]; + int StdHepFm[npmax]; + int StdHepLm[npmax]; + + void ConnectToTree(TTree* gtrac_tree); + void PrintEvent(); + + ClassDef(GenieAnaEventData, 2) +}; + +} +} + +#endif //ESBROOT_ESBTOOLS_GENIEANAEVENTDATA_H diff --git a/EsbTools/THStackPlus.cxx b/EsbTools/THStackPlus.cxx new file mode 100644 index 0000000..243825f --- /dev/null +++ b/EsbTools/THStackPlus.cxx @@ -0,0 +1,236 @@ +#include "EsbTools/THStackPlus.h" + +#include +#include +#include +#include +#include +#include + +#include "TH1D.h" + +#include "TList.h" +#include "TObject.h" +#include "TDirectory.h" +#include "TClass.h" +#include "TKey.h" +#include "TROOT.h" +#include "TPad.h" +#include "TObjString.h" +#include "THashList.h" +#include "TBuffer.h" + +namespace esbroot { +namespace tools { + +int THStackPlus::save_as_thstack_ = false; + +THStackPlus::~THStackPlus() { + delete protoHisto_; +} + +void THStackPlus::common_constructor() { + SetProtoHisto(NULL); + gDirectory->Add(this); +} + + +TH1D *THStackPlus::GetCreate1D(const char* name, const char* title) { + TH1D *tmpHisto = Get1D(name); + + if(tmpHisto != NULL) { + if( std::strcmp(tmpHisto->GetTitle(), title) ) { + std::cerr << __PRETTY_FUNCTION__ << " FATAL: Wrong title."; + exit(EXIT_FAILURE); + } + return(tmpHisto); + } else { + if(GetProtoHisto() == NULL) { + std::cerr << __PRETTY_FUNCTION__ << " FATAL: " << name << " does not exist in " + << GetName() << " and there is no proto histogram. Aborting." << std::endl; + exit(EXIT_FAILURE); + } + if(GetProtoHisto()->IsA() == TH1D::Class()) { + TH1D *protoHisto = static_cast(GetProtoHisto()); + TH1D *newHisto = new TH1D(*protoHisto); + newHisto->SetName(name); + newHisto->SetTitle(title); + Add(newHisto); + return(newHisto); + } else { + std::cerr << __PRETTY_FUNCTION__ << " FATAL: prototype histogram not TH1D. Aborting." << std::endl; + exit(EXIT_FAILURE); + } + } + +} + +void THStackPlus::WriteToDirectory(TDirectory *outDir) { + if(GetHists() == NULL) return; + + { + TIterator *it = GetHists()->MakeIterator(); + while(TH1 *histo = static_cast(it->Next())) { + histo->SetDirectory(outDir); + histo->Write(); + } + delete it; + } +} + +void THStackPlus::ReadFromDirectory(TDirectory *inDir) { + if(GetHists() != NULL) { + std::cerr << __PRETTY_FUNCTION__ << " FATAL: Trying to read into a stack which is not empty. Aborting." << std::endl; + exit(EXIT_FAILURE); + } + + TList *objs = inDir->GetList(); + if(objs != NULL) { + TIterator *it = objs->MakeIterator(); + while(TObject *obj = it->Next()) { + if(obj->IsA()->InheritsFrom(TH1::Class())) { + Add(static_cast(obj)); + } + } + delete it; + } + + TList *keys = inDir->GetListOfKeys(); + if(keys != NULL) { + TIterator *it = keys->MakeIterator(); + while(TKey *key = static_cast(it->Next())) { + TClass *tmpClass = gROOT->GetClass(key->GetClassName()); + if(tmpClass->InheritsFrom(TH1::Class())) { + Add(static_cast(key->ReadObj())); + } + } + } + + +} + +TH1D* THStackPlus::Get1D(const char *name) { + TObject *tmpObject; + + if(GetHists() == NULL) { + tmpObject = NULL; + } else { + tmpObject = GetHists()->FindObject(name); + } + + if(tmpObject != NULL) { + if(tmpObject->IsA() == TH1D::Class()) { + return(static_cast(tmpObject)); + } else { + std::cerr << __PRETTY_FUNCTION__ << " FATAL: " << name << "exists in " << GetName() << "and is not TH1D! Aborting." << std::endl; + exit(EXIT_FAILURE); + } + } else return(NULL); +} + +void THStackPlus::Add(TH1* h, Option_t* option /* = "" */) { + if(h==NULL) return; + h->SetDirectory(NULL); + THStack::Add(h, option); +} + +void THStackPlus::Draw(Option_t* chopt /* = "" */) { + THStack::Draw(chopt); + static_cast(gPad)->BuildLegend(); +} + +void THStackPlus::SetProtoHisto(TH1* protoHisto) { + protoHisto_ = protoHisto; + if(protoHisto_ != NULL) protoHisto_->SetDirectory(NULL); +} + +void THStackPlus::SyncTextLabels() { //Because ROOT is crap + //Make a set of all labels + if(GetHists() == NULL) return; + + std::set known_labels; + TIterator *iter = GetHists()->MakeIterator(); + while(TH1D* hist = dynamic_cast(iter->Next())) { + TIterator *iter1 = hist->GetXaxis()->GetLabels()->MakeIterator(); + while( TObjString* label = dynamic_cast(iter1->Next()) ) { + known_labels.insert(label->String().Data()); + } + delete(iter1); + } + delete(iter); + + //Add missing labels to histograms + iter = GetHists()->MakeIterator(); + while(TH1D* hist = dynamic_cast(iter->Next())) { + for(auto it = known_labels.begin(); it != known_labels.end(); ++it) { + hist->GetXaxis()->FindBin(it->c_str()); + } + hist->LabelsDeflate("x"); + hist->LabelsOption("a", "x"); + } + delete(iter); +} + +THStackPlus* THStackPlus::DrawNormalized(Option_t* chopt /* = "" */) { + TString clone_name = this->GetName(); + clone_name += "_normalized"; + + THStackPlus *ts_clone = dynamic_cast(this->Clone(clone_name)); + + double total_norm = 0.0; + TIterator *iter = ts_clone->GetHists()->MakeIterator(); + while( TH1D* hist = dynamic_cast(iter->Next()) ) { + total_norm += hist->Integral(); + } + iter->Reset(); + while( TH1D* hist = dynamic_cast(iter->Next()) ) { + hist->Scale(1.0/total_norm); + } + delete(iter); + + ts_clone->Draw(chopt); + return(ts_clone); + +} + +THStack *THStackPlus::MakeTHStack(const char* name /*= NULL*/, const char* title /*= NULL*/) const +{ + const char *new_name, *new_title; + new_name = (name == NULL) ? GetName() : name; + new_title = (title == NULL) ? GetTitle() : title; + + THStack *retval = new THStack(new_name, new_title); + if(GetHists() == NULL) return(retval); + + { + TIterator *it = GetHists()->MakeIterator(); + while(TH1 *histo = dynamic_cast(it->Next())) { + retval->Add(histo); + } + delete(it); + } + + return(retval); +} + +/*virtual*/ Int_t THStackPlus::Write(const char *name /*= 0*/, Int_t option /*= 0*/, Int_t bufsize /*= 0*/) const +{ + if(GetSaveAsTHStack()) { + THStack *ths = MakeTHStack(); + Int_t retval = ths->Write(name, option, bufsize); + delete(ths); + return(retval); + } else { + return(TObject::Write(name, option, bufsize)); + } +} + +void THStackPlus::ApplyToAll(std::function const& func) { + for(auto&& obj : *GetHists()) { + func(dynamic_cast(obj)); + } +} + + +} //namespace tools +} //namespace esbroot diff --git a/EsbTools/THStackPlus.h b/EsbTools/THStackPlus.h new file mode 100644 index 0000000..7a445fa --- /dev/null +++ b/EsbTools/THStackPlus.h @@ -0,0 +1,73 @@ +#ifndef ESBROOT_ESBTOOLS_THSTACKPLUS_H +#define ESBROOT_ESBTOOLS_THSTACKPLUS_H + +#include "THStack.h" + +#include + +#include + +class TH1; +class TH1D; +class TDirectory; + +namespace esbroot { +namespace tools { + +class THStackPlus : public THStack { + public: + THStackPlus() : protoHisto_(NULL) {}; + THStackPlus(const char* name, const char* title) : + THStack(name, title) {common_constructor();}; + THStackPlus(const char* name, const char* title, TH1* proto) : + THStack(name, title) {common_constructor(); proto->SetName(TString(name) + "-proto"); SetProtoHisto(proto);} + THStackPlus(const char* name, const char* title, TH1 const& proto) : + THStack(name, title) {common_constructor(); SetProtoHisto(dynamic_cast(proto.Clone(TString(name) + "-proto")));} + virtual ~THStackPlus(); + + TH1 *GetProtoHisto() {return(protoHisto_);}; + void SetProtoHisto(TH1* protoHisto); + + TH1D *Get1D(const char *name); + + TH1D *GetCreate1D(const char* name, const char* title); + TH1D *GetCreate1D(const char* name) {return(GetCreate1D(name, name));}; + + void WriteToDirectory(TDirectory *outDir); + void ReadFromDirectory(TDirectory *outDir); + + virtual void Add(TH1* h, Option_t* option = ""); + + virtual void Draw(Option_t* chopt = ""); + virtual void DrawClone(Option_t* chopt = "") {dynamic_cast(this->Clone())->Draw(chopt);}; + virtual THStackPlus* DrawNormalized(Option_t* chopt = ""); + + THStackPlus* SmartClone(const char* newname = "") {return(dynamic_cast(this->Clone()));}; + + virtual Int_t Write(const char *name = 0, Int_t option = 0, Int_t bufsize = 0) const; + + void SyncTextLabels(); //Because ROOT is crap + + THStack *MakeTHStack(const char* name = NULL, const char* title = NULL) const; + + void ApplyToAll(std::function const& func); + + static void SetSaveAsTHStack(int option) {save_as_thstack_ = option;}; + static int GetSaveAsTHStack() {return(save_as_thstack_);}; + + protected: + void common_constructor(); + //~ Color_t GetNewColor(); + + private: + TH1 *protoHisto_; + //~ Color_t currentColor_; + + static int save_as_thstack_; + + ClassDef(THStackPlus, 3) +}; + +} //namespace tools +} //namespace esbroot +#endif //ESBROOT_ESBTOOLS_THSTACKPLUS_H diff --git a/EsbTools/ToolsLinkDef.h b/EsbTools/ToolsLinkDef.h index 8d82470..0e99525 100755 --- a/EsbTools/ToolsLinkDef.h +++ b/EsbTools/ToolsLinkDef.h @@ -17,6 +17,9 @@ #pragma link C++ namespace esbroot; #pragma link C++ class esbroot::tools::PMTubeGeoCreator+; +#pragma link C++ class esbroot::tools::THStackPlus+; +#pragma link C++ class esbroot::tools::GenieAnaEventData+; +#pragma link C++ class esbroot::tools::fiTQunAnaEventData+; #endif diff --git a/EsbTools/UtilityDefs.h b/EsbTools/UtilityDefs.h new file mode 100644 index 0000000..3b745fa --- /dev/null +++ b/EsbTools/UtilityDefs.h @@ -0,0 +1,13 @@ +/** + * This header contains the utility definitions of variables + * and global constants that should be used throughtout the + * application. + */ + + + +#define OUT + + +/* PDG Codes */ +#define CARBON_12 1000060120 \ No newline at end of file diff --git a/EsbTools/fiTQunAnaEventData.cxx b/EsbTools/fiTQunAnaEventData.cxx new file mode 100644 index 0000000..c6892e7 --- /dev/null +++ b/EsbTools/fiTQunAnaEventData.cxx @@ -0,0 +1,27 @@ +#include "EsbTools/fiTQunAnaEventData.h" + +#include + +namespace esbroot { +namespace tools { + +void fiTQunAnaEventData::ConnectToTree(TTree* fitqun_tree) { + fitqun_tree->SetBranchAddress("fqnse", &fqnse); + + fitqun_tree->SetBranchAddress("fqnhitpmt", fqnhitpmt); + fitqun_tree->SetBranchAddress("fqtotq", fqtotq); + fitqun_tree->SetBranchAddress("fq0rnll", fq0rnll); + + fitqun_tree->SetBranchAddress("fq1rpcflg", fq1rpcflg); + fitqun_tree->SetBranchAddress("fq1rnll", fq1rnll); + fitqun_tree->SetBranchAddress("fq1rmom", fq1rmom); + fitqun_tree->SetBranchAddress("fq1rt0", fq1rt0); + fitqun_tree->SetBranchAddress("fq1rpos", fq1rpos); + fitqun_tree->SetBranchAddress("fq1rdir", fq1rdir); + + fitqun_tree->SetBranchAddress("fqpi0nll", fqpi0nll); + fitqun_tree->SetBranchAddress("fqpi0mass", fqpi0mass); +} + +} +} diff --git a/EsbTools/fiTQunAnaEventData.h b/EsbTools/fiTQunAnaEventData.h new file mode 100644 index 0000000..49ecb33 --- /dev/null +++ b/EsbTools/fiTQunAnaEventData.h @@ -0,0 +1,38 @@ +#ifndef ESBROOT_ESBTOOLS_FITQUNANAEVENTDATA_H +#define ESBROOT_ESBTOOLS_FITQUNANAEVENTDATA_H + +#include + +class TTree; + +namespace esbroot { +namespace tools { + +struct fiTQunAnaEventData +{ + static constexpr size_t max_fqnse = 100; + + int fqnse; + + int fqnhitpmt[max_fqnse]; + float fqtotq[max_fqnse]; + float fq0rnll[max_fqnse]; + + int fq1rpcflg[max_fqnse][7]; + float fq1rnll[max_fqnse][7]; + float fq1rmom[max_fqnse][7]; + float fq1rt0[max_fqnse][7]; + float fq1rpos[max_fqnse][7][3]; + float fq1rdir[max_fqnse][7][3]; + + float fqpi0nll[2]; + float fqpi0mass[2]; + + void ConnectToTree(TTree* fitqun_tree); +}; + + +} +} + +#endif //ESBROOT_ESBTOOLS_FITQUNANAEVENTDATA_H diff --git a/README.md b/README.md old mode 100644 new mode 100755 index 909e4bd..58e3566 --- a/README.md +++ b/README.md @@ -1,46 +1,206 @@ # EsbRoot -Software for physics simulation of ESSnuSB project +Software for physics simulation of the ESSnuSB project + +Doxygen documentation can be found here: \ +https://essnusb.irb.hr/doxygen/ # How to install -1. Install FairSoft and FairRoot as described here:\ +This guide is heavily based on this talk: \ http://essnusb.eu/docdbprivate/ShowDocument?docid=186 \ -**IMPORTANT:** Do **not** check-out specific versions of FairSoft and FairRoot as described in the slides above. +## 0.1 Install prerequisites +Debian-based distributions (e.g. Linux Mint): \ +sudo apt-get install cmake cmake-data g++ gcc gfortran debianutils build-essential make patch sed libx11-dev libxft-dev libxext-dev libxpm-dev libxmu-dev libglu1-mesa-dev libgl1-mesa-dev libncurses5-dev curl libcurl4-openssl-dev bzip2 libbz2-dev gzip unzip tar subversion git xutils-dev flex bison lsb-release python-dev libc6-dev-i386 libxml2-dev wget libssl-dev libkrb5-dev automake autoconf libtool + +## 0.2 Prepare the directory +For example, we will install everything in ~/ESSnuSB/soft/ . Change the INSTALL_PATH variable if you want to put it somewhere else. +``` +export INSTALL_PATH=~/ESSnuSB/soft/ +mkdir -p $INSTALL_PATH +cd $INSTALL_PATH +``` +We will put soures in $INSTALL_PATH/src +``` +mkdir src +cd src +``` +## 1. Install FairSoft +``` +git clone https://github.com/ESSnuSB/FairSoft.git FairSoft +cd FairSoft +./configure.sh +``` +In the configrue script chose: +``` +1) GCC (on Linux)|| Intel Compiler (Linux) || CC (Solaris) || Portland Compiler || Clang (Mac OSX) +1) No Debug Info|| Debug Info || Optimize || Optimize with Debug Info +2) No (install FairMQOnly)|| Yes +1) Yes (install Simulation engines and event generators)|| No +2) Internet (install G4 additional files from internet)|| Don't install || Directory +1) Yes (install the python bindings for ROOT and Geant4)|| No +path: $INSTALL_PATH/fairsoft +``` +Go get a cofee until it compiles. It takes a while. + +## 2. Install FairRoot +Prepare the environment: +``` +export SIMPATH=$INSTALL_PATH/fairsoft +export PATH=$SIMPATH/bin:$PATH +``` +Get FairRoot +``` +cd $INSTALL_PATH/src +git clone https://github.com/ESSnuSB/FairRoot.git FairRoot +``` +Build and install +``` +cd FairRoot +mkdir build +cd build +cmake -DCMAKE_INSTALL_PREFIX="$INSTALL_PATH/fairroot" .. +make +make install +``` +Now FairRoot and Fairsoft should be installed in $INSTALL_PATH. Take a look + +## 3 Install Genie (optional for now) +Install the prerequisites for Genie: log4cpp, libxml2, and LHAPDF. On Ubuntu based system (like Mint), you can do this using a command: +``` +sudo apt-get install liblog4cpp5-dev libxml2-dev liblhapdf-dev +``` + +Source the FairRoot configuration script to get all the environmental variables. +``` +source $INSTALL_PATH/fairroot/bin/FairRootConfig.sh +``` + +The build system of Genie-Generator has been modified so that the entire Genie generator is compiled into a single library. This allows easy linking and usage from ROOT. So, you need to get Genie from the ESSnuSB repository +``` +cd $INSTALL_PATH/src +git clone https://github.com/ESSnuSB/Genie-Generator.git Genie +cd Genie +git checkout essnusb-current +``` +This checks out Genie version currently recommended to use with EsbRoot. You can see the verson by looking at the file +``` +$INSTALL_PATH/src/Genie/VERSION +``` + +Link and enter the Genie directory +``` +cd $INSTALL_PATH +ln -s $INSTALL_PATH/src/Genie GENIE +cd GENIE +``` + +Budild Genie +``` +export GENIE="$PWD" +./configure +make megalib +``` +Genie should now be built. + +``` +NOTE: to use Genie, the cross sections have to be downloaded (see: http://scisoft.fnal.gov/scisoft/packages/genie_xsec/). +The following variable has to be defined in the macro files +generators::GenieGenerator::GlobalState.fXsecSplineFileName = "PATH_TO_CROSS_SECTION.xml"; +``` + +## 4 Install GenFit and PathFinder (optional for now) + +Install the prerequisites for GenFit: + +sudo apt-get install libeigen3-dev +``` +Download the getfit git repository from +https://github.com/ESSnuSB/GenFit +``` +Follow the build instructions from +https://github.com/ESSnuSB/GenFit/blob/master/README.build + +``` +NOTE: the following environmental variables have to be exported +export ROOTSYS=/** PATH TO FAIRSOFT **/fairsoft +export GENFIT_HOME=/** PATH TO Downloaded GenFit directory **/ +export GENFIT_BUILD=/** PATH TO the build directory in the used build folder**/ +``` + +Download PathFinder from +``` +https://github.com/ESSnuSB/PathFinder +``` -That is, when installing FairSoft, ignore this line: +The only prerequisite is to have CERN ROOT installed (which should be installed with Fairsoft installation). +Create a folder and execute ``` -git checkout may18 +$cmake PATH_TO_PATHFINDERSOURCES +$make ``` -When istalling FairRoot, ignore this line: +After the build is successdull two enviormental variables have to be defined. +One to the include directory which is located 'include' folder of the downloaded Pathdinder source +directory, and the second environemntal variable is to the 'lib' folder in the Pathfinder build directory (the used cmake folder). ``` -git checkout v-17.10d +export PATHFINDER_HOME=/** PATHFINDER extracted directory containing the sources **/ +export PATHFINDER_BUILD=/** PATHFINDER build directory **/ ``` -This goes quite smoothly, but it might take a long time to compile everything. If it doesnt work on your GNU/Linux distro, try to do it in our virtual machine (worked out-of-the-box for me on Mint 18.x). +When building the EsbRoot application with the -DWITH_GENFIT=ON option, both +Genfit and Pathfinder will be included in EsbRoot. -2. Go to FairRoot install dir, source the config script and set FAIRROOTPATH: \ -cd [your FairRoot installation directory] \ -source bin/FairRootConfig.sh\ +## 5. Install EsbRoot +Go to FairRoot install dir, source the config script and set FAIRROOTPATH: +``` +cd $INSTALL_PATH/fairroot +source bin/FairRootConfig.sh export FAIRROOTPATH="$PWD" +``` +Get EsbRoot and prepare build directory +``` +cd $INSTALL_PATH +git clone https://github.com/ESSnuSB/EsbRoot +cd EsbRoot +mkdir build +cd build +``` +To compile without Genie support, just do +``` +cmake .. +make +``` -3. compile ESSnuSB software\ -cd [directory which will contain EsbRoot/ directory] \ -git clone https://github.com/ESSnuSB/EsbRoot \ -cd EsbRoot/ \ -mkdir build \ -cd build \ -cmake .. \ +To compile with Genie support, do +``` +export GENIE=$INSTALL_PATH/GENIE +cmake -DWITH_GENIE=ON .. make +``` +To compile with Genie and GenFit support, do +``` +export GENIE=$INSTALL_PATH/GENIE +export GENFIT_HOME=/** PATH TO Downloaded GenFit directory **/ +export GENFIT_BUILD=/** PATH TO the build directory in the used build folder**/ +export PATHFINDER_HOME=/** PATHFINDER extracted directory containing the sources **/ +export PATHFINDER_BUILD=/** PATHFINDER build directory **/ +cmake -DWITH_GENIE=ON -DWITH_GENFIT=ON .. +make +``` The software should now be compiled! # How to use -1. Set up the environment \ -cd [EsbRoot directory]/build \ +1. Set up the environment +``` +cd [EsbRoot directory]/build source config.sh +``` 2. Try running macros + Go to EsbMacro directory, try running: -- ess_sim.C (root -l -b ess_sim.C) - this shoud produce evetest.root file which contains tracks and (Cherenkov) hits in a small cherenkov detector using muon as a primary track (for now). +- ess_sim.C (```root -l -b ess_sim.C```) - this shoud produce evetest.root file which contains tracks and (Cherenkov) hits in a small cherenkov detector using muon as a primary track (for now). - evetest.C - read the evetest.root file and output some information. - diplay_event_ND.C - simple display of hits on walls of the detector - eventDisplay.C - full 3D event display, still not working properly +- ess_sim_genie.C - example how to run with Genie generator. You will need to download the Genie cross-sections, see the code for comments. + diff --git a/config.sh.in b/config.sh.in new file mode 100644 index 0000000..3b8bb68 --- /dev/null +++ b/config.sh.in @@ -0,0 +1,41 @@ +source @CMAKE_BINARY_DIR@/fairroot_config.sh -p + +#If WITH_GENIE is was to ON during cmake +if [ "@WITH_GENIE@" = "ON" ]; then + export GENIE=@GENIE_DIR@ + export PATH=$GENIE/bin:$PATH + export LD_LIBRARY_PATH=@GENIE_LIB_DIR@:$LD_LIBRARY_PATH + export LHAPATH=$GENIE/data/evgen/pdfs +fi + + +#If WITH_GENFIT is was to ON during cmake +if [ "@WITH_GENFIT@" = "ON" ]; then + + #================================================================== + #========== Genfit =========================== + #================================================================== + # Genfit include loops all folders and adds "folder"/include to included folders + export GENFIT_INCLUDE=@GENFIT_INCLUDE@ + + # Genfit folder contains the root dictionary. + # the subfolder /lib is later used to include *.so library files + export GENFIT_LIBRARY=@GENFIT_LIBRARY@ + + export PATH=@GENFIT_LIBRARY@/bin:$PATH + + # Add root dictionaries. ALso used in the bin examples (if build) + export LD_LIBRARY_PATH=@GENFIT_LIBRARY@:$LD_LIBRARY_PATH + # Add Genfit libs + export LD_LIBRARY_PATH=@GENFIT_LIBRARY@/lib:$LD_LIBRARY_PATH + + #================================================================== + #========== PATHFINDER ======================= + #================================================================== + + export PATHFINDER_INC=@PATHFINDER_INC@/include + export PATHFINDER_LIB=@PATHFINDER_LIB@/lib + + export PATH=@PATHFINDER_LIB@/bin:$PATH + export LD_LIBRARY_PATH=@PATHFINDER_LIB@/lib:$LD_LIBRARY_PATH +fi diff --git a/geometry/media.geo b/geometry/media.geo index e3daa62..36a1147 100644 --- a/geometry/media.geo +++ b/geometry/media.geo @@ -1,3 +1,139 @@ +//---------------------------------------------------------- +// MEMPHYS_Water and WCSim_Water are water parameters taken +// from MEMPHYS and WCSim code. Provided by Guy Barrand, +// for more information and caveats see here: +// https://github.com/gbarrand/g42fair +// Budimir: There is a significant difference in +// apsorption lengths between the two parameter sets. This +// needs to be investigated, compared to literature and +// validated. +MEMPHYS_Water 2 1.01 16 1 8 1 0.112098 0.887902 + 0 0 20. .001 + 60 + 1.56962 253.504 1 1.32885 + 1.58974 317.938 1 1.32906 + 1.61039 399.915 1 1.32927 + 1.63157 504.54 1 1.32948 + 1.65333 638.5 1 1.3297 + 1.67567 810.584 1 1.32992 + 1.69863 1032.4 1 1.33014 + 1.72222 1319.3 1 1.33037 + 1.74647 1691.72 1 1.3306 + 1.77142 2176.94 1 1.33084 + 1.7971 2249.21 1 1.33109 + 1.82352 2496.88 1 1.33134 + 1.85074 2626.74 1 1.3316 + 1.87878 2730 1 1.33186 + 1.90769 3211.3 1 1.33213 + 1.93749 3397.89 1 1.33241 + 1.96825 3516.17 1 1.3327 + 1.99999 3631.08 1 1.33299 + 2.03278 3858.02 1 1.33329 + 2.06666 4610.42 1 1.33361 + 2.10169 7077.14 1 1.33393 + 2.13793 10384.2 1 1.33427 + 2.17543 13837 1 1.33462 + 2.21428 15583.6 1 1.33498 + 2.25454 17226.5 1 1.33536 + 2.29629 19391.1 1 1.33576 + 2.33962 20924.9 1 1.33617 + 2.38461 22401.4 1 1.3366 + 2.43137 29629.6 1 1.33705 + 2.47999 49670.3 1 1.33753 + 2.53061 63685.8 1 1.33803 + 2.58333 82075.6 1 1.33855 + 2.63829 106342 1 1.33911 + 2.69565 138553 1 1.3397 + 2.75555 181573 1 1.34033 + 2.81817 239402 1 1.341 + 2.88371 317660 1 1.34172 + 2.95237 424316 1 1.34248 + 3.02438 570749 1 1.34331 + 3.09999 773359 1 1.34419 + 3.17948 1.05598e+06 1 1.34515 + 3.26315 1.45361e+06 1 1.3462 + 3.35134 1.92434e+06 1 1.34733 + 3.44444 1.83898e+06 1 1.34858 + 3.54285 1.76087e+06 1 1.34994 + 3.64705 1.68913e+06 1 1.35145 + 3.75757 1.62301e+06 1 1.35312 + 3.87499 1.56187e+06 1 1.35498 + 3.99999 1.50516e+06 1 1.35707 + 4.13332 1.45243e+06 1 1.35943 + 4.27585 1.40327e+06 1 1.36211 + 4.42856 1.35733e+06 1 1.36518 + 4.59258 1.3143e+06 1 1.36872 + 4.76922 1.27392e+06 1 1.37287 + 4.95999 1.23594e+06 1 1.37776 + 5.16665 1.20016e+06 1 1.38362 + 5.39129 1.1664e+06 1 1.39074 + 5.63635 1.13448e+06 1 1.39956 + 5.90475 1.10426e+06 1 1.41075 + 6.19998 1.07562e+06 1 1.42535 +WCSim_Water 2 1.01 16 1 8 1 0.112098 0.887902 + 0 0 20. .001 + 60 + 1.56962 209.845 1 1.32885 + 1.58974 237.614 1 1.32906 + 1.61039 273.854 1 1.32927 + 1.63157 323.138 1 1.32948 + 1.65333 394.052 1 1.3297 + 1.67567 504.843 1 1.32992 + 1.69863 702.3 1 1.33014 + 1.72222 1056 1 1.33037 + 1.74647 1571.82 1 1.3306 + 1.77142 2083.09 1 1.33084 + 1.7971 2519.02 1 1.33109 + 1.82352 2795.22 1 1.33134 + 1.85074 2960.71 1 1.3316 + 1.87878 3170.05 1 1.33186 + 1.90769 3822.47 1 1.33213 + 1.93749 4181.41 1 1.33241 + 1.96825 4456.53 1 1.3327 + 1.99999 4716.75 1 1.33299 + 2.03278 4914.53 1 1.33329 + 2.06666 5841.91 1 1.33361 + 2.10169 9612.64 1 1.33393 + 2.13793 14485 1 1.33427 + 2.17543 18662.3 1 1.33462 + 2.21428 20943.8 1 1.33498 + 2.25454 22934.3 1 1.33536 + 2.29629 27312.4 1 1.33576 + 2.33962 29807.7 1 1.33617 + 2.38461 31607.3 1 1.3366 + 2.43137 39696.8 1 1.33705 + 2.47999 62897 1 1.33753 + 2.53061 85015.4 1 1.33803 + 2.58333 99874.2 1 1.33855 + 2.63829 118785 1 1.33911 + 2.69565 158872 1 1.3397 + 2.75555 198519 1 1.34033 + 2.81817 247670 1 1.341 + 2.88371 307727 1 1.34172 + 2.95237 379484 1 1.34248 + 3.02438 462383 1 1.34331 + 3.09999 553579 1 1.34419 + 3.17948 647135 1 1.34515 + 3.26315 734049 1 1.3462 + 3.35134 803790 1 1.34733 + 3.44444 847270 1 1.34858 + 3.54285 859868 1 1.34994 + 3.64705 842660 1 1.35145 + 3.75757 801255 1 1.35312 + 3.87499 743291 1 1.35498 + 3.99999 676157 1 1.35707 + 4.13332 605744 1 1.35943 + 4.27585 536147 1 1.36211 + 4.42856 469902 1 1.36518 + 4.59258 408400 1 1.36872 + 4.76922 352271 1 1.37287 + 4.95999 301674 1 1.37776 + 5.16665 256494 1 1.38362 + 5.39129 216471 1 1.39074 + 5.63635 181267 1 1.39956 + 5.90475 150515 1 1.41075 + 6.19998 123840 1 1.42535 + //---------------------------------------------------------- // Budimir: these numbers come from nowhere, they are just for test H2O_ESSnuSB -2 1.00794 15.9994 1. 8. 1. 2. 1. @@ -2222,6 +2358,82 @@ STTelectronics -2 28.0855 15.9994 14. 8. 2.20 1 2 // ----------------- end STT +//-------- Super Fgd material Start +hydrogen 1 1.008 1. 0.08988 + 0 1 20. .001 + 0 + +brass 2 63.54 65.38 29. 30. 8.5 0.9 0.1 + 0 0 20. .001 + 0 + +bronze 2 63.54 118.71 29. 50. 8.5 0.6 0.4 + 0 0 20. .001 + 0 + +stainlessSteel 3 12.0107 55.847 58.933 6. 26. 27. 8.0 0.04 0.88 0.08 + 0 0 20. .001 + 0 + +methane 2 12.0107 1.008 6. 1. 0.656e-3 1 4 + 0 0 20. .001 + 0 + +CO2 2 12.0107 15.9994 6. 8. 1.842e-3 1 2 + 0 0 20. .001 + 0 + +CF4 2 12.0107 18.9984 6. 9. 3.66e-3 1 4 + 0 0 20. .001 + 0 + +TiO2 -2 47.867 15.9994 22. 8. 4.26 1 2 + 0 0 20. .001 + 0 + +polystyrene -2 12.01 1.008 6. 1. 1.032 8. 8. + 1 0 20. .001 + 0 + +scintillator -2 12.01 1.008 6. 1. 1.050 8. 8. + 1 0 20. .001 + 0 + +paraterphnyl -2 12.01 1.008 6. 1. 1.240 18. 14. + 1 0 20. .001 + 0 + +podscintillator -2 12.01 1.008 6. 1. 1.051 8. 8. + 1 0 20. .001 + 0 + +polyethylene 2 12.0107 1.008 6. 1. 0.94 1 2 + 0 0 20. .001 + 0 + +poduleEpoxy 3 12.0107 1.008 35.453 6. 1. 17. 1.36 3 3 1 + 0 0 20. .001 + 0 + +polycarbonate 3 12.0107 1.008 15.9994 6. 1. 8. 1.2 0.755751 0.055491 0.188758 + 0 0 20. .001 + 0 + +// NB : chemical composition may not be completely right but close +carbonFiber 2 12.0107 15.9994 6. 8. 1.75 6 1 + 0 0 20. .001 + 0 + +fiberCore -2 12.0107 1.008 6. 1. 1.05 9 10 + 0 0 20. .001 + 0 + +fiberCladding -3 12.0107 1.008 15.9994 6. 1. 8. 1.19 5 8 2 + 0 0 20. .001 + 0 + +//-------- Super Fgd material End + // ----- Caution with putting materials below that line ----- // The next materials must specify additional parameters! @@ -2234,3 +2446,5 @@ vacuum2 1 1.e-16 1.e-16 1.e-16 // ---- end of Panda media ---- //---------------------------------------------------------- + +