LISTSERV mailing list manager LISTSERV 16.5

Help for LCDET-SVN Archives


LCDET-SVN Archives

LCDET-SVN Archives


LCDET-SVN@LISTSERV.SLAC.STANFORD.EDU


View:

Message:

[

First

|

Previous

|

Next

|

Last

]

By Topic:

[

First

|

Previous

|

Next

|

Last

]

By Author:

[

First

|

Previous

|

Next

|

Last

]

Font:

Proportional Font

LISTSERV Archives

LISTSERV Archives

LCDET-SVN Home

LCDET-SVN Home

LCDET-SVN  October 2015

LCDET-SVN October 2015

Subject:

r3665 - in /projects/slic/trunk: include/MCParticleManager.hh src/MCParticleManager.cc

From:

[log in to unmask]

Reply-To:

Notification of commits to the lcdet svn repository <[log in to unmask]>

Date:

Thu, 1 Oct 2015 18:25:53 -0000

Content-Type:

text/plain

Parts/Attachments:

Parts/Attachments

text/plain (488 lines)

Author: [log in to unmask]
Date: Thu Oct  1 11:25:51 2015
New Revision: 3665

Log:
[SLIC-251] Preliminary rewrite of MCParticle event generation to correctly handle displaced vertices.

Modified:
    projects/slic/trunk/include/MCParticleManager.hh
    projects/slic/trunk/src/MCParticleManager.cc

Modified: projects/slic/trunk/include/MCParticleManager.hh
 =============================================================================
--- projects/slic/trunk/include/MCParticleManager.hh	(original)
+++ projects/slic/trunk/include/MCParticleManager.hh	Thu Oct  1 11:25:51 2015
@@ -32,6 +32,7 @@
 
 typedef map<G4int, MCParticle*> TrackIDMap;
 typedef map<MCParticle*, G4PrimaryParticle*> PrimaryParticleMap;
+typedef map<G4PrimaryParticle*, MCParticle*> MCParticleMap;
 typedef PrimaryParticleMap::iterator PrimaryParticleMapIterator;
 typedef set<MCParticle*> MCParticleSet;
 
@@ -102,7 +103,7 @@
     void reset() {
         _trackIDMap.clear();
         _primaryMap.clear();
-        _visitedParticles.clear();
+        _mcpMap.clear();
         _mcpVec = 0;
     }
 
@@ -116,7 +117,7 @@
     }
 
     /**
-     * Generate a G4Event from a collection of MCParticles.
+     * Generate an event from a collection of MCParticles.
      * @param[in] mcparticles The MCParticle collection.
      * @param[in] event The output G4Event.
      */
@@ -136,14 +137,27 @@
      */
     G4double smearZPosition(const G4double rms);
 
-private:
+    /**
+     * Create a primary particle from an MCParticle and recursively create primaries for all its daughters.
+     * @param[in] mcp the input MCParticle
+     * @return the primary particle converted from the MCParticle
+     */
+    std::set<G4PrimaryParticle*> createPrimary(G4PrimaryParticle* parent, MCParticle* mcp);
 
     /**
-     * Get the relevant G4ParticleParticle objects from an MCParticle.
-     * @param[in] p The MCParticle.
-     * @return The set of relevant G4PrimaryParticle objects.
+     * Create a primary vertex from an MCParticle.
+     * @param[in] mcp the input MCParticle
+     * @return the primary vertex converted from the MCParticle
      */
-    std::set<G4PrimaryParticle*> getRelevantParticles(MCParticle* p);
+    G4PrimaryVertex* createVertex(MCParticle* mcp);
+
+    /**
+     * Return true if particle is a daughter of another primary.
+     * @return true if particle is a daughter
+     */
+    bool isDaughter(G4PrimaryParticle* particle, const std::set<G4PrimaryParticle*>& primaries);
+
+private:
 
     /**
      * Set the MCParticle collection.
@@ -161,9 +175,9 @@
     PrimaryParticleMap _primaryMap;
 
     /**
-     * Set keeping track of which MCParticles have been processed in generator.
+     * Reverse map of G4PrimaryParticle to MCParticle.
      */
