Add task to handle the muon type in simulations. The class allows to identify, among...
[u/mrichter/AliRoot.git] / PWG / muon / AliAnalysisMuonUtility.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-2007, 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: AliAnalysisMuonUtility.cxx 47782 2011-02-24 18:37:31Z martinez $ */
17
18 //-----------------------------------------------------------------------------
19 /// \class AliAnalysisMuonUtility
20 /// Static tilities for muon analysis
21 /// The class allows to treat AODs and ESDs
22 /// as well as MC AODs and MC in a transparent way
23 ///
24 /// \author Diego Stocco
25 //-----------------------------------------------------------------------------
26
27 #include "AliAnalysisMuonUtility.h"
28
29 // ROOT includes
30 #include "TAxis.h"
31 #include "TMath.h"
32 #include "TLorentzVector.h"
33 #include "TFile.h"
34
35 // STEER includes
36 #include "AliInputEventHandler.h"
37 #include "AliAODHeader.h"
38 #include "AliAODEvent.h"
39 #include "AliAODTrack.h"
40 #include "AliAODMCHeader.h"
41 #include "AliAODMCParticle.h"
42 #include "AliMCEvent.h"
43 #include "AliMCParticle.h"
44 #include "AliESDEvent.h"
45 #include "AliESDMuonTrack.h"
46 #include "AliVVertex.h"
47 #include "AliLog.h"
48 #include "AliStack.h"
49
50 // CORRFW includes
51 #include "AliCFGridSparse.h"
52
53 /// \cond CLASSIMP
54 ClassImp(AliAnalysisMuonUtility) // Class implementation in ROOT context
55 /// \endcond
56
57
58 //________________________________________________________________________
59 Bool_t AliAnalysisMuonUtility::IsAODEvent ( const AliVEvent* event )
60 {
61   /// Check if event is from ESD or AOD
62   return ( event->IsA() == AliAODEvent::Class() );
63 }
64
65 //________________________________________________________________________
66 Bool_t AliAnalysisMuonUtility::IsAODTrack ( const AliVParticle* track )
67 {
68   /// Check if track is from ESD or AOD
69   return ( track->IsA() == AliAODTrack::Class() );
70 }
71
72 //________________________________________________________________________
73 Bool_t AliAnalysisMuonUtility::IsMuonTrack ( const AliVParticle* track )
74 {
75   /// Check if track has muon tracker info
76   return ( IsAODTrack(track) ) ? static_cast<const AliAODTrack*>(track)->IsMuonTrack() : static_cast<const AliESDMuonTrack*>(track)->ContainTrackerData();
77 }
78
79 //________________________________________________________________________
80 Bool_t AliAnalysisMuonUtility::IsMuonGhost ( const AliVParticle* track )
81 {
82   /// Check if track has trigger info
83   return ( IsAODTrack(track) ) ? kFALSE : ( ! static_cast<const AliESDMuonTrack*>(track)->ContainTrackerData() );
84 }
85
86 //________________________________________________________________________
87 Double_t AliAnalysisMuonUtility::GetRabs ( const AliVParticle* track )
88 {
89   /// Get Rabs
90   return ( IsAODTrack(track) ) ? static_cast<const AliAODTrack*>(track)->GetRAtAbsorberEnd() : static_cast<const AliESDMuonTrack*>(track)->GetRAtAbsorberEnd();
91 }
92
93 //________________________________________________________________________
94 Double_t AliAnalysisMuonUtility::GetThetaAbsDeg ( const AliVParticle* track )
95 {
96   /// Get Theta at absorber end (in deg)
97   return TMath::ATan( GetRabs(track) / 505. ) * TMath::RadToDeg();
98 }
99
100 //________________________________________________________________________
101 Int_t AliAnalysisMuonUtility::GetMatchTrigger ( const AliVParticle* track )
102 {
103   /// Get match trigger
104   return IsAODTrack(track) ? static_cast<const AliAODTrack*>(track)->GetMatchTrigger() : static_cast<const AliESDMuonTrack*>(track)->GetMatchTrigger();
105 }
106
107 //________________________________________________________________________
108 Double_t AliAnalysisMuonUtility::GetChi2perNDFtracker ( const AliVParticle* track )
109 {
110   /// Get the normalized chi2 of the tracker track
111   return IsAODTrack(track) ? static_cast<const AliAODTrack*>(track)->Chi2perNDF() : static_cast<const AliESDMuonTrack*>(track)->GetNormalizedChi2();
112 }
113
114 //________________________________________________________________________
115 Double_t AliAnalysisMuonUtility::GetChi2MatchTrigger ( const AliVParticle* track )
116 {
117   /// Get the normalized chi2 of the tracker-trigger track matching
118   return IsAODTrack(track) ? static_cast<const AliAODTrack*>(track)->GetChi2MatchTrigger() : static_cast<const AliESDMuonTrack*>(track)->GetChi2MatchTrigger();
119 }
120
121 //________________________________________________________________________
122 Double_t AliAnalysisMuonUtility::GetXatVertex ( const AliVParticle* track )
123 {
124   /// Get X at vertex
125   Double_t coor = 0.;
126   if ( IsAODTrack(track) ) {
127     Double_t vtxPos[3];
128     static_cast<const AliAODTrack*>(track)->GetXYZ(vtxPos);
129     coor = vtxPos[0];
130   }
131   else coor = static_cast<const AliESDMuonTrack*>(track)->GetNonBendingCoor();
132   
133   return coor;
134 }
135
136 //________________________________________________________________________
137 Double_t AliAnalysisMuonUtility::GetYatVertex ( const AliVParticle* track )
138 {
139   /// Get Y at vertex
140   Double_t coor = 0.;
141   if ( IsAODTrack(track) ) {
142     Double_t vtxPos[3];
143     static_cast<const AliAODTrack*>(track)->GetXYZ(vtxPos);
144     coor = vtxPos[1];
145   }
146   else coor = static_cast<const AliESDMuonTrack*>(track)->GetBendingCoor();
147   
148   return coor;
149 }
150
151 //________________________________________________________________________
152 Double_t AliAnalysisMuonUtility::GetZatVertex ( const AliVParticle* track )
153 {
154   /// Get Z at vertex
155   Double_t coor = 0.;
156   if ( IsAODTrack(track) ) {
157     Double_t vtxPos[3];
158     static_cast<const AliAODTrack*>(track)->GetXYZ(vtxPos);
159     coor = vtxPos[2];
160   }
161   else coor = static_cast<const AliESDMuonTrack*>(track)->GetZ();
162   
163   return coor;
164 }
165
166 //________________________________________________________________________
167 Double_t AliAnalysisMuonUtility::GetXatDCA ( const AliVParticle* track )
168 {
169   /// Get X at DCA
170   return IsAODTrack(track) ? static_cast<const AliAODTrack*>(track)->XAtDCA() : static_cast<const AliESDMuonTrack*>(track)->GetNonBendingCoorAtDCA();
171 }
172
173 //________________________________________________________________________
174 Double_t AliAnalysisMuonUtility::GetYatDCA ( const AliVParticle* track )
175 {
176   /// Get Y at DCA
177   return IsAODTrack(track) ? static_cast<const AliAODTrack*>(track)->YAtDCA() : static_cast<const AliESDMuonTrack*>(track)->GetBendingCoorAtDCA();
178 }
179
180 //________________________________________________________________________
181 Bool_t AliAnalysisMuonUtility::IsTrkChamberHit( Int_t chamber, const AliVParticle* track )
182 {
183   /// Check if the given tracking chamber has been fired
184   if (chamber < 0 || chamber > 9) return kFALSE;
185   return IsAODTrack(track) ? static_cast<const AliAODTrack*>(track)->HitsMuonChamber(chamber) : static_cast<const AliESDMuonTrack*>(track)->IsInMuonClusterMap(chamber);
186 }
187
188 //________________________________________________________________________
189 UInt_t AliAnalysisMuonUtility::GetMUONTrigHitsMapTrk ( const AliVParticle* track )
190 {
191   /// Get hit pattern in trigger chambers from tracker track extrapolation
192   return ( IsAODTrack(track) ) ? const_cast<AliAODTrack*>(static_cast<const AliAODTrack*>(track))->GetMUONTrigHitsMapTrk() : static_cast<const AliESDMuonTrack*>(track)->GetHitsPatternInTrigChTrk();
193 }
194
195 //________________________________________________________________________
196 UInt_t AliAnalysisMuonUtility::GetMUONTrigHitsMapTrg ( const AliVParticle* track )
197 {
198   /// Get hit pattern in trigger chambers from tracker track extrapolation
199   return ( IsAODTrack(track) ) ? const_cast<AliAODTrack*>(static_cast<const AliAODTrack*>(track))->GetMUONTrigHitsMapTrg() : static_cast<const AliESDMuonTrack*>(track)->GetHitsPatternInTrigCh();
200 }
201
202 //________________________________________________________________________
203 Int_t AliAnalysisMuonUtility::GetLoCircuit ( const AliVParticle* track )
204 {
205   /// Get local board
206   Int_t loCircuit = 0;
207   if ( IsAODTrack (track) ) {
208     UInt_t pattern = const_cast<AliAODTrack*>(static_cast<const AliAODTrack*>(track))->GetMUONTrigHitsMapTrg();
209     loCircuit = AliESDMuonTrack::GetCrossedBoard(pattern);
210   }
211   else loCircuit = static_cast<const AliESDMuonTrack*>(track)->LoCircuit();
212   
213   return loCircuit;
214 }
215
216 //________________________________________________________________________
217 TString AliAnalysisMuonUtility::GetFiredTriggerClasses ( const AliVEvent* event )
218 {
219   /// Check if track is from ESD or AOD
220   return ( IsAODEvent(event) ) ? static_cast<const AliAODEvent*>(event)->GetFiredTriggerClasses() : static_cast<const AliESDEvent*>(event)->GetFiredTriggerClasses();
221 }
222
223 //________________________________________________________________________
224 Int_t AliAnalysisMuonUtility::GetNTracks ( const AliVEvent* event )
225 {
226   //
227   /// Return the number of tracks in event
228   //
229   return ( IsAODEvent(event) ) ? static_cast<const AliAODEvent*>(event)->GetNTracks() : static_cast<const AliESDEvent*>(event)->GetNumberOfMuonTracks();
230 }
231
232 //________________________________________________________________________
233 UInt_t AliAnalysisMuonUtility::GetL0TriggerInputs ( const AliVEvent* event )
234 {
235   //
236   /// Return the L0 trigger inputs
237   //
238   return ( IsAODEvent(event) ) ? static_cast<const AliAODEvent*>(event)->GetHeader()->GetL0TriggerInputs() : static_cast<const AliESDEvent*>(event)->GetHeader()->GetL0TriggerInputs();
239 }
240
241 //________________________________________________________________________
242 UInt_t AliAnalysisMuonUtility::GetL1TriggerInputs ( const AliVEvent* event )
243 {
244   //
245   /// Return the L1 trigger inputs
246   //
247   return ( IsAODEvent(event) ) ? static_cast<const AliAODEvent*>(event)->GetHeader()->GetL1TriggerInputs() : static_cast<const AliESDEvent*>(event)->GetHeader()->GetL1TriggerInputs();
248 }
249
250 //________________________________________________________________________
251 UInt_t AliAnalysisMuonUtility::GetL2TriggerInputs ( const AliVEvent* event )
252 {
253   //
254   /// Return the L2 trigger inputs
255   //
256   return ( IsAODEvent(event) ) ? static_cast<const AliAODEvent*>(event)->GetHeader()->GetL2TriggerInputs() : static_cast<const AliESDEvent*>(event)->GetHeader()->GetL2TriggerInputs();
257 }
258
259 //________________________________________________________________________
260 AliVParticle* AliAnalysisMuonUtility::GetTrack ( Int_t itrack, const AliVEvent* event )
261 {
262   //
263   /// Get the current track
264   //
265   AliVParticle* track = 0x0;
266   if ( IsAODEvent(event) ) track = static_cast<const AliAODEvent*>(event)->GetTrack(itrack);
267   else {
268     AliESDEvent* esdEvent = const_cast<AliESDEvent*>(static_cast<const AliESDEvent*> (event));
269     track = esdEvent->GetMuonTrack(itrack);
270   }
271   return track;
272 }
273
274 //________________________________________________________________________
275 Double_t AliAnalysisMuonUtility::MuonMass2()
276 {
277   /// A usefull constant
278   return 1.11636129640000012e-02;
279 }
280
281 //________________________________________________________________________
282 TLorentzVector AliAnalysisMuonUtility::GetTrackPair ( const AliVParticle* track1, const AliVParticle* track2 )
283 {
284   //
285   /// Get track pair
286   //
287   const AliVParticle* tracks[2] = {track1, track2};
288   
289   TLorentzVector vec[2];
290   for ( Int_t itrack=0; itrack<2; ++itrack ) {
291     Double_t trackP = tracks[itrack]->P();
292     Double_t energy = TMath::Sqrt(trackP*trackP + MuonMass2());
293     vec[itrack].SetPxPyPzE(tracks[itrack]->Px(), tracks[itrack]->Py(), tracks[itrack]->Pz(), energy);
294   }
295   
296   TLorentzVector vecPair = vec[0] + vec[1];
297   return vecPair;
298 }
299
300
301 //________________________________________________________________________
302 Bool_t AliAnalysisMuonUtility::IsAODMCTrack( const AliVParticle* mcParticle )
303 {
304   /// Check if track is from AOD MC
305   return ( mcParticle->IsA() == AliAODMCParticle::Class() );
306 }
307
308 //________________________________________________________________________
309 Bool_t AliAnalysisMuonUtility::IsMCTrack( const AliVParticle* mcParticle )
310 {
311   /// Check if track is MC track
312   return ( mcParticle->IsA() == AliAODMCParticle::Class() || mcParticle->IsA() == AliMCParticle::Class() );
313 }
314
315
316 //________________________________________________________________________
317 Double_t AliAnalysisMuonUtility::GetMCVertexZ ( const AliVEvent* event, const AliMCEvent* mcEvent )
318 {
319   /// Get MC vertex Z
320   Double_t vz = 0.;
321   if ( IsAODEvent(event) ) {
322     AliAODMCHeader* aodMCHeader = static_cast<AliAODMCHeader*> (static_cast<const AliAODEvent*>(event)->FindListObject(AliAODMCHeader::StdBranchName()));
323     vz = aodMCHeader->GetVtxZ();
324   }
325   else if ( mcEvent ) vz = mcEvent->GetPrimaryVertex()->GetZ();
326   else AliErrorClass("No MC event found");
327   return vz;
328 }
329
330 //________________________________________________________________________
331 Int_t AliAnalysisMuonUtility::GetMotherIndex ( const AliVParticle* mcParticle )
332 {
333   //
334   /// Return the mother index
335   //
336   return ( IsAODMCTrack(mcParticle) ) ? static_cast<const AliAODMCParticle*>(mcParticle)->GetMother() : static_cast<const AliMCParticle*>(mcParticle)->GetMother();
337 }
338
339 //________________________________________________________________________
340 Int_t AliAnalysisMuonUtility::GetDaughterIndex ( const AliVParticle* mcParticle, Int_t idaughter )
341 {
342   //
343   /// Return the daughter index
344   /// idaughter can be:
345   /// 0 -> first daughter
346   /// 1 -> last daughter
347   //
348   if ( idaughter < 0 || idaughter > 1 ) {
349     AliErrorClass(Form("Requested daughter %i Daughter index can be either 0 (first) or 1 (last)", idaughter));
350     return -1;
351   }
352   
353   if ( IsAODMCTrack(mcParticle) ) return static_cast<const AliAODMCParticle*>(mcParticle)->GetDaughter(idaughter);
354   
355   if ( idaughter == 0 ) return static_cast<const AliMCParticle*>(mcParticle)->GetFirstDaughter();
356   else return static_cast<const AliMCParticle*>(mcParticle)->GetLastDaughter();
357 }
358
359 //________________________________________________________________________
360 Bool_t AliAnalysisMuonUtility::IsPrimary ( const AliVParticle* mcParticle, const AliMCEvent* mcEvent )
361 {
362   /// Check if the particle is primary
363   
364   Bool_t isPrimary = kFALSE;
365   if ( IsAODMCTrack(mcParticle) ) isPrimary = static_cast<const AliAODMCParticle*>(mcParticle)->IsPrimary();
366   else if ( mcEvent ) {
367     // First get the index of the current particle in the stack.
368     // For this: get the mother, and get its daughter.
369     // Since the mother can have many daughters, you can come up to a "sister"
370     // of the particle. Nevertheless, if it is primary, then also the particle itself should be.
371     Int_t imother = static_cast<const AliMCParticle*> (mcParticle)->GetMother();
372     if ( imother < 0 ) isPrimary = kTRUE;
373     else if ( static_cast<const AliMCParticle*>(mcEvent->GetTrack(imother))->GetFirstDaughter() < const_cast<AliMCEvent*>(mcEvent)->GetNumberOfPrimaries() ) isPrimary = kTRUE;
374   }
375   else AliWarningClass("There is no MC info");
376   return isPrimary;
377 }
378
379 //________________________________________________________________________
380 UInt_t AliAnalysisMuonUtility::GetMCProcess ( const AliVParticle* mcParticle )
381 {
382   /// Get MC process
383   /// WARNING: the method may fail when running on AODs for old MC production,
384   /// the information was propagated to the AOD level only recently
385   UInt_t mcProcess = 0;
386   if ( IsAODMCTrack(mcParticle) ) {
387     mcProcess = const_cast<AliAODMCParticle*>(static_cast<const AliAODMCParticle*>(mcParticle))->GetMCProcessCode();
388   }
389   else if ( mcParticle->IsA() == AliMCParticle::Class() ) {
390     mcProcess = static_cast<const AliMCParticle*>(mcParticle)->Particle()->GetUniqueID();
391   }
392   else AliWarningClass("There is no MC info");
393   return mcProcess;
394 }
395
396 //________________________________________________________________________
397 UInt_t AliAnalysisMuonUtility::GetStatusCode ( const AliVParticle* mcParticle )
398 {
399   /// Get particle status code
400   UInt_t statusCode = 0;
401   if ( IsAODMCTrack(mcParticle) ) {
402     statusCode = static_cast<const AliAODMCParticle*>(mcParticle)->GetStatus();
403   }
404   else if ( mcParticle->IsA() == AliMCParticle::Class() ) {
405     statusCode = static_cast<const AliMCParticle*>(mcParticle)->Particle()->GetStatusCode();
406   }
407   else AliWarningClass("There is no MC info");
408   return statusCode;
409 }
410
411 //________________________________________________________________________
412 AliVVertex* AliAnalysisMuonUtility::GetVertexSPD ( const AliVEvent* event )
413 {
414   //
415   /// Get vertex SPD
416   //
417   
418   AliVVertex* primaryVertex = ( IsAODEvent(event) ) ? (AliVVertex*)static_cast<const AliAODEvent*>(event)->GetPrimaryVertexSPD() : (AliVVertex*)static_cast<const AliESDEvent*>(event)->GetPrimaryVertexSPD();
419   return primaryVertex;
420 }
421
422
423 //________________________________________________________________________
424 TString AliAnalysisMuonUtility::GetPassName ( const AliInputEventHandler* eventHandler )
425 {
426   /// Get pass name from event
427   
428   // At present there is no straightforward way to get the pass name.
429   // The pass name is usually written in the path to the ESDs/AODs
430   // but this won't work for:
431   // - MC data (no pass info available)
432   // - local ESDs/AODs
433   
434   TString filePath = "";
435   const AliVEvent* event = eventHandler->GetEvent();
436   if ( IsAODEvent(event) ) {
437     // In AODs, the header contains the path to the input ESD event
438     // However, sometimes there is not the FULL path of the ESDs.
439     // In that case we cannot extract the pass number.
440     // To increase the possibility of getting the pass number,
441     // try first to find the info in the AOD header
442     // (which is a priori safer because it works even on local copies of AODs)
443     // and if it does not work, directly check the path to the AOD
444     filePath = static_cast<const AliAODEvent*> (event)->GetHeader()->GetESDFileName();
445     TString passName = GetPassName(filePath.Data());
446     if ( passName.IsNull() ) AliWarningClass("Check again with the AOD path");
447     else return passName;
448   }
449   
450   filePath = eventHandler->GetTree()->GetCurrentFile()->GetName();
451   return GetPassName(filePath.Data());
452 }
453
454
455 //________________________________________________________________________
456 Int_t AliAnalysisMuonUtility::GetPassNumber ( const AliInputEventHandler* eventHandler )
457 {
458   /// Get pass number from event
459
460   // At present there is no straightforward way to get the pass number.
461   // The pass number is usually written in the path to the ESDs/AODs
462   // but this won't work for:
463   // - MC data (no pass info available)
464   // - local ESDs/AODs
465   
466   TString passName = GetPassName(eventHandler);
467   return GetPassNumber(passName);
468 }
469
470
471 //________________________________________________________________________
472 TString AliAnalysisMuonUtility::GetPassName ( const char* str )
473 {
474   //
475   /// Get pass name from string
476   //
477   
478   TString currName(str);
479   TObjArray* array = currName.Tokenize("/");
480   
481   TString passName = "";
482   for ( Int_t ientry=0; ientry<array->GetEntries(); ientry++ ) {
483     TString currToken = static_cast<TObjString*>(array->At(ientry))->GetString();
484     TString checkToken(currToken);
485     checkToken.ToUpper();
486     if ( checkToken.Contains("PASS") || checkToken.Contains("MUON_CALO") ) {
487       passName = currToken;
488       break;
489     }
490   }
491   
492   delete array;
493   
494   if ( passName.IsNull() ) AliWarningClass(Form("Cannot find pass name in: %s", str));
495   
496   return passName;
497 }
498
499 //________________________________________________________________________
500 Int_t AliAnalysisMuonUtility::GetPassNumber ( const char* str )
501 {
502   //
503   /// Get pass number from string
504   //
505   
506   TString currName(str);
507   currName.ToUpper();
508   Int_t idx = currName.Index("PASS");
509   if ( idx >= 0 ) {
510     // Remove all of the words before PASS (and remove the word PASS itself)
511     currName.Remove(0,idx+4);
512     // Cut the word from the end untill only the digits are left
513     // (In this way we can extract the pass number even if it has more than one digit)
514     while ( ! currName.IsDigit() && currName.Length() > 0 ) {
515       currName.Remove(currName.Length()-1);
516     }
517     
518     if ( currName.Length() > 0 ) return currName.Atoi();
519   }
520   
521   AliWarningClass(Form("Cannot find pass number in: %s", str));
522   return -1;
523 }
524
525 //________________________________________________________________________
526 TString AliAnalysisMuonUtility::GetTrackHistory ( const AliVParticle* track, const AliMCEvent* mcEvent, Bool_t verbose )
527 {
528   //
529   /// Get string containing particle history
530   /// Useful when debugging MC
531   //
532   TString trackHistory = "";
533   if ( ! mcEvent ) return trackHistory;
534   Int_t fakeMother = 999999999;
535   Int_t imother = IsMCTrack(track) ? fakeMother : track->GetLabel();
536
537   while ( imother >= 0 ) {
538     const AliVParticle* part = ( imother == fakeMother ) ? track : mcEvent->GetTrack(imother);
539     if ( ! part ) break; // In principle not needed...but for some old MC it breaks sometimes
540     TParticlePDG* partPdg = TDatabasePDG::Instance()->GetParticle(part->PdgCode());
541     TString pname = ( partPdg ) ? partPdg->GetName() : Form("%i",part->PdgCode());
542     if ( ! trackHistory.IsNull() ) trackHistory.Append(" <- ");
543     if ( imother != fakeMother ) trackHistory.Append(Form("%i ", imother));
544     trackHistory.Append(Form("(%s)", pname.Data()));
545     if ( verbose ) trackHistory.Append(Form(" [vz %g  mc %i]", part->Zv(), GetMCProcess(part)));
546     imother = AliAnalysisMuonUtility::GetMotherIndex(part);
547   }
548   return trackHistory;
549 }
550
551
552 //_______________________________________________________________________
553 Bool_t AliAnalysisMuonUtility::SetSparseRange(AliCFGridSparse* gridSparse,
554                                         Int_t ivar, TString labelName,
555                                         Double_t varMin, Double_t varMax,
556                                         TString option)
557 {
558   //
559   /// Set range in a smart way.
560   /// Allows to select a bin from the label.
561   /// Check the bin limits.
562   //
563   
564   option.ToUpper();
565   Int_t minVarBin = -1, maxVarBin = -1;
566   TAxis* axis = gridSparse->GetAxis(ivar);
567   
568   if ( ! axis ) {
569     printf("Warning: Axis %i not found in %s", ivar, gridSparse->GetName());
570     return kFALSE;
571   }
572   
573   if ( ! labelName.IsNull() ) {
574     minVarBin = axis->FindBin(labelName.Data());
575     maxVarBin = minVarBin;
576     if ( minVarBin < 1 ) {
577       printf("Warning: %s: label %s not found. Nothing done", gridSparse->GetName(), labelName.Data());
578       return kFALSE;
579     }
580   }
581   else if ( option.Contains( "USEBIN" ) ) {
582     minVarBin = (Int_t)varMin;
583     maxVarBin = (Int_t)varMax;
584   }
585   else {
586     minVarBin = axis->FindBin(varMin);
587     maxVarBin = axis->FindBin(varMax);
588   }
589   
590   if ( axis->GetFirst() == minVarBin && axis->GetLast() == maxVarBin ) return kFALSE;
591   
592   gridSparse->SetRangeUser(ivar, axis->GetBinCenter(minVarBin), axis->GetBinCenter(maxVarBin));
593   
594   return kTRUE;
595 }