StFmsSimulatorMaker
1.0.0
FMS fast simulator maker
|
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 }