-
Holly Szumila authoredHolly Szumila authored
THcDriftChamber.cxx 46.75 KiB
/** \class THcDriftChamber
\ingroup DetSupport
Subdetector class to hold a bunch of planes constituting a chamber
This class will be created by the THcDC class which will also create
the plane objects.
The THcDC class will then pass this class a list of the planes.
*/
#include "THcDriftChamber.h"
#include "THcDC.h"
#include "THcDCHit.h"
#include "THcGlobals.h"
#include "THcParmList.h"
#include "VarDef.h"
#include "VarType.h"
#include "THaTrack.h"
#include "TClonesArray.h"
#include "TMath.h"
#include "TVectorD.h"
#include "THcSpacePoint.h"
#include "THaApparatus.h"
#include "THaTrackProj.h"
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <iomanip>
using namespace std;
//_____________________________________________________________________________
THcDriftChamber::THcDriftChamber(
const char* name, const char* description,
const Int_t chambernum, THaDetectorBase* parent ) :
THaSubDetector(name,description,parent)
{
// Constructor
// fTrackProj = new TClonesArray( "THaTrackProj", 5 );
fTrackProj = NULL;
fNPlanes = 0; // No planes until we make them
fChamberNum = chambernum;
fSpacePoints = new TClonesArray("THcSpacePoint",10);
fHMSStyleChambers = 0; // Default
}
//_____________________________________________________________________________
THcDriftChamber::THcDriftChamber() :
THaSubDetector()
{
// Constructor
fTrackProj = NULL;
fSpacePoints = NULL;
fIsInit = 0;
}
//_____________________________________________________________________________
void THcDriftChamber::Setup(const char* name, const char* description)
{
}
//_____________________________________________________________________________
Int_t THcDriftChamber::Decode( const THaEvData& evdata )
{
return 0;
}
//_____________________________________________________________________________
THaAnalysisObject::EStatus THcDriftChamber::Init( const TDatime& date )
{
// static const char* const here = "Init()";
Setup(GetName(), GetTitle());
EStatus status;
// This triggers call of ReadDatabase and DefineVariables
if( (status = THaSubDetector::Init( date )) )
return fStatus=status;
return fStatus = kOK;
}
void THcDriftChamber::AddPlane(THcDriftChamberPlane *plane)
{
plane->SetPlaneIndex(fNPlanes);
fPlanes.push_back(plane);
// HMS Specific
// Hard code Y plane numbers. Eventually need to get from database
if (fHMSStyleChambers) {
if(fChamberNum == 1) {
YPlaneNum=2;
YPlanePNum=5;
if(plane->GetPlaneNum() == 2) YPlaneInd = fNPlanes;
if(plane->GetPlaneNum() == 5) YPlanePInd = fNPlanes;
} else {
YPlaneNum=8;
YPlanePNum=11;
if(plane->GetPlaneNum() == 8) YPlaneInd = fNPlanes;
if(plane->GetPlaneNum() == 11) YPlanePInd = fNPlanes;
}
} else {
// SOS Specific
// Hard code X plane numbers. Eventually need to get from database
if(fChamberNum == 1) {
XPlaneNum=3;
XPlanePNum=4;
if(plane->GetPlaneNum() == 3) XPlaneInd = fNPlanes;
if(plane->GetPlaneNum() == 4) XPlanePInd = fNPlanes;
} else {
XPlaneNum=9;
XPlanePNum=10;
if(plane->GetPlaneNum() == 9) XPlaneInd = fNPlanes;
if(plane->GetPlaneNum() == 10) XPlanePInd = fNPlanes;
}
}
fNPlanes++;
return;
}
//_____________________________________________________________________________
Int_t THcDriftChamber::ReadDatabase( const TDatime& date )
{
// cout << "THcDriftChamber::ReadDatabase()" << endl;
char prefix[2];
prefix[0]=tolower(GetApparatus()->GetName()[0]);
prefix[1]='\0';
DBRequest list[]={
{"_remove_sppt_if_one_y_plane",&fRemove_Sppt_If_One_YPlane, kInt,0,1},
{"dc_wire_velocity", &fWireVelocity, kDouble},
{"SmallAngleApprox", &fSmallAngleApprox, kInt},
{"stub_max_xpdiff", &fStubMaxXPDiff, kDouble,0,1},
{"debugflagpr", &fhdebugflagpr, kInt},
{"debugstubchisq", &fdebugstubchisq, kInt},
{Form("dc_%d_zpos",fChamberNum), &fZPos, kDouble},
{0}
};
fRemove_Sppt_If_One_YPlane = 0; // Default
fStubMaxXPDiff = 0.05; // The HMS default. Not used for SOS.
gHcParms->LoadParmValues((DBRequest*)&list,prefix);
// Get parameters parent knows about
THcDC* fParent;
fParent = (THcDC*) GetParent();
fMinHits = fParent->GetMinHits(fChamberNum);
fMaxHits = fParent->GetMaxHits(fChamberNum);
fMinCombos = fParent->GetMinCombos(fChamberNum);
fFixPropagationCorrection = fParent->GetFixPropagationCorrectionFlag();
fSpacePointCriterion = fParent->GetSpacePointCriterion(fChamberNum);
fMaxDist = TMath::Sqrt(fSpacePointCriterion/2.0); // For easy space points
if (fhdebugflagpr) cout << " cham = " << fChamberNum << " Set yplane num " << YPlaneNum << " "<< YPlanePNum << endl;
// Generate the HAA3INV matrix for all the acceptable combinations
// of hit planes. Try to make it as generic as possible
// pindex=0 -> Plane 1 missing, pindex5 -> plane 6 missing. Won't
// replicate the exact values used in the ENGINE, because the engine
// had one big list of matrices for both chambers, while here we will
// have a list just for one chamber. Also, call pindex, pmindex as
// we tend to use pindex as a plane index.
fCosBeta = new Double_t [fNPlanes];
fSinBeta = new Double_t [fNPlanes];
fTanBeta = new Double_t [fNPlanes];
fSigma = new Double_t [fNPlanes];
fPsi0 = new Double_t [fNPlanes];
fStubCoefs = new Double_t* [fNPlanes];
Int_t allplanes=0;
for(Int_t ip=0;ip<fNPlanes;ip++) {
fCosBeta[ip] = TMath::Cos(fPlanes[ip]->GetBeta());
fSinBeta[ip] = TMath::Sin(fPlanes[ip]->GetBeta());
fTanBeta[ip] = fSinBeta[ip]/fCosBeta[ip];
fSigma[ip] = fPlanes[ip]->GetSigma();
fPsi0[ip] = fPlanes[ip]->GetPsi0();
fStubCoefs[ip] = fPlanes[ip]->GetStubCoef();
allplanes |= 1<<ip;
}
// Unordered map introduced in C++-11
// Can use unordered_map if using C++-11
// May not want to use map a all for performance, but using it now
// for code clarity
for(Int_t ipm1=0;ipm1<fNPlanes+1;ipm1++) { // Loop over missing plane1
for(Int_t ipm2=ipm1;ipm2<fNPlanes+1;ipm2++) {
if(ipm1==ipm2 && ipm1<fNPlanes) continue;
TMatrixD* AA3 = new TMatrixD(3,3);
for(Int_t i=0;i<3;i++) {
for(Int_t j=i;j<3;j++) {
(*AA3)[i][j] = 0.0;
for(Int_t ip=0;ip<fNPlanes;ip++) {
if(ipm1 != ip && ipm2 != ip) {
(*AA3)[i][j] += fStubCoefs[ip][i]*fStubCoefs[ip][j];
}
}
(*AA3)[j][i] = (*AA3)[i][j];
}
}
Int_t bitpat = allplanes & ~(1<<ipm1) & ~(1<<ipm2);
// Should check that it is invertable
// if (fhdebugflagpr) cout << bitpat << " Determinant: " << AA3->Determinant() << endl;
AA3->Invert();
fAA3Inv[bitpat] = AA3;
}
}
fIsInit = true;
return kOK;
}
//_____________________________________________________________________________
Int_t THcDriftChamber::DefineVariables( EMode mode )
{
// Initialize global variables and lookup table for decoder
if( mode == kDefine && fIsSetup ) return kOK;
fIsSetup = ( mode == kDefine );
// Register variables in global list
RVarDef vars[] = {
{ "maxhits", "Maximum hits allowed", "fMaxHits" },
{ "spacepoints", "Space points of DC", "fNSpacePoints" },
{ "nhit", "Number of DC hits", "fNhits" },
{ "trawhit", "Number of True Raw hits", "fN_True_RawHits" },
{ 0 }
};
return DefineVarsFromList( vars, mode );
//return kOK;
}
void THcDriftChamber::ProcessHits( void)
{
// Make a list of hits for whole chamber
fNhits = 0;
fHits.clear();
fHits.reserve(10);
for(Int_t ip=0;ip<fNPlanes;ip++) {
TClonesArray* hitsarray = fPlanes[ip]->GetHits();
for(Int_t ihit=0;ihit<fPlanes[ip]->GetNHits();ihit++) {
fHits.push_back(static_cast<THcDCHit*>(hitsarray->At(ihit)));
fNhits++;
}
}
// if (fhdebugflagpr) cout << "ThcDriftChamber::ProcessHits() " << fNhits << " hits" << endl;
}
void THcDriftChamber::PrintDecode( void )
{
cout << " Num of nits = " << fNhits << endl;
cout << " Num " << " Plane " << " Wire " << " Wire-Center " << " RAW TDC " << " Drift time" << endl;
for(Int_t ihit=0;ihit<fNhits;ihit++) {
THcDCHit* thishit = fHits[ihit];
cout << ihit << " " <<thishit->GetPlaneNum() << " " << thishit->GetWireNum() << " " << thishit->GetPos() << " " << thishit->GetRawTime() << " " << thishit->GetTime() << endl;
}
}
Int_t THcDriftChamber::FindSpacePoints( void )
{
fSpacePoints->Clear();
Int_t plane_hitind=0;
Int_t planep_hitind=0;
fNSpacePoints=0;
fEasySpacePoint = 0;
if(fNhits >= fMinHits && fNhits < fMaxHits) {
for(Int_t ihit=0;ihit<fNhits;ihit++) {
THcDCHit* thishit = fHits[ihit];
Int_t ip=thishit->GetPlaneNum(); // This is the absolute plane mumber
if(ip==YPlaneNum && fHMSStyleChambers) plane_hitind = ihit;
if(ip==YPlanePNum && fHMSStyleChambers) planep_hitind = ihit;
if(ip==XPlaneNum && !fHMSStyleChambers) plane_hitind = ihit;
if(ip==XPlanePNum && !fHMSStyleChambers) planep_hitind = ihit;
}
Int_t PlaneInd=0,PlanePInd=0;
if (fHMSStyleChambers) {
PlaneInd=YPlaneInd;
PlanePInd=YPlanePInd;
} else {
PlaneInd=XPlaneInd;
PlanePInd=XPlanePInd;
}
if(fPlanes[PlaneInd]->GetNHits() == 1 && fPlanes[PlanePInd]->GetNHits() == 1
&& pow( (fHits[plane_hitind]->GetPos() - fHits[planep_hitind]->GetPos()),2)
< fSpacePointCriterion
&& fNhits <= 6) { // An easy case, probably one hit per plane
if(fHMSStyleChambers) fEasySpacePoint = FindEasySpacePoint_HMS(plane_hitind, planep_hitind);
if(!fHMSStyleChambers) fEasySpacePoint = FindEasySpacePoint_SOS(plane_hitind, planep_hitind);
}
if(!fEasySpacePoint) { // It's not easy
FindHardSpacePoints();
}
// We have our space points for this chamber
if(fNSpacePoints > 0) {
if(fHMSStyleChambers) {
if(fRemove_Sppt_If_One_YPlane == 1) {
// The routine is specific to HMS
//Int_t ndest=
DestroyPoorSpacePoints(); // Only for HMS?
// Loop over space points and remove those with less than 4 planes
// hit and missing hits in Y,Y' planes
}
Int_t nadded=SpacePointMultiWire(); // Only for HMS?
if (nadded) if (fhdebugflagpr) cout << nadded << " Space Points added with SpacePointMultiWire()" << endl;
}
ChooseSingleHit();
SelectSpacePoints();
// if(fNSpacePoints == 0) if (fhdebugflagpr) cout << "SelectSpacePoints() killed SP" << endl;
}
// if (fhdebugflagpr) cout << fNSpacePoints << " Space Points remain" << endl;
}
return(fNSpacePoints);
}
//_____________________________________________________________________________
// HMS Specific
Int_t THcDriftChamber::FindEasySpacePoint_HMS(Int_t yplane_hitind,Int_t yplanep_hitind)
{
// Simplified HMS find_space_point routing. It is given all y hits and
// checks to see if all x-like hits are close enough together to make
// a space point.
Int_t easy_space_point=0;
Double_t yt = (fHits[yplane_hitind]->GetPos() + fHits[yplanep_hitind]->GetPos())/2.0;
Double_t xt = 0.0;
Int_t num_xhits = 0;
Double_t x_pos[MAX_HITS_PER_POINT];
for(Int_t ihit=0;ihit<fNhits;ihit++) {
THcDCHit* thishit = fHits[ihit];
if(ihit!=yplane_hitind && ihit!=yplanep_hitind) { // x-like hit
// ysp and xsp are from h_generate_geometry
x_pos[ihit] = (thishit->GetPos()
-yt*thishit->GetWirePlane()->GetYsp())
/thishit->GetWirePlane()->GetXsp();
xt += x_pos[ihit];
num_xhits++;
} else {
x_pos[ihit] = 0.0;
}
}
xt = (num_xhits>0?xt/num_xhits:0.0);
easy_space_point = 1; // Assume we have an easy space point
// Rule it out if x points don't cluster well enough
for(Int_t ihit=0;ihit<fNhits;ihit++) {
if(ihit!=yplane_hitind && ihit!=yplanep_hitind) { // select x-like hit
if(TMath::Abs(xt-x_pos[ihit]) >= fMaxDist)
{ easy_space_point=0; break;}
}
}
if(easy_space_point) { // Register the space point
THcSpacePoint* sp = (THcSpacePoint*)fSpacePoints->ConstructedAt(fNSpacePoints++);
sp->Clear();
sp->SetXY(xt, yt);
sp->SetCombos(0);
for(Int_t ihit=0;ihit<fNhits;ihit++) {
sp->AddHit(fHits[ihit]);
}
}
return(easy_space_point);
}
// SOS Specific
Int_t THcDriftChamber::FindEasySpacePoint_SOS(Int_t xplane_hitind,Int_t xplanep_hitind)
{
// Simplified SOS find_space_point routing. It is given all x hits and
// checks to see if all y-like hits are close enough together to make
// a space point.
Int_t easy_space_point=0;
Double_t xt = (fHits[xplane_hitind]->GetPos() + fHits[xplanep_hitind]->GetPos())/2.0;
Double_t yt = 0.0;
Int_t num_yhits = 0;
Double_t y_pos[MAX_HITS_PER_POINT];
for(Int_t ihit=0;ihit<fNhits;ihit++) {
THcDCHit* thishit = fHits[ihit];
if(ihit!=xplane_hitind && ihit!=xplanep_hitind) { // y-like hit
// ysp and xsp are from h_generate_geometry
y_pos[ihit] = (thishit->GetPos()
-xt*thishit->GetWirePlane()->GetXsp())
/thishit->GetWirePlane()->GetYsp();
yt += y_pos[ihit];
num_yhits++;
} else {
y_pos[ihit] = 0.0;
}
}
yt = (num_yhits>0?yt/num_yhits:0.0);
easy_space_point = 1; // Assume we have an easy space point
// Rule it out if x points don't cluster well enough
for(Int_t ihit=0;ihit<fNhits;ihit++) {
if(ihit!=xplane_hitind && ihit!=xplanep_hitind) { // select y-like hit
if(TMath::Abs(yt-y_pos[ihit]) >= fMaxDist)
{ easy_space_point=0; break;}
}
}
if(easy_space_point) { // Register the space point
THcSpacePoint* sp = (THcSpacePoint*)fSpacePoints->ConstructedAt(fNSpacePoints++);
sp->Clear();
sp->SetXY(xt, yt);
sp->SetCombos(0);
for(Int_t ihit=0;ihit<fNhits;ihit++) {
sp->AddHit(fHits[ihit]);
}
}
return(easy_space_point);
}
//_____________________________________________________________________________
// Generic
Int_t THcDriftChamber::FindHardSpacePoints()
{
Int_t MAX_NUMBER_PAIRS=1000; // Where does this get set?
struct Pair {
THcDCHit* hit1;
THcDCHit* hit2;
Double_t x, y;
};
Pair pairs[MAX_NUMBER_PAIRS];
//
Int_t ntest_points=0;
for(Int_t ihit1=0;ihit1<fNhits-1;ihit1++) {
THcDCHit* hit1=fHits[ihit1];
THcDriftChamberPlane* plane1 = hit1->GetWirePlane();
for(Int_t ihit2=ihit1+1;ihit2<fNhits;ihit2++) {
if(ntest_points < MAX_NUMBER_PAIRS) {
THcDCHit* hit2=fHits[ihit2];
THcDriftChamberPlane* plane2 = hit2->GetWirePlane();
Double_t determinate = plane1->GetXsp()*plane2->GetYsp()
-plane1->GetYsp()*plane2->GetXsp();
if(TMath::Abs(determinate) > 0.3) { // 0.3 is sin(alpha1-alpha2)=sin(17.5)
pairs[ntest_points].hit1 = hit1;
pairs[ntest_points].hit2 = hit2;
pairs[ntest_points].x = (hit1->GetPos()*plane2->GetYsp()
- hit2->GetPos()*plane1->GetYsp())
/determinate;
pairs[ntest_points].y = (hit2->GetPos()*plane1->GetXsp()
- hit1->GetPos()*plane2->GetXsp())
/determinate;
ntest_points++;
}
}
}
}
Int_t ncombos=0;
struct Combo {
Pair* pair1;
Pair* pair2;
};
Combo combos[10*MAX_NUMBER_PAIRS];
for(Int_t ipair1=0;ipair1<ntest_points-1;ipair1++) {
for(Int_t ipair2=ipair1+1;ipair2<ntest_points;ipair2++) {
if(ncombos < 10*MAX_NUMBER_PAIRS) {
Double_t dist2 = pow(pairs[ipair1].x - pairs[ipair2].x,2)
+ pow(pairs[ipair1].y - pairs[ipair2].y,2);
if(dist2 <= fSpacePointCriterion) {
combos[ncombos].pair1 = &pairs[ipair1];
combos[ncombos].pair2 = &pairs[ipair2];
ncombos++;
}
}
}
}
// Loop over all valid combinations and build space points
//if (fhdebugflagpr) cout << "looking for hard Space Point combos = " << ncombos << endl;
for(Int_t icombo=0;icombo<ncombos;icombo++) {
THcDCHit* hits[4];
hits[0]=combos[icombo].pair1->hit1;
hits[1]=combos[icombo].pair1->hit2;
hits[2]=combos[icombo].pair2->hit1;
hits[3]=combos[icombo].pair2->hit2;
// Get Average Space point xt, yt
Double_t xt = (combos[icombo].pair1->x + combos[icombo].pair2->x)/2.0;
Double_t yt = (combos[icombo].pair1->y + combos[icombo].pair2->y)/2.0;
// Loop over space points
if(fNSpacePoints > 0) {
Int_t add_flag=1;
for(Int_t ispace=0;ispace<fNSpacePoints;ispace++) {
THcSpacePoint* sp = (THcSpacePoint*)(*fSpacePoints)[ispace];
if(sp->GetNHits() > 0) {
Double_t sqdist_test = pow(xt - sp->GetX(),2) + pow(yt - sp->GetY(),2);
// I (who is I) want to be careful if sqdist_test is bvetween 1 and
// 3 fSpacePointCriterion. Let me ignore not add a new point the
if(sqdist_test < 3*fSpacePointCriterion) {
add_flag = 0; // do not add a new space point
}
if(sqdist_test < fSpacePointCriterion) {
// This is a real match
// Add the new hits to the existing space point
Int_t iflag[4];
iflag[0]=0;iflag[1]=0;iflag[2]=0;iflag[3]=0;
// Find out which of the four hits in the combo are already
// in the space point under consideration so that we don't
// add duplicate hits to the space point
for(Int_t isp_hit=0;isp_hit<sp->GetNHits();isp_hit++) {
for(Int_t icm_hit=0;icm_hit<4;icm_hit++) { // Loop over combo hits
if(sp->GetHit(isp_hit)==hits[icm_hit]) {
iflag[icm_hit] = 1;
}
}
}
// Remove duplicated pionts in the combo so we don't add
// duplicate hits to the space point
for(Int_t icm1=0;icm1<3;icm1++) {
for(Int_t icm2=icm1+1;icm2<4;icm2++) {
if(hits[icm1]==hits[icm2]) {
iflag[icm2] = 1;
}
}
}
// Add the unique combo hits to the space point
for(Int_t icm=0;icm<4;icm++) {
if(iflag[icm]==0) {
sp->AddHit(hits[icm]);
}
}
sp->IncCombos();
// cout << " number of combos = " << sp->GetCombos() << endl;
// Terminate loop since this combo can only belong to one space point
break;
}
}
}// End of loop over existing space points
// Create a new space point if more than 2*space_point_criteria
if(fNSpacePoints < MAX_SPACE_POINTS) {
if(add_flag) {
//if (fhdebugflagpr) cout << " add glag = " << add_flag << " space pts = " << fNSpacePoints << endl ;
THcSpacePoint* sp = (THcSpacePoint*)fSpacePoints->ConstructedAt(fNSpacePoints++);
sp->Clear();
sp->SetXY(xt, yt);
sp->SetCombos(1);
sp->AddHit(hits[0]);
sp->AddHit(hits[1]);
if(hits[0] != hits[2] && hits[1] != hits[2]) {
sp->AddHit(hits[2]);
}
if(hits[0] != hits[3] && hits[1] != hits[3]) {
sp->AddHit(hits[3]);
}
}
}
} else {// Create first space point
// This duplicates code above. Need to see if we can restructure
// to avoid
THcSpacePoint* sp = (THcSpacePoint*)fSpacePoints->ConstructedAt(fNSpacePoints++);
sp->Clear();
sp->SetXY(xt, yt);
sp->SetCombos(1);
sp->AddHit(hits[0]);
sp->AddHit(hits[1]);
if(hits[0] != hits[2] && hits[1] != hits[2]) {
sp->AddHit(hits[2]);
}
if(hits[0] != hits[3] && hits[1] != hits[3]) {
sp->AddHit(hits[3]);
}
//if (fhdebugflagpr) cout << "1st hard Space Point " << xt << " " << yt << " Space point # =" << fNSpacePoints << " combos = " << sp->GetCombos() << endl;
}//End check on 0 space points
}//End loop over combos
//if (fhdebugflagpr) cout << " finished findspacept # of sp pts = " << fNSpacePoints << endl;
return(fNSpacePoints);
}
//_____________________________________________________________________________
// HMS Specific?
Int_t THcDriftChamber::DestroyPoorSpacePoints()
{
Int_t nhitsperplane[fNPlanes];
Int_t spacepointsgood[fNSpacePoints];
Int_t ngood=0;
for(Int_t i=0;i<fNSpacePoints;i++) {
spacepointsgood[i] = 0;
}
for(Int_t isp=0;isp<fNSpacePoints;isp++) {
Int_t nplanes_hit = 0;
for(Int_t ip=0;ip<fNPlanes;ip++) {
nhitsperplane[ip] = 0;
}
// Count # hits in each plane for this space point
THcSpacePoint* sp = (THcSpacePoint*)(*fSpacePoints)[isp];
for(Int_t ihit=0;ihit<sp->GetNHits();ihit++) {
THcDCHit* hit=sp->GetHit(ihit);
// hit_order(hit) = ihit;
Int_t ip = hit->GetPlaneIndex();
nhitsperplane[ip]++;
}
// Count # planes that have hits
for(Int_t ip=0;ip<fNPlanes;ip++) {
if(nhitsperplane[ip] > 0) {
nplanes_hit++;
}
}
if(nplanes_hit >= fMinHits && nhitsperplane[YPlaneInd]>0
&& nhitsperplane[YPlanePInd] > 0) {
spacepointsgood[ngood++] = isp; // Build list of good points
} else {
// if (fhdebugflagpr) cout << "Missing Y-hit!!";
}
}
// Remove the bad space points
Int_t nremoved=fNSpacePoints-ngood;
fNSpacePoints = ngood;
for(Int_t isp=0;isp<fNSpacePoints;isp++) { // New index num ber
Int_t osp=spacepointsgood[isp]; // Original index number
if(osp > isp) {
// Does this work, or do we have to copy each member?
// If it doesn't we should overload the = operator
//(*fSpacePoints)[isp] = (*fSpacePoints)[osp];
THcSpacePoint* spi = (THcSpacePoint*)(*fSpacePoints)[isp];
THcSpacePoint* spo = (THcSpacePoint*)(*fSpacePoints)[osp];
spi->Clear();
Double_t xt,yt;
xt=spo->GetX();
yt=spo->GetY();
spi->SetXY(xt, yt);
for(Int_t ihit=0;ihit<spo->GetNHits();ihit++) {
THcDCHit* hit = spo->GetHit(ihit);
spi->AddHit(hit);
}
}
}
return nremoved;
}
//_____________________________________________________________________________
// HMS Specific?
/*
Purpose and Methods : This routine loops over space points and
looks at all hits in the space
point. If more than 1 hit is in the same
plane then the space point is cloned with
all combinations of 1 wire per plane. The
requirements for cloning are: 1) at least
4 planes fire, and 2) no more than 6 planes
have multiple hits.
*/
Int_t THcDriftChamber::SpacePointMultiWire()
{
Int_t nhitsperplane[fNPlanes];
THcDCHit* hits_plane[fNPlanes][MAX_HITS_PER_POINT];
Int_t nsp_check;
//Int_t nplanes_single;
Int_t nsp_tot=fNSpacePoints;
Int_t nsp_totl=fNSpacePoints;
//if (fhdebugflagpr) cout << "Start Multiwire # of sp pts = " << nsp_totl << endl;
for(Int_t isp=0;isp<nsp_totl;isp++) {
Int_t nplanes_hit = 0; // Number of planes with hits
Int_t nplanes_mult = 0; // Number of planes with multiple hits
Int_t nsp_new = 1;
Int_t newsp_num=0;
//if (fhdebugflagpr) cout << "Looping thru space pts at # = " << isp << " total = " << fNSpacePoints << endl;
for(Int_t ip=0;ip<fNPlanes;ip++) {
nhitsperplane[ip] = 0;
for(Int_t ih=0;ih<MAX_HITS_PER_POINT;ih++) {
hits_plane[ip][ih] = 0;
}
}
// Sort Space Points hits by plane
THcSpacePoint* sp = (THcSpacePoint*)(*fSpacePoints)[isp];
for(Int_t ihit=0;ihit<sp->GetNHits();ihit++) { // All hits in SP
THcDCHit* hit=sp->GetHit(ihit);
// hit_order Make a hash
// hash(hit) = ihit;
Int_t ip = hit->GetPlaneIndex();
hits_plane[ip][nhitsperplane[ip]++] = hit;
//if (fhdebugflagpr) cout << " hit = " << ihit+1 << " plane index = " << ip << " nhitsperplane = " << nhitsperplane[ip] << endl;
}
for(Int_t ip=0;ip<fNPlanes;ip++) {
if(nhitsperplane[ip] > 0) {
nplanes_hit++;
nsp_new *= nhitsperplane[ip];
if(nhitsperplane[ip] > 1) nplanes_mult++;
//if (fhdebugflagpr) cout << "Found plane with multi hits plane =" << ip+1 << " nplane_hit = "<< nplanes_hit << " nsp_new = " <<nsp_new << " nplane_mult = "<< nplanes_mult << endl;
}
}
--nsp_new;
nsp_check=nsp_tot + nsp_new;
//nplanes_single = nplanes_hit - nplanes_mult;
//if (fhdebugflagpr) cout << " # of new space points = " << nsp_new << " total now = " << nsp_tot<< endl;
// Check if cloning conditions are met
Int_t ntot = 0;
if(nplanes_hit >= 4 && nplanes_mult < 4 && nplanes_mult >0
&& nsp_check < 20) {
//if (fhdebugflagpr) cout << " Cloning space point " << endl;
// Order planes by decreasing # of hits
Int_t maxplane[fNPlanes];
for(Int_t ip=0;ip<fNPlanes;ip++) {
maxplane[ip] = ip;
}
// Sort by decreasing # of hits
for(Int_t ip1=0;ip1<fNPlanes-1;ip1++) {
for(Int_t ip2=ip1+1;ip2<fNPlanes;ip2++) {
if(nhitsperplane[maxplane[ip2]] > nhitsperplane[maxplane[ip1]]) {
Int_t temp = maxplane[ip1];
maxplane[ip1] = maxplane[ip2];
maxplane[ip2] = temp;
}
}
}
// First fill clones with 1 hit each from the 3 planes with the most hits
for(Int_t n1=0;n1<nhitsperplane[maxplane[0]];n1++) {
for(Int_t n2=0;n2<nhitsperplane[maxplane[1]];n2++) {
for(Int_t n3=0;n3<nhitsperplane[maxplane[2]];n3++) {
ntot++;
newsp_num = fNSpacePoints; //
//if (fhdebugflagpr) cout << " new space pt num = " << newsp_num << " " << fNSpacePoints << endl;
//THcSpacePoint* newsp;
if(n1==0 && n2==0 && n3==0) {
newsp_num = isp; // Copy over the original SP
THcSpacePoint* newsp = (THcSpacePoint*)fSpacePoints->ConstructedAt(newsp_num);//= (THcSpacePoint*)(*fSpacePoints)[newsp_num];
//if (fhdebugflagpr) cout << " Copy over original SP " << endl;
// newsp = sp;
Int_t combos_save=sp->GetCombos();
newsp->Clear(); // Clear doesn't clear X, Y
// if (fhdebugflagpr) cout << " original sp #hits combos X y " << sp->GetCombos() << sp->GetNHits() << sp->GetX() << " " << sp->GetY() << endl;
newsp->SetXY(sp->GetX(), sp->GetY());
newsp->SetCombos(combos_save);
newsp->AddHit(hits_plane[maxplane[0]][n1]);
newsp->AddHit(hits_plane[maxplane[1]][n2]);
newsp->AddHit(hits_plane[maxplane[2]][n3]);
newsp->AddHit(hits_plane[maxplane[3]][0]);
if(nhitsperplane[maxplane[4]] == 1) {
newsp->AddHit(hits_plane[maxplane[4]][0]);
if(nhitsperplane[maxplane[5]] == 1)
newsp->AddHit(hits_plane[maxplane[5]][0]);
}
} else {
// if (fhdebugflagpr) cout << " setting other sp " << "# space pts now = " << fNSpacePoints << endl;
THcSpacePoint* newsp = (THcSpacePoint*)fSpacePoints->ConstructedAt(newsp_num);
fNSpacePoints++;
Int_t combos_save=sp->GetCombos();
newsp->Clear();
newsp->SetXY(sp->GetX(), sp->GetY());
newsp->SetCombos(combos_save);
newsp->AddHit(hits_plane[maxplane[0]][n1]);
newsp->AddHit(hits_plane[maxplane[1]][n2]);
newsp->AddHit(hits_plane[maxplane[2]][n3]);
newsp->AddHit(hits_plane[maxplane[3]][0]);
if(nhitsperplane[maxplane[4]] == 1) {
newsp->AddHit(hits_plane[maxplane[4]][0]);
if(nhitsperplane[maxplane[5]] == 1)
newsp->AddHit(hits_plane[maxplane[5]][0]);
}
}
}
}
}
// In the ENGINE, we loop over the clones and order the hits in the
// same order as the parent SP. It is not done here because it is a little
// tricky. Is it necessary?
nsp_tot += (ntot-1);
} else {
ntot=1; // space point not to be cloned
}
}
assert (nsp_tot > 0); // program terminates if nsp_tot <=0
Int_t nadded=0;
if(nsp_tot <= 20) {
nadded = nsp_tot - fNSpacePoints;
// fNSpacePoints = nsp_tot;
}
//if (fhdebugflagpr) cout << " Added space pts " << nadded << " total space pts = " << fNSpacePoints << endl;
// In Fortran, fill in zeros.
return(nadded);
}
//_____________________________________________________________________________
// Generic
void THcDriftChamber::ChooseSingleHit()
{
// Look at all hits in a space point. If two hits are in the same plane,
// reject the one with the longer drift time.
for(Int_t isp=0;isp<fNSpacePoints;isp++) {
THcSpacePoint* sp = (THcSpacePoint*)(*fSpacePoints)[isp];
Int_t startnum = sp->GetNHits();
Int_t goodhit[startnum];
for(Int_t ihit=0;ihit<startnum;ihit++) {
goodhit[ihit] = 1;
}
// For each plane, mark all hits longer than the shortest drift time
for(Int_t ihit1=0;ihit1<startnum-1;ihit1++) {
THcDCHit* hit1 = sp->GetHit(ihit1);
Int_t plane1=hit1->GetPlaneIndex();
Double_t tdrift1 = hit1->GetTime();
for(Int_t ihit2=ihit1+1;ihit2<startnum;ihit2++) {
THcDCHit* hit2 = sp->GetHit(ihit2);
Int_t plane2=hit2->GetPlaneIndex();
Double_t tdrift2 = hit2->GetTime();
if(plane1 == plane2) {
if(tdrift1 > tdrift2) {
goodhit[ihit1] = 0;
} else {
goodhit[ihit2] = 0;
}
// if (fhdebugflagpr) cout << " Rejecting hit " << ihit1 << " " << tdrift1 << " " << ihit2 << " " << tdrift2 << endl;
}
}
}
// Gather the remaining hits
Int_t finalnum = 0;
for(Int_t ihit=0;ihit<startnum;ihit++) {
//THcDCHit* hit = sp->GetHit(ihit);
// if (fhdebugflagpr) cout << " good hit = "<< ihit << " " << goodhit[ihit] << " time = " << hit->GetTime() << endl;
if(goodhit[ihit] > 0) { // Keep this hit
if (ihit > finalnum) { // Move hit
sp->ReplaceHit(finalnum++, sp->GetHit(ihit));
} else {
finalnum++ ;
}
}
}
sp->SetNHits(finalnum);
// if (fhdebugflagpr) cout << " choose single hit start # of hits = " << startnum << " final # = " <<finalnum << endl;
}
}
//_____________________________________________________________________________
// Generic
void THcDriftChamber::SelectSpacePoints()
// This routine goes through the list of space_points and space_point_hits
// found by find_space_points and only accepts those with
// number of hits > min_hits
// number of combinations > min_combos
{
Int_t sp_count=0;
for(Int_t isp=0;isp<fNSpacePoints;isp++) {
// Include fEasySpacePoint because ncombos not filled in
THcSpacePoint* sp = (THcSpacePoint*)(*fSpacePoints)[isp];
// if (fhdebugflagpr) cout << " looping sp points " << sp->GetCombos() << " " << fMinCombos << " " << fEasySpacePoint << " " << sp->GetNHits() << " " << fMinHits << endl;
if(sp->GetCombos() >= fMinCombos || fEasySpacePoint) {
if(sp->GetNHits() >= fMinHits) {
if(isp > sp_count) {
// (*fSpacePoints)[sp_count] = (*fSpacePoints)[isp];
THcSpacePoint* sp1 = (THcSpacePoint*)(*fSpacePoints)[sp_count];
//if (fhdebugflagpr) cout << " select space pt = " << isp << endl;
sp1->Clear();
Double_t xt,yt;
xt=sp->GetX();
yt=sp->GetY();
sp1->SetXY(xt, yt);
sp1->SetCombos(sp->GetCombos());
for(Int_t ihit=0;ihit<sp->GetNHits();ihit++) {
THcDCHit* hit = sp->GetHit(ihit);
sp1->AddHit(hit);
}
}
sp_count++;
}
}
}
// if(sp_count < fNSpacePoints) if (fhdebugflagpr) cout << "Reduced from " << fNSpacePoints << " to " << sp_count << " space points" << endl;
fNSpacePoints = sp_count;
//for(Int_t isp=0;isp<fNSpacePoints;isp++) {
// THcSpacePoint* sp = (THcSpacePoint*)(*fSpacePoints)[isp];
//if (fhdebugflagpr) cout << " sp pt = " << isp+1 << " # of hits = " << sp->GetNHits() << endl;
//for(Int_t ihit=0;ihit<sp->GetNHits();ihit++) {
//THcDCHit* hit = sp->GetHit(ihit);
//THcDriftChamberPlane* plane=hit->GetWirePlane();
// if (fhdebugflagpr) cout << ihit+1 << "selecting " << plane->GetPlaneNum() << " " << plane->GetChamberNum() << " " << hit->GetTime() << " " << hit->GetDist() << " " << plane->GetCentralTime() << " " << plane->GetDriftTimeSign() << endl;
// }
// }
}
void THcDriftChamber::CorrectHitTimes()
{
//cout<<"next event"<<endl;
// Use the rough hit positions in the chambers to correct the drift time
// for hits in the space points.
// Assume all wires for a plane are read out on the same side (l/r or t/b).
// If the wire is closer to horizontal, read out left/right. If nearer
// vertical, assume top/bottom. (Note, this is not always true for the
// SOS u and v planes. They have 1 card each on the side, but the overall
// time offset per card will cancel much of the error caused by this. The
// alternative is to check by card, rather than by plane and this is harder.
//if (fhdebugflagpr) cout << "In correcthittimes fNSpacePoints = " << fNSpacePoints << endl;
for(Int_t isp=0;isp<fNSpacePoints;isp++) {
THcSpacePoint* sp = (THcSpacePoint*)(*fSpacePoints)[isp];
Double_t x = sp->GetX();
Double_t y = sp->GetY();
for(Int_t ihit=0;ihit<sp->GetNHits();ihit++) {
THcDCHit* hit = sp->GetHit(ihit);
THcDriftChamberPlane* plane=hit->GetWirePlane();
// How do we know this correction only gets applied once? Is
// it determined that a given hit can only belong to one space point?
Double_t time_corr = plane->GetReadoutX() ?
y*plane->GetReadoutCorr()/fWireVelocity :
x*plane->GetReadoutCorr()/fWireVelocity;
// This applies the wire velocity correction for new SHMS chambers --hszumila, SEP17
THcDC* fParent;
fParent = (THcDC*) GetParent();
Int_t version = fParent->GetVersion();
if (version!= 0){
Int_t pln = hit->GetPlaneNum();
Int_t readoutSide = hit->GetReadoutSide();
Double_t posn = hit->GetPos();
//The following values are determined from param file as permutations on planes 5 and 10
Int_t readhoriz = plane->GetReadoutLR();
Int_t readvert = plane->GetReadoutTB();
//+x is up and +y is beam right!
double alpha = fParent->GetAlphaAngle(pln);
double xc = posn*TMath::Sin(alpha);
double yc = posn*TMath::Cos(alpha);
Double_t wireDistance = plane->GetReadoutX() ?
(abs(y-yc))*abs(plane->GetReadoutCorr()) :
(abs(x-xc))*abs(plane->GetReadoutCorr());
//Readout side is based off wiring diagrams
switch (readoutSide){
case 1: //readout from top of chamber
if (x>xc){wireDistance = -readvert*wireDistance;}
else{wireDistance = readvert*wireDistance;}
break;
case 2://readout from right of chamber
if (y>yc){wireDistance = -readhoriz*wireDistance;}
else{wireDistance = readhoriz*wireDistance;}
break;
case 3: //readout from bottom of chamber
if (xc>x){wireDistance= -readvert*wireDistance;}
else{wireDistance = readvert*wireDistance;}
break;
case 4: //readout from left of chamber
if(yc>y){wireDistance = -readhoriz*wireDistance;}
else{wireDistance = readhoriz*wireDistance;}
break;
default:
wireDistance = 0.0;
}
Double_t timeCorrection = wireDistance/fWireVelocity;
if(fFixPropagationCorrection==0) { // ENGINE behavior
Double_t time=hit->GetTime();
hit->SetTime(time - timeCorrection);
hit->ConvertTimeToDist();
}
else{
Double_t time=hit->GetTime();
Double_t dist=hit->GetDist();
hit->SetTime(time - timeCorrection);
//double usingOldTime = time-time_corr;
//hit->SetTime(time- time_corr);
hit->ConvertTimeToDist();
sp->SetHitDist(ihit, hit->GetDist());
hit->SetTime(time); // Restore time
hit->SetDist(dist); // Restore distance
}
}
/////////////////////////////////////////////////////////////
// if (fhdebugflagpr) cout << "Correcting hit " << hit << " " << plane->GetPlaneNum() << " " << isp << "/" << ihit << " " << x << "," << y << endl;
// Fortran ENGINE does not do this check, so hits can get "corrected"
// multiple times if they belong to multiple space points.
// To reproduce the precise ENGINE behavior, remove this if condition.
else{
if(fFixPropagationCorrection==0) { // ENGINE behavior
hit->SetTime(hit->GetTime() - plane->GetCentralTime()
+ plane->GetDriftTimeSign()*time_corr);
hit->ConvertTimeToDist();
// hit->SetCorrectedStatus(1);
} else {
// New behavior: Save corrected distance with the hit in the space point
// so that the same hit can have a different correction depending on
// which space point it is in.
//
// This is a hack now because the converttimetodist method is connected to the hit
// so I compute the corrected time and distance, and then restore the original
// time and distance. Can probably add a method to hit that does a conversion on a time
// but does not modify the hit data.
Double_t time=hit->GetTime();
Double_t dist=hit->GetDist();
hit->SetTime(time - plane->GetCentralTime()
+ plane->GetDriftTimeSign()*time_corr);
hit->ConvertTimeToDist();
sp->SetHitDist(ihit, hit->GetDist());
hit->SetTime(time); // Restore time
hit->SetDist(dist); // Restore distance
}
}
}
}
}
UInt_t THcDriftChamber::Count1Bits(UInt_t x)
// From http://graphics.stanford.edu/~seander/bithacks.html
{
x = x - ((x >> 1) & 0x55555555);
x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
return (((x + (x >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24;
}
//_____________________________________________________________________________
void THcDriftChamber::LeftRight()
{
// For each space point,
// Fit stubs to all possible left-right combinations of drift distances
// and choose the set with the minimum chi**2.
for(Int_t isp=0; isp<fNSpacePoints; isp++) {
// Build a bit pattern of which planes are hit
THcSpacePoint* sp = (THcSpacePoint*)(*fSpacePoints)[isp];
Int_t nhits = sp->GetNHits();
UInt_t bitpat = 0; // Bit pattern of which planes are hit
Double_t minchi2 = 1.0e10;
Double_t tmp_minchi2;
Double_t minxp = 0.25;
Int_t hasy1 = -1;
Int_t hasy2 = -1;
Int_t plusminusknown[nhits];
Int_t plusminusbest[nhits];
Int_t plusminus[nhits]; // ENGINE makes this array float. Why?
Int_t tmp_plusminus[nhits];
Int_t plane_list[nhits];
Double_t stub[4];
Double_t tmp_stub[4];
Int_t nplusminus;
if(nhits < 0) {
if (fhdebugflagpr) cout << "THcDriftChamber::LeftRight() nhits < 0" << endl;
} else if (nhits==0) {
if (fhdebugflagpr) cout << "THcDriftChamber::LeftRight() nhits = 0" << endl;
}
for(Int_t ihit=0;ihit < nhits;ihit++) {
THcDCHit* hit = sp->GetHit(ihit);
Int_t pindex = hit->GetPlaneIndex();
plane_list[ihit] = pindex;
bitpat |= 1<<pindex;
plusminusknown[ihit] = 0;
if(pindex == YPlaneInd) hasy1 = ihit;
if(pindex == YPlanePInd) hasy2 = ihit;
}
nplusminus = 1<<nhits;
if(fHMSStyleChambers) {
Int_t smallAngOK = (hasy1>=0) && (hasy2>=0);
if(fSmallAngleApprox !=0 && smallAngOK) { // to small Angle L/R for Y,Y' planes
if(sp->GetHit(hasy2)->GetPos() <=
sp->GetHit(hasy1)->GetPos()) {
plusminusknown[hasy1] = -1;
plusminusknown[hasy2] = 1;
} else {
plusminusknown[hasy1] = 1;
plusminusknown[hasy2] = -1;
}
nplusminus = 1<<(nhits-2);
// if (fhdebugflagpr) cout << " Small angle approx = " << smallAngOK << " " << plusminusknown[hasy1] << endl;
//if (fhdebugflagpr) cout << "pm = " << plusminusknown[hasy2] << " " << hasy1 << " " << hasy2 << endl;
//if (fhdebugflagpr) cout << " Plane index " << YPlaneInd << " " << YPlanePInd << endl;
}
} else { // SOS Style
if(fSmallAngleApprox !=0) {
// Brookhaven style chamber L/R code
Int_t npaired=0;
for(Int_t ihit1=0;ihit1 < nhits;ihit1++) {
THcDCHit* hit1 = sp->GetHit(ihit1);
Int_t pindex1=hit1->GetPlaneIndex();
if((pindex1%2)==0) { // Odd plane (or even index)
for(Int_t ihit2=0;ihit2<nhits;ihit2++) {
THcDCHit* hit2 = sp->GetHit(ihit2);
if(hit2->GetPlaneIndex()-pindex1 == 1) { // Adjacent plane
if(hit2->GetPos() <= hit1->GetPos()) {
plusminusknown[ihit1] = -1;
plusminusknown[ihit2] = 1;
} else {
plusminusknown[ihit1] = 1;
plusminusknown[ihit2] = -1;
}
npaired+=2;
}
}
}
}
nplusminus = 1 << (nhits-npaired);
}//end if fSmallAngleApprox!=0
}//end else SOS style
if(nhits < 2) {
if (fdebugstubchisq) cout << "THcDriftChamber::LeftRight: numhits-2 < 0" << endl;
} else if (nhits == 2) {
if (fdebugstubchisq) cout << "THcDriftChamber::LeftRight: numhits-2 = 0" << endl;
}
Int_t nplaneshit = Count1Bits(bitpat);
//if (fhdebugflagpr) cout << " num of pm = " << nplusminus << " num of hits =" << nhits << endl;
// Use bit value of integer word to set + or -
// Loop over all combinations of left right.
for(Int_t pmloop=0;pmloop<nplusminus;pmloop++) {
Int_t iswhit = 1;
for(Int_t ihit=0;ihit<nhits;ihit++) {
if(plusminusknown[ihit]!=0) {
plusminus[ihit] = plusminusknown[ihit];
} else {
// Max hits per point has to be less than 32.
if(pmloop & iswhit) {
plusminus[ihit] = 1;
} else {
plusminus[ihit] = -1;
}
iswhit <<= 1;
}
}
if (nplaneshit >= fNPlanes-1) {
Double_t chi2 = FindStub(nhits, sp,
plane_list, bitpat, plusminus, stub);
if (fdebugstubchisq) cout << " pmloop = " << pmloop << " chi2 = " << chi2 << endl;
if(chi2 < minchi2) {
if(fHMSStyleChambers) { // Perhaps a different flag here
// Take best chi2 IF x' of the stub agrees with x' as expected from x.
// Sometimes an incorrect x' gives a good chi2 for the stub, even though it is
// not the correct left/right combination for the real track.
// Rotate x'(=stub(3)) to hut coordinates and compare to x' expected from x.
// THIS ASSUMES STANDARD HMS TUNE!!!!, for which x' is approx. x/875.
if(stub[2]*fTanBeta[plane_list[0]]==-1.0) {
if (fhdebugflagpr) cout << "THcDriftChamber::LeftRight() Error 3" << endl;
}
Double_t xp_fit=stub[2]-fTanBeta[plane_list[0]]
/(1+stub[2]*fTanBeta[plane_list[0]]);
// Tune depdendent. Definitely HMS specific
Double_t xp_expect = sp->GetX()/875.0;
if(TMath::Abs(xp_fit-xp_expect)<fStubMaxXPDiff) {
minchi2 = chi2;
for(Int_t ihit=0;ihit<nhits;ihit++) {
plusminusbest[ihit] = plusminus[ihit];
}
sp->SetStub(stub);
} else { // Record best stub failing angle cut
tmp_minchi2 = chi2;
for(Int_t ihit=0;ihit<nhits;ihit++) {
tmp_plusminus[ihit] = plusminus[ihit];
}
for(Int_t i=0;i<4;i++) {
tmp_stub[i] = stub[i];
}
}
} else { // Not HMS specific
minchi2 = chi2;
for(Int_t ihit=0;ihit<nhits;ihit++) {
plusminusbest[ihit] = plusminus[ihit];
}
sp->SetStub(stub);
}
}
///////////////
} else if (nplaneshit >= fNPlanes-2 && fHMSStyleChambers) { // Two planes missing
Double_t chi2 = FindStub(nhits, sp,
plane_list, bitpat, plusminus, stub);
//if(debugging)
//if (fhdebugflagpr) cout << "pmloop=" << pmloop << " Chi2=" << chi2 << endl;
// Isn't this a bad idea, doing == with reals
if(stub[2]*fTanBeta[plane_list[0]] == -1.0) {
if (fhdebugflagpr) cout << "THcDriftChamber::LeftRight() Error 3" << endl;
}
Double_t xp_fit=stub[2]-fTanBeta[plane_list[0]]
/(1+stub[2]*fTanBeta[plane_list[0]]);
if(TMath::Abs(xp_fit) <= minxp) {
minxp = TMath::Abs(xp_fit);
minchi2 = chi2;
for(Int_t ihit=0;ihit<nhits;ihit++) {
plusminusbest[ihit] = plusminus[ihit];
}
sp->SetStub(stub);
}
}//////////
else {
if (fhdebugflagpr) cout << "Insufficient planes hit in THcDriftChamber::LeftRight()" << bitpat <<endl;
}
} // End loop of pm combinations
if(minchi2 > 9.9e9) { // No track passed angle cut
minchi2 = tmp_minchi2;
for(Int_t ihit=0;ihit<nhits;ihit++) {
plusminusbest[ihit] = tmp_plusminus[ihit];
}
sp->SetStub(tmp_stub);
}
Double_t *spstub = sp->GetStubP();
// Calculate final coordinate based on plusminusbest
// Update the hit positions in the space points
for(Int_t ihit=0; ihit<nhits; ihit++) {
// Save left/right status with the hit and in the spaleftce point
// In THcDC will decide which to used based on fix_lr flag
sp->GetHit(ihit)->SetLeftRight(plusminusbest[ihit]);
sp->SetHitLR(ihit, plusminusbest[ihit]);
}
// Stubs are calculated in rotated coordinate system
// (I think this rotates in case chambers not perpendicular to central ray)
Int_t pindex=plane_list[0];
if(spstub[2] - fTanBeta[pindex] == -1.0) {
if (fhdebugflagpr) cout << "THcDriftChamber::LeftRight(): stub3 error" << endl;
}
stub[2] = (spstub[2] - fTanBeta[pindex])
/ (1.0 + spstub[2]*fTanBeta[pindex]);
if(spstub[2]*fSinBeta[pindex] == -fCosBeta[pindex]) {
if (fhdebugflagpr) cout << "THcDriftChamber::LeftRight(): stub4 error" << endl;
}
stub[3] = spstub[3]
/ (spstub[2]*fSinBeta[pindex]+fCosBeta[pindex]);
stub[0] = spstub[0]*fCosBeta[pindex]
- spstub[0]*stub[2]*fSinBeta[pindex];
stub[1] = spstub[1]
- spstub[1]*stub[3]*fSinBeta[pindex];
sp->SetStub(stub);
//if (fhdebugflagpr) cout << " Left/Right space pt " << isp+1 << " " << stub[0]<< " " << stub[1] << " " << stub[2]<< " " << stub[3] << endl;
}
// Option to print stubs
}
//_____________________________________________________________________________
Double_t THcDriftChamber::FindStub(Int_t nhits, THcSpacePoint *sp,
Int_t* plane_list, UInt_t bitpat,
Int_t* plusminus, Double_t* stub)
{
// For a given combination of L/R, fit a stub to the space point
// This method does a linear least squares fit of a line to the
// hits in an individual chamber. It assumes that the y slope is 0
// The wire coordinate is calculated by
// wire center + plusminus*(drift distance).
// Method is called in a loop over all combinations of plusminus
Double_t zeros[] = {0.0,0.0,0.0};
TVectorD TT; TT.Use(3, zeros); // X, X', Y
Double_t dpos[nhits];
for(Int_t ihit=0;ihit<nhits; ihit++) {
dpos[ihit] = sp->GetHit(ihit)->GetPos()
+ plusminus[ihit]*sp->GetHitDist(ihit)
- fPsi0[plane_list[ihit]];
for(Int_t index=0;index<3;index++) {
TT[index]+= dpos[ihit]*fStubCoefs[plane_list[ihit]][index]
/fSigma[plane_list[ihit]];
}
}
// fAA3Inv[bitpat]->Print();
// if (fhdebugflagpr) cout << TT[0] << " " << TT[1] << " " << TT[2] << endl;
// TT->Print();
TT *= *fAA3Inv[bitpat];
// if (fhdebugflagpr) cout << TT[0] << " " << TT[1] << " " << TT[2] << endl;
// Calculate Chi2. Remember one power of sigma is in fStubCoefs
stub[0] = TT[0];
stub[1] = TT[1];
stub[2] = TT[2];
stub[3] = 0.0;
Double_t chi2=0.0;
for(Int_t ihit=0;ihit<nhits; ihit++) {
chi2 += pow( dpos[ihit]/fSigma[plane_list[ihit]]
- fStubCoefs[plane_list[ihit]][0]*stub[0]
- fStubCoefs[plane_list[ihit]][1]*stub[1]
- fStubCoefs[plane_list[ihit]][2]*stub[2]
, 2);
}
return(chi2);
}
//_____________________________________________________________________________
THcDriftChamber::~THcDriftChamber()
{
// Destructor. Remove variables from global list.
if (fhdebugflagpr) cout << fChamberNum << ": delete fSpacePoints: " << hex << fSpacePoints << endl;
delete fSpacePoints;
// Should delete the matrices
if( fIsSetup )
RemoveVariables();
if( fIsInit )
DeleteArrays();
if (fTrackProj) {
fTrackProj->Clear();
delete fTrackProj; fTrackProj = 0;
}
}
//_____________________________________________________________________________
void THcDriftChamber::DeleteArrays()
{
// Delete member arrays. Used by destructor.
delete fCosBeta; fCosBeta = NULL;
delete fSinBeta; fSinBeta = NULL;
delete fTanBeta; fTanBeta = NULL;
delete fSigma; fSigma = NULL;
delete fPsi0; fPsi0 = NULL;
delete fStubCoefs; fStubCoefs = NULL;
// Need to delete each element of the fAA3Inv map
}
//_____________________________________________________________________________
inline
void THcDriftChamber::Clear( const Option_t* )
{
// Reset per-event data.
// fNhits = 0;
// fTrackProj->Clear();
fNhits = 0;
}
//_____________________________________________________________________________
Int_t THcDriftChamber::ApplyCorrections( void )
{
return(0);
}
ClassImp(THcDriftChamber)
////////////////////////////////////////////////////////////////////////////////