diff --git a/CRVResponse/CMakeLists.txt b/CRVResponse/CMakeLists.txt index a7ce7b1c07..e2b669a3ff 100644 --- a/CRVResponse/CMakeLists.txt +++ b/CRVResponse/CMakeLists.txt @@ -66,6 +66,7 @@ cet_build_plugin(CrvPlot art::module Offline::CRVConditions Offline::DataProducts Offline::GeometryService + Offline::GlobalConstantsService Offline::MCDataProducts Offline::ProditionsService Offline::RecoDataProducts diff --git a/CRVResponse/src/CrvPhotonGenerator_module.cc b/CRVResponse/src/CrvPhotonGenerator_module.cc index fee11ffdf0..7eb0529f0e 100644 --- a/CRVResponse/src/CrvPhotonGenerator_module.cc +++ b/CRVResponse/src/CrvPhotonGenerator_module.cc @@ -198,7 +198,10 @@ namespace mu2e bool tableLoaded=false; for(size_t j=0; j crvRecoPulseCollection; event.getByLabel(_crvRecoPulsesModuleLabel,"",crvRecoPulseCollection); + // any of these products can legitimately be absent from a file whose intermediate CRV + // collections were dropped, so say which one is missing instead of dereferencing an + // invalid handle (CrvMCHelper.cc and CrvCoincidenceClusterMatchMC_module.cc guard the same way) + if(!crvPhotonsCollection.isValid()) + throw cet::exception("SIM")<<"mu2e::CrvPlot: no CrvPhotonsCollection with label "<<_crvPhotonsModuleLabel< CRS; @@ -233,8 +246,10 @@ namespace mu2e //waveforms std::vector > ADCs[4]; //there can be multiple disconnected ADC waveforms per SiPM std::vector > times[4]; - double scale[4]={NAN}; - double maxADC[4]={NAN}; + // NB: `double x[4]={NAN};` would set only element 0 to NAN and value-initialize 1-3 to 0.0, + // which silently defeats the isnan() "no digis" guard below for SiPMs 1-3 + double scale[4]={NAN,NAN,NAN,NAN}; + double maxADC[4]={NAN,NAN,NAN,NAN}; CrvDigiCollection::const_iterator digis; for(digis=crvDigiCollection->begin(); digis!=crvDigiCollection->end(); ++digis) { diff --git a/CRVResponse/src/CrvWidebandTest_module.cc b/CRVResponse/src/CrvWidebandTest_module.cc index 171ce092cb..87a5532823 100644 --- a/CRVResponse/src/CrvWidebandTest_module.cc +++ b/CRVResponse/src/CrvWidebandTest_module.cc @@ -241,8 +241,23 @@ namespace mu2e CrvWidebandTest::~CrvWidebandTest() { delete[] _recoPEs; + delete[] _recoTime; + delete[] _fitStatus; delete[] _depositedEnergy; delete[] _coincidencePDGid; + delete[] _coincidenceTime; + delete[] _coincidencePosX; + delete[] _coincidencePosY; + delete[] _coincidencePosZ; + delete[] _trackSlope; + delete[] _trackIntercept; + delete[] _trackPoints; + delete[] _trackPEs; + delete[] _trackChi2; + delete[] _summaryPEs; + delete[] _summaryFWHMs; + delete[] _summarySignals; + delete[] _summaryChi2s; } void CrvWidebandTest::beginJob() @@ -396,6 +411,15 @@ namespace mu2e //fits for the entire stack of modules/sectors (sectorType=0) and for individual modules/sectors (sectorType=1,...) for(int iSectorType=0; iSectorType<_nSectorTypes; ++iSectorType) { + //reset the per-event track variables for EVERY sector type, including the trigger sectors + //skipped below: these arrays are branched into the tree at dimension _nSectorTypes and are + //filled every event, so an un-reset trigger-sector entry would persist whatever new[] left there + _trackSlope[iSectorType] =0; + _trackIntercept[iSectorType]=0; + _trackPEs[iSectorType] =0; + _trackPoints[iSectorType] =0; + _trackChi2[iSectorType] =-1; + if(std::find(_triggerSectorTypes.begin(),_triggerSectorTypes.end(), iSectorType) != _triggerSectorTypes.end()) continue; //initialize track variables @@ -403,11 +427,6 @@ namespace mu2e float sumY =0; float sumXY =0; float sumYY =0; - _trackSlope[iSectorType] =0; - _trackIntercept[iSectorType]=0; - _trackPEs[iSectorType] =0; - _trackPoints[iSectorType] =0; - _trackChi2[iSectorType] =-1; double counterWidth = counters.at(0)->getBarDetail().getHalfWidth()*2.0; int widthDirection = counters.at(0)->getBarDetail().getWidthDirection(); //assumes that all counters are oriented in the same way diff --git a/CRVResponse/src/MakeCrvDigis.cc b/CRVResponse/src/MakeCrvDigis.cc index daaf467dc4..567e7cb407 100644 --- a/CRVResponse/src/MakeCrvDigis.cc +++ b/CRVResponse/src/MakeCrvDigis.cc @@ -9,10 +9,12 @@ void MakeCrvDigis::SetWaveform(const std::vector &waveform, double ADCco _ADCs.resize(waveform.size()); for(size_t i=0; i(waveform[i]*ADCconversionFactor+pedestal+0.5); - if(ADCmaxADC) ADC=maxADC; - _ADCs.at(i)=ADC; + // clamp before narrowing: an extreme sample cast to int16_t first would wrap around and + // land back inside [minADC,maxADC], so the saturation clamp would never see it + double ADCd = waveform[i]*ADCconversionFactor+pedestal+0.5; + if(ADCdmaxADC) ADCd=maxADC; + _ADCs.at(i)=static_cast(ADCd); } int TDCtmp=lrint(startTime/digitizationPrecision); diff --git a/CRVResponse/src/MakeCrvPhotons.cc b/CRVResponse/src/MakeCrvPhotons.cc index cbf4e18027..bf1d7fcfd2 100644 --- a/CRVResponse/src/MakeCrvPhotons.cc +++ b/CRVResponse/src/MakeCrvPhotons.cc @@ -275,6 +275,10 @@ void LookupBin::Read(std::ifstream &lookupfile, const unsigned int &i) for(unsigned int i=0; i0) std::cout<<"Done."< MakeCrvSiPMCharges::FindFiberPhotonsPixelId() { double x,y; _photonMap->GetRandom2(x,y); - return std::pair(lrint(x),lrint(y)); + // GetRandom2 samples the full width of the outermost bin, so lrint can return _nPixelsX/Y, + // one past the last pixel; that phantom pixel would carry its own discharge state + int ix=std::min(std::max(static_cast(lrint(x)),0),_nPixelsX-1); + int iy=std::min(std::max(static_cast(lrint(y)),0),_nPixelsY-1); + return std::pair(ix,iy); } bool MakeCrvSiPMCharges::IsInactivePixelId(const std::pair &pixelId) diff --git a/CRVResponse/src/MakeCrvWaveforms.cc b/CRVResponse/src/MakeCrvWaveforms.cc index 1e05466b83..a5bbd82e26 100644 --- a/CRVResponse/src/MakeCrvWaveforms.cc +++ b/CRVResponse/src/MakeCrvWaveforms.cc @@ -48,6 +48,8 @@ void MakeCrvWaveforms::LoadSinglePEWaveform(const std::string &filename, double } f.close(); + if(_singlePEWaveform.empty()) + throw std::logic_error("Could not read any single PE waveform points from "+filename); _singlePEMaxVoltage = *std::max_element(_singlePEWaveform.begin(), _singlePEWaveform.end()); }