13 #include <pxd/modules/pxdBackground/PXDMCBgTupleProducerModule.h>
14 #include <framework/datastore/DataStore.h>
15 #include <framework/datastore/StoreObjPtr.h>
16 #include <framework/datastore/StoreArray.h>
17 #include <framework/dataobjects/BackgroundMetaData.h>
18 #include <pxd/reconstruction/PXDGainCalibrator.h>
19 #include <pxd/reconstruction/PXDPixelMasker.h>
21 #include <pxd/dataobjects/PXDDigit.h>
22 #include <pxd/dataobjects/PXDCluster.h>
23 #include <boost/format.hpp>
46 , m_hasPXDData(false), m_componentTime(0)
49 setDescription(
"PXD background tuple producer module");
50 addParam(
"integrationTime", m_integrationTime,
"PXD integration time in micro seconds",
double(20));
51 addParam(
"outputFileName", m_outputFileName,
"Output file name",
string(
"beast_tuple.root"));
52 addParam(
"maskDeadPixels", m_maskDeadPixels,
"Correct bg rates by known dead pixels",
bool(
true));
53 addParam(
"nBinsU", m_nBinsU,
"Number of regions per sensor along u side",
int(1));
54 addParam(
"nBinsV", m_nBinsV,
"Number of regions per sensor along v side",
int(6));
55 addParam(
"overrideComponentTime", m_overrideComponentTime,
"User specified component time in micro seconds",
double(0.0));
60 void PXDMCBgTupleProducerModule::initialize()
68 m_storeDigitsName = storeDigits.getName();
69 m_storeBgMetaDataName = storeBgMetaData.getName();
72 m_integrationTime *= Unit::us;
74 m_overrideComponentTime *= Unit::us;
80 auto gTools = VXD::GeoCache::getInstance().getGeoTools();
81 if (gTools->getNumberOfPXDLayers() == 0) {
82 B2WARNING(
"Missing geometry for PXD, PXD-masking is skiped.");
84 int nPXDSensors = gTools->getNumberOfPXDSensors();
87 for (
int i = 0; i < nPXDSensors; i++) {
88 VxdID sensorID = gTools->getSensorIDFromPXDIndex(i);
91 m_sensorData[sensorID].m_regionExpoMap = vector<double>(m_nBinsU * m_nBinsV, 0);
92 m_sensorData[sensorID].m_regionDoseMap = vector<double>(m_nBinsU * m_nBinsV, 0);
93 m_sensorData[sensorID].m_regionSoftPhotonFluxMap = vector<double>(m_nBinsU * m_nBinsV, 0);
94 m_sensorData[sensorID].m_regionChargedParticleFluxMap = vector<double>(m_nBinsU * m_nBinsV, 0);
95 m_sensorData[sensorID].m_regionHardPhotonFluxMap = vector<double>(m_nBinsU * m_nBinsV, 0);
99 void PXDMCBgTupleProducerModule::beginRun()
102 for (
auto const& pair2 : m_sensorData) {
103 auto const& sensorID = pair2.first;
104 auto info = getInfo(sensorID);
107 m_sensitivePixelMap[sensorID] = info.getUCells() * info.getVCells();
109 m_sensitiveAreaMap[sensorID] = getSensorArea(sensorID);
111 for (
int uBin = 0; uBin < m_nBinsU; ++uBin) {
112 for (
int vBin = 0; vBin < m_nBinsV; ++vBin) {
113 std::pair<VxdID, int> key(sensorID, getRegionID(uBin, vBin));
115 m_regionSensitivePixelMap[key] = info.getUCells() * info.getVCells() / m_nBinsU / m_nBinsV;
117 m_regionSensitiveAreaMap[key] = getRegionArea(sensorID, vBin);
121 if (m_maskDeadPixels) {
122 for (
int ui = 0; ui < info.getUCells(); ++ui) {
123 for (
int vi = 0; vi < info.getVCells(); ++vi) {
124 if (PXD::PXDPixelMasker::getInstance().pixelDead(sensorID, ui, vi)
125 || !PXD::PXDPixelMasker::getInstance().pixelOK(sensorID, ui, vi)) {
126 m_sensitivePixelMap[sensorID] -= 1;
127 m_sensitiveAreaMap[sensorID] -= info.getVPitch(info.getVCellPosition(vi)) * info.getUPitch();
128 int uBin = PXDGainCalibrator::getInstance().getBinU(sensorID, ui, vi, m_nBinsU);
129 int vBin = PXDGainCalibrator::getInstance().getBinV(sensorID, vi, m_nBinsV);
130 std::pair<VxdID, int> key(sensorID, getRegionID(uBin, vBin));
131 m_regionSensitivePixelMap[key] -= 1;
132 m_regionSensitiveAreaMap[key] -= info.getVPitch(info.getVCellPosition(vi)) * info.getUPitch();
138 if (m_sensitivePixelMap[sensorID] == 0) {
139 B2WARNING(
"All pixels from Sensor=" << sensorID <<
" are masked.");
142 for (
int uBin = 0; uBin < m_nBinsU; ++uBin) {
143 for (
int vBin = 0; vBin < m_nBinsV; ++vBin) {
144 std::pair<VxdID, int> key(sensorID, getRegionID(uBin, vBin));
145 if (m_regionSensitivePixelMap[key] == 0) {
146 B2WARNING(
"All pixels from subregion uBin=" << uBin <<
" vBin=" << vBin <<
" on Sensor=" << sensorID <<
" are masked.");
154 void PXDMCBgTupleProducerModule::event()
162 m_componentTime = storeBgMetaData->getRealTime();
165 std::map<VxdID, double> occupancyMap;
172 for (
const PXDDigit& storeDigit : storeDigits) {
173 VxdID sensorID = storeDigit.getSensorID();
174 double ADUToEnergy = PXDGainCalibrator::getInstance().getADUToEnergy(sensorID, storeDigit.getUCellID(), storeDigit.getVCellID());
175 double hitEnergy = storeDigit.getCharge() * ADUToEnergy;
177 if (m_sensitivePixelMap[sensorID] != 0) {
178 occupancyMap[sensorID] += 1.0 / m_sensitivePixelMap[sensorID];
180 m_sensorData[sensorID].m_dose += (hitEnergy / Unit::J);
181 m_sensorData[sensorID].m_expo += hitEnergy;
183 int uBin = PXDGainCalibrator::getInstance().getBinU(sensorID, storeDigit.getUCellID(), storeDigit.getVCellID(), m_nBinsU);
184 int vBin = PXDGainCalibrator::getInstance().getBinV(sensorID, storeDigit.getVCellID(), m_nBinsV);
185 int regionID = getRegionID(uBin, vBin);
186 m_sensorData[sensorID].m_regionDoseMap[regionID] += (hitEnergy / Unit::J);
187 m_sensorData[sensorID].m_regionExpoMap[regionID] += hitEnergy;
190 for (
auto& pair : m_sensorData) {
191 auto& sensorID = pair.first;
192 auto& bgdata = pair.second;
195 if (occupancyMap.find(sensorID) != occupancyMap.end()) {
196 bgdata.m_meanOccupancy += occupancyMap[sensorID];
200 for (
const PXDCluster& cluster : storeClusters) {
202 VxdID sensorID = cluster.getSensorID();
203 auto info = getInfo(sensorID);
205 auto cluster_uID = info.getUCellID(cluster.getU());
206 auto cluster_vID = info.getVCellID(cluster.getV());
207 int uBin = PXDGainCalibrator::getInstance().getBinU(sensorID, cluster_uID, cluster_vID, m_nBinsU);
208 int vBin = PXDGainCalibrator::getInstance().getBinV(sensorID, cluster_vID, m_nBinsV);
209 int regionID = getRegionID(uBin, vBin);
210 double ADUToEnergy = PXDGainCalibrator::getInstance().getADUToEnergy(sensorID, cluster_uID, cluster_vID);
211 double clusterEnergy = cluster.getCharge() * ADUToEnergy;
213 if (cluster.getSize() == 1 && clusterEnergy < 10000 * Unit::eV && clusterEnergy > 6000 * Unit::eV) {
214 m_sensorData[sensorID].m_softPhotonFlux += 1.0;
215 m_sensorData[sensorID].m_regionSoftPhotonFluxMap[regionID] += 1.0;
216 }
else if (cluster.getSize() == 1 && clusterEnergy > 10000 * Unit::eV) {
217 m_sensorData[sensorID].m_hardPhotonFlux += 1.0;
218 m_sensorData[sensorID].m_regionHardPhotonFluxMap[regionID] += 1.0;
219 }
else if (cluster.getSize() > 1 && clusterEnergy > 10000 * Unit::eV) {
220 m_sensorData[sensorID].m_chargedParticleFlux += 1.0;
221 m_sensorData[sensorID].m_regionChargedParticleFluxMap[regionID] += 1.0;
226 void PXDMCBgTupleProducerModule::terminate()
230 TFile* rfile =
new TFile(m_outputFileName.c_str(),
"RECREATE");
231 TTree* treeBEAST =
new TTree(
"tout",
"BEAST data tree");
233 double currentComponentTime = m_componentTime;
234 if (m_overrideComponentTime > 0.0) currentComponentTime = m_overrideComponentTime;
236 B2RESULT(
"Total real time is " << currentComponentTime / Unit::us <<
" microseconds.");
237 B2RESULT(
"This is equivalent to " << currentComponentTime / m_integrationTime <<
" random triggered events.");
239 for (
auto& pair : m_sensorData) {
240 auto& sensorID = pair.first;
241 auto& bgdata = pair.second;
243 double currentSensorMass = m_sensitiveAreaMap[sensorID] * info.getThickness() * c_densitySi;
244 double currentSensorArea = m_sensitiveAreaMap[sensorID];
247 m_sensorData[sensorID].m_meanOccupancy = bgdata.m_meanOccupancy * (m_integrationTime / currentComponentTime);
249 if (currentSensorArea > 0) {
250 m_sensorData[sensorID].m_dose *= (1.0 / (currentComponentTime / Unit::s)) * (1000 / currentSensorMass);
251 m_sensorData[sensorID].m_expo *= (1.0 / currentSensorArea) * (1.0 / (currentComponentTime / Unit::s));
252 m_sensorData[sensorID].m_softPhotonFlux *= (1.0 / currentSensorArea) * (1.0 / (currentComponentTime / Unit::s));
253 m_sensorData[sensorID].m_hardPhotonFlux *= (1.0 / currentSensorArea) * (1.0 / (currentComponentTime / Unit::s));
254 m_sensorData[sensorID].m_chargedParticleFlux *= (1.0 / currentSensorArea) * (1.0 / (currentComponentTime / Unit::s));
256 for (
int regionID = 0; regionID < m_nBinsU * m_nBinsV; ++regionID) {
257 std::pair<VxdID, int> key(sensorID, regionID);
258 double currentRegionMass = m_regionSensitiveAreaMap[key] * info.getThickness() * c_densitySi;
259 double currentRegionArea = m_regionSensitiveAreaMap[key];
260 if (currentRegionArea > 0) {
261 m_sensorData[sensorID].m_regionDoseMap[regionID] *= (1.0 / currentComponentTime) * (1000 / currentRegionMass);
262 m_sensorData[sensorID].m_regionExpoMap[regionID] *= (1.0 / currentRegionArea) * (1.0 / (currentComponentTime / Unit::s));
263 m_sensorData[sensorID].m_regionSoftPhotonFluxMap[regionID] *= (1.0 / currentRegionArea) * (1.0 / (currentComponentTime / Unit::s));
264 m_sensorData[sensorID].m_regionHardPhotonFluxMap[regionID] *= (1.0 / currentRegionArea) * (1.0 / (currentComponentTime / Unit::s));
265 m_sensorData[sensorID].m_regionChargedParticleFluxMap[regionID] *= (1.0 / currentRegionArea) * (1.0 /
266 (currentComponentTime / Unit::s));
272 string sensorDescr = sensorID;
273 treeBEAST->Branch(str(format(
"pxd_%1%_meanOccupancy") % sensorDescr).c_str(), &(bgdata.m_meanOccupancy));
274 treeBEAST->Branch(str(format(
"pxd_%1%_exposition") % sensorDescr).c_str(), &(bgdata.m_expo));
275 treeBEAST->Branch(str(format(
"pxd_%1%_dose") % sensorDescr).c_str(), &(bgdata.m_dose));
276 treeBEAST->Branch(str(format(
"pxd_%1%_softPhotonFlux") % sensorDescr).c_str(), &(bgdata.m_softPhotonFlux));
277 treeBEAST->Branch(str(format(
"pxd_%1%_hardPhotonFlux") % sensorDescr).c_str(), &(bgdata.m_hardPhotonFlux));
278 treeBEAST->Branch(str(format(
"pxd_%1%_chargedParticleFlux") % sensorDescr).c_str(),
279 &(bgdata.m_chargedParticleFlux));
281 for (
int uBin = 0; uBin < m_nBinsU; ++uBin) {
282 for (
int vBin = 0; vBin < m_nBinsV; ++vBin) {
283 int regionID = getRegionID(uBin, vBin);
284 treeBEAST->Branch(str(format(
"pxd_%1%_region_%2%_%3%_exposition") % sensorDescr % uBin % vBin).c_str(),
285 &(bgdata.m_regionExpoMap[regionID]));
286 treeBEAST->Branch(str(format(
"pxd_%1%_region_%2%_%3%_dose") % sensorDescr % uBin % vBin).c_str(),
287 &(bgdata.m_regionDoseMap[regionID]));
288 treeBEAST->Branch(str(format(
"pxd_%1%_region_%2%_%3%_softPhotonFlux") % sensorDescr % uBin % vBin).c_str(),
289 &(bgdata.m_regionSoftPhotonFluxMap[regionID]));
290 treeBEAST->Branch(str(format(
"pxd_%1%_region_%2%_%3%_hardPhotonFlux") % sensorDescr % uBin % vBin).c_str(),
291 &(bgdata.m_regionHardPhotonFluxMap[regionID]));
292 treeBEAST->Branch(str(format(
"pxd_%1%_region_%2%_%3%_chargedParticleFlux") % sensorDescr % uBin % vBin).c_str(),
293 &(bgdata.m_regionChargedParticleFluxMap[regionID]));