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