13 #include "cetlib/pow.h" 21 #include "RtypesCore.h" 30 #include "TVirtualPad.h" 32 #include "range/v3/view.hpp" 38 : fDebug{pset.
get<
bool>(
"Debug",
false)}
39 ,
fDetector{pset.get<std::string>(
"Detector",
"dune35t")}
49 ,
fMinSize{pset.get<
unsigned int>(
"MinSize")}
50 ,
fMinSeed{pset.get<
double>(
"MinSeed")}
62 closeName.append(
"]");
73 Double_t Red[2] = {1.00, 0.00};
74 Double_t Green[2] = {1.00, 0.00};
75 Double_t Blue[2] = {1.00, 0.00};
76 Double_t
Length[2] = {0.00, 1.00};
77 TColor::CreateGradientColorTable(2, Length, Red, Green, Blue, 1000);
78 gStyle->SetOptStat(110000);
81 std::ostringstream oss;
82 oss <<
"BlurredImages_Run" << run <<
"_Subrun" << subrun;
95 for (
int i = 1; i <= 4; ++i) {
99 std::ostringstream oss;
100 oss <<
"Event " << event;
104 l.DrawLatex(0.1, 0.1, oss.str().c_str());
110 std::vector<std::vector<int>>
const& allClusterBins,
114 for (
auto const& bins : allClusterBins) {
118 mf::LogInfo(
"BlurredClustering") <<
"Cluster made from " << bins.size() <<
" bins, of which " 119 << clusHits.
size() <<
" were real hits";
124 <<
"Cluster of size " << clusHits.
size()
125 <<
" not saved since it is smaller than the minimum cluster size, set to " <<
fMinSize;
129 clusters.push_back(clusHits);
135 int const readoutWindowSize)
138 int lowerTick = readoutWindowSize, upperTick{}, lowerWire =
fGeom->
MaxWires(), upperWire{};
140 using ranges::views::transform;
143 if (
hit.PeakTime() < lowerTick) lowerTick =
hit.PeakTime();
144 if (
hit.PeakTime() > upperTick) upperTick =
hit.PeakTime();
145 if (histWire < lowerWire) lowerWire = histWire;
146 if (histWire > upperWire) upperWire = histWire;
165 auto const tick =
static_cast<int>(
hit->PeakTime());
166 float const charge =
hit->Integral();
179 for (
int wire = fLowerWire; wire <
fUpperWire; ++wire) {
191 int const nbinsx = blurred.size();
192 int const nbinsy = blurred.at(0).size();
193 int const nbins = nbinsx * nbinsy;
196 std::vector<bool> used(nbins);
197 std::vector<std::pair<double, int>>
values;
200 for (
int xbin = 0; xbin <
nbinsx; ++xbin) {
201 for (
int ybin = 0; ybin < nbinsy; ++ybin) {
208 std::sort(values.rbegin(), values.rend());
220 std::vector<double> times;
223 if (
double const blurred_binval = values[niter].first; blurred_binval <
fMinSeed)
break;
226 int const bin = values[niter++].second;
229 if (used[bin])
continue;
233 cluster.push_back(bin);
236 if (
double const time =
GetTimeOfBin(blurred, bin); time > 0) times.push_back(time);
241 bool added_cluster{
false};
243 for (
unsigned int clusBin = 0; clusBin < cluster.size(); ++clusBin) {
246 int const binx = cluster[clusBin] %
nbinsx;
247 int const biny = ((cluster[clusBin] - binx) / nbinsx) % nbinsy;
251 if (
x >= nbinsx or
x < 0)
continue;
253 if (
y >= nbinsy or
y < 0)
continue;
254 if (
x == binx and
y == biny)
continue;
258 if (bin >= nbinsx * nbinsy or bin < 0)
continue;
259 if (used[bin])
continue;
267 if (time > 0 && times.size() > 0 && !
PassesTimeCut(times, time))
continue;
272 cluster.push_back(bin);
273 added_cluster =
true;
274 if (time > 0) { times.push_back(time); }
281 if (!added_cluster)
break;
287 for (
auto const bin : cluster) {
295 for (
unsigned int clusBin = 0; clusBin < cluster.size(); clusBin++) {
298 for (
int x = -1;
x <= 1; ++
x) {
299 for (
int y = -1;
y <= 1; ++
y) {
300 if (
x == 0 &&
y == 0)
continue;
303 int neighbouringBin = cluster[clusBin] +
x + (
y *
nbinsx);
304 if (neighbouringBin < nbinsx || neighbouringBin % nbinsx == 0 ||
305 neighbouringBin % nbinsx == nbinsx - 1 || neighbouringBin >= nbinsx * (nbinsy - 1))
308 double const time =
GetTimeOfBin(blurred, neighbouringBin);
311 if (!used[neighbouringBin] &&
314 used[neighbouringBin] =
true;
315 cluster.push_back(neighbouringBin);
317 if (time > 0) { times.push_back(time); }
325 <<
"Size of cluster after filling in holes: " << cluster.size();
329 bool removed_cluster{
false};
332 for (
int clusBin = cluster.size() - 1; clusBin >= 0; clusBin--) {
333 auto const bin = cluster[clusBin];
336 if (bin < nbinsx || bin % nbinsx == 0 || bin % nbinsx == nbinsx - 1 ||
337 bin >= nbinsx * (nbinsy - 1))
343 removed_cluster =
true;
344 cluster.erase(cluster.begin() + clusBin);
348 if (!removed_cluster)
break;
352 <<
"Size of cluster after removing peninsulas: " << cluster.size();
356 for (
auto const bin : cluster) {
364 allcluster.push_back(cluster);
369 return allcluster.size();
374 double globalWire = -999;
390 if (wireID.
TPC == 0 or wireID.
TPC == 1)
391 globalWire = wireID.
Wire;
392 else if (wireID.
TPC == 2 or wireID.
TPC == 3 or wireID.
TPC == 4 or wireID.
TPC == 5)
393 globalWire = nwires + wireID.
Wire;
394 else if (wireID.
TPC == 6 or wireID.
TPC == 7)
395 globalWire = (2 * nwires) + wireID.
Wire;
398 <<
"Error when trying to find a global induction plane coordinate for TPC " << wireID.
TPC 404 int block = wireID.
TPC / 4;
405 globalWire = (nwires * block) + wireID.
Wire;
414 return std::round(globalWire);
418 std::vector<std::vector<double>>
const& image)
const 425 int width = 2 * blur_wire + 1;
426 int height = 2 * blur_tick + 1;
427 int nbinsx = image.size();
428 int nbinsy = image.at(0).size();
431 std::vector<std::vector<double>> copy(nbinsx, std::vector<double>(nbinsy, 0));
435 for (
int y = 0;
y < nbinsy; ++
y) {
437 if (image[
x][
y] == 0)
continue;
441 std::sqrt(cet::square(
fHitMap[
x][
y]->RMS()) + cet::square(sigma_tick)) / (double)sigma_tick;
443 auto const& correct_kernel =
fAllKernels[sigma_wire][sigma_tick * tick_scale];
446 auto const [lower_bin_dead, upper_bin_dead] =
DeadWireCount(
x, width);
451 auto dead_wires_passed{lower_bin_dead};
454 for (
int blurx = -(width / 2 + lower_bin_dead); blurx < (width + 1) / 2 + upper_bin_dead;
456 if (
x + blurx < 0)
continue;
457 for (
int blury = -height / 2 * tick_scale;
458 blury < ((((height + 1) / 2) - 1) * tick_scale) + 1;
460 if (blurx < 0 and
fDeadWires[
x + blurx]) dead_wires_passed -= 1;
465 if (
x + blurx >= 0 and
x + blurx < nbinsx and y + blury >= 0 and
y + blury < nbinsy)
466 copy[
x + blurx][
y + blury] += weight * image[
x][
y];
468 if (blurx > 0 and
fDeadWires[
x + blurx]) dead_wires_passed += 1;
483 TString
const name)
const 485 auto hist =
new TH2F(name,
493 hist->SetXTitle(
"Wire number");
494 hist->SetYTitle(
"Tick number");
495 hist->SetZTitle(
"Charge");
497 for (
unsigned int imageWireIt = 0; imageWireIt < image.size(); ++imageWireIt) {
499 for (
unsigned int imageTickIt = 0; imageTickIt < image.at(imageWireIt).size(); ++imageTickIt) {
501 hist->Fill(wire, tick, image.at(imageWireIt).at(imageTickIt));
516 std::vector<std::vector<int>> allClusterBins;
518 for (
auto const&
cluster : allClusters) {
521 std::vector<int> clusterBins;
525 float const tick =
hit->PeakTime();
527 if (cluster.size() <
fMinSize) bin *= -1;
529 clusterBins.push_back(bin);
532 allClusterBins.push_back(clusterBins);
535 SaveImage(image, allClusterBins, pad, tpc, plane);
543 std::vector<std::vector<int>> allClusterBins;
544 SaveImage(image, allClusterBins, pad, tpc, plane);
548 std::vector<std::vector<int>>
const& allClusterBins,
557 case 1: stage =
"Stage 1: Unblurred";
break;
558 case 2: stage =
"Stage 2: Blurred";
break;
559 case 3: stage =
"Stage 3: Blurred with clusters overlaid";
break;
560 case 4: stage =
"Stage 4: Output clusters";
break;
561 default: stage =
"Unknown stage";
break;
564 std::stringstream title;
565 title << stage <<
" -- TPC " << tpc <<
", Plane " << plane;
567 image->SetName(title.str().c_str());
568 image->SetTitle(title.str().c_str());
569 image->DrawCopy(
"colz");
573 for (
auto const& bins : allClusterBins) {
574 TMarker mark(0, 0, 20);
575 mark.SetMarkerColor(clusterNum);
576 mark.SetMarkerSize(0.1);
578 for (
auto bin : bins) {
582 mark.SetMarkerStyle(24);
586 image->GetBinXYZ(
bin, wire, tick, z);
588 mark.SetMarkerStyle(20);
602 std::vector<int>
const& bins)
const 608 for (
auto const bin : bins) {
624 int const wire = bin % image.size();
625 int const tick = bin / image.size();
632 int const ybin)
const 634 return ybin * image.size() + xbin;
641 int const x = bin % image.size();
642 int const y = bin / image.size();
643 return image.at(x).at(y);
647 int const width)
const 649 auto deadWires = std::make_pair(0, 0);
651 int const lower_bin = width / 2;
652 int const upper_bin = (width + 1) / 2;
655 for (
int wire = std::max(offset - lower_bin, fLowerWire);
656 wire < std::min(offset + upper_bin,
fUpperWire);
662 else if (wire > offset)
672 double nhits{}, sumx{}, sumy{}, sumx2{}, sumxy{};
673 for (
unsigned int wireIt = 0; wireIt <
fHitMap.size(); ++wireIt) {
674 for (
unsigned int tickIt = 0; tickIt <
fHitMap.at(wireIt).size(); ++tickIt) {
675 if (
fHitMap[wireIt][tickIt].isNull())
continue;
685 double const gradient = (nhits * sumxy - sumx * sumy) / (nhits * sumx2 - sumx * sumx);
689 auto const unit = std::isnan(gradient) ? TVector2{0, 1} : TVector2{1, gradient}.Unit();
697 return {{blur_wire, blur_tick, sigma_wire, sigma_tick}};
704 return hit.isNull() ? -10000. :
hit->PeakTime();
710 std::vector<std::vector<std::vector<double>>> allKernels(
717 for (
int sigma_wire = 1; sigma_wire <=
fSigmaWire; ++sigma_wire) {
721 std::vector<double> kernel(
fKernelWidth * fKernelHeight, 0);
728 double const sig2i = 2. * sigma_wire * sigma_wire;
729 double const sig2j = 2. * sigma_tick * sigma_tick;
732 double const value = 1. / std::sqrt(sig2i * M_PI) * std::exp(-i * i / sig2i) * 1. /
733 std::sqrt(sig2j * M_PI) * std::exp(-j * j / sig2j);
734 kernel.at(key) =
value;
738 allKernels[sigma_wire][sigma_tick] = move(kernel);
745 std::vector<bool>
const& used,
748 unsigned int neighbours = 0;
751 for (
int x = -1;
x <= 1;
x++) {
752 for (
int y = -1;
y <= 1;
y++) {
753 if (
x == 0 &&
y == 0)
continue;
756 int neighbouringBin =
762 if (used.at(neighbouringBin)) neighbours++;
771 double const time)
const 773 for (
auto const t : times) {
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
float Length(const PFPStruct &pfp)
unsigned int fNeighboursThreshold
Length_t WireCoordinate(Point_t const &pos, PlaneID const &planeid) const
Returns the index of the nearest wire to the specified position.
Point_t const & GetCenter() const
Returns the world coordinate of the center of the wire [cm].
BlurredClusteringAlg(fhicl::ParameterSet const &pset)
WireGeo const & WireIDToWireGeo(WireID const &wireid) const
Returns the specified wire.
Utilities related to art service access.
TH2F * MakeHistogram(std::vector< std::vector< double >> const &image, TString name) const
Converts a 2D vector in a histogram for the debug pdf.
constexpr to_element_t to_element
std::vector< std::vector< art::Ptr< recob::Hit > > > fHitMap
std::vector< std::vector< std::vector< double > > > MakeKernels() const
Makes all the kernels which could be required given the tuned parameters.
double GetTimeOfBin(std::vector< std::vector< double >> const &image, int bin) const
Returns the hit time of a hit in a particular bin.
MaybeLogger_< ELseverityLevel::ELsev_info, false > LogInfo
bool PassesTimeCut(std::vector< double > const ×, double time) const
Determine if a hit is within a time threshold of any other hits in a cluster.
The data type to uniquely identify a Plane.
unsigned int NumNeighbours(int nx, std::vector< bool > const &used, int bin) const
Determines the number of clustered neighbours of a hit.
constexpr auto abs(T v)
Returns the absolute value of the argument.
std::array< int, 4 > FindBlurringParameters() const
Dynamically find the blurring radii and Gaussian sigma in each dimension.
CryostatID_t Cryostat
Index of cryostat.
unsigned int MaxWires() const
Returns the largest number of wires among all planes in this detector.
WireID_t Wire
Index of the wire within its plane.
std::string fDebugPDFName
Cluster finding and building.
std::vector< bool > fDeadWires
int FindClusters(std::vector< std::vector< double >> const &image, std::vector< std::vector< int >> &allcluster) const
Find clusters in the histogram.
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
art::PtrVector< recob::Hit > ConvertBinsToRecobHits(std::vector< std::vector< double >> const &image, std::vector< int > const &bins) const
Converts a vector of bins into a hit selection - not all the hits in the bins vector are real hits...
void CreateDebugPDF(int run, int subrun, int event)
Create the PDF to save debug images.
std::pair< int, int > DeadWireCount(int wire_bin, int width) const
double ConvertBinToCharge(std::vector< std::vector< double >> const &image, int bin) const
Returns the charge stored in the global bin value.
void push_back(Ptr< U > const &p)
int ConvertWireTickToBin(std::vector< std::vector< double >> const &image, int xbin, int ybin) const
Converts an xbin and a ybin to a global bin number.
Signal from induction planes.
decltype(auto) values(Coll &&coll)
Range-for loop helper iterating across the values of the specified collection.
T get(std::string const &key) const
art::Ptr< recob::Hit > ConvertBinToRecobHit(std::vector< std::vector< double >> const &image, int bin) const
Converts a bin into a recob::Hit (not all of these bins correspond to recob::Hits - some are fake hit...
int GlobalWire(geo::WireID const &wireID) const
Find the global wire position.
bool isNull() const noexcept
tick_as<> tick
Tick number, represented by std::ptrdiff_t.
std::vector< std::vector< double > > GaussianBlur(std::vector< std::vector< double >> const &image) const
Applies Gaussian blur to image.
void SaveImage(TH2F *image, std::vector< art::PtrVector< recob::Hit >> const &allClusters, int pad, int tpc, int plane)
unsigned int fMinNeighbours
PlaneID_t Plane
Index of the plane within its TPC.
Definition of data types for geometry description.
art::ServiceHandle< geo::Geometry const > fGeom
Detector simulation of raw signals on wires.
Encapsulate the geometry of a wire.
void ConvertBinsToClusters(std::vector< std::vector< double >> const &image, std::vector< std::vector< int >> const &allClusterBins, std::vector< art::PtrVector< recob::Hit >> &clusters) const
Takes a vector of clusters (itself a vector of hits) and turns them into clusters using the initial h...
raw::ChannelID_t PlaneWireToChannel(WireID const &wireid) const
Returns the ID of the TPC channel connected to the specified wire.
SigType_t SignalType(PlaneID const &pid) const
Returns the type of signal on the channels of specified TPC plane.
std::vector< std::vector< double > > ConvertRecobHitsToVector(std::vector< art::Ptr< recob::Hit >> const &hits, int readoutWindowSize)
Takes hit map and returns a 2D vector representing wire and tick, filled with the charge...
unsigned int Nwires(PlaneID const &planeid) const
Returns the total number of wires in the specified plane.
std::vector< std::vector< std::vector< double > > > fAllKernels
unsigned int ChannelID_t
Type representing the ID of a readout channel.
TPCID_t TPC
Index of the TPC within its cryostat.
lariov::ChannelStatusProvider const & fChanStatus
Event finding and building.