Public Member Functions | Private Member Functions | Private Attributes | List of all members
gar::rec::tpccathodestitch Class Reference
Inheritance diagram for gar::rec::tpccathodestitch:
art::EDProducer art::detail::Producer art::detail::LegacyModule art::Modifier art::ModuleBase art::ProductRegistryHelper

Public Member Functions

 tpccathodestitch (fhicl::ParameterSet const &p)
 
 tpccathodestitch (tpccathodestitch const &)=delete
 
 tpccathodestitch (tpccathodestitch &&)=delete
 
tpccathodestitchoperator= (tpccathodestitch const &)=delete
 
tpccathodestitchoperator= (tpccathodestitch &&)=delete
 
void produce (art::Event &e) override
 
- Public Member Functions inherited from art::EDProducer
 EDProducer (fhicl::ParameterSet const &pset)
 
template<typename Config >
 EDProducer (Table< Config > const &config)
 
std::string workerType () const
 
- Public Member Functions inherited from art::detail::Producer
virtual ~Producer () noexcept
 
 Producer (fhicl::ParameterSet const &)
 
 Producer (Producer const &)=delete
 
 Producer (Producer &&)=delete
 
Produceroperator= (Producer const &)=delete
 
Produceroperator= (Producer &&)=delete
 
void doBeginJob (SharedResources const &resources)
 
void doEndJob ()
 
void doRespondToOpenInputFile (FileBlock const &fb)
 
void doRespondToCloseInputFile (FileBlock const &fb)
 
void doRespondToOpenOutputFiles (FileBlock const &fb)
 
void doRespondToCloseOutputFiles (FileBlock const &fb)
 
bool doBeginRun (RunPrincipal &rp, ModuleContext const &mc)
 
bool doEndRun (RunPrincipal &rp, ModuleContext const &mc)
 
bool doBeginSubRun (SubRunPrincipal &srp, ModuleContext const &mc)
 
bool doEndSubRun (SubRunPrincipal &srp, ModuleContext const &mc)
 
bool doEvent (EventPrincipal &ep, ModuleContext const &mc, std::atomic< std::size_t > &counts_run, std::atomic< std::size_t > &counts_passed, std::atomic< std::size_t > &counts_failed)
 
- Public Member Functions inherited from art::Modifier
 ~Modifier () noexcept
 
 Modifier ()
 
 Modifier (Modifier const &)=delete
 
 Modifier (Modifier &&)=delete
 
Modifieroperator= (Modifier const &)=delete
 
Modifieroperator= (Modifier &&)=delete
 
- Public Member Functions inherited from art::ModuleBase
virtual ~ModuleBase () noexcept
 
 ModuleBase ()
 
ModuleDescription const & moduleDescription () const
 
void setModuleDescription (ModuleDescription const &)
 
std::array< std::vector< ProductInfo >, NumBranchTypes > const & getConsumables () const
 
void sortConsumables (std::string const &current_process_name)
 
template<typename T , BranchType BT>
ViewToken< T > consumesView (InputTag const &tag)
 
template<typename T , BranchType BT>
ViewToken< T > mayConsumeView (InputTag const &tag)
 

Private Member Functions

bool cathodematch (const gar::rec::Track &trackA, const gar::rec::Track &trackB, int &fwdflagA, int &fwdflagB, float &deltaX)
 

Private Attributes

std::string fInputTrackLabel
 input tracks and associations with TPCClusters. Get vertices associated with these tracks from the assns More...
 
std::string fInputVertexLabel
 input vertices and associations with tracks More...
 
std::string fInputTPCClusterLabel
 input TPC Clusters More...
 
std::string fInputHitLabel
 needed to make TPCCluster - hit associations More...
 
int fPrintLevel
 debug printout: 0: none, 1: just track parameters and residuals, 2: all More...
 
float fDistCut
 cut in distance between best-matching points More...
 
float fCTCut
 cut on cosine of angle matching More...
 
float fMaxDX
 cut on maximum translation of dX on one side. More...
 
float fMinDX
 cut on minimum translation of dX on one side. More...
 

Additional Inherited Members

- Public Types inherited from art::EDProducer
using ModuleType = EDProducer
 
using WorkerType = WorkerT< EDProducer >
 
- Public Types inherited from art::detail::Producer
template<typename UserConfig , typename KeysToIgnore = void>
using Table = Modifier::Table< UserConfig, KeysToIgnore >
 
- Public Types inherited from art::Modifier
template<typename UserConfig , typename UserKeysToIgnore = void>
using Table = ProducerTable< UserConfig, detail::ModuleConfig, UserKeysToIgnore >
 
- Static Public Member Functions inherited from art::EDProducer
static void commitEvent (EventPrincipal &ep, Event &e)
 
- Protected Member Functions inherited from art::ModuleBase
ConsumesCollectorconsumesCollector ()
 
template<typename T , BranchType = InEvent>
ProductToken< T > consumes (InputTag const &)
 
template<typename Element , BranchType = InEvent>
ViewToken< Element > consumesView (InputTag const &)
 
