4 #include <marlin/Global.h> 
    5 #include <marlin/Exceptions.h> 
    6 #include <EVENT/LCCollection.h> 
    7 #include <IMPL/LCCollectionVec.h> 
    8 #include <IMPL/CalorimeterHitImpl.h> 
    9 #include <IMPL/LCRelationImpl.h> 
   10 #include <CalorimeterHitType.h> 
   11 #include <EVENT/LCParameters.h> 
   12 #include <UTIL/CellIDDecoder.h> 
   13 #include <marlin/ProcessorEventSeeder.h> 
   21 #include "CLHEP/Random/Random.h" 
   22 #include "CLHEP/Random/RandGauss.h" 
   23 #include "CLHEP/Random/RandFlat.h" 
   24 #include "CLHEP/Units/PhysicalConstants.h" 
   26 #define RELATIONFROMTYPESTR "FromType" 
   27 #define RELATIONTOTYPESTR "ToType" 
   30 using namespace lcio ;
 
   31 using namespace marlin ;
 
   32 using namespace std::placeholders;
 
   41   _description = 
"Performs digitization of sim calo hits. Virtual class." ;
 
   44   std::vector<std::string> inputCollections;
 
   45   inputCollections.push_back(
"SimCalorimeterHits");
 
   47   registerInputCollections( LCIO::SIMCALORIMETERHIT,
 
   48                             "inputHitCollections" ,
 
   49                             "input simcalhit Collection Names" ,
 
   55   std::vector<std::string>  outputCollections;
 
   56   registerProcessorParameter( 
"outputHitCollections",
 
   57                   "output calorimeterhit Collection Names" ,
 
   62   std::vector<std::string>  outputRelCollections;
 
   63   registerProcessorParameter( 
"outputRelationCollections",
 
   64                   "output hit relatiob Collection Names" ,
 
   66                   outputRelCollections );
 
   69   registerProcessorParameter(
"threshold" ,
 
   74   registerProcessorParameter(
"thresholdUnit" ,
 
   75                              "Unit for threshold. Can be \"GeV\", \"MIP\" or \"px\". MIP and px need properly set calibration constants" ,
 
   80   registerProcessorParameter(
"timingCut" ,
 
   85   registerProcessorParameter(
"timingCorrectForPropagation" ,
 
   86                              "Correct hit times for propagation: radial distance/c" ,
 
   90   registerProcessorParameter(
"timingWindowMin" ,
 
   91                              "Time Window minimum time in ns" ,
 
   95   registerProcessorParameter(
"timingWindowMax" ,
 
   96                              "Time Window maximum time in ns" ,
 
  100   registerProcessorParameter(
"integrationMethod" ,
 
  101                              "Energy integration and time calculation method. Options: Standard, ROC" ,
 
  103                              std::string(
"Standard"));
 
  105   registerProcessorParameter(
"fastShaper" ,
 
  106                              "Fast shaper value. Unit in ns" ,
 
  110   registerProcessorParameter(
"slowShaper" ,
 
  111                              "Slow shaper value. Unit in ns" ,
 
  115   registerProcessorParameter(
"timingResolution" ,
 
  116                              "Time resolution to apply (gaussian smearing). Unit in ns" ,
 
  123   registerProcessorParameter(
"calibration_mip" ,
 
  124                              "average G4 deposited energy by MIP for calibration" ,
 
  128   registerProcessorParameter(
"miscalibration_uncorrel" ,
 
  129                              "uncorrelated random gaussian miscalibration (as a fraction: 1.0 = 100%) " ,
 
  133   registerProcessorParameter(
"miscalibration_uncorrel_memorise" ,
 
  134                              "store oncorrelated miscalbrations in memory? (i.e. use same miscalibrations in each event. WARNING: can take a lot of memory if used...) " ,
 
  138   registerProcessorParameter(
"miscalibration_correl" ,
 
  139                              "correlated random gaussian miscalibration (as a fraction: 1.0 = 100%) " ,
 
  143   registerProcessorParameter(
"deadCell_fraction" ,
 
  144                              "random dead cell fraction (as a fraction: 0->1) " ,
 
  148   registerProcessorParameter(
"deadCell_memorise" ,
 
  149                              "store dead cells in memory? (i.e. use same dead cells in each event. WARNING: can take a lot of memory if used...) " ,
 
  154   registerProcessorParameter(
"elec_noise_mip",
 
  155                              "typical electronics noise (in MIP units)",
 
  159   registerProcessorParameter(
"elec_range_mip",
 
  160                              "maximum of dynamic range of electronics (in MIPs)",
 
  165   registerProcessorParameter(
"CellIDLayerString" ,
 
  166                              "name of the part of the cellID that holds the layer" , 
 
  201     streamlog_out(ERROR) << 
"could not identify threshold unit. Please use \"GeV\", \"MIP\" or \"px\"! Aborting." << std::endl;
 
  202     marlin::StopProcessingException(
this);
 
  209   std::map<std::string, integr_function> integrations = {
 
  214   if(integrations.end() == findIter) {
 
  215     streamlog_out(ERROR) << 
"Could not guess timing calculation method!" << std::endl;
 
  216     streamlog_out(ERROR) << 
"Available are: Standard, ROC. Provided: " << 
_integration_method << std::endl;
 
  217     streamlog_out(ERROR) << 
"Aborting..." << std::endl;
 
  218     marlin::StopProcessingException(
this);
 
  224     if(!parameterSet(
"fastShaper") || !parameterSet(
"slowShaper")) {
 
  225       streamlog_out(ERROR) << 
"Fast/slow shaper parameter(s) not set. Required for ROC integration!" << std::endl;
 
  226       streamlog_out(ERROR) << 
"Aborting..." << std::endl;
 
  227       marlin::StopProcessingException(
this);
 
  231   _flag.setBit(LCIO::CHBIT_LONG);
 
  232   _flag.setBit(LCIO::RCHBIT_TIME); 
 
  236   marlin::Global::EVENTSEEDER->registerProcessor(
this);
 
  246   CLHEP::HepRandom::setTheSeed( marlin::Global::EVENTSEEDER->getSeed(
this) );
 
  257     streamlog_out ( DEBUG1 ) << 
"looking for collection: " << colName << endl;
 
  259       LCCollection * col = evt->getCollection( colName.c_str() ) ;
 
  260       string initString = col->getParameters().getStringVal(LCIO::CellIDEncoding);
 
  261       CHT::CaloType cht_type = caloTypeFromString(colName);
 
  262       CHT::CaloID   cht_id   = caloIDFromString(colName);
 
  263       CHT::Layout   cht_lay  = layoutFromString(colName);
 
  265       CellIDDecoder<SimCalorimeterHit> idDecoder( col );
 
  267       int numElements = col->getNumberOfElements();
 
  268       streamlog_out ( DEBUG1 ) << colName << 
" number of elements = " << numElements << endl;
 
  270       if ( numElements==0 ) 
continue;
 
  274       newcol->setFlag(
_flag.getFlag());
 
  283       for (
int j=0; j < numElements; ++j) {
 
  284         SimCalorimeterHit * simhit = 
dynamic_cast<SimCalorimeterHit*
>( col->getElementAt( j ) ) ;
 
  287         auto integrationResult = 
Integrate(simhit);
 
  288         if( ! integrationResult.has_value() ) {
 
  291         float time      = integrationResult.value().first;
 
  292         float energyDep = integrationResult.value().second;
 
  294         float energyDig = 
EnergyDigi(energyDep, simhit->getCellID0() , simhit->getCellID1() );
 
  297           CalorimeterHitImpl* newhit = 
new CalorimeterHitImpl();
 
  298           newhit->setCellID0( simhit->getCellID0() );
 
  299           newhit->setCellID1( simhit->getCellID1() );
 
  300           newhit->setTime( time );
 
  301           newhit->setPosition( simhit->getPosition() );
 
  302             newhit->setEnergy( energyDig );
 
  304             newhit->setType( CHT( cht_type, cht_id, cht_lay, layer ) );
 
  305           newhit->setRawHit( simhit );
 
  306           newcol->addElement( newhit ); 
 
  308             streamlog_out ( DEBUG1 ) << 
"orig/new hit energy: " << simhit->getEnergy() << 
" " << newhit->getEnergy() << endl;
 
  310           LCRelationImpl *rel = 
new LCRelationImpl(newhit,simhit,1.0);
 
  311           relcol->addElement( rel );
 
  317       newcol->parameters().setValue(LCIO::CellIDEncoding,initString);
 
  323     } 
catch(DataNotAvailableException &
e){
 
  324       streamlog_out(DEBUG1) << 
"could not find input collection " << colName << std::endl;
 
  367       std::pair <int, int> id(id0, id1);
 
  392       std::pair <int, int> id(id0, id1);
 
  400         if (thisDead == 
true){
 
  416   float timeCorrection(0);
 
  419     for (
int i=0; i<3; i++) 
 
  420       r+=pow(hit->getPosition()[i],2); 
 
  421     timeCorrection = sqrt(r)/CLHEP::c_light; 
 
  427   float earliestTime=std::numeric_limits<float>::max();
 
  428   for(
int i = 0; i<hit->getNMCContributions(); i++){ 
 
  429     float timei   = hit->getTimeCont(i); 
 
  430     float energyi = hit->getEnergyCont(i); 
 
  431     float relativetime = timei - timeCorrection; 
 
  433       energySum += energyi;
 
  434       if (relativetime<earliestTime){
 
  435            earliestTime = relativetime; 
 
  448   const unsigned int ncontrib = hit->getNMCContributions() ;
 
  450   std::vector<MCC> mcconts{ncontrib};
 
  451   for(
unsigned int i = 0; i<ncontrib; i++){
 
  452     mcconts[i].energy = hit->getEnergyCont(i);
 
  453     mcconts[i].time = hit->getTimeCont(i);
 
  455   std::sort(mcconts.begin(), mcconts.end(), [](
auto lhs, 
auto rhs){
 
  456     return (lhs.time < rhs.time);
 
  460   bool passThreshold = 
false;
 
  461   float epar=0.f, hitTime=0.f;
 
  462   unsigned int thresholdIndex=0;
 
  465   for(
unsigned int i=0; i<ncontrib ; ++i) {
 
  466     const auto timei = mcconts[i].time;
 
  469     for(
unsigned int j=i; j<ncontrib ; ++j) {
 
  470       const auto timej = mcconts[j].time;
 
  472         epar += mcconts[j].energy;
 
  479         passThreshold = true ;
 
  488   const float thresholdTime = mcconts[thresholdIndex].time;
 
  495     float energySum = 0.f ; 
 
  496     for(
unsigned int i=thresholdIndex ; i<ncontrib ; ++i) {
 
  498         energySum += mcconts[i].energy;
 
std::map< std::pair< int, int >, bool > _cell_dead
 
virtual float EnergyDigi(float energy, int id0, int id1)
 
integr_function _integr_function
 
virtual integr_res_opt Integrate(const SimCalorimeterHit *hit) const 
 
bool _misCalib_uncorrel_keep
 
#define RELATIONTOTYPESTR
 
virtual float digitiseDetectorEnergy(float energy) const =0
 
std::string _integration_method
 
std::string _cellIDLayerString
 
virtual float convertEnergy(float energy, int inScale) const =0
 
int _time_correctForPropagation
 
std::vector< std::string > _outputCollections
 
float _event_correl_miscalib
 
std::map< std::pair< int, int >, float > _cell_miscalibs
 
float SmearTime(float time) const 
 
integr_res_opt StandardIntegration(const SimCalorimeterHit *hit) const 
 
std::vector< std::string > _outputRelCollections
 
virtual void processRunHeader(LCRunHeader *run)
 
std::string _threshold_unit
 
std::optional< integr_res > integr_res_opt
 
virtual void check(LCEvent *evt)
 
std::vector< LCCollection * > LCCollectionVec
 
integr_res_opt ROCIntegration(const SimCalorimeterHit *hit) const 
 
std::vector< std::string > _inputCollections
 
virtual void processEvent(LCEvent *evt)
 
#define RELATIONFROMTYPESTR
 
std::pair< float, float > integr_res