30 #include "CLHEP/Units/PhysicalConstants.h"
50 constexpr
float maxNoiseSmall_eta1 = 2100;
51 constexpr
float minNoiseSmall_eta1 = 1000;
52 constexpr
float maxNoiseSmall_eta2 = 2600;
53 constexpr
float minNoiseSmall_eta2 = 2100;
55 constexpr
float maxNoiseLarge_eta1 = 2500;
56 constexpr
float minNoiseLarge_eta1 = 1200;
57 constexpr
float maxNoiseLarge_eta2 = 3000;
58 constexpr
float minNoiseLarge_eta2 = 2500;
82 return StatusCode::FAILURE;
111 strip_cfg.NSWCalib::MicroMegaGas::operator=(prop);
140 std::for_each(vmmReadoutMode.begin(), vmmReadoutMode.end(), [](
char&
c) { c = ::tolower(c); });
141 if (vmmReadoutMode.find(
"peak") != std::string::npos)
143 else if (vmmReadoutMode.find(
"threshold") != std::string::npos)
146 ATH_MSG_ERROR(
"MM_DigitizationTool can't interperet vmmReadoutMode option! (Should be 'peak' or 'threshold'.) Contains: "
148 return StatusCode::FAILURE;
152 std::for_each(vmmARTMode.begin(), vmmARTMode.end(), [](
char&
c) { c = ::tolower(c); });
153 if (vmmARTMode.find(
"peak") != std::string::npos)
155 else if (vmmARTMode.find(
"threshold") != std::string::npos)
159 "MM_DigitizationTool can't interperet vmmARTMode option! (Should be 'peak' or 'threshold'.) Contains: " <<
m_vmmARTMode);
167 int stripNumberShortestStrip{-1}, stripNumberLongestStrip{-1};
168 Identifier tmpIdShortestStrip{0},tmpIdLongestStrip{0};
169 float shortestStripLength{FLT_MAX}, longestStripLength{0};
174 tmpId =
m_idHelperSvc->mmIdHelper().channelID(
"MMS", 1, 1, 1, 1, 1);
176 stripNumberShortestStrip = (detectorReadoutElement->
getDesign(tmpId))->nMissedBottomEta + 1;
177 tmpIdShortestStrip =
m_idHelperSvc->mmIdHelper().channelID(
"MMS", 1, 1, 1, 1, stripNumberShortestStrip);
178 shortestStripLength = detectorReadoutElement->
stripLength(tmpIdShortestStrip);
180 stripNumberLongestStrip = (detectorReadoutElement->
getDesign(tmpId))->totalStrips - (detectorReadoutElement->
getDesign(tmpId))->nMissedTopEta;
181 tmpIdLongestStrip =
m_idHelperSvc->mmIdHelper().channelID(
"MMS", 1, 1, 1, 1, stripNumberLongestStrip);
182 longestStripLength = detectorReadoutElement->
stripLength(tmpIdLongestStrip);
188 noise_smallEta1.
slope = (maxNoiseSmall_eta1 - minNoiseSmall_eta1) / (longestStripLength - shortestStripLength);
189 noise_smallEta1.
intercept = minNoiseSmall_eta1 - noise_smallEta1.
slope* shortestStripLength;
195 tmpId =
m_idHelperSvc->mmIdHelper().channelID(
"MMS", 2, 1, 1, 1, 1);
196 detectorReadoutElement = muonGeoMgr->getMMReadoutElement(tmpId);
197 stripNumberShortestStrip = (detectorReadoutElement->
getDesign(tmpId))->nMissedBottomEta + 1;
198 tmpIdShortestStrip =
m_idHelperSvc->mmIdHelper().channelID(
"MMS", 2, 1, 1, 1, stripNumberShortestStrip);
199 shortestStripLength = detectorReadoutElement->
stripLength(tmpIdShortestStrip);
201 stripNumberLongestStrip = (detectorReadoutElement->
getDesign(tmpId))->totalStrips - (detectorReadoutElement->
getDesign(tmpId))->nMissedTopEta;
202 tmpIdLongestStrip =
m_idHelperSvc->mmIdHelper().channelID(
"MMS", 2, 1, 1, 1, stripNumberLongestStrip);
203 longestStripLength = detectorReadoutElement->
stripLength(tmpIdLongestStrip);
209 noise_smallEta2.
slope = (maxNoiseSmall_eta2 - minNoiseSmall_eta2) / (longestStripLength - shortestStripLength);
210 noise_smallEta2.
intercept = minNoiseSmall_eta2 - noise_smallEta2.
slope * shortestStripLength;
216 tmpId =
m_idHelperSvc->mmIdHelper().channelID(
"MML", 1, 1, 1, 1, 1);
217 detectorReadoutElement = muonGeoMgr->getMMReadoutElement(tmpId);
218 stripNumberShortestStrip = (detectorReadoutElement->
getDesign(tmpId))->nMissedBottomEta + 1;
219 tmpIdShortestStrip =
m_idHelperSvc->mmIdHelper().channelID(
"MML", 1, 1, 1, 1, stripNumberShortestStrip);
220 shortestStripLength = detectorReadoutElement->
stripLength(tmpIdShortestStrip);
222 stripNumberLongestStrip = (detectorReadoutElement->
getDesign(tmpId))->totalStrips - (detectorReadoutElement->
getDesign(tmpId))->nMissedTopEta;
223 tmpIdLongestStrip =
m_idHelperSvc->mmIdHelper().channelID(
"MML", 1, 1, 1, 1, stripNumberLongestStrip);
224 longestStripLength = detectorReadoutElement->
stripLength(tmpIdLongestStrip);
230 noise_largeEta1.
slope = (maxNoiseLarge_eta1 - minNoiseLarge_eta1) / (longestStripLength - shortestStripLength);
231 noise_largeEta1.
intercept = minNoiseLarge_eta1 - noise_largeEta1.
slope * shortestStripLength;
237 tmpId =
m_idHelperSvc->mmIdHelper().channelID(
"MML", 2, 1, 1, 1, 1);
238 detectorReadoutElement = muonGeoMgr->getMMReadoutElement(tmpId);
239 stripNumberShortestStrip = (detectorReadoutElement->
getDesign(tmpId))->nMissedBottomEta + 1;
240 tmpIdShortestStrip =
m_idHelperSvc->mmIdHelper().channelID(
"MML", 2, 1, 1, 1, stripNumberShortestStrip);
241 shortestStripLength = detectorReadoutElement->
stripLength(tmpIdShortestStrip);
243 stripNumberLongestStrip = (detectorReadoutElement->
getDesign(tmpId))->totalStrips - (detectorReadoutElement->
getDesign(tmpId))->nMissedTopEta;
244 tmpIdLongestStrip =
m_idHelperSvc->mmIdHelper().channelID(
"MML", 2, 1, 1, 1, stripNumberLongestStrip);
245 longestStripLength = detectorReadoutElement->
stripLength(tmpIdLongestStrip);
251 noise_largeEta2.
slope = (maxNoiseLarge_eta2 - minNoiseLarge_eta2) / (longestStripLength - shortestStripLength);
252 noise_largeEta2.
intercept = minNoiseLarge_eta2 - noise_largeEta2.
slope * shortestStripLength;
273 return StatusCode::SUCCESS;
280 ATH_MSG_DEBUG(
"MM_DigitizationTool::prepareEvent() called for " << nInputEvents <<
" input events");
288 return StatusCode::FAILURE;
291 return StatusCode::SUCCESS;
295 ATH_MSG_DEBUG(
"MM_DigitizationTool::in processBunchXing()" << bunchXing);
298 TimedHitCollList hitCollList;
301 hitCollList.empty()) {
303 return StatusCode::FAILURE;
312 for (; iColl != endColl; ++iColl) {
313 auto hitCollPtr = std::make_unique<MMSimHitCollection>(*iColl->second);
316 ATH_MSG_DEBUG(
"MMSimHitCollection found with " << hitCollPtr->size() <<
" hits");
322 return StatusCode::SUCCESS;
338 if (!hitCollection.
isValid()) {
339 ATH_MSG_ERROR(
"Could not get MMSimHitCollection container " << hitCollection.
name() <<
" from store " << hitCollection.
store());
340 return StatusCode::FAILURE;
346 ATH_MSG_DEBUG(
"MMSimHitCollection found with " << hitCollection->
size() <<
" hits");
347 return StatusCode::SUCCESS;
351 TimedHitCollList hitCollList;
354 if (hitCollList.empty()) {
356 return StatusCode::FAILURE;
366 return StatusCode::FAILURE;
374 while (iColl != endColl) {
380 return StatusCode::SUCCESS;
393 return StatusCode::SUCCESS;
409 return StatusCode::SUCCESS;
417 if (!muonGeoMgrHandle.isValid()) {
418 ATH_MSG_FATAL(
"Failed to retrieve the detector manager from the conditiosn store");
419 return StatusCode::FAILURE;
430 ATH_CHECK(sdoContainer.
record(std::make_unique<MuonSimDataCollection>()));
439 return StatusCode::FAILURE;
446 std::vector<std::unique_ptr<MmDigitCollection> > collections;
452 std::vector<MM_ElectronicsToolInput> v_stripDigitOutput;
461 const double eventTime = phit.
eventTime();
465 if (hitKineticEnergy <= 0)
continue;
469 const double globalHitTime = hit.
globalTime();
470 const double tofCorrection = globalHitPosition.mag() /
CLHEP::c_light;
471 const double bunchTime = globalHitTime - tofCorrection + eventTime;
473 const int hitID = hit.
MMId();
482 int simId = hit.
MMId();
483 layerID = simToOffline.
convert(simId);
487 bool acceptHit =
true;
496 ATH_MSG_DEBUG(
"> hitID " << hitID <<
" Hit bunch time " << bunchTime <<
" tot " << globalHitTime <<
" tof/G4 time "
497 << hit.
globalTime() <<
" globalHitPosition " << globalHitPosition <<
"hit: r "
498 << globalHitPosition.perp() <<
" z " << globalHitPosition.z() <<
" mclink " << particleLink
522 if (!detectorReadoutElement) {
526 const std::array<int, 4>& readoutSide=detectorReadoutElement->
getReadoutSide();
533 const std::string stName =
m_idHelperSvc->stationNameString(layerID);
556 if (inAngleCompliment_XZ < 0.0) inAngleCompliment_XZ += 180;
557 if (inAngleCompliment_YZ < 0.0) inAngleCompliment_YZ += 180;
560 float inAngle_XZ = 90. - inAngleCompliment_XZ;
561 float inAngle_YZ = 90. - inAngleCompliment_YZ;
565 <<
" Layer: " <<
m_muonHelper->
GetLayer(simId) <<
"\n\t\t\t inAngle_XZ (degrees): " << inAngle_XZ
566 <<
" inAngle_YZ (degrees): " << inAngle_YZ);
570 Amg::Vector2D positionOnSurfaceUnprojected{stripLayerPosition.x(), stripLayerPosition.y()};
576 if ((readoutSide).at(idHelper.gasGap(layerID) - 1) == 1) {
577 localDirectionTime = localDirection;
578 inAngle_XZ = (-inAngle_XZ);
580 localDirectionTime = surf.
transform().inverse().linear() * globalHitDirection;
583 int gasGap = idHelper.gasGap(layerID);
587 scale = -(stripLayerPosition.z() + shift) / localDirection.z();
589 scale = -(stripLayerPosition.z() - shift) / localDirection.z();
593 Amg::Vector2D positionOnSurface{hitOnSurface.x(), hitOnSurface.y()};
597 Amg::Vector3D hitAfterTimeShift(hitOnSurface.x(), hitOnSurface.y(), shiftTimeOffset);
598 Amg::Vector3D hitAfterTimeShiftOnSurface = hitAfterTimeShift - (shiftTimeOffset / localDirectionTime.z()) * localDirectionTime;
600 if (std::abs(hitAfterTimeShiftOnSurface.z()) > 0.1)
601 ATH_MSG_WARNING(
"Bad propagation to surface after time shift " << hitAfterTimeShiftOnSurface);
604 double scaleSDO = -stripLayerPosition.z() / localDirection.z();
605 Amg::Vector3D hitAtCenterOfGasGap = stripLayerPosition + scaleSDO * localDirection;
607 ATH_MSG_DEBUG(
"strip layer position z" << stripLayerPosition.z() <<
"hitAtCenterOfGasGap "
621 int stripNumber = detectorReadoutElement->
stripNumber(positionOnSurface, layerID);
624 if (stripNumber == -1) {
626 <<
m_idHelperSvc->mmIdHelper().print_to_string(layerID) <<
"\n\t\t with pos " << positionOnSurface <<
" z "
628 <<
" unprojectedStrip: " << detectorReadoutElement->
stripNumber(positionOnSurfaceUnprojected, layerID));
633 Identifier parentID = idHelper.parentID(layerID);
634 Identifier digitID = idHelper.channelID(parentID,
635 idHelper.multilayer(layerID),
636 idHelper.gasGap(layerID), stripNumber);
639 const IdentifierHash moduleHash =
m_idHelperSvc->moduleHash(layerID);
642 <<
static_cast<int>(moduleHash) <<
" " <<
m_idHelperSvc->toString(layerID)
646 double distToChannel = mmChannelDesign->
distanceToChannel(positionOnSurface, stripNumber);
650 int geoStripNumber = mmChannelDesign->
channelNumber(positionOnSurface);
651 if (geoStripNumber == -1)
ATH_MSG_WARNING(
"Failed to retrieve strip number");
654 if (!mmChannelDesign->
center(geoStripNumber, chPos)) {
655 ATH_MSG_DEBUG(
"Failed to retrieve channel position for closest strip number "
657 <<
". Can happen if hit was found in non-active strip. Will not digitize it, since in data, "
658 <<
"we would probably not find a cluster formed well enough to survive reconstruction.");
667 return StatusCode::FAILURE;
669 fieldCondObj->getInitializedCache(fieldCache);
674 fieldCache.
getField(hitOnSurfaceGlobal.data(), magneticField.data());
679 localMagneticField[
Amg::y] = -localMagneticField[
Amg::y];
691 stripNumber, distToChannel, inAngle_XZ, inAngle_YZ, localMagneticField,
694 idHelper.gasGap(layerID), eventTime + globalHitTime);
706 std::vector<MuonSimData::Deposit> deposits{deposit};
708 simData.setPosition(hitAtCenterOfGasGapGlobal);
709 simData.setTime(globalHitTime);
710 sdoContainer->insert(std::make_pair(digitID,
simData));
713 float gainFraction = 1.0;
716 Identifier
id = idHelper.channelID(layerID,
717 idHelper.multilayer(layerID),
718 idHelper.gasGap(layerID), stripNumber);
727 v_stripDigitOutput.push_back(stripDigitOutput);
733 if (v_stripDigitOutput.empty()) {
734 ATH_MSG_DEBUG(
"MM_DigitizationTool::doDigitization() -- there is no strip response on this VMM.");
749 <<
" is not a MM Identifier, skipping");
759 if (!electronicsOutputForReadout.isValid()) {
761 " there is no electronics response (peak finding mode) even though there is a strip response.");
765 for (
unsigned int firedCh = 0; firedCh < electronicsOutputForReadout.stripPos().
size(); ++firedCh) {
767 const int channel = electronicsOutputForReadout.stripPos()[firedCh];
768 float time = electronicsOutputForReadout.stripTime()[firedCh];
769 float charge = electronicsOutputForReadout.stripCharge()[firedCh];
771 const Identifier digitID = idHelper.channelID(stripDigitOutputAllHits.
digitID(),
772 idHelper.multilayer(stripDigitOutputAllHits.
digitID()),
773 idHelper.gasGap(stripDigitOutputAllHits.
digitID()),
779 bool acceptStrip =
true;
789 std::unique_ptr<MmDigit> newDigit = std::make_unique<MmDigit>(digitID,
time,
charge);
791 const IdentifierHash moduleHash =
m_idHelperSvc->moduleHash(digitID);
792 if (moduleHash >= collections.size()) {
793 collections.resize(moduleHash+1);
797 collections[moduleHash] = std::make_unique<MmDigitCollection>(
m_idHelperSvc->chamberId(digitID), moduleHash);
798 coll = collections[moduleHash].get();
802 v_stripDigitOutput.clear();
805 for (
size_t coll_hash = 0; coll_hash < collections.size(); ++coll_hash) {
806 if (collections[coll_hash]) {
815 return StatusCode::SUCCESS;
820 const EventContext& ctx = Gaudi::Hive::currentContext();
825 if (!readThresholds.isValid()) {
ATH_MSG_ERROR(
"Cannot find conditions data container for VMM thresholds!"); }
826 thresholdData = readThresholds.cptr();
830 if (!muonGeoMgrHandle.isValid()) {
ATH_MSG_FATAL(
"Failed to retrieve the detector manager from the conditiosn store"); }
833 std::vector<int> v_stripStripResponseAllHits;
834 std::vector<std::vector<float>> v_timeStripResponseAllHits;
835 std::vector<std::vector<float>> v_qStripResponseAllHits;
836 std::vector<float> v_stripThresholdResponseAllHits;
838 Identifier digitID = v_stripDigitOutput.at(0).digitID();
839 float max_kineticEnergy = 0.0;
842 for (
auto& i_stripDigitOutput : v_stripDigitOutput) {
844 if (i_stripDigitOutput.kineticEnergy() > max_kineticEnergy) {
845 digitID = i_stripDigitOutput.digitID();
846 max_kineticEnergy = i_stripDigitOutput.kineticEnergy();
849 for (
size_t i = 0;
i < i_stripDigitOutput.NumberOfStripsPos().
size(); ++
i) {
850 int strip_id = i_stripDigitOutput.NumberOfStripsPos().at(
i);
853 for (
size_t ii = 0; ii < v_stripStripResponseAllHits.size(); ++ii) {
854 if (v_stripStripResponseAllHits.at(ii) == strip_id) {
855 for (
size_t iii = 0; iii < i_stripDigitOutput.chipTime().at(
i).
size(); ++iii) {
856 v_timeStripResponseAllHits.at(ii).push_back(i_stripDigitOutput.chipTime().at(
i).at(iii));
857 v_qStripResponseAllHits.at(ii).push_back(i_stripDigitOutput.chipCharge().at(
i).at(iii));
863 v_stripStripResponseAllHits.push_back(strip_id);
864 v_timeStripResponseAllHits.push_back(i_stripDigitOutput.chipTime().at(
i));
865 v_qStripResponseAllHits.push_back(i_stripDigitOutput.chipCharge().at(
i));
870 if (!thresholdData->getThreshold(
id,
threshold))
871 ATH_MSG_ERROR(
"Cannot find retrieve VMM threshold from conditions data base!");
872 v_stripThresholdResponseAllHits.push_back(
threshold);
877 float stripLength = detectorReadoutElement->
stripLength(
id);
881 v_stripThresholdResponseAllHits.push_back(
threshold);
889 MM_ElectronicsToolInput stripDigitOutputAllHits(v_stripStripResponseAllHits, v_qStripResponseAllHits, v_timeStripResponseAllHits,
890 v_stripThresholdResponseAllHits, digitID, max_kineticEnergy);
892 return stripDigitOutputAllHits;