template<typename T , BranchType = InEvent>
void consumesMany ()
 
template<typename T , BranchType = InEvent>
ProductToken< T > mayConsume (InputTag const &)
 
template<typename Element , BranchType = InEvent>
ViewToken< Element > mayConsumeView (InputTag const &)
 
template<typename T , BranchType = InEvent>
void mayConsumeMany ()
 

Detailed Description

Definition at line 61 of file tpccathodestitch_module.cc.

Constructor & Destructor Documentation

gar::rec::tpccathodestitch::tpccathodestitch ( fhicl::ParameterSet const &  p)
explicit

Definition at line 100 of file tpccathodestitch_module.cc.

100  : EDProducer{p}
101  {
102  fInputTrackLabel = p.get<std::string>("InputTrackLabel","track");
103  fInputVertexLabel = p.get<std::string>("InputVertexLabel","vertex");
104  fInputTPCClusterLabel = p.get<std::string>("InputTPCClusterLabel","tpccluster");
105  fInputHitLabel = p.get<std::string>("InputHitLabel","hit");
106  fPrintLevel = p.get<int>("PrintLevel",0);
107  fDistCut = p.get<float>("DistCut",3);
108  fCTCut = p.get<float>("CTCut",0.99);
109  fMaxDX = p.get<float>("MaxDX",50.0);
110  fMinDX = p.get<float>("MinDX",-50.0);
111 
112  art::InputTag inputTrackTag(fInputTrackLabel);
113  consumes< std::vector<rec::Track> >(inputTrackTag);
114  consumes< art::Assns<rec::TPCCluster, rec::Track> >(inputTrackTag);
115  art::InputTag inputVertexTag(fInputVertexLabel);
116  consumes< art::Assns<rec::Vertex, rec::Track> >(inputVertexTag);
117  consumes<std::vector<rec::TrackIoniz>>(inputTrackTag);
118  consumes<art::Assns<rec::TrackIoniz, rec::Track>>(inputTrackTag);
119  art::InputTag inputHitTag(fInputHitLabel);
120  consumes<art::Assns<rec::Hit, rec::TPCCluster>>(inputHitTag);
121  art::InputTag inputTPCClusterTag(fInputTPCClusterLabel);
122  consumes< std::vector<rec::TPCCluster>>(inputTPCClusterTag);
123 
124  // probably don't need the vector hits at this point if we have the TPCClusters
125  //consumes< std::vector<rec::VecHit> >(patrecTag);
126  //consumes< art::Assns<rec::VecHit, rec::Track> >(patrecTag);
127 
128  produces< std::vector<rec::Track> >();
129  produces< art::Assns<rec::TPCCluster, rec::Track> >();
130  produces<std::vector<rec::TrackIoniz>>();
131  produces<art::Assns<rec::TrackIoniz, rec::Track>>();
132  produces< std::vector<rec::Vertex> >();
133  produces< art::Assns<rec::Track, rec::Vertex, rec::TrackEnd> >();
134  produces< std::vector<gar::rec::TPCCluster> >();
135  produces< art::Assns<gar::rec::Hit, gar::rec::TPCCluster> >();
136  }
std::string fInputTrackLabel
input tracks and associations with TPCClusters. Get vertices associated with these tracks from the as...
std::string string
Definition: nybbler.cc:12
EDProducer(fhicl::ParameterSet const &pset)
Definition: EDProducer.h:20
int fPrintLevel
debug printout: 0: none, 1: just track parameters and residuals, 2: all
std::string fInputTPCClusterLabel
input TPC Clusters
float fMinDX
cut on minimum translation of dX on one side.
std::string fInputVertexLabel
input vertices and associations with tracks
p
Definition: test.py:223
float fDistCut
cut in distance between best-matching points
float fMaxDX
cut on maximum translation of dX on one side.
std::string fInputHitLabel
needed to make TPCCluster - hit associations
float fCTCut
cut on cosine of angle matching
gar::rec::tpccathodestitch::tpccathodestitch ( tpccathodestitch const &  )
delete
gar::rec::tpccathodestitch::tpccathodestitch ( tpccathodestitch &&  )
delete

Member Function Documentation

bool gar::rec::tpccathodestitch::cathodematch ( const gar::rec::Track trackA,
const gar::rec::Track trackB,
int &  fwdflagA,
int &  fwdflagB,
float &  deltaX 
)
private

Definition at line 642 of file tpccathodestitch_module.cc.

