11 #include <pxd/modules/pxdBackground/PXDMCBgTupleProducerModule.h>
12 #include <framework/datastore/DataStore.h>
13 #include <framework/datastore/StoreObjPtr.h>
14 #include <framework/datastore/StoreArray.h>
15 #include <framework/dataobjects/BackgroundMetaData.h>
16 #include <pxd/reconstruction/PXDGainCalibrator.h>
17 #include <pxd/reconstruction/PXDPixelMasker.h>
19 #include <pxd/dataobjects/PXDDigit.h>
20 #include <pxd/dataobjects/PXDCluster.h>
21 #include <boost/format.hpp>
44 , m_hasPXDData(false), m_componentTime(0)
47 setDescription(
"PXD background tuple producer module");
48 addParam(
"integrationTime", m_integrationTime,
"PXD integration time in micro seconds",
double(20));
49 addParam(
"outputFileName", m_outputFileName,
"Output file name",
string(
"beast_tuple.root"));
50 addParam(
"maskDeadPixels", m_maskDeadPixels,
"Correct bg rates by known dead pixels",
bool(
true));
51 addParam(
"nBinsU", m_nBinsU,
"Number of regions per sensor along u side",
int(1));
52 addParam(
"nBinsV", m_nBinsV,
"Number of regions per sensor along v side",
int(6));
53 addParam(
"overrideComponentTime", m_overrideComponentTime,
"User specified component time in micro seconds",
double(0.0));
58 void PXDMCBgTupleProducerModule::initialize()
66 m_storeDigitsName = storeDigits.
getName();
67 m_storeBgMetaDataName = storeBgMetaData.
getName();
70 m_integrationTime *= Unit::us;
72 m_overrideComponentTime *= Unit::us;
78 auto gTools = VXD::GeoCache::getInstance().getGeoTools();
79 if (gTools->getNumberOfPXDLayers() == 0) {
80 B2WARNING(
"Missing geometry for PXD, PXD-masking is skiped.");
82 int nPXDSensors = gTools->getNumberOfPXDSensors();
85 for (
int i = 0; i < nPXDSensors; i++) {
86 VxdID sensorID = gTools->getSensorIDFromPXDIndex(i);
89 m_sensorData[sensorID].m_regionExpoMap = vector<double>(m_nBinsU * m_nBinsV, 0);
90 m_sensorData[sensorID].m_regionDoseMap = vector<double>(m_nBinsU * m_nBinsV, 0);
91 m_sensorData[sensorID].m_regionSoftPhotonFluxMap = vector<double>(m_nBinsU * m_nBinsV, 0);
92 m_sensorData[sensorID].m_regionChargedParticleFluxMap = vector<double>(m_nBinsU * m_nBinsV, 0);
93 m_sensorData[sensorID].m_regionHardPhotonFluxMap = vector<double>(m_nBinsU * m_nBinsV, 0);
97 void PXDMCBgTupleProducerModule::beginRun()
100 for (
auto const& pair2 : m_sensorData) {
101 auto const& sensorID = pair2.first;
102 auto info = getInfo(sensorID);
105 m_sensitivePixelMap[sensorID] = info.getUCells() * info.getVCells();
107 m_sensitiveAreaMap[sensorID] = getSensorArea(sensorID);
109 for (
int uBin = 0; uBin < m_nBinsU; ++uBin) {
110 for (
int vBin = 0; vBin < m_nBinsV; ++vBin) {
111 std::pair<VxdID, int> key(sensorID, getRegionID(uBin, vBin));
113 m_regionSensitivePixelMap[key] = info.getUCells() * info.getVCells() / m_nBinsU / m_nBinsV;
115 m_regionSensitiveAreaMap[key] = getRegionArea(sensorID, vBin);
119 if (m_maskDeadPixels) {
120 for (
int ui = 0; ui < info.getUCells(); ++ui) {
121 for (
int vi = 0; vi < info.getVCells(); ++vi) {
122 if (PXD::PXDPixelMasker::getInstance().pixelDead(sensorID, ui, vi)
123 || !PXD::PXDPixelMasker::getInstance().pixelOK(sensorID, ui, vi)) {
124 m_sensitivePixelMap[sensorID] -= 1;
125 m_sensitiveAreaMap[sensorID] -= info.getVPitch(info.getVCellPosition(vi)) * info.getUPitch();
126 int uBin = PXDGainCalibrator::getInstance().getBinU(sensorID, ui, vi, m_nBinsU);
127 int vBin = PXDGainCalibrator::getInstance().getBinV(sensorID, vi, m_nBinsV);
128 std::pair<VxdID, int> key(sensorID, getRegionID(uBin, vBin));
129 m_regionSensitivePixelMap[key] -= 1;
130 m_regionSensitiveAreaMap[key] -= info.getVPitch(info.getVCellPosition(vi)) * info.getUPitch();
136 if (m_sensitivePixelMap[sensorID] == 0) {
137 B2WARNING(
"All pixels from Sensor=" << sensorID <<
" are masked.");
140 for (
int uBin = 0; uBin < m_nBinsU; ++uBin) {
141 for (
int vBin = 0; vBin < m_nBinsV; ++vBin) {
142 std::pair<VxdID, int> key(sensorID, getRegionID(uBin, vBin));
143 if (m_regionSensitivePixelMap[key] == 0) {
144 B2WARNING(
"All pixels from subregion uBin=" << uBin <<
" vBin=" << vBin <<
" on Sensor=" << sensorID <<
" are masked.");
152 void PXDMCBgTupleProducerModule::event()
160 m_componentTime = storeBgMetaData->getRealTime();
163 std::map<VxdID, double> occupancyMap;
170 for (
const PXDDigit& storeDigit : storeDigits) {
171 VxdID sensorID = storeDigit.getSensorID();
172 double ADUToEnergy = PXDGainCalibrator::getInstance().getADUToEnergy(sensorID, storeDigit.getUCellID(), storeDigit.getVCellID());
173 double hitEnergy = storeDigit.getCharge() * ADUToEnergy;
175 if (m_sensitivePixelMap[sensorID] != 0) {
176 occupancyMap[sensorID] += 1.0 / m_sensitivePixelMap[sensorID];
178 m_sensorData[sensorID].m_dose += (hitEnergy / Unit::J);
179 m_sensorData[sensorID].m_expo += hitEnergy;
181 int uBin = PXDGainCalibrator::getInstance().getBinU(sensorID, storeDigit.getUCellID(), storeDigit.getVCellID(), m_nBinsU);
182 int vBin = PXDGainCalibrator::getInstance().getBinV(sensorID, storeDigit.getVCellID(), m_nBinsV);
183 int regionID = getRegionID(uBin, vBin);
184 m_sensorData[sensorID].m_regionDoseMap[regionID] += (hitEnergy / Unit::J);
185 m_sensorData[sensorID].m_regionExpoMap[regionID] += hitEnergy;
188 for (
auto& pair : m_sensorData) {
189 auto& sensorID = pair.first;
190 auto& bgdata = pair.second;
193 if (occupancyMap.find(sensorID) != occupancyMap.end()) {
194 bgdata.m_meanOccupancy += occupancyMap[sensorID];
198 for (
const PXDCluster& cluster : storeClusters) {
200 VxdID sensorID = cluster.getSensorID();
201 auto info = getInfo(sensorID);
203 auto cluster_uID = info.getUCellID(cluster.getU());
204 auto cluster_vID = info.getVCellID(cluster.getV());
205 int uBin = PXDGainCalibrator::getInstance().getBinU(sensorID, cluster_uID, cluster_vID, m_nBinsU);
206 int vBin = PXDGainCalibrator::getInstance().getBinV(sensorID, cluster_vID, m_nBinsV);
207 int regionID = getRegionID(uBin, vBin);
208 double ADUToEnergy = PXDGainCalibrator::getInstance().getADUToEnergy(sensorID, cluster_uID, cluster_vID);
209 double clusterEnergy = cluster.getCharge() * ADUToEnergy;
211 if (cluster.getSize() == 1 && clusterEnergy < 10000 * Unit::eV && clusterEnergy > 6000 * Unit::eV) {
212 m_sensorData[sensorID].m_softPhotonFlux += 1.0;
213 m_sensorData[sensorID].m_regionSoftPhotonFluxMap[regionID] += 1.0;
214 }
else if (cluster.getSize() == 1 && clusterEnergy > 10000 * Unit::eV) {
215 m_sensorData[sensorID].m_hardPhotonFlux += 1.0;
216 m_sensorData[sensorID].m_regionHardPhotonFluxMap[regionID] += 1.0;
217 }
else if (cluster.getSize() > 1 && clusterEnergy > 10000 * Unit::eV) {
218 m_sensorData[sensorID].m_chargedParticleFlux += 1.0;
219 m_sensorData[sensorID].m_regionChargedParticleFluxMap[regionID] += 1.0;
224 void PXDMCBgTupleProducerModule::terminate()
228 TFile* rfile =
new TFile(m_outputFileName.c_str(),
"RECREATE");
229 TTree* treeBEAST =
new TTree(
"tout",
"BEAST data tree");
231 double currentComponentTime = m_componentTime;
232 if (m_overrideComponentTime > 0.0) currentComponentTime = m_overrideComponentTime;
234 B2RESULT(
"Total real time is " << currentComponentTime / Unit::us <<
" microseconds.");
235 B2RESULT(
"This is equivalent to " << currentComponentTime / m_integrationTime <<
" random triggered events.");
237 for (
auto& pair : m_sensorData) {
238 auto& sensorID = pair.first;
239 auto& bgdata = pair.second;
241 double currentSensorMass = m_sensitiveAreaMap[sensorID] * info.getThickness() * c_densitySi;
242 double currentSensorArea = m_sensitiveAreaMap[sensorID];
245 m_sensorData[sensorID].m_meanOccupancy = bgdata.m_meanOccupancy * (m_integrationTime / currentComponentTime);
247 if (currentSensorArea > 0) {
248 m_sensorData[sensorID].m_dose *= (1.0 / (currentComponentTime / Unit::s)) * (1000 / currentSensorMass);
249 m_sensorData[sensorID].m_expo *= (1.0 / currentSensorArea) * (1.0 / (currentComponentTime / Unit::s));
250 m_sensorData[sensorID].m_softPhotonFlux *= (1.0 / currentSensorArea) * (1.0 / (currentComponentTime / Unit::s));
251 m_sensorData[sensorID].m_hardPhotonFlux *= (1.0 / currentSensorArea) * (1.0 / (currentComponentTime / Unit::s));
252 m_sensorData[sensorID].m_chargedParticleFlux *= (1.0 / currentSensorArea) * (1.0 / (currentComponentTime / Unit::s));
254 for (
int regionID = 0; regionID < m_nBinsU * m_nBinsV; ++regionID) {
255 std::pair<VxdID, int> key(sensorID, regionID);
256 double currentRegionMass = m_regionSensitiveAreaMap[key] * info.getThickness() * c_densitySi;
257 double currentRegionArea = m_regionSensitiveAreaMap[key];
258 if (currentRegionArea > 0) {
259 m_sensorData[sensorID].m_regionDoseMap[regionID] *= (1.0 / currentComponentTime) * (1000 / currentRegionMass);
260 m_sensorData[sensorID].m_regionExpoMap[regionID] *= (1.0 / currentRegionArea) * (1.0 / (currentComponentTime / Unit::s));
261 m_sensorData[sensorID].m_regionSoftPhotonFluxMap[regionID] *= (1.0 / currentRegionArea) * (1.0 / (currentComponentTime / Unit::s));
262 m_sensorData[sensorID].m_regionHardPhotonFluxMap[regionID] *= (1.0 / currentRegionArea) * (1.0 / (currentComponentTime / Unit::s));
263 m_sensorData[sensorID].m_regionChargedParticleFluxMap[regionID] *= (1.0 / currentRegionArea) * (1.0 /
264 (currentComponentTime / Unit::s));
270 string sensorDescr = sensorID;
271 treeBEAST->Branch(str(format(
"pxd_%1%_meanOccupancy") % sensorDescr).c_str(), &(bgdata.m_meanOccupancy));
272 treeBEAST->Branch(str(format(
"pxd_%1%_exposition") % sensorDescr).c_str(), &(bgdata.m_expo));
273 treeBEAST->Branch(str(format(
"pxd_%1%_dose") % sensorDescr).c_str(), &(bgdata.m_dose));
274 treeBEAST->Branch(str(format(
"pxd_%1%_softPhotonFlux") % sensorDescr).c_str(), &(bgdata.m_softPhotonFlux));
275 treeBEAST->Branch(str(format(
"pxd_%1%_hardPhotonFlux") % sensorDescr).c_str(), &(bgdata.m_hardPhotonFlux));
276 treeBEAST->Branch(str(format(
"pxd_%1%_chargedParticleFlux") % sensorDescr).c_str(),
277 &(bgdata.m_chargedParticleFlux));
279 for (
int uBin = 0; uBin < m_nBinsU; ++uBin) {
280 for (
int vBin = 0; vBin < m_nBinsV; ++vBin) {
281 int regionID = getRegionID(uBin, vBin);
282 treeBEAST->Branch(str(format(
"pxd_%1%_region_%2%_%3%_exposition") % sensorDescr % uBin % vBin).c_str(),
283 &(bgdata.m_regionExpoMap[regionID]));
284 treeBEAST->Branch(str(format(
"pxd_%1%_region_%2%_%3%_dose") % sensorDescr % uBin % vBin).c_str(),
285 &(bgdata.m_regionDoseMap[regionID]));
286 treeBEAST->Branch(str(format(
"pxd_%1%_region_%2%_%3%_softPhotonFlux") % sensorDescr % uBin % vBin).c_str(),
287 &(bgdata.m_regionSoftPhotonFluxMap[regionID]));
288 treeBEAST->Branch(str(format(
"pxd_%1%_region_%2%_%3%_hardPhotonFlux") % sensorDescr % uBin % vBin).c_str(),
289 &(bgdata.m_regionHardPhotonFluxMap[regionID]));
290 treeBEAST->Branch(str(format(
"pxd_%1%_region_%2%_%3%_chargedParticleFlux") % sensorDescr % uBin % vBin).c_str(),
291 &(bgdata.m_regionChargedParticleFluxMap[regionID]));
The PXD Cluster class This class stores all information about reconstructed PXD clusters The position...
PXD MC Background Tuple Producer.
Specific implementation of SensorInfo for PXD Sensors which provides additional pixel specific inform...
const std::string & getName() const
Return name under which the object is saved in the DataStore.
int getEntries() const
Get the number of objects in the array.
Type-safe access to single objects in the data store.
Class to uniquely identify a any structure of the PXD and SVD.
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Namespace to encapsulate code needed for simulation and reconstrucion of the PXD.
Abstract base class for different kinds of events.
Struct to hold data of an PXD sensor.