//______________________________________________________________________________ // // C++ Implementation: PndSdsCalcStrip // // Description: // // // Author: HG Zaunick , (C) 2007 // // Copyright: See COPYING file that comes with this distribution // // #include #include #include "PndSdsCalcStrip.h" #include "TRandom.h" //______________________________________________________________________________ PndSdsCalcStrip::PndSdsCalcStrip(){ fPitch = 0.; fOrient = 0.; fAnchor = TVector2(0.,0.); fNrStrips = 0; fThreshold = 0.; fNoise = 0.; fCSigma = 0.; fVerboseLevel = 0; } //______________________________________________________________________________ PndSdsCalcStrip::PndSdsCalcStrip(Double_t pitch, Double_t orient, Int_t nrStrips, Int_t nrFeChannels, const TVector2& firstStripAnchor, Double_t threshold, Double_t noise, Double_t csigma=0) : fPitch(pitch), fOrient(orient), fNrStrips(nrStrips), fNrFeChannels(nrFeChannels), fAnchor(firstStripAnchor), fThreshold(threshold), fNoise(noise), fCSigma(csigma) { fStripDir.Set(cos(fOrient),sin(fOrient)); fOrthoDir.Set(sin(fOrient),-cos(fOrient)); fVerboseLevel = 0; //Print(); } //______________________________________________________________________________ PndSdsCalcStrip::PndSdsCalcStrip(const PndSdsStripDigiPar* digipar, SensorSide side) { if(side == kTOP) { fPitch = digipar->GetTopPitch(); fOrient = digipar->GetOrient(); fAnchor = digipar->GetTopAnchor(); fNrStrips = digipar->GetNrTopFE()*digipar->GetNrFECh(); } else if(side == kBOTTOM) { fPitch = digipar->GetBotPitch(); fOrient = digipar->GetOrient() + digipar->GetSkew(); fAnchor = digipar->GetBotAnchor(); fNrStrips = digipar->GetNrBotFE()*digipar->GetNrFECh(); } fNrFeChannels = digipar->GetNrFECh(); fThreshold = digipar->GetThreshold(); fNoise = digipar->GetNoise(); fCSigma = digipar->GetQCloudSigma(); fStripDir.Set(cos(fOrient),sin(fOrient)); fOrthoDir.Set(sin(fOrient),-cos(fOrient)); fVerboseLevel = 0; if (fVerboseLevel > 0) Print(); } //______________________________________________________________________________ std::vector PndSdsCalcStrip::GetStrips(Double_t inx, Double_t iny, Double_t inz, Double_t outx, Double_t outy, Double_t outz, Double_t eLoss) { if (fVerboseLevel > 2) std::cout<<"-I- PndSdsCalcStrip::GetStrips "< 2){ std::cout<<" InPoint: ("< 2) std::cout<<" nuIn = "< strips; if (fVerboseLevel > 2) std::cout<<" nuIn = "< (Double_t(fNrStrips))){ Q *= ((Double_t)fNrStrips-nuOut)/(-nuOut+nuIn); nuIn = Double_t(fNrStrips); } // is the Out-Point inside active area ? if (nuOut<0.){ Q *= (nuIn)/(-nuOut+nuIn); nuOut = 0.; } else if (nuOut > (Double_t(fNrStrips))){ Q *= ((Double_t)fNrStrips-nuIn)/(nuOut-nuIn); nuOut = Double_t(fNrStrips); } // only one strip hit ? if (Int_t(nuIn) == Int_t(nuOut)){ // this strip collected the entire charge InjectStripCharge(strips,(Int_t)nuOut,Q); return strips; } else { // more than one strip is hit Double_t dQ=Q/std::fabs(nuOut-nuIn); Double_t dir = (nuOut>nuIn) ? 1. : -1.; Int_t nrHits = 0; // calculate portion of track in first strip Int_t nextIn = Int_t(nuIn + 0.5+0.5*dir); Double_t Q1 = dQ*std::fabs(nextIn-nuIn); if (fVerboseLevel > 2){ std::cout<<" part of first strip : "< 2){ std::cout<<" part of last strip : "<<(nuOut-prevOut)< 2) { std::cout<<" dir="< 1) std::cout<<" -> "< PndSdsCalcStrip::GetStripsDif(Double_t pathstart, Double_t pathend, Double_t Q) { // Do charge diffusion integrated analytically over a path length // 0.5*(1+erf(x)) is the integral over a gauss from -inf to x // factor 0.5 is applied last, the +1 terms cancel in the difference if(pathend array; Double_t DQ = 0.; // sigma_str = sigma_um/pitch_str-per-um Double_t sigma_str=fCSigma/fPitch; // TODO how much extra bins to fill?, minimum 1... // how about 2sigma? shall be collected Int_t xtra = (Int_t)ceil(2.*sigma_str); for(Int_t i=(Int_t)pathstart-xtra;i<(Int_t)pathend+1+xtra;i++) { DQ=0; if(fabs(pathstart-pathend) < 1e-6) { // too small path, don't integrate over path DQ+=TMath::Erf(i+1-0.5*(pathstart+pathend))/(sqrt(2)*sigma_str); DQ-=TMath::Erf(i-0.5*(pathstart+pathend))/(sqrt(2)*sigma_str); } else { DQ+=CalcFk(i,pathend,sigma_str); DQ-=CalcFk(i+1,pathend,sigma_str); DQ-=CalcFk(i,pathstart,sigma_str); DQ+=CalcFk(i+1,pathstart,sigma_str); DQ/=(pathend-pathstart); } DQ*=0.5*Q; InjectStripCharge(array,i,DQ); } return array; } //______________________________________________________________________________ Double_t PndSdsCalcStrip::CalcFk(Double_t strip, Double_t x, Double_t sig) { const Double_t t=(strip-x)/(sqrt(2)*sig); return ( (strip-x)*TMath::Erf(t) + sqrt(2/TMath::Pi())*sig*exp(-t*t) ); } //______________________________________________________________________________ Int_t PndSdsCalcStrip::GetStripsAlternative(Double_t nuIn, Double_t nuOut, Double_t Q, Int_t mode, std::vector& indice, std::vector& charges) { if(fVerboseLevel>2)Info("GetStripsAlternative()","begin with in=%f, out=%f, Q=%f",nuIn,nuOut,Q); std::vector strips; if(mode == 0) strips = GetStripsNoDif(nuIn,nuOut,Q); if(mode == 1) strips = GetStripsDif(nuIn,nuOut,Q); Int_t nstr=strips.size(); for(Int_t i=0;i2) Info("GetStripsAlternative()","pass this strip: i=%i, s=%i, q=%f",i,strips[i].GetIndex(),strips[i].GetCharge()); indice.push_back(strips[i].GetIndex()); charges.push_back(strips[i].GetCharge()); } return nstr; } //______________________________________________________________________________ Double_t PndSdsCalcStrip::CalcStripFromPoint(Double_t x, Double_t y) { // fOrthoDir is already set to magnitude == 1., makes it cheaper here. return ((x-fAnchor.X())*fOrthoDir.X() + (y-fAnchor.Y())*fOrthoDir.Y())/fPitch; } //______________________________________________________________________________ void PndSdsCalcStrip::CalcStripPointOnLine(Double_t strip,TVector2& point) const { point = fPitch*(strip+0.5)*fOrthoDir + fAnchor; } //______________________________________________________________________________ Int_t PndSdsCalcStrip::CalcFEfromStrip(Int_t stripNr) const { return (stripNr/fNrFeChannels); } //______________________________________________________________________________ Int_t PndSdsCalcStrip::CalcChannelfromStrip(Int_t stripNr) const { return (stripNr%fNrFeChannels); } //______________________________________________________________________________ void PndSdsCalcStrip::CalcFeChToStrip(Int_t fe, Int_t channel, Int_t& strip, enum SensorSide& side) const { //Caution! The top side s always the reference side! Int_t nr = fe * fNrFeChannels + channel; if (nr < fNrStrips) { side = kTOP; } else { nr -= fNrStrips; side = kBOTTOM; } strip = nr; } //______________________________________________________________________________ void PndSdsCalcStrip::InjectStripCharge(std::vector& array, Int_t istrip, Double_t charge) { if(istrip<0) {if(fVerboseLevel>2)Warning("InjectStripCharge","Invalid strip number: %i < 0",istrip); return;} if(istrip>fNrStrips) {if(fVerboseLevel>2)Warning("InjectStripCharge","Invalid strip number: %i > %i",istrip,fNrStrips); return;} if(charge==0) return; // cut zero electron charge now, real threshold later Double_t smearedQ = SmearCharge(charge); if(smearedQ < fThreshold) {if(fVerboseLevel>3)Info("InjectStripCharge","Strip %i, charge %f below threshold %f",istrip,smearedQ,fThreshold); return;} if(fVerboseLevel>3) Info("InjectStripCharge","istrip=%i,charge=%f,smearedCharge=%f",istrip,charge,smearedQ); array.push_back( PndSdsStrip(Int_t(istrip),smearedQ) ); return; } //______________________________________________________________________________ Double_t PndSdsCalcStrip::SmearCharge(Double_t charge) { Double_t smeared = gRandom->Gaus(charge,fNoise); if (fVerboseLevel > 3) Info("SmearCharge:"," charge = %f, smeared = %f",charge,smeared); return smeared; } void PndSdsCalcStrip::Print() const { std::cout<<"-I- PndSdsCalcStrip Info :"<