7 #include "GaudiKernel/ITHistSvc.h"
8 #include "GaudiKernel/IIncidentSvc.h"
19 #include <boost/geometry.hpp>
20 #include <boost/geometry/geometries/point_xy.hpp>
21 #include <boost/geometry/geometries/polygon.hpp>
32 m_detManager(nullptr) {
33 declareInterface<NSWL1::IPadTriggerLookupTool>(
this);
43 std::ofstream padGeoFile(
"NSWSectorPadsGeoDump.dat");
53 return StatusCode::SUCCESS;
59 if( inc.type()==IncidentType::BeginEvent ) {
68 std::vector<std::unique_ptr<PadTrigger>> &
triggers)
70 std::set<int> activeSides;
71 std::set<int> activeSectors;
73 std::for_each(pads.begin(),pads.end(),[&](
const std::shared_ptr<PadData>&
p){
74 activeSides.insert(p->sideId() );
75 activeSectors.insert(p->triggerSectorNumber());
80 for(
const int side : activeSides){
81 for(
const int sector : activeSectors){
90 return StatusCode::SUCCESS;
101 return StatusCode::FAILURE;
106 std::stringstream iss(
line );
108 std::vector<int> fullPattern;
110 fullPattern.push_back(
number );
114 std::vector<int> padsOnlyPattern(fullPattern.begin(), fullPattern.begin() + 8);
115 std::vector<int> bandAndPhiId(fullPattern.begin()+8, fullPattern.begin() + 10);
116 int bandId=bandAndPhiId.at(0);
117 int phiId=bandAndPhiId.at(1);
118 m_pats[padsOnlyPattern]=std::pair<int,int>(bandId,phiId);
123 return StatusCode::SUCCESS;
128 std::unordered_map<std::vector<int>,std::pair<int,int> ,
hashPattern> derivedCoincidencePatterns;
130 std::vector<int> innerIndices(4);
131 std::vector<int> outerIndices(4);
132 std::vector<int> allIndices(8);
133 std::iota(innerIndices.begin(), innerIndices.begin() + 4, 0);
134 std::iota(outerIndices.begin(), outerIndices.begin() + 4, 4);
135 std::iota(allIndices.begin(),allIndices.begin()+8,0);
137 for(
const auto& kv :
m_pats){
138 int bandid=kv.second.first;
139 int phiid=kv.second.second;
140 for(
int in : innerIndices ){
141 std::vector<int>
pattern=kv.first;
146 for(
int out :outerIndices){
149 derivedCoincidencePatterns[
pattern]=std::pair<int,int>(bandid,phiid);
154 for(
int i : allIndices){
155 std::vector<int>
pattern=kv.first;
157 derivedCoincidencePatterns[
pattern]=std::pair<int,int>(bandid,phiid);
161 m_pats.insert(derivedCoincidencePatterns.begin(),derivedCoincidencePatterns.end());
163 return StatusCode::SUCCESS;
185 std::vector<std::shared_ptr<PadData> > padsInThisWedge;
187 auto wedgeSelector=[=](
const std::shared_ptr<PadData>& pad)->
bool{
188 return pad->sideId() ==
side &&
189 pad->triggerSectorNumber() == sector &&
190 pad->multipletId() == wedge;
193 std::copy_if(pads.begin(),pads.end(),std::back_inserter(padsInThisWedge),[=](
const std::shared_ptr<PadData>& pad){ return wedgeSelector(pad);} );
195 if(padsInThisWedge.size()>100){
196 ATH_MSG_WARNING(
"Too many pad hits: ("<<padsInThisWedge.size()<<
")pad hits on side= "<<
side<<
" sector="<<sector<<
" wedge="<<wedge);
199 std::vector<std::shared_ptr<PadData> > padsOnLayer1;
200 std::vector<std::shared_ptr<PadData> > padsOnLayer2;
201 std::vector<std::shared_ptr<PadData> > padsOnLayer3;
202 std::vector<std::shared_ptr<PadData> > padsOnLayer4;
203 std::copy_if(padsInThisWedge.begin(),padsInThisWedge.end(),std::back_inserter(padsOnLayer1),[](
const std::shared_ptr<PadData>& pad){ return pad->gasGapId()==1;} );
204 std::copy_if(padsInThisWedge.begin(),padsInThisWedge.end(),std::back_inserter(padsOnLayer2),[](
const std::shared_ptr<PadData>& pad){ return pad->gasGapId()==2;} );
205 std::copy_if(padsInThisWedge.begin(),padsInThisWedge.end(),std::back_inserter(padsOnLayer3),[](
const std::shared_ptr<PadData>& pad){ return pad->gasGapId()==3;} );
206 std::copy_if(padsInThisWedge.begin(),padsInThisWedge.end(),std::back_inserter(padsOnLayer4),[](
const std::shared_ptr<PadData>& pad){ return pad->gasGapId()==4;} );
209 std::vector<std::vector<std::shared_ptr<PadData> >> padCombinationsInWedge;
211 std::vector< size_t> nHitsLayerWise={ padsOnLayer1.size(),padsOnLayer2.size(),padsOnLayer3.size(),padsOnLayer4.size() };
212 if(
std::count(nHitsLayerWise.begin(),nHitsLayerWise.end(),0)>1){
213 ATH_MSG_WARNING(
"Not enough layer hits to build a pattern at side="<<
side<<
" sector="<<sector);
214 return padCombinationsInWedge;
217 auto addEmptyLayerIfAny=[]( std::vector<std::shared_ptr<PadData> >& layerPads)->
void{
218 if(layerPads.empty()){
219 std::vector<std::shared_ptr<PadData>> emptyLayer;
220 std::shared_ptr<PadData> nullPad=std::make_shared<PadOfflineData>(
Identifier(0), 0, 0,
nullptr);
221 emptyLayer.push_back(nullPad);
222 layerPads=emptyLayer;
226 addEmptyLayerIfAny(padsOnLayer1);
227 addEmptyLayerIfAny(padsOnLayer2);
228 addEmptyLayerIfAny(padsOnLayer3);
229 addEmptyLayerIfAny(padsOnLayer4);
233 auto padBinaryLogic=[](
const std::shared_ptr<PadData>& padNext,
const std::shared_ptr<PadData>& padPrev)->
bool{
236 return std::abs(padNext->padNumber()-padPrev->padNumber() )==1 ||
237 std::abs(padNext->padNumber() -padPrev->padNumber() )==18 ||
238 std::abs(padNext->padNumber() -padPrev->padNumber() )==19 ||
239 std::abs(padNext->padNumber() -padPrev->padNumber() )==17 ||
240 (padNext->padNumber() -padPrev->padNumber() ==0);
245 auto allInSameModule=[](
const std::vector<std::shared_ptr<PadData>>& pads)->
bool{
246 if(pads.size()!=4)
return false;
249 for(
const std::shared_ptr<PadData>& pad : pads){
252 moduleIdFirst=pad->moduleId();
256 if(pad->moduleId()!=moduleIdFirst)
return false;
264 auto padTowerLogic=[&padBinaryLogic,&allInSameModule](
const std::vector<std::shared_ptr<PadData>>& pads)->
bool{
265 std::bitset<3> layerbits;
267 if(not allInSameModule(pads))
return false;
268 for(
unsigned i=0;
i<4;
i++){
269 if( padBinaryLogic(pads.at(
i),pads.at(
i+1)) ) layerbits.set(
i);
274 bool is4o4=
true ? std::count_if(pads.begin(),pads.end(),[](
const std::shared_ptr<PadData>&
p){ return p->padNumber()==nullPadNumber;})==0 :
false;
276 return layerbits.count()>=2;
279 return layerbits.count()==3;
283 auto sameModule=[](
const std::shared_ptr<PadData>& padNext,
const std::shared_ptr<PadData>& padPrev )->
bool{
285 else return (padNext->padNumber()/1000 == padPrev->padNumber()/1000);
292 for(
const std::shared_ptr<PadData>& pad1 : padsOnLayer1 ){
293 for(
const std::shared_ptr<PadData>& pad2 : padsOnLayer2 ){
294 if( !sameModule(pad2,pad1) )
continue;
295 for(
const std::shared_ptr<PadData>& pad3 : padsOnLayer3 ){
296 if( !sameModule(pad3,pad2) )
continue;
297 for(
const std::shared_ptr<PadData>& pad4 : padsOnLayer4 ){
298 if( !sameModule(pad4,pad3) )
continue;
299 std::vector<std::shared_ptr<PadData>> patt={pad1,pad2,pad3,pad4};
300 if(! padTowerLogic(patt) )
continue;
301 padCombinationsInWedge.emplace_back(std::vector<std::shared_ptr<PadData> >({pad1,pad2,pad3,pad4}) );
306 return padCombinationsInWedge;
310 const int STGCINNER=1;
311 const int STGCOUTER=2;
312 auto inOutModuleMatch=[](
const std::vector<std::shared_ptr<PadData>>& inM,
const std::vector<std::shared_ptr<PadData>>& outM)->
bool{
313 for(
const auto& in : inM){
314 for(
const auto&
out : outM){
317 return out->padNumber()/1000-in->padNumber()/1000 <=1;
324 std::vector<std::pair<int,int> > uniqueBandPhiIds;
325 std::vector<std::vector<std::shared_ptr<PadData>> > innerPatterns=
selectWedgePatterns(pads,
side, sector,STGCINNER);
326 std::vector<std::vector<std::shared_ptr<PadData>> > outerPatterns=
selectWedgePatterns(pads,
side, sector,STGCOUTER);
327 if(innerPatterns.empty()){
329 return StatusCode::SUCCESS;
331 if(outerPatterns.empty()){
333 return StatusCode::SUCCESS;
336 for(
const std::vector<std::shared_ptr<PadData>>& inner: innerPatterns){
337 for(
const std::vector<std::shared_ptr<PadData>>& outer: outerPatterns){
339 if(! inOutModuleMatch(inner,outer))
continue;
340 std::vector<std::shared_ptr<PadData>> combinedInOut;
341 combinedInOut.insert(combinedInOut.end(),inner.begin(),inner.end());
342 combinedInOut.insert(combinedInOut.end(),outer.begin(),outer.end());
344 std::vector<int> pads2Numbers;
345 std::transform(combinedInOut.begin(),combinedInOut.end(),std::back_inserter(pads2Numbers),[](
const std::shared_ptr<PadData>&
p){ return p->padNumber();});
346 std::pair<int,int> lookupValue=
Lookup(pads2Numbers);
347 if(lookupValue.first<0)
continue;
352 [&lookupValue,&
side,§or](
const std::unique_ptr<PadTrigger>&tr){
353 return tr->bandId() == lookupValue.second &&
354 tr->phiId() == lookupValue.first &&
355 tr->triggerSectorNumber() == sector &&
356 tr->sideId() == side;
358 if( trgpos !=
triggers.end() )
continue;
359 uniqueBandPhiIds.push_back(lookupValue);
361 auto trigger=std::make_unique<PadTrigger>();
362 std::copy(combinedInOut.begin(),combinedInOut.begin()+4,std::back_inserter(trigger->m_padsInner));
363 std::copy(combinedInOut.begin()+4,combinedInOut.end(),std::back_inserter(trigger->m_padsOuter));
364 std::copy(combinedInOut.begin(),combinedInOut.end(),std::back_inserter(trigger->m_pads));
365 trigger->m_bandid=lookupValue.second;
366 trigger->m_phi_id=lookupValue.first;
367 int triggerSectorType=trigger->firstPad()->sectorType();
368 switch(triggerSectorType){
385 triggers.push_back(std::move(trigger));
389 ATH_MSG_DEBUG(
"Found "<<uniqueBandPhiIds.size()<<
" unique triggers from LUT");
394 return StatusCode::SUCCESS;
403 std::vector<std::shared_ptr<PadOfflineData>> sectorPads;
404 std::vector<Identifier> padIds;
407 int ModuleSide=1?
m_idHelperSvc->stgcIdHelper().stationEta(modId)>0 :0;
408 int ModuleSect=
m_idHelperSvc->stgcIdHelper().stationPhi(modId);
410 if(ModuleSide!=
SIDE || ModuleSect !=SECTOR || SectType!=isSmall)
continue;
414 std::vector<Identifier> pad_channels;
418 int chanType=idHelper->channelType(id);
422 padIds.insert(padIds.end(),pad_channels.begin(),pad_channels.end());
430 int channeltype=
m_idHelperSvc->stgcIdHelper().channelType(
id);
440 int nPadRowsFromDesign=padEtaMaxFromDesign-padEtaMinFromDesign;
441 if( thisEta>nPadRowsFromDesign ||
thisPhi > nPadCols )
continue;
445 pad->fillGeometricInformation();
446 sectorPads.push_back(pad);
462 const static std::vector<int> vertexordering={0,1,3,2};
463 if(!
ofile.is_open()){
466 auto dumpPadGeometry=[&
ofile](
const std::shared_ptr<PadOfflineData>&
p)->
void{
468 for(
int i=0;
i<4;
i++){
469 int index=vertexordering.at(
i);
470 float x=
p->m_cornerXyz[
index][0];
471 float y=
p->m_cornerXyz[
index][1];
473 padVertices.push_back(std::move(vtx));
475 std::string secType=
p->sectorType()==1 ?
"LARGE":
"SMALL";
476 float layerZ=
p->m_cornerXyz[0][2];
478 std::stringstream
ss;
479 ss<<secType<<
" multilayer="<<
p->multipletId()<<
" module="<<
p->moduleId()<<
" layer="<<
p->gasGapId()<<
" layerZ="<<layerZ<<
" iEta="<<
p->padEtaId()<<
" iPhi="<<
p->padPhiId()<<
" <--> "<<boost::geometry::wkt(padPolygon)<<std::endl;
482 std::for_each(pads.begin(),pads.end(),dumpPadGeometry);
483 return StatusCode::SUCCESS;
498 if(nullCountInner+nullCountOuter==2)
return std::pair<int,int>(-1,-1);
499 if( nullCountInner ==0 ){
500 for(
int i :{0,1,2,3}){
501 int valueOnLayer=patt.at(
i);
505 patt.at(
i)=valueOnLayer;
508 if( nullCountOuter ==0 ){
509 for(
int i :{4,5,6,7}){
510 int valueOnLayer=patt.at(
i);
514 patt.at(
i)=valueOnLayer;
517 return std::pair<int,int>(-1,-1);