18 #include "art/Framework/Core/EDProducer.h"
19 #include "art/Framework/Core/ModuleMacros.h"
20 #include "art/Framework/Principal/Event.h"
21 #include "art/Framework/Principal/Handle.h"
22 #include "art/Framework/Principal/Run.h"
23 #include "art/Framework/Principal/SubRun.h"
24 #include "canvas/Utilities/InputTag.h"
25 #include "fhiclcpp/ParameterSet.h"
26 #include "messagefacility/MessageLogger/MessageLogger.h"
27 #include "art_root_io/TFileService.h"
30 #include "sbndaq-artdaq-core/Overlays/Common/CAENV1730Fragment.hh"
31 #include "sbndaq-artdaq-core/Overlays/FragmentType.hh"
32 #include "artdaq-core/Data/Fragment.hh"
47 #include "nurandom/RandomUtils/NuRandomService.h"
48 #include "CLHEP/Random/RandFlat.h"
76 void produce(art::Event&
e)
override;
107 art::ServiceHandle<art::TFileService>
tfs;
117 fInputModuleNameWvfm(
p.get<std::string>(
"InputModuleNameWvfm")),
118 fInputModuleNameTrigger(
p.get<std::string>(
"InputModuleNameTrigger")),
120 fMultiplicityThreshold(
p.get<
int>(
"MultiplicityThreshold")),
121 fBeamWindowLength(
p.get<
double>(
"BeamWindowLength", 1.6)),
122 nChannelsFrag(
p.get<
double>(
"nChannelsFrag", 15)),
123 wfm_length(
p.get<
double>(
"WfmLength", 5120)),
124 fVerbose(
p.get<
bool>(
"Verbose",
false)),
125 fTriggerTimeEngine(art::ServiceHandle<rndm::NuRandomService>{}->createEngine(*
this,
"HepJamesRandom",
"trigger",
p,
"SeedTriggerTime"))
129 produces< std::vector<artdaq::Fragment> >();
132 auto const clockData = art::ServiceHandle<detinfo::DetectorClocksService const>()->DataForJob();
133 fSampling = clockData.OpticalClock().Frequency();
136 auto subsetCondition = [](
auto const& i)->
bool {
return i[
"pd_type"] ==
"pmt_coated" || i[
"pd_type"] ==
"pmt_uncoated"; };
137 auto pmtMap = pdMap.getCollectionFromCondition(subsetCondition);
138 if (fVerbose)
std::cout <<
"Number of PDs selected: \t" << pmtMap.size() <<
"\n";
139 for(
auto const& i:pmtMap){
140 channelList.push_back(i[
"channel"]);
151 fSubrun = e.subRun();
152 fEvent = e.id().event();
154 if (fVerbose)
std::cout <<
"Processing Run: " << fRun <<
", Subrun: " << fSubrun <<
", Event: " << fEvent << std::endl;
157 art::Handle< std::vector< raw::OpDetWaveform > > wvfmHandle;
158 art::Handle< std::vector< sbnd::comm::pmtTrigger > > triggerHandle;
159 e.getByLabel(fInputModuleNameWvfm, wvfmHandle);
160 e.getByLabel(fInputModuleNameTrigger, triggerHandle);
162 if(!wvfmHandle.isValid()) {
163 throw art::Exception(art::errors::Configuration)
164 <<
"Could not find any waveforms, input must contain OpDetWaveforms." <<
"\n";
166 if(!triggerHandle.isValid()) {
167 throw art::Exception(art::errors::Configuration)
168 <<
"Could not find any PMT hardware trigger object, must run PMT trigger producer before running this module." <<
"\n";
172 double fMinStartTime = -1510.0;
173 double fMaxEndTime = 1510.0;
175 for(
auto const& wvf : (*wvfmHandle)) {
176 double fChNumber = wvf.ChannelNumber();
177 std::string opdetType = pdMap.pdType(fChNumber);
179 if (opdetType !=
"pmt_coated" && opdetType !=
"pmt_uncoated")
continue;
180 if (wvf.TimeStamp() < fMinStartTime){ fMinStartTime = wvf.TimeStamp(); }
181 if ((
double(wvf.size()) / fSampling + wvf.TimeStamp()) > fMaxEndTime){ fMaxEndTime = double(wvf.size()) / fSampling + wvf.TimeStamp();}
184 if (fVerbose){
std::cout<<
"MinStartTime: "<<fMinStartTime<<
" MaxEndTime: "<<fMaxEndTime<<std::endl;}
186 std::vector<short> wvf_0; wvf_0.reserve((
int)(3020*1e6/2));
187 for (
double i = fMinStartTime; i<fMaxEndTime+(1./fSampling); i+=(1./fSampling)){
190 for (
size_t i = 0; i < channelList.size(); i++){
191 wvf_channel.push_back(wvf_0);
200 for(
auto const& wvf : (*wvfmHandle)) {
202 double fChNumber = wvf.ChannelNumber();
203 std::string opdetType = pdMap.pdType(fChNumber);
206 if (opdetType !=
"pmt_coated" && opdetType !=
"pmt_uncoated")
continue;
210 double fStartTime = wvf.TimeStamp();
211 double fEndTime = double(wvf.size()) / fSampling + fStartTime;
214 std::vector<short> wvf_full; wvf_full.reserve((
short)(3020*1e6/2));
216 if (fStartTime > fMinStartTime){
217 for (
double i = fStartTime-fMinStartTime; i>0.; i-=(1./fSampling)){
222 for(
unsigned int i = 0; i < wvf.size(); i++) {
223 wvf_full.push_back(wvf[i]);
226 if (fEndTime < fMaxEndTime){
227 for (
double i = fMaxEndTime-fEndTime; i>0.; i-=(1./fSampling)){
234 auto ich = std::find(channelList.begin(), channelList.end(), fChNumber);
235 if (ich != channelList.end()){
236 i_ch = ich - channelList.begin();
238 if (wvf_channel.at(i_ch).size() < wvf_full.size()){
239 if (fVerbose)
std::cout<<
"Full waveform -- Previous Channel" << fChNumber <<
" Size: "<<wvf_channel.at(i_ch).size()<<
"New Channel" << fChNumber <<
" Size: "<<wvf_full.size()<<std::endl;
240 for(
unsigned int i = wvf_channel.at(i_ch).size(); i < wvf_full.size(); i++) {
241 wvf_channel.at(i_ch).push_back(
fBaseline);
244 for(
unsigned int i = 0; i < wvf_full.size(); i++) {
245 wvf_channel.at(i_ch)[i] += (wvf_full[i] -
fBaseline);
254 std::vector<size_t> triggerIndex;
255 for(
auto const& trigger : (*triggerHandle)) {
256 for (
size_t idx = 0; idx < trigger.numPassed.size(); idx++) {
257 if (trigger.numPassed[idx] >= fMultiplicityThreshold) {
259 triggerIndex.push_back(idx);
266 if (fVerbose)
std::cout <<
"Number of PMT hardware triggers found: " << triggerIndex.size() << std::endl;
269 std::unique_ptr<std::vector<artdaq::Fragment>> vecFrag = std::make_unique<std::vector<artdaq::Fragment>>();
272 uint32_t nChannelsTotal = channelList.size();
274 uint32_t nFrag = (uint32_t)nChannelsTotal/nChannelsFrag;
278 uint32_t sequenceIDVal = fEvent;
281 sbndaq::CAENV1730FragmentMetadata metadata;
282 metadata.nChannels = nChannelsFrag + 1;
283 metadata.nSamples = wfm_length;
286 uint32_t eventCounterVal = fEvent;
287 uint32_t boardIDVal = 0;
288 uint32_t triggerTimeTagVal = (uint32_t)CLHEP::RandFlat::shoot(&fTriggerTimeEngine, 0, 1e9);
289 uint32_t eventSizeVal = ((wfm_length * (nChannelsFrag+1)) *
sizeof(uint16_t) +
sizeof(sbndaq::CAENV1730EventHeader)) /
sizeof(uint32_t);
292 for (
auto wvfIdx : triggerIndex) {
295 size_t trigIdx = wvfIdx*4;
296 size_t startIdx = trigIdx-500;
299 double triggerTime = fMinStartTime + wvfIdx*0.008;
300 double timestampVal = 0.5 + (triggerTime*1e-6);
301 metadata.timeStampSec = (uint32_t)timestampVal;
302 metadata.timeStampNSec = (uint32_t)(timestampVal*1e9);
309 const auto fragment_datasize_bytes = metadata.ExpectedDataSize();
310 uint32_t fragmentIDVal =
counter;
311 auto fragment_uptr = artdaq::Fragment::FragmentBytes(fragment_datasize_bytes, sequenceIDVal, fragmentIDVal, sbndaq::detail::FragmentType::CAENV1730, metadata);
312 fragment_uptr->setTimestamp(timestampVal);
315 auto header_ptr =
reinterpret_cast<sbndaq::CAENV1730EventHeader*
>(fragment_uptr->dataBeginBytes());
317 header_ptr->eventCounter = eventCounterVal;
318 header_ptr->boardID = boardIDVal;
319 header_ptr->triggerTimeTag = triggerTimeTagVal;
320 header_ptr->eventSize = eventSizeVal;
324 uint16_t* data_begin =
reinterpret_cast<uint16_t*
>(fragment_uptr->dataBeginBytes() +
sizeof(sbndaq::CAENV1730EventHeader));
325 uint16_t* value_ptr = data_begin;
327 size_t ch_offset = 0;
330 for (
size_t i_ch = 0; i_ch < nChannelsFrag; i_ch++) {
331 ch_offset = (size_t)(i_ch*wfm_length);
333 for (
size_t i_t = 0; i_t < wfm_length; i_t++) {
335 value = wvf_channel[
counter*nChannelsFrag + i_ch][startIdx+i_t];
336 value_ptr = data_begin + ch_offset + i_t;
342 ch_offset = (size_t)(nChannelsFrag*wfm_length);
343 size_t beamStartIdx =
abs(fMinStartTime)*1000/2;
344 size_t beamEndIdx = beamStartIdx + fBeamWindowLength*1000/2;
346 for (
size_t i_t = 0; i_t < wfm_length; i_t++) {
348 if (startIdx + i_t >= beamStartIdx && startIdx + i_t <= beamEndIdx) value = 1;
350 value_ptr = data_begin + ch_offset + i_t;
355 vecFrag->push_back(*fragment_uptr);
359 if(fVerbose)
std::cout <<
"Fragments written: " << vecFrag->size() << std::endl;
362 e.put(std::move(vecFrag));
366 wvf_channel.shrink_to_fit();
void produce(art::Event &e) override
std::string fInputModuleNameWvfm
art::ServiceHandle< art::TFileService > tfs
pmtArtdaqFragmentProducer & operator=(pmtArtdaqFragmentProducer const &)=delete
opdet::sbndPDMapAlg pdMap
BEGIN_PROLOG pmtArtdaqFragmentProducer
auto counter(T begin, T end)
Returns an object to iterate values from begin to end in a range-for loop.
std::string fInputModuleNameTrigger
pmtArtdaqFragmentProducer(fhicl::ParameterSet const &p)
std::vector< unsigned int > channelList
std::vector< std::vector< short > > wvf_channel
CLHEP::HepRandomEngine & fTriggerTimeEngine
int fMultiplicityThreshold
stream1 can override from command line with o or output services user sbnd
art::EventNumber_t fEvent
BEGIN_PROLOG could also be cout