// $Id: hrichchernovringfitter.cc,v 1.7 2009-07-15 11:39:21 halo Exp $ // Last update by Thomas Eberl: 03/04/02 16:55:48 // // Class HRichChernovRingFitter // implementation of fit routine // shamelessly adapted from: Thomas Ullrich, Dec 1999, STAR Collaboration // *************************************************************************** // * // * Description: // * // * Fast fitting routine using an iterative linear regression // * method (ILRM). Reference: N.I.Chernov, G.A.Ososkov, Computer // * Physics Communication 33 (1984) 329-333. // * // *************************************************************************** // FIXME: // *** apply pad cleaning algorithm before fitting (single pads w/ a distance) // *** subtract contributions from a second nearby ring before fitting // *** implement functional minimization with distance-from-center weighted coords // *** improve padpattern->photon model, the "de-digitization" // *** the routine is fast, but the extraction of the fired pads into a suitable // interface structure for the fitting routing is too slow !!! // *************************************************************************** #include "hrichchernovringfitter.h" #include "hrichphotonhit.h" #include "hrichphotonhitheader.h" #include "hruntimedb.h" #include "hevent.h" #include "hspectrometer.h" #include "hdetector.h" #include "hrichdetector.h" #include "hcategory.h" #include "hiterator.h" #include "hmatrixcatiter.h" #include "hlocation.h" #include "hdebug.h" #include "hades.h" #include "richdef.h" #include "hrichhit.h" #include "hrichhitfit.h" #include "hrichcal.h" #include "hrichpad.h" #include "hrichgeometrypar.h" #include "hlinearcategory.h" #include "TMath.h" #include ClassImp(HRichChernovRingFitter) HRichChernovRingFitter::HRichChernovRingFitter(const Text_t *name,const Text_t *title,Bool_t kPhoton) : HReconstructor(name,title) { kPhotonFinder = kPhoton; pIterCal=NULL; pIterHit=NULL; pIterPhotonHit=NULL; fs = 6; //half size of square to be cut out around hit point arraysize = (2*fs+1)*(2*fs+1); evtcounter=0; pCalCat=NULL; pHitCat=NULL; pHitFitCat=NULL; pPhotonHitCat=NULL; pGeomPar=NULL; } HRichChernovRingFitter::~HRichChernovRingFitter(void) { if (pIterCal) delete pIterCal; if (pIterHit) delete pIterHit; if (pIterPhotonHit) delete pIterPhotonHit; } Bool_t HRichChernovRingFitter::init() { HRichDetector *pRichDet = (HRichDetector*)gHades->getSetup() ->getDetector("Rich"); HRuntimeDb* rtdb=gHades->getRuntimeDb(); HRichGeometryPar *pGeomPar = (HRichGeometryPar*)rtdb->getContainer("RichGeometryParameters"); setGeometryPar(pGeomPar); if (getGeometryPar()==NULL) { cout<<"ERROR in init: no pointer to geom container" <getCurrentEvent()->getCategory(catRichCal); if (!pCalCat) { cout<<"no valid CAL category on file"<MakeIterator("native"); // RICH HIT container pHitCat=gHades->getCurrentEvent()->getCategory(catRichHit); if (!pHitCat) { cout<<"no valid HIT category on file"<MakeIterator(); // RICH HIT FIT container pHitFitCat=gHades->getCurrentEvent()->getCategory(catRichHitFit); if (!pHitFitCat) { pHitFitCat=pRichDet->buildCategory(catRichHitFit); if (!pHitFitCat) return kFALSE; else gHades->getCurrentEvent() ->addCategory(catRichHitFit, pHitFitCat, "Rich"); } if (kPhotonFinder){ // RICH PHOTON HITHEADER container pPhotonHitHeaderCat=gHades->getCurrentEvent() ->getCategory(catRichPhotonHitHeader); if (!pPhotonHitHeaderCat) { pPhotonHitHeaderCat=pRichDet ->buildCategory(catRichPhotonHitHeader); if (!pPhotonHitHeaderCat) return kFALSE; else gHades->getCurrentEvent() ->addCategory(catRichPhotonHitHeader, pPhotonHitHeaderCat, "Rich"); } pIterPhotonHitHeader = (HIterator*)getPhotonHitHeaderCat() ->MakeIterator("native"); // RICH PHOTON HIT container pPhotonHitCat=gHades->getCurrentEvent()->getCategory(catRichPhotonHit); if (!pPhotonHitCat) { pPhotonHitCat=pRichDet->buildCategory(catRichPhotonHit); if (!pPhotonHitCat) return kFALSE; else gHades->getCurrentEvent() ->addCategory(catRichPhotonHit, pPhotonHitCat, "Rich"); } pIterPhotonHit = (HIterator*)getPhotonHitCat()->MakeIterator("native"); } return kTRUE; } Bool_t HRichChernovRingFitter::finalize() { return kTRUE; } Int_t HRichChernovRingFitter::execute() { if (kPhotonFinder){ // search and use photon impact coords for fit if(!fitFoundPhotons()) return kFALSE; }else{ // use fired pad coords for fit if(!fitFiredPads()) return kFALSE; } evtcounter++; return 0; } // Bool_t HRichChernovRingFitter::fitFoundPhotons() // { // // this function is not yet checked !!! // HRichPhotonHitHeader *pPhotonHitHeader; // pIterPhotonHitHeader->Reset(); // Double_t *dX = new Double_t[arraysize]; // Double_t *dY = new Double_t[arraysize]; // Double_t *dCh = new Double_t[arraysize]; // while( (pPhotonHitHeader = (HRichPhotonHitHeader *) // pIterPhotonHitHeader->Next()) // ) // { // //cout<<"in photon hit header loop"<getRingX(); // Int_t nHeaderRingY = pPhotonHitHeader->getRingY(); // Float_t fHeaderRingPhi = pPhotonHitHeader->getRingPhi(); // Float_t fHeaderRingTheta = pPhotonHitHeader->getRingTheta(); // Int_t nHeaderSector = pPhotonHitHeader->getSector(); // Int_t nHeaderNbPhot = pPhotonHitHeader->getNbPhotons(); // //cout<<"ring X: "<Reset(); // Int_t nHitCounter=0; // while( (pPhotonHit = (HRichPhotonHit *)pIterPhotonHit->Next()) ) // { // //cout<<"in photon hit header loop"<getRingX(); // Int_t nHitRingY = pPhotonHit->getRingY(); // Int_t nHitSector = pPhotonHit->getSector(); // if (nHitSector==nHeaderSector && // nHitRingX ==nHeaderRingX && // nHitRingY ==nHeaderRingY) // { // dX[nHitCounter]=pPhotonHit->getPhi(); // dY[nHitCounter]=pPhotonHit->getTheta(); // dCh[nHitCounter]=pPhotonHit->getCharge(); // nHitCounter++; // } // } //end while photon hits // if (nHitCounter!=nHeaderNbPhot) cout<<"Error:photon nb mismatch"<Set(nHitCounter,compress(dX,nHitCounter)); // //if (!mY) mY = new TArrayD(nHitCounter,compress(dY,nHitCounter)); // mY->Set(nHitCounter,compress(dY,nHitCounter)); // //if (!mCh) mCh = new TArrayD(nHitCounter,compress(dCh,nHitCounter)); // mCh->Set(nHitCounter,compress(dCh,nHitCounter)); // clearFitParams(); // // =================================================================== // if (fit()) // <------ here the actual fitting algorithm is called !!! // // =================================================================== // {//check if fit is reasonable // if (! ((dFittedCenterX-fHeaderRingPhi) < 2. && // (dFittedCenterY-fHeaderRingTheta) < 2. ) ) // unvalidFitParams(); // }else{unvalidFitParams();} // switchXtoPhi(); // Int_t ind=-1; // storeFitinHRichHitFit(nHeaderSector,nHitCounter,ind); // //dumpFitParameters(nHeaderSector,nHeaderRingX,nHeaderRingY,-1.); // } // end while photon hit header // if (dX) delete [] dX; // if (dY) delete [] dY; // if (dCh) delete [] dCh; // return kTRUE; // } void HRichChernovRingFitter::switchXtoPhi() { dFittedCenterPhi=dFittedCenterX; dFittedCenterTheta=dFittedCenterY; dFittedCenterX=-1; dFittedCenterY=-1; } Bool_t HRichChernovRingFitter::fitFiredPads2() { // alternative implementation which is slower, astonishingly HRichHit *pHit; pIterHit->Reset(); while((pHit = (HRichHit *)pIterHit->Next())) { Double_t *dX = new Double_t[arraysize]; Double_t *dY = new Double_t[arraysize]; Double_t *dCh = new Double_t[arraysize]; for (Int_t ii=0;iigetSector(); Int_t nHitX = pHit->iRingX; Int_t nHitY = pHit->iRingY; Int_t startcol=0; if (nHitX-fs>=0) startcol = nHitX-fs; else startcol = 0; Int_t startrow=0; if (nHitY-fs>=0) startrow = nHitY-fs; else startrow = 0; Int_t endcol=0; if (nHitX+fs<=92) endcol = nHitX+fs; else endcol = 92; Int_t endrow=0; if (nHitY+fs<=92) endrow = nHitY+fs; else endrow = 92; for (Int_t i=startcol;i<=endcol;i++) { for (Int_t j=startrow;j<=endrow;j++) { HLocation loc; loc.set(3,0,0,0); loc.setOffset(i); loc.setIndex(1,j); loc.setIndex(0,nHitSector); HRichCal *c = (HRichCal*)((HMatrixCategory*)getCalCat())->getObject(loc); if (c) { dX[nPadCounter] = i; dY[nPadCounter] = j; dCh[nPadCounter] = c->getCharge(); //cout<<"col: "<getCharge()<3) {if (fit(x,y)) calcThetaAndPhi(pHit);} //dumpFitParameters(nHitSector,nHitX,nHitY,pHit->getRadius()); //cout<<"end ring ************************** "<Reset(); // loop over each ring in event while((pHit = (HRichHit *)pIterHit->Next())) { // store pad coords of ring Double_t *dX = new Double_t[arraysize]; Double_t *dY = new Double_t[arraysize]; Double_t *dCh = new Double_t[arraysize]; for (Int_t i=0;igetSector(); Int_t nHitX = pHit->iRingX; Int_t nHitY = pHit->iRingY; // fired pad data HRichCal* pCal; pIterCal->Reset(); Int_t nPadCounter=0; // loop over fired pads in arraysize sized square around hit // and store them for fitting while((pCal = (HRichCal *)pIterCal->Next())) { if (nHitSector == pCal->getSector()) { Int_t nCalRow = pCal->getRow(); Int_t nCalCol = pCal->getCol(); Float_t nCalChrg = pCal->getCharge(); if(TMath::Abs(nCalRow-nHitY) <= fs && TMath::Abs(nCalCol-nHitX) <= fs) { dX[nPadCounter] = nCalCol; dY[nPadCounter] = nCalRow; dCh[nPadCounter] = nCalChrg; nPadCounter++; } } } // endwhile cal container // resize array according to nr of found pads in square Double_t *dnewX = compress(dX,nPadCounter); Double_t *dnewY = compress(dY,nPadCounter); Double_t *dnewCh = compress(dCh,nPadCounter); // use ROOT arrays as interface to fit routine // (historical reasons, potentially slow ... ) TArrayD x(nPadCounter,dnewX); TArrayD y(nPadCounter,dnewY); TArrayD c(nPadCounter,dnewCh); // free mem of used helper arrays if (dX) delete [] dX; if (dY) delete [] dY; if (dCh) delete [] dCh; if (dnewX) delete [] dnewX; if (dnewY) delete [] dnewY; if (dnewCh) delete [] dnewCh; // reset params filled by fitting routine clearFitParams(); // =================================================================== // do not fit rings with less than 4 pads if (nPadCounter>3 && fit(x,y)) // <------ here the actual fitting algorithm is called !!! // =================================================================== {//check if fit is reasonable if ((dFittedCenterX-nHitX) < 2. && (dFittedCenterY-nHitY) < 2. ) { // calculate theta and phi by linear interpolation of pad centers calcThetaAndPhi(pHit); } else // fit was too far off { //cout<<"ERROR: Fitted center too far off !"<getIndex(pHit); storeFitinHRichHitFit(pHit->getSector(),nPadCounter,ind); //dumpFitParameters(nHitSector,nHitX,nHitY,pHit->fRingRadius); } //endwhile hit container return kTRUE; } void HRichChernovRingFitter::storeFitinHRichHitFit(Int_t s, Int_t n,Int_t i) { HLocation loc; loc.set(1,s); HRichHitFit *hitfit = (HRichHitFit*)((HLinearCategory*)getHitFitCat()) ->getNewSlot(loc); if (hitfit!=NULL) { hitfit->Reset(); hitfit = new(hitfit) HRichHitFit; hitfit->setHitIndex(i); hitfit->setSector(s); hitfit->setNbCoords(n); hitfit->setFitRadius(getFitRadius()); hitfit->setFitCenterX(getFitCenterX()); hitfit->setFitCenterY(getFitCenterY()); hitfit->setFitVar(getFitVar()); hitfit->setFitCenterTheta(getFitCenterTheta()); hitfit->setFitCenterPhi(getFitCenterPhi()); } } void HRichChernovRingFitter::clearFitParams() { dFittedRadius = 0.; dFittedCenterX = 0.; dFittedCenterY = 0.; dFitVariance = 0.; dFittedCenterTheta = 0.; dFittedCenterPhi = 0.; } void HRichChernovRingFitter::unvalidFitParams() { dFittedRadius = -1.; dFittedCenterX = -1.; dFittedCenterY = -1.; dFitVariance = -1.; dFittedCenterTheta = -1.; dFittedCenterPhi = -1.; } Double_t* HRichChernovRingFitter::compress(Double_t* arr,Int_t nPadCounter) { Int_t nNonZeroElementCounter=0; Double_t* arr2=0; for (Int_t i=0;iGetSize(); // if (npoints <= 3) { // mRC = 1; // //cout<<"Error: less than 4 points for fit !!"<GetSum() / npoints; // ygravity = mY->GetSum() / npoints; // for (i=0; igetPadsPar(); if (pPadsPar) { HRichPad *pPad0 = pPadsPar->getPad(x,y); if (pPad0) { Float_t theta = pPad0->getTheta(); Float_t phi = pPad0->getPhi(sec); cout<<"EVENT NUMBER :"< x:"< x:"<getPadsPar(); Int_t nPadX0 = (Int_t) TMath::Floor(dFittedCenterX); Int_t nPadY0 = (Int_t) TMath::Floor(dFittedCenterY); if (pPadsPar) { Float_t fThetaOfPadCenter0 = 0; Float_t fPhiOfPadCenter0 = 0; HRichPad *pPad0 = pPadsPar->getPad(nPadX0,nPadY0); if (pPad0) { fThetaOfPadCenter0 = pPad0->getTheta(); fPhiOfPadCenter0 = pPad0->getPhi(pHit->getSector()); } else { return; // cout<<"ERROR: no pointer to pad 0"<getSector(),pHit->iRingX,pHit->iRingY, // pHit->fRingRadius); // cout<<" PadX: "<getPad(nPadX0,nPadY0-1); if (pPad1) { fThetaOfPadCenter1 = pPad1->getTheta(); //fPhiOfPadCenter1 = pPad1->getPhi(sector);//for later use } else { return; // cout<<"ERROR: no pointer to pad 1"<getSector(),pHit->iRingX,pHit->iRingY, // pHit->fRingRadius); // cout<<" PadX: "<getPad(nPadX0-1,nPadY0); if (pPad2) { //fThetaOfPadCenter2 = pPad2->getTheta();//for later use fPhiOfPadCenter2 = pPad2->getPhi(pHit->getSector()); } else { return; // cout<<"ERROR: no pointer to pad 2"<getSector(),pHit->iRingX,pHit->iRingY, // pHit->fRingRadius); // cout<<" PadX: "<getPad(nPadX0+1,nPadY0); if (pPad3) { // fThetaOfPadCenter3 = pPad3->getTheta();//for later use fPhiOfPadCenter3 = pPad3->getPhi(pHit->getSector()); } else { return; // cout<<"ERROR: no pointer to pad 3"<getSector(),pHit->iRingX,pHit->iRingY, // pHit->fRingRadius); // cout<<" PadX: "<getPad(nPadX0,nPadY0+1); if (pPad4) { fThetaOfPadCenter4 = pPad4->getTheta(); //fPhiOfPadCenter4 = pPad4->getPhi(sector);//for later use } else { return; // cout<<"ERROR: no pointer to pad 4"<getSector(),pHit->iRingX,pHit->iRingY, // pHit->fRingRadius); // cout<<" PadX: "< 0.5) { dFittedCenterPhi = (dFittedCenterX-0.5-nPadX0)* (fPhiOfPadCenter3-fPhiOfPadCenter0) + fPhiOfPadCenter0; } if (dFittedCenterX-nPadX0 < 0.5) { dFittedCenterPhi = (dFittedCenterX+0.5-nPadX0)* (fPhiOfPadCenter0-fPhiOfPadCenter2) + fPhiOfPadCenter2; } // theta interpolation //cout<<"theta interpolation"< 0.5) { dFittedCenterTheta = (dFittedCenterY-0.5-nPadY0)* (fThetaOfPadCenter4-fThetaOfPadCenter0) + fThetaOfPadCenter0; } if (dFittedCenterY-nPadY0 < 0.5) { dFittedCenterTheta = (dFittedCenterY+0.5-nPadY0)* (fThetaOfPadCenter0-fThetaOfPadCenter1) + fThetaOfPadCenter1; } // FIXME: if e.g. theta of 3 and 0 are not equal, one has to calc // the difference and add to dFittedCenterTheta according to the phi !! // but this should be a very small effect } else cout<<"ERROR: no pointer to RTDB"<