-    MCParticleSet _visitedParticles;
+    MCParticleMap _mcpMap;
 
     /**
      * Map of MCParticle to track ID.

Modified: projects/slic/trunk/src/MCParticleManager.cc
 =============================================================================
--- projects/slic/trunk/src/MCParticleManager.cc	(original)
+++ projects/slic/trunk/src/MCParticleManager.cc	Thu Oct  1 11:25:51 2015
@@ -5,181 +5,199 @@
 
 // Geant4
 #include "G4SystemOfUnits.hh"
+#include "globals.hh"
 #include "Randomize.hh"
 
 namespace slic {
 
 void MCParticleManager::generateEvent(LCCollectionVec* particles, G4Event* event) {
 
-    /* Apply Z smearing to input particles. */
+#if SLIC_LOG
+    log() << LOG::head << LOG::debug << "generating event " << event->GetEventID() << " from " << particles->size() << " MCParticles" << LOG::done;
+#endif
+
+    // Apply Z smearing to input particles.
+#if SLIC_LOG
+    log() << LOG::debug << "applying Z smearing: " << EventSourceManager::instance()->getZSmearing() << LOG::done;
+#endif
     G4double z = smearZPosition(EventSourceManager::instance()->getZSmearing());
 
-    /* Apply the Lorentz Transformation to input particles. */
+    /// Apply the Lorentz Transformation to input particles.
+#if SLIC_LOG
+    log() << LOG::debug << "applying Lorentz transform: " << EventSourceManager::instance()->getLorentzTransformationAngle() << LOG::done;
+#endif
     applyLorentzTransformation(particles, EventSourceManager::instance()->getLorentzTransformationAngle());
 
