8 #include "art/Framework/Services/Registry/ServiceHandle.h"
9 #include "messagefacility/MessageLogger/MessageLogger.h"
10 #include "cetlib_except/exception.h"
17 class DetectorClocksData;
25 #include "CLHEP/Random/RandGauss.h"
36 , fCalorimetryAlg(config.CalorimetryAlg())
37 , fGeometry(art::ServiceHandle<geo::Geometry const>().get())
45 fCalibrateLifetime = config.CalibrateLifetime();
46 fCalibrateAmpl = config.CalibrateAmpl();
48 fAmplCalibConst.resize(fGeometry->MaxPlanes());
50 mf::LogInfo(
"DataProviderAlg") <<
"Using calibration constants:";
51 for (
size_t p = 0;
p < fAmplCalibConst.size(); ++
p) {
53 fAmplCalibConst[
p] = 1.2e-3 * fCalorimetryAlg.ElectronsFromADCPeak(1.0,
p);
54 mf::LogInfo(
"DataProviderAlg") <<
" plane:" <<
p <<
" const:" << 1.0 / fAmplCalibConst[
p];
57 fAmplCalibConst[
p] = 1.0;
62 mf::LogInfo(
"DataProviderAlg") <<
"No plane-to-plane calibration.";
63 for (
size_t p = 0;
p < fAmplCalibConst.size(); ++
p) {
64 fAmplCalibConst[
p] = 1.0;
68 fDriftWindow = config.DriftWindow();
69 fDownscaleFullView = config.DownscaleFullView();
70 fDriftWindowInv = 1.0 / fDriftWindow;
72 std::string mode_str = config.DownscaleFn();
73 mf::LogVerbatim(
"DataProviderAlg") <<
"Downscale mode is: " << mode_str;
74 if (mode_str ==
"maxpool") {
78 else if (mode_str ==
"maxmean") {
82 else if (mode_str ==
"mean") {
87 mf::LogError(
"DataProviderAlg") <<
"Downscale mode string not recognized, set to max pooling.";
92 fAdcMax = config.AdcMax();
93 fAdcMin = config.AdcMin();
94 fAdcOffset = config.OutMin();
95 fAdcScale = (config.OutMax() - fAdcOffset) / (fAdcMax - fAdcMin);
96 fAdcZero = fAdcOffset + fAdcScale * (0 - fAdcMin);
98 if (fAdcMax <= fAdcMin) {
99 throw cet::exception(
"img::DataProviderAlg") <<
"Misconfigured: AdcMax <= AdcMin" << std::endl;
101 if (fAdcScale == 0) {
102 throw cet::exception(
"img::DataProviderAlg") <<
"Misconfigured: OutMax == OutMin" << std::endl;
105 fBlurKernel = config.BlurKernel();
106 fNoiseSigma = config.NoiseSigma();
107 fCoherentSigma = config.CoherentSigma();
132 for (
size_t t = 0; t < drifts; ++t) {
137 for (
size_t t = 0; t < drifts; ++t) {
148 size_t rw =
r, rd =
r;
149 if (!fDownscaleFullView) { rd *= fDriftWindow; }
151 size_t didx = getDriftIndex(drift);
153 if (d0 < 0) { d0 = 0; }
155 if (d1 >= (
int)fAlgView.fNCachedDrifts) { d1 = fAlgView.fNCachedDrifts - 1; }
158 if (w0 < 0) { w0 = 0; }
160 if (w1 >= (
int)fAlgView.fNWires) { w1 = fAlgView.fNWires - 1; }
162 float adc, max_adc = 0;
163 for (
int w = w0;
w <= w1; ++
w) {
164 auto const* col = fAlgView.fWireDriftData[
w].data();
165 for (
int d = d0; d <= d1; ++d) {
167 if (adc > max_adc) { max_adc = adc; }
199 std::vector<float>
const& adc,
202 size_t kStop = dst_size;
203 std::vector<float> result(dst_size);
204 if (adc.size() < kStop) { kStop = adc.size(); }
205 for (
size_t i = 0, k0 = 0; i < kStop; ++i, k0 += fDriftWindow) {
206 size_t k1 = k0 + fDriftWindow;
208 float max_adc = adc[k0] * fAlgView.fLifetimeCorrFactors[k0 + tick0];
209 for (
size_t k = k0 + 1;
k < k1; ++
k) {
210 float ak = adc[
k] * fAlgView.fLifetimeCorrFactors[
k + tick0];
211 if (ak > max_adc) max_adc = ak;
215 scaleAdcSamples(result);
221 std::vector<float>
const& adc,
224 size_t kStop = dst_size;
225 std::vector<float> result(dst_size);
226 if (adc.size() < kStop) { kStop = adc.size(); }
227 for (
size_t i = 0, k0 = 0; i < kStop; ++i, k0 += fDriftWindow) {
228 size_t k1 = k0 + fDriftWindow;
230 float max_adc = adc[k0] * fAlgView.fLifetimeCorrFactors[k0 + tick0];
231 for (
size_t k = k0 + 1;
k < k1; ++
k) {
232 float ak = adc[
k] * fAlgView.fLifetimeCorrFactors[
k + tick0];
241 max_adc += adc[max_idx - 1] * fAlgView.fLifetimeCorrFactors[max_idx - 1 + tick0];
244 if (max_idx + 1 < adc.size()) {
245 max_adc += adc[max_idx + 1] * fAlgView.fLifetimeCorrFactors[max_idx + 1 + tick0];
249 result[i] = max_adc /
n;
251 scaleAdcSamples(result);
257 std::vector<float>
const& adc,
260 size_t kStop = dst_size;
261 std::vector<float> result(dst_size);
262 if (adc.size() < kStop) { kStop = adc.size(); }
263 for (
size_t i = 0, k0 = 0; i < kStop; ++i, k0 += fDriftWindow) {
264 size_t k1 = k0 + fDriftWindow;
267 for (
size_t k = k0;
k < k1; ++
k) {
268 if (
k + tick0 < fAlgView.fLifetimeCorrFactors.size())
269 sum_adc += adc[
k] * fAlgView.fLifetimeCorrFactors[
k + tick0];
271 result[i] = sum_adc * fDriftWindowInv;
273 scaleAdcSamples(result);
277 std::optional<std::vector<float>>
280 if (wireIdx >= fAlgView.fWireDriftData.size())
return std::nullopt;
281 auto& wData = fAlgView.fWireDriftData[wireIdx];
283 if (fDownscaleFullView) {
284 if (!adc.empty()) {
return downscale(wData.size(), adc, 0); }
290 if (adc.empty()) {
return std::nullopt; }
291 else if (adc.size() <= wData.size())
294 return std::vector<float>(adc.begin(), adc.begin() + wData.size());
297 return std::make_optional(wData);
304 const std::vector<recob::Wire>& wires,
309 mf::LogInfo(
"DataProviderAlg") <<
"Create image for cryo:" << cryo <<
" tpc:" << tpc
310 <<
" plane:" << plane;
319 size_t nwires = fGeometry->Nwires(plane, tpc, cryo);
322 fAlgView = resizeView(clock_data, det_prop, nwires, ndrifts);
324 auto const& channelStatus =
325 art::ServiceHandle<lariov::ChannelStatusService const>()->GetProvider();
327 bool allWrong =
true;
328 for (
auto const& wire : wires) {
329 auto wireChannelNumber = wire.Channel();
330 if (!channelStatus.IsGood(wireChannelNumber)) {
continue; }
333 for (
auto const&
id : fGeometry->ChannelToWire(wireChannelNumber)) {
334 if ((
id.
Plane == plane) && (
id.TPC == tpc) && (
id.Cryostat == cryo)) {
337 auto adc = wire.Signal();
338 if (adc.size() < ndrifts) {
339 mf::LogWarning(
"DataProviderAlg") <<
"Wire ADC vector size lower than NumberTimeSamples.";
342 auto wire_data = setWireData(adc, w_idx);
344 mf::LogWarning(
"DataProviderAlg") <<
"Wire data not set.";
347 fAlgView.fWireDriftData[w_idx] = *wire_data;
349 if (v >= fAdcSumThr) {
355 fAlgView.fWireChannels[w_idx] = wireChannelNumber;
361 mf::LogError(
"DataProviderAlg")
362 <<
"Wires data not set in the cryo:" << cryo <<
" tpc:" << tpc <<
" plane:" << plane;
377 val *= fAmplCalibConst[fPlane];
379 if (val < fAdcMin) { val = fAdcMin; }
380 else if (val > fAdcMax) {
392 float calib = fAmplCalibConst[fPlane];
393 auto* data = values.data();
395 size_t k = 0, size4 = values.size() >> 2,
size = values.size();
396 for (
size_t i = 0; i < size4; ++i)
399 data[k + 1] *= calib;
400 data[k + 2] *= calib;
401 data[k + 3] *= calib;
403 if (data[k] < fAdcMin) { data[
k] = fAdcMin; }
404 if (data[k + 1] < fAdcMin) { data[k + 1] = fAdcMin; }
405 if (data[k + 2] < fAdcMin) { data[k + 2] = fAdcMin; }
406 if (data[k + 3] < fAdcMin) { data[k + 3] = fAdcMin; }
408 if (data[k] > fAdcMax) { data[
k] = fAdcMax; }
409 if (data[k + 1] > fAdcMax) { data[k + 1] = fAdcMax; }
410 if (data[k + 2] > fAdcMax) { data[k + 2] = fAdcMax; }
411 if (data[k + 3] > fAdcMax) { data[k + 3] = fAdcMax; }
413 data[
k] = fAdcOffset +
416 data[k + 1] = fAdcOffset + fAdcScale * (data[k + 1] - fAdcMin);
417 data[k + 2] = fAdcOffset + fAdcScale * (data[k + 2] - fAdcMin);
418 data[k + 3] = fAdcOffset + fAdcScale * (data[k + 3] - fAdcMin);
423 data[
k] = scaleAdcSample(data[k]);
432 if (fBlurKernel.size() < 2)
return;
434 size_t margin_left = (fBlurKernel.size() - 1) >> 1,
435 margin_right = fBlurKernel.size() - margin_left - 1;
437 std::vector<std::vector<float>> src(fAlgView.fWireDriftData.size());
438 for (
size_t w = 0;
w < fAlgView.fWireDriftData.size(); ++
w) {
439 src[
w] = fAlgView.fWireDriftData[
w];
442 for (
size_t w = margin_left;
w < fAlgView.fWireDriftData.size() - margin_right; ++
w) {
443 for (
size_t d = 0; d < fAlgView.fWireDriftData[
w].size(); ++d) {
445 for (
size_t i = 0; i < fBlurKernel.size(); ++i) {
446 sum += fBlurKernel[i] * src[
w + i - margin_left][d];
448 fAlgView.fWireDriftData[
w][d] = sum;
462 int halfSizeW = size_w / 2;
463 int halfSizeD = size_d / 2;
465 int w0 = wire - halfSizeW;
466 int w1 = wire + halfSizeW;
468 size_t sd = (size_t)(drift / fDriftWindow);
469 int d0 = sd - halfSizeD;
470 int d1 = sd + halfSizeD;
472 int wsize = fAlgView.fWireDriftData.size();
473 for (
int w = w0, wpatch = 0;
w < w1; ++
w, ++wpatch) {
474 auto& dst = patch[wpatch];
475 if ((
w >= 0) && (
w < wsize)) {
476 auto& src = fAlgView.fWireDriftData[
w];
477 int dsize = src.size();
478 for (
int d = d0, dpatch = 0; d < d1; ++d, ++dpatch) {
479 if ((d >= 0) && (d < dsize)) { dst[dpatch] = src[d]; }
481 dst[dpatch] = fAdcZero;
486 std::fill(dst.begin(), dst.end(), fAdcZero);
500 int dsize = fDriftWindow * size_d;
501 int halfSizeW = size_w / 2;
502 int halfSizeD = dsize / 2;
504 int w0 = wire - halfSizeW;
505 int w1 = wire + halfSizeW;
507 int d0 = int(drift) - halfSizeD;
508 int d1 = int(drift) + halfSizeD;
512 std::vector<float> tmp(dsize);
513 int wsize = fAlgView.fWireDriftData.size();
514 for (
int w = w0, wpatch = 0;
w < w1; ++
w, ++wpatch) {
515 if ((
w >= 0) && (
w < wsize)) {
516 auto& src = fAlgView.fWireDriftData[
w];
517 int src_size = src.size();
518 for (
int d = d0, dpatch = 0; d < d1; ++d, ++dpatch) {
519 if ((d >= 0) && (d < src_size)) { tmp[dpatch] = src[d]; }
521 tmp[dpatch] = fAdcZero;
526 std::fill(tmp.begin(), tmp.end(), fAdcZero);
528 patch[wpatch] = downscale(patch[wpatch].
size(), tmp, d0);
538 if (fNoiseSigma == 0)
return;
540 double effectiveSigma = scaleAdcSample(fNoiseSigma);
541 if (fDownscaleFullView) effectiveSigma /= fDriftWindow;
543 CLHEP::RandGauss gauss(fRndEngine);
544 std::vector<double> noise(fAlgView.fNCachedDrifts);
545 for (
auto& wire : fAlgView.fWireDriftData) {
546 gauss.fireArray(fAlgView.fNCachedDrifts, noise.data(), 0., effectiveSigma);
547 for (
size_t d = 0; d < wire.size(); ++d) {
557 if (fCoherentSigma == 0)
return;
559 double effectiveSigma = scaleAdcSample(fCoherentSigma);
560 if (fDownscaleFullView) effectiveSigma /= fDriftWindow;
562 CLHEP::RandGauss gauss(fRndEngine);
563 std::vector<double> amps1(fAlgView.fWireDriftData.size());
564 std::vector<double> amps2(1 + (fAlgView.fWireDriftData.size() / 32));
565 gauss.fireArray(amps1.size(), amps1.data(), 1., 0.1);
566 gauss.fireArray(amps2.size(), amps2.data(), 1., 0.1);
568 double group_amp = 1.0;
569 std::vector<double> noise(fAlgView.fNCachedDrifts);
570 for (
size_t w = 0;
w < fAlgView.fWireDriftData.size(); ++
w) {
572 group_amp = amps2[
w >> 5];
573 gauss.fireArray(fAlgView.fNCachedDrifts, noise.data(), 0., effectiveSigma);
576 auto& wire = fAlgView.fWireDriftData[
w];
577 for (
size_t d = 0; d < wire.size(); ++d) {
578 wire[d] += group_amp * amps1[
w] * noise[d];
std::optional< std::vector< float > > setWireData(std::vector< float > const &adc, size_t wireIdx) const
unsigned int fNCachedDrifts
std::vector< std::vector< float > > fWireDriftData
BEGIN_PROLOG true icarus_rawdigitfilter FilterTools FilterPlane1 Plane
virtual ~DataProviderAlg()
virtual DataProviderAlgView resizeView(detinfo::DetectorClocksData const &clock_data, detinfo::DetectorPropertiesData const &det_prop, size_t wires, size_t drifts)
std::size_t size(FixedBins< T, C > const &) noexcept
DataProviderAlg(const fhicl::ParameterSet &pset)
std::vector< float > downscaleMaxMean(std::size_t dst_size, std::vector< float > const &adc, size_t tick0) const
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
constexpr ChannelID_t InvalidChannelID
ID of an invalid channel.
std::vector< float > downscaleMax(std::size_t dst_size, std::vector< float > const &adc, size_t tick0) const
std::vector< float > downscaleMean(std::size_t dst_size, std::vector< float > const &adc, size_t tick0) const
unsigned int fNScaledDrifts
void scaleAdcSamples(std::vector< float > &values) const
std::vector< raw::ChannelID_t > fWireChannels
unsigned int NumberTimeSamples() const
void fill(const art::PtrVector< recob::Hit > &hits, int only_plane)
float scaleAdcSample(float val) const
calo::CalorimetryAlg fCalorimetryAlg
bool patchFromOriginalView(size_t wire, float drift, size_t size_w, size_t size_d, std::vector< std::vector< float >> &patch) const
bool setWireDriftData(const detinfo::DetectorClocksData &clock_data, const detinfo::DetectorPropertiesData &det_prop, const std::vector< recob::Wire > &wires, unsigned int plane, unsigned int tpc, unsigned int cryo)
Contains all timing reference information for the detector.
std::vector< float > fLifetimeCorrFactors
Interface for experiment-specific channel quality info provider.
Declaration of basic channel signal object.
bool patchFromDownsampledView(size_t wire, float drift, size_t size_w, size_t size_d, std::vector< std::vector< float >> &patch) const
float poolMax(int wire, int drift, size_t r=0) const
Pool max value in a patch around the wire/drift pixel.
Interface for experiment-specific service for channel quality info.
double LifetimeCorrection(detinfo::DetectorClocksData const &clock_data, detinfo::DetectorPropertiesData const &det_prop, double time, double T0=0) const
art framework interface to geometry description