StFmsSimulatorMaker  1.0.0
FMS fast simulator maker
StRoot/StFmsSimulatorMaker/StFmsSimulatorMaker.cxx
Go to the documentation of this file.
00001 // $Id$
00002 //
00003 // $Log$
00004 //
00011 #include "StFmsSimulatorMaker/StFmsSimulatorMaker.h"
00012 
00013 #include <algorithm>  // For std::fill(), std::max(), std::min()
00014 
00015 #include "St_base/StMessMgr.h"
00016 #include "StEvent/StEvent.h"
00017 #include "StEvent/StFmsCollection.h"
00018 #include "StEvent/StFmsHit.h"
00019 #include "StFmsDbMaker/StFmsDbMaker.h"
00020 #include "tables/St_g2t_emc_hit_Table.h"
00021 
00022 /* Constructor. */
00023 StFmsSimulatorMaker::StFmsSimulatorMaker(const Char_t* name) : StMaker(name) { }
00024 
00025 /* Process one event. */
00026 Int_t StFmsSimulatorMaker::Make() {
00027   // Check for the FMS database maker, bail out if it can't be located.
00028   if (!GetMaker("fmsDb")) {
00029     LOG_ERROR << "No StFmsDbMaker. StFmsDbMaker library not loaded?" << endm;
00030     return kStErr;
00031   }  // if
00032   // Get the existing StEvent, or add one if it doesn't exist.
00033   StEvent* event = static_cast<StEvent*>(GetDataSet("StEvent"));
00034   if (!event) {
00035     event = new StEvent;
00036     AddData(event);
00037   }  // if
00038   // Add an FMS collection to the event if one does not already exist.
00039   if (!event->fmsCollection()) {
00040     event->setFmsCollection(new StFmsCollection);
00041   }  // if
00042   // Digitize GEANT FPD/FMS hits
00043   fillStEvent(event);
00044   printStEventSummary(event);
00045   return kStOk;
00046 }
00047 
00048 /* Fill an event with StFmsHits. */
00049 void StFmsSimulatorMaker::fillStEvent(StEvent* event) {
00050   // Read the g2t table
00051   St_g2t_emc_hit* hitTable =
00052       static_cast<St_g2t_emc_hit*>(GetDataSet("g2t_fpd_hit"));
00053   if (!hitTable) {
00054     LOG_INFO << "g2t_fpd_hit table is empty" << endm;
00055     return;  // Nothing to do
00056   }  // if
00057   // Loop over FPD hits
00058   const Int_t nHits = hitTable->GetNRows();
00059   // Point to the first hit in the table
00060   const g2t_emc_hit_st* hitPointer = hitTable->GetTable();
00061   // Loop through hits, incrementing pointer each time
00062   for (Int_t i(0); i < nHits; ++i, ++hitPointer) {
00063     if (hitPointer) {
00064       event->fmsCollection()->addHit(makeFmsHit(*hitPointer));
00065     }  // if
00066   }  // for
00067 }
00068 
00069 /* Create and set all values in an StFmsHit from a g2t_emc_hit_st. */
00070 StFmsHit* StFmsSimulatorMaker::makeFmsHit(const g2t_emc_hit_st& hit) {
00071   // Existence of StFmsDbMaker was already checked in Make()
00072   // so we don't confirm the pointer again here.
00073   StFmsDbMaker* dbMaker = static_cast<StFmsDbMaker*>(GetMaker("fmsDb"));
00074   // Decode detector information from hit:
00075   const Int_t channel = hit.volume_id % 1000;
00076   const Int_t detectorId = getDetectorId(hit);
00077   // Get gain and correction from the database.
00078   Float_t gain = dbMaker->getGain(detectorId, channel);
00079   Float_t gainCorrection = dbMaker->getGainCorrection(detectorId, channel);
00080   // Check for ADC values outside the allowed range and cap.
00081   Float_t energy = hit.de;
00082   Int_t adc = static_cast<Int_t>(energy / (gain * gainCorrection) + 0.5);
00083   adc = std::max(adc, 0);  // Prevent negative ADC
00084   adc = std::min(adc, 4095);  // Cap maximum ADC = 4,095
00085   // Recalculate energy accounting for ADC range
00086   energy = adc * gain * gainCorrection;
00087   // Determine the QT crate, slot and channel for this detector and channel.
00088   Int_t qtCrate, qtSlot, qtChannel;
00089   dbMaker->getMap(detectorId, channel, &qtCrate, &qtSlot, &qtChannel);
00090   // Create the hit.
00091   Int_t tdc = 0;
00092   return new StFmsHit(detectorId, channel, qtCrate, qtSlot, qtChannel, adc,
00093                       tdc, energy);
00094 }
00095 
00096 /*
00097  Returns the standard ID for the detector containing a hit.
00098  
00099  Detector parameters are defined as follows in the database:
00100    Name                ID type ew ns nx ny
00101    FPD-north           0  0    0  0   7  7
00102    FPD-south           1  0    0  1   7  7
00103    FPD-north-preshower 2  1    0  0   7  1
00104    FPD-south-preshower 3  1    0  1   7  1
00105    FPD-north-smdv      4  2    0  0  48  1
00106    FPD-south-smdv      5  2    0  1  48  1
00107    FPD-north-smdh      6  3    0  0   1 48
00108    FMS-south-smdh      7  3    0  1   1 48
00109    FMS-north-large     8  4    1  0  17 34
00110    FMS-south-large     9  4    1  1  17 34
00111    FMS-north-small     10 0    1  0  12 24
00112    FMS-south-small     11 0    1  1  12 24
00113  where
00114    - ew is the east-or-west location: 0 = east (the FPD), 1 = west (the FMS)
00115    - ns is the north-or-south location: 0 = north, 1 = south
00116    - nx, ny is the number of x, y channels
00117    - type corresponds to:
00118       - 0 = Small cell
00119       - 1 = Preshower
00120       - 2 = SMD-V
00121       - 3 = SMD-H
00122       - 4 = Large cell
00123       - 5 = Hadron calorimetry
00124  See:
00125  http://online.star.bnl.gov/dbExplorer/# --> Geometry/fms/ChannelGeometry
00126  Look into pams/sim/g2t/g2t_volume_id.g
00127  and search for FLGR (small pbg) or FLXF (large pbg).
00128 
00129 Email from Akio describing decoding of the g2t volume ID, 16th Jan 2014:
00130 
00131  G2T volume id is currently
00132  id = ew*10000+nstb*1000+ch
00133  where
00134  ew: 1=fpd, 2=fms
00135  nstb for ew=1(FPD):
00136        1=north, 2=south, 3=top, 4=bottom
00137        5=north pbG preshower, 6=south pbg preshower
00138  nstb for ew=2(FMS):
00139        1=north large, 2=south large
00140        3=north small, 4=south small ch: channel#
00141 
00142  Once we add preshower, it will become
00143  id = det*100000 + ew*10000+nstb*1000+ch
00144  where
00145  det: 0=fpd/fms, 1 for PS
00146  ch:  will be devided into layer & ch for PS
00147  so fms/fpd volume id should NOT change at all.
00148  */
00149 Int_t StFmsSimulatorMaker::getDetectorId(const g2t_emc_hit_st& hit) const {
00150   const Int_t volumeId = hit.volume_id;
00151   // Decode volume ID into detector type, fpd/fms and north/south locations
00152   const Int_t fpdOrFms = (volumeId % 100000) / 10000;
00153   const Int_t module = (volumeId % 10000) / 1000;
00154   // FPD/FMS and north/south to determine the detector ID
00155   enum { kFpd = 1, kFms = 2, kNorth = 0, kSouth = 1 };
00156   switch (fpdOrFms) {
00157     case kFpd:
00158       switch (module) {
00159         case 1: return kFpdNorth;  // north
00160         case 2: return kFpdSouth;  // south
00161         case 5: return kFpdNorthPreshower;  // preshower north
00162         case 6: return kFpdSouthPreshower;  // preshower south
00163       }  // switch
00164       break;
00165     case kFms:
00166       switch (module) {
00167         case 1: return kFmsNorthLarge;  // north large cells
00168         case 2: return kFmsSouthLarge;  // south large cells
00169         case 3: return kFmsNorthSmall;  // north small cells
00170         case 4: return kFmsSouthSmall;  // south small cells
00171       }  // switch
00172       break;
00173   }  // switch
00174   return kFmsInvalidDetectorId;
00175 }
00176 
00177 /* Dump hit information to LOG_INFO. */
00178 void StFmsSimulatorMaker::printStEventSummary(const StEvent* event) {
00179   const Int_t NDETECTORS = 14;
00180   const Char_t* detectorNames[NDETECTORS] = {
00181       "FPD-North ",
00182       "FPD-South",
00183       "FPD-North-Pres",
00184       "FPD-South-Pres",
00185       "FPD-North-SMDV",
00186       "FPD-South-SMDV",
00187       "FPD-North-SMDH",
00188       "FPD-South-SMDH",
00189       "FMS-North-Large",
00190       "FMS-South-Large",
00191       "FMS-North-Small",
00192       "FMS-South-Small",
00193       "FHC-North",
00194       "FHC-South"
00195   };
00196   // Array of total hits per subdetector, initialised to all zeros
00197   Int_t nhits[NDETECTORS];
00198   std::fill(nhits, nhits + NDETECTORS, 0);
00199   // Array of total energy per sub-detector, initialised to all zeros
00200   Float_t detectorEnergy[NDETECTORS];
00201   std::fill(detectorEnergy, detectorEnergy + NDETECTORS, 0.f);
00202   // Sum number of hits and energies
00203   const StSPtrVecFmsHit& hits = event->fmsCollection()->hits();
00204   for (size_t i = 0; i < hits.size(); ++i) {
00205     const StFmsHit* hit = hits[i];
00206     if (Debug()) {
00207       hit->print();
00208     }  // if
00209     ++nhits[hit->detectorId()];
00210     detectorEnergy[hit->detectorId()] += hit->energy();
00211   }  // for
00212   // Print detectors summary
00213   LOG_INFO << "ID\tNAME\t\tNHITS\tENERGY" << endm;
00214   for (Int_t detectorId = 0; detectorId < NDETECTORS; ++detectorId) {
00215     LOG_INFO << detectorId << '\t' << detectorNames[detectorId] << '\t'
00216              << nhits[detectorId] << '\t' << detectorEnergy[detectorId] << endm;
00217   }  // for
00218 }