-    /*
-     * Process particles and add them to the primary vertex of the event.
-     */
-    G4ThreeVector particlePosition(0, 0, z);
-    G4double particleTime;
-    G4PrimaryVertex* vertex = new G4PrimaryVertex(particlePosition, particleTime);
-    for(size_t i=0; i < particles->size(); i++) {
-        MCParticle* mcp = (MCParticle*)(*particles)[i];
-        if (mcp->getParents().size()==0) {
-            //std::cout << "construct tree of relevant G4PrimaryParticles for initial MCParticle " << i << " " << std::flush;
-            std::set<G4PrimaryParticle*> primaries = getRelevantParticles(mcp);
-            //std::cout << "... finished" << std::endl;
-            std::set<G4PrimaryParticle*>::iterator primaryIt;
-            for (primaryIt = primaries.begin(); primaryIt != primaries.end(); primaryIt++) {
-                vertex->SetPrimary(*primaryIt);
-                //std::cout << "G4PrimaryParticle ("<< (*primaryIt)->GetPDGcode() << ") added to G4PrimaryVertex." << std::endl;
+    log() << LOG::endl;
+
+    // Loop over MCParticle input list.
+    for (size_t i = 0; i < particles->size(); i++) {
+
+        // Get the next MCParticle.
+        MCParticle* mcp = (MCParticle*) (*particles)[i];
+
+        // Debug print information about the particle.
+#ifdef SLIC_LOG
+        log() <<  LOG::debug << "processing MCParticle " << i << LOG::done;
+        log() << LOG::debug
+                << "PDG: " << mcp->getPDG() << LOG::endl
+                << "gen status: " << mcp->getGeneratorStatus() << LOG::endl
+                << "sim status: " << mcp->getSimulatorStatus() << LOG::endl
+                << "energy: " << mcp->getEnergy() << LOG::endl
+                << "time: " << mcp->getTime() << LOG::endl
+                << "daughters: " << mcp->getDaughters().size() << LOG::endl
+                << "vertex: ( " << mcp->getVertex()[0] << " " << mcp->getVertex()[1] << " " << mcp->getVertex()[2] << " )" << LOG::endl
+                << "p: ( " << mcp->getMomentum()[0] << ", " << mcp->getMomentum()[1] << ", " << mcp->getMomentum()[2] << " )" << LOG::endl
+                << "charge: " << mcp->getCharge() << LOG::endl
+                << "mass: " << mcp->getMass() << LOG::endl
+                << "daughters: " << mcp->getDaughters().size() << LOG::endl
+                << "parents: " << mcp->getParents().size()
+                << LOG::done;
+        log() << LOG::endl;
+#endif
+
+        // Only make vertices for particles without parents.
+        if (mcp->getParents().size() == 0) {
+
+#ifdef SLIC_LOG
+            log() << LOG::debug << "creating new vertex for MCParticle " << i << LOG::done;
+#endif
+
+            // Create a new primary vertex.
+            G4PrimaryVertex* vertex = 0;
+
+            if (mcp->getGeneratorStatus() == 1 || mcp->getGeneratorStatus() == 2) {
+                vertex = createVertex(mcp);
             }
-        }
-    }
-
-    /* Add the primary vertex to Geant4. */
-    event->AddPrimaryVertex(vertex);
-
-    /* Register the collection of MCParticles that was created. */
-    setMCParticleCollection(particles);
-}
-
-
-std::set<G4PrimaryParticle*> MCParticleManager::getRelevantParticles(MCParticle* p) {
-
-    //log each particle which has been called, to avoid double counting and increase efficiency
-    _visitedParticles.insert(p);
-    PrimaryParticleMap::iterator mcpIT;
-    std::set<G4PrimaryParticle*> relevantParticlesSet; //holds all relevant decay particles of p
-
-    /*
-     * Case #1:
-     *
-     * If p is a stable particle: search for it in LCIO2Geant4Map
-     *
-     * If exists in map: get the G4PrimaryParticle version of p from LCIO2Geant4Map
-     * Else: create G4PrimaryParticle version write it to LCIO2Geant4Map
-     *
-     * Finally: insert the G4PrimaryParticle verion of p into the relevant particle list
-     * and return the list.
-     */
-    if (p->getGeneratorStatus() == 1) {
-        G4PrimaryParticle* g4p;
-        mcpIT = _primaryMap.find(p);
-        if (mcpIT != _primaryMap.end()) {
-            g4p = mcpIT->second;
-        } else {
-            G4int IDHEP = p->getPDG();
-            G4double PHEP1 = p->getMomentum()[0];
-            G4double PHEP2 = p->getMomentum()[1];
-            G4double PHEP3 = p->getMomentum()[2];
-            G4double PHEP5 = p->getMass();
-            // create G4PrimaryParticle object
-            g4p = new G4PrimaryParticle(IDHEP, PHEP1 * GeV, PHEP2 * GeV, PHEP3 * GeV);
-            g4p->SetMass(PHEP5 * GeV);
-            _primaryMap[p] = g4p;
-            //std::cout << "*" << std::flush;
-        }
-        //std::cout << g4p->GetPDGcode() << std::flush;
-        relevantParticlesSet.insert(g4p);
-        return relevantParticlesSet;
-    }
-
-    /*
-     * CASE #2:
-     *
-     * If p is not stable: get first decay daughter and calculate the proper time of p.
-     *
-     * If proper time is not zero: particle is "relevant", since it carries vertex information.
-     *
-     * If p is already in LCIO2Geant4Map: take it.
-     * Else: create G4PrimaryParticle version of p and write it to LCIO2Geant4Map
-     *
-     * Collect all relevant particles of all daughters and setup "relevant mother-
-     * daughter-relations" between relevant decay particles and G4PrimaryParticle version of p
-     *
-     * Finally: insert only the G4PrimaryParticle version of p to the relevant particle list and return this "list".
-     * The added particle has now the correct pre-assigned decay products and (hopefully) the right lifetime.
-     */
-    else if (p->getDaughters().size() > 0) {  //fg: require that there is at least one daughter - otherwise forget the particle
-        // calculate proper time
-        MCParticle* dp = p->getDaughters()[0];
-
-        double proper_time = fabs((dp->getTime() - p->getTime()) * p->getMass()) / p->getEnergy();
-        //  fix by S.Morozov for real != 0
-        double aPrecision = dp->getTime() * p->getMass() / p->getEnergy();
-        double bPrecision = p->getTime() * p->getMass() / p->getEnergy();
-
-        double proper_time_Precision = pow(10, -DBL_DIG)*fmax(fabs(aPrecision),fabs(bPrecision));
-
-        bool isProperTimeZero = (proper_time <= proper_time_Precision);
-
-        // -- remove original --- if (proper_time != 0) {
-        if (isProperTimeZero == false) {
-
-            G4PrimaryParticle* g4p;
-            mcpIT = _primaryMap.find(p);
-            if (mcpIT != _primaryMap.end()) {
-                g4p = mcpIT->second;
-            } else {
-                G4int IDHEP = p->getPDG();
-                G4double PHEP1 = p->getMomentum()[0];
-                G4double PHEP2 = p->getMomentum()[1];
-                G4double PHEP3 = p->getMomentum()[2];
-                G4double PHEP5 = p->getMass();
-                // create G4PrimaryParticle object
-                g4p = new G4PrimaryParticle(IDHEP, PHEP1 * GeV, PHEP2 * GeV, PHEP3 * GeV);
-                g4p->SetMass(PHEP5 * GeV);
-                g4p->SetProperTime(proper_time * ns);
-                _primaryMap[p] = g4p;
-                std::set<G4PrimaryParticle*> vec3;
-                for (size_t i = 0; i < p->getDaughters().size(); i++) {
-                    if (_visitedParticles.count(p->getDaughters()[i]) == 0) {
-                        std::set<G4PrimaryParticle*> vec2 = getRelevantParticles(p->getDaughters()[i]);
-                        std::set<G4PrimaryParticle*>::iterator setit;
-                        for (setit = vec2.begin(); setit != vec2.end(); setit++) {
-                            vec3.insert(*setit);
-                        }
+
+#ifdef SLIC_LOG
+            log() << LOG::debug << "creating primary for MCParticle " << i << LOG::done;
+#endif
+
+            // Create a primary particle and recursively create its daughters.
+            const std::set<G4PrimaryParticle*> primaries = createPrimary(0, mcp);
+
+            // Loop over returned set of primary particles.
+            for (std::set<G4PrimaryParticle*>::const_iterator it = primaries.begin(); it != primaries.end(); it++) {
+
+                // Is this a top-level particle with no daughters?
+                if (!MCParticleManager::isDaughter((*it), primaries)) {
+
+                    // Create a new vertex if necessary.
+                    if (vertex == 0) {
+                        // Create vertex by looking up MCParticle from the primary.
+                        vertex = createVertex(_mcpMap[(*it)]);
                     }
-                }
-                std::set<G4PrimaryParticle*>::iterator setit;
-                for (setit = vec3.begin(); setit != vec3.end(); setit++) {
-                    g4p->SetDaughter(*setit);
-                }
-                //std::cout << "*" << std::flush;
-            }
-            //std::cout << g4p->GetPDGcode() << std::flush;
-            relevantParticlesSet.insert(g4p);
-            return relevantParticlesSet;
-        }
-        /* CASE #3:
-         *
-         * If p is not stable AND has zero lifetime: forget about p and retrieve all relevant
-         * decay particles of all daughters of p.
-         *
-         * In this case this step of recursion is just there for collecting all relevant decay
-         * products of daughters and returning them.
-         */
-        else {
-            for (size_t i = 0; i < p->getDaughters().size(); i++) {
-                if (_visitedParticles.count(p->getDaughters()[i]) == 0) {
-                    std::set<G4PrimaryParticle*> vec2 = getRelevantParticles(p->getDaughters()[i]);
-                    std::set<G4PrimaryParticle*>::iterator setit;
-                    for (setit = vec2.begin(); setit != vec2.end(); setit++) {
-                        relevantParticlesSet.insert(*setit);
-                    }
+
+                    // Add the primary particle to the vertex.
+                    vertex->SetPrimary(*it);
                 }
             }
-            return relevantParticlesSet;
-        }
-    }
-    return relevantParticlesSet;
+
+            // Add the vertex to the event.
+            event->AddPrimaryVertex(vertex);
+        }
+#ifdef SLIC_LOG
+        log() << "-------------------------------------------------" << LOG::endl;
+#endif
+    }
+
+    // Register the collection of MCParticles that was created.
+    setMCParticleCollection(particles);
+}
+
+std::set<G4PrimaryParticle*> MCParticleManager::createPrimary(G4PrimaryParticle* parent, MCParticle* mcp) {
+
+    // The MCParticle argument should not be null.
+    if (mcp == 0) {
+        G4Exception("", "", FatalException, "MCParticle is null.");
+    }
+
+    // Set of primaries that will be returned.
+    std::set<G4PrimaryParticle*> primaries;
+
+    G4PrimaryParticle* primary = 0;
+
+    // Is this primary not created yet and does it have a valid generator status?
+    if (_primaryMap.count(mcp) == 0 && (mcp->getGeneratorStatus() == 1 || mcp->getGeneratorStatus() == 2)) {
+
+        // Create the primary particle from the MCParticle's information.
+        primary = new G4PrimaryParticle();
+        primary->SetPDGcode(mcp->getPDG());
+        primary->SetCharge(mcp->getCharge());
+        primary->SetMass(mcp->getMass() * GeV);
+        const double* p = mcp->getMomentum();
+        primary->SetMomentum(p[0] * GeV, p[1] * GeV, p[2] * GeV);
+
+        // Set the proper time by subtracting from daughter's time.
+        if (mcp->getDaughters().size() > 0) {
+            MCParticle* dp = mcp->getDaughters()[0];
+            double properTime = fabs((dp->getTime() - mcp->getTime()) * mcp->getMass()) / mcp->getEnergy();
+#ifdef SLIC_LOG
+            log() << LOG::debug << "proper time set to " << properTime << LOG::done;
+#endif
+            primary->SetProperTime(mcp->getTime() * ns);
+        }
+
+        // Map primary to MCParticle.
+#ifdef SLIC_LOG
+            log() << LOG::debug << "mapping MCParticle " << mcp << " to primary " << primary << LOG::done;
+#endif
+        _primaryMap[mcp] = primary;
+
+        // Map MCParticle to primary.
+        _mcpMap[primary] = mcp;
+
+        if (parent != 0) {
+#ifdef SLIC_LOG
+            log() << LOG::debug << "setting parent primary on daughter" << LOG::done;
+#endif
+            parent->SetDaughter(primary);
+        }
+
+        primaries.insert(primary);
+    }
+
+    for (int i = 0; i < mcp->getDaughters().size(); i++) {
+#ifdef SLIC_LOG
+        log() << LOG::debug << "creating primary for dau particle " << i << LOG::done;
+#endif
+        std::set<G4PrimaryParticle*> daughters = createPrimary(primary, mcp->getDaughters()[i]);
+#ifdef SLIC_LOG
+        log() << LOG::debug << "created " << daughters.size() << " daughter primaries" << LOG::done;
+#endif
+
+        primaries.insert(daughters.begin(), daughters.end());
+    }
+#ifdef SLIC_LOG
+        log().getOutputStream().flush();
+#endif
+    return primaries;
+}
+
+G4PrimaryVertex* MCParticleManager::createVertex(MCParticle* mcp) {
+
+    // Get the particle's origin.
+    const double* particleVertex = mcp->getVertex();
+    G4ThreeVector particlePosition(particleVertex[0], particleVertex[1], particleVertex[2]);
+
+    // Get the particle's time.
+    G4double particleTime = mcp->getTime();
+
+    // Create a new vertex for this particle.
+#ifdef SLIC_LOG
+    log() << LOG::debug << "creating vertex at position " << particlePosition << " with time " << particleTime << LOG::done;
+#endif
+    G4PrimaryVertex* vertex = new G4PrimaryVertex(particlePosition, particleTime);
+
+    return vertex;
 }
 
 void MCParticleManager::applyLorentzTransformation(LCCollection* particles, const G4double alpha) {
 
-    if (alpha == 0)
+    if (alpha == 0) {
         return; // nothing to do
+    }
 
     //G4cout << "Applying Lorentz Transformation angle: " << alpha << G4endl;
 
@@ -206,7 +224,6 @@
 
             // after the transformation (boost in x-direction)
             pPrime[0] = betagamma * sqrt(sqr(p[0]) + sqr(p[1]) + sqr(p[2]) + sqr(m)) + gamma * p[0];
-
             pPrime[1] = p[1];
             pPrime[2] = p[2];
 
@@ -223,9 +240,23 @@
     if (rms != 0) {
         // Generate smeared Z position.
         z = G4RandGauss::shoot(0, rms/mm);
-        G4cout << "Smeared Z position: " << z << G4endl;
+        //G4cout << "Smeared Z position: " << z << G4endl;
     }
     return z;
 }
 
-};
+bool MCParticleManager::isDaughter(G4PrimaryParticle* particle, const std::set<G4PrimaryParticle*>& primaries) {
+    for (std::set<G4PrimaryParticle*>::iterator it = primaries.begin(); it != primaries.end(); it++) {
+        G4PrimaryParticle* dau = (*it)->GetDaughter();
+        while (dau != 0) {
+            if (dau == particle) {
+                return true;
+            }
+            dau = dau->GetNext();
+        }
+    }
+    return false;
+}
+
+}
+;

########################################################################
Use REPLY-ALL to reply to list

To unsubscribe from the LCDET-SVN list, click the following link:
https://listserv.slac.stanford.edu/cgi-bin/wa?SUBED1=LCDET-SVN&A=1

Top of Message | Previous Page | Permalink

Advanced Options


Options

Log In

Log In

Get Password

Get Password


Search Archives

Search Archives


Subscribe or Unsubscribe

Subscribe or Unsubscribe


Archives

January 2016
December 2015
November 2015
October 2015
September 2015
August 2015
July 2015
June 2015
May 2015
April 2015
March 2015
February 2015
January 2015
December 2014
November 2014
October 2014
September 2014
August 2014
July 2014
June 2014
May 2014
April 2014
March 2014
February 2014
January 2014
December 2013
November 2013

ATOM RSS1 RSS2



LISTSERV.SLAC.STANFORD.EDU

Secured by F-Secure Anti-Virus CataList Email List Search Powered by the LISTSERV Email List Manager

Privacy Notice, Security Notice and Terms of Use