diff --git a/UserTools/AssignBunchTimingMC/AssignBunchTimingMC.cpp b/UserTools/AssignBunchTimingMC/AssignBunchTimingMC.cpp index a821d6685..c34aa7b75 100644 --- a/UserTools/AssignBunchTimingMC/AssignBunchTimingMC.cpp +++ b/UserTools/AssignBunchTimingMC/AssignBunchTimingMC.cpp @@ -99,16 +99,6 @@ bool AssignBunchTimingMC::Execute() std::cout << "AssignBunchTimingMC: Executing tool..." << std::endl; } - // An upstream tool may opt to skip this execution stage - // For example the PMTWaveformSim tool will skip events with no MCHits or if - // no waveforms are produced. - bool skip = false; - bool got_skip_status = m_data->Stores["ANNIEEvent"]->Get("SkipExecute", skip); - if (got_skip_status && skip) { - Log("AssignBunchTimingMC: An upstream tool told me to skip this event.",v_warning,verbosity); - return true; - } - if (!LoadStores()) // Load info from store return false; if (verbosity >= v_debug) { diff --git a/UserTools/ClusterClassifiers/ClusterClassifiers.cpp b/UserTools/ClusterClassifiers/ClusterClassifiers.cpp index 3480e8cea..939d2dbef 100644 --- a/UserTools/ClusterClassifiers/ClusterClassifiers.cpp +++ b/UserTools/ClusterClassifiers/ClusterClassifiers.cpp @@ -35,15 +35,6 @@ bool ClusterClassifiers::Initialise(std::string configfile, DataModel &data){ bool ClusterClassifiers::Execute(){ - //We're gonna make ourselves a couple cluster classifier maps boyeeee - bool skip = false; - bool goodSkipStatus = m_data->Stores.at("ANNIEEvent")->Get("SkipExecute", skip); - if (goodSkipStatus && skip) { - logmessage = "ClusterClassifier: An upstream tool told me to skip this event."; - Log(logmessage, v_warning, verbosity); - return true; - } - if(verbosity>4) std::cout << "ClusterClassifiers tool: Accessing cluster map in CStore" << std::endl; bool get_clusters = false; m_data->CStore.Get("ClusterMap",m_all_clusters); diff --git a/UserTools/ClusterFinder/ClusterFinder.cpp b/UserTools/ClusterFinder/ClusterFinder.cpp index de16c4b23..3d90cf910 100644 --- a/UserTools/ClusterFinder/ClusterFinder.cpp +++ b/UserTools/ClusterFinder/ClusterFinder.cpp @@ -165,16 +165,6 @@ bool ClusterFinder::Execute(){ //---------------------------------------------------------------------------- //---------------get the members of the ANNIEEvent---------------------------- //---------------------------------------------------------------------------- - - // An upstream tool may opt to skip this execution stage - // For example the PMTWaveformSim tool will skip events with no MCHits or if - // no waveforms are produced. - bool skip = false; - bool got_skip_status = m_data->Stores["ANNIEEvent"]->Get("SkipExecute", skip); - if (got_skip_status && skip) { - Log("ClusterFinder: An upstream tool told me to skip this event.",v_warning,verbose); - return true; - } m_data->Stores["ANNIEEvent"]->Get("EventNumber", evnum); //m_data->Stores["ANNIEEvent"]->Get("BeamStatus", BeamStatus); diff --git a/UserTools/PMTWaveformSim/PMTWaveformSim.cpp b/UserTools/PMTWaveformSim/PMTWaveformSim.cpp index d5789e354..0f1a4f804 100644 --- a/UserTools/PMTWaveformSim/PMTWaveformSim.cpp +++ b/UserTools/PMTWaveformSim/PMTWaveformSim.cpp @@ -97,11 +97,51 @@ bool PMTWaveformSim::Execute() { int load_status = LoadFromStores(); - + if (load_status == 0) return false; + // The container for the data that we'll put into the ANNIEEvent std::map> > RawADCDataMC; std::map> > CalADCDataMC; + + // If MCHits is empty (load_status == 2), create one minimal baseline waveform so that the hit finder doesn't freak out + // while keeping the rest of the machinery the same + if (load_status == 2) { + logmessage = "PMTWaveformSim: Creating single minimal baseline waveform (No MCHits)..."; + Log(logmessage, v_message, verbosity); + + // we can put the dummy baseline in a dead PMT channel so it won't be integrated + unsigned long dummy_chankey = 333; // PMT ID 333 is dead + + // create a short baseline waveform (~50ns) so that the hit finder will be satisfied + int num_samples = 25; // 50ns + double noiseSigma = fRandom.Gaus(1, 0.01); // set the noise to basically 0 + int baseline = fRandom.Uniform(300, 350); + + std::vector rawSamples; + std::vector calSamples; + + for (int i = 0; i < num_samples; i++) { + double noise = fRandom.Gaus(0, noiseSigma); + int sample = std::round(noise + baseline); + sample = (sample > 4095) ? 4095 : ((sample < 0) ? 0 : sample); // shouldn't matter + + rawSamples.push_back(sample); + calSamples.push_back((sample - baseline) * ADC_TO_VOLT); + } + + std::vector> rawWaveforms; + std::vector> calWaveforms; + + rawWaveforms.emplace_back(0, rawSamples); + calWaveforms.emplace_back(0, calSamples, baseline, noiseSigma); + + RawADCDataMC.emplace(dummy_chankey, rawWaveforms); + CalADCDataMC.emplace(dummy_chankey, calWaveforms); + + } + + // normal use case (no blank MCHits) for (auto mcHitsIt : *fMCHits) { // Loop over the hit PMTs int PMTID = mcHitsIt.first; @@ -177,22 +217,14 @@ bool PMTWaveformSim::Execute() CalADCDataMC.emplace(PMTID, calWaveforms); }// end loop over PMTs + // Publish the waveforms to the ANNIEEvent store if we have them - if (RawADCDataMC.size()) { - m_data->Stores.at("ANNIEEvent")->Set("RawADCDataMC", RawADCDataMC); - m_data->Stores.at("ANNIEEvent")->Set("CalibratedADCData", CalADCDataMC); - } else { - logmessage = "PMTWaveformSim: No waveforms produced. Skipping!"; - Log(logmessage, v_warning, verbosity); - m_data->Stores.at("ANNIEEvent")->Set("SkipExecute", true); - return true; - } - + m_data->Stores.at("ANNIEEvent")->Set("RawADCDataMC", RawADCDataMC); + m_data->Stores.at("ANNIEEvent")->Set("CalibratedADCData", CalADCDataMC); if (fDebug) FillDebugGraphs(RawADCDataMC); - m_data->Stores.at("ANNIEEvent")->Set("SkipExecute", false); return true; } @@ -460,7 +492,7 @@ int PMTWaveformSim::LoadFromStores() } if (fMCHits->empty()) { - logmessage = "PMTWaveformSim: The MCHits map is empty! Skipping!"; + logmessage = "PMTWaveformSim: The MCHits map is empty! Will fill a single PMT with a minimal waveform."; Log(logmessage, v_warning, verbosity); return 2; } diff --git a/UserTools/PMTWaveformSim/README.md b/UserTools/PMTWaveformSim/README.md index a31230d80..09dd5b692 100644 --- a/UserTools/PMTWaveformSim/README.md +++ b/UserTools/PMTWaveformSim/README.md @@ -35,3 +35,6 @@ MakeDebugFile 0 # Produce a root file containing all the simulated waveforms ## Other notes #### CAUTION: In line 90, the RNG seed is set in Initialization based on the clock time. If any other downstream tools are also setting a random seed, there may be unexpected behavior as a result of this tool. + +For events with no MCHits (and hence no waveforms to simulate) a "dummy" waveform is simulated in one of the dead PMT channels (333). The dummy waveform is very short (50ns) and samples from a noise distribution lower than normal, as to not have any hits register in the hit finder (the hit finder will skip dead PMTs anyways). Passing at least one waveform to the hit finding tools prevents crashing. **IF** that PMT is ever repaired or comes back online, please move this dummy channel to a different offline channel. + diff --git a/UserTools/PhaseIIADCHitFinder/PhaseIIADCHitFinder.cpp b/UserTools/PhaseIIADCHitFinder/PhaseIIADCHitFinder.cpp index 761e22ddf..f1a48b62d 100755 --- a/UserTools/PhaseIIADCHitFinder/PhaseIIADCHitFinder.cpp +++ b/UserTools/PhaseIIADCHitFinder/PhaseIIADCHitFinder.cpp @@ -140,20 +140,6 @@ bool PhaseIIADCHitFinder::Execute() { if (mc_waveforms) { got_raw_data = annie_event->Get("RawADCDataMC", raw_waveform_map); - - // Some executes are skipped if there are no MCHits or waveforms produced - // Put the cleared maps into the ANNIEEvent to ensure that a downstream - // tool doesn't grab a map from a previous event - bool skip = false; - bool got_skip_status = annie_event->Get("SkipExecute", skip); - if (got_skip_status && skip) { - Log("PhaseIIADCHitFinder: An upstream tool told me to skip this event.",v_warning,verbosity); - - m_data->Stores.at("ANNIEEvent")->Set("RecoADCHits", pulse_map); - m_data->Stores.at("ANNIEEvent")->Set("RecoADCAuxHits", aux_pulse_map); - - return true; - } }// end if mc_waveforms } @@ -168,7 +154,7 @@ bool PhaseIIADCHitFinder::Execute() { verbosity); return false; } - else if ( raw_waveform_map.empty() ) { + else if ( raw_waveform_map.empty() && !mc_waveforms ) { Log("Error: The PhaseIIADCHitFinder tool found an empty RawADCData entry", v_error, verbosity); return false; @@ -197,7 +183,7 @@ bool PhaseIIADCHitFinder::Execute() { " entry", v_error, verbosity); return false; } - else if ( calibrated_waveform_map.empty() ) { + else if ( calibrated_waveform_map.empty() && !mc_waveforms ) { Log("Error: The PhaseIIADCHitFinder tool found an empty CalibratedADCData entry", v_error, verbosity); return false; diff --git a/UserTools/PhaseIITreeMaker/PhaseIITreeMaker.cpp b/UserTools/PhaseIITreeMaker/PhaseIITreeMaker.cpp index 573b64c24..d952cd04f 100644 --- a/UserTools/PhaseIITreeMaker/PhaseIITreeMaker.cpp +++ b/UserTools/PhaseIITreeMaker/PhaseIITreeMaker.cpp @@ -526,16 +526,6 @@ bool PhaseIITreeMaker::Execute(){ // Reset variables this->ResetVariables(); // Get a pointer to the ANNIEEvent Store - - // An upstream tool may opt to skip this execution stage - // For example the PMTWaveformSim tool will skip events with no MCHits or if - // no waveforms are produced. - bool skip = false; - bool got_skip_status = m_data->Stores["ANNIEEvent"]->Get("SkipExecute", skip); - if (got_skip_status && skip) { - Log("PhaseIITreeMaker: An upstream tool told me to skip this event.",v_warning,verbosity); - return true; - } // If only clean events are built, return true for dirty events if(fillCleanEventsOnly){