#include <AlgEventSRList.h>
Inheritance diagram for AlgEventSRList:

Public Member Functions | |
| AlgEventSRList () | |
| virtual | ~AlgEventSRList () |
| virtual void | RunAlg (AlgConfig &ac, CandHandle &ch, CandContext &cx) |
| void | BuildEventFromUnassoc (AlgConfig &ac, CandHandle &ch, CandContext &cx, CandSliceHandle *slice) |
| virtual void | Trace (const char *c) const |
| void | SetPrimaryShowers (CandHandle &ch, AlgConfig &ac) |
| void | ReConstructShowers (AlgConfig &ac, CandHandle &ch, CandContext &cx) |
| void | RemoveTracksinShowers (AlgConfig &ac, TObjArray *recolist) |
| void | FillRecoList (CandSliceHandle *, CandShowerHandleItr *, CandTrackHandleItr *, TObjArray &) |
| Bool_t | MatchOtherTracksInEvent (AlgConfig &ac, const VldContext *vldcptr, CandTrackHandle *, TObjArray *) |
| void | AddObjectToEvent (CandRecoHandle *reco, TObjArray *, TObjArray *, Bool_t) |
| void | MergeShowers (CandContext &cxx, TObjArray &eventlist, AlgConfig &ac, CandSliceHandle *slice, CandClusterListHandle *clusterlist, CandShowerListHandle *showerlist) |
| void | AddStripToEvent (CandEventHandle *ev, CandShowerHandle *shw, CandSubShowerSRListHandle *subshwlist, CandClusterListHandle *clslist, CandStripHandle *closeststrip) |
| void | CreatePrimaryShower (AlgConfig &ac, CandContext &cxx, CandEventHandle *closestevent, CandShowerListHandle *showerlist, CandSubShowerSRListHandle *subshowerlist, CandClusterListHandle *clusterlist, CandStripHandle *closeststrip) |
| void | FindUnassociated (CandSliceHandleItr &sliceItr, CandShowerHandleItr *, CandTrackHandleItr *, TObjArray &unassociated) |
| void | ReFillDist2Map (AlgConfig &ac, CandStripHandle *closeststrip, CandEventHandle *closestevent, TObjArray &unassociated, std::vector< std::map< const CandEventHandle *, Double_t > > &dist2map) |
| void | FillDist2Map (AlgConfig &ac, TObjArray &unassociated, CandHandle &ch, std::vector< std::map< const CandEventHandle *, Double_t > > &dist2map) |
|
|
Definition at line 61 of file AlgEventSRList.cxx. 00062 {
00063 }
|
|
|
Definition at line 66 of file AlgEventSRList.cxx. 00067 {
00068 }
|
|
||||||||||||||||||||
|
Definition at line 1666 of file AlgEventSRList.cxx. References Registry::Clear(), and MSG. Referenced by RunAlg(). 01666 {
01667 if (!merge) {
01668 // if this is the first match we have found for this object,
01669 //add object to list
01670 // and point prevlist to this object list
01671 objectlist->Add(reco);
01672 MSG("EventSR",Msg::kVerbose) << " adding to list\n";
01673 }
01674 else {
01675 MSG("EventSR",Msg::kVerbose) << " combining lists\n";
01676 // this object matches more than one event - merge their member
01677 // objects to list prevlist, and add the new object
01678 for (Int_t ireco2=0; ireco2<=objectlist->GetLast();ireco2++)
01679 prevlist->Add(objectlist->At(ireco2));
01680 prevlist->Add(reco);
01681 objectlist->Clear();
01682 }
01683 }
|
|
||||||||||||||||||||||||
|
Add a strip to the event daughter list, the primary shower, and place the modified cluster on the cluster list Definition at line 550 of file AlgEventSRList.cxx. References CandShowerHandle::AddCluster(), CandHandle::AddDaughterLink(), CandShowerSRHandle::AddSubShower(), CandClusterHandle::DupHandle(), CandSubShowerSRHandle::DupHandle(), CandSubShowerSRHandle::GetAvgDev(), CandClusterHandle::GetCandSlice(), CandRecoHandle::GetCandSlice(), CandRecoHandle::GetCharge(), CandShowerHandle::GetCluster(), CandHandle::GetDaughterIterator(), CandSubShowerSRHandle::GetEnergy(), CandShowerHandle::GetLastCluster(), CandShowerSRHandle::GetLastSubShower(), Calibrator::GetMIP(), CandStripHandle::GetPlane(), CandClusterHandle::GetPlaneView(), CandStripHandle::GetPlaneView(), CandSubShowerSRHandle::GetPlaneView(), CandSubShowerSRHandle::GetSlope(), CandShowerSRHandle::GetSubShower(), CandStripHandle::GetTPos(), CandRecoHandle::GetVtxU(), CandRecoHandle::GetVtxV(), CandRecoHandle::GetVtxZ(), CandStripHandle::GetZPos(), Calibrator::Instance(), CandHandle::IsEquivalent(), MSG, CandShowerHandle::RemoveCluster(), CandHandle::RemoveDaughter(), CandShowerSRHandle::RemoveSubShower(), CandClusterHandle::SetCandSlice(), CandRecoHandle::SetCandSlice(), and CandSubShowerSRHandle::SetEnergy(). Referenced by RunAlg(). 00555 {
00556 closestevent->AddDaughterLink(*closeststrip);
00557 shower->AddDaughterLink(*closeststrip);
00558 if(subshowerlist && shower->InheritsFrom("CandShowerSRHandle")) {
00559 Calibrator& calibrator=Calibrator::Instance();
00560 Int_t foundsubshower=0;
00561 Int_t closestSubShower=-1;
00562 Double_t BestStripDistance = 99999;
00563 CandShowerSRHandle *showerSR =
00564 dynamic_cast<CandShowerSRHandle*> (shower);
00565 for (Int_t isubshower=0;
00566 isubshower<showerSR->GetLastSubShower()+1;
00567 isubshower++) {
00568 CandSubShowerSRHandle *ssl = const_cast<CandSubShowerSRHandle*>
00569 (showerSR->GetSubShower(isubshower));
00570 //add strip to cluster of the same view
00571 if (ssl->GetPlaneView()==closeststrip->GetPlaneView()) {
00572 //decide which is most appropriate subshower to add strip to
00573 //based on distance to/spread of subshower:
00574 Double_t tposVtx = 0;
00575 if(ssl->GetPlaneView()==PlaneView::kU ||
00576 ssl->GetPlaneView()==PlaneView::kX)
00577 tposVtx = ssl->GetVtxU();
00578 else if(ssl->GetPlaneView()==PlaneView::kV ||
00579 ssl->GetPlaneView()==PlaneView::kY)
00580 tposVtx = ssl->GetVtxV();
00581 Double_t StripDistance = 99999;
00582 if(ssl->GetAvgDev()!=0.) {
00583 StripDistance =
00584 (TMath::Abs(closeststrip->GetTPos() -
00585 (tposVtx + ssl->GetSlope() *
00586 (closeststrip->GetZPos() -
00587 ssl->GetVtxZ()))) *
00588 TMath::Cos(TMath::ATan(ssl->GetSlope()))) *
00589 calibrator.GetMIP(closeststrip->
00590 GetCharge(CalDigitType::kSigCorr)) /
00591 ssl->GetAvgDev();
00592 }
00593 else {
00594 StripDistance = 9999 +
00595 TMath::Sqrt(TMath::Power(TMath::Abs(closeststrip->GetZPos() -
00596 ssl->GetVtxZ())*6.,2) +
00597 TMath::Power(TMath::Abs(closeststrip->GetTPos() -
00598 tposVtx)*4.1,2));
00599 }
00600 if(StripDistance<BestStripDistance){
00601 foundsubshower=1;
00602 BestStripDistance = StripDistance;
00603 closestSubShower = isubshower;
00604 }
00605 }
00606 }
00607 if(foundsubshower) {
00608 MSG("EventSR",Msg::kVerbose) << "adding strip to subshower "
00609 << closeststrip->GetPlane()
00610 << endl;
00611 CandSubShowerSRHandle *ssl = const_cast<CandSubShowerSRHandle*>
00612 (showerSR->GetSubShower(closestSubShower));
00613 //extract mip -> gev conversion:
00614 Double_t GeVperMIP = 0;
00615 if(ssl->GetEnergy()!=0) GeVperMIP = ssl->GetEnergy()/
00616 Double_t(calibrator.GetMIP(ssl->GetCharge(CalStripType::kSigCorr)));
00617 TIter csshItr(subshowerlist->GetDaughterIterator());
00618 while (CandSubShowerSRHandle *cssh =
00619 dynamic_cast<CandSubShowerSRHandle*>(csshItr())) {
00620 if(cssh->IsEquivalent(ssl)) {
00621 showerSR->RemoveSubShower(ssl);
00622 CandSubShowerSRHandle * newss = cssh->DupHandle();
00623 newss->SetCandSlice(cssh->GetCandSlice());
00624 newss->AddDaughterLink(*closeststrip);
00625 newss->SetEnergy(GeVperMIP*Double_t(calibrator.GetMIP(closeststrip->
00626 GetCharge(CalDigitType::kSigCorr))) + newss->GetEnergy());
00627 subshowerlist->RemoveDaughter(cssh);
00628 subshowerlist->AddDaughterLink(*newss);
00629 showerSR->AddSubShower(newss);
00630 delete newss;
00631 break;
00632 }
00633 }
00634 }
00635 }
00636 else {
00637 Int_t foundcluster=0;
00638 for (Int_t icluster=0; icluster < shower->GetLastCluster()+1 &&
00639 foundcluster==0; icluster++) {
00640 CandClusterHandle *cl = const_cast<CandClusterHandle *>
00641 (shower->GetCluster(icluster));
00642 // add strip to cluster of the same view
00643 if (cl->GetPlaneView()==closeststrip->GetPlaneView()) {
00644 foundcluster=1;
00645 MSG("EventSR",Msg::kVerbose) << "adding strip to cluster "
00646 << closeststrip->GetPlane() << endl;
00647 TIter cchItr(clusterlist->GetDaughterIterator());
00648 while (CandClusterHandle *cch =
00649 dynamic_cast<CandClusterHandle*>(cchItr())) {
00650 if(cch->IsEquivalent(cl)) {
00651 shower->RemoveCluster(cl);
00652 CandClusterHandle * newcl = cch->DupHandle();
00653 newcl->SetCandSlice(cch->GetCandSlice());
00654 newcl->AddDaughterLink(*closeststrip);
00655 clusterlist->RemoveDaughter(cch);
00656 clusterlist->AddDaughterLink(*newcl);
00657 shower->AddCluster(newcl);
00658 delete newcl;
00659 break;
00660 }
00661 }
00662 }
00663 }
00664 }
00665 }
|
|
||||||||||||||||||||
|
this method is called for slices in which no shower or track was previously found. We see whether there is a 3D cluster in this slice which could be an event Definition at line 1058 of file AlgEventSRList.cxx. References abs(), CandHandle::AddDaughterLink(), CandShowerHandle::BelongsWithShower(), CandShowerSRHandle::BelongsWithShower(), CandHandle::FindDaughter(), Registry::Get(), AlgFactory::GetAlgHandle(), CandStripHandle::GetBegTime(), CandHandle::GetCandRecord(), CandContext::GetCandRecord(), CandStripHandle::GetCharge(), CandContext::GetDataIn(), CandHandle::GetDaughterIterator(), VldContext::GetDetector(), Registry::GetDouble(), AlgFactory::GetInstance(), Registry::GetInt(), CandContext::GetMom(), CandStripHandle::GetPlane(), CandStripHandle::GetPlaneView(), CandStripHandle::GetTPos(), RecMinos::GetVldContext(), CandHandle::GetVldContext(), CandClusterHandle::IsShowerLike(), CandEvent::MakeCandidate(), CandShower::MakeCandidate(), CandCluster::MakeCandidate(), CandShowerSR::MakeCandidate(), CandSubShowerSR::MakeCandidate(), MSG, CandHandle::SetCandRecord(), CandEventHandle::SetCandSlice(), CandClusterHandle::SetCandSlice(), CandRecoHandle::SetCandSlice(), CandSubShowerSRHandle::SetClusterID(), and CandEventHandle::SetPrimaryShower(). Referenced by RunAlg(). 01062 {
01063 assert(cx.GetDataIn());
01064 MSG("EventSR",Msg::kDebug)<<" Building Event - no showers or tracks " << endl;
01065 if (!(cx.GetDataIn()->InheritsFrom("TObjArray"))) {
01066 MSG("EventSR",Msg::kDebug)<<" dataIn inherits from TObjArray " << endl;
01067 return;
01068 }
01069
01070 const CandSliceListHandle *slicelist = 0;
01071 CandShowerListHandle *showerlist = 0;
01072 CandClusterListHandle *clusterlist = 0;
01073 CandSubShowerSRListHandle *subshowerlist = 0;
01074 const TObjArray *cxin =
01075 dynamic_cast<const TObjArray *>(cx.GetDataIn());
01076 for (Int_t i=0; i<=cxin->GetLast(); i++) {
01077 TObject *tobj = cxin->At(i);
01078 if (tobj->InheritsFrom("CandSliceListHandle")) {
01079 slicelist = dynamic_cast<CandSliceListHandle*>(tobj);
01080 }
01081 // Retrieve persistant modifiable CandShowerList
01082 if (tobj->InheritsFrom("CandShowerListHandle")) {
01083 showerlist = dynamic_cast<CandShowerListHandle*>(tobj);
01084 }
01085 if (tobj->InheritsFrom("CandClusterListHandle")) {
01086 clusterlist = dynamic_cast<CandClusterListHandle*>(tobj);
01087 }
01088 if (tobj->InheritsFrom("CandSubShowerSRListHandle")) {
01089 subshowerlist = dynamic_cast<CandSubShowerSRListHandle*>(tobj);
01090 }
01091 }
01092
01093 if (!showerlist || !slicelist) {
01094 MSG("EventSR",Msg::kDebug)<<" no showerlist " << endl;
01095 return;
01096 }
01097 Int_t detectorType = slicelist->GetVldContext()->GetDetector();
01098
01099 CandContext cxx(this,cx.GetMom());
01100 AlgFactory &af = AlgFactory::GetInstance();
01101
01102 const char *pEventAlgConfig = 0;
01103 ac.Get("EventAlgConfig",pEventAlgConfig);
01104 AlgHandle ah = af.GetAlgHandle("AlgEventSR",pEventAlgConfig);
01105
01106 Double_t pHitAssocDPlane = ac.GetInt("HitAssocDPlane");
01107 Double_t pHitAssocDTime0 = ac.GetDouble("HitAssocDTime0");
01108 Double_t pHitAssocDTime1 = ac.GetDouble("HitAssocDTime1");
01109 Double_t pHitAssocMaxDist2 = ac.GetDouble("HitAssocMaxDist2");
01110 Double_t pHitAssocZParm = ac.GetDouble("HitAssocZParm");
01111 Double_t pHitAssocPParm = ac.GetDouble("HitAssocPParm");
01112 Double_t pHitAssocTParm = ac.GetDouble("HitAssocTParm");
01113 Double_t pShwShwDtpos2 = ac.GetDouble("ShwShwDtpos2");
01114 Double_t pShwShwDz = ac.GetDouble("ShwShwDz");
01115 Double_t pShwShwDt = ac.GetDouble("ShwShwDt");
01116
01117 const CandRecord *candrec = cx.GetCandRecord();
01118 assert(candrec);
01119 const VldContext *vldcptr = candrec->GetVldContext();
01120 assert(vldcptr);
01121 VldContext vldc = *vldcptr;
01122 UgliGeomHandle ugh(vldc);
01123
01124 // Iterate over strips , finding sets which are 'in time', and within
01125 // a given distance of the nearest neighbor in the set, in both views.
01126 // Each of these sets is then used to construct a shower, which becomes
01127 // the primary shower of a new event. We continue until an iteration
01128 // in which no new event is created.
01129
01130
01131 // fill array of unique unassociated strips
01132 TObjArray unassociated;
01133 TIter stripItr(slice->GetDaughterIterator());
01134 while (CandStripHandle *strip =
01135 dynamic_cast<CandStripHandle*>(stripItr())) {
01136 Bool_t found=false;
01137 for (Int_t i=0; i<=unassociated.GetLast() && !found; i++) {
01138 CandStripHandle *strip0 =
01139 dynamic_cast<CandStripHandle*>(unassociated.At(i));
01140 if (*strip == *strip0) {
01141 found = true;
01142 }
01143 }
01144 if (!found) {
01145 if(!(detectorType==DetectorType::kNear && strip->GetPlane()>120)){
01146 unassociated.Add(strip);
01147 }
01148 }
01149 }
01150
01151 // loop until no new matches are found in the loop over unassoc hits.
01152 Bool_t found=false;
01153 while (unassociated.GetLast()>0 && !found) {
01154 MSG("EventSR",Msg::kDebug)<< " # unassoc " << unassociated.GetLast()+1 << endl;
01155 Bool_t firstu=true;
01156 Bool_t firstv=true;
01157 TObjArray neweventu;
01158 TObjArray neweventv;
01159 Bool_t addedstrip = true;
01160 Float_t totcharge=0;
01161 while (addedstrip) {
01162 addedstrip=false;
01163 // loop over unassoc strips.
01164 for (Int_t i=0; i<=unassociated.GetLast(); i++) {
01165 CandStripHandle *strip =
01166 dynamic_cast<CandStripHandle*>(unassociated.At(i));
01167 switch (strip->GetPlaneView()) {
01168 case PlaneView::kU:
01169 // strip is in U plane
01170 // if this is the first strip, add to newevent strip list
01171 if (firstu) {
01172 // if we don't have v strips yet, just add this strip to u list
01173 // seed the event
01174 if (firstv) {
01175 neweventu.Add(strip);
01176 MSG("EventSR",Msg::kDebug)<< " add first " << endl;
01177 totcharge +=strip->GetCharge();
01178 addedstrip = true;
01179 firstu=false;
01180 }
01181 // if we already have one or more v strips check that they are
01182 // in time, and agree in Z position.
01183 else {
01184 Bool_t found2=false;
01185 for (Int_t j=0; j<=neweventv.GetLast() && !found2;
01186 j++) {
01187 CandStripHandle *estrip =
01188 dynamic_cast<CandStripHandle*>(neweventv.At(j));
01189 Double_t dtime =
01190 strip->GetBegTime()-estrip->GetBegTime();
01191 MSG("EventSR",Msg::kDebug)<< " dtime " << dtime*1e9 << " " <<pHitAssocDTime0*1e9 << "/" << pHitAssocDTime1*1e9
01192 << " plane diff " << abs(strip->GetPlane()-estrip->GetPlane()) << "/" << pHitAssocDPlane << endl;
01193 if (dtime>pHitAssocDTime0 &&
01194 dtime<pHitAssocDTime1 &&
01195 abs(strip->GetPlane()-estrip->GetPlane()) <=
01196 pHitAssocDPlane) {
01197 MSG("EventSR",Msg::kDebug)<< " add " << endl;
01198 // match is found, add this strip to array
01199 neweventu.Add(strip);
01200 totcharge +=strip->GetCharge();
01201 addedstrip = true;
01202 firstu=0;
01203 found2=true;
01204 } // if match found
01205 } // for loop over V strips in new event
01206 } // end not first V strip
01207 } // end first U strip
01208 else {
01209 // if we already have u strips, make sure that the one we
01210 // add is adjaccent, using distance criteria based
01211 // on plane, time, and transverse postion separation
01212 Bool_t found2=false;
01213 for (Int_t j=0; j<=neweventu.GetLast() && !found2; j++) {
01214 CandStripHandle *estrip =
01215 dynamic_cast<CandStripHandle*>(neweventu.At(j));
01216 Double_t dtime =
01217 strip->GetBegTime()-estrip->GetBegTime();
01218 MSG("EventSR",Msg::kDebug)<< " dtime " << dtime*1e9 << " " <<pHitAssocDTime0*1e9 << "/" << pHitAssocDTime1*1e9
01219 << " plane diff " << abs(strip->GetPlane()-estrip->GetPlane())
01220 << " dtpos " << strip->GetTPos()-estrip->GetTPos() << endl;
01221 if (dtime>pHitAssocDTime0 &&
01222 dtime<pHitAssocDTime1) {
01223 Double_t dplane =
01224 (Double_t)(strip->GetPlane()-estrip->GetPlane());
01225 Double_t dtpos = strip->GetTPos()-estrip->GetTPos();
01226 Double_t dist2 = (pHitAssocZParm*dplane*dplane) +
01227 (pHitAssocPParm*dtpos*dtpos) +
01228 (pHitAssocTParm*dtime*dtime);
01229 // if dist2 2 parameter meets match criteria, add strip to array
01230 if (dist2<pHitAssocMaxDist2*4) {
01231 MSG("EventSR",Msg::kDebug)<< " add " << endl;
01232 neweventu.Add(strip);
01233 totcharge +=strip->GetCharge();
01234 addedstrip = true;
01235 firstu=0;
01236 found2=true;
01237 } // if positions match
01238 } // if in time
01239 } // end loop over event u strips
01240 } // end if already have u strip
01241 break;
01242
01243 case PlaneView::kV:
01244
01245 // if this is the first strip, add to newevent strip list
01246 if (firstv) {
01247 // strip is in V plane
01248 // if this is the first strip, add to newevent strip list
01249 if (firstu) {
01250 neweventv.Add(strip);
01251 totcharge +=strip->GetCharge();
01252 MSG("EventSR",Msg::kDebug)<< " add first" << endl;
01253 addedstrip = true;
01254 firstv = 0;
01255 }
01256 else {
01257 // if we already have one or more u strips check that they are
01258 // in time, and require agreement in Z position.
01259 Bool_t found2=false;
01260 for (Int_t j=0; j<=neweventu.GetLast() && !found2;
01261 j++) {
01262 CandStripHandle *estrip =
01263 dynamic_cast<CandStripHandle*>(neweventu.At(j));
01264 Double_t dtime =
01265 strip->GetBegTime()-estrip->GetBegTime();
01266 MSG("EventSR",Msg::kDebug)<< " dtime " << dtime*1e9 << " " << pHitAssocDTime0*1e9 << "/" << pHitAssocDTime1*1e9
01267 << " plane diff " << abs(strip->GetPlane()-estrip->GetPlane()) << "/" << pHitAssocDPlane << endl;
01268 if (dtime>pHitAssocDTime0 &&
01269 dtime<pHitAssocDTime1 &&
01270 abs(strip->GetPlane()-estrip->GetPlane()) <=
01271 pHitAssocDPlane) {
01272 // if dist2 2 parameter meets match criteria, add strip to array
01273 MSG("EventSR",Msg::kDebug)<< " add " << endl;
01274 neweventv.Add(strip);
01275 totcharge +=strip->GetCharge();
01276 addedstrip = true;
01277 firstv = false;
01278 found2 = true;
01279 }
01280 } // end loop over u strips in event
01281 } // end if already have u strips
01282 } // end if this is the first v strip
01283 else {
01284 // if we already have v strips, make sure that the one we
01285 // add is adjaccent, using same distance criteria base
01286 // on plane, time, and transverse postion separation
01287 Bool_t found2=false;
01288 for (Int_t j=0; j<=neweventv.GetLast() && !found2; j++) {
01289 CandStripHandle *estrip =
01290 dynamic_cast<CandStripHandle*>(neweventv.At(j));
01291 Double_t dtime = strip->GetBegTime() -
01292 estrip->GetBegTime();
01293 MSG("EventSR",Msg::kDebug)<< " dtime " << dtime*1e9 << " " << pHitAssocDTime0*1e9 << "/" << pHitAssocDTime1*1e9
01294 << " plane diff " << abs(strip->GetPlane()-estrip->GetPlane())
01295 << " dtpos " << strip->GetTPos()-estrip->GetTPos() << endl;
01296 if (dtime>pHitAssocDTime0 &&
01297 dtime<pHitAssocDTime1) {
01298 Double_t dplane =
01299 (Double_t)(strip->GetPlane()-estrip->GetPlane());
01300 Double_t dtpos = strip->GetTPos()-estrip->GetTPos();
01301 Double_t dist2 = (pHitAssocZParm*dplane*dplane) +
01302 (pHitAssocPParm*dtpos*dtpos) +
01303 (pHitAssocTParm*dtime*dtime);
01304 // if dist2 2 parameter meets match criteria, add strip to array
01305 if (dist2<pHitAssocMaxDist2*4) {
01306 MSG("EventSR",Msg::kDebug)<< " add " << endl;
01307 neweventv.Add(strip);
01308 totcharge +=strip->GetCharge();
01309 addedstrip = true;
01310 firstv = false;
01311 found2 = true;
01312 } // end if add strip
01313 } //end if in time
01314 } // end loop over v strips
01315 }
01316 break;
01317
01318 default:
01319 break;
01320 }
01321 }
01322
01323 // end of loop over hits - remove new 'associations' and compress
01324 for (Int_t i=0; i<=neweventu.GetLast(); i++) {
01325 CandStripHandle *estrip =
01326 dynamic_cast<CandStripHandle*>(neweventu.At(i));
01327 unassociated.Remove(estrip);
01328 }
01329 for (Int_t i=0; i<=neweventv.GetLast(); i++) {
01330 CandStripHandle *estrip =
01331 dynamic_cast<CandStripHandle*>(neweventv.At(i));
01332 unassociated.Remove(estrip);
01333 }
01334 unassociated.Compress();
01335 }
01336
01337 // if we have hits in both views, build an event from them
01338 // if pulse height>10 pes
01339 MSG("EventSR",Msg::kDebug)<< " considering event formation u/v: " << !firstu << "/" << !firstv << " charge " << totcharge << endl;
01340 if (!firstu && !firstv && totcharge>20.0) {
01341 found=true;
01342
01343 Bool_t newShowerOverlapsOld=false;
01344 CandHandle *shw = NULL;
01345
01346 if(showerlist->InheritsFrom("CandShowerSRListHandle") &&
01347 subshowerlist) {
01348
01349 // construct CandSubShowerSRs
01350 cxx.SetDataIn(&neweventu);
01351 AlgHandle subshowerah = af.GetAlgHandle("AlgSubShowerSR","default");
01352 CandSubShowerSRHandle usubshowerhandle =
01353 CandSubShowerSR::MakeCandidate(subshowerah,cxx);
01354 usubshowerhandle.SetCandSlice(slice);
01355 usubshowerhandle.SetClusterID(ClusterType::kUnknown);
01356 subshowerlist->AddDaughterLink(usubshowerhandle);
01357 cxx.SetDataIn(&neweventv);
01358 CandSubShowerSRHandle vsubshowerhandle =
01359 CandSubShowerSR::MakeCandidate(subshowerah,cxx);
01360 vsubshowerhandle.SetCandSlice(slice);
01361 vsubshowerhandle.SetClusterID(ClusterType::kUnknown);
01362 subshowerlist->AddDaughterLink(vsubshowerhandle);
01363 CandHandle *usubshower=subshowerlist->FindDaughter(&usubshowerhandle);
01364 CandHandle *vsubshower=subshowerlist->FindDaughter(&vsubshowerhandle);
01365
01366 //build shower
01367 TObjArray newshower;
01368 newshower.Add(usubshower);
01369 newshower.Add(vsubshower);
01370 cxx.SetDataIn(&newshower);
01371 AlgHandle showerah = af.GetAlgHandle("AlgShowerSS","default");
01372 CandShowerSRHandle showerhandle =
01373 CandShowerSR::MakeCandidate(showerah,cxx);
01374 showerhandle.SetCandSlice(slice);
01375 showerhandle.SetCandRecord(slicelist->GetCandRecord());
01376
01377 CandShowerHandleItr showerItr(showerlist->GetDaughterIterator());
01378 while (CandShowerHandle *shower =
01379 dynamic_cast<CandShowerHandle*>(showerItr())){
01380 if(showerhandle.BelongsWithShower(shower,ac,
01381 vldcptr,
01382 pShwShwDtpos2,
01383 pShwShwDz,
01384 pShwShwDt)){
01385 newShowerOverlapsOld=true;
01386 MSG("EventSR",Msg::kDebug)
01387 << " new shower overlaps with previous - don't make new event "
01388 << endl;
01389 break;
01390 }
01391 }
01392
01393 if(!newShowerOverlapsOld){
01394 MSG("EventSR",Msg::kDebug)<< " Building Event! " << endl;
01395 showerlist->AddDaughterLink(showerhandle);
01396 shw = showerlist->FindDaughter(&showerhandle);
01397 }
01398 }
01399 else {
01400
01401 // construct CandClusters
01402 cxx.SetDataIn(&neweventu);
01403 AlgHandle clusterah = af.GetAlgHandle("AlgClusterSR","default");
01404 CandClusterHandle uclusterhandle =
01405 CandCluster::MakeCandidate(clusterah,cxx);
01406 uclusterhandle.SetCandSlice(slice);
01407 uclusterhandle.IsShowerLike(1);
01408 clusterlist->AddDaughterLink(uclusterhandle);
01409 cxx.SetDataIn(&neweventv);
01410 CandClusterHandle vclusterhandle =
01411 CandCluster::MakeCandidate(clusterah,cxx);
01412 vclusterhandle.SetCandSlice(slice);
01413 vclusterhandle.IsShowerLike(1);
01414 clusterlist->AddDaughterLink(vclusterhandle);
01415 CandHandle *ucluster = clusterlist->FindDaughter(&uclusterhandle);
01416 CandHandle *vcluster = clusterlist->FindDaughter(&vclusterhandle);
01417
01418 //build shower
01419 TObjArray newshower;
01420 newshower.Add(ucluster);
01421 newshower.Add(vcluster);
01422 cxx.SetDataIn(&newshower);
01423
01424
01425 AlgHandle showerah = af.GetAlgHandle("AlgShowerSR",pEventAlgConfig);
01426 CandShowerHandle showerhandle =
01427 CandShower::MakeCandidate(showerah,cxx);
01428 showerhandle.SetCandSlice(slice);
01429 showerhandle.SetCandRecord(slicelist->GetCandRecord());
01430
01431 CandShowerHandleItr showerItr(showerlist->GetDaughterIterator());
01432 while (CandShowerHandle *shower =
01433 dynamic_cast<CandShowerHandle*>(showerItr())){
01434 if(showerhandle.BelongsWithShower(shower,ac,
01435 vldcptr,
01436 pShwShwDtpos2,
01437 pShwShwDz,
01438 pShwShwDt)){
01439 newShowerOverlapsOld=true;
01440 MSG("EventSR",Msg::kDebug)
01441 << " new shower overlaps with previous - don't make new event "
01442 << endl;
01443 break;
01444 }
01445 }
01446
01447 if(!newShowerOverlapsOld){
01448 MSG("EventSR",Msg::kDebug)<< " Building Event! " << endl;
01449 showerlist->AddDaughterLink(showerhandle);
01450 shw = showerlist->FindDaughter(&showerhandle);
01451 }
01452 }
01453
01454 if(!newShowerOverlapsOld){
01455 // form event from shower
01456 TObjArray recolist;
01457 recolist.Add(shw);
01458 cxx.SetDataIn(&recolist);
01459 AlgHandle eventah = af.GetAlgHandle("AlgEventSR",pEventAlgConfig);
01460 CandEventHandle eventhandle =
01461 CandEvent::MakeCandidate(eventah,cxx);
01462 eventhandle.SetCandSlice(slice);
01463 eventhandle.SetPrimaryShower(dynamic_cast<CandShowerHandle*>
01464 (shw));
01465 ch.AddDaughterLink(eventhandle);
01466 }
01467 }
01468 }
01469 }
|
|
||||||||||||||||||||||||||||||||
|
Definition at line 668 of file AlgEventSRList.cxx. References abs(), CandHandle::AddDaughterLink(), CandEventHandle::AddShower(), CandHandle::FindDaughter(), Registry::Get(), AlgFactory::GetAlgHandle(), CandRecoHandle::GetBegPlane(), CandEventHandle::GetCandSlice(), CandStripHandle::GetCharge(), CandHandle::GetDaughterIterator(), Registry::GetDouble(), AlgFactory::GetInstance(), CandStripHandle::GetPlane(), CandSubShowerSRHandle::GetPlaneView(), CandStripHandle::GetPlaneView(), CandEventHandle::GetPrimaryTrack(), CandClusterHandle::IsShowerLike(), CandShower::MakeCandidate(), CandCluster::MakeCandidate(), CandShowerSR::MakeCandidate(), CandSubShowerSR::MakeCandidate(), MSG, CandClusterHandle::SetCandSlice(), CandRecoHandle::SetCandSlice(), CandSubShowerSRHandle::SetClusterID(), CandContext::SetDataIn(), and CandEventHandle::SetPrimaryShower(). Referenced by RunAlg(). 00674 {
00675 // need to create a shower -- include strips from first plane in each
00676 // view plus this previously unassociated hit to generate a 3D object
00677
00678 // Get singleton instance of AlgFactory
00679 const char *pEventAlgConfig = 0;
00680 ac.Get("EventAlgConfig",pEventAlgConfig);
00681
00682 Double_t pMinShwStripPE = ac.GetDouble("MinShwStripPE");
00683 Double_t pMaxNewShwLen = ac.GetDouble("MaxNewShwLen");
00684
00685 AlgFactory &af = AlgFactory::GetInstance();
00686
00687 CandTrackHandle *track = closestevent->GetPrimaryTrack();
00688 if (!showerlist) {
00689 MSG("EventSR",Msg::kError) <<"CandShowerListHandle missing\n" << endl;
00690 return;
00691 }
00692
00693 closestevent->AddDaughterLink(*closeststrip);
00694
00695 // create arrays of strips for each planeview to create
00696 // shower from
00697
00698 MSG("EventSR",Msg::kVerbose) << "creating shower \n";
00699 TObjArray ustriparray;
00700 TObjArray vstriparray;
00701 Int_t uplane=track->GetBegPlane(PlaneView::kU);
00702 Int_t vplane=track->GetBegPlane(PlaneView::kV);
00703 // seed this shower with strips in most upstream track hits
00704 // in each view, along with hits above a charge threshold and
00705 // within pMaxNewShwLen of the track start
00706 TIter stripItr(track->GetDaughterIterator());
00707 while (CandStripHandle *tstrip =
00708 dynamic_cast<CandStripHandle*>(stripItr())) {
00709 if ((tstrip->GetPlane() == uplane) ||
00710 (tstrip->GetPlaneView()==PlaneView::kU &&
00711 tstrip->GetCharge()>pMinShwStripPE &&
00712 abs(tstrip->GetPlane()-uplane)<pMaxNewShwLen)) {
00713 ustriparray.Add(tstrip);
00714 }
00715 if ((tstrip->GetPlane() == vplane) ||
00716 (tstrip->GetPlaneView()==PlaneView::kV &&
00717 tstrip->GetCharge()>pMinShwStripPE &&
00718 abs(tstrip->GetPlane()-vplane)<pMaxNewShwLen)) {
00719 vstriparray.Add(tstrip);
00720 }
00721 }
00722 // add unassoc strip to appropriate array
00723 switch (closeststrip->GetPlaneView()) {
00724 case PlaneView::kU:
00725 ustriparray.Add(closeststrip);
00726 break;
00727 case PlaneView::kV:
00728 vstriparray.Add(closeststrip);
00729 break;
00730 default:
00731 break;
00732 }
00733 // build shower from U/V clusters or subshowers
00734 if(ustriparray.GetLast()>=0 && vstriparray.GetLast()>=0){
00735 if(showerlist->InheritsFrom("CandShowerSRListHandle") && subshowerlist){
00736
00737 MSG("EventSR",Msg::kVerbose) << "U striparray has " << ustriparray.GetLast()+1 << " entries" << endl;
00738 MSG("EventSR",Msg::kVerbose) << "V striparray has " << vstriparray.GetLast()+1 << " entries" << endl;
00739 // now construct CandSubShowers
00740 AlgHandle subshowerah = af.GetAlgHandle("AlgSubShowerSR","default");
00741
00742 cxx.SetDataIn(&ustriparray);
00743 CandSubShowerSRHandle usubshowerhandle =
00744 CandSubShowerSR::MakeCandidate(subshowerah,cxx);
00745 usubshowerhandle.SetCandSlice(closestevent->GetCandSlice());
00746 usubshowerhandle.SetClusterID(ClusterType::kUnknown);
00747 subshowerlist->AddDaughterLink(usubshowerhandle);
00748 MSG("EventSR",Msg::kVerbose) << "U subshower view: " << usubshowerhandle.GetPlaneView()
00749 <<endl;
00750
00751 cxx.SetDataIn(&vstriparray);
00752 CandSubShowerSRHandle vsubshowerhandle =
00753 CandSubShowerSR::MakeCandidate(subshowerah,cxx);
00754 vsubshowerhandle.SetCandSlice(closestevent->GetCandSlice());
00755 vsubshowerhandle.SetClusterID(ClusterType::kUnknown);
00756 subshowerlist->AddDaughterLink(vsubshowerhandle);
00757 MSG("EventSR",Msg::kVerbose) << "V subshower view: " << vsubshowerhandle.GetPlaneView()
00758 <<endl;
00759
00760 //add subshowers to list
00761 CandShowerSRListHandle* showerlistSR = dynamic_cast<CandShowerSRListHandle*>(showerlist);
00762 TObjArray newshower;
00763 CandSubShowerSRHandle * usubshower = dynamic_cast<CandSubShowerSRHandle*>
00764 (subshowerlist->FindDaughter(&usubshowerhandle));
00765
00766 CandSubShowerSRHandle * vsubshower = dynamic_cast<CandSubShowerSRHandle*>
00767 (subshowerlist->FindDaughter(&vsubshowerhandle));
00768 newshower.Add(usubshower);
00769 newshower.Add(vsubshower);
00770 cxx.SetDataIn(&newshower);
00771
00772 //get ShowerSS alghandle and make shower from subshowers
00773 AlgHandle showerahSS = af.GetAlgHandle("AlgShowerSS","default");
00774 CandShowerSRHandle showerhandleSR = CandShowerSR::MakeCandidate(showerahSS,cxx);
00775 showerhandleSR.SetCandSlice(closestevent->GetCandSlice());
00776 showerlistSR->AddDaughterLink(showerhandleSR);
00777 CandHandle *shw = showerlistSR->FindDaughter(&showerhandleSR);
00778 CandShowerHandle *shwh = dynamic_cast<CandShowerHandle*>(shw);
00779 closestevent->AddShower(shwh);
00780 closestevent->SetPrimaryShower(shwh);
00781 }
00782 else {
00783 // now construct CandClusters
00784 AlgHandle clusterah = af.GetAlgHandle("AlgClusterSR","default");
00785
00786 cxx.SetDataIn(&ustriparray);
00787 CandClusterHandle uclusterhandle =
00788 CandCluster::MakeCandidate(clusterah,cxx);
00789 uclusterhandle.SetCandSlice(closestevent->GetCandSlice());
00790 uclusterhandle.IsShowerLike(1);
00791 clusterlist->AddDaughterLink(uclusterhandle);
00792
00793 cxx.SetDataIn(&vstriparray);
00794 CandClusterHandle vclusterhandle =
00795 CandCluster::MakeCandidate(clusterah,cxx);
00796 vclusterhandle.SetCandSlice(closestevent->GetCandSlice());
00797 vclusterhandle.IsShowerLike(1);
00798 clusterlist->AddDaughterLink(vclusterhandle);
00799
00800 // build shower from U/V clusters just created
00801 TObjArray newshower;
00802 CandHandle * ucluster =
00803 clusterlist->FindDaughter(&uclusterhandle);
00804 CandHandle * vcluster =
00805 clusterlist->FindDaughter(&vclusterhandle);
00806
00807 newshower.Add(ucluster);
00808 newshower.Add(vcluster);
00809
00810 cxx.SetDataIn(&newshower);
00811 AlgHandle showerah = af.GetAlgHandle("AlgShowerSR",pEventAlgConfig);
00812 CandShowerHandle showerhandle =
00813 CandShower::MakeCandidate(showerah,cxx);
00814 showerhandle.SetCandSlice(closestevent->GetCandSlice());
00815 showerlist->AddDaughterLink(showerhandle);
00816 CandHandle *shw = showerlist->FindDaughter(&showerhandle);
00817 CandShowerHandle *shwh = dynamic_cast<CandShowerHandle*>(shw);
00818
00819 // add this new shower to this event, and make it the
00820 // primary shower
00821 closestevent->AddShower(shwh);
00822 closestevent->SetPrimaryShower(shwh);
00823 }
00824 }
00825 }
|
|
||||||||||||||||||||
|
Definition at line 1851 of file AlgEventSRList.cxx. References CandRecoHandle::GetBegPlane(), CandStripHandle::GetBegTime(), CandHandle::GetDaughterIterator(), Registry::GetDouble(), CandStripHandle::GetPlane(), CandStripHandle::GetPlaneView(), CandEventHandle::GetPrimaryShower(), CandEventHandle::GetPrimaryTrack(), CandStripHandle::GetStrip(), CandStripHandle::GetTPos(), CandRecoHandle::GetVtxT(), CandRecoHandle::GetVtxZ(), and MSG. Referenced by RunAlg(). 01851 {
01852 // grab all needed algorithm parameters
01853
01854
01855 Double_t pShwTrkDz = ac.GetDouble("ShwTrkDz");
01856 Double_t pHitAssocDTime0 = ac.GetDouble("HitAssocDTime0");
01857 Double_t pHitAssocDTime1 = ac.GetDouble("HitAssocDTime1");
01858 Double_t pHitAssocZParm = ac.GetDouble("HitAssocZParm");
01859 Double_t pHitAssocPParm = ac.GetDouble("HitAssocPParm");
01860 Double_t pHitAssocTParm = ac.GetDouble("HitAssocTParm");
01861
01862 // construct the map, first looping over strips
01863 for (Int_t i=0; i<=unassociated.GetLast(); i++) {
01864 CandStripHandle *strip =
01865 dynamic_cast<CandStripHandle*>(unassociated.At(i));
01866 TIter eventItr(ch.GetDaughterIterator());
01867 // inner loop is over events
01868 while (CandEventHandle *event =
01869 dynamic_cast<CandEventHandle*>(eventItr())) {
01870
01871 // calculate separation in space/time
01872 Double_t dtime = (strip->GetBegTime()-event->GetVtxT());
01873 Double_t bestdist2=-1.;
01874 Double_t bestdplane=-1;
01875 Double_t bestdtpos=-1;
01876 Double_t bestdtime=-1;
01877 dist2map[i][event] = 999999999.;
01878 MSG("EventSR",Msg::kVerbose) << i << " "
01879 << strip->GetPlane() << " " << strip->GetStrip() << " dtime " << dtime*1e9 << "/" << pHitAssocDTime0*1e9 << "/" << pHitAssocDTime1*1e9 << endl;
01880 // if there is a rough time match proceed
01881 if (dtime>pHitAssocDTime0 && dtime<pHitAssocDTime1) {
01882
01883 Float_t vertexsep = 0;
01884 // If event has both shower
01885 // and track calc separation between the two. If this
01886 // separation is greater
01887 // than pSHwTrkDz, we won't bother adding the strip to the
01888 // primary shower, and will instead consider whether
01889 // to create a new shower at track vertex.
01890 if (event->GetPrimaryShower() && event->GetPrimaryTrack())
01891 vertexsep = fabs(event->GetPrimaryShower()->GetVtxZ() -
01892 event->GetPrimaryTrack()->GetVtxZ());
01893
01894 // the event has a shower, and either no track, or track and
01895 // shower vertices are in agreement. In this case, we
01896 // consider adding this strip to this shower, so calc separation.
01897 if (event->GetPrimaryShower() &&
01898 (!event->GetPrimaryTrack() || vertexsep<pShwTrkDz)) {
01899
01900 // create iterator of shower daughter strips in same view
01901 // as unassoc strip
01902 CandStripHandleItr shwstripItr(
01903 event->GetPrimaryShower()->GetDaughterIterator());
01904 CandStripHandleKeyFunc *shwstripKf =
01905 shwstripItr.CreateKeyFunc();
01906 shwstripKf->SetFun(CandStripHandle::KeyFromView);
01907 shwstripItr.GetSet()->AdoptSortKeyFunc(shwstripKf);
01908 shwstripKf = 0;
01909 shwstripItr.GetSet()->Slice();
01910 shwstripItr.GetSet()->Slice(strip->GetPlaneView(),
01911 strip->GetPlaneView());
01912
01913 // iterate over the daughter list, and find minimum distane
01914 // between daughter and unassoc strip
01915 while (CandStripHandle *shwstrip =
01916 dynamic_cast<CandStripHandle*>(shwstripItr())) {
01917 Double_t dplane =
01918 (Double_t)(strip->GetPlane()-shwstrip->GetPlane());
01919 Double_t dtpos = strip->GetTPos()-shwstrip->GetTPos();
01920 Double_t dist2 = (pHitAssocZParm*dplane*dplane) +
01921 (pHitAssocPParm*dtpos*dtpos) +
01922 (pHitAssocTParm*dtime*dtime);
01923 if (bestdist2<0. || dist2<bestdist2) {
01924 bestdist2 = dist2;
01925 bestdplane=dplane;
01926 bestdtpos=dtpos;
01927 bestdtime=dtime;
01928 }
01929 }
01930 MSG("EventSR",Msg::kVerbose)
01931 << "primary shower." << " dplane:" << bestdplane <<" dtpos:"
01932 << bestdtpos <<" dtime:" << bestdtime <<" dist2:"
01933 << bestdist2<< "\n";
01934 dist2map[i][event] = bestdist2;
01935 } // end if event has shower, etc.
01936 // else if criteria above was not satisfied, consider whether
01937 // strip is near track vertex, in which case we start new shower
01938 else if (event->GetPrimaryTrack()) {
01939
01940 // calc distance to vertex
01941 Double_t dplane =
01942 (Double_t)(strip->GetPlane()-event->GetPrimaryTrack()->
01943 GetBegPlane());
01944 Double_t dtpos=0;
01945 switch (strip->GetPlaneView()) {
01946 case PlaneView::kU:
01947 dtpos=strip->GetTPos()-event->GetPrimaryTrack()->
01948 GetU(event->GetPrimaryTrack()->GetBegPlane());
01949 break;
01950 case PlaneView::kV:
01951 dtpos=strip->GetTPos()-event->GetPrimaryTrack()->
01952 GetV(event->GetPrimaryTrack()->GetBegPlane());
01953 break;
01954 default:
01955 break;
01956 }
01957 Double_t dist2 = (pHitAssocZParm*dplane*dplane) +
01958 (pHitAssocPParm*dtpos*dtpos) +
01959 (pHitAssocTParm*dtime*dtime);
01960 dist2map[i][event] = dist2;
01961 MSG("EventSR",Msg::kVerbose)
01962 << "primary track. begin:" << " dplane:" << dplane
01963 << " dtpos:" << dtpos <<" dtime:" << dtime <<" dist2:"
01964 << dist2 << "\n";
01965 } // end if primary track
01966 } // end if time match OK
01967 } // end loop over events
01968 } // end loop over unassoc strips
01969 }
|
|
||||||||||||||||||||
|
Definition at line 1597 of file AlgEventSRList.cxx. References CandRecoHandle::GetCandSlice(), CandHandle::GetNDaughters(), CandHandle::IsCloneOf(), and MSG. Referenced by RunAlg(). 01597 {
01598
01599 if (showerItr) {
01600 showerItr->Reset();
01601 while (CandShowerHandle *shower =
01602 dynamic_cast<CandShowerHandle*>((*showerItr)())) {
01603 if (shower->GetCandSlice()) {
01604 if (slice->IsCloneOf(*(shower->GetCandSlice()))) {
01605 recolist.Add(shower);
01606 }
01607 }
01608 else {
01609 MSG("EventSR", Msg::kError)
01610 << "Shower doesn't contain a slice. Not added to recolist."
01611 << endl;
01612 }
01613 }
01614 }
01615
01616 if (trackItr) {
01617 trackItr->Reset();
01618 while (CandTrackHandle *track =
01619 dynamic_cast<CandTrackHandle*>((*trackItr)())) {
01620 if (track->GetCandSlice()) {
01621 if (slice->IsCloneOf(*track->GetCandSlice())) {
01622 if(track->GetNDaughters()==0 &&
01623 track->InheritsFrom("CandFitTrackHandle") &&
01624 dynamic_cast<CandFitTrackHandle*>(track)->GetFinderTrack()){
01625 track = dynamic_cast<CandFitTrackHandle*>(track)->GetFinderTrack();
01626 MSG("EventSR", Msg::kDebug)<< "Finder Track being used " << endl;
01627 }
01628 recolist.Add(track);
01629 }
01630 }
01631 else {
01632 MSG("EventSR", Msg::kError)
01633 << "Track doesn't contain a slice. Not added to recolist."
01634 << endl;
01635 }
01636 }
01637 }
01638 }
|
|
||||||||||||||||||||
|
Definition at line 1793 of file AlgEventSRList.cxx. References CandHandle::FindDaughter(), CandRecoHandle::GetCandSlice(), CandHandle::GetDaughterIterator(), and CandHandle::IsCloneOf(). Referenced by RunAlg(). 01793 {
01794
01795 while (CandSliceHandle *slice =
01796 dynamic_cast<CandSliceHandle*>(sliceItr())) {
01797 TIter stripItr(slice->GetDaughterIterator());
01798 while (CandStripHandle *strip =
01799 dynamic_cast<CandStripHandle*>(stripItr())) {
01800 Bool_t found=false;
01801 // check for duplicates
01802
01803 for (Int_t i=0; i<=unassociated.GetLast() && !found; i++) {
01804 CandStripHandle *strip0 =
01805 dynamic_cast<CandStripHandle*>(unassociated.At(i));
01806 if (*strip == *strip0) {
01807 found = true;
01808 break;
01809 }
01810 }
01811 // if this strip not already in unnassociated list, then
01812 // loop over objects in this slice, and check against all daughter strips
01813 if (!found) {
01814 if (showerItr) {
01815 showerItr->Reset();
01816 while (CandShowerHandle *shower =
01817 dynamic_cast<CandShowerHandle*>((*showerItr)())) {
01818 if (shower->GetCandSlice()) {
01819 if (slice->IsCloneOf(*(shower->GetCandSlice()))) {
01820 if (shower->FindDaughter(strip)) {
01821 found = true;
01822 break;
01823 }
01824 }
01825 }
01826 }
01827 }
01828 if (trackItr && !found) {
01829 trackItr->Reset();
01830 while (CandTrackHandle *track =
01831 dynamic_cast<CandTrackHandle*>((*trackItr)())) {
01832 if (track->GetCandSlice()) {
01833 if (slice->IsCloneOf(*(track->GetCandSlice()))) {
01834 if (track->FindDaughter(strip)) {
01835 found = true;
01836 break;
01837 }
01838 }
01839 }
01840 }
01841 }
01842 }
01843 // this strip is not in any event, add to unassociated list
01844 if (!found) {
01845 unassociated.Add(strip);
01846 }
01847 }
01848 }
01849 }
|
|
||||||||||||||||||||
|
Definition at line 1646 of file AlgEventSRList.cxx. References CandTrackHandle::BelongsWithTrack(), and Registry::GetDouble(). Referenced by RunAlg(). 01646 {
01647
01648 Double_t pTrkTrkDtpos2 = ac.GetDouble("TrkTrkDtpos2")*9;
01649 Double_t pTrkTrkDz = ac.GetDouble("TrkTrkDz")*3;
01650 Double_t pTrkTrkDt = ac.GetDouble("TrkTrkDt");
01651 for (Int_t ireco2=0; ireco2<=objectlist->GetLast();
01652 ireco2++) {
01653 if (objectlist->At(ireco2)->InheritsFrom("CandTrackHandle")) {
01654 CandTrackHandle *othertrack = dynamic_cast<CandTrackHandle*>
01655 (objectlist->At(ireco2));
01656 if( !track->BelongsWithTrack(othertrack,
01657 ac,
01658 vldcptr,
01659 pTrkTrkDtpos2,pTrkTrkDz,pTrkTrkDt))return false;
01660 }
01661 }
01662 return true;
01663 }
|
|
||||||||||||||||||||||||||||
|
Definition at line 1688 of file AlgEventSRList.cxx. References CandHandle::AddDaughterLink(), CandHandle::FindDaughter(), Registry::Get(), AlgFactory::GetAlgHandle(), CandHandle::GetDaughterIterator(), AlgFactory::GetInstance(), CandStripHandle::GetPlaneView(), CandHandle::GetVldContext(), CandHandle::IsEqual(), CandClusterHandle::IsShowerLike(), CandShower::MakeCandidate(), CandCluster::MakeCandidate(), MSG, CandHandle::RemoveDaughter(), CandRecoHandle::SetCandSlice(), CandClusterHandle::SetCandSlice(), and CandContext::SetDataIn(). Referenced by RunAlg(). 01692 {
01693
01694
01695 const char *pEventAlgConfig = 0;
01696 ac.Get("EventAlgConfig",pEventAlgConfig);
01697
01698 for (Int_t i=0; i<=eventlist.GetLast(); i++) {
01699 TObjArray *objectlist = dynamic_cast<TObjArray*>(eventlist.At(i));
01700 if(objectlist->GetLast()<=0)break;
01701 Bool_t foundtrack=false;
01702 for (Int_t i=0; i<=objectlist->GetLast(); i++) {
01703 if (!(objectlist->At(i)->InheritsFrom("CandShowerHandle"))) {
01704 foundtrack=true;
01705 break;
01706 }
01707 }
01708 if(foundtrack)break;
01709 MSG("EventSR",Msg::kDebug) << " merging showers\n";
01710
01711 // if we are here, we have an event with multiple showers and no tracks, so we merge into single shower.
01712
01713 // Get singleton instance of AlgFactory
01714 AlgFactory &af = AlgFactory::GetInstance();
01715
01716 // construct total U/V cluster daughter list
01717 TObjArray ustriparray;
01718 TObjArray vstriparray;
01719 for (Int_t i=0; i<=objectlist->GetLast(); i++) {
01720 CandShowerHandle * shower = dynamic_cast<CandShowerHandle *>(objectlist->At(i));
01721 TIter stripItr(shower->GetDaughterIterator());
01722 while (CandStripHandle *strip =
01723 dynamic_cast<CandStripHandle*>(stripItr())) {
01724 if(strip->GetPlaneView()==PlaneView::kU)ustriparray.Add(strip);
01725 if(strip->GetPlaneView()==PlaneView::kV)vstriparray.Add(strip);
01726 }
01727 }
01728
01729 // make U cluster
01730 cxx.SetDataIn(&ustriparray);
01731 AlgHandle clusterah = af.GetAlgHandle("AlgClusterSR","default");
01732 CandClusterHandle uclusterhandle =
01733 CandCluster::MakeCandidate(clusterah,cxx);
01734 uclusterhandle.SetCandSlice(slice);
01735 uclusterhandle.IsShowerLike(1);
01736
01737 // make V cluster
01738 cxx.SetDataIn(&vstriparray);
01739 CandClusterHandle vclusterhandle =
01740 CandCluster::MakeCandidate(clusterah,cxx);
01741 vclusterhandle.SetCandSlice(slice);
01742 vclusterhandle.IsShowerLike(1);
01743
01744 // add new clusters to cluster list
01745 clusterlist->AddDaughterLink(uclusterhandle);
01746 clusterlist->AddDaughterLink(vclusterhandle);
01747
01748 // build shower
01749 TObjArray newshower;
01750 CandHandle *ucluster =
01751 clusterlist->FindDaughter(&uclusterhandle);
01752 CandHandle *vcluster =
01753 clusterlist->FindDaughter(&vclusterhandle);
01754 newshower.Add(ucluster);
01755 newshower.Add(vcluster);
01756 cxx.SetDataIn(&newshower);
01757
01758 AlgHandle showerah = af.GetAlgHandle("AlgShowerSR",pEventAlgConfig);
01759 CandShowerHandle showerhandle =
01760 CandShower::MakeCandidate(showerah,cxx);
01761 showerhandle.SetCandSlice(slice);
01762 showerlist->AddDaughterLink(showerhandle);
01763 // need to clean up shower list
01764 for (Int_t i=0; i<=objectlist->GetLast(); i++) {
01765 CandShowerHandle * shower = dynamic_cast<CandShowerHandle *>(objectlist->At(i));
01766 TIter shiter(showerlist->GetDaughterIterator());
01767 CandShowerHandle *oldshower;
01768 Bool_t found=false;
01769 while (!found &&
01770 (oldshower = dynamic_cast<CandShowerHandle*>(shiter()))) {
01771 if (shower->IsEqual(oldshower)) {
01772 found=true;
01773 showerlist->RemoveDaughter(oldshower);
01774 }
01775 }
01776 }
01777 CandShowerHandleItr showerItr(showerlist->GetDaughterIterator());
01778 while (CandShowerHandle *shower =
01779 dynamic_cast<CandShowerHandle*>(showerItr())){
01780 MSG("EventSR",Msg::kDebug) << " new shower " << shower << " " << shower->GetVldContext() << endl;
01781 }
01782 // reset object list to contain new shower
01783 objectlist->Clear();
01784 CandShowerHandle * shower = dynamic_cast<CandShowerHandle *>(showerlist->FindDaughter(&showerhandle));
01785 assert (shower);
01786 objectlist->Add(shower);
01787 }
01788 }
|
|
||||||||||||||||
|
This method fills a cluster list for every shower in the snarl, and then reruns the shower algorithm. Following this, it tracks the primary track in each event through the primary shower, and subtracts 1 MIP for each strip passed through. Definition at line 857 of file AlgEventSRList.cxx. References CandHandle::AddDaughterLink(), CandShowerHandle::CalibrateEnergy(), CandClusterHandle::DupHandle(), CandSubShowerSRHandle::DupHandle(), Registry::Get(), AlgHandle::GetAlgConfig(), AlgFactory::GetAlgHandle(), CandEventHandle::GetCandSlice(), CandShowerHandle::GetCluster(), CandContext::GetDataIn(), CandHandle::GetDaughterIterator(), AlgFactory::GetInstance(), CandShowerHandle::GetLastCluster(), CandEventHandle::GetLastShower(), CandShowerSRHandle::GetLastSubShower(), CandEventHandle::GetPrimaryTrack(), CandEventHandle::GetShowerWritable(), CandShowerSRHandle::GetSubShower(), CandHandle::IsCloneOf(), CandHandle::IsEqual(), MSG, CandHandle::RemoveDaughter(), AlgHandle::RunAlg(), CandRecoHandle::SetCandSlice(), and CandContext::SetDataIn(). Referenced by RunAlg(). 00858 {
00859
00860 // Retrieve persistant modifiable CandShowerList
00861 CandShowerListHandle *showerlist = const_cast<CandShowerListHandle*>
00862 (dynamic_cast<const CandShowerListHandle*>(cxx.GetDataIn()));
00863
00864 // Get singleton instance of AlgFactory
00865 AlgFactory &af = AlgFactory::GetInstance();
00866
00867 // Get an AlgHandle to AlgShowerSR with default AlgConfig
00868 const char *pEventAlgConfig = 0;
00869 ac.Get("EventAlgConfig",pEventAlgConfig);
00870
00871 AlgHandle ah = af.GetAlgHandle("AlgShowerSR",pEventAlgConfig);
00872 AlgHandle ahss = af.GetAlgHandle("AlgShowerSS","default");
00873 AlgConfig acsr = ah.GetAlgConfig();
00874 AlgConfig acss = ahss.GetAlgConfig();
00875
00876 TIter evItr(ch.GetDaughterIterator());
00877 while (CandEventHandle *ev =
00878 dynamic_cast<CandEventHandle*>(evItr())) {
00879 for (Int_t ishower=0; ishower<ev->GetLastShower()+1; ishower++) {
00880 CandShowerHandle *shower =
00881 dynamic_cast<CandShowerHandle*>(ev->GetShowerWritable(ishower));
00882 CandShowerSRHandle *showerSR = 0;
00883 if(shower->InheritsFrom("CandShowerSRHandle")) {
00884 showerSR = dynamic_cast<CandShowerSRHandle*>(shower);
00885 }
00886
00887 if(showerSR) { //if this is a CandShowerSRHandle, then assume subshower chain
00888 TObjArray newshower;
00889 // fill array of subshowers for this shower
00890 for (Int_t isubshower=0;
00891 isubshower<showerSR->GetLastSubShower()+1;
00892 isubshower++) {
00893 const CandSubShowerSRHandle *ssh = showerSR->GetSubShower(isubshower);
00894 if (ssh) {
00895 // New handle on heap
00896 CandSubShowerSRHandle *sshd = ssh->DupHandle();
00897 // Add new heap-based CandHandle to TObjArray
00898 newshower.Add(sshd);
00899 }
00900 }
00901 // re-run algorithm for this shower
00902 if (newshower.GetEntriesFast() > 0) {
00903 cxx.SetDataIn(&newshower);
00904 ahss.RunAlg(*showerSR,cxx);
00905 }
00906 else {
00907 MSG("EventSR", Msg::kError)
00908 << "Attempt to pass empty TObjArray newshower to AlgShowerSS"
00909 << " in CandContext. AlgShowerSS::RunAlg() call ignored."
00910 << endl;
00911 }
00912 // Delete heap-based CandHandles in TObjArray
00913 newshower.Delete();
00914 }
00915 else if (shower) {
00916 TObjArray newshower;
00917 // fill array of clusters for this shower
00918 for (Int_t icluster=0; icluster<shower->GetLastCluster()+1;
00919 icluster++) {
00920 const CandClusterHandle *cl = shower->GetCluster(icluster);
00921 if (cl) {
00922 // New handle on heap
00923 CandClusterHandle *cclh = cl->DupHandle();
00924 // Add new heap-based CandHandle to TObjArray
00925 newshower.Add(cclh);
00926 }
00927 }
00928 // re-run algorithm for this shower
00929 if (newshower.GetEntriesFast() > 0) {
00930 cxx.SetDataIn(&newshower);
00931 ah.RunAlg(*shower,cxx);
00932 }
00933 else {
00934 MSG("EventSR", Msg::kError)
00935 << "Attempt to pass empty TObjArray newshower to AlgShowerSR"
00936 << " in CandContext. AlgShowerSR::RunAlg() call ignored."
00937 << endl;
00938 }
00939
00940 // Delete heap-based CandHandles in TObjArray
00941 newshower.Delete();
00942 }
00943 else {
00944 MSG("EventSR",Msg::kWarning)
00945 << "Handle is not a CandShowerHandle."
00946 << " Shower not processed in ReConstructShowers."
00947 << endl;
00948 continue;
00949 }
00950
00951 // now loop through strips in this shower, and determine whether primary
00952 // track in this event intercepts this strip. If so, subtract 1 mip
00953 // from shower energy.
00954
00955 CandTrackHandle *primaryTrack = ev->GetPrimaryTrack();
00956
00957 // if event has primary track, extrapolate through shower and subtract energy loss to recalibrate
00958 if (primaryTrack) {
00959 AlgConfig acshw = acsr;
00960 if(shower->InheritsFrom("CandShowerSRHandle")) acshw=acss;
00961 shower->CalibrateEnergy(primaryTrack,acshw);
00962 }
00963
00964 // Update modified showers in persistent modifiable CandShowerList.
00965 // CandHandle could potentially supply a ReplaceDaughter() function.
00966 // Interface of ReplaceDaughter() would be debatable.
00967 if (showerlist) {
00968 TIter shiter(showerlist->GetDaughterIterator());
00969 CandShowerHandle *target;
00970 Bool_t found = kFALSE;
00971 while (!found &&
00972 (target = dynamic_cast<CandShowerHandle*>(shiter()))) {
00973 if (shower->IsCloneOf(*target)) { // Tests clone or Cand ==
00974 found = kTRUE;
00975
00976 // Replace target only if shower is a modified version of target
00977
00978 if (!(shower->IsEqual(target))) { // CandBase inequality
00979 shower->SetCandSlice(ev->GetCandSlice());
00980 if (!showerlist->RemoveDaughter(target)) { // Failure
00981 MSG("EventSR",Msg::kError) << endl
00982 << "Failure of ShowerList daughter removal " << endl
00983 << "attempted during replacement by modified Shower."
00984 << endl << "Will result in double counted Shower."
00985 << endl;
00986 }
00987 showerlist->AddDaughterLink(*shower);
00988 }
00989 }
00990 }
00991
00992 // Add new (unfound) shower to persistent modifiable CandShowerList.
00993 if (!found){
00994 shower->SetCandSlice(ev->GetCandSlice());
00995 showerlist->AddDaughterLink(*shower);
00996 }
00997 }
00998 }
00999 }
01000 }
|
|
||||||||||||||||||||||||
|
Definition at line 828 of file AlgEventSRList.cxx. References CandStripHandle::GetBegTime(), Registry::GetDouble(), CandStripHandle::GetPlane(), CandStripHandle::GetPlaneView(), CandStripHandle::GetTPos(), and CandRecoHandle::GetVtxT(). Referenced by RunAlg(). 00830 {
00831 Double_t pHitAssocZParm = ac.GetDouble("HitAssocZParm");
00832 Double_t pHitAssocPParm = ac.GetDouble("HitAssocPParm");
00833 Double_t pHitAssocTParm = ac.GetDouble("HitAssocTParm");
00834
00835 for (Int_t i=0; i<=unassociated.GetLast(); i++) {
00836 CandStripHandle *strip =
00837 dynamic_cast<CandStripHandle*>(unassociated.At(i));
00838 if(strip->GetPlaneView()==closeststrip->GetPlaneView()){
00839 Double_t dtime = strip->GetBegTime()-closestevent->GetVtxT();
00840 Double_t dplane =
00841 (Double_t)(strip->GetPlane()-closeststrip->GetPlane());
00842 Double_t dtpos = strip->GetTPos()-closeststrip->GetTPos();
00843 Double_t dist2 = (pHitAssocZParm*dplane*dplane) +
00844 (pHitAssocPParm*dtpos*dtpos) +
00845 (pHitAssocTParm*dtime*dtime);
00846 if (dist2<dist2map[i][closestevent]) {
00847 dist2map[i][closestevent] = dist2;
00848 }
00849 }
00850 } // loop over unassoc hits
00851 }
|
|
||||||||||||
|
This method loops over tracks in a slice, and for each loops over all showers in the same slice. For each track/shower pair, the number of isolated track points is determined, by looking in each plane whether the track location is spanned by the shower. It the number of isolated track planes is below threshold, the track is removed from the object list. Definition at line 1475 of file AlgEventSRList.cxx. References CandRecoHandle::GetBegPlane(), VldContext::GetDetector(), Registry::GetDouble(), CandRecoHandle::GetEndPlane(), CandShowerHandle::GetMaxU(), CandShowerHandle::GetMaxV(), CandShowerHandle::GetMinU(), CandShowerHandle::GetMinV(), CandHandle::GetNDaughters(), CandTrackHandle::GetU(), CandTrackHandle::GetV(), CandHandle::GetVldContext(), CandTrackHandle::IsTPosValid(), and MSG. Referenced by RunAlg(). 01475 {
01476
01477
01478 Double_t pMinTrackIsolation = ac.GetDouble("MinTrackIsolation");
01479 Double_t pMinTrackIsolationDist = ac.GetDouble("MinTrackIsolationDist");
01480 for (Int_t i = 0; i <= recolist->GetLast(); i++) {
01481 CandTrackHandle *track=0;
01482 Int_t nisolated = 0;
01483 Int_t nisolatedU = 0;
01484 Int_t nisolatedV = 0;
01485 Bool_t isolated = true;
01486 Int_t longestcontig = 0;
01487 Int_t longestcontigU = 0;
01488 Int_t longestcontigV = 0;
01489
01490 if (recolist->At(i)->InheritsFrom("CandTrackHandle")) {
01491 track = dynamic_cast<CandTrackHandle*>(recolist->At(i));
01492
01493 // count number of planes in each view in which
01494 // track is outside shower
01495 Int_t firstplane = TMath::Min(track->GetBegPlane(),
01496 track->GetEndPlane());
01497 Int_t lastplane = TMath::Max(track->GetBegPlane(),
01498 track->GetEndPlane());
01499 Int_t firstuplane = TMath::Min(track->GetBegPlane(PlaneView::kU),
01500 track->GetEndPlane(PlaneView::kU));
01501 Int_t firstvplane = TMath::Min(track->GetBegPlane(PlaneView::kV),
01502 track->GetEndPlane(PlaneView::kV));
01503 Int_t lastuplane = TMath::Max(track->GetBegPlane(PlaneView::kU),
01504 track->GetEndPlane(PlaneView::kU) );
01505 Int_t lastvplane = TMath::Max(track->GetBegPlane(PlaneView::kV),
01506 track->GetEndPlane(PlaneView::kV) );
01507
01508 MSG("RemoveTracksInShowers",Msg::kDebug) << " track extent " << firstplane << " " << lastplane << " " << track->GetNDaughters() << " " << track->GetBegPlane() << " " << track->GetEndPlane() << endl;
01509
01510 for(Int_t iplane = firstplane;iplane <= lastplane;iplane++){
01511 PlexPlaneId plnid(track->GetVldContext()->GetDetector(),iplane,false);
01512 // require that the plane be within the track
01513 // extent for this planeview
01514 isolated = true;
01515 if((plnid.GetPlaneView() == PlaneView::kU &&
01516 iplane >= firstuplane && iplane <= lastuplane) ||
01517 (plnid.GetPlaneView() == PlaneView::kV &&
01518 iplane >= firstvplane &&
01519 iplane<=lastvplane)){
01520
01521 for (Int_t j = 0; j<=recolist->GetLast(); j++) {
01522 if(isolated){
01523 if (recolist->At(j)->InheritsFrom("CandShowerHandle")) {
01524 CandShowerHandle * shower = dynamic_cast<CandShowerHandle*>(recolist->At(j));
01525 if(iplane >= shower->GetBegPlane() &&
01526 iplane <= shower->GetEndPlane()){
01527 // if plane within shower extent, compare track position
01528 // with shower width. If track outside shower by
01529 // a distance pMinTrackIsolationDist, or shower width
01530 // is less than this distance, inc isolated.
01531 Double_t minPE=2.0;
01532 Float_t minUshw = shower->GetMinU(iplane,minPE)+0.02;
01533 Float_t minVshw = shower->GetMinV(iplane,minPE)+0.02;
01534 Float_t maxUshw = shower->GetMaxU(iplane,minPE)-0.02;
01535 Float_t maxVshw = shower->GetMaxV(iplane,minPE)-0.02;
01536
01537 MSG("RemoveTracksInShowers",Msg::kDebug) << " shower extent Plane: " << iplane << " U " << minUshw << "/" << track->GetU(iplane) << "/" << maxUshw << " V " << minVshw << "/" << track->GetV(iplane) << "/" << maxVshw << endl;
01538
01539 if(plnid.GetPlaneView() == PlaneView::kU &&
01540 (track->GetU(iplane) >= (minUshw-pMinTrackIsolationDist) &&
01541 track->GetU(iplane) <= (maxUshw+pMinTrackIsolationDist) &&
01542 maxUshw-minUshw > (pMinTrackIsolationDist))){
01543 isolated = false;
01544 }
01545 if(plnid.GetPlaneView() == PlaneView::kV &&
01546 (track->GetV(iplane) >= (minVshw-pMinTrackIsolationDist)&&
01547 track->GetV(iplane) <= (maxVshw+pMinTrackIsolationDist)&&
01548 maxVshw-minVshw > (pMinTrackIsolationDist))){
01549 isolated = false;
01550 }
01551 if(!track->IsTPosValid(iplane))isolated = false;
01552 }
01553 }
01554 }
01555 }
01556 if(track->IsTPosValid(iplane)){
01557 nisolated++;
01558 if(plnid.GetPlaneView() == PlaneView::kU){
01559 nisolatedU++;
01560 }
01561 else{
01562 nisolatedV++;
01563 }
01564 }
01565 if(!isolated) {
01566 nisolated=0; // reset contig. isolation counter
01567 if(plnid.GetPlaneView() == PlaneView::kU){
01568 nisolatedU=0;
01569 }
01570 else{
01571 nisolatedV=0;
01572 }
01573 }
01574 if(nisolated > longestcontig)longestcontig = nisolated;
01575 if(nisolatedU > longestcontigU)longestcontigU = nisolatedU;
01576 if(nisolatedV > longestcontigV)longestcontigV = nisolatedV;
01577
01578 MSG("RemoveTracksInShowers",Msg::kDebug) << " nisolated, longest " << nisolated << " " << longestcontig << endl;
01579
01580 // if the number of contiguous isolated track planes is less than threshold
01581 // we remove this track from the event
01582 }
01583 }
01584 }
01585 MSG("RemoveTracksInShowers",Msg::kDebug) << " longest contig:" << longestcontig << " U " << longestcontigU << " V " << longestcontigV<< "/" << pMinTrackIsolation << endl;
01586 if(track && longestcontig < pMinTrackIsolation &&
01587 longestcontigU < pMinTrackIsolation &&
01588 longestcontigV < pMinTrackIsolation){
01589 MSG("RemoveTracksInShowers",Msg::kDebug) << " REMOVING TRACK" << endl;
01590 recolist->RemoveAt(i);
01591 recolist->Compress();
01592 }
01593 }
01594 }
|
|
||||||||||||||||
|
Implements AlgBase. Definition at line 71 of file AlgEventSRList.cxx. References CandHandle::AddDaughterLink(), AddObjectToEvent(), AddStripToEvent(), CandTrackHandle::BelongsWithShower(), CandShowerHandle::BelongsWithShower(), CandTrackHandle::BelongsWithTrack(), CandShowerHandle::BelongsWithTrack(), BuildEventFromUnassoc(), CreatePrimaryShower(), FillDist2Map(), FillRecoList(), FindUnassociated(), Registry::Get(), AlgFactory::GetAlgHandle(), CandStripHandle::GetBegTime(), CandContext::GetCandRecord(), CandContext::GetDataIn(), CandHandle::GetDaughterIterator(), Registry::GetDouble(), CandRecoHandle::GetEndPlane(), AlgFactory::GetInstance(), CandEventHandle::GetLastShower(), CandContext::GetMom(), CandHandle::GetNDaughters(), CandStripHandle::GetPlane(), CandEventHandle::GetPrimaryShower(), CandEventHandle::GetPrimaryTrack(), CandEventHandle::GetShower(), CandEventHandle::GetShowerWritable(), CandStripHandle::GetTPos(), RecMinos::GetVldContext(), CandRecoHandle::GetVtxPlane(), CandRecoHandle::GetVtxT(), CandRecoHandle::GetVtxU(), CandRecoHandle::GetVtxV(), CandRecoHandle::GetVtxZ(), CandHandle::IsCloneOf(), CandEvent::MakeCandidate(), MatchOtherTracksInEvent(), max(), MergeShowers(), min(), MSG, ReConstructShowers(), ReFillDist2Map(), RemoveTracksinShowers(), CandEventHandle::SetCandSlice(), and SetPrimaryShowers(). 00073 {
00074
00075 assert(cx.GetDataIn());
00076 if (!(cx.GetDataIn()->InheritsFrom("TObjArray"))) return;
00077
00078 CandContext cxx(this,cx.GetMom());
00079 AlgFactory &af = AlgFactory::GetInstance();
00080 const char *pEventAlgConfig = 0;
00081 ac.Get("EventAlgConfig",pEventAlgConfig);
00082 AlgHandle ah = af.GetAlgHandle("AlgEventSR",pEventAlgConfig);
00083 // grab all needed algorithm parameters
00084 Double_t pTrkTrkDtpos2 = ac.GetDouble("TrkTrkDtpos2");
00085 Double_t pTrkTrkDz = ac.GetDouble("TrkTrkDz");
00086 Double_t pTrkTrkDt = ac.GetDouble("TrkTrkDt");
00087 Double_t pShwTrkDtpos2 = ac.GetDouble("ShwTrkDtpos2");
00088 Double_t pShwTrkDz = ac.GetDouble("ShwTrkDz");
00089 Double_t pShwTrkDt = ac.GetDouble("ShwTrkDt");
00090 Double_t pShwShwDtpos2 = ac.GetDouble("ShwShwDtpos2");
00091 Double_t pShwShwDz = ac.GetDouble("ShwShwDz");
00092 Double_t pShwShwDt = ac.GetDouble("ShwShwDt");
00093 Double_t pMaxNewShwLen = ac.GetDouble("MaxNewShwLen");
00094 Double_t pHitAssocDTime0 = ac.GetDouble("HitAssocDTime0");
00095 Double_t pHitAssocDTime1 = ac.GetDouble("HitAssocDTime1");
00096 Double_t pHitAssocMaxDist2 = ac.GetDouble("HitAssocMaxDist2");
00097
00098 // grab all needed input lists
00099 const CandRecord *candrec = cx.GetCandRecord();
00100 assert(candrec);
00101 const VldContext *vldcptr = candrec->GetVldContext();
00102 assert(vldcptr);
00103 VldContext vldc = *vldcptr;
00104 const CandSliceListHandle *slicelist = 0;
00105 CandShowerListHandle *showerlist = 0;
00106 const CandTrackListHandle *tracklist = 0;
00107 CandClusterListHandle *clusterlist = 0;
00108 CandSubShowerSRListHandle *subshowerlist = 0;
00109 const TObjArray *cxin =
00110 dynamic_cast<const TObjArray *>(cx.GetDataIn());
00111 for (Int_t i=0; i<=cxin->GetLast(); i++) {
00112 TObject *tobj = cxin->At(i);
00113 if (tobj->InheritsFrom("CandSliceListHandle")) {
00114 slicelist = dynamic_cast<CandSliceListHandle*>(tobj);
00115 }
00116 if (tobj->InheritsFrom("CandShowerListHandle")) {
00117 showerlist = dynamic_cast<CandShowerListHandle*>(tobj);
00118 }
00119 if (tobj->InheritsFrom("CandTrackListHandle")) {
00120 tracklist = dynamic_cast<CandTrackListHandle*>(tobj);
00121 }
00122 if (tobj->InheritsFrom("CandClusterListHandle")) {
00123 clusterlist = dynamic_cast<CandClusterListHandle*>(tobj);
00124 }
00125 if (tobj->InheritsFrom("CandSubShowerSRListHandle")) {
00126 subshowerlist = dynamic_cast<CandSubShowerSRListHandle*>(tobj);
00127 }
00128 }
00129 if (!slicelist) {
00130 MSG("EventSR",Msg::kError) << "CandSliceListHandle missing\n";
00131 return;
00132 }
00133
00134
00135 CandShowerHandleItr * showerItr=0;
00136 // create iterators for track, shower, and cluster lists, keying on slice
00137 if (showerlist && showerlist->GetNDaughters()>0) {
00138 showerItr = new CandShowerHandleItr(showerlist->GetDaughterIterator());
00139 CandShowerHandleKeyFunc *showerKf = showerItr->CreateKeyFunc();
00140 showerKf->SetFun(CandShowerHandle::KeyFromSlice);
00141 showerItr->GetSet()->AdoptSortKeyFunc(showerKf);
00142 showerKf = 0;
00143 }
00144
00145 CandTrackHandleItr * trackItr = 0;
00146 if (tracklist && tracklist->GetNDaughters()>0) {
00147 trackItr = new CandTrackHandleItr(tracklist->GetDaughterIterator());
00148 CandTrackHandleKeyFunc *trackKf = trackItr->CreateKeyFunc();
00149 trackKf->SetFun(CandTrackHandle::KeyFromSlice);
00150 trackItr->GetSet()->AdoptSortKeyFunc(trackKf);
00151 trackKf = 0;
00152 }
00153
00154 CandClusterHandleItr * clusterItr = 0;
00155 if (clusterlist && clusterlist->GetNDaughters()>0) {
00156 clusterItr = new CandClusterHandleItr(clusterlist->GetDaughterIterator());
00157 CandClusterHandleKeyFunc *clusterKf = clusterItr->CreateKeyFunc();
00158 clusterKf->SetFun(CandClusterHandle::KeyFromSlice);
00159 clusterItr->GetSet()->AdoptSortKeyFunc(clusterKf);
00160 clusterKf = 0;
00161 }
00162
00163 CandSubShowerSRHandleItr * subshowerItr = 0;
00164 if (subshowerlist && subshowerlist->GetNDaughters()>0) {
00165 subshowerItr = new CandSubShowerSRHandleItr(subshowerlist->
00166 GetDaughterIterator());
00167 CandSubShowerSRHandleKeyFunc *subshowerKf = subshowerItr->CreateKeyFunc();
00168 subshowerKf->SetFun(CandSubShowerSRHandle::KeyFromSlice);
00169 subshowerItr->GetSet()->AdoptSortKeyFunc(subshowerKf);
00170 subshowerKf = 0;
00171 }
00172
00173 Int_t nslice=0;
00174
00175 // loop over slices
00176
00177 CandSliceHandleItr sliceItr(slicelist->GetDaughterIterator());
00178 while (CandSliceHandle *slice =
00179 dynamic_cast<CandSliceHandle*>(sliceItr())) {
00180
00181 ++nslice;
00182 MSG("EventSR", Msg::kDebug)
00183 << " ****** Slice " << nslice << " *******"
00184 << endl;
00185 TObjArray newevent;
00186 TObjArray recolist;
00187 TObjArray eventlist;
00188
00189 // construct list of all showers and tracks in this slice
00190 FillRecoList(slice,showerItr,trackItr,recolist);
00191
00192 // remove tracks in recolist which have few/any isolated hits
00193 RemoveTracksinShowers(ac,&recolist);
00194
00195 MSG("EventSR",Msg::kVerbose)
00196 << "recolist begin " << recolist.GetLast()+1 << "\n";
00197 // loop over shower+tracklist, and find associations
00198 for (Int_t i=0; i<=recolist.GetLast(); i++) {
00199 // determine whether this entry is shower or track
00200 CandShowerHandle *shower=0;
00201 CandTrackHandle *track=0;
00202 CandRecoHandle *reco=0;
00203 if (recolist.At(i)->InheritsFrom("CandShowerHandle")) {
00204 shower = dynamic_cast<CandShowerHandle*>(recolist.At(i));
00205 reco = shower;
00206 MSG("EventSR",Msg::kVerbose) << " shower " << reco->GetVtxU()
00207 << " " << reco->GetVtxV() << " "
00208 << reco->GetVtxZ() << "\n";
00209 }
00210 if (recolist.At(i)->InheritsFrom("CandTrackHandle")) {
00211 track = dynamic_cast<CandTrackHandle*>(recolist.At(i));
00212 reco = track;
00213 MSG("EventSR",Msg::kVerbose) << " track " << reco->GetVtxU()
00214 << " " << reco->GetVtxV() << " "
00215 << reco->GetVtxZ() << "\n";
00216 }
00217
00218 // now loop over events previously created
00219 // and see whether this object should be added
00220 Bool_t merge=false;
00221 TObjArray *prevlist=0;
00222 for (Int_t ievt=0; ievt<=eventlist.GetLast(); ievt++) {
00223 Bool_t thiseventmatches=false;
00224 TObjArray *objectlist =
00225 dynamic_cast<TObjArray*>(eventlist.At(ievt));
00226
00227 // loop over objects within this event
00228 for (Int_t ireco=0; !thiseventmatches && ireco<=objectlist->GetLast();
00229 ireco++) {
00230
00231 Bool_t match=false;
00232 if (objectlist->At(ireco)->InheritsFrom("CandShowerHandle")) {
00233 CandShowerHandle *target = dynamic_cast<CandShowerHandle*>
00234 (objectlist->At(ireco));
00235 if(shower) {
00236 match = target->BelongsWithShower(shower,
00237 ac,
00238 vldcptr,
00239 pShwShwDtpos2,
00240 pShwShwDz,
00241 pShwShwDt);
00242 }
00243 if(track) {
00244 match = target->BelongsWithTrack(track,
00245 ac,
00246 vldcptr,
00247 pShwTrkDtpos2,
00248 pShwTrkDz,
00249 pShwTrkDt);
00250 match = match && MatchOtherTracksInEvent(ac,
00251 vldcptr,
00252 track,
00253 objectlist);
00254 /*
00255 if(track->InheritsFrom("CandFitTrackHandle")){
00256 CandFitTrackHandle * fittrack = dynamic_cast<CandFitTrackHandle*>(track);
00257 match = match && fittrack->GetPass();
00258 }
00259 */
00260 }
00261 }
00262 else if (objectlist->At(ireco)->InheritsFrom("CandTrackHandle")) {
00263 CandTrackHandle *target = dynamic_cast<CandTrackHandle*>
00264 (objectlist->At(ireco));
00265 if(shower) {
00266 if(shower->InheritsFrom("CandShowerSRHandle")) {
00267 //use same function to match tracks to showerSRs
00268 //and showerSRs to tracks
00269 match = shower->BelongsWithTrack(target,
00270 ac,
00271 vldcptr,
00272 pShwTrkDtpos2,
00273 pShwTrkDz,
00274 pShwTrkDt);
00275 }
00276 else {
00277
00278 match = target->BelongsWithShower(shower,
00279 ac,
00280 vldcptr,
00281 pShwTrkDtpos2,
00282 pShwTrkDz,
00283 pShwTrkDt);
00284 }
00285 }
00286 if(track) {
00287 match = target->BelongsWithTrack(track,
00288 ac,
00289 vldcptr,
00290 pTrkTrkDtpos2,
00291 pTrkTrkDz,
00292 pTrkTrkDt);
00293 match = match && MatchOtherTracksInEvent(ac,
00294 vldcptr,
00295 track,
00296 objectlist);
00297 /*
00298 if(track->InheritsFrom("CandFitTrackHandle")){
00299 CandFitTrackHandle * fittrack = dynamic_cast<CandFitTrackHandle*>(track);
00300 match = match && fittrack->GetPass();
00301 }
00302 */
00303 }
00304 }
00305 if(match){
00306 thiseventmatches = true;
00307 MSG("EventSR",Msg::kVerbose)
00308 << " adding object to event \n";
00309 AddObjectToEvent(reco,objectlist,prevlist,merge);
00310 if(!merge)prevlist=objectlist;
00311 merge=true;
00312 }
00313 } // end loop over objects in event
00314 } // end loop over event list
00315 // we found no matches for this object, so start a new event
00316 if (!merge) {
00317 Bool_t pass=true;
00318 if (shower) {
00319 MSG("EventSR",Msg::kVerbose)
00320 << " none found, creating event for shower\n";
00321 }
00322
00323 if (track) {
00324 /*
00325 if(track->InheritsFrom("CandFitTrackHandle")){
00326 CandFitTrackHandle * fittrack = dynamic_cast<CandFitTrackHandle*>(track);
00327 pass=fittrack->GetPass();
00328 }
00329 */
00330 MSG("EventSR",Msg::kVerbose)
00331 << " none found, creating event for track\n";
00332 }
00333
00334 if(pass){
00335 TObjArray *event = new TObjArray;
00336 event->Add(recolist.At(i));
00337 eventlist.Add(event);
00338 }
00339 }
00340 } // end loop over recolist
00341
00342 // remove all empty events from event list
00343 for (Int_t i=0; i<=eventlist.GetLast(); i++) {
00344 TObjArray *objectlist = dynamic_cast<TObjArray*>(eventlist.At(i));
00345 if (objectlist->GetLast()<0) {
00346 eventlist.Remove(objectlist);
00347 }
00348 }
00349 eventlist.Compress();
00350
00351 // merge showers in NC events (if not using subshower reco chain)
00352 if(!showerlist->InheritsFrom("CandShowerSRListHandle") || !subshowerlist)
00353 MergeShowers(cxx, eventlist,ac,slice,clusterlist,showerlist);
00354
00355 // now make CandEvents for each event we have found
00356 Bool_t buildEvent=false;
00357 for (Int_t i=0; i<=eventlist.GetLast(); i++) {
00358 TObjArray *objectlist = dynamic_cast<TObjArray*>(eventlist.At(i));
00359 MSG("EventSR",Msg::kVerbose) << "making event of " << objectlist->GetLast()+1 << " objects \n";
00360 cxx.SetDataIn(objectlist);
00361 buildEvent=true;
00362 CandEventHandle eventhandle = CandEvent::MakeCandidate(ah,cxx);
00363 MSG("EventSR",Msg::kVerbose) << " # of strips: " << eventhandle.GetNDaughters() << "\n";
00364 eventhandle.SetCandSlice(slice);
00365 ch.AddDaughterLink(eventhandle);
00366 delete eventlist.At(i);
00367 }
00368 if (!buildEvent)
00369 BuildEventFromUnassoc(ac,ch,cx,slice);
00370 }
00371
00372 delete trackItr;
00373 delete showerItr;
00374 delete clusterItr;
00375 delete subshowerItr;
00376
00377 MSG("EventSR",Msg::kVerbose)
00378 << "starting unassociated hits assignment \n";
00379
00380 // find unassociated hits, and place them in tobjarray
00381 sliceItr.Reset();
00382 TObjArray unassociated;
00383 CandShowerHandleItr * showerItr2=0;
00384 CandTrackHandleItr * trackItr2=0;
00385 if (showerlist && showerlist->GetNDaughters()>0) {
00386 showerItr2 = new CandShowerHandleItr(showerlist->GetDaughterIterator());
00387 }
00388 if (tracklist && tracklist->GetNDaughters()>0) {
00389 trackItr2 = new CandTrackHandleItr(tracklist->GetDaughterIterator());
00390 }
00391 FindUnassociated(sliceItr,showerItr2,trackItr2, unassociated);
00392 delete trackItr2;
00393 delete showerItr2;
00394
00395 // reset primary shower assignment for each event (is this needed?)
00396 SetPrimaryShowers(ch,ac);
00397
00398 // now loop over unnassociated hits, and check for adjacency with all
00399 // showers, and track vertices (in the case that no shower exists).
00400 // If a match is found in the former case,
00401 // add strip to shower. In the latter case, create a new shower.
00402
00403 // this map contains the separation between each event/unassociated hit
00404 vector<map<const CandEventHandle*, Double_t> > dist2map(unassociated.GetLast()+1);
00405 FillDist2Map(ac,unassociated,ch,dist2map);
00406
00407 // initialize map which holds bool value, indicating whether hit can be associated with an event.
00408 vector<map<const CandEventHandle*, Bool_t> > assocmap(unassociated.GetLast()+1);
00409 for (Int_t i=0; i<=unassociated.GetLast(); i++) {
00410 TIter eventItr(ch.GetDaughterIterator());
00411 while (CandEventHandle *event =
00412 dynamic_cast<CandEventHandle*>(eventItr())) {
00413 assocmap[i][event]=false;
00414 }
00415 }
00416
00417 // loop over unnassociated hits, adding them to events.
00418 // After each loop the affected distance map entries are recalculated,
00419 // and the loop is repeated. This continues until a loop adds no strips.
00420 Bool_t found=true;
00421 Int_t n_found=0;
00422 while (found) {
00423 // found indicates whether a strip was added to an event in this loop
00424 found=false;
00425
00426 CandStripHandle *closeststrip= 0;
00427 CandEventHandle *closestevent= 0;
00428 Double_t closestdist2 = 9999999.;
00429 Int_t closesti=-1;
00430
00431 // loop over unassoc strips
00432 for (Int_t i=0; i<=unassociated.GetLast(); i++) {
00433 CandStripHandle *strip =
00434 dynamic_cast<CandStripHandle*>(unassociated.At(i));
00435
00436 CandEventHandle *bestevent = 0;
00437 Double_t bestdist2 = 9999999.;
00438 // loop over events, and find event which is closest to strip
00439 // and in time
00440 TIter eventItr(ch.GetDaughterIterator());
00441 while (CandEventHandle *event =
00442 dynamic_cast<CandEventHandle*>(eventItr())) {
00443 if (!assocmap[i][event]) {
00444 Double_t dtime = strip->GetBegTime()-event->GetVtxT();
00445 if (dtime>pHitAssocDTime0 && dtime<pHitAssocDTime1
00446 && (!bestevent || dist2map[i][event]<bestdist2)) {
00447 bestevent = event;
00448 bestdist2 = dist2map[i][event];
00449 }
00450 }
00451 }
00452 if (bestevent && (!closeststrip || bestdist2<closestdist2)) {
00453 closeststrip = strip;
00454 closesti=i;
00455 closestdist2 = bestdist2;
00456 closestevent = bestevent;
00457 }
00458 }
00459 MSG("EventSR",Msg::kVerbose)<< "closest strip " << closestdist2
00460 << "/"<<pHitAssocMaxDist2<< endl;
00461
00462 // if distance to closest event less than maximum allowable add to event
00463 if(closeststrip && closestevent && closestdist2<pHitAssocMaxDist2){
00464
00465 MSG("EventSR",Msg::kVerbose) << "closest strip "
00466 << closeststrip->GetPlane() << " "
00467 << closeststrip->GetTPos()
00468 << " " << closestdist2 << "\n";
00469
00470 assocmap[closesti][closestevent]=true;
00471 found=true;
00472 ++n_found;
00473
00474 // now either add this strip to existing primary shower, or
00475 // create a new shower at the track vertex if one does not exist
00476 // Get PrimaryShower CandHandle from fShowerList for modification.
00477 CandShowerHandle *shower = 0;
00478 if (CandShowerHandle *primsh = closestevent->GetPrimaryShower()) {
00479 for (Int_t ishower=0; !shower &&
00480 ishower<closestevent->GetLastShower()+1; ishower++) {
00481 const CandShowerHandle *target =
00482 closestevent->GetShower(ishower);
00483 if (primsh->IsCloneOf(*target)) // Tests clone or Cand ==
00484 shower = closestevent->GetShowerWritable(ishower);
00485 }
00486 }
00487
00488 Float_t minShwPlane=0;
00489 Float_t maxShwPlane=0;
00490 if(shower){
00491 minShwPlane=min(shower->GetVtxPlane(),shower->GetEndPlane());
00492 maxShwPlane=max(shower->GetVtxPlane(),shower->GetEndPlane());
00493 }
00494 Float_t vertexsep = 0;
00495 CandTrackHandle *track = closestevent->GetPrimaryTrack();
00496 if (shower && track)
00497 vertexsep = fabs(shower->GetVtxZ() -
00498 closestevent->GetPrimaryTrack()->GetVtxZ());
00499
00500 // if event has shower and either no track, or shower is close
00501 // to track vertex, add this hit to the shower which was
00502 // compared in position to this strip earler.
00503 if (shower && (!track || vertexsep<pShwTrkDz)) {
00504
00505 // NOTE: CandShowerHandle *shower, used to modify CandShower, is owned
00506 // by fShowerList.
00507 // add new strip to this shower, and the appropriate cluster
00508 if(closeststrip->GetPlane()>minShwPlane-pMaxNewShwLen &&
00509 closeststrip->GetPlane()<maxShwPlane+pMaxNewShwLen ){
00510
00511 MSG("EventSR",Msg::kVerbose) << "adding strip to shower \n";
00512 AddStripToEvent(closestevent,shower,subshowerlist,clusterlist,closeststrip);
00513 }
00514 }
00515
00516 // no shower consistent with track vertex, and this strip
00517 // is close to vertex, so start new shower.
00518 else if (track) {
00519 CreatePrimaryShower(ac,cxx,closestevent,showerlist,subshowerlist,clusterlist,closeststrip);
00520 }
00521
00522 // need to recalculate distances bewteen remaining
00523 // unassoc hits and this modified event, if the added strip
00524 // results in a smaller separation, replace value in dist2map
00525 ReFillDist2Map(ac,closeststrip,closestevent,unassociated,dist2map);
00526 } // if adding strip to event in form of new shower
00527 } // if found (if an unassoc hit was matched to event in last loop over them
00528
00529 // because we have added strips to previously constructed showers, their
00530 // runalg method should be run on them again. In the future, an
00531 // optimization would be to do this only on showers which have been
00532 // touched.
00533 MSG("EventSR",Msg::kVerbose) << "added " << n_found << " of "
00534 << unassociated.GetLast()+1 << " unassociated hits " << endl;
00535
00536 cxx.SetDataIn(showerlist); // Pass along persistable CandShowerList
00537 ReConstructShowers(ac,ch,cxx);
00538
00539 // For each event, we set it's primary shower to that which has the
00540 // highest energy.
00541
00542 SetPrimaryShowers(ch,ac);
00543 }
|
|
||||||||||||
|
Redetermine primary shower for each event. If the largest shower is greater than shwshwdz from the track vertex, and the closest shower has energy greater than minshwEfract call the closest shower the primary, otherwise the largest shower is the primary Definition at line 1005 of file AlgEventSRList.cxx. References abs(), CandHandle::GetDaughterIterator(), Registry::GetDouble(), CandShowerHandle::GetEnergy(), CandEventHandle::GetLastShower(), CandEventHandle::GetPrimaryTrack(), CandEventHandle::GetShower(), CandRecoHandle::GetVtxZ(), and CandEventHandle::SetPrimaryShower(). Referenced by RunAlg(). 01006 {
01007
01008 // This method loops over events in the eventlist, finding the largest
01009 // shower and setting that to the primary shower in the event.
01010
01011 Double_t pShwShwDz = ac.GetDouble("ShwShwDz");
01012 Double_t pMinShwEFract = ac.GetDouble("MinShwEFract");
01013
01014 TIter evItr(ch.GetDaughterIterator());
01015 while (CandEventHandle *ev =
01016 dynamic_cast<CandEventHandle*>(evItr())) {
01017 Float_t largestenergy = -1;
01018 const CandTrackHandle *track=ev->GetPrimaryTrack();
01019 const CandShowerHandle *largestshower = 0;
01020 const CandShowerHandle *closestshower = 0;
01021 Float_t dzclosest=1e6;
01022 Float_t dzlargest=0;
01023 Float_t closestenergy = -1;
01024 for (Int_t ishower=0; ishower<ev->GetLastShower()+1; ishower++) {
01025 const CandShowerHandle *shower = ev->GetShower(ishower);
01026 if (shower) {
01027 if (shower->GetEnergy()>largestenergy) {
01028 largestenergy = shower->GetEnergy();
01029 largestshower = shower;
01030 if(track)dzlargest=fabs(shower->GetVtxZ()-track->GetVtxZ());
01031 }
01032 if(track){
01033 if(fabs(shower->GetVtxZ()-track->GetVtxZ())<dzclosest){
01034 dzclosest=abs(shower->GetVtxZ()-track->GetVtxZ());
01035 closestshower=shower;
01036 closestenergy=shower->GetEnergy();
01037 }
01038 }
01039 }
01040 }
01041 Float_t efract=0;
01042 if(largestenergy){
01043 efract=closestenergy/largestenergy;
01044 }
01045 // closest shower to track vertex is primary if largest shower too far away in Z
01046 if(closestshower && (dzlargest-dzclosest)>pShwShwDz && efract>pMinShwEFract){
01047 ev->SetPrimaryShower(closestshower);
01048 }
01049 //largest shower is the primary if there is no track
01050 else if(largestshower)
01051 ev->SetPrimaryShower(largestshower);
01052 }
01053 }
|
|
|
Reimplemented from AlgBase. Definition at line 1972 of file AlgEventSRList.cxx. 01973 {
01974 }
|
1.3.9.1