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)
141 using ranges::views::transform;
144 if (
hit.PeakTime() < lowerTick) lowerTick =
hit.PeakTime();
145 if (
hit.PeakTime() > upperTick) upperTick =
hit.PeakTime();
146 if (histWire < lowerWire) lowerWire = histWire;
147 if (histWire > upperWire) upperWire = histWire;
166 auto const tick =
static_cast<int>(
hit->PeakTime());
167 float const charge =
hit->Integral();
180 for (
int wire = fLowerWire; wire <
fUpperWire; ++wire) {
193 int const nbinsx = blurred.size();
194 int const nbinsy = blurred.at(0).size();
195 int const nbins = nbinsx * nbinsy;
198 std::vector<bool> used(nbins);
199 std::vector<std::pair<double, int>>
values;
202 for (
int xbin = 0; xbin <
nbinsx; ++xbin) {
203 for (
int ybin = 0; ybin < nbinsy; ++ybin) {
210 std::sort(values.rbegin(), values.rend());
222 std::vector<double> times;
225 if (
double const blurred_binval = values[niter].first; blurred_binval <
fMinSeed)
break;
228 int const bin = values[niter++].second;
231 if (used[bin])
continue;
235 cluster.push_back(bin);
238 if (
double const time =
GetTimeOfBin(blurred, bin); time > 0) times.push_back(time);
243 bool added_cluster{
false};
245 for (
unsigned int clusBin = 0; clusBin < cluster.size(); ++clusBin) {
248 int const binx = cluster[clusBin] %
nbinsx;
249 int const biny = ((cluster[clusBin] - binx) / nbinsx) % nbinsy;
253 if (
x >= nbinsx or
x < 0)
continue;
255 if (
y >= nbinsy or
y < 0)
continue;
256 if (
x == binx and
y == biny)
continue;
260 if (bin >= nbinsx * nbinsy or bin < 0)
continue;
261 if (used[bin])
continue;
269 if (time > 0 && times.size() > 0 && !
PassesTimeCut(times, time))
continue;
274 cluster.push_back(bin);
275 added_cluster =
true;
276 if (time > 0) { times.push_back(time); }
283 if (!added_cluster)
break;
289 for (
auto const bin : cluster) {
297 for (
unsigned int clusBin = 0; clusBin < cluster.size(); clusBin++) {
300 for (
int x = -1;
x <= 1; ++
x) {
301 for (
int y = -1;
y <= 1; ++
y) {
302 if (
x == 0 &&
y == 0)
continue;
305 int neighbouringBin = cluster[clusBin] +
x + (
y *
nbinsx);
306 if (neighbouringBin < nbinsx || neighbouringBin % nbinsx == 0 ||
307 neighbouringBin % nbinsx == nbinsx - 1 || neighbouringBin >= nbinsx * (nbinsy - 1))
310 double const time =
GetTimeOfBin(blurred, neighbouringBin);
313 if (!used[neighbouringBin] &&
316 used[neighbouringBin] =
true;
317 cluster.push_back(neighbouringBin);
319 if (time > 0) { times.push_back(time); }
327 <<
"Size of cluster after filling in holes: " << cluster.size();
331 bool removed_cluster{
false};
334 for (
int clusBin = cluster.size() - 1; clusBin >= 0; clusBin--) {
335 auto const bin = cluster[clusBin];
338 if (bin < nbinsx || bin % nbinsx == 0 || bin % nbinsx == nbinsx - 1 ||
339 bin >= nbinsx * (nbinsy - 1))
345 removed_cluster =
true;
346 cluster.erase(cluster.begin() + clusBin);
350 if (!removed_cluster)
break;
354 <<
"Size of cluster after removing peninsulas: " << cluster.size();
358 for (
auto const bin : cluster) {
366 allcluster.push_back(cluster);
371 return allcluster.size();
376 double globalWire = -999;
383 .WireCoordinate(wireCenter);
393 if (wireID.
TPC == 0 or wireID.
TPC == 1)
394 globalWire = wireID.
Wire;
395 else if (wireID.
TPC == 2 or wireID.
TPC == 3 or wireID.
TPC == 4 or wireID.
TPC == 5)
396 globalWire = nwires + wireID.
Wire;
397 else if (wireID.
TPC == 6 or wireID.
TPC == 7)
398 globalWire = (2 * nwires) + wireID.
Wire;
401 <<
"Error when trying to find a global induction plane coordinate for TPC " << wireID.
TPC 407 int block = wireID.
TPC / 4;
408 globalWire = (nwires * block) + wireID.
Wire;
414 .WireCoordinate(wireCenter);
418 return std::round(globalWire);
422 std::vector<std::vector<double>>
const& image)
const 429 int width = 2 * blur_wire + 1;
430 int height = 2 * blur_tick + 1;
431 int nbinsx = image.size();
432 int nbinsy = image.at(0).size();
435 std::vector<std::vector<double>> copy(nbinsx, std::vector<double>(nbinsy, 0));
439 for (
int y = 0;
y < nbinsy; ++
y) {
441 if (image[
x][
y] == 0)
continue;
445 std::sqrt(cet::square(
fHitMap[
x][
y]->RMS()) + cet::square(sigma_tick)) / (double)sigma_tick;
447 auto const& correct_kernel =
fAllKernels[sigma_wire][sigma_tick * tick_scale];
450 auto const [lower_bin_dead, upper_bin_dead] =
DeadWireCount(
x, width);
455 auto dead_wires_passed{lower_bin_dead};
458 for (
int blurx = -(width / 2 + lower_bin_dead); blurx < (width + 1) / 2 + upper_bin_dead;
460 if (
x + blurx < 0)
continue;
461 for (
int blury = -height / 2 * tick_scale;
462 blury < ((((height + 1) / 2) - 1) * tick_scale) + 1;
464 if (blurx < 0 and
fDeadWires[
x + blurx]) dead_wires_passed -= 1;
469 if (
x + blurx >= 0 and
x + blurx < nbinsx and y + blury >= 0 and
y + blury < nbinsy)
470 copy[
x + blurx][
y + blury] += weight * image[
x][
y];
472 if (blurx > 0 and
fDeadWires[
x + blurx]) dead_wires_passed += 1;
487 TString
const name)
const 489 auto hist =
new TH2F(name,
497 hist->SetXTitle(
"Wire number");
498 hist->SetYTitle(
"Tick number");
499 hist->SetZTitle(
"Charge");
501 for (
unsigned int imageWireIt = 0; imageWireIt < image.size(); ++imageWireIt) {
503 for (
unsigned int imageTickIt = 0; imageTickIt < image.at(imageWireIt).size(); ++imageTickIt) {
505 hist->Fill(wire, tick, image.at(imageWireIt).at(imageTickIt));
520 std::vector<std::vector<int>> allClusterBins;
522 for (
auto const&
cluster : allClusters) {
525 std::vector<int> clusterBins;
529 float const tick =
hit->PeakTime();
531 if (cluster.size() <
fMinSize) bin *= -1;
533 clusterBins.push_back(bin);
536 allClusterBins.push_back(clusterBins);
539 SaveImage(image, allClusterBins, pad, tpc, plane);
547 std::vector<std::vector<int>> allClusterBins;
548 SaveImage(image, allClusterBins, pad, tpc, plane);
552 std::vector<std::vector<int>>
const& allClusterBins,
561 case 1: stage =
"Stage 1: Unblurred";
break;
562 case 2: stage =
"Stage 2: Blurred";
break;
563 case 3: stage =
"Stage 3: Blurred with clusters overlaid";
break;
564 case 4: stage =
"Stage 4: Output clusters";
break;
565 default: stage =
"Unknown stage";
break;
568 std::stringstream title;
569 title << stage <<
" -- TPC " << tpc <<
", Plane " << plane;
571 image->SetName(title.str().c_str());
572 image->SetTitle(title.str().c_str());
573 image->DrawCopy(
"colz");
577 for (
auto const& bins : allClusterBins) {
578 TMarker mark(0, 0, 20);
579 mark.SetMarkerColor(clusterNum);
580 mark.SetMarkerSize(0.1);
582 for (
auto bin : bins) {
586 mark.SetMarkerStyle(24);
590 image->GetBinXYZ(
bin, wire, tick, z);
592 mark.SetMarkerStyle(20);
606 std::vector<int>
const& bins)
const 612 for (
auto const bin : bins) {
628 int const wire = bin % image.size();
629 int const tick = bin / image.size();
636 int const ybin)
const 638 return ybin * image.size() + xbin;
645 int const x = bin % image.size();
646 int const y = bin / image.size();
647 return image.at(x).at(y);
651 int const width)
const 653 auto deadWires = std::make_pair(0, 0);
655 int const lower_bin = width / 2;
656 int const upper_bin = (width + 1) / 2;
659 for (
int wire = std::max(offset - lower_bin, fLowerWire);
660 wire < std::min(offset + upper_bin,
fUpperWire);
666 else if (wire > offset)
676 double nhits{}, sumx{}, sumy{}, sumx2{}, sumxy{};
677 for (
unsigned int wireIt = 0; wireIt <
fHitMap.size(); ++wireIt) {
678 for (
unsigned int tickIt = 0; tickIt <
fHitMap.at(wireIt).size(); ++tickIt) {
679 if (
fHitMap[wireIt][tickIt].isNull())
continue;
689 double const gradient = (nhits * sumxy - sumx * sumy) / (nhits * sumx2 - sumx * sumx);
693 auto const unit = std::isnan(gradient) ? TVector2{0, 1} : TVector2{1, gradient}.Unit();
701 return {{blur_wire, blur_tick, sigma_wire, sigma_tick}};
708 return hit.isNull() ? -10000. :
hit->PeakTime();
714 std::vector<std::vector<std::vector<double>>> allKernels(
721 for (
int sigma_wire = 1; sigma_wire <=
fSigmaWire; ++sigma_wire) {
725 std::vector<double> kernel(
fKernelWidth * fKernelHeight, 0);
732 double const sig2i = 2. * sigma_wire * sigma_wire;
733 double const sig2j = 2. * sigma_tick * sigma_tick;
736 double const value = 1. / std::sqrt(sig2i * M_PI) * std::exp(-i * i / sig2i) * 1. /
737 std::sqrt(sig2j * M_PI) * std::exp(-j * j / sig2j);
738 kernel.at(key) =
value;
742 allKernels[sigma_wire][sigma_tick] = move(kernel);
749 std::vector<bool>
const& used,
752 unsigned int neighbours = 0;
755 for (
int x = -1;
x <= 1;
x++) {
756 for (
int y = -1;
y <= 1;
y++) {
757 if (
x == 0 &&
y == 0)
continue;
760 int neighbouringBin =
766 if (used.at(neighbouringBin)) neighbours++;
775 double const time)
const 777 for (
auto const t : times) {
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
float Length(const PFPStruct &pfp)
unsigned int fNeighboursThreshold
Point_t const & GetCenter() const
Returns the world coordinate of the center of the wire [cm].
BlurredClusteringAlg(fhicl::ParameterSet const &pset)
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
unsigned int Nwires(PlaneID const &planeid) const
Returns the total number of wires in the specified plane.
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.
WireID_t Wire
Index of the wire within its plane.
std::string fDebugPDFName
SigType_t SignalType(PlaneID const &pid) const
Returns the type of signal on the channels of specified TPC plane.
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.
WireGeo const & Wire(WireID const &wireid) const
Returns the specified wire.
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.
unsigned int MaxWires() const
Returns the total number of wires in the specified plane.
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.
virtual raw::ChannelID_t PlaneWireToChannel(WireID const &wireID) const =0
Returns the channel ID a wire is connected to.
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.
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...
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...
geo::WireReadoutGeom const * fWireReadoutGeom
std::vector< std::vector< std::vector< double > > > fAllKernels
PlaneGeo const & Plane(TPCID const &tpcid, View_t view) const
Returns the specified wire.
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.