]> git.uio.no Git - u/mrichter/AliRoot.git/blob - MUON/AliMUONSt1Response.cxx
macro moved to oldmacros directory. It has to be updated
[u/mrichter/AliRoot.git] / MUON / AliMUONSt1Response.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author: The ALICE Off-line Project.                                    *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
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  **************************************************************************/
15
16 /* $Id$ */
17
18 // Authors: David Guez, Ivana Hrivnacova, Marion MacCormick; IPN Orsay
19 //
20 // Class AliMUONSt1Response
21 // ----------------------------
22 // Response class for station 1 including electronics and detector response. 
23 // Individual pedestals or noise levels can be controlled separately. 
24 // The current pulse height responses do not contain any physics
25
26 #include <vector>
27 #include <TMath.h>
28 #include <TRandom.h>
29 #include <TSystem.h>
30 #include <Riostream.h>
31 #include "AliMpIntPair.h"
32 #include "AliMpPlaneSegmentation.h"
33 #include "AliMpPad.h"
34 #include "AliMpMotifMap.h"
35 #include "AliMpSector.h"
36 #include "AliMpPlane.h"
37 #include "AliMpZone.h"
38 #include "AliMpSubZone.h"
39 #include "AliMpVRowSegment.h"
40 #include "AliMUONSt1Response.h"
41 #include "AliMUONSt1ResponseParameter.h"
42 #include "AliMUONSt1ResponseRule.h"
43 #include "AliMUONSt1IniReader.h"
44 #include "AliMUONSt1Decoder.h"
45 #include "AliMUONTransientDigit.h"
46
47 ClassImp(AliMUONSt1Response);
48
49 const TString AliMUONSt1Response::fgkTopDir = getenv("ALICE_ROOT");
50 const TString AliMUONSt1Response::fgkDataDir = "/MUON/data/";
51 const TString AliMUONSt1Response::fgkConfigBaseName = "configChamber";
52 const TString AliMUONSt1Response::fgkStandardIniFileName = "st1StdParameter.ini";
53
54 const TString AliMUONSt1Response::fgkBaseName ="base";
55 const TString AliMUONSt1Response::fgkIncludeName ="include";
56 const TString AliMUONSt1Response::fgkParameterName ="parameter";
57 const TString AliMUONSt1Response::fgkRegionName ="region";
58 const TString AliMUONSt1Response::fgkRuleName ="rule";
59 const TString AliMUONSt1Response::fgkNameName ="name";
60 const TString AliMUONSt1Response::fgkPedestalName ="pedestal";
61 const TString AliMUONSt1Response::fgkNoiseName ="noise";
62 const TString AliMUONSt1Response::fgkStateName ="state";
63 const TString AliMUONSt1Response::fgkMName ="padM";
64 const TString AliMUONSt1Response::fgkMGName ="padMG";
65 const TString AliMUONSt1Response::fgkMGCName ="padMGC";
66 const TString AliMUONSt1Response::fgkIJName ="padIJ";
67 const TString AliMUONSt1Response::fgkXYName ="padXY";
68 const TString AliMUONSt1Response::fgkZoneName ="zone";
69 const TString AliMUONSt1Response::fgkStickyOnName ="stickyOn";
70 const TString AliMUONSt1Response::fgkStickyOffName ="stickyOff";
71 const TString AliMUONSt1Response::fgkFileName ="file";
72 const TString AliMUONSt1Response::fgkValueName ="value";
73 const TString AliMUONSt1Response::fgkGausName ="gaus";
74 const TString AliMUONSt1Response::fgkNotName ="no";
75 const TString AliMUONSt1Response::fgkNofSigmaName ="nofSigma";
76
77
78
79 //__________________________________________________________________________
80 AliMUONSt1Response::AliMUONSt1Response(Int_t chamber)
81   :AliMUONResponseV0()
82   ,fChamber(chamber),fParams(),fRegions(),fTrashList()
83   
84 {
85    // default pedestal value
86    fCountNofCalls=0;
87    fCountUnknownZone=0;
88    fCountUnknownIndices=0;
89
90    Int_t i;
91    for (i=0;i<2;i++){
92      fIniFileName[i]="";
93      fPlane[0]=0;
94      fPlaneSegmentation[i]=0;
95      for (Int_t j=0;j<fgkNofZones;j++)
96      {
97        fDefaultParameters[i][j]=0;
98      }
99    }
100    fTrashList.SetOwner(kTRUE);
101 }
102
103
104 //__________________________________________________________________________
105 AliMUONSt1Response::~AliMUONSt1Response()
106 {
107 //destructor
108   Int_t i;
109   for (i=0;i<2;i++){
110     if (fPlaneSegmentation[i]) delete fPlaneSegmentation[i];
111     if (fPlane[i]) delete fPlane[i];
112     fTrashList.Delete();
113   }
114 }
115
116 //__________________________________________________________________________
117 void AliMUONSt1Response::SetIniFileName(Int_t plane,const TString& fileName)
118 {
119 // Set the file to be read for the response parameters
120   if ((plane>=0) && (plane<=1)) fIniFileName[plane] = fileName;
121 }
122
123
124 //__________________________________________________________________________
125 void AliMUONSt1Response::ReadCouplesOfIntRanges(const string& value,TList* list,AliMUONSt1ElectronicElement::TDescription descr) 
126 {
127 // Decode couplets of integer ranges (enclosed within parenthesis and 
128 // separated by a comma, eg. (12/20,33/60) for ranges 12 to 20 and 33 to 60) 
129 // and save these ranges in <list> 
130   vector<string> lstCpl = decoder::SplitNtuples(value);
131   for (unsigned int n=0;n<lstCpl.size();n++){ // for each (..,..) couplet
132     vector<string> lst = decoder::SplitList(lstCpl[n],","); 
133                                               // should have 2 elements
134     if (lst.size() != 2) {
135       Warning("ReadIniFile","Bad pad definition");
136       continue;
137     }
138     vector<pair <int,int> > lst1 = decoder::DecodeListOfIntRanges(lst[0],";");
139     vector<pair <int,int> > lst2 = decoder::DecodeListOfIntRanges(lst[1],";");
140     for (unsigned int u1=0;u1<lst1.size();u1++){
141       for (unsigned int u2=0;u2<lst2.size();u2++){
142         AliMUONSt1ElectronicElement* elem 
143           = new AliMUONSt1ElectronicElement(descr);
144         fTrashList.Add(elem);
145         elem->SetRange(0,lst1[u1].first,lst1[u1].second);
146         elem->SetRange(1,lst2[u2].first,lst2[u2].second);
147         list->Add(elem);
148       }
149     }
150   }
151 }
152
153
154 //__________________________________________________________________________
155 void AliMUONSt1Response::ReadCouplesOfFloatRanges(const string& value,TList* list)
156 {
157 // Decode couplets of floating point ranges (enclosed within parenthesis and 
158 // separated by a comma, eg. (12./20.,33./60.) for ranges 12. to 20. and 33. to 60.) 
159 // and save these ranges in <list> 
160   vector<string> lstCpl = decoder::SplitNtuples(value);
161   for (unsigned int n=0;n<lstCpl.size();n++){ // for each (..,..) couplets
162     vector<string> lst = decoder::SplitList(lstCpl[n],","); 
163                                               // should have 2 elements
164     if (lst.size() != 2) {
165       Warning("ReadIniFile","Bad pad definition");
166       continue;
167     }
168     vector<pair <double,double> > lst1 = decoder::DecodeListOfFloatRanges(lst[0],";");
169     vector<pair <double,double> > lst2 = decoder::DecodeListOfFloatRanges(lst[1],";");
170     for (unsigned int u1=0;u1<lst1.size();u1++){
171       for (unsigned int u2=0;u2<lst2.size();u2++){
172         AliMUONSt1ElectronicElement* elem 
173           = new AliMUONSt1ElectronicElement(AliMUONSt1ElectronicElement::kXY);
174         fTrashList.Add(elem);
175         elem->SetRange(0,lst1[u1].first,lst1[u1].second);
176         elem->SetRange(1,lst2[u2].first,lst2[u2].second);
177         list->Add(elem);
178       }
179     }
180   }
181 }
182
183
184 //__________________________________________________________________________
185 void AliMUONSt1Response::SetPairToParam(const string& name,const string& value,AliMUONSt1ResponseParameter* param) const
186 {
187 // set a (name,value) pair to <param>
188   TString path = fgkTopDir + fgkDataDir ;
189   const char* nm = name.c_str();
190   if (fgkStateName.CompareTo(nm,TString::kIgnoreCase)==0){
191     param->SetState(atoi(value.c_str()));
192   } else if (fgkPedestalName.CompareTo(nm,TString::kIgnoreCase)==0){
193     vector<string> lst = decoder::SplitList(value," ");
194     if ((lst.size()>0) && (fgkNotName.CompareTo(lst[0].c_str(),TString::kIgnoreCase)==0)){
195       param->UnSetPedestal();
196     } else if ((lst.size()>1) && (fgkValueName.CompareTo(lst[0].c_str(),TString::kIgnoreCase)==0)){
197       param->SetPedestal(atof(lst[1].c_str()));
198     } else if ((lst.size()>1) && (fgkFileName.CompareTo(lst[0].c_str(),TString::kIgnoreCase)==0)){
199       param->SetPedestal(path+lst[1].c_str());
200     } else if ((lst.size()>2) && (fgkGausName.CompareTo(lst[0].c_str(),TString::kIgnoreCase)==0)){
201       param->SetPedestal(atof(lst[1].c_str()),atof(lst[2].c_str()));
202     }
203   } else if (fgkNoiseName.CompareTo(nm,TString::kIgnoreCase)==0){
204     vector<string> lst = decoder::SplitList(value," ");
205     if ((lst.size()>1) && (fgkValueName.CompareTo(lst[0].c_str(),TString::kIgnoreCase)==0)){
206       param->SetNoise(atof(lst[1].c_str()));
207     } else if ((lst.size()>1) && (fgkFileName.CompareTo(lst[0].c_str(),TString::kIgnoreCase)==0)){
208       param->SetNoise(path+lst[1].c_str());
209     } else if ((lst.size()>2) && (fgkGausName.CompareTo(lst[0].c_str(),TString::kIgnoreCase)==0)){
210       param->SetNoise(atof(lst[1].c_str()),atof(lst[2].c_str()));
211     }
212   } else if (fgkNofSigmaName.CompareTo(nm,TString::kIgnoreCase)==0){
213     param->SetNofSigma(atoi(value.c_str()));
214   } else if (fgkStickyOnName.CompareTo(nm,TString::kIgnoreCase)==0){
215     vector< pair<int,int> > lst = decoder::DecodeListOfIntRanges(value);
216     for (unsigned int i=0;i<lst.size();i++){
217       for (int j=lst[i].first;(j<12) && (j<=lst[i].second);j++){
218         param->SetStickyBitOn(j);
219       }
220     }
221   } else if (fgkStickyOffName.CompareTo(nm,TString::kIgnoreCase)==0){
222     vector< pair<int,int> > lst = decoder::DecodeListOfIntRanges(value);
223     for (unsigned int i=0;i<lst.size();i++){
224       for (int j=lst[i].first;(j<12) && (j<=lst[i].second);j++){
225         param->SetStickyBitOff(j);
226       }
227     }
228   }
229 }
230
231
232 //__________________________________________________________________________
233 void AliMUONSt1Response::SetPairToListElem(const string& name,const string& value,TList* list)
234 {
235 // set a (name,value) pair to <list>
236   const char* nm = name.c_str();
237   if (fgkIJName.CompareTo(nm,TString::kIgnoreCase)==0){
238     ReadCouplesOfIntRanges(value,list,AliMUONSt1ElectronicElement::kIJ);
239   } else if (fgkMGCName.CompareTo(nm,TString::kIgnoreCase)==0){
240     ReadCouplesOfIntRanges(value,list,AliMUONSt1ElectronicElement::kMGC);
241   } else if (fgkMGName.CompareTo(nm,TString::kIgnoreCase)==0){
242     ReadCouplesOfIntRanges(value,list,AliMUONSt1ElectronicElement::kMG);
243   } else if (fgkMName.CompareTo(nm,TString::kIgnoreCase)==0){
244     vector< pair<int,int> > lst = decoder::DecodeListOfIntRanges(value);
245     for (unsigned int i=0;i<lst.size();i++){
246       AliMUONSt1ElectronicElement* elem 
247         = new AliMUONSt1ElectronicElement(AliMUONSt1ElectronicElement::kM);
248       fTrashList.Add(elem);
249       elem->SetRange(0,lst[i].first,lst[i].second);
250       list->Add(elem);
251     }
252   } else if (fgkXYName.CompareTo(nm,TString::kIgnoreCase)==0){
253     ReadCouplesOfFloatRanges(value,list);
254   }
255 }
256
257
258 //__________________________________________________________________________
259 void AliMUONSt1Response::ReadIniFile(Int_t plane)
260 {
261   //Read the ini file and fill the <plane>th structures 
262   TString path = fgkTopDir + fgkDataDir ;
263   //read .ini file
264   if (gSystem->AccessPathName(path+fIniFileName[plane],kReadPermission)){
265     Fatal("ReadIniFile",
266           Form("Unable to Read the file %s",fIniFileName[plane].Data()));
267     return;
268   }
269   fRegions.clear();
270   fParams.clear();
271   ReadIniFile(plane,path+fIniFileName[plane],kTRUE,kTRUE,kTRUE);
272 }
273
274
275 //__________________________________________________________________________
276 void AliMUONSt1Response::ReadIniFile(Int_t plane,const TString& fileName,
277                                     Bool_t rdParam,Bool_t rdRegion,Bool_t rdRule)
278 {
279   //Read the given ini file and fill the <plane>th structures 
280   cout<<"Reading parameter file "<<fileName<<endl;
281   AliMUONSt1IniReader iniFile(fileName.Data());
282   AliMUONSt1IniReader::TChapter chap;
283   AliMUONSt1IniReader::TValueList vals;
284   AliMUONSt1IniReader::TValueList::iterator itValue;
285   while (!iniFile.Eof()){
286     chap = iniFile.MakeCurrentChapter();
287     TString chapName = chap.first.c_str();
288     vals = chap.second;
289     if (fgkBaseName.CompareTo(chapName,TString::kIgnoreCase)==0){
290       for (itValue = vals.begin() ; itValue != vals.end(); ++itValue){
291         string name =  (*itValue).first;
292         string value = (*itValue).second;
293         if (fgkIncludeName.CompareTo(name.c_str(),TString::kIgnoreCase)==0){
294           vector<string> lst = decoder::SplitList(value,":");
295           if (lst.size()>0){
296             TString inFileName = TString(gSystem->DirName(fileName))+"/" + lst[0].c_str();
297             Bool_t inParam=kFALSE,inRegion=kFALSE,inRule=kFALSE;
298             if (lst.size()>1) {
299               vector<string> lst2 = decoder::SplitList(lst[1],",");
300               for (unsigned int k=0;k<lst2.size();k++){
301                 if (fgkParameterName.CompareTo(lst2[k].c_str(),TString::kIgnoreCase)==0){
302                   inParam=kTRUE;
303                 } else if (fgkRegionName.CompareTo(lst2[k].c_str(),TString::kIgnoreCase)==0){
304                   inRegion=kTRUE;
305                 } else if (fgkRuleName.CompareTo(lst2[k].c_str(),TString::kIgnoreCase)==0){
306                   inRule=kTRUE;
307                 }
308               }
309             } else {
310               inParam=inRegion=inRule=kTRUE;
311             }
312             ReadIniFile(plane,inFileName,inParam,inRegion,inRule);
313           }
314         }
315       }
316     } else if (rdParam && fgkParameterName.CompareTo(chapName,TString::kIgnoreCase)==0){
317       AliMUONSt1ResponseParameter* param = new AliMUONSt1ResponseParameter();
318       fTrashList.Add(param);
319       string paramName=Form("Parameter %d",fParams.size()+1);
320       for (itValue = vals.begin() ; itValue != vals.end(); ++itValue){
321         string name =  (*itValue).first;
322         string value = (*itValue).second;
323         if (fgkNameName.CompareTo(name.c_str(),TString::kIgnoreCase)==0){
324           paramName=value;
325         } else SetPairToParam(name,value,param);
326       }
327       fParams[paramName]=param;
328     } else if (rdRegion && fgkRegionName.CompareTo(chapName,TString::kIgnoreCase)==0){
329       TList* lstElem = new TList;
330       string listName=Form("Region %d",fRegions.size()+1);
331       for (itValue = vals.begin() ; itValue != vals.end(); ++itValue){
332         string name =  (*itValue).first;
333         string value = (*itValue).second;
334         if (fgkNameName.CompareTo(name.c_str(),TString::kIgnoreCase)==0){
335           listName=value;
336         } else SetPairToListElem(name,value,lstElem);
337       }
338       fRegions[listName]=lstElem;
339     }
340   }
341   iniFile.Reset();
342   while (!iniFile.Eof()){
343     chap = iniFile.MakeCurrentChapter();
344     TString chapName = chap.first.c_str();
345     vals = chap.second;
346     if (rdRule && fgkRuleName.CompareTo(chapName,TString::kIgnoreCase)==0){
347       Int_t i;
348       Bool_t zones[fgkNofZones];
349       for (i=0;i<fgkNofZones;i++) zones[i]=kFALSE;
350       AliMUONSt1ResponseRule* rule=0;
351       for (itValue = vals.begin() ; itValue != vals.end(); ++itValue){
352         string name =  (*itValue).first;
353         string value = (*itValue).second;
354         if (fgkZoneName.CompareTo(name.c_str(),TString::kIgnoreCase)==0){
355           vector< pair<int,int> > lst = decoder::DecodeListOfIntRanges(value);
356           for (unsigned int i=0;i<lst.size();i++){
357             for (int j=lst[i].first;(j<=fgkNofZones) && (j<=lst[i].second);j++) {
358               if (j>0) zones[j-1] = kTRUE;
359             }
360           }
361         } else if (fgkRegionName.CompareTo(name.c_str(),TString::kIgnoreCase)==0){
362           TListMap::iterator it = fRegions.find(value);
363           if (it != fRegions.end()){
364             if (!rule) {
365               rule = new AliMUONSt1ResponseRule();
366               fTrashList.Add(rule);
367             }
368             TIter next((*it).second);
369             AliMUONSt1ElectronicElement* el;
370             while ((el = static_cast<AliMUONSt1ElectronicElement*>(next()))){
371               rule->AddElement(el);
372             }
373           } else Warning("ReadIniFile",Form("Can't find region named %s",value.c_str()));
374         }
375       }
376       for (itValue = vals.begin() ; itValue != vals.end(); ++itValue){
377         string name =  (*itValue).first;
378         string value = (*itValue).second;
379         if (fgkParameterName.CompareTo(name.c_str(),TString::kIgnoreCase)==0){
380           TParamsMap::iterator it = fParams.find(value);
381           if (it != fParams.end()){
382             AliMUONSt1ResponseParameter* param = (*it).second;
383             for (i=0;i<fgkNofZones;i++) if (zones[i]) {
384               fDefaultParameters[plane][i]=param;
385             }
386             if (rule) rule->AddParameter(param);
387           } else Warning("ReadIniFile",Form("Can't find parameter named %s",value.c_str()));
388         }
389       }
390       if (rule) fRulesList[plane].AddFirst(rule);
391     }
392   }
393   for (TListMap::iterator it = fRegions.begin() ; it != fRegions.end(); ++it) delete (*it).second;
394 }
395
396
397 //__________________________________________________________________________
398 void AliMUONSt1Response::ReadFiles()
399 {
400 // Define the current response rules with respect to the description
401 // given in the "configChamber1.ini" and "configChamber2.ini" files.
402   Int_t i;
403   TString path = fgkTopDir + fgkDataDir ;
404
405   TString configFileName = path + fgkConfigBaseName + Form("%d.ini",fChamber);
406   if (gSystem->AccessPathName(configFileName,kReadPermission)){
407     // no configChamberI.ini file exists
408     SetIniFileName(0,fgkStandardIniFileName);
409     SetIniFileName(1,fgkStandardIniFileName);
410   } else {
411     cout<<"Reading configuration file "<<configFileName<<endl;
412     AliMUONSt1IniReader iniFile(configFileName.Data());
413     while (!iniFile.Eof()) {
414       iniFile.ReadNextLine();
415       if (iniFile.GetCurrentType() != AliMUONSt1IniReader::kValue) continue;
416       Int_t plane;
417       if ((sscanf(iniFile.GetCurrentName().c_str()
418                  ,"file%d",&plane)==1) && (plane>=0) && (plane<=1)){
419         SetIniFileName(plane,iniFile.GetCurrentValue().c_str());
420       }
421     }
422   }
423   //book memory and fill them with .ini files
424   fPlane[0]=AliMpPlane::Create(kBendingPlane);
425   fPlane[1]=AliMpPlane::Create(kNonBendingPlane);
426   for (i=0;i<2;i++){
427     fPlaneSegmentation[i]= new AliMpPlaneSegmentation(fPlane[i]);
428     ReadIniFile(i);
429   }
430 }
431
432 //__________________________________________________________________________
433 Float_t AliMUONSt1Response::IntPH(Float_t eloss)
434 {
435   // Calculate charge from given ionization energy lost.
436   Int_t nel;
437   nel= Int_t(eloss*1.e9/20); 
438   Float_t charge=0;
439   if (nel == 0) nel=1;
440   for (Int_t i=1;i<=nel;i++) {
441       Float_t arg=0.;
442       while(!arg) arg = gRandom->Rndm();
443       charge -= fChargeSlope*TMath::Log(arg);    
444   }
445   return charge;
446 }
447
448
449 //__________________________________________________________________________
450 AliMpZone* AliMUONSt1Response::FindZone(AliMpSector* sector,Int_t posId)
451 {
452 // to be moved to AliMpSector::
453   for (Int_t izone=1;izone<=sector->GetNofZones();izone++){
454     AliMpZone* zone = sector->GetZone(izone);
455     for (Int_t isub=0;isub<zone->GetNofSubZones();isub++){
456       AliMpSubZone* sub=zone->GetSubZone(isub);
457       for (Int_t iseg=0;iseg<sub->GetNofRowSegments();iseg++){
458         if (sub->GetRowSegment(iseg)->HasMotifPosition(posId)) return zone;
459       }
460     }
461   }
462   return 0;
463 }
464
465
466 //__________________________________________________________________________
467
468 Int_t  AliMUONSt1Response::DigitResponse(Int_t digit,AliMUONTransientDigit* where)
469 {
470   // returns the electronic response of pad located at <where>, when
471   // a charge <digit> is present
472   
473     //cout<<"electronic of pad "<<where->PadX()<<' '<<where->PadY()
474     //                          <<" on plane "<<where->Cathode()<<endl;
475     
476     //read the files the first time this function is called
477     if (!fPlane[0]) ReadFiles();
478
479     fCountNofCalls++;
480     
481     AliMpIntPair indices(where->PadX(),where->PadY());
482     AliMpPad pad = fPlaneSegmentation[where->Cathode()]->PadByIndices(indices,kFALSE);
483     Int_t GC=0;
484     Int_t numZone=0;
485     AliMpZone* zone=0;
486
487     if (pad.IsValid()) {
488       AliMpIntPair location = pad.GetLocation();
489       //cout<<location.GetFirst()<<endl;
490       Int_t posId=abs(location.GetFirst());
491       AliMpSector* sector=0;
492       if (fPlane[0]->GetFrontSector()->GetMotifMap()->FindMotifPosition(posId))
493                 sector=(AliMpSector*)fPlane[0]->GetFrontSector();
494       else if (fPlane[0]->GetBackSector()->GetMotifMap()->FindMotifPosition(posId))
495                 sector=(AliMpSector*)fPlane[0]->GetBackSector();
496
497       if (sector) zone=FindZone(sector,posId);
498       if (zone){
499         numZone=zone->GetID()-1;
500         GC=location.GetSecond();
501       } else {
502         fCountUnknownZone++;
503       }
504     } else {
505       fCountUnknownIndices++;
506     }
507
508     if (!zone) {
509       cout<<"Probleme electronic of pad "<<where->PadX()<<' '<<where->PadY()
510           <<" on plane "<<where->Cathode()<<endl;
511       return 6666;
512     }
513     TList listParams;
514     TIter next(&fRulesList[where->Cathode()]);
515     AliMUONSt1ResponseRule* rule;
516     while ( (rule = static_cast<AliMUONSt1ResponseRule*>(next())))
517       if (rule->Contains(pad)) listParams.AddAll(rule->GetParameters());
518     if (fDefaultParameters[where->Cathode()][numZone])
519       listParams.Add(fDefaultParameters[where->Cathode()][numZone]);
520
521     AliMUONSt1ResponseParameter* param;
522     TIter nextParam(&listParams);
523     while ( (param = static_cast<AliMUONSt1ResponseParameter*>(nextParam()))){
524       if (param->GetState()==kFALSE) {
525         return 0;
526       }
527     }
528     nextParam.Reset();
529     while ( (param = static_cast<AliMUONSt1ResponseParameter*>(nextParam()))){
530       if (param->HasPedestal()) {
531         digit  = param->ApplyPedestal(digit,GC);
532         break; // Apply pedestals just once -->  break the loop once a pedestal 
533 //                                               rule is applied
534       }
535     }
536     if ( digit < 0) digit=0;
537     if (digit >  MaxAdc()) digit=MaxAdc();
538     nextParam.Reset();
539     while ( (param = static_cast<AliMUONSt1ResponseParameter*>(nextParam()))){
540       digit  = param->ApplyStickyBits(digit);
541     }
542    
543     //cout<<digit<<endl;
544     return digit;
545 }
546
547
548 //__________________________________________________________________________
549 void AliMUONSt1Response::PrintStatistics() const
550 {
551 // Show the results of the statistics
552   cout<<"The DigitResponse() method was called "<<fCountNofCalls<<" times"<<endl;
553   cout<<" it was unable to find the pad corresponding to the given indices "
554       <<fCountUnknownIndices<<" times ("
555       <<(Double_t)100.*fCountUnknownIndices/fCountNofCalls
556       <<"%)"<<endl;
557   cout<<" it was unable to find the zone corresponding to the found pad "
558       <<fCountUnknownZone<<" times ("
559       <<(Double_t)100.*fCountUnknownZone/fCountNofCalls
560       <<"%)"<<endl;
561 }
562
563
564
565
566
567
568