1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
18 #include "AliMpDCSNamer.h"
20 #include "AliCodeTimer.h"
22 #include "AliMpArea.h"
23 #include "AliMpDEIterator.h"
24 #include "AliMpDEManager.h"
25 #include "AliMpHelper.h"
26 #include "AliMpMotifMap.h"
27 #include "AliMpMotifPosition.h"
28 #include "AliMpSector.h"
29 #include "AliMpSegmentation.h"
30 #include "AliMpSlat.h"
31 #include "AliMpConstants.h"
32 #include <Riostream.h>
34 #include <TObjArray.h>
35 #include <TObjString.h>
39 //-----------------------------------------------------------------------------
40 /// \class AliMpDCSNamer
42 /// A utility class to manage DCS aliases names, in particular the
43 /// two conventions used to number the detection elements within a detector.
45 /// \author: Laurent Aphecetche and Diego Stocco, Subatech
46 //-----------------------------------------------------------------------------
49 ClassImp(AliMpDCSNamer)
52 const char* AliMpDCSNamer::fgkDCSChannelSt345Pattern[] =
53 { "MchHvLvLeft/Chamber%02dLeft/Slat%02d.actual.vMon",
54 "MchHvLvRight/Chamber%02dRight/Slat%02d.actual.vMon"
57 const char* AliMpDCSNamer::fgkDCSChannelSt12Pattern[] =
59 "MchHvLvLeft/Chamber%02dLeft/Quad%dSect%d.actual.vMon",
60 "MchHvLvRight/Chamber%02dRight/Quad%dSect%d.actual.vMon",
63 const char* AliMpDCSNamer::fgkDCSSideTrackerName[] = { "Left", "Right" };
66 const char* AliMpDCSNamer::fgkDCSSwitchSt345Pattern = "MchDE%04dsw%d.inValue";
68 const char* AliMpDCSNamer::fgkDCSChannelTriggerPatternRead[] = {"MTR_%3sSIDE_MT%2i_RPC%i_HV.%14s", "MTR_%2sSIDE_MT%2i_RPC%i_HV.%14s"};
69 const char* AliMpDCSNamer::fgkDCSChannelTriggerPattern[] = {"MTR_%3sSIDE_MT%2i_RPC%i_HV.%s", "MTR_%2sSIDE_MT%2i_RPC%i_HV.%s"};
70 const char* AliMpDCSNamer::fgkDCSSideTriggerName[] = { "OUT", "IN" };
71 const char* AliMpDCSNamer::fgkDCSMeasureName[] = { "vEff", "actual.iMon" };
73 const char* AliMpDCSNamer::fgkDetectorName[] = { "TRACKER", "TRIGGER" };
75 //_____________________________________________________________________________
76 AliMpDCSNamer::AliMpDCSNamer():
79 SetDetector("TRACKER");
83 //_____________________________________________________________________________
84 AliMpDCSNamer::AliMpDCSNamer(const char* detName):
87 /// ctor taking the detector name as argument (either trigger or tracker)
91 //_____________________________________________________________________________
92 AliMpDCSNamer::~AliMpDCSNamer()
97 //_____________________________________________________________________________
98 Bool_t AliMpDCSNamer::SetDetector(const char* detName)
100 /// Set the detector type
101 /// \param detName = tracker, trigger
103 TString sDetName(detName);
106 if(sDetName.Contains(fgkDetectorName[kTrackerDet]))
107 fDetector = kTrackerDet;
108 else if(sDetName.Contains(fgkDetectorName[kTriggerDet]))
109 fDetector = kTriggerDet;
111 AliWarning("Detector name must be either tracker or trigger. Default tracker selected");
118 //_____________________________________________________________________________
120 AliMpDCSNamer::AliasesAsLdif(const char* ldiffile) const
122 /// Export the aliases in LDIF format
124 ofstream out(ldiffile);
126 TObjArray* a = CompactAliases();
131 // Some header. host name and port probably not up to date.
132 TString detName = (fDetector == kTriggerDet) ? "MTR" : "MCH";
134 out << "#" << detName.Data() << " config" << endl
135 << "dn: det=" << detName.Data() <<",o=alice,dc=cern,dc=ch" << endl
136 << "objectClass: AliShuttleDetector" << endl
137 << "det: " << detName.Data() << endl
138 << "StrictRunOrder: 1" << endl
139 << "responsible: aphecetc@in2p3.fr" << endl
140 << "DCSHost: aldcs053.cern.ch" << endl
141 << "DCSPort: 4242" <<endl;
143 while ( ( s = (TObjString*)(next()) ) )
145 out << "DCSalias: " << s->String().Data() << endl;
153 //_____________________________________________________________________________
155 AliMpDCSNamer::CompactAliases() const
157 /// Generate a compact list of aliases, for Shuttle test
158 /// This one is completely hand-made, in contrast with GenerateAliases()
161 TObjArray* a = new TObjArray;
166 // St 12 (DCS Channels)
167 a->Add(new TObjString("MchHvLvRight/Chamber[00..03]Right/Quad0Sect[0..2].actual.vMon"));
168 a->Add(new TObjString("MchHvLvLeft/Chamber[00..03]Left/Quad1Sect[0..2].actual.vMon"));
169 a->Add(new TObjString("MchHvLvLeft/Chamber[00..03]Left/Quad2Sect[0..2].actual.vMon"));
170 a->Add(new TObjString("MchHvLvRight/Chamber[00..03]Right/Quad3Sect[0..2].actual.vMon"));
172 // St345 (DCS Channels)
174 a->Add(new TObjString("MchHvLvRight/Chamber[04..09]Right/Slat[00..08].actual.vMon"));
175 a->Add(new TObjString("MchHvLvLeft/Chamber[04..09]Left/Slat[00..08].actual.vMon"));
177 a->Add(new TObjString("MchHvLvRight/Chamber[06..09]Right/Slat[09..12].actual.vMon"));
178 a->Add(new TObjString("MchHvLvLeft/Chamber[06..09]Left/Slat[09..12].actual.vMon"));
182 a->Add(new TObjString("MTR_OUTSIDE_MT[11..12]Right/RPC[1..9]_HV.imon"));
183 a->Add(new TObjString("MTR_OUTSIDE_MT[21..22]Right/RPC[1..9]_HV.imon"));
184 a->Add(new TObjString("MTR_INSIDE_MT[11..12]Right/RPC[1..9]_HV.imon"));
185 a->Add(new TObjString("MTR_INSIDE_MT[21..22]Right/RPC[1..9]_HV.imon"));
187 a->Add(new TObjString("MTR_OUTSIDE_MT[11..12]Right/RPC[1..9]_HV.vmon"));
188 a->Add(new TObjString("MTR_OUTSIDE_MT[21..22]Right/RPC[1..9]_HV.vmon"));
189 a->Add(new TObjString("MTR_INSIDE_MT[11..12]Right/RPC[1..9]_HV.vmon"));
190 a->Add(new TObjString("MTR_INSIDE_MT[21..22]Right/RPC[1..9]_HV.vmon"));
194 if(fDetector == kTrackerDet){
195 // St345 (DCS Switches)
202 Int_t detElemId = it.CurrentDEId();
203 if ( AliMpDEManager::GetStationType(detElemId) == AliMp::kStation345 )
205 a->Add(new TObjString(Form("MchDE%04dsw[0..%d].inValue",detElemId,NumberOfPCBs(detElemId)-1)));
214 //_____________________________________________________________________________
216 AliMpDCSNamer::DCS2DE(Int_t chId, Int_t side, Int_t dcsNumber) const
218 /// Convert DCS Tracker "slat number" (old convention) to DE (new) convention.
220 /// \param chamberId : chamber number (starting at 0)
221 /// \param side : 0 for Left, 1 for Right
222 /// \param dcsNumber : slat number in DCS convention
224 /// note that dcsNumber should be >=0 and < number of DEs/2 in chamber
227 Int_t chamberId = chId;
229 if(fDetector == kTrackerDet){ // Tracker
231 Int_t nofDE = AliMpDEManager::GetNofDEInChamber(chamberId);
233 Int_t half = nofDE/2;
235 dcsNumber = half - dcsNumber;
237 Int_t quarter = nofDE/4;
238 Int_t threeQuarter = half + quarter;
240 if ( side == 0 ) // left
242 de = threeQuarter + 1 - dcsNumber;
244 else if ( side == 1 ) // right
246 if ( dcsNumber <= quarter )
248 de = dcsNumber + threeQuarter;
252 de = dcsNumber - quarter - 1;
258 if ( chId < 19 ) chamberId = chId - 1;
259 else chamberId = chId - 9;
261 Int_t nofDE = AliMpDEManager::GetNofDEInChamber(chamberId);
263 if ( side == 0 ) // left -> Outside
267 else if ( side == 1 ) // right -> Inside
269 de = (13 + dcsNumber) % nofDE;
273 return (chamberId+1)*100 + de;
277 //_____________________________________________________________________________
279 AliMpDCSNamer::DetElemId2DCS(Int_t detElemId, Int_t& side, Int_t &chId) const
281 /// Convert DE to DCS "slat number"
284 CheckConsistency(detElemId);
286 Int_t chamberId = AliMpDEManager::GetChamberId(detElemId);
289 AliDebug(1,Form("DetElemId %d invalid",detElemId));
292 Int_t dcsNumber = (detElemId-(chamberId+1)*100);
294 switch ( AliMpDEManager::GetStationType(detElemId) )
296 case AliMp::kStation12:
312 case AliMp::kStation345:
314 Int_t nofDE = AliMpDEManager::GetNofDEInChamber(chamberId);
316 Int_t quarter = nofDE/4;
318 Int_t half = nofDE/2;
320 Int_t threeQuarter = half + quarter;
324 if ( dcsNumber <= quarter )
326 dcsNumber += quarter + 1 ;
329 else if ( dcsNumber <= threeQuarter )
331 dcsNumber = ( threeQuarter - dcsNumber + 1 );
334 else if ( dcsNumber > threeQuarter )
336 dcsNumber = dcsNumber - threeQuarter;
343 // dcs convention change : numbering from top, not from bottom
344 dcsNumber = half-dcsNumber;
347 case AliMp::kStationTrigger:
349 if (chamberId < AliMpConstants::NofChambers()-2)
350 chId = chamberId + 1;
351 else chId = 23 + chamberId - AliMpConstants::NofChambers();
353 Int_t nofDE = AliMpDEManager::GetNofDEInChamber(chamberId);
355 if ( dcsNumber >=5 && dcsNumber <= 13 ) {
357 dcsNumber = 14 - dcsNumber;
361 dcsNumber = (5 + dcsNumber) % nofDE;
363 AliDebug(10, Form("detElemId %i -> MT%i_side%i_L%i", detElemId, chId, side, dcsNumber));
374 //_____________________________________________________________________________
376 AliMpDCSNamer::DCSChannelName(Int_t detElemId, Int_t sector, Int_t dcsMeasure) const
378 /// Return the alias name of the DCS Channel for a given DCS area
380 /// \param sector = 0,1 or 2 for St12, and is unused for st345 and trigger
381 /// \param dcsMeasure = kDCSHV, kDCSI and is unused for tracker
383 Int_t chamberId = AliMpDEManager::GetChamberId(detElemId);
384 if ( chamberId < 0 ) return 0x0;
386 Int_t side(-1), chId(-1);
387 Int_t dcsNumber = DetElemId2DCS(detElemId,side,chId);
389 switch (AliMpDEManager::GetStationType(detElemId))
391 case AliMp::kStation12:
392 return Form(fgkDCSChannelSt12Pattern[side],chamberId,dcsNumber,sector);
394 case AliMp::kStation345:
395 return Form(fgkDCSChannelSt345Pattern[side],chamberId,dcsNumber);
397 case AliMp::kStationTrigger:
398 return Form(fgkDCSChannelTriggerPattern[side],fgkDCSSideTriggerName[side],chId,dcsNumber,fgkDCSMeasureName[dcsMeasure]);
406 //_____________________________________________________________________________
408 AliMpDCSNamer::DCSSwitchName(Int_t detElemId, Int_t pcbNumber) const
410 /// Return the alias name of the DCS Switch for a given PCB
411 /// within a slat of St345
413 if (AliMpDEManager::GetStationType(detElemId) == AliMp::kStation345)
415 return Form(fgkDCSSwitchSt345Pattern,detElemId,pcbNumber);
420 //_____________________________________________________________________________
422 AliMpDCSNamer::DCSIndexFromDCSAlias(const char* dcsAlias) const
424 /// Converts the dcs alias to a hv index
426 /// dcsAlias has one of the following 3 forms :
428 /// MchHvLv[Left|Right]/Chamber##[Left|Right]/Chamber##[Left|Right]Slat##.actual.vMon
430 /// MchHvLv[Left|Right]/Chamber##[Left|Right]/Chamber##[Left|Right]Quad#Sect#.actual.vMon
432 /// MchDE####dsw#.inValue
434 TString sDcsAlias(dcsAlias);
440 if ( sDcsAlias.Contains("Left") )
444 else if ( sDcsAlias.Contains("Right") )
451 sscanf(sDcsAlias.Data(),fgkDCSSwitchSt345Pattern,&de,&sw);
459 if ( sDcsAlias.Contains("Quad") )
461 sscanf(sDcsAlias.Data(),fgkDCSChannelSt12Pattern[side],&n1,&n3,&n4);
468 //_____________________________________________________________________________
470 AliMpDCSNamer::DetElemIdFromDCSAlias(const char* dcsAlias) const
472 /// Converts the dcs alias to a detection element identifier
474 /// dcsAlias has one of the following forms :
476 /// MchHvLv[Left|Right]/Chamber##[Left|Right]/Chamber##[Left|Right]Slat##.actual.vMon
478 /// MchHvLv[Left|Right]/Chamber##[Left|Right]/Chamber##[Left|Right]Quad#Sect#.actual.vMon
480 /// MTR_Side[OUTSIDE|INSIDE]_MTChamber##_RPC#_HV.Type[actual.iMon|vEff]
482 AliDebug(1,Form("dcsAlias=%s",dcsAlias));
484 TString sDcsAlias(dcsAlias);
488 const char** sideName = (fDetector == kTriggerDet) ? fgkDCSSideTriggerName : fgkDCSSideTrackerName;
490 for(Int_t iside=0; iside<2; iside++){
491 if ( sDcsAlias.Contains(sideName[iside]) ) {
496 if(side<0) return -2;
505 if ( sDcsAlias.Contains("Slat") )
507 sscanf(sDcsAlias.Data(),fgkDCSChannelSt345Pattern[side],&n1,&n3);
508 detElemId = DCS2DE(n1,side,n3);
509 AliDebug(1,Form("Slat side=%d n1=%d n3=%d de=%d",side,n1,n3,detElemId));
511 else if ( sDcsAlias.Contains("Quad") )
513 sscanf(sDcsAlias.Data(),fgkDCSChannelSt12Pattern[side],&n1,&n3,&n4);
514 detElemId = 100*(n1+1) + n3;
515 AliDebug(1,Form("Quad side=%d n1=%d n3=%d n4=%d de=%d",side,n1,n3,n4,detElemId));
517 else if ( sDcsAlias.Contains("MT") )
519 sscanf(sDcsAlias.Data(),fgkDCSChannelTriggerPatternRead[side],cside,&n1,&n3,type);
520 detElemId = DCS2DE(n1,side,n3);
521 AliDebug(1,Form("Slat side=%d n1=%d n3=%d de=%d",side,n1,n3,detElemId));
528 if ( !AliMpDEManager::IsValidDetElemId(detElemId) )
530 AliError(Form("Invalid aliasName %s",dcsAlias));
537 //_____________________________________________________________________________
538 Int_t AliMpDCSNamer::DCSvariableFromDCSAlias(const char* dcsAlias) const
540 /// Get DCS variable from an alias (trigger)
542 TString sDcsAlias(dcsAlias);
544 Int_t dcsMeasurement = -1;
546 for(Int_t iMeas=0; iMeas<kNDCSMeas; iMeas++){
547 if ( sDcsAlias.Contains(fgkDCSMeasureName[iMeas]) ) {
548 dcsMeasurement = iMeas;
553 return dcsMeasurement;
557 //_____________________________________________________________________________
559 AliMpDCSNamer::GenerateAliases() const
561 /// Generate DCS alias names, for MUON Tracker High Voltage system.
562 /// or for MUON Trigger HV and current system.
564 /// We first generate aliases of DCS channels :
566 /// St 1 ch 1 : 12 channels
567 /// ch 2 : 12 channels
568 /// St 2 ch 3 : 12 channels
569 /// ch 4 : 12 channels
570 /// St 3 ch 5 : 18 channels
571 /// ch 6 : 18 channels
572 /// St 4 ch 7 : 26 channels
573 /// ch 8 : 26 channels
574 /// St 5 ch 9 : 26 channels
575 /// ch 10 : 26 channels
577 /// then aliases of DCS switches (only for St345) : 1 switch per PCB.
579 /// Returns a TObjArray of TObjString(=alias name)
581 TObjArray* aliases = new TObjArray;
582 aliases->SetOwner(kTRUE);
584 Int_t nMeasures = (fDetector == kTriggerDet) ? kNDCSMeas : 1;
586 for(Int_t iMeas=0; iMeas<nMeasures; iMeas++){
594 Int_t detElemId = it.CurrentDEId();
598 switch ( AliMpDEManager::GetStationType(detElemId) )
600 case AliMp::kStation12:
601 for ( int sector = 0; sector < 3; ++sector)
603 aliases->Add(new TObjString(DCSChannelName(detElemId,sector)));
606 case AliMp::kStation345:
607 aliases->Add(new TObjString(DCSChannelName(detElemId)));
608 for ( Int_t i = 0; i < NumberOfPCBs(detElemId); ++i )
610 aliases->Add(new TObjString(DCSSwitchName(detElemId,i)));
620 switch ( AliMpDEManager::GetStationType(detElemId) )
622 case AliMp::kStationTrigger:
623 AliDebug(10,Form("Current DetElemId %i",detElemId));
624 aliases->Add(new TObjString(DCSChannelName(detElemId,0,iMeas)));
633 } // loop on detElemId
634 } // Loop on measurement type
639 //_____________________________________________________________________________
641 AliMpDCSNamer::ManuId2Index(Int_t detElemId, Int_t manuId) const
643 /// Convert (de,manu) to hv index, depending on the station
645 AliMp::StationType stationType = AliMpDEManager::GetStationType(detElemId);
646 if ( stationType == AliMp::kStation345 )
648 return ManuId2PCBIndex(detElemId,manuId);
650 else if ( stationType == AliMp::kStation12 )
652 return ManuId2Sector(detElemId,manuId);
657 //_____________________________________________________________________________
659 AliMpDCSNamer::ManuId2PCBIndex(Int_t detElemId, Int_t manuId) const
661 /// Returns the index of PCB (within a St345 slat) for a given manu number.
662 /// Returns -1 if (detElemId,manuId) is incorrect
664 AliCodeTimerAuto("",0)
666 const AliMpSlat* slat
667 = AliMpSegmentation::Instance()->GetSlatByElectronics(detElemId, manuId);
668 if ( ! slat ) return -1;
670 return slat->FindPCBIndexByMotifPositionID(manuId);
673 //_____________________________________________________________________________
675 AliMpDCSNamer::ManuId2Sector(Int_t detElemId, Int_t manuId) const
677 /// Return the DCS-sector number (within a St12 quadrant) for a given manu number.
679 AliCodeTimerAuto("",0)
681 const AliMpSector* sector
682 = AliMpSegmentation::Instance()->GetSectorByElectronics(detElemId, manuId);
683 if ( ! sector ) return -1;
685 const AliMpMotifMap* motifMap = sector->GetMotifMap();
686 const AliMpMotifPosition* motifPos = motifMap->FindMotifPosition(manuId);
689 = motifPos->GetPositionX()-motifPos->GetDimensionX();
691 Double_t x = lowerLeftX*10.0; // cm -> mm
694 AliMq::Station12Type stationType = AliMpDEManager::GetStation12Type(detElemId);
696 if ( stationType == AliMq::kStation1 )
698 if ( x < -10 ) AliFatal("");
700 if ( x < 291.65 ) isector = 0;
701 else if ( x < 585.65 ) isector = 1;
702 else if ( x < 879.65 ) isector = 2;
706 if ( x < -140 ) AliFatal("");
708 if ( x < 283.75 ) isector = 0;
709 else if ( x < 606.25 ) isector = 1;
710 else if ( x < 1158.75 ) isector = 2;
716 //_____________________________________________________________________________
718 AliMpDCSNamer::NumberOfPCBs(Int_t detElemId) const
720 /// Returns the number of PCB in a given detection element
721 /// Only works for St345
723 AliMp::StationType stationType = AliMpDEManager::GetStationType(detElemId);
724 if ( stationType != AliMp::kStation345 )
730 const AliMpSlat* slat
731 = AliMpSegmentation::Instance()->GetSlat(detElemId, AliMp::kCath0);
732 return slat->GetSize();
736 //_____________________________________________________________________________
737 Bool_t AliMpDCSNamer::CheckConsistency(Int_t detElemId) const
740 /// Check that the required detElemId either belongs to tracker or trigger
741 /// consistently with the initial definition of the namer
744 Bool_t isConsistent(kFALSE);
746 switch(AliMpDEManager::GetStationType(detElemId))
748 case AliMp::kStation12:
749 case AliMp::kStation345:
750 if (fDetector == kTrackerDet) isConsistent = kTRUE;
751 requestInfo = "TRACKER";
753 case AliMp::kStationTrigger:
754 if (fDetector == kTriggerDet) isConsistent = kTRUE;
755 requestInfo = "TRIGGER";
761 if(!isConsistent) AliWarning(Form("Requesting information for %s station but class initialized for %s",requestInfo.Data(), fgkDetectorName[fDetector]));