643  {
644  afw = 0;
645  bfw = 0;
646  bool matchable = false;
647 
648  // may not need this yet -- but magnetic field will be a function of position someday
649  // auto const *magFieldService = gar::providerFrom<mag::MagneticFieldService>();
650  // G4ThreeVector zerovec(0,0,0);
651  // G4ThreeVector magfield = magFieldService->FieldAtPoint(zerovec);
652 
654  double xtpccent = geo->TPCXCent();
655  TVector3 xhat(1,0,0);
656  TVector3 xcentv = xhat*xtpccent;
657 
658  std::vector<TVector3> apt; // endpoint
659  std::vector<TVector3> bpt;
660  std::vector<TVector3> adir; // direction
661  std::vector<TVector3> bdir;
662 
663  apt.emplace_back(atrack.Vertex());
664  apt.emplace_back(atrack.End());
665  adir.emplace_back(atrack.VtxDir());
666  adir.emplace_back(atrack.EndDir());
667  bpt.emplace_back(btrack.Vertex());
668  bpt.emplace_back(btrack.End());
669  bdir.emplace_back(btrack.VtxDir());
670  bdir.emplace_back(btrack.EndDir());
671 
672  // center the postions on the center of the detector
673 
674  for (size_t i=0; i<apt.size(); ++i) apt.at(i) -= xcentv;
675  for (size_t i=0; i<bpt.size(); ++i) bpt.at(i) -= xcentv;
676 
677  std::vector<int> fwflag = {2, 1};
678 
679  for (size_t ia=0; ia<apt.size(); ++ia)
680  {
681  for (size_t ib=0; ib<bpt.size(); ++ib)
682  {
683  // directions should point along track pieces to stitch, so they should be back to back
684  TVector3 v=adir.at(ia);
685  TVector3 u=bdir.at(ib);
686 
687  if (v.Dot(u) > -fCTCut) continue;
688 
689  // simple comparisons of vertex positions. Ignores the fact that we may be missing
690  // part of one of the tracks near the endpoint due to the gaps or patrec failure
691  //if ( ((apt.at(ia)-bpt.at(ib)).Cross(xhat)).Mag() > dYZCut) continue;
692  //if (TMath::Abs(apt.at(ia).X() + bpt.at(ib).X()) > fdXCut) continue;
693 
694  // solved for X shift called tau
695 
696  float tdenom = 1.0 - TMath::Sq(xhat.Dot(v));
697  if (tdenom == 0) continue;
698  TVector3 d = apt.at(ia) - bpt.at(ib);
699  float tau = (0.5/tdenom) * d.Dot( (v.Dot(xhat))*v - xhat );
700 
701  if (tau > fMaxDX) continue;
702  if (tau < fMinDX) continue;
703 
704  // solve for displacement along adir.
705 
706  float gamma = -v.Dot(2*tau*xhat + d);
707  TVector3 chivec = d + gamma*v + 2.0*tau*xhat;
708  if (chivec.Mag() > fDistCut) continue;
709 
710  // we have a match
711  afw = fwflag.at(ia);
712  bfw = fwflag.at(1-ib);
713  deltaX = tau;
714  matchable = true;
715 
716  break; // just find the first match -- possible to match the same tracks with different endpoints?
717  }
718  if (matchable) break;
719  }
720  return matchable;
721  }
float fMinDX
cut on minimum translation of dX on one side.
float fDistCut
cut in distance between best-matching points
double gamma(double KE, const simb::MCParticle *part)
float fMaxDX
cut on maximum translation of dX on one side.
float fCTCut
cut on cosine of angle matching
LArSoft geometry interface.
Definition: ChannelGeo.h:16
tpccathodestitch& gar::rec::tpccathodestitch::operator= ( tpccathodestitch const &  )
delete
tpccathodestitch& gar::rec::tpccathodestitch::operator= ( tpccathodestitch &&  )
delete
void gar::rec::tpccathodestitch::produce ( art::Event e)
overridevirtual

Implements art::EDProducer.

Definition at line 140 of file tpccathodestitch_module.cc.

