8 #ifndef GAR_READOUTSIMULATION_IONIZATIONREADOUT     9 #define GAR_READOUTSIMULATION_IONIZATIONREADOUT    29 #include "cetlib_except/exception.h"    34 #include "nug4/ParticleNavigation/ParticleList.h"    35 #include "nurandom/RandomUtils/NuRandomService.h"    42 #include "Utilities/AssociationUtil.h"    46 #include "CoreUtils/ServiceUtil.h"    85                                    std::vector<edepIDE>                 & edepIDEs);
    87                        std::vector<sdp::EnergyDeposit> 
const& edepCol);
    89                              std::vector<float>                                     & electrons,
    90                              std::set<size_t>                                       & eDepLocs,
    91                              std::deque<float>                                      & eDepWeights,
    92                              std::vector<raw::RawDigit>                             & digCol,
   132       fTime  = gar::providerFrom<detinfo::DetectorClocksServiceGAr>();
   134       fNumTicks = gar::providerFrom<detinfo::DetectorPropertiesService>()->NumberTimeSamples();
   136       fGeo = gar::providerFrom<geo::GeometryGAr>();
   140       produces< std::vector<raw::RawDigit>                      >();
   141       produces< ::art::Assns<sdp::EnergyDeposit, raw::RawDigit, float> >();
   150       if (fullname.empty() || 
stat(fullname.c_str(), &sb)!=0)
   151         throw cet::exception(
"IonizationReadout") << 
"Input pad response function file "   153                           << 
" not found in FW_SEARCH_PATH\n";
   155       TFile 
infile(fullname.c_str(),
"READ");  
   160       fHFILLPRF->SetDirectory(0);
   179       MF_LOG_DEBUG(
"IonizationReadout") << 
"Debug: IonizationReadout()";
   189       auto driftAlgName = driftAlgPars.
