00001 #include "PhotonCalibratedPeComputer.h"
00002 #include "PhotonTransportMaker.h"
00003 #include "MessageService/MsgService.h"
00004 #include "UgliGeometry/UgliGeomHandle.h"
00005 #include "Calibrator/Calibrator.h"
00006
00007 CVSID( " $Id: PhotonCalibratedPeComputer.cxx,v 1.23 2008/04/04 20:55:32 rhatcher Exp $" );
00008
00009 ClassImp(PhotonCalibratedPeComputer)
00010 PhotonTransportMakerProxy<PhotonCalibratedPeComputer>
00011 gPhotonCalibratedPeComputerProxy("photonCalibratedPeComputer");
00012
00013
00015
00016 PhotonCalibratedPeComputer::PhotonCalibratedPeComputer()
00017 {
00018 Configure(PhotonConfiguration());
00019 }
00020
00022
00023 PhotonCalibratedPeComputer::~PhotonCalibratedPeComputer()
00024 {
00025
00026 }
00027
00029
00030 void
00031 PhotonCalibratedPeComputer::Configure( const Registry& r )
00032 {
00033 MSG("Photon",Msg::kDebug) << "Configuring CalibratedPeComputer." << std::endl;
00034
00035 bool ok = true;
00036 ok = ok && r.Get("OverallLightOutput",fOverallLightOutput);
00037 ok = ok && r.Get("BirksConstant",fBirksConstant);
00038 ok = ok && r.Get("GeVPerMip",fGeVPerMip);
00039 ok = ok && r.Get("ScintillatorClipping",fScintillatorClipping);
00040 ok = ok && r.Get("MaxPePerHit",fMaxPePerHit);
00041 if (!ok) MSG("Photon",Msg::kError)
00042 << "Trouble configuring PhotonCalibratedPeComputer." << endl;
00043 }
00044
00046
00047 void
00048 PhotonCalibratedPeComputer::Reset( const VldContext& )
00049 {
00050 }
00051
00052
00054
00055
00056
00057
00058 Bool_t
00059 PhotonCalibratedPeComputer::ComputePhotons( const DigiScintHit* inHit,
00060 Double_t ,
00061 Double_t ,
00062 Double_t ,
00063 PhotonCount& outCount )
00064 {
00065
00066 if (!inHit) return false;
00067 double dE = inHit->DE();
00068 double dx = inHit->DS();
00069 double dEdx = dE/dx;
00070
00071
00072 double x = 0.5*(inHit->X1() + inHit->X2());
00073
00074 double clippedfrac = 1.0;
00075
00076 UgliGeomHandle ugli(fContext);
00077 UgliStripHandle ustrip=ugli.GetStripHandle(inHit->StripEndId());
00078
00079 if (fScintillatorClipping) {
00080
00081
00082
00083
00084
00085
00086 double distToEnd;
00087
00088 distToEnd = ustrip.GetHalfLength()-x;
00089 clippedfrac *= ClipFraction( distToEnd );
00090
00091 distToEnd = x+ustrip.GetHalfLength();
00092 clippedfrac *= ClipFraction( distToEnd );
00093
00094 if (ustrip.WlsBypass() > 0.) {
00095
00096
00097 double coilpos = 0.5*(ustrip.PartialLength(StripEnd::kNegative) - ustrip.PartialLength(StripEnd::kPositive));
00098 if (x<coilpos) {
00099 distToEnd = (-x) - ( ustrip.GetHalfLength() - ustrip.PartialLength(StripEnd::kNegative));
00100 clippedfrac *= ClipFraction( distToEnd );
00101
00102 } else {
00103 distToEnd = (x) - ( ustrip.GetHalfLength() - ustrip.PartialLength(StripEnd::kPositive));
00104 clippedfrac *= ClipFraction( distToEnd );
00105 }
00106 }
00107 }
00108
00109 if (clippedfrac < 0.49) {
00110 MSG("Photon",Msg::kError) << "Error: saw clipfrac less than 0.5: " << clippedfrac<< endl;
00111 clippedfrac = 0.5;
00112 }
00113
00114 PlexStripEndId end[2];
00115 end[0] = inHit->StripEndId(); end[0].SetEnd(StripEnd::kNegative);
00116 end[1] = inHit->StripEndId(); end[1].SetEnd(StripEnd::kPositive);
00117
00118
00119
00120 double emips =
00121 clippedfrac
00122 * fOverallLightOutput
00123 * dE/(1. + fBirksConstant*dEdx)
00124 / fGeVPerMip;
00125
00126
00127
00128
00129
00130
00131 const Calibrator& cal = Calibrator::Instance();
00132
00133
00134 double sigmap[2] = {0,0};
00135 double sigcorr[2]= {0,0};
00136 double siglin[2] = {0,0};
00137 double adc[2] = {0,0};
00138 double meanpe[2] = {0,0};
00139 double pe[2] = {0,0};
00140 int npe[2] = {0,0};
00141
00142 if (ustrip.IsMirrored(StripEnd::kNegative) || ustrip.IsMirrored(StripEnd::kPositive) ) {
00143
00144 } else {
00145
00146 emips *= 0.5;
00147 }
00148
00149 for (int i=0;i<2;i++) {
00150 if ( ustrip.IsMirrored(end[i].GetEnd()) ) {
00151
00152 sigmap[i] = sigcorr[i] = siglin[i] = pe[i] = 0;
00153 npe[i] = 0;
00154 } else {
00155
00156
00157
00158 sigmap[i] = cal.DecalMIP( emips , end[i]);
00159
00160
00161 sigcorr[i] = cal.DecalAttenCorrected(sigmap[i],x,end[i]);
00162
00163
00164 siglin[i] = cal.DecalStripToStrip(sigcorr[i],end[i]);
00165
00166
00167 adc[i] = cal.DecalDrift(siglin[i],end[i]);
00168
00169
00170 meanpe[i] = cal.GetPhotoElectrons(adc[i],end[i]);
00171
00172 if (isnan(meanpe[i])) {
00173 MSG("Photon",Msg::kError)
00174 << "Got an expectation value of NaN photons in CalibratedPeComputer.\n"
00175 << "\tHit on stripend " << end[i].AsString() << endl
00176 << "\tPosition: " << x << " m (in strip coords) " << endl
00177 << "\t" << dE/Munits::MeV << " MeV, "<< endl
00178 << "\t" << emips << " MIP, "<< endl
00179 << "\t" << sigmap[0] << " / " << sigmap[1] << " SigMap, "<< endl
00180 << "\t" << sigcorr[0] << " / " << sigcorr[1] << " SigCorr, "<< endl
00181 << "\t" << siglin[0] << " / " << siglin[1] << " SigLin, "<< endl
00182 << "\t" << adc[0] << " / " << adc[1] << " ADC, "<< endl
00183 << "\t" << meanpe[0] << " / " << meanpe[1] << " PE" << endl;
00184 outCount.SetPeNegPos(0,0);
00185 return false;
00186 }
00187
00188
00189 pe[i] = fRandom->PoissonD(meanpe[i]);
00190
00191
00192 if (isnan(pe[i])) {
00193 MSG("Photon",Msg::kError)
00194 << "Got a random poisson value of NaN photons in CalibratedPeComputer.\n"
00195 << "\tHit on stripend " << end[i].AsString() << endl
00196 << "\tPosition: " << x << " m (in strip coords) " << endl
00197 << "\t" << dE/Munits::MeV << " MeV, "<< endl
00198 << "\t" << emips << " MIP, "<< endl
00199 << "\t" << sigmap[0] << " / " << sigmap[1] << " SigMap, "<< endl
00200 << "\t" << sigcorr[0] << " / " << sigcorr[1] << " SigCorr, "<< endl
00201 << "\t" << siglin[0] << " / " << siglin[1] << " SigLin, "<< endl
00202 << "\t" << adc[0] << " / " << adc[1] << " ADC, "<< endl
00203 << "\t" << meanpe[0] << " / " << meanpe[1] << " PE" << endl;
00204 outCount.SetPeNegPos(0,0);
00205 return false;
00206 }
00207
00208 if (pe[i] < 0) {
00209 MSG("Photon",Msg::kError)
00210 << "Got -ve PEs on end " << i << endl
00211 << "\tHit on stripend " << end[i].AsString() << endl
00212 << "\tPosition: " << x << " m (in strip coords) " << endl
00213 << "\t" << dE/Munits::MeV << " MeV, "<< endl
00214 << "\t" << emips << " MIP, "<< endl
00215 << "\t" << sigmap[0] << " / " << sigmap[1] << " SigMap, "<< endl
00216 << "\t" << sigcorr[0] << " / " << sigcorr[1] << " SigCorr, "<< endl
00217 << "\t" << siglin[0] << " / " << siglin[1] << " SigLin, "<< endl
00218 << "\t" << adc[0] << " / " << adc[1] << " ADC, "<< endl
00219 << "\t" << meanpe[0] << " / " << meanpe[1] << " PE" << endl;
00220 pe[i] = 0;
00221 }
00222
00223 if (pe[i] > fMaxPePerHit) {
00224 MSG("Photon",Msg::kError)
00225 << "Got huge pulse on end " << i << endl
00226 << "\tHit on stripend " << end[i].AsString() << endl
00227 << "\tPosition: " << x << " m (strip coords) " << endl
00228 << "\t" << dE/Munits::MeV << " MeV, "<< endl
00229 << "\t" << emips << " MIP, "<< endl
00230 << "\t" << sigmap[0] << " / " << sigmap[1] << " SigMap, "<< endl
00231 << "\t" << sigcorr[0] << " / " << sigcorr[1] << " SigCorr, "<< endl
00232 << "\t" << siglin[0] << " / " << siglin[1] << " SigLin, "<< endl
00233 << "\t" << adc[0] << " / " << adc[1] << " ADC, "<< endl
00234 << "\t" << meanpe[0] << " / " << meanpe[1] << " PE" << endl
00235 << "\t ... Truncating to " << fMaxPePerHit << " pes." << endl;
00236 pe[i] = fMaxPePerHit;
00237 }
00238 npe[i] = (int) pe[i];
00239 }
00240 }
00241
00242
00243
00244 outCount.SetPeNegPos( npe[0], npe[1] );
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262 MSG("Photon",Msg::kDebug) << "CalibratedPeComputer: "
00263 << dE/Munits::MeV << " MeV, "
00264 << emips << " MIP, "
00265 << sigmap[0] + sigmap[1] << " SigMap, "
00266 << sigcorr[0] + sigcorr[1] << " SigCorr, "
00267 << siglin[0] + siglin[1] << " SigLin, "
00268 << meanpe[0] + meanpe[1] << " PE"
00269 << endl;
00270 MSG("Photon",Msg::kDebug) << " "
00271 << outCount.GetPe_Neg()
00272 << " (" << pe[0] << ") pe Neg "
00273 << outCount.GetPe_Pos()
00274 << " (" << pe[1] << ") pe Pos"
00275 << endl;
00276
00277 return true;
00278 }
00279
00280 Double_t PhotonCalibratedPeComputer::ClipFraction(double x) const
00281 {
00282
00283
00284
00285
00286
00287 const double kLorentzWidth1 = 0.017853;
00288 const double kArea1 = 8.178052;
00289 const double kLorentzWidth2 = 0.001309;
00290 const double kArea2 = 0.864215;
00291
00292 const double kArea = kArea1+kArea2;
00293
00294 double frac = kArea1 * atan(x/kLorentzWidth1)
00295 + kArea2 * atan(x/kLorentzWidth2);
00296 frac = frac / (kArea * TMath::Pi());
00297 frac += 0.5;
00298
00299
00300
00301
00302
00303 if (x>0.2) frac = 1-(1-frac)*exp(-(x-0.2)*20.);
00304
00305 return frac;
00306 }
00307