11 #include "art/Framework/Core/EDProducer.h"
12 #include "art/Framework/Core/ModuleMacros.h"
13 #include "art/Framework/Principal/Event.h"
14 #include "art/Framework/Principal/Handle.h"
15 #include "art/Framework/Services/Registry/ServiceHandle.h"
16 #include "art_root_io/TFileService.h"
17 #include "canvas/Persistency/Common/Ptr.h"
18 #include "cetlib/pow.h"
19 #include "fhiclcpp/ParameterSet.h"
20 #include "messagefacility/MessageLogger/MessageLogger.h"
37 Pt2D(
double _x,
double _z,
int _view,
double _energy)
55 :
m((b.
x - a.
x) / (b.
z - a.
z))
76 explicit QuadVtx(
const fhicl::ParameterSet& pset);
83 const std::vector<recob::Hit>& hits,
99 , fHitLabel(pset.
get<
std::
string>("HitLabel"))
100 , fSavePlots(pset.
get<
bool>("SavePlots"))
102 produces<std::vector<recob::Vertex>>();
109 geom = art::ServiceHandle<const geo::Geometry>()->provider();
121 const float A = 1 + cet::square(m);
122 const float B = 2 * m * c;
123 const float C = cet::square(c) - cet::square(R);
125 double desc = cet::square(B) - 4 * A * C;
127 if (desc < 0)
return false;
131 z1 = (-B - desc) / (2 * A);
132 z2 = (-B + desc) / (2 * A);
144 std::vector<Line2D>& lines,
149 constexpr
size_t kMaxLines = 10 * 1000 * 1000;
151 const size_t product = (pts.size() * (pts.size() - 1)) / 2;
152 const int stride = product / kMaxLines + 1;
154 lines.reserve(std::min(product, kMaxLines));
157 for (
unsigned int i = 0; i < pts.size(); ++i) {
158 for (
unsigned int j = i +
offset + 1; j < pts.size(); j += stride) {
159 const Line2D l(pts[i], pts[j]);
161 if (isinf(l.
m) || isnan(l.
m) || isinf(l.
c) || isnan(l.
c))
continue;
169 lines.push_back(std::move(l));
170 if (lines.size() == kMaxLines)
goto end;
177 lines.shrink_to_fit();
179 mf::LogInfo() <<
"Made " << lines.size() <<
" lines using stride " << stride
180 <<
" to fit under cap of " << kMaxLines << std::endl;
183 std::sort(lines.begin(), lines.end());
190 const float cosCrit = cos(10 * M_PI / 180.);
191 const float dot = 1 + ma * mb;
192 return cet::square(dot) > (1 + cet::square(ma)) * (1 + cet::square(mb)) * cet::square(cosCrit);
200 constexpr
size_t kMaxPts = 10 * 1000 * 1000;
203 unsigned int jmax = 0;
206 for (
unsigned int i = 0; i + 1 < lines.size(); ++i) {
209 j0 = std::max(j0, i + 1);
210 while (j0 < lines.size() &&
CloseAngles(a.
m, lines[j0].m))
212 jmax = std::max(jmax, j0);
213 while (jmax < lines.size() && !
CloseAngles(a.
m, lines[jmax].m))
219 const size_t product = (lines.size() * (lines.size() - 1)) / 2;
220 const int stride = npts / kMaxPts + 1;
222 mf::LogInfo() <<
"Combining lines to points with stride " << stride << std::endl;
224 mf::LogInfo() << npts <<
" cf " << product <<
" ie " << double(npts) / product << std::endl;
229 for (
unsigned int i = 0; i + 1 < lines.size(); ++i) {
232 j0 = std::max(j0, i + 1);
233 while (j0 < lines.size() &&
CloseAngles(a.
m, lines[j0].m))
235 jmax = std::max(jmax, j0);
236 while (jmax < lines.size() && !
CloseAngles(a.
m, lines[jmax].m))
239 for (
unsigned int j = j0; j < jmax; j += stride) {
240 const Line2D& b = lines[j];
243 const float z = (b.
c - a.
c) / (a.
m - b.
m);
244 const float x = a.
m * z + a.
c;
247 if ((z < a.minz || z > a.
maxz) && (z < b.
minz || z > b.
maxz)) {
248 const int iz = hm.
ZToBin(z);
249 const int ix = hm.
XToBin(x);
250 if (iz >= 0 && iz < hm.Nz && ix >= 0 && ix < hm.
Nx) { hm.
map[iz * hm.
Nx + ix] += stride; }
259 FindPeak3D(
const std::vector<HeatMap>& hs,
const std::vector<TVector3>& dirs) noexcept
261 assert(hs.size() == 3);
262 assert(dirs.size() == 3);
264 const int Nx = hs[0].Nx;
267 M(0, 0) = dirs[0].Y();
268 M(0, 1) = dirs[0].Z();
269 M(1, 0) = dirs[1].Y();
270 M(1, 1) = dirs[1].Z();
273 if (M(0, 0) * M(1, 1) - M(1, 0) * M(0, 1) == 0)
return TVector3(0, 0, 0);
277 float bestscore = -1;
281 std::vector<float> colMax[3];
282 for (
int view = 0; view < 3; ++view) {
283 colMax[view].resize(hs[view].Nz);
284 for (
int iz = 0; iz < hs[view].Nz; ++iz) {
285 colMax[view][iz] = *std::max_element(&hs[view].map[Nx * iz], &hs[view].map[Nx * (iz + 1)]);
289 for (
int iz = 0; iz < hs[0].Nz; ++iz) {
290 const float z = hs[0].ZBinCenter(iz);
291 const float bonus = 1;
293 for (
int iu = 0; iu < hs[1].Nz; ++iu) {
294 const float u = hs[1].ZBinCenter(iu);
299 const TVectorD
r = M *
p;
300 const float v = r[0] * dirs[2].Y() + r[1] * dirs[2].Z();
301 const int iv = hs[2].ZToBin(v);
302 if (iv < 0 || iv >= hs[2].Nz)
continue;
303 const double y =
r(0);
306 if (colMax[0][iz] + colMax[1][iu] + colMax[2][iv] < bestscore)
continue;
309 const float* __restrict__ h0 = &hs[0].map[Nx * iz];
310 const float* __restrict__ h1 = &hs[1].map[Nx * iu];
311 const float* __restrict__ h2 = &hs[2].map[Nx * iv];
314 for (
int ix = 1; ix < Nx - 1; ++ix) {
315 const float score = bonus * (h0[ix] + h1[ix] + h2[ix]);
317 if (score > bestscore) {
323 if (bestix != -1) { bestr = TVector3(hs[0].XBinCenter(bestix), y, z); }
333 const std::vector<recob::Hit>& hits,
335 std::vector<TVector3>& dirs,
340 TVector3 dirZ(0, 0, 1);
351 const double energy =
hit.Integral();
354 pts[0].emplace_back(xpos, r0.z(), 0, energy);
359 TVector3 perp = (r1 - r0).Unit();
360 perp = TVector3(0, -perp.z(), perp.y());
362 if (perp.z() < 0) perp *= -1;
367 if (dirU.Mag2() == 0) { dirU = perp; }
368 else if (dirV.Mag2() == 0 && fabs(dirU.Dot(perp)) < 0.99) {
374 if (fabs(dirU.Dot(perp)) > 0.99) { pts[1].emplace_back(xpos, r0.Dot(dirU), 1, energy); }
376 pts[2].emplace_back(xpos, r0.Dot(dirV), 2, energy);
380 dirs = {dirZ, dirU, dirV};
382 std::default_random_engine gen;
385 for (
int view = 0; view < 3; ++view) {
386 std::shuffle(pts[view].
begin(), pts[view].
end(), gen);
393 const std::vector<recob::Hit>& hits,
397 if (hits.empty())
return false;
399 std::vector<std::vector<Pt2D>> pts;
400 std::vector<TVector3> dirs;
406 double minz[3] = {+1e9, +1e9, +1e9};
407 double maxz[3] = {-1e9, -1e9, -1e9};
408 for (
int view = 0; view < 3; ++view) {
409 for (
const Pt2D&
p : pts[view]) {
410 minx = std::min(minx,
p.x);
411 maxx = std::max(maxx,
p.x);
412 minz[view] = std::min(minz[view],
p.z);
413 maxz[view] = std::max(maxz[view],
p.z);
418 for (
int view = 0; view < 3; ++view) {
427 std::vector<float> zs;
428 zs.reserve(pts[0].
size());
429 for (
const Pt2D&
p : pts[0])
431 auto mid = zs.begin() + zs.size() / 4;
432 if (mid != zs.end()) {
433 std::nth_element(zs.begin(), mid, zs.end());
437 std::vector<HeatMap> hms;
439 for (
int view = 0; view < 3; ++view) {
440 if (pts[view].
empty())
return false;
442 std::vector<Line2D> lines;
445 if (lines.empty())
return false;
448 hms.emplace_back(maxz[view] - minz[view], minz[view], maxz[view], maxx - minx, minx, maxx);
454 std::vector<HeatMap> hms_zoom;
456 for (
int view = 0; view < 3; ++view) {
457 const double x0 = vtx.X();
458 const double z0 = vtx.Dot(dirs[view]);
460 std::vector<Line2D> lines;
463 if (lines.empty())
return false;
466 hms_zoom.emplace_back(50, z0 - 2.5, z0 + 2.5, 50, x0 - 2.5, x0 + 2.5);
474 art::TFileDirectory evt_dir =
475 art::ServiceHandle<art::TFileService>()->
mkdir(TString::Format(
"evt%d", evt).Data());
477 for (
int view = 0; view < 3; ++view) {
478 art::TFileDirectory view_dir = evt_dir.mkdir(TString::Format(
"view%d", view).
Data());
480 TGraph* gpts = view_dir.makeAndRegister<TGraph>(
"hits",
"");
481 for (
const Pt2D&
p : pts[view])
482 gpts->SetPoint(gpts->GetN(),
p.z,
p.x);
484 view_dir.makeAndRegister<TH2F>(
"hmap",
"", *hms[view].AsTH2());
486 view_dir.makeAndRegister<TH2F>(
"hmap_zoom",
"", *hms_zoom[view].AsTH2());
488 const double x = vtx.X();
489 const double z = vtx.Dot(dirs[view]);
490 view_dir.makeAndRegister<TGraph>(
"vtx3d",
"", 1, &
z, &
x);
501 auto vtxcol = std::make_unique<std::vector<recob::Vertex>>();
503 art::Handle<std::vector<recob::Hit>> hits;
507 art::ServiceHandle<detinfo::DetectorPropertiesService const>()->DataFor(evt);
510 vtxcol->emplace_back(
514 evt.put(std::move(vtxcol));
process_name opflash particleana ie ie ie z
void GetPts2D(const detinfo::DetectorPropertiesData &detProp, const std::vector< recob::Hit > &hits, std::vector< std::vector< Pt2D >> &pts, std::vector< TVector3 > &dirs, const geo::GeometryCore *geom)
int XToBin(double x) const
double std(const std::vector< short > &wf, const double ped_mean, size_t start, size_t nsample)
BEGIN_PROLOG TPC Trig offset(g4 rise time) ProjectToHeight
TVector3 FindPeak3D(const std::vector< HeatMap > &hs, const std::vector< TVector3 > &dirs) noexcept
constexpr auto dot(Vector const &a, Vector const &b)
Return cross product of two vectors.
process_name opflash particleana ie x
Declaration of signal hit object.
tracking::SMatrixSym33 SMatrixSym33
BEGIN_PROLOG or score(default)}sbnd_crttrackmatchingalg_crID
int ZToBin(double z) const
std::size_t size(FixedBins< T, C > const &) noexcept
Planes which measure Z direction.
tuple m
now if test mode generate materials, CRT shell, world, gdml header else just generate CRT shell for u...
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
tracking::Point_t Point_t
bool FindVtx(const detinfo::DetectorPropertiesData &detProp, const std::vector< recob::Hit > &hits, TVector3 &vtx, int evt) const
process_name opflash particleana ie ie y
Pt2D(double _x, double _z, int _view, double _energy)
void MapFromLines(const std::vector< Line2D > &lines, HeatMap &hm)
QuadVtx(const fhicl::ParameterSet &pset)
bool IntersectsCircle(float m, float c, float z0, float x0, float R, float &z1, float &z2)
auto end(FixedBins< T, C > const &) noexcept
bool operator<(const Pt2D &p) const
Description of geometry of one entire detector.
View_t View(geo::PlaneID const &pid) const
Returns the view (wire orientation) on the channels of specified TPC plane.
double ConvertTicksToX(double ticks, int p, int t, int c) const
auto begin(FixedBins< T, C > const &) noexcept
bool CloseAngles(float ma, float mb)
bool operator<(const Line2D &l) const
void LinesFromPoints(const std::vector< Pt2D > &pts, std::vector< Line2D > &lines, float z0=0, float x0=0, float R=-1)
void WireEndPoints(geo::WireID const &wireid, double *xyzStart, double *xyzEnd) const
Fills two arrays with the coordinates of the wire end points.
2D representation of charge deposited in the TDC/wire plane
const geo::GeometryCore * geom
bool empty(FixedBins< T, C > const &) noexcept
art framework interface to geometry description
void produce(art::Event &evt) override
Line2D(const Pt2D &a, const Pt2D &b)