12 #include "cetlib/pow.h" 19 : fDebug{pset.
get<
bool>(
"Debug",
false)}
20 ,
fDetector{pset.get<std::string>(
"Detector",
"dune35t")}
30 ,
fMinSize{pset.get<
unsigned int>(
"MinSize")}
31 ,
fMinSeed{pset.get<
double>(
"MinSeed")}
37 ,
fDetProp{lar::providerFrom<detinfo::DetectorPropertiesService>()}
44 closeName.append(
"]");
55 Double_t Red[2] = { 1.00, 0.00 };
56 Double_t Green[2] = { 1.00, 0.00 };
57 Double_t Blue[2] = { 1.00, 0.00 };
58 Double_t Length[2] = { 0.00, 1.00 };
59 TColor::CreateGradientColorTable(2, Length, Red, Green, Blue, 1000);
60 gStyle->SetOptStat(110000);
63 std::ostringstream oss;
64 oss <<
"BlurredImages_Run" << run <<
"_Subrun" << subrun;
77 for (
int i = 1; i <= 4; ++i) {
81 std::ostringstream oss;
82 oss <<
"Event " << event;
86 l.DrawLatex(0.1, 0.1, oss.str().c_str());
93 std::vector<std::vector<int>>
const& allClusterBins,
97 for (
auto const& bins : allClusterBins) {
101 mf::LogInfo(
"BlurredClustering") <<
"Cluster made from " << bins.size() <<
" bins, of which " << clusHits.
size() <<
" were real hits";
105 mf::LogVerbatim(
"BlurredClustering") <<
"Cluster of size " << clusHits.
size() <<
" not saved since it is smaller than the minimum cluster size, set to " <<
fMinSize;
109 clusters.push_back(clusHits);
113 std::vector<std::vector<double>>
120 if (
hit->PeakTime() < lowerTick) lowerTick =
hit->PeakTime();
121 if (
hit->PeakTime() > upperTick) upperTick =
hit->PeakTime();
122 if (histWire < lowerWire) lowerWire = histWire;
123 if (histWire > upperWire) upperWire = histWire;
138 for (
auto const&
hit : hits) {
140 auto const tick =
static_cast<int>(
hit->PeakTime());
141 float const charge =
hit->Integral();
152 geo::PlaneID const planeID = hits.front()->WireID().planeID();
154 for (
int wire = fLowerWire; wire <
fUpperWire; ++wire) {
167 int const nbinsx = blurred.size();
168 int const nbinsy = blurred.at(0).size();
169 int const nbins = nbinsx * nbinsy;
172 std::vector<bool> used(nbins);
173 std::vector<std::pair<double, int>> values;
176 for (
int xbin = 0; xbin < nbinsx; ++xbin) {
177 for (
int ybin = 0; ybin < nbinsy; ++ybin) {
184 std::sort(values.rbegin(), values.rend());
196 std::vector<double> times;
199 if (
double const blurred_binval = values[niter].first; blurred_binval <
fMinSeed)
203 int const bin = values[niter++].second;
211 cluster.push_back(bin);
214 if (
double const time =
GetTimeOfBin(blurred, bin); time > 0)
215 times.push_back(time);
220 bool added_cluster{
false};
222 for (
unsigned int clusBin = 0; clusBin < cluster.size(); ++clusBin) {
225 int const binx = cluster[clusBin] % nbinsx;
226 int const biny = ((cluster[clusBin] - binx) / nbinsx) % nbinsy;
230 if (
x >= nbinsx or
x < 0)
continue;
232 if (
y >= nbinsy or
y < 0)
continue;
233 if (
x == binx and
y == biny)
continue;
237 if (bin >= nbinsx * nbinsy or bin < 0)
247 if (time > 0 && times.size() > 0 && !
PassesTimeCut(times, time))
253 cluster.push_back(bin);
254 added_cluster =
true;
256 times.push_back(time);
272 for (
auto const bin : cluster) {
280 for (
unsigned int clusBin = 0; clusBin < cluster.size(); clusBin++) {
283 for (
int x = -1;
x <= 1; ++
x) {
284 for (
int y = -1;
y <= 1; ++
y) {
285 if (
x == 0 &&
y == 0)
continue;
288 int neighbouringBin = cluster[clusBin] +
x + (
y * nbinsx);
289 if (neighbouringBin < nbinsx || neighbouringBin % nbinsx == 0 || neighbouringBin % nbinsx == nbinsx - 1 || neighbouringBin >= nbinsx * (nbinsy - 1))
292 double const time =
GetTimeOfBin(blurred, neighbouringBin);
296 used[neighbouringBin] =
true;
297 cluster.push_back(neighbouringBin);
300 times.push_back(time);
309 mf::LogVerbatim(
"Blurred Clustering") <<
"Size of cluster after filling in holes: " << cluster.size();
314 bool removed_cluster{
false};
317 for (
int clusBin = cluster.size() - 1; clusBin >= 0; clusBin--) {
318 auto const bin = cluster[clusBin];
321 if (bin < nbinsx || bin % nbinsx == 0 || bin % nbinsx == nbinsx - 1 || bin >= nbinsx * (nbinsy - 1))
continue;
326 removed_cluster =
true;
327 cluster.erase(cluster.begin() + clusBin);
331 if (!removed_cluster)
335 mf::LogVerbatim(
"Blurred Clustering") <<
"Size of cluster after removing peninsulas: " << cluster.size();
340 for (
auto const bin : cluster) {
348 allcluster.push_back(cluster);
353 return allcluster.size();
360 double globalWire = -999;
364 double wireCentre[3];
376 if (wireID.
TPC == 0 or wireID.
TPC == 1) globalWire = wireID.
Wire;
377 else if (wireID.
TPC == 2 or wireID.
TPC == 3 or wireID.
TPC == 4 or wireID.
TPC == 5) globalWire = nwires + wireID.
Wire;
378 else if (wireID.
TPC == 6 or wireID.
TPC == 7) globalWire = (2*nwires) + wireID.
Wire;
379 else mf::LogError(
"BlurredClusterAlg") <<
"Error when trying to find a global induction plane coordinate for TPC " << wireID.
TPC <<
" (geometry " <<
fDetector <<
")";
384 int block = wireID.
TPC / 4;
385 globalWire = (nwires*block) + wireID.
Wire;
388 double wireCentre[3];
395 return std::round(globalWire);
399 std::vector<std::vector<double>>
408 int width = 2 * blur_wire + 1;
409 int height = 2 * blur_tick + 1;
410 int nbinsx = image.size();
411 int nbinsy = image.at(0).size();
414 std::vector<std::vector<double>> copy(nbinsx, std::vector<double>(nbinsy, 0));
417 for (
int x = 0;
x < nbinsx; ++
x) {
418 for (
int y = 0;
y < nbinsy; ++
y) {
420 if (image[
x][
y] == 0)
424 int tick_scale = std::sqrt(cet::square(
fHitMap[
x][
y]->RMS()) + cet::square(sigma_tick)) / (double)sigma_tick;
426 auto const& correct_kernel =
fAllKernels[sigma_wire][sigma_tick*tick_scale];
429 auto const [lower_bin_dead, upper_bin_dead] =
DeadWireCount(
x, width);
434 auto dead_wires_passed{lower_bin_dead};
437 for (
int blurx = -(width/2+lower_bin_dead); blurx < (width+1)/2+upper_bin_dead; ++blurx) {
438 if (
x + blurx < 0)
continue;
439 for (
int blury = -height/2*tick_scale; blury < ((((height+1)/2)-1)*tick_scale)+1; ++blury) {
441 dead_wires_passed -= 1;
445 if (
x + blurx >= 0 and
x + blurx < nbinsx and y + blury >= 0 and
y + blury < nbinsy)
446 copy[
x+blurx][
y+blury] += weight * image[
x][
y];
449 dead_wires_passed += 1;
468 auto hist =
new TH2F(name, name,
471 hist->SetXTitle(
"Wire number");
472 hist->SetYTitle(
"Tick number");
473 hist->SetZTitle(
"Charge");
475 for (
unsigned int imageWireIt = 0; imageWireIt < image.size(); ++imageWireIt) {
477 for (
unsigned int imageTickIt = 0; imageTickIt < image.at(imageWireIt).size(); ++imageTickIt) {
479 hist->Fill(wire, tick, image.at(imageWireIt).at(imageTickIt));
494 std::vector<std::vector<int>> allClusterBins;
496 for (
auto const&
cluster : allClusters) {
500 std::vector<int> clusterBins;
504 float const tick =
hit->PeakTime();
509 clusterBins.push_back(bin);
512 allClusterBins.push_back(clusterBins);
515 SaveImage(image, allClusterBins, pad, tpc, plane);
524 std::vector<std::vector<int>> allClusterBins;
525 SaveImage(image, allClusterBins, pad, tpc, plane);
530 std::vector<std::vector<int>>
const& allClusterBins,
540 stage =
"Stage 1: Unblurred";
543 stage =
"Stage 2: Blurred";
546 stage =
"Stage 3: Blurred with clusters overlaid";
549 stage =
"Stage 4: Output clusters";
552 stage =
"Unknown stage";
556 std::stringstream title;
557 title << stage <<
" -- TPC " << tpc <<
", Plane " << plane;
559 image->SetName(title.str().c_str());
560 image->SetTitle(title.str().c_str());
561 image->DrawCopy(
"colz");
565 for (
auto const& bins : allClusterBins) {
566 TMarker mark(0, 0, 20);
567 mark.SetMarkerColor(clusterNum);
568 mark.SetMarkerSize(0.1);
570 for (
auto bin : bins) {
574 mark.SetMarkerStyle(24);
578 image->GetBinXYZ(
bin,wire,tick,z);
580 mark.SetMarkerStyle(20);
595 std::vector<int>
const& bins)
const 601 for (
auto const bin : bins) {
618 int const wire = bin % image.size();
619 int const tick = bin / image.size();
626 int const ybin)
const 628 return ybin * image.size() + xbin;
635 int const x = bin % image.size();
636 int const y = bin / image.size();
637 return image.at(x).at(y);
643 auto deadWires = std::make_pair(0, 0);
645 int const lower_bin = width / 2;
646 int const upper_bin = (width+1) / 2;
654 else if (wire > offset)
666 double nhits{}, sumx{}, sumy{}, sumx2{}, sumxy{};
667 for (
unsigned int wireIt = 0; wireIt <
fHitMap.size(); ++wireIt) {
668 for (
unsigned int tickIt = 0; tickIt <
fHitMap.at(wireIt).size(); ++tickIt) {
669 if (
fHitMap[wireIt][tickIt].isNull())
680 double const gradient = (nhits * sumxy - sumx * sumy) / (nhits * sumx2 - sumx * sumx);
684 auto const unit = std::isnan(gradient) ? TVector2{0, 1} : TVector2{1, gradient}.Unit();
692 return {{blur_wire, blur_tick, sigma_wire, sigma_tick}};
700 return hit.isNull() ? -10000. :
hit->PeakTime();
703 std::vector<std::vector<std::vector<double>>>
707 std::vector<std::vector<std::vector<double>>> allKernels(
fSigmaWire + 1,
712 for (
int sigma_wire = 1; sigma_wire <=
fSigmaWire; ++sigma_wire) {
716 std::vector<double> kernel(
fKernelWidth*fKernelHeight,0);
723 double const sig2i = 2. * sigma_wire * sigma_wire;
724 double const sig2j = 2. * sigma_tick * sigma_tick;
727 double const value = 1. / std::sqrt(sig2i * M_PI) * std::exp(-i * i / sig2i) * 1. / std::sqrt(sig2j * M_PI) * std::exp(-j * j / sig2j);
728 kernel.at(key) =
value;
733 allKernels[sigma_wire][sigma_tick] = move(kernel);
741 std::vector<bool>
const& used,
744 unsigned int neighbours = 0;
747 for (
int x = -1;
x <= 1;
x++) {
748 for (
int y = -1;
y <= 1;
y++) {
749 if (
x == 0 &&
y == 0)
continue;
752 int neighbouringBin = bin +
x + (
y * nbinsx);
755 if (used.at(neighbouringBin))
766 double const time)
const 768 for (
auto const t : times) {
geo::Length_t WireCoordinate(double YPos, double ZPos, geo::PlaneID const &planeid) const
Returns the index of the nearest wire to the specified position.
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
unsigned int fNeighboursThreshold
BlurredClusteringAlg(fhicl::ParameterSet const &pset)
virtual unsigned int ReadOutWindowSize() const =0
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.
std::vector< std::vector< double > > ConvertRecobHitsToVector(std::vector< art::Ptr< recob::Hit >> const &hits)
Takes hit map and returns a 2D vector representing wire and tick, filled with the charge...
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
SigType_t SignalType(geo::PlaneID const &pid) const
Returns the type of signal on the channels of specified TPC plane.
Cluster finding and building.
art::ServiceHandle< geo::Geometry > fGeom
std::vector< bool > fDeadWires
int FindClusters(std::vector< std::vector< double >> const &image, std::vector< std::vector< int >> &allcluster)
Find clusters in the histogram.
unsigned int Nwires(unsigned int p, unsigned int tpc=0, unsigned int cstat=0) const
Returns the total number of wires in the specified plane.
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.
TH2F * MakeHistogram(std::vector< std::vector< double >> const &image, TString name)
Converts a 2D vector in a histogram for the debug pdf.
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...
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.
Detector simulation of raw signals on wires.
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.
std::string value(boost::any const &)
std::vector< std::vector< double > > GaussianBlur(std::vector< std::vector< double >> const &image)
Applies Gaussian blur to image.
std::vector< std::vector< std::vector< double > > > fAllKernels
void GetCenter(double *xyz, double localz=0.0) const
Fills the world coordinate of a point on the 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
detinfo::DetectorProperties const * fDetProp
Event finding and building.
WireGeo const & WireIDToWireGeo(geo::WireID const &wireid) const
Returns the specified wire.
int GlobalWire(geo::WireID const &wireID)
Find the global wire position.