get<
std::string>(
"DriftAlgType");
   192       if (driftAlgName.compare(
"Standard") == 0) {
   197           << 
"Unable to determine which electron drift algorithm to use, bail";
   201       auto tpcROAlgName = tpcROAlgPars.
get<
std::string>(
"TPCReadoutSimType");
   203       if (tpcROAlgName.compare(
"Standard") == 0){
   208           << 
"Unable to determine which TPC readout simulation algorithm to use, bail";
   245       std::unique_ptr< std::vector<raw::RawDigit>                      > rdCol (
new std::vector<raw::RawDigit>                     );
   246       std::unique_ptr< ::art::Assns<sdp::EnergyDeposit, raw::RawDigit, float> > erassn(new ::art::Assns<sdp::EnergyDeposit, raw::RawDigit, float>);
   251       if(eDepCol->size() > 0){
   253         std::vector<edepIDE> eDepIDEs;
   258         if (eDepIDEs.size()>0)
   262             unsigned int       prevChan = eDepIDEs.front().Channel;
   263             std::set<size_t>   digitEDepLocs;
   264             std::deque<float>  digitEDepWeights;
   265             std::vector<float> electrons(
fNumTicks, 0.);
   268             for(
auto edide : eDepIDEs){
   271                 << 
"Current eDepIDE channel is "   273                 << 
" previous channel is "   276               if(edide.Channel != prevChan){
   279                   << digitEDepLocs.size()
   282                   << 
" rdCol size is currently "   297                 prevChan = edide.Channel;
   302               size_t esize = electrons.size();
   304                 if (edide.TDC >= esize) {
   305                   electrons[esize - 1] = edide.NumElect;
   307                   electrons[edide.TDC] = edide.NumElect;
   311               for(
auto loc : edide.edepLocs) digitEDepLocs.insert(
loc);
   312               for(
auto w : edide.edepWeights) digitEDepWeights.push_front(
w);
   329               << 
" raw digits from signal";
   349                                                     std::vector<edepIDE>                 & edepIDEs)
   351       auto geo = gar::providerFrom<geo::GeometryGAr>();
   354       unsigned int chan   = 0;
   356       std::vector<edepIDE> edepIDEaccumulator;
   363       for (
size_t e = 0; 
e < edepCol.size(); ++
e) {
   367         fDriftAlg->DriftElectronsToReadout(edepCol[
e], driftInfo);
   379         for (
size_t c = 0; 
c < clusterXPos.size(); ++
c) {
   381           xyz[0] = clusterXPos[
c];
   382           xyz[1] = clusterYPos[
c];
   383           xyz[2] = clusterZPos[
c];
   389           geo->NearestChannelInfo(xyz, cwn);
   396           if (chan == 
geo->GapChannelNumber()) 
continue;
   402           TVector3 
pos = cwn.at(0).pos;
   403           TVector3 pproj(0,xyz[1],xyz[2]);  
   405           std::vector<float> chanweight;
   406           size_t ncdistrib = cwn.size();
   410           MF_LOG_DEBUG(
"IonizationReadout::DriftElectronsToReadout") << 
"pproj: " << pproj.Y() << 
" " << pproj.Z() << 
std::endl;
   411           for (
size_t icd=0; icd<ncdistrib; ++icd) {
   426               throw cet::exception(
"IonizationReadout::DriftElectronsToReadout") << 
"Ununderstood readout chamber type "   427                                 << cwn.at(icd).roctype << 
"\n";
   429             TVector3 dproj = pproj - cwn.at(icd).pos;
   431             MF_LOG_DEBUG(
"IonizationReadout::DriftElectronsToReadout") << 
" Pad loc: " << cwn.at(icd).pos.Y() << 
   434             float dist_along_padrow = dproj.Dot(cwn.at(icd).padrowdir);  
   435             float dist_perp_padrow = (dproj - dist_along_padrow*cwn.at(icd).padrowdir).Mag(); 
   436             MF_LOG_DEBUG(
"IonizationReadout::DriftElectronsToReadout") << 
"along, perp: " << dist_along_padrow << 
   439             dist_along_padrow = TMath::Abs(dist_along_padrow);
   440             if (dist_along_padrow < prfhist->GetXaxis()->GetBinUpEdge(prfhist->GetNbinsX()) &&
   441                 dist_perp_padrow < prfhist->GetYaxis()->GetBinUpEdge(prfhist->GetNbinsY())) {
   442               chanweight.push_back(prfhist->GetBinContent(prfhist->FindBin(dist_along_padrow,dist_perp_padrow)));
   444               chanweight.push_back(0);
   447             sumw += chanweight.back();
   451             throw cet::exception(
"IonizationReadout::DriftElectronsToReadout") << 
   452               "Weight sum is zero, even when including the closest channel " << 
std::endl;
   454           float rsumw = 1.0/sumw;
   455           for (
size_t i=0; i<chanweight.size(); ++i) {
   456             if (chanweight.at(i)>0 && clusterSize.at(
c) > 0) {
   457               edepIDEaccumulator.emplace_back(clusterSize.at(
c)*chanweight.at(i)*rsumw,
   460                                               e, chanweight.at(i));
   463                                                        "DriftElectronsToReadout");
   465               if (edepIDEaccumulator.size() > 10000)
   468                   edepIDEs.insert(edepIDEs.end(),edepIDEaccumulator.begin(),edepIDEaccumulator.end());
   469                   edepIDEaccumulator.clear();
   474           MF_LOG_DEBUG(
"IonizationReadout::DriftElectronsToReadout")
   488       edepIDEs.insert(edepIDEs.end(),edepIDEaccumulator.begin(),edepIDEaccumulator.end());
   496                                         std::vector<sdp::EnergyDeposit> 
const& edepCol) {
   501         << 
" energy deposits";
   503       if (edepIDEs.size()==0) 
return;
   505       std::vector<edepIDE> 
temp;
   509       std::sort(edepIDEs.begin(), edepIDEs.end());
   511       for(
auto itr : edepIDEs){
   512         for(
auto edloc : itr.edepLocs) {
   515                                                                                            "CombineIDEsAfterSort");
   519       edepIDE prev = edepIDEs.front();
   527       for (
size_t e = 1; 
e < edepIDEs.size(); ++
e) {
   531           << 
"current edepIDE: "   538           << cur.edepLocs.size();
   542             << 
"storing edepIDE sum: "   549             << sum.edepLocs.size();
   552                 for (
auto edloc : sum.edepLocs) {
   568                 << 
"summing current edepIDE";
   581         << 
" energy deposits";
   588                                               std::vector<float>                                     & electrons,
   589                                               std::set<size_t>                                       & eDepLocs,
   590                                               std::deque<float>                                      & eDepWeights,
   591                                               std::vector<raw::RawDigit>                             & digCol,
   603         digCol.emplace_back(tmpdigit);
   608           << 
" energy deposits to digit for channel "   613         for (
auto ed : eDepLocs) {
   618             << 
"Making association: " << digCol.size() << 
" " << ptr << 
std::endl;
   648         MF_LOG_DEBUG(
"IonizationReadout::CheckChannelToEnergyDepositMapping")
   653           << 
" is off from the energy deposit: ("   675 #endif // GAR_READOUTSIMULATION_IONIZATIONREADOUT 
std::vector< gar::geo::ChanWithPos > ChanWithNeighbors
TH2F * fIOROCPRF
pad response function for IOROC 
base_engine_t & createEngine(seed_t seed)
bool fCheckChan
flag to check mapping of energy deposits to channels 
std::vector< double > const & ClusterZPos() const 
std::vector< double > const & ClusterYPos() const 
TH2F * fHFILLPRF
pad response function for hole-filler chamber 
EDProducer(fhicl::ParameterSet const &pset)
const gar::detinfo::DetectorClocks * fTime
electronics clock 
std::unique_ptr< TPCReadoutSimAlg > fROSimAlg
algorithm to simulate the electronics 
Description of geometry of one entire detector. 
void DriftElectronsToReadout(std::vector< sdp::EnergyDeposit > const &edepCol, std::vector< edepIDE > &edepIDEs)
std::vector< double > const & ClusterXPos() const 
void produce(::art::Event &evt)
double TickPeriod() const 
A single tick period in nano-second, frequency is in MHz. 
fhicl::ParameterSet fISCalcPars
parameter set for the IS calculator 
void beginRun(::art::Run &run)
#define DEFINE_ART_MODULE(klass)                                                                                          
bool CreateAssnD(PRODUCER const &prod, art::Event &evt, art::Assns< T, U, D > &assn, size_t first_index, size_t second_index, typename art::Assns< T, U, D >::data_t &&data)
Creates a single one-to-one association with associated data. 
virtual double G4ToElecTime(double g4_time) const  =0
Given Geant4 time [ns], returns relative time [ns] w.r.t. electronics time T0. 
T get(std::string const &key) const 
Runs Readout simulation including propagation of electrons and photons to readout. 
bool fUsePRF
switch to turn on PRF modeling, otherwise just use the arrival pad 
IonizationReadout(fhicl::ParameterSet const &pset)
Standard constructor and destructor for an FMWK module. 
std::string fPRFFileName
where to find the pad response function histograms 
ValidHandle< PROD > getValidHandle(InputTag const &tag) const 
std::string fG4Label
label of G4 module 
ProductID put(std::unique_ptr< PROD > &&edp, std::string const &instance={})
static IonizationAndScintillation * CreateInstance(CLHEP::HepRandomEngine &engine, fhicl::ParameterSet const &pset)
virtual double TPCG4Time2TDC(double g4time) const  =0
Given G4 time [ns], returns corresponding TPC electronics clock count [tdc]. 
size_t fNumTicks
number of TDC samples 
const gar::geo::GeometryCore * fGeo
geometry information 
void CombineIDEs(std::vector< edepIDE > &edepIDEs, std::vector< sdp::EnergyDeposit > const &edepCol)
virtual ~IonizationReadout()
General GArSoft Utilities. 
void CheckChannelToEnergyDepositMapping(unsigned int const &channel, sdp::EnergyDeposit const &edep, std::string const &id)
TH2F * fOOROCPRF
pad response function for OOROC 
std::unique_ptr< ElectronDriftAlg > fDriftAlg
algorithm to drift ionization electrons 
virtual const ElecClock & TPCClock() const  =0
Borrow a const TPC clock with time set to Trigger time [ns]. 
std::vector< double > const & ClusterTime() const 
TH2F * fIROCPRF
pad response function for IROC 
CLHEP::HepRandomEngine & fEngine
random engine 
LArSoft geometry interface. 
art framework interface to geometry description 
void ChannelToPosition(unsigned int const channel, float *const worldLoc) const 
static ServiceHandle< RandomNumberGenerator > & rng()
std::vector< int > const & ClusterSize() const 
Collection of charge vs time digitized from a single readout channel. 
cet::coded_exception< error, detail::translate > exception
QTextStream & endl(QTextStream &s)
void reconfigure(fhicl::ParameterSet const &pset)
void CreateSignalDigit(unsigned int const &channel, std::vector< float > &electrons, std::set< size_t > &eDepLocs, std::deque< float > &eDepWeights, std::vector< raw::RawDigit > &digCol,::art::ValidHandle< std::vector< sdp::EnergyDeposit > > &eDepCol,::art::Assns< sdp::EnergyDeposit, raw::RawDigit, float > &erassn,::art::Event &evt)