9 #include "G4LogicalVolumeStore.hh"
10 #include "G4LogicalVolume.hh"
13 #include "G4VProcess.hh"
14 #include "G4Poisson.hh"
29 CaloSD(name, cpv, clg, p, manager) {
40 edm::LogInfo(
"EcalSim") <<
"Constructing a DreamSD with name " << GetName() <<
"\n"
41 <<
"DreamSD:: Use of Birks law is set to "
42 << useBirk <<
" with three constants kB = "
43 << birk1 <<
", C1 = " << birk2 <<
", C2 = "
45 <<
" Slope for Light yield is set to "
47 <<
" Parameterization of Cherenkov is set to "
48 << doCherenkov_ <<
" and readout both sides is "
58 <<
"please add it to config file";
60 ntuple_ = tfile->
make<TTree>(
"tree",
"Cherenkov photons");
100 G4String nameVolume =
preStepPoint->GetPhysicalVolume()->GetName();
107 LogDebug(
"EcalSim") <<
"DreamSD:: " << nameVolume <<
" Side " <<
side
108 <<
" Light Collection Efficiency " << weight
109 <<
" Weighted Energy Deposit " <<
edepositEM/MeV
118 double time = (aStep->GetPostStepPoint()->GetGlobalTime())/nanosecond;
120 if (
side < 0) unitID++;
129 if (primaryID == 0) {
130 edm::LogWarning(
"EcalSim") <<
"CaloSD: Problem with primaryID **** set by "
131 <<
"force to TkID **** "
132 <<
theTrack->GetTrackID() <<
" in Volume "
133 <<
preStepPoint->GetTouchable()->GetVolume(0)->GetName();
137 bool flag = (unitID > 0);
138 G4TouchableHistory* touch =(G4TouchableHistory*)(
theTrack->GetTouchable());
142 LogDebug(
"EcalSim") <<
"CaloSD:: GetStepInfo for"
143 <<
" PV " << touch->GetVolume(0)->GetName()
144 <<
" PVid = " << touch->GetReplicaNumber(0)
145 <<
" MVid = " << touch->GetReplicaNumber(1)
149 LogDebug(
"EcalSim") <<
"CaloSD:: GetStepInfo for"
150 <<
" PV " << touch->GetVolume(0)->GetName()
151 <<
" PVid = " << touch->GetReplicaNumber(0)
152 <<
" MVid = " << touch->GetReplicaNumber(1)
153 <<
" Unit " << std::hex << unitID << std::dec
165 DimensionMap::const_iterator ite =
xtalLMap.begin();
166 G4LogicalVolume* lv = (ite->first);
167 G4Material* material = lv->GetMaterial();
168 edm::LogInfo(
"EcalSim") <<
"DreamSD::initRun: Initializes for material "
169 << material->GetName() <<
" in " << lv->GetName();
173 edm::LogWarning(
"EcalSim") <<
"Couldn't retrieve material properties table\n"
174 <<
" Material = " << material->GetName();
183 const G4VTouchable* touch = aStep->GetPreStepPoint()->GetTouchable();
184 uint32_t
id = (touch->GetReplicaNumber(1))*10 + (touch->GetReplicaNumber(0));
193 G4String attribute =
"ReadOutName";
201 const G4LogicalVolumeStore * lvs = G4LogicalVolumeStore::GetInstance();
202 std::vector<G4LogicalVolume *>::const_iterator lvcite;
208 G4LogicalVolume* lv=0;
209 for (lvcite = lvs->begin(); lvcite != lvs->end(); lvcite++)
210 if ((*lvcite)->GetName() ==
name) {
214 LogDebug(
"EcalSim") <<
"DreamSD::initMap (for " << sd <<
"): Solid "
215 << name <<
" Shape " << sol.
shape() <<
" Parameter 0 = "
216 << paras[0] <<
" Logical Volume " << lv;
217 double length = 0,
width = 0;
220 length = 2.0*paras.back();
221 width = 2.0*paras.front();
225 LogDebug(
"EcalSim") <<
"DreamSD: Length Table for " << attribute <<
" = "
227 DimensionMap::const_iterator ite =
xtalLMap.begin();
229 for (; ite !=
xtalLMap.end(); ite++, i++) {
230 G4String
name =
"Unknown";
231 if (ite->first != 0) name = (ite->first)->GetName();
232 LogDebug(
"EcalSim") <<
" " << i <<
" " << ite->first <<
" " << name
233 <<
" L = " << ite->second.first
234 <<
" W = " << ite->second.second;
241 G4StepPoint* stepPoint = aStep->GetPreStepPoint();
242 G4LogicalVolume* lv = stepPoint->GetTouchable()->GetVolume(0)->GetLogicalVolume();
243 G4String nameVolume= lv->GetName();
246 G4ThreeVector localPoint =
setToLocal(stepPoint->GetPosition(),
247 stepPoint->GetTouchable());
249 double localz = localPoint.x();
250 double dapd = 0.5 * crlength - flag*localz;
251 if (dapd >= -0.1 || dapd <= crlength+0.1) {
255 edm::LogWarning(
"EcalSim") <<
"DreamSD: light coll curve : wrong distance "
256 <<
"to APD " << dapd <<
" crlength = "
257 << crlength <<
" crystal name = " << nameVolume
258 <<
" z of localPoint = " << localz
259 <<
" take weight = " <<
weight;
261 LogDebug(
"EcalSim") <<
"DreamSD, light coll curve : " << dapd
262 <<
" crlength = " << crlength
263 <<
" crystal name = " << nameVolume
264 <<
" z of localPoint = " << localz
265 <<
" take weight = " <<
weight;
273 DimensionMap::const_iterator ite =
xtalLMap.find(lv);
274 if (ite !=
xtalLMap.end()) length = ite->second.first;
283 DimensionMap::const_iterator ite =
xtalLMap.find(lv);
284 if (ite !=
xtalLMap.end()) width = ite->second.second;
295 double cherenkovEnergy = 0;
297 G4Material* material = aStep->GetTrack()->GetMaterial();
301 if ( Rindex ==
NULL ) {
303 return cherenkovEnergy;
306 LogDebug(
"EcalSim") <<
"Material properties: " <<
"\n"
307 <<
" Pmin = " << Rindex->GetMinPhotonEnergy()
308 <<
" Pmax = " << Rindex->GetMaxPhotonEnergy();
311 G4StepPoint* pPreStepPoint = aStep->GetPreStepPoint();
312 G4StepPoint* pPostStepPoint = aStep->GetPostStepPoint();
313 G4ThreeVector x0 = pPreStepPoint->GetPosition();
314 G4ThreeVector p0 = aStep->GetDeltaPosition().unit();
315 const G4DynamicParticle* aParticle = aStep->GetTrack()->GetDynamicParticle();
316 const double charge = aParticle->GetDefinition()->GetPDGCharge();
318 double beta = 0.5*( pPreStepPoint->GetBeta() + pPostStepPoint->GetBeta() );
319 double BetaInverse = 1.0/
beta;
321 LogDebug(
"EcalSim") <<
"Particle properties: " <<
"\n"
322 <<
" charge = " << charge
323 <<
" beta = " <<
beta;
327 if ( meanNumberOfPhotons <= 0.0 ) {
328 LogDebug(
"EcalSim") <<
"Mean number of photons is zero: " << meanNumberOfPhotons
329 <<
", stopping here";
330 return cherenkovEnergy;
334 meanNumberOfPhotons *= aStep->GetStepLength();
337 int numPhotons =
static_cast<int>( G4Poisson(meanNumberOfPhotons) );
339 if ( numPhotons <= 0 ) {
340 LogDebug(
"EcalSim") <<
"Poission number of photons is zero: " << numPhotons
341 <<
", stopping here";
342 return cherenkovEnergy;
346 double Pmin = Rindex->GetMinPhotonEnergy();
347 double Pmax = Rindex->GetMaxPhotonEnergy();
348 double dp = Pmax - Pmin;
349 double maxCos = BetaInverse / Rindex->GetMaxProperty();
350 double maxSin2 = (1.0 - maxCos) * (1.0 + maxCos);
353 for (
int iPhoton = 0; iPhoton<numPhotons; ++iPhoton ) {
357 double sampledMomentum, sampledRI;
358 double cosTheta, sin2Theta;
362 randomNumber = G4UniformRand();
363 sampledMomentum = Pmin + randomNumber * dp;
364 sampledRI = Rindex->GetProperty(sampledMomentum);
365 cosTheta = BetaInverse / sampledRI;
367 sin2Theta = (1.0 - cosTheta)*(1.0 + cosTheta);
368 randomNumber = G4UniformRand();
370 }
while (randomNumber*maxSin2 > sin2Theta);
374 randomNumber = G4UniformRand();
376 double phi = twopi*randomNumber;
377 double sinPhi =
sin(phi);
378 double cosPhi =
cos(phi);
383 double sinTheta =
sqrt(sin2Theta);
384 double px = sinTheta*cosPhi;
385 double py = sinTheta*sinPhi;
386 double pz = cosTheta;
387 G4ThreeVector photonDirection(px, py, pz);
390 photonDirection.rotateUz(p0);
393 randomNumber = G4UniformRand();
394 G4ThreeVector photonPosition = x0 + randomNumber * aStep->GetDeltaPosition();
395 G4ThreeVector photonMomentum = sampledMomentum*photonDirection;
402 px_[iPhoton] = photonMomentum.x();
403 py_[iPhoton] = photonMomentum.y();
404 pz_[iPhoton] = photonMomentum.z();
405 x_[iPhoton] = photonPosition.x();
406 y_[iPhoton] = photonPosition.y();
407 z_[iPhoton] = photonPosition.z();
414 return cherenkovEnergy;
424 const G4Material* aMaterial,
425 const G4MaterialPropertyVector* Rindex )
const
427 const G4double rFact = 369.81/(eV * cm);
429 if( beta <= 0.0 )
return 0.0;
431 double BetaInverse = 1./
beta;
438 double Pmin = Rindex->GetMinPhotonEnergy();
439 double Pmax = Rindex->GetMaxPhotonEnergy();
442 double nMin = Rindex->GetMinProperty();
443 double nMax = Rindex->GetMaxProperty();
448 double dp = 0., ge = 0., CAImin = 0.;
451 if ( nMax < BetaInverse) { }
454 else if (nMin > BetaInverse) {
464 Pmin = Rindex->GetPhotonEnergy(BetaInverse);
470 ge = CAImax - CAImin;
475 double numPhotons = rFact * charge/eplus * charge/eplus *
476 (dp - ge * BetaInverse*BetaInverse);
478 LogDebug(
"EcalSim") <<
"@SUB=getAverageNumberOfPhotons"
479 <<
"CAImin = " << CAImin <<
"\n"
480 <<
"CAImax = " << CAImax <<
"\n"
481 <<
"dp = " << dp <<
", ge = " << ge <<
"\n"
482 <<
"numPhotons = " << numPhotons;
496 std::string pbWO2Name(
"E_PbWO4");
497 if ( pbWO2Name != aMaterial->GetName() ) {
499 <<
"expecting " << pbWO2Name
500 <<
", got " << aMaterial->GetName();
504 G4MaterialPropertiesTable*
table =
new G4MaterialPropertiesTable();
508 const int nEntries = 14;
509 double PhotonEnergy[nEntries] = { 1.7712*eV, 1.8368*eV, 1.90745*eV, 1.98375*eV, 2.0664*eV,
510 2.15625*eV, 2.25426*eV, 2.3616*eV, 2.47968*eV, 2.61019*eV,
511 2.75521*eV, 2.91728*eV, 3.09961*eV, 3.30625*eV };
512 double RefractiveIndex[nEntries] = { 2.17728, 2.18025, 2.18357, 2.18753, 2.19285,
513 2.19813, 2.20441, 2.21337, 2.22328, 2.23619,
514 2.25203, 2.27381, 2.30282, 2.34666 };
516 table->AddProperty(
"RINDEX", PhotonEnergy, RefractiveIndex, nEntries );
517 aMaterial->SetMaterialPropertiesTable(table);
522 std::auto_ptr<G4PhysicsOrderedFreeVector>(
new G4PhysicsOrderedFreeVector() );
525 double currentRI = RefractiveIndex[
index];
526 double currentPM = PhotonEnergy[
index];
527 double currentCAI = 0.0;
529 double prevPM = currentPM;
530 double prevCAI = currentCAI;
531 double prevRI = currentRI;
532 while ( ++index < nEntries ) {
533 currentRI = RefractiveIndex[
index];
534 currentPM = PhotonEnergy[
index];
535 currentCAI = 0.5*(1.0/(prevRI*prevRI) + 1.0/(currentRI*currentRI));
536 currentCAI = prevCAI + (currentPM - prevPM) * currentCAI;
541 prevCAI = currentCAI;
545 LogDebug(
"EcalSim") <<
"Material properties set for " << aMaterial->GetName();
558 const G4ThreeVector&
x,
559 const G4Step* aStep )
572 G4StepPoint* stepPoint = aStep->GetPreStepPoint();
573 G4LogicalVolume* lv = stepPoint->GetTouchable()->GetVolume(0)->GetLogicalVolume();
574 G4String nameVolume= lv->GetName();
578 double dapd = 0.5 * crlength - x.x();
579 double y = p.y()/p.x()*dapd;
581 LogDebug(
"EcalSim") <<
"Distance to APD: " << dapd
582 <<
" - y at APD: " <<
y;
585 if ( fabs(y)>crwidth*0.5 ) {
590 double waveLength = p.mag()*1.239e8;
595 LogDebug(
"EcalSim") <<
"Wavelength: " << waveLength <<
" - Energy: " <<
energy;
G4ThreeVector setToLocal(G4ThreeVector, const G4VTouchable *)
T getParameter(std::string const &) const
T getUntrackedParameter(std::string const &, T const &) const
const std::vector< double > & parameters(void) const
Give the parameters of the solid.
const DDLogicalPart & logicalPart() const
The logical-part of the current node in the filtered-view.
void addFilter(const DDFilter &, log_op op=AND)
virtual G4bool getStepInfo(G4Step *aStep)
std::pair< double, double > Doubles
virtual bool ProcessHits(G4Step *step, G4TouchableHistory *tHistory)
Sin< T >::type sin(const T &t)
bool setPbWO2MaterialProperties_(G4Material *aMaterial)
Sets material properties at run-time...
std::auto_ptr< G4PhysicsOrderedFreeVector > chAngleIntegrals_
Table of Cherenkov angle integrals vs photon momentum.
const DDSolid & solid(void) const
Returns a reference object of the solid being the shape of this LogicalPart.
virtual uint32_t setDetUnitId(G4Step *)
type of data representation of DDCompactView
The Signals That Services Can Subscribe To This is based on ActivityRegistry and is current per Services can connect to the signals distributed by the ActivityRegistry in order to monitor the activity of the application Each possible callback has some defined which we here list in angle e g
A DDSolid represents the shape of a part.
const double getAverageNumberOfPhotons_(const double charge, const double beta, const G4Material *aMaterial, const G4MaterialPropertyVector *rIndex) const
Returns average number of photons created by track.
bool next()
set current node to the next node in the filtered tree
Cos< T >::type cos(const T &t)
DreamSD(G4String, const DDCompactView &, SensitiveDetectorCatalog &, edm::ParameterSet const &, const SimTrackManager *)
DDSolidShape shape(void) const
The type of the solid.
double getAttenuation(G4Step *aStep, double birk1, double birk2, double birk3)
G4MaterialPropertiesTable * materialPropertiesTable
const double getPhotonEnergyDeposit_(const G4ParticleMomentum &p, const G4ThreeVector &x, const G4Step *aStep)
Returns energy deposit for a given photon.
const double crystalWidth(G4LogicalVolume *) const
void setID(uint32_t unitID, double timeSlice, int trackID, uint16_t depth=0)
G4StepPoint * preStepPoint
double cherenkovDeposit_(G4Step *aStep)
Returns the total energy due to Cherenkov radiation.
bool firstChild()
set the current node to the first child ...
T * make() const
make new ROOT object
void setCriteria(const DDValue &nameVal, comp_op, log_op l=AND, bool asString=true, bool merged=true)
const double crystalLength(G4LogicalVolume *) const
void initMap(G4String, const DDCompactView &)
const std::string & name() const
Returns the name.
double curve_LY(G4Step *, int)
static const double getEfficiency(const double &waveLengthNm)
Return efficiency for given photon wavelength (in nm)
CaloG4Hit * createNewHit()
The DDGenericFilter is a runtime-parametrized Filter looking on DDSpecifcs.