141  {
142 
143  // some useful structs
144 
145  typedef struct locVtx
146  {
147  float fPosition[3];
148  float fCovMat[9];
149  double fTime;
150  } locVtx_t;
151 
152  // for keeping a list of track endpoints associated with vertices. Keep dx in here so we can average
153  // it at a later step
154 
155  typedef struct trkiend
156  {
157  size_t trkindex;
158  rec::TrackEnd trkend;
159  float dx;
160  } trkiend_t;
161 
163  float xtpccent = geo->TPCXCent();
164 
165  // get the distance corresponding to one ADC tick so we can report the time in ticks
166 
167  auto detProp = gar::providerFrom<detinfo::DetectorPropertiesService>();
168  double DriftVelocity = detProp->DriftVelocity(detProp->Efield(),detProp->Temperature()); // in cm per microsecond
169  //auto clockService = gar::providerFrom<detinfo::DetectorClocksServiceGAr>();
170  //double distonetick = DriftVelocity * (clockService->TPCTick2Time(1) - clockService->TPCTick2Time(0)) ;
171 
172  // output collections
173 
174  std::unique_ptr< std::vector<rec::Track> > trkCol(new std::vector<rec::Track>);
175  std::unique_ptr<std::vector<gar::rec::TPCCluster> > TPCClusterCol (new std::vector<gar::rec::TPCCluster> );
176  std::unique_ptr< art::Assns<rec::TPCCluster,rec::Track> > TPCClusterTrkAssns(new art::Assns<rec::TPCCluster,rec::Track>);
177  std::unique_ptr< std::vector<rec::TrackIoniz> > ionCol(new std::vector<rec::TrackIoniz>);
178  std::unique_ptr< art::Assns<rec::TrackIoniz,rec::Track> > ionTrkAssns(new art::Assns<rec::TrackIoniz,rec::Track>);
179  std::unique_ptr< std::vector<rec::Vertex> > vtxCol(new std::vector<rec::Vertex>);
180  std::unique_ptr< art::Assns<rec::Track, rec::Vertex, rec::TrackEnd> > trkVtxAssns(new art::Assns<rec::Track, rec::Vertex, rec::TrackEnd>);
181  std::unique_ptr< art::Assns<rec::Hit,rec::TPCCluster> > HitTPCClusterAssns(new art::Assns<rec::Hit,rec::TPCCluster>);
182 
183  // inputs
184 
185  auto inputTrackHandle = e.getValidHandle< std::vector<rec::Track> >(fInputTrackLabel);
186  auto const& inputTracks = *inputTrackHandle;
187  auto inputTPCClusterHandle = e.getValidHandle< std::vector<rec::TPCCluster> >(fInputTPCClusterLabel);
188  auto const& inputTPCClusters = *inputTPCClusterHandle;
189 
190  const art::FindManyP<rec::TPCCluster> TPCClustersFromInputTracks(inputTrackHandle,e,fInputTrackLabel);
191  const art::FindManyP<rec::TrackIoniz> TrackIonizFromInputTracks(inputTrackHandle,e,fInputTrackLabel);
192  const art::FindManyP<rec::Vertex, rec::TrackEnd> VerticesFromInputTracks(inputTrackHandle,e,fInputVertexLabel);
193  const art::FindManyP<rec::Hit> HitsFromInputTPCClusters(inputTPCClusterHandle,e,fInputTPCClusterLabel);
194 
195  // we get the input ionization data products from the associations
196  //auto inputIonHandle = e.getValidHandle< std::vector<rec::TrackIoniz> >(fInputTrackLabel);
197  //auto const& inputIoniz = *inputIonHandle;
198 
199  // for making output associations
200 
201  auto const trackPtrMaker = art::PtrMaker<rec::Track>(e);
202  auto const ionizPtrMaker = art::PtrMaker<rec::TrackIoniz>(e);
203  auto const TPCClusterPtrMaker = art::PtrMaker<rec::TPCCluster>(e);
204  auto const vtxPtrMaker = art::PtrMaker<rec::Vertex>(e);
205 
206 
207  // and a map of TPC Cluster ID numbers to locations in the hit-cluster assocation FindManyP
208 
209  std::map<rec::IDNumber,size_t> hcim;
210  for (size_t iclus = 0; iclus<inputTPCClusters.size(); ++iclus)
211  {
212  rec::IDNumber clusid = inputTPCClusters.at(iclus).getIDNumber();
213  hcim[clusid] = iclus;
214  }
215 
216  // make a list of which side each track is on by checking the majority of hits
217  // this is used so we do not stitch tracks on the same side of the cathode
218 
219  std::vector<int> trackside;
220  float chanpos[3] = {0,0,0};
221  for (size_t itrack = 0; itrack < inputTracks.size(); ++itrack)
222  {
223  size_t nplus = 0;
224  size_t nminus = 0;
225  for (size_t iTPCCluster=0; iTPCCluster<TPCClustersFromInputTracks.at(itrack).size(); ++iTPCCluster)
226  {
227  size_t icindex = hcim[TPCClustersFromInputTracks.at(itrack).at(iTPCCluster)->getIDNumber()];
228  for (size_t ihit=0; ihit < HitsFromInputTPCClusters.at(icindex).size(); ++ihit)
229  {
230  auto hitchan = HitsFromInputTPCClusters.at(icindex).at(ihit)->Channel();
231  geo->ChannelToPosition(hitchan, chanpos);
232  if (chanpos[0] > xtpccent)
233  {
234  nplus++;
235  }
236  else
237  {
238  nminus++;
239  }
240  }
241  }
242  if (nplus > nminus)
243  {
244  trackside.push_back(1);
245  }
246  else
247  {
248  trackside.push_back(-1);
249  }
250  }
251 
252  // vector of merged flags contains a list of which pairs of tracks are merged
253  // A more general track stitcher may want to stitch kinked tracks together and thus be able to stitch
254  // more than a pair of tracks, but this module so far just stitches across the cathode.
255 
256  size_t nti = inputTracks.size();
257  std::vector<int> mergedflag(nti,-1); // save indexes here; negative means unmerged
258  std::vector<int> fwdflag(nti,0); // 1 for forwards, 2 for backwards
259  std::vector<float> dx(nti,0); // shift in X needed
260 
261  for (size_t itrack = 0; itrack < inputTracks.size(); ++itrack)
262  {
263  if (mergedflag.at(itrack) >= 0) continue; // this track is already part of an earlier merge
264  for (size_t jtrack = itrack+1; jtrack < inputTracks.size(); ++jtrack)
265  {
266  if (mergedflag.at(jtrack)>=0) continue; // already merged, don't merge another one
267  if (trackside.at(itrack) == trackside.at(jtrack)) continue; // don't merge tracks on the same side
268  if (cathodematch(inputTracks.at(itrack),inputTracks.at(jtrack),fwdflag.at(itrack),fwdflag.at(jtrack),dx.at(itrack)))
269  {
270  if (fPrintLevel >0)
271  {
272  std::cout << "found a merge. dx= " <<
273  dx.at(itrack) <<
274  " flip flags: " << fwdflag.at(itrack) << " " << fwdflag.at(jtrack) << std::endl;
275  }
276  mergedflag.at(itrack) = jtrack;
277  mergedflag.at(jtrack) = itrack;
278  dx.at(jtrack) = -dx.at(itrack);
279  break;
280  }
281  }
282  }
283 
284  // we have lists of tracks to merge and how much to shift them by, and which ones to flip. Look for associated vertices
285  // and follow the chain of associated tracks, proposing new shifts to them.
286 
287  // make a local copy of vertex information so we can change the X locations
288 
289  std::map<rec::IDNumber,locVtx_t> vtxmap; // index of vertices by Leo's IDNumber
290 
291  // a map of vertex to track associations, the inverse of the track to vertex assocation list
292  std::map<rec::IDNumber,std::vector<trkiend_t>> vttrackmap;
293 
294  // keep track of which vertices we have already shifted
295  std::map<rec::IDNumber,bool> vtxshifted;
296 
297  // fill out the list of vertices. A track may belong to more than one vertex (either end, and a track end
298  // itself may belong to more than one vertex. fill in the dx's as needed.
299 
300  for (size_t itrack = 0; itrack < inputTracks.size(); ++itrack)
301  {
302  trkiend_t tmpti;
303  tmpti.trkindex = itrack;
304  tmpti.dx = dx.at(itrack);
305 
306  for (size_t ivtx = 0; ivtx < VerticesFromInputTracks.at(itrack).size(); ++ivtx)
307  {
308  auto vtxp = VerticesFromInputTracks.at(itrack).at(ivtx);
309  rec::IDNumber vtxid = vtxp->getIDNumber();
310  auto vtxiter = vtxmap.find(vtxid);
311  if (vtxiter == vtxmap.end())
312  {
313  locVtx_t tmpvtxdat;
314  tmpvtxdat.fTime = vtxp->Time();
315  for (int i=0; i<3; ++i)
316  {
317  tmpvtxdat.fPosition[i] = vtxp->Position()[i];
318  }
319  for (int i=0; i<9; ++i)
320  {
321  tmpvtxdat.fCovMat[i] = vtxp->CovMat()[i];
322  }
323  vtxmap[vtxid] = tmpvtxdat;
324  vtxshifted[vtxid] = false;
325 
326  std::vector<trkiend_t> trkindexvector;
327  tmpti.trkend = *(VerticesFromInputTracks.data(itrack).at(ivtx));
328  trkindexvector.push_back(tmpti);
329  vttrackmap[vtxid] = trkindexvector;
330  }
331  else
332  {
333  tmpti.trkend = *(VerticesFromInputTracks.data(itrack).at(ivtx));
334  vttrackmap[vtxid].push_back(tmpti);
335  }
336  }
337  }
338 
339  // Find new vertex shift positions by averaging the shifts of associated tracks that are on the
340  // cathode-crosser list. To do -- carry uncertainties around and include in the average.
341  // This while loop searches for chains of tracks and vertices to shift.
342 
343  bool moretodo = true;
344  while (moretodo)
345  {
346  moretodo = false;
347  for (const auto &vtxi : vttrackmap)
348  {
349  if (vtxshifted[vtxi.first]) continue; // skip the ones we've already shifted
350 
351  float avgdx = 0;
352  size_t numdx = 0;
353  for (size_t i=0; i< vtxi.second.size(); ++i)
354  {
355  size_t itrack = vtxi.second.at(i).trkindex;
356  if (mergedflag.at(itrack) >= 0 || dx.at(itrack) != 0)
357  {
358  avgdx += dx.at(itrack);
359  ++numdx;
360  }
361  }
362  if (numdx > 0)
363  {
364  avgdx /= (float) numdx;
365  vtxshifted[vtxi.first] = true; // we are shifting a vertex.
366  moretodo = true; // we'll shift its tracks and thus need to go around looking for more vertices
367  }
368  vtxmap[vtxi.first].fPosition[0] += avgdx;
369 
370  double ts = vtxmap[vtxi.first].fTime;
371  double deltat = avgdx/DriftVelocity;
372  ts += deltat;
373  vtxmap[vtxi.first].fTime = ts;
374 
375  // shift the as-yet-unshifted tracks (or rather mark them for shifting)
376  for (size_t i=0; i< vtxi.second.size(); ++i)
377  {
378  size_t itrack = vtxi.second.at(i).trkindex;
379  if (mergedflag.at(itrack) < 0 && dx.at(itrack) == 0)
380  {
381  dx.at(itrack) = avgdx;
382  }
383  }
384  }
385  }
386 
387  // put the new vertices into the output collection, and remember where we put them so we can
388  // use it in associations.
389 
390  std::map<rec::IDNumber,size_t> vtxoutmap;
391  for (const auto &vtxr : vtxmap)
392  {
393  vtxCol->emplace_back(vtxr.second.fPosition,vtxr.second.fCovMat,vtxr.second.fTime);
394  vtxoutmap[vtxr.first] = vtxCol->size() - 1;
395  }
396 
397 
398  // fill the output track collection, merging, shifting, and flipping as needed.
399  // fill in the associations, updating the
400  // trkend flags if the tracks have been flipped.
401 
402  for (size_t itrack = 0; itrack < inputTracks.size(); ++itrack)
403  {
404  if (mergedflag.at(itrack) < 0) // not merged, but make a new shifted track if need be
405  {
406  TrackPar tpi(inputTracks.at(itrack));
407  double ts = tpi.getTime();
408  double deltat = dx.at(itrack)/DriftVelocity;
409  ts += deltat;
410  TrackPar tpm(tpi.getLengthForwards(),
411  tpi.getLengthBackwards(),
412  tpi.getNTPCClusters(),
413  tpi.getXBeg() + dx.at(itrack),
414  tpi.getTrackParametersBegin(),
415  tpi.getCovMatBeg(),
416  tpi.getChisqForwards(),
417  tpi.getXEnd() + dx.at(itrack),
418  tpi.getTrackParametersEnd(),
419  tpi.getCovMatEnd(),
420  tpi.getChisqBackwards(),
421  ts);
422  trkCol->push_back(tpm.CreateTrack());
423 
424  //Make copies of the associated TPCClusters and shift them as need be.
425 
426  auto const trackpointer = trackPtrMaker(trkCol->size()-1);
427  float cpos[3] = {0,0,0};
428  for (size_t iTPCCluster=0; iTPCCluster<TPCClustersFromInputTracks.at(itrack).size(); ++iTPCCluster)
429  {
430  auto const &tc = TPCClustersFromInputTracks.at(itrack).at(iTPCCluster);
431  for (size_t i=0; i<3; ++i)
432  {
433  cpos[i] = tc->Position()[i];
434  }
435  cpos[0] += dx.at(itrack);
436  TPCClusterCol->emplace_back(tc->Signal(),
437  cpos,
438  tc->StartTime(),
439  tc->EndTime(),
440  tc->Time(),
441  tc->RMS(),
442  tc->CovMatPacked());
443  auto const TPCClusterPointer = TPCClusterPtrMaker(TPCClusterCol->size()-1);
444  TPCClusterTrkAssns->addSingle(TPCClusterPointer,trackpointer);
445  rec::IDNumber oldclusid = tc->getIDNumber();
446  size_t icindex = hcim[oldclusid];
447  for (size_t ihit=0; ihit < HitsFromInputTPCClusters.at(icindex).size(); ++ihit)
448  {
449  HitTPCClusterAssns->addSingle(HitsFromInputTPCClusters.at(icindex).at(ihit),TPCClusterPointer);
450  }
451  }
452 
453  // copy trkioniz and associations to the output collections.
454  // this loop may be unnecessary as there is only one TrackIoniz per Track, but just in case
455 
456  for (size_t iTrkIoniz=0; iTrkIoniz<TrackIonizFromInputTracks.at(itrack).size(); ++iTrkIoniz)
457  {
458  ionCol->push_back(*TrackIonizFromInputTracks.at(itrack).at(iTrkIoniz));
459  auto const ionizpointer = ionizPtrMaker(ionCol->size()-1);
460  ionTrkAssns->addSingle(ionizpointer, trackpointer);
461  }
462 
463  // copy over associations with vertices to the new vertex collection. Retain
464  // track-end identification as these tracks are not flipped.
465 
466  for (size_t ivtx = 0; ivtx < VerticesFromInputTracks.at(itrack).size(); ++ivtx)
467  {
468  auto vtxp = VerticesFromInputTracks.at(itrack).at(ivtx);
469  auto trkend = *(VerticesFromInputTracks.data(itrack).at(ivtx));
470  rec::IDNumber vtxid = vtxp->getIDNumber();
471  size_t ivout = vtxoutmap[vtxid];
472  auto const vtxptr = vtxPtrMaker(ivout);
473  trkVtxAssns->addSingle(trackpointer,vtxptr,trkend);
474  }
475  }
476  else // merge them -- adjust track parameters and put in the time
477  {
478  // assume directions are set so that itrack is the "beginning" and jtrack is the "end"
479  if (mergedflag.at(itrack) < 0)
480  {
481  MF_LOG_WARNING("tpccathodestitch: inconsistent merge flags ") << itrack << " " << mergedflag.at(itrack);
482  continue;
483  }
484  size_t jtrack = mergedflag.at(itrack);
485  if (jtrack < itrack) continue; // don't merge the same tracks twice
486 
487  // flip the tracks around according to the fwdflag returned by the cathode match method
488  // fwdflag == 1 means don't flip
489 
490  TrackPar tpi(inputTracks.at(itrack), fwdflag.at(itrack) != 1);
491  TrackPar tpj(inputTracks.at(jtrack), fwdflag.at(jtrack) != 1);
492 
493  tpi.setXBeg( tpi.getXBeg() + dx.at(itrack) );
494  tpi.setXEnd( tpi.getXEnd() + dx.at(itrack) );
495  tpj.setXBeg( tpj.getXBeg() + dx.at(jtrack) );
496  tpj.setXEnd( tpj.getXEnd() + dx.at(jtrack) );
497 
498  // some checking due to the unsigned nature of the timestmap. Assume in ticks.
499  double ts = tpi.getTime();
500  int deltat = dx.at(itrack)/DriftVelocity;
501  if ( (int) ts + deltat >= 0)
502  {
503  ts += deltat;
504  }
505 
506  TrackPar tpm(tpi.getLengthForwards() + tpj.getLengthForwards(),
507  tpi.getLengthBackwards() + tpj.getLengthBackwards(),
508  tpi.getNTPCClusters() + tpj.getNTPCClusters(),
509  tpi.getXBeg(),
510  tpi.getTrackParametersBegin(),
511  tpi.getCovMatBeg(),
512  tpi.getChisqForwards() + tpj.getChisqForwards(),
513  tpj.getXEnd(),
514  tpj.getTrackParametersEnd(),
515  tpj.getCovMatEnd(),
516  tpi.getChisqBackwards() + tpj.getChisqBackwards(),
517  ts);
518  trkCol->push_back(tpm.CreateTrack());
519  auto const trackpointer = trackPtrMaker(trkCol->size()-1);
520 
521  // make new TPCClusters, shifted with the track dx. To think about: the times. They are arrival times of hit charge at the moment
522 
523  float cpos[3] = {0,0,0};
524  for (size_t iTPCCluster=0; iTPCCluster<TPCClustersFromInputTracks.at(itrack).size(); ++iTPCCluster)
525  {
526  auto const &tc = TPCClustersFromInputTracks.at(itrack).at(iTPCCluster);
527  for (size_t i=0; i<3; ++i)
528  {
529  cpos[i] = tc->Position()[i];
530  }
531  cpos[0] += dx.at(itrack);
532  TPCClusterCol->emplace_back(tc->Signal(),
533  cpos,
534  tc->StartTime(),
535  tc->EndTime(),
536  tc->Time(),
537  tc->RMS(),
538  tc->CovMatPacked());
539  auto const TPCClusterPointer = TPCClusterPtrMaker(TPCClusterCol->size()-1);
540  TPCClusterTrkAssns->addSingle(TPCClusterPointer,trackpointer);
541  rec::IDNumber oldclusid = tc->getIDNumber();
542  size_t icindex = hcim[oldclusid];
543  for (size_t ihit=0; ihit < HitsFromInputTPCClusters.at(icindex).size(); ++ihit)
544  {
545  HitTPCClusterAssns->addSingle(HitsFromInputTPCClusters.at(icindex).at(ihit),TPCClusterPointer);
546  }
547  }
548  for (size_t iTPCCluster=0; iTPCCluster<TPCClustersFromInputTracks.at(jtrack).size(); ++iTPCCluster)
549  {
550  auto const &tc = TPCClustersFromInputTracks.at(jtrack).at(iTPCCluster);
551  for (size_t i=0; i<3; ++i)
552  {
553  cpos[i] = tc->Position()[i];
554  }
555  cpos[0] += dx.at(jtrack);
556  TPCClusterCol->emplace_back(tc->Signal(),
557  cpos,
558  tc->StartTime(),
559  tc->EndTime(),
560  tc->Time(),
561  tc->RMS(),
562  tc->CovMatPacked());
563  auto const TPCClusterPointer = TPCClusterPtrMaker(TPCClusterCol->size()-1);
564  TPCClusterTrkAssns->addSingle(TPCClusterPointer,trackpointer);
565  rec::IDNumber oldclusid = tc->getIDNumber();
566  size_t icindex = hcim[oldclusid];
567  for (size_t ihit=0; ihit < HitsFromInputTPCClusters.at(icindex).size(); ++ihit)
568  {
569  HitTPCClusterAssns->addSingle(HitsFromInputTPCClusters.at(icindex).at(ihit),TPCClusterPointer);
570  }
571  }
572 
573  // merge the track ionization data -- assume just one TrackIoniz per track, with forward and backward vectors
574  // reverse them if need be.
575 
576  const auto itif = TrackIonizFromInputTracks.at(itrack).at(0)->getFWD_dSigdXs();
577  const auto itib = TrackIonizFromInputTracks.at(itrack).at(0)->getBAK_dSigdXs();
578  const auto jtif = TrackIonizFromInputTracks.at(jtrack).at(0)->getFWD_dSigdXs();
579  const auto jtib = TrackIonizFromInputTracks.at(jtrack).at(0)->getBAK_dSigdXs();
580 
581  auto mtif = itif;
582  auto mtib = itib;
583  if (fwdflag.at(itrack) != 1) // flip itrack's ionization vector if need be
584  {
585  mtif = itib;
586  mtib = itif;
587  }
588  auto jmtif = jtif;
589  auto jmtib = jtib;
590  if (fwdflag.at(jtrack) != 1)
591  {
592  jmtif = jtib;
593  jmtib = jtif;
594  }
595 
596  for (size_t i=0; i<jmtif.size(); ++i)
597  {
598  mtif.push_back(jmtif.at(i));
599  }
600  for (size_t i=0; i<jmtib.size(); ++i)
601  {
602  mtib.push_back(jmtib.at(i));
603  }
604  TrackIoniz tim;
605  tim.setData(mtif,mtib);
606  ionCol->push_back(tim);
607  auto const ionizpointer = ionizPtrMaker(ionCol->size()-1);
608  ionTrkAssns->addSingle(ionizpointer, trackpointer);
609 
610  for (size_t ivtx = 0; ivtx < VerticesFromInputTracks.at(itrack).size(); ++ivtx)
611  {
612  auto vtxp = VerticesFromInputTracks.at(itrack).at(ivtx);
613  auto trkend = *(VerticesFromInputTracks.data(itrack).at(ivtx));
614  if (fwdflag.at(itrack) != 1)
615  {
616  trkend = 1 - trkend;
617  }
618  rec::IDNumber vtxid = vtxp->getIDNumber();
619  size_t ivout = vtxoutmap[vtxid];
620  auto const vtxptr = vtxPtrMaker(ivout);
621  trkVtxAssns->addSingle(trackpointer,vtxptr,trkend);
622  }
623 
624  }
625  }
626 
627  e.put(std::move(trkCol));
628  e.put(std::move(TPCClusterCol));
629  e.put(std::move(TPCClusterTrkAssns));
630  e.put(std::move(ionCol));
631  e.put(std::move(ionTrkAssns));
632  e.put(std::move(vtxCol));
633  e.put(std::move(trkVtxAssns));
634  e.put(std::move(HitTPCClusterAssns));
635  }
std::string fInputTrackLabel
input tracks and associations with TPCClusters. Get vertices associated with these tracks from the as...
int TrackEnd
Definition: Track.h:32
int fPrintLevel
debug printout: 0: none, 1: just track parameters and residuals, 2: all
const double e
std::string fInputTPCClusterLabel
input TPC Clusters
def move(depos, offset)
Definition: depos.py:107
std::string fInputVertexLabel
input vertices and associations with tracks
ValidHandle< PROD > getValidHandle(InputTag const &tag) const
Definition: DataViewImpl.h:441
ProductID put(std::unique_ptr< PROD > &&edp, std::string const &instance={})
Definition: DataViewImpl.h:686
#define MF_LOG_WARNING(category)
bool cathodematch(const gar::rec::Track &trackA, const gar::rec::Track &trackB, int &fwdflagA, int &fwdflagB, float &deltaX)
LArSoft geometry interface.
Definition: ChannelGeo.h:16
size_t IDNumber
Definition: IDNumberGen.h:71
QTextStream & endl(QTextStream &s)

