3 #include "fhiclcpp/ParameterSet.h"
4 #include "art/Utilities/ToolMacros.h"
5 #include "art/Framework/Services/Registry/ServiceHandle.h"
6 #include "art_root_io/TFileService.h"
7 #include "art/Framework/Core/ModuleMacros.h"
8 #include "art/Utilities/make_tool.h"
9 #include "art_root_io/TFileDirectory.h"
10 #include "messagefacility/MessageLogger/MessageLogger.h"
26 #include "TProfile2D.h"
29 #include "icarus_signal_processing/Filters/ICARUSFFT.h"
30 #include "icarus_signal_processing/WaveformTools.h"
71 void configure(fhicl::ParameterSet
const & pset)
override;
81 art::ServiceHandle<art::TFileService>&,
const std::string&)
override;
88 void endJob(
int numEvents)
override;
135 using FFTPointer = std::unique_ptr<icarus_signal_processing::ICARUSFFT<double>>;
153 fCharacterizationAlg(pset.
get<fhicl::ParameterSet>(
"CharacterizationAlg")),
155 fSignalServices(*art::ServiceHandle<icarusutil::SignalShapingICARUSService>()),
156 fPedestalRetrievalAlg(*lar::
providerFrom<lariov::DetPedestalService>())
159 auto const detProp = art::ServiceHandle<detinfo::DetectorPropertiesService const>()->DataForJob();
160 int numberTimeSamples =
detProp.NumberTimeSamples();
162 fFFT = std::make_unique<icarus_signal_processing::ICARUSFFT<double>>(numberTimeSamples);
167 mf::LogInfo(
"BasicRawDigitAnalysis") <<
"BasicRawDigitAnalysis configured\n";
172 BasicRawDigitAnalysis::~BasicRawDigitAnalysis()
182 void BasicRawDigitAnalysis::configure(fhicl::ParameterSet
const & pset)
184 fLoWireByPlane = pset.get<std::vector<size_t>> (
"LoWireByPlane", std::vector<size_t>()={0,0,0});
185 fHiWireByPlane = pset.get<std::vector<size_t>> (
"HiWireByPlane", std::vector<size_t>()={100,100,100});
186 fFFTFitFuncVec = pset.get<std::vector<std::string>> (
"FFTFunctionVec", std::vector<std::string>()={
"1",
"1",
"1"});
187 fParameterVec = pset.get<std::vector<std::vector<double>>>(
"FFTFuncParamsVec", std::vector<std::vector<double>>() = {{1},{1},{1}});
196 art::ServiceHandle<art::TFileService>&
tfs,
const std::string& dirName)
199 art::TFileDirectory
dir = tfs->mkdir(dirName.c_str());
208 double maxFreq = 1.e6 / (2. * sampleRate);
209 size_t numSamples = readOutSize / 2;
240 for(
size_t idx = 0; idx < 20; idx++)
244 fFFTPowerVec[plane][idx] = dir.make<TProfile>(histName.c_str(),
"Power Spectrum;kHz;Power", numSamples, 0., maxFreq, 0., 10000.);
248 fFFTPowerDerivVec[plane][idx] = dir.make<TProfile>(histName.c_str(),
"Power Deriv;kHz;Power", numSamples, 0., maxFreq, -500., 500.);
252 fFFTRealVec[plane][idx] = dir.make<TProfile>(histName.c_str(),
"Real values;kHz;Power", numSamples, 0., maxFreq, -10000., 10000.);
256 fFFTImaginaryVec[plane][idx] = dir.make<TProfile>(histName.c_str(),
"Imaginary values;kHz;Power", numSamples, 0., maxFreq, -10000., 10000.);
260 fSmoothPowerVec[plane][idx] = dir.make<TProfile>(histName.c_str(),
"Power Spectrum;kHz;Power", numSamples, 0., maxFreq, 0., 10000.);
265 fAveFFTPowerVec[plane] = dir.make<TProfile>(histName.c_str(),
"Power Spectrum;kHz;Power", numSamples, 0., maxFreq, 0., 1000.);
269 fConvFFTPowerVec[plane] = dir.make<TProfile>(histName.c_str(),
"Power Spectrum;kHz;Power", numSamples, 0., maxFreq, 0., 1000.);
273 fConvKernelVec[plane] = dir.make<TProfile>(histName.c_str(),
"Convolution Kernel;kHz;Power", numSamples, 0., maxFreq, 0., 1000.);
277 fFilterFuncVec[plane] = dir.make<TProfile>(histName.c_str(),
"Filter Function;kHz;Power", numSamples, 0., maxFreq, 0., 1000.);
281 fAveFFTPowerDerivVec[plane] = dir.make<TProfile>(histName.c_str(),
"Power Deriv;kHz;Power", numSamples, 0., maxFreq, -500., 500.);
285 fAveFFTRealVec[plane] = dir.make<TProfile>(histName.c_str(),
"Real values;kHz;Power", numSamples, 0., maxFreq, -10000., 1000.);
289 fAveFFTImaginaryVec[plane] = dir.make<TProfile>(histName.c_str(),
"Imaginary values;kHz;Power", numSamples, 0., maxFreq, -1000., 1000.);
293 fAveSmoothPowerVec[plane] = dir.make<TProfile>(histName.c_str(),
"Power Spectrum;kHz;Power", numSamples, 0., maxFreq, 0., 1000.);
297 fTruncMeanHist[plane] = dir.make<TH1D>(histName.c_str(),
";ADC", 200, -50., 50.);
301 fTruncRmsHist[plane] = dir.make<TH1D>(histName.c_str(),
";ADC", 100, 0., 20.);
305 fFullRmsHist[plane] = dir.make<TH1D>(histName.c_str(),
";ADC", 100, 0., 20.);
314 for(
size_t idx = 0; idx < numSamples; idx++)
316 double freq = 1.e6 * double(idx)/ (sampleRate * readOutSize);
332 std::vector<const raw::RawDigit*> rawDigitVec;
335 for(
size_t idx = 0; idx < rawDigitPtrVec.size(); idx++) rawDigitVec.push_back(rawDigitPtrVec.at(idx).get());
346 std::vector<caldata::RawDigitVector> rawDataWireTimeVec;
347 std::vector<float> truncMeanWireVec;
348 std::vector<float> truncRmsWireVec;
349 std::vector<short> meanWireVec;
350 std::vector<short> medianWireVec;
351 std::vector<short> modeWireVec;
352 std::vector<float> skewnessWireVec;
353 std::vector<float> fullRmsWireVec;
354 std::vector<short> minMaxWireVec;
355 std::vector<float> neighborRatioWireVec;
356 std::vector<float> pedCorWireVec;
359 size_t numWiresToGroup(1);
361 rawDataWireTimeVec.resize(numWiresToGroup);
362 truncMeanWireVec.resize(numWiresToGroup);
363 truncRmsWireVec.resize(numWiresToGroup);
364 meanWireVec.resize(numWiresToGroup);
365 medianWireVec.resize(numWiresToGroup);
366 modeWireVec.resize(numWiresToGroup);
367 skewnessWireVec.resize(numWiresToGroup);
368 fullRmsWireVec.resize(numWiresToGroup);
369 minMaxWireVec.resize(numWiresToGroup);
370 neighborRatioWireVec.resize(numWiresToGroup);
371 pedCorWireVec.resize(numWiresToGroup);
374 for(
const auto& rawDigit : rawDigitVec)
382 std::vector<geo::WireID> wids;
392 if (!goodChan)
continue;
395 unsigned int plane = wids[0].Plane;
396 unsigned int wire = wids[0].Wire;
398 unsigned int dataSize = rawDigit->Samples();
402 std::cout <<
"****>> Found zero length raw digit buffer, channel: " << channel <<
", plane: " << plane <<
", wire: " << wire << std::endl;
407 bool hasSignal = channelMap.find(channel) != channelMap.end();
410 std::vector<short>& rawadc = rawDataWireTimeVec[0];
412 if (rawadc.size() != dataSize) rawadc.resize(dataSize);
420 filterFFT(clockData, detProp, rawadc, channel, plane, wire, pedestal, hasSignal);
438 neighborRatioWireVec[0],
453 std::vector<short>& rawadc,
455 size_t plane,
size_t wire,
float pedestal,
bool hasSignal)
const
462 size_t fftDataSize = rawadc.size();
463 size_t halfFFTDataSize = fftDataSize / 2 + 1;
468 std::transform(rawadc.begin(),rawadc.end(),inputVec.begin(),[pedestal](
const auto& val){
return double(val) - pedestal;});
470 fFFT->getFFTPower(inputVec,powerVec);
476 for(
size_t idx = 0; idx < halfFFTDataSize; idx++)
478 double freq = 1.e6 * double(idx + 1)/ (sampleRate * readOutSize);
483 for(
size_t idx = 0; idx < halfFFTDataSize; idx++)
485 double freq = 1.e6 * double(idx + 1)/ (sampleRate * readOutSize);
490 size_t numBinsToAve(9);
493 size_t currentBin(halfFFTDataSize - numBinsToAve - 1);
502 icarus_signal_processing::WaveformTools<float>::PeakTupleVec peakTupleVec;
504 fWaveformTool.findPeaks(powerDerivVec.begin() + 300, powerDerivVec.end(), peakTupleVec, 10., 0);
509 for(
const auto& peakTuple : peakTupleVec)
511 if (std::get<0>(peakTuple) >= powerVec.size() || std::get<2>(peakTuple) >= powerVec.size())
513 std::cout <<
"indexing problem - first: " << std::get<0>(peakTuple) <<
", last: " << std::get<2>(peakTuple) << std::endl;
517 size_t firstBin = std::get<0>(peakTuple);
518 size_t lastBin = std::get<2>(peakTuple);
519 double firstBinVal = powerVec.at(firstBin);
520 double lastBinVal = powerVec.at(lastBin);
521 double stepVal = (lastBinVal - firstBinVal) /
double(lastBin - firstBin);
522 double newBinVal = firstBinVal + stepVal;
524 while(++firstBin < lastBin)
527 smoothPowerVec[firstBin] = newBinVal;
528 newBinVal += stepVal;
532 while(currentBin > lowestBin)
534 double avePowerThisBin(smoothPowerVec.at(currentBin));
535 double freq = 1.e6 * double(currentBin)/ (sampleRate * readOutSize);
553 fFFT->convolute(inputVec,filter,0);
554 fFFT->getFFTPower(inputVec,powerVec);
556 for(
size_t idx = 0; idx < halfFFTDataSize; idx++)
558 double freq = 1.e6 * double(idx)/ (sampleRate * readOutSize);
566 void BasicRawDigitAnalysis::endJob(
int numEvents)
578 std::string funcName = std::string(avePowerHist->GetName()) +
"_func";
581 TF1 fitFunc(funcName.c_str(),
fFFTFitFuncVec.at(planeIdx).c_str(),avePowerHist->GetMinimum(),avePowerHist->GetMaximum());
586 for(
const auto& param :
fParameterVec.at(planeIdx)) fitFunc.SetParameter(paramIdx++, param);
591 { fitResult = avePowerHist->Fit(&fitFunc,
"QNRWB",
"", avePowerHist->GetMinimum(),avePowerHist->GetMaximum());}
594 std::cout <<
"******* FFT power vec fit failure, skipping *******" << std::endl;
600 double chi2PerNDF = (fitFunc.GetChisquare() / fitFunc.GetNDF());
601 int NDF = fitFunc.GetNDF();
603 std::cout <<
"******************** Fit of " << avePowerHist->GetName() <<
" ********************" << std::endl;
604 std::cout <<
"-- Function: " <<
fFFTFitFuncVec.at(planeIdx) <<
", chi2PerNDF: " << chi2PerNDF <<
", NDF: " << NDF << std::endl;
605 std::cout <<
"-- Parameters - 0: " << fitFunc.GetParameter(0);
607 for(
size_t idx = 1; idx <
fParameterVec.at(planeIdx).size(); idx++)
std::cout <<
", " << idx <<
": " << fitFunc.GetParameter(idx);
caldata::RawDigitCharacterizationAlg fCharacterizationAlg
std::vector< TProfile * > fAveFFTPowerVec
Utilities related to art service access.
Collection of charge vs time digitized from a single readout channel.
std::vector< TProfile * > fAveFFTPowerDerivVec
icarusutil::SignalShapingICARUSService & fSignalServices
The signal shaping service.
std::vector< std::vector< TProfile * > > fSmoothPowerVec
std::vector< TProfile * > fConvKernelVec
T::provider_type const * providerFrom()
Returns a constant pointer to the provider of specified service.
std::vector< TProfile * > fAveFFTRealVec
WaveformTools fWaveformTool
ChannelID_t Channel() const
DAQ channel this raw data was read from.
std::vector< TH1D * > fTruncRmsHist
std::vector< TProfile * > fConvFFTPowerVec
std::vector< geo::WireID > ChannelToWire(raw::ChannelID_t const channel) const
Returns a list of wires connected to the specified TPC channel.
std::vector< std::vector< TProfile * > > fFFTPowerVec
unsigned int ReadOutWindowSize() const
std::vector< ComplexVal > FrequencyVec
void configure(fhicl::ParameterSet const &pset) override
pure virtual base interface for detector clocks
const lariov::DetPedestalProvider & fPedestalRetrievalAlg
Keep track of an instance to the pedestal retrieval alg.
std::unique_ptr< icarus_signal_processing::ICARUSFFT< double >> FFTPointer
unsigned int Nplanes(unsigned int tpc=0, unsigned int cstat=0) const
Returns the total number of wire planes in the specified TPC.
std::vector< TProfile * > fFilterFuncVec
icarus_signal_processing::WaveformTools< double > WaveformTools
std::vector< SigProcPrecision > TimeVec
std::vector< TH1D * > fTruncMeanHist
~BasicRawDigitAnalysis()
Destructor.
std::vector< std::vector< TProfile * > > fFFTRealVec
Description of geometry of one entire detector.
virtual float PedMean(raw::ChannelID_t ch) const =0
Retrieve pedestal information.
std::vector< TH1D * > fFullRmsHist
const geo::GeometryCore & fGeometry
pointer to Geometry service
raw::ChannelID_t PlaneWireToChannel(WireID const &wireid) const
Returns the ID of the TPC channel connected to the specified wire.
std::vector< std::vector< TProfile * > > fFFTImaginaryVec
void initializeHists(detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, art::ServiceHandle< art::TFileService > &, const std::string &) override
Interface for initializing the histograms to be filled.
Contains all timing reference information for the detector.
std::string to_string(WindowPattern const &pattern)
void filterFFT(const detinfo::DetectorClocksData &clockData, const detinfo::DetectorPropertiesData &detProp, std::vector< short > &, raw::ChannelID_t, size_t, size_t, float, bool) const
std::vector< std::vector< TProfile * > > fFFTPowerDerivVec
void fillHistograms(const detinfo::DetectorClocksData &clockData, const detinfo::DetectorPropertiesData &detProp, const IRawDigitHistogramTool::RawDigitPtrVec &, const IRawDigitHistogramTool::SimChannelMap &) const override
Interface for filling histograms.
std::vector< TProfile * > fAveSmoothPowerVec
const icarus_tool::IResponse & GetResponse(size_t channel) const
std::vector< size_t > fHiWireByPlane
Hi wire for individual wire histograms.
void endJob(int numEvents) override
Interface for method to executve at the end of run processing.
art::ServiceHandle< art::TFileService > tfs
unsigned int ChannelID_t
Type representing the ID of a readout channel.
void Uncompress(const std::vector< short > &adc, std::vector< short > &uncompressed, raw::Compress_t compress)
Uncompresses a raw data buffer.
BasicRawDigitAnalysis(fhicl::ParameterSet const &pset)
Constructor.
double sampling_rate(DetectorClocksData const &data)
Returns the period of the TPC readout electronics clock.
void getWaveformParams(const RawDigitVector &rawWaveform, unsigned int channel, unsigned int view, unsigned int wire, float &truncMean, float &truncRms, short &mean, short &median, short &mode, float &skewness, float &rms, short &minMax, float &neighborRatio, float &pedCorVal) const
std::vector< size_t > fLoWireByPlane
Low wire for individual wire histograms.
std::vector< std::vector< double > > fParameterVec
Initial parameters for fit function.
std::vector< std::string > fFFTFitFuncVec
Function definitions for fitting the average FFT power spectra.
art framework interface to geometry description
BEGIN_PROLOG could also be cout
std::vector< TProfile * > fAveFFTImaginaryVec