43 template<
class T> T
sqr(T
x){
return x*
x;}
74 bool CloseDrift(
double xa,
double xb)
const;
83 bool ISect(
int chanA,
int chanB,
geo::TPCID tpc,
86 bool ISect(
int chanA,
int chanB,
geo::TPCID tpc)
const;
88 void AddNeighbours(
const std::vector<SpaceCharge*>& spaceCharges)
const;
90 typedef std::map<const WireHit*, art::Ptr<recob::Hit>>
HitMap_t;
95 std::vector<CollectionWireHit*>& cwires,
96 std::vector<InductionWireHit*>& iwires,
98 HitMap_t& hitmap)
const;
102 std::vector<CollectionWireHit*>& cwires,
103 std::vector<InductionWireHit*>& iwires,
105 HitMap_t& hitmap)
const;
112 void FillSystemToSpacePoints(
const std::vector<CollectionWireHit*>& cwires,
115 void FillSystemToSpacePointsAndAssns(
const std::vector<CollectionWireHit*>& cwires,
116 const HitMap_t& hitmap,
136 : fHitLabel(pset.get<
std::
string>("HitLabel")),
137 fFit(pset.get<
bool>("
Fit")),
138 fAlpha(pset.get<
double>("Alpha"))
143 produces<art::Assns<recob::SpacePoint, recob::Hit>>();
160 fDeltaX = tfs->
make<TH1F>(
"deltax",
";#Deltax (cm)", 100, -2, +2);
175 typedef std::tuple<int, int, std::string> Key_t;
176 static std::unordered_map<Key_t, bool> bCache;
177 static std::unordered_map<Key_t, geo::WireIDIntersection> pCache;
180 if(bCache.size() > 1e8){
181 std::cout <<
"Clearing Intersection caches" << std::endl;
186 const Key_t key = std::make_tuple(chanA, chanB, std::string(tpc));
187 if(bCache.count(key)){
188 if(bCache[key]) pt = pCache[key];
192 const std::vector<geo::WireID> awires = geom->ChannelToWire(chanA);
193 const std::vector<geo::WireID> bwires = geom->ChannelToWire(chanB);
200 if(geom->WireIDsIntersect(awire, bwire, pt)){
216 return ISect(chanA, chanB, tpc, junk);
227 const double k = 0.2;
230 return fabs(xa-xb) < k;
237 TVector3 pa(ra.
y, ra.
z, 0);
238 TVector3 pb(rb.
y, rb.
z, 0);
243 return (pa-pb).Mag() < .35;
252 while(it != end && it->xpos < target && !CloseDrift(it->xpos, target)) ++it;
258 const std::vector<geo::WireID> ws = geom->ChannelToWire(hit.
Channel());
261 return detprop->ConvertTicksToX(hit.
PeakTime(),
w);
264 std::cout <<
"Wire does not exist on given TPC!" << std::endl;
272 static const double kCritDist = 5;
279 : fX(sc.
fX/kCritDist),
287 return std::make_tuple(fX, fY, fZ) < std::make_tuple(i.fX, i.fY, i.fZ);
290 std::vector<IntCoord> Neighbours()
const 292 std::vector<IntCoord> ret;
293 for(
int dx = -1; dx <= +1; ++dx){
294 for(
int dy = -1; dy <= +1; ++dy){
295 for(
int dz = -1; dz <= +1; ++dz){
296 ret.push_back(IntCoord(fX+dx, fY+dy, fZ+dz));
303 IntCoord(
int x,
int y,
int z) : fX(x), fY(y), fZ(z) {}
308 std::map<IntCoord, std::vector<SpaceCharge*>> scMap;
310 scMap[IntCoord(*sc)].push_back(sc);
313 std::cout <<
"Neighbour search..." << std::endl;
314 std::cout << spaceCharges.size() << std::endl;
321 for(IntCoord icn: ic.Neighbours()){
326 if(sc1 == sc2)
continue;
327 double dist2 =
sqr(sc1->fX-sc2->fX) +
sqr(sc1->fY-sc2->fY) +
sqr(sc1->fZ-sc2->fZ);
329 if(dist2 >
sqr(kCritDist))
continue;
332 std::cout <<
"ZERO DISTANCE SOMEHOW?" << std::endl;
333 std::cout << sc1->fCWire <<
" " << sc1->fWire1 <<
" " << sc1->fWire2 << std::endl;
334 std::cout << sc2->fCWire <<
" " << sc2->fWire1 <<
" " << sc2->fWire2 << std::endl;
335 std::cout << dist2 <<
" " << sc1->fX <<
" " << sc2->fX <<
" " << sc1->fY <<
" " << sc2->fY <<
" " << sc1->fZ <<
" " << sc2->fZ << std::endl;
337 dist2 =
sqr(kCritDist);
343 const double coupling = exp(-sqrt(dist2)/2);
344 sc1->fNeighbours.emplace_back(sc2, coupling);
346 if(isnan(1/sqrt(dist2)) || isinf(1/sqrt(dist2))){
347 std::cout << dist2 <<
" " << sc1->fX <<
" " << sc2->fX <<
" " << sc1->fY <<
" " << sc2->fY <<
" " << sc1->fZ <<
" " << sc2->fZ << std::endl;
354 sc1->fNeighbours.shrink_to_fit();
363 std::cout << Ntests <<
" tests to find " << Nnei << std::endl;
371 std::vector<CollectionWireHit*>& cwires,
372 std::vector<InductionWireHit*>& iwires,
376 std::map<geo::TPCID, std::vector<art::Ptr<recob::Hit>>> xhits_by_tpc;
377 for(
auto& xhit: xhits){
378 const std::vector<geo::TPCID> tpcs = geom->ROPtoTPCs(geom->ChannelToROP(xhit->Channel()));
379 assert(tpcs.size() == 1);
381 xhits_by_tpc[tpc].push_back(xhit);
386 std::map<geo::TPCID, std::vector<InductionWireWithXPos>> uwires, vwires;
388 for(
auto& ihits: {uhits, vhits}){
389 for(
auto&
hit: ihits){
390 const std::vector<geo::TPCID> tpcs = geom->ROPtoTPCs(geom->ChannelToROP(
hit->Channel()));
396 iwires.emplace_back(iwire);
400 if(xhits_by_tpc.count(tpc) == 0)
continue;
402 const double xpos = HitToXPos(*
hit, tpc);
404 if(
hit->View() ==
geo::kU) uwires[tpc].emplace_back(iwire, xpos);
405 if(
hit->View() ==
geo::kV) vwires[tpc].emplace_back(iwire, xpos);
410 for(
auto it = uwires.begin(); it != uwires.end(); ++it){
411 std::sort(it->second.begin(), it->second.end());
413 for(
auto it = vwires.begin(); it != vwires.end(); ++it){
414 std::sort(it->second.begin(), it->second.end());
417 for(
auto it = xhits_by_tpc.begin(); it != xhits_by_tpc.end(); ++it){
419 std::sort(it->second.begin(), it->second.end(),
422 return HitToXPos(*a, tpc) < HitToXPos(*b, tpc);
434 return std::make_tuple(tpc, u, v) < std::make_tuple(x.tpc, x.u, x.v);
439 std::cout <<
"Building UV table..." << std::endl;
440 std::map<UVCrossing, bool> isectUV;
441 std::map<UVCrossing, geo::WireIDIntersection> ptsUV;
443 for(
auto it: uwires){
446 auto vwires_begin = vwires[tpc].begin();
451 FastForward(vwires_begin, uwire.xpos, vwires[tpc].end());
453 for(
auto vit = vwires_begin; vit != vwires[tpc].end(); ++vit){
457 if(vwire.
xpos > uwire.xpos &&
458 !CloseDrift(uwire.xpos, vwire.
xpos))
break;
460 const UVCrossing key = {tpc, uwire.
iwire, vwire.
iwire};
462 isectUV[key] = ISect(uwire.iwire->fChannel, vwire.
iwire->
fChannel, tpc,
468 std::cout <<
"Finding XUV coincidences..." << std::endl;
469 std::vector<SpaceCharge*> spaceCharges;
471 for(
auto it: xhits_by_tpc){
474 auto uwires_begin = uwires[tpc].begin();
475 auto vwires_begin = vwires[tpc].begin();
477 for(
auto&
hit: it.second){
478 const double xpos = HitToXPos(*
hit, tpc);
480 FastForward(uwires_begin, xpos, uwires[tpc].
end());
481 FastForward(vwires_begin, xpos, vwires[tpc].
end());
485 std::vector<InductionWireWithXPos> vwires_cross;
486 std::unordered_map<InductionWireHit*, geo::WireIDIntersection> ptsXV;
487 vwires_cross.reserve(vwires[tpc].size());
488 for(
auto vit = vwires_begin; vit != vwires[tpc].end(); ++vit){
491 if(vwire.
xpos > xpos && !CloseDrift(vwire.
xpos, xpos))
break;
494 vwires_cross.push_back(vwire);
497 std::vector<SpaceCharge*> crossers;
498 for(
auto uit = uwires_begin; uit != uwires[tpc].end(); ++uit){
501 if(uwire.
xpos > xpos && !CloseDrift(uwire.
xpos, xpos))
break;
509 if(!CloseSpace(ptXU, ptXV))
continue;
511 if(!isectUV[{tpc, uwire.
iwire, vwire.iwire}])
continue;
515 if(!CloseSpace(ptXU, ptUV) ||
516 !CloseSpace(ptXV, ptUV))
continue;
518 fDeltaX->Fill(xpos-uwire.
xpos);
519 fDeltaX->Fill(xpos-vwire.xpos);
520 fDeltaX->Fill(uwire.
xpos-vwire.xpos);
529 0, uwire.
iwire, vwire.iwire);
530 spaceCharges.push_back(sc);
531 crossers.push_back(sc);
537 cwires.push_back(cwire);
542 if(incNei) AddNeighbours(spaceCharges);
549 std::vector<CollectionWireHit*>& cwires,
550 std::vector<InductionWireHit*>& iwires,
554 std::map<geo::TPCID, std::vector<art::Ptr<recob::Hit>>> xhits_by_tpc;
555 for(
auto& xhit: xhits){
556 const std::vector<geo::TPCID> tpcs = geom->ROPtoTPCs(geom->ChannelToROP(xhit->Channel()));
557 assert(tpcs.size() == 1);
559 xhits_by_tpc[tpc].push_back(xhit);
564 std::map<geo::TPCID, std::vector<InductionWireWithXPos>> uwires;
566 for(
auto&
hit: uhits){
567 const std::vector<geo::TPCID> tpcs = geom->ROPtoTPCs(geom->ChannelToROP(
hit->Channel()));
570 iwires.emplace_back(iwire);
574 if(xhits_by_tpc.count(tpc) == 0)
continue;
576 const double xpos = HitToXPos(*
hit, tpc);
578 uwires[tpc].emplace_back(iwire, xpos);
582 for(
auto it = uwires.begin(); it != uwires.end(); ++it){
583 std::sort(it->second.begin(), it->second.end());
586 for(
auto it = xhits_by_tpc.begin(); it != xhits_by_tpc.end(); ++it){
588 std::sort(it->second.begin(), it->second.end(),
591 return HitToXPos(*a, tpc) < HitToXPos(*b, tpc);
596 std::cout <<
"Finding UV coincidences..." << std::endl;
597 std::vector<SpaceCharge*> spaceCharges;
599 for(
auto it: xhits_by_tpc){
602 auto uwires_begin = uwires[tpc].begin();
604 for(
auto&
hit: it.second){
605 const double xpos = HitToXPos(*
hit, tpc);
607 std::vector<SpaceCharge*> crossers;
609 FastForward(uwires_begin, xpos, uwires[tpc].
end());
612 for(
auto uit = uwires_begin; uit != uwires[tpc].end(); ++uit){
615 if(uwire.
xpos > xpos && !CloseDrift(uwire.
xpos, xpos))
break;
623 spaceCharges.push_back(sc);
624 crossers.push_back(sc);
630 cwires.push_back(cwire);
635 if(incNei) AddNeighbours(spaceCharges);
644 static const double err[6] = {0,};
646 const float charge = sc.
fPred;
647 if(charge == 0)
return false;
649 const double xyz[3] = {sc.
fX, sc.
fY, sc.
fZ};
650 points.
add({ xyz, err, 0.0,
id }, charge);
663 AddSpacePoint(*sc, iPoint++, points);
681 if(!AddSpacePoint(*sc, iPoint++, points))
continue;
686 const auto&
hit = hitmap.at(cwire);
704 std::vector<art::Ptr<recob::Hit> > hitlist;
711 auto assns = std::make_unique<art::Assns<recob::SpacePoint, recob::Hit>>();
714 if(hits->size() < 20){
718 evt.
put(std::move(assns));
726 bool is2view =
false;
727 std::vector<art::Ptr<recob::Hit>> xhits, uhits, vhits;
728 for(
auto&
hit: hitlist){
729 if(isnan(
hit->Integral()) || isinf(
hit->Integral())){
730 std::cout <<
"WARNING: bad recob::Hit::Integral() = " 732 <<
". Skipping." << std::endl;
741 xhits.push_back(
hit);
744 xhits.push_back(
hit);
748 uhits.push_back(
hit);
758 std::vector<CollectionWireHit*> cwires;
760 std::vector<InductionWireHit*> iwires;
764 BuildSystemXU(xhits, uhits, cwires, iwires, fAlpha != 0, hitmap);
766 BuildSystemXUV(xhits, uhits, vhits, cwires, iwires, fAlpha != 0, hitmap);
768 FillSystemToSpacePoints(cwires, spcol_pre);
772 std::cout <<
"Iterating..." << std::endl;
773 double prevMetric =
Metric(cwires, 0);
774 std::cout <<
"Begin: " << prevMetric << std::endl;
775 for(
int i = 0;; ++i){
777 const double metric =
Metric(cwires, 0);
778 std::cout << i <<
" " << metric << std::endl;
779 if(fabs(metric-prevMetric) < 1
e-3*fabs(prevMetric))
break;
785 FillSystemToSpacePoints(cwires, spcol_noreg);
788 prevMetric =
Metric(cwires, fAlpha);
789 std::cout <<
"Begin: " << prevMetric << std::endl;
790 for(
int i = 0;; ++i){
792 const double metric =
Metric(cwires, fAlpha);
793 std::cout << i <<
" " << metric << std::endl;
794 if(fabs(metric-prevMetric) < 1
e-3*fabs(prevMetric))
break;
800 FillSystemToSpacePointsAndAssns(cwires, hitmap, spcol, *assns);
802 evt.
put(std::move(assns));
double z
z position of intersection
const geo::GeometryCore * geom
void produce(art::Event &evt)
cout<< "-> Edep in the target
art::Ptr< recob::SpacePoint > lastSpacePointPtr() const
Returns an art pointer to the last inserted space point (no check!).
Declaration of signal hit object.
const detinfo::DetectorProperties * detprop
std::map< const WireHit *, art::Ptr< recob::Hit > > HitMap_t
void AddNeighbours(const std::vector< SpaceCharge * > &spaceCharges) const
Planes which measure Z direction.
Information about charge reconstructed in the active volume.
InductionWireWithXPos(InductionWireHit *w, double x)
Planes which measure Y direction.
static void produces(art::ProducerBase &producer, std::string const &instanceName={})
Declares the data products being produced.
ProductID put(std::unique_ptr< PROD > &&product)
void FillSystemToSpacePointsAndAssns(const std::vector< CollectionWireHit * > &cwires, const HitMap_t &hitmap, recob::ChargedSpacePointCollectionCreator &points, art::Assns< recob::SpacePoint, recob::Hit > &assn) const
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
bool CloseDrift(double xa, double xb) const
#define DEFINE_ART_MODULE(klass)
void Iterate(CollectionWireHit *cwire, double alpha)
InductionWireHit * fWire2
virtual ~SpacePointSolver()
bool AddSpacePoint(const SpaceCharge &sc, int id, recob::ChargedSpacePointCollectionCreator &points) const
return whether the point was inserted (only happens when it has charge)
bool ISect(int chanA, int chanB, geo::TPCID tpc, geo::WireIDIntersection &pt) const
InductionWireHit * fWire1
double Metric(double q, double p)
void BuildSystemXU(const std::vector< art::Ptr< recob::Hit >> &xhits, const std::vector< art::Ptr< recob::Hit >> &uhits, std::vector< CollectionWireHit * > &cwires, std::vector< InductionWireHit * > &iwires, bool incNei, HitMap_t &hitmap) const
bool operator<(const InductionWireWithXPos &w) const
The data type to uniquely identify a TPC.
Description of geometry of one entire detector.
void BuildSystemXUV(const std::vector< art::Ptr< recob::Hit >> &xhits, const std::vector< art::Ptr< recob::Hit >> &uhits, const std::vector< art::Ptr< recob::Hit >> &vhits, std::vector< CollectionWireHit * > &cwires, std::vector< InductionWireHit * > &iwires, bool incNei, HitMap_t &hitmap) const
Detector simulation of raw signals on wires.
float PeakTime() const
Time of the signal peak, in tick units.
T * make(ARGS...args) const
Creates a collection of space points with associated charge.
Utility object to perform functions of association.
bool CloseSpace(geo::WireIDIntersection ra, geo::WireIDIntersection rb) const
void FillSystemToSpacePoints(const std::vector< CollectionWireHit * > &cwires, recob::ChargedSpacePointCollectionCreator &pts) const
bool getByLabel(std::string const &label, std::string const &productInstanceName, Handle< PROD > &result) const
double y
y position of intersection
void addSingle(Ptr< left_t > const &left, Ptr< right_t > const &right, data_t const &data)
void FastForward(std::vector< InductionWireWithXPos >::iterator &it, double target, const std::vector< InductionWireWithXPos >::const_iterator &end) const
object containing MC truth information necessary for making RawDigits and doing back tracking ...
Declaration of basic channel signal object.
Helpers to create space points with associated charge.
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
2D representation of charge deposited in the TDC/wire plane
double HitToXPos(const recob::Hit &hit, geo::TPCID tpc) const
void put()
Puts all data products into the event, leaving the creator empty().
void fill_ptr_vector(std::vector< Ptr< T >> &ptrs, H const &h)
void add(recob::SpacePoint const &spacePoint, recob::PointCharge const &charge)
Inserts the specified space point and associated data into the collection.
raw::ChannelID_t Channel() const
ID of the readout channel the hit was extracted from.
art framework interface to geometry description
Signal from collection planes.