Member Data Documentation

float gar::rec::tpccathodestitch::fCTCut
private

cut on cosine of angle matching

Definition at line 86 of file tpccathodestitch_module.cc.

float gar::rec::tpccathodestitch::fDistCut
private

cut in distance between best-matching points

Definition at line 85 of file tpccathodestitch_module.cc.

std::string gar::rec::tpccathodestitch::fInputHitLabel
private

needed to make TPCCluster - hit associations

Definition at line 83 of file tpccathodestitch_module.cc.

std::string gar::rec::tpccathodestitch::fInputTPCClusterLabel
private

input TPC Clusters

Definition at line 82 of file tpccathodestitch_module.cc.

std::string gar::rec::tpccathodestitch::fInputTrackLabel
private

input tracks and associations with TPCClusters. Get vertices associated with these tracks from the assns

Definition at line 80 of file tpccathodestitch_module.cc.

std::string gar::rec::tpccathodestitch::fInputVertexLabel
private

input vertices and associations with tracks

Definition at line 81 of file tpccathodestitch_module.cc.

float gar::rec::tpccathodestitch::fMaxDX
private

cut on maximum translation of dX on one side.

Definition at line 87 of file tpccathodestitch_module.cc.

float gar::rec::tpccathodestitch::fMinDX
private

cut on minimum translation of dX on one side.

Definition at line 88 of file tpccathodestitch_module.cc.

int gar::rec::tpccathodestitch::fPrintLevel
private

debug printout: 0: none, 1: just track parameters and residuals, 2: all

Definition at line 84 of file tpccathodestitch_module.cc.


The documentation for this class was generated from the following file: