//_____________________________________________________________________________ THaVDCTrackID::THaVDCTrackID( const THaVDCUVTrack* lower, const THaVDCUVTrack* upper) : THaTrackID() { // Constructor that automatically determines pivot numbers // from the given THaVDCUVTracks. THaVDCCluster* cluster; if( lower ) { if( (cluster = lower->GetUCluster())) fLowerU = cluster->GetPivotWireNum(); if( (cluster = lower->GetVCluster())) fLowerV = cluster->GetPivotWireNum(); } if( upper ) { if( (cluster = upper->GetUCluster())) fUpperU = cluster->GetPivotWireNum(); if( (cluster = upper->GetVCluster())) fUpperV = cluster->GetPivotWireNum(); } }
//_____________________________________________________________________________ Int_t THaVDC::ConstructTracks( TClonesArray* tracks, Int_t mode ) { // Construct tracks from pairs of upper and lower UV tracks and add // them to 'tracks' #ifdef WITH_DEBUG if( fDebug>1 ) { cout << "-----------------------------------------------\n"; cout << "ConstructTracks: "; if( mode == 0 ) cout << "iterating"; if( mode == 1 ) cout << "coarse tracking"; if( mode == 2 ) cout << "fine tracking"; cout << endl; } #endif UInt_t theStage = ( mode == 1 ) ? kCoarse : kFine; fUVpairs->Clear(); Int_t nUpperTracks = fUpper->GetNUVTracks(); Int_t nLowerTracks = fLower->GetNUVTracks(); #ifdef WITH_DEBUG if( fDebug>1 ) cout << "nUpper/nLower = " << nUpperTracks << " " << nLowerTracks << endl; #endif // No tracks at all -> can't have any tracks if( nUpperTracks == 0 && nLowerTracks == 0 ) { #ifdef WITH_DEBUG if( fDebug>1 ) cout << "No tracks.\n"; #endif return 0; } Int_t nTracks = 0; // Number of valid particle tracks through the detector Int_t nPairs = 0; // Number of UV track pairs to consider // One plane has no tracks, the other does // -> maybe recoverable with loss of precision // FIXME: Only do this if missing cluster recovery flag set if( nUpperTracks == 0 || nLowerTracks == 0 ) { //FIXME: Put missing cluster recovery code here //For now, do nothing #ifdef WITH_DEBUG if( fDebug>1 ) cout << "missing cluster " << nUpperTracks << " " << nUpperTracks << endl; #endif return 0; } THaVDCUVTrack *track, *partner; THaVDCTrackPair *thePair; for( int i = 0; i < nLowerTracks; i++ ) { track = fLower->GetUVTrack(i); if( !track ) continue; for( int j = 0; j < nUpperTracks; j++ ) { partner = fUpper->GetUVTrack(j); if( !partner ) continue; // Create new UV track pair. thePair = new( (*fUVpairs)[nPairs++] ) THaVDCTrackPair( track, partner ); // Explicitly mark these UV tracks as unpartnered track->SetPartner( NULL ); partner->SetPartner( NULL ); // Compute goodness of match parameter thePair->Analyze( fUSpacing ); } } #ifdef WITH_DEBUG if( fDebug>1 ) cout << nPairs << " pairs.\n"; #endif // Initialize some counters int n_exist = 0, n_mod = 0; int n_oops = 0; // How many tracks already exist in the global track array? if( tracks ) n_exist = tracks->GetLast()+1; // Sort pairs in order of ascending goodness of match if( nPairs > 1 ) fUVpairs->Sort(); // Mark pairs as partners, starting with the best matches, // until all tracks are marked. for( int i = 0; i < nPairs; i++ ) { if( !(thePair = static_cast<THaVDCTrackPair*>( fUVpairs->At(i) )) ) continue; #ifdef WITH_DEBUG if( fDebug>1 ) { cout << "Pair " << i << ": " << thePair->GetUpper()->GetUCluster()->GetPivotWireNum() << " " << thePair->GetUpper()->GetVCluster()->GetPivotWireNum() << " " << thePair->GetLower()->GetUCluster()->GetPivotWireNum() << " " << thePair->GetLower()->GetVCluster()->GetPivotWireNum() << " " << thePair->GetError() << endl; } #endif // Stop if track matching error too big if( thePair->GetError() > fErrorCutoff ) break; // Get the tracks of the pair track = thePair->GetLower(); partner = thePair->GetUpper(); if( !track || !partner ) continue; //FIXME: debug #ifdef WITH_DEBUG if( fDebug>1 ) { cout << "dUpper/dLower = " << thePair->GetProjectedDistance( track,partner,fUSpacing) << " " << thePair->GetProjectedDistance( partner,track,-fUSpacing); } #endif // Skip pairs where any of the tracks already has a partner if( track->GetPartner() || partner->GetPartner() ) { #ifdef WITH_DEBUG if( fDebug>1 ) cout << " ... skipped.\n"; #endif continue; } #ifdef WITH_DEBUG if( fDebug>1 ) cout << " ... good.\n"; #endif // Make the tracks of this pair each other's partners. This prevents // tracks from being associated with more than one valid pair. track->SetPartner( partner ); partner->SetPartner( track ); thePair->SetStatus(1); nTracks++; // Compute global track values and get TRANSPORT coordinates for tracks. // Replace local cluster slopes with global ones, // which have higher precision. THaVDCCluster *tu = track->GetUCluster(), *tv = track->GetVCluster(), *pu = partner->GetUCluster(), *pv = partner->GetVCluster(); Double_t du = pu->GetIntercept() - tu->GetIntercept(); Double_t dv = pv->GetIntercept() - tv->GetIntercept(); Double_t mu = du / fUSpacing; Double_t mv = dv / fVSpacing; tu->SetSlope(mu); tv->SetSlope(mv); pu->SetSlope(mu); pv->SetSlope(mv); // Recalculate the UV track's detector coordinates using the global // U,V slopes. track->CalcDetCoords(); partner->CalcDetCoords(); #ifdef WITH_DEBUG if( fDebug>2 ) cout << "Global track parameters: " << mu << " " << mv << " " << track->GetTheta() << " " << track->GetPhi() << endl; #endif // If the 'tracks' array was given, add THaTracks to it // (or modify existing ones). if (tracks) { // Decide whether this is a new track or an old track // that is being updated THaVDCTrackID* thisID = new THaVDCTrackID(track,partner); THaTrack* theTrack = NULL; bool found = false; int t; for( t = 0; t < n_exist; t++ ) { theTrack = static_cast<THaTrack*>( tracks->At(t) ); // This test is true if an existing track has exactly the same clusters // as the current one (defined by track/partner) if( theTrack && theTrack->GetCreator() == this && *thisID == *theTrack->GetID() ) { found = true; break; } // FIXME: for debugging n_oops++; } UInt_t flag = theStage; if( nPairs > 1 ) flag |= kMultiTrack; if( found ) { #ifdef WITH_DEBUG if( fDebug>1 ) cout << "Track " << t << " modified.\n"; #endif delete thisID; ++n_mod; } else { #ifdef WITH_DEBUG if( fDebug>1 ) cout << "Track " << tracks->GetLast()+1 << " added.\n"; #endif theTrack = AddTrack(*tracks, 0.0, 0.0, 0.0, 0.0, thisID ); // theTrack->SetID( thisID ); // theTrack->SetCreator( this ); theTrack->AddCluster( track ); theTrack->AddCluster( partner ); if( theStage == kFine ) flag |= kReassigned; } theTrack->SetD(track->GetX(), track->GetY(), track->GetTheta(), track->GetPhi()); theTrack->SetFlag( flag ); Double_t chi2=0; Int_t nhits=0; track->CalcChisquare(chi2,nhits); partner->CalcChisquare(chi2,nhits); theTrack->SetChi2(chi2,nhits-4); // Nconstraints - Nparameters // calculate the TRANSPORT coordinates CalcFocalPlaneCoords(theTrack, kRotatingTransport); } } #ifdef WITH_DEBUG if( fDebug>1 ) cout << nTracks << " good tracks.\n"; #endif // Delete tracks that were not updated if( tracks && n_exist > n_mod ) { bool modified = false; for( int i = 0; i < tracks->GetLast()+1; i++ ) { THaTrack* theTrack = static_cast<THaTrack*>( tracks->At(i) ); // Track created by this class and not updated? if( (theTrack->GetCreator() == this) && ((theTrack->GetFlag() & kStageMask) != theStage ) ) { #ifdef WITH_DEBUG if( fDebug>1 ) cout << "Track " << i << " deleted.\n"; #endif tracks->RemoveAt(i); modified = true; } } // Get rid of empty slots - they may cause trouble in the Event class and // with global variables. // Note that the PIDinfo and vertices arrays are not reordered. // Therefore, PID and vertex information must always be retrieved from the // track objects, not from the PID and vertex TClonesArrays. // FIXME: Is this really what we want? if( modified ) tracks->Compress(); } return nTracks; }
//_____________________________________________________________________________ Int_t THaVDCPlane::FitTracks() { // Fit tracks to cluster positions and drift distances. Int_t nClust = GetNClusters(); for (int i = 0; i < nClust; i++) { THaVDCCluster* clust = static_cast<THaVDCCluster*>( (*fClusters)[i] ); if( !clust ) continue; // Convert drift times to distances. // The conversion algorithm is determined at wire initialization time, // i.e. currently in the ReadDatabase() function of this class. // The conversion is done with the current value of fSlope in the // clusters, i.e. either the rough guess from // THaVDCCluster::EstTrackParameters or the global slope from // THaVDC::ConstructTracks clust->ConvertTimeToDist(); // Fit drift distances to get intercept, slope. clust->FitTrack(); #ifdef CLUST_RAWDATA_HACK // HACK: write out cluster info for small-t0 clusters in u1 if( fName == "u" && !strcmp(GetParent()->GetName(),"uv1") && TMath::Abs(clust->GetT0()) < fT0Resolution/3. && clust->GetSize() <= 6 ) { ofstream outp; outp.open("u1_cluster_data.out",ios_base::app); outp << clust->GetSize() << endl; for( int i=clust->GetSize()-1; i>=0; i-- ) { outp << clust->GetHit(i)->GetPos() << " " << clust->GetHit(i)->GetDist() << endl; } outp << 1./clust->GetSlope() << " " << clust->GetIntercept() << endl; outp.close(); } #endif } return 0; }
//_____________________________________________________________________________ Int_t THaVDCPlane::FindClusters() { // Reconstruct clusters in a VDC plane // Assumes that the wires are numbered such that increasing wire numbers // correspond to decreasing physical position. // Ignores possibility of overlapping clusters TimeCut timecut(fVDC,this); // #ifndef NDEBUG // // bugcheck // bool only_fastest_hit = false; // if( fVDC ) // only_fastest_hit = fVDC->TestBit(THaVDC::kOnlyFastest); // #endif Int_t nHits = GetNHits(); // Number of hits in the plane Int_t nUsed = 0; // Number of wires used in clustering Int_t nLastUsed = -1; Int_t nextClust = 0; // Current cluster number assert( GetNClusters() == 0 ); vector <THaVDCHit *> clushits; Double_t deltat; Bool_t falling; fNpass = 0; Int_t nwires, span; UInt_t j; // Loop while we're making new clusters while( nLastUsed != nUsed ){ fNpass++; nLastUsed = nUsed; //Loop through all TDC hits for( Int_t i = 0; i < nHits; ) { clushits.clear(); falling = kTRUE; THaVDCHit* hit = GetHit(i); assert(hit); if( !timecut(hit) ) { ++i; continue; } if( hit->GetClsNum() != -1 ) { ++i; continue; } // Ensures we don't use this to try and start a new // cluster hit->SetClsNum(-3); // Consider this hit the beginning of a potential new cluster. // Find the end of the cluster. span = 0; nwires = 1; while( ++i < nHits ) { THaVDCHit* nextHit = GetHit(i); assert( nextHit ); // should never happen, else bug in Decode if( !timecut(nextHit) ) continue; if( nextHit->GetClsNum() != -1 // -1 is virgin && nextHit->GetClsNum() != -3 ) // -3 was considered to start //a clus but is not in cluster continue; Int_t ndif = nextHit->GetWireNum() - hit->GetWireNum(); // Do not consider adding hits from a wire that was already // added if( ndif == 0 ) { continue; } assert( ndif >= 0 ); // The cluster ends when we encounter a gap in wire numbers. // TODO: cluster should also end if // DONE (a) it is too big // DONE (b) drift times decrease again after initial fall/rise (V-shape) // DONE (c) Enforce reasonable changes in wire-to-wire V-shape // Times are sorted by earliest first when on same wire deltat = nextHit->GetTime() - hit->GetTime(); span += ndif; if( ndif > fNMaxGap+1 || span > fMaxClustSpan ){ break; } // Make sure the time structure is sensible // If this cluster is rising, wire with falling time // should not be associated in the cluster if( !falling ){ if( deltat < fMinTdiff*ndif || deltat > fMaxTdiff*ndif ) { continue; } } if( falling ){ // Step is too big, can't be associated if( deltat < -fMaxTdiff*ndif ){ continue; } if( deltat > 0.0 ){ // if rise is reasonable and we don't // have a monotonically increasing cluster if( deltat < fMaxTdiff*ndif && span > 1 ){ // now we're rising falling = kFALSE; } else { continue; } } } nwires++; if( clushits.size() == 0 ){ clushits.push_back(hit); hit->SetClsNum(-2); nUsed++; } clushits.push_back(nextHit); nextHit->SetClsNum(-2); nUsed++; hit = nextHit; } assert( i <= nHits ); // Make a new cluster if it is big enough // If not, the hits of this i-iteration are ignored // Also, make sure that we did indeed see the time // spectrum turn around at some point if( nwires >= fMinClustSize && !falling ) { THaVDCCluster* clust = new ( (*fClusters)[nextClust++] ) THaVDCCluster(this); for( j = 0; j < clushits.size(); j++ ){ clushits[j]->SetClsNum(nextClust-1); clust->AddHit( clushits[j] ); } assert( clust->GetSize() > 0 && clust->GetSize() >= nwires ); // This is a good cluster candidate. Estimate its position/slope clust->EstTrackParameters(); } //end new cluster } //end loop over hits } // end passes over hits assert( GetNClusters() == nextClust ); return nextClust; // return the number of clusters found }