Line data Source code
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 : #include "AliMUONPainterEnv.h"
19 :
20 : #include <TEnv.h>
21 : #include <TSystem.h>
22 : #include "TObjString.h"
23 : #include "TObjArray.h"
24 : #include "Riostream.h"
25 : #include "AliLog.h"
26 : #include <cassert>
27 : #include <limits>
28 :
29 : ///\class AliMUONPainterEnv
30 : ///
31 : /// A resource file handling class.
32 : ///
33 : /// Used to get some things persistent between two sessions of the mchview
34 : /// program.
35 : ///
36 : /// Main usage is for data sources.
37 : ///
38 : /// Syntax is :
39 : ///
40 : /// NumberOfDataSources: n
41 : /// DataSource.%d: ID;NAME;RANGES
42 : ///
43 : /// ID = ORIGIN|URI|TYPE
44 : /// URI = depends on source
45 : ///
46 : /// where ORIGIN might be OCDB or FILE
47 : /// (see AliMUONPainterDataSourceFrame::CreateOCDBDataSource())
48 : /// (see AliMUONPainterDataSourceFrame::CreateRawDataSource())
49 : /// (see AliMUONPainterDataSourceFrame::CreateACFDataSource())
50 : ///
51 : /// URI is a source dependent set of information (separated by |) needed to recreate the source, e.g.
52 : /// local:///cvmfs/alice-ocdb.cern.ch/calibration/data/2015/OCDB|216253
53 : ///
54 : /// TYPE is the data source type (e.g. PED, RAW, CALZ, see AliMUONPainterDataSourceTypes)
55 : ///
56 : /// NAME is a (unique) shortname for display, e.g. PED216253(alien)
57 : ///
58 : /// RANGES is a set of "|"-separated range definition. A range definition indicates,
59 : /// for one of the dimension of the data source, the min and max value to be plotted.
60 : /// Syntax is DIMNAME/XMIN/XMAX
61 : ///
62 : /// The full line ID NAME RANGES is called the data source descriptor
63 : ///
64 : /// Examples :
65 : ///
66 : /// DataSource.0: OCDB|local:///cvmfs/alice-ocdb.cern.ch/calibration/data/2015/OCDB|228901|PED;PED228901(cvmfs);Mean/0/500|Sigma/0/2
67 : ///
68 : ///
69 : /// Apart from data source descriptions, the following keywords are recognized :
70 : ///
71 : /// disableAutoPedCanvas: 0 | 1
72 : ///
73 : /// which is used to suppress the automatic creation of summary canvases when opening a pedestal source
74 : ///
75 : ///
76 : /// defaultRange: TYPE1/DIMNAME1/XMIN1/XMAX1|TYPE1/DIMNAME2/XMIN2/XMAX2
77 : ///
78 : /// example of defaultRange :
79 : ///
80 : /// defaultRange: PED/Mean/0/500|PED/Sigma/0/2|OCC/occ/0/0.01|HV/mean of HV/0/1650|
81 : ///
82 : /// which is used to define default ranges for some dimensions of some source types
83 : ///
84 : ///
85 : /// \author Laurent Aphecetche, Subatech
86 : ///
87 :
88 : ///\cond CLASSIMP
89 12 : ClassImp(AliMUONPainterEnv)
90 : ///\endcond
91 :
92 : const char* AliMUONPainterEnv::fgkNumberOfDataSourcesKey = "NumberOfDataSources";
93 : const char* AliMUONPainterEnv::fgkDataSourceKey = "DataSource.%d";
94 : const char* AliMUONPainterEnv::fgkDefaultRangeKey = "defaultRange";
95 : const char* AliMUONPainterEnv::fgkDisableAutoPedCanvasKey = "disableAutoPedCanvas";
96 : const char* AliMUONPainterEnv::fgkSeparatorWithinRange = "/";
97 : const char* AliMUONPainterEnv::fgkSeparatorWithinPart = "|";
98 : const char* AliMUONPainterEnv::fgkSeparatorBetweenDescriptorParts=";";
99 :
100 : //_____________________________________________________________________________
101 0 : AliMUONPainterEnv::AliMUONPainterEnv(const char* resourceFile)
102 0 : : fEnv(new TEnv(resourceFile))
103 0 : {
104 : /// Ctor
105 :
106 0 : if ( String(fgkDisableAutoPedCanvasKey,"").Length()==0 )
107 : {
108 : // no default for that one, assume it should be 1
109 0 : Set(fgkDisableAutoPedCanvasKey,1);
110 : }
111 :
112 0 : if ( String(fgkDefaultRangeKey,"").Length()==0 )
113 : {
114 : // no default ranges defined at all, let's make some reasonable guesses
115 :
116 0 : AliInfo("No default ranges defined in the resource file, generating a few...");
117 :
118 0 : SetDefaultRange("PED","Mean",0.0,500.0);
119 0 : SetDefaultRange("PED","Sigma",0.0,5.0);
120 0 : SetDefaultRange("OCC","occ",0.0,0.01);
121 0 : SetDefaultRange("HV","Mean of HV",0,1650);
122 :
123 0 : Save();
124 : }
125 0 : }
126 :
127 : //_____________________________________________________________________________
128 : AliMUONPainterEnv::~AliMUONPainterEnv()
129 0 : {
130 : /// dtor
131 0 : }
132 :
133 : //_____________________________________________________________________________
134 : TString AliMUONPainterEnv::AddDataSource(const char* dataSourceDescriptor)
135 : {
136 : /// Add (or replace) a data source to the list of data sources we handle
137 : /// Return the full descriptor of the data source
138 :
139 0 : TString name = Descriptor2Name(dataSourceDescriptor);
140 0 : TString sid = Descriptor2ID(dataSourceDescriptor);
141 0 : TString uri = ID2URI(sid);
142 :
143 0 : for ( Int_t i = 0; i < NumberOfDataSources(); ++i )
144 : {
145 0 : TString desc = DataSourceDescriptor(i);
146 0 : TString sid = Descriptor2ID(desc);
147 0 : TString urii = ID2URI(sid);
148 :
149 0 : if ( name == Descriptor2Name(desc) && uri == urii )
150 : {
151 : // already there, just replace
152 0 : Set(Form(fgkDataSourceKey,i),dataSourceDescriptor);
153 0 : return dataSourceDescriptor;
154 : }
155 0 : }
156 :
157 : // new source
158 :
159 0 : Int_t n = NumberOfDataSources();
160 :
161 0 : Set(fgkNumberOfDataSourcesKey,n+1);
162 :
163 0 : Set(Form(fgkDataSourceKey,n),dataSourceDescriptor);
164 :
165 0 : ForceDataSourceToDefaultRange(name);
166 :
167 0 : Save();
168 :
169 0 : return DataSourceDescriptor(name);
170 0 : }
171 :
172 : //_____________________________________________________________________________
173 : TString AliMUONPainterEnv::DataSourceDescriptor(Int_t index) const
174 : {
175 0 : if ( index >= 0 && index < NumberOfDataSources() )
176 : {
177 0 : return String(Form(fgkDataSourceKey,index),"");
178 : }
179 0 : return "";
180 0 : }
181 :
182 : //_____________________________________________________________________________
183 : TString AliMUONPainterEnv::DataSourceDescriptor(const char* dataSourceName) const
184 : {
185 0 : Int_t index = GetDataSourceIndex(dataSourceName);
186 0 : return DataSourceDescriptor(index);
187 0 : }
188 :
189 : //_____________________________________________________________________________
190 : TString AliMUONPainterEnv::DataSourceID(const char* dataSourceName) const
191 : {
192 0 : return Descriptor2ID(DataSourceDescriptor(dataSourceName));
193 0 : }
194 :
195 : //_____________________________________________________________________________
196 : TString AliMUONPainterEnv::DataSourceName(const char* dataSourceName) const
197 : {
198 0 : return Descriptor2Name(DataSourceDescriptor(dataSourceName));
199 0 : }
200 :
201 : //_____________________________________________________________________________
202 : TString AliMUONPainterEnv::DataSourceOrigin(const char* dataSourceName) const
203 : {
204 0 : return ID2Origin(DataSourceID(dataSourceName));
205 0 : }
206 :
207 : //_____________________________________________________________________________
208 : TString AliMUONPainterEnv::DataSourceRanges(const char* dataSourceName) const
209 : {
210 0 : return Descriptor2Ranges(DataSourceDescriptor(dataSourceName));
211 0 : }
212 :
213 : //_____________________________________________________________________________
214 : TString AliMUONPainterEnv::DataSourceType(const char* dataSourceName) const
215 : {
216 0 : return ID2Type(DataSourceID(dataSourceName));
217 0 : }
218 :
219 : //_____________________________________________________________________________
220 : TString AliMUONPainterEnv::DataSourceURI(const char* dataSourceName) const
221 : {
222 0 : return ID2URI(DataSourceID(dataSourceName));
223 0 : }
224 :
225 : //_____________________________________________________________________________
226 : TString AliMUONPainterEnv::Descriptor2Name(const char* dataSourceDescriptor)
227 : {
228 : /// From descriptor = ID NAME RANGES return the NAME part
229 :
230 0 : TString rv;
231 :
232 0 : TObjArray* a = TString(dataSourceDescriptor).Tokenize(fgkSeparatorBetweenDescriptorParts);
233 0 : if ( a->GetLast() >= 1 )
234 : {
235 0 : rv = static_cast<TObjString*>(a->At(1))->String();
236 : }
237 0 : delete a;
238 : return rv;
239 0 : }
240 :
241 : //_____________________________________________________________________________
242 : TString AliMUONPainterEnv::Descriptor2Ranges(const char* dataSourceDescriptor)
243 : {
244 : /// From descriptor = ID NAME RANGES return the RANGES part
245 :
246 0 : return TupleLast(dataSourceDescriptor,fgkSeparatorBetweenDescriptorParts);
247 0 : }
248 :
249 :
250 : //_____________________________________________________________________________
251 : TString AliMUONPainterEnv::Descriptor2ID(const char* dataSourceDescriptor)
252 : {
253 : /// From descriptor = ID NAME RANGES return the ID part
254 :
255 0 : return TupleFirst(dataSourceDescriptor,fgkSeparatorBetweenDescriptorParts);
256 0 : }
257 :
258 : //_____________________________________________________________________________
259 : Double_t
260 : AliMUONPainterEnv::Double(const char* resourceName, Double_t defaultValue) const
261 : {
262 : /// Retrieve the value associated with a given source, as a double
263 :
264 0 : return fEnv->GetValue(resourceName,defaultValue);
265 : }
266 :
267 : //__________________________________________________________________________________________________
268 : void AliMUONPainterEnv::ForceDataSourceToDefaultRange(const char* dataSourceName, const char* dimensionName)
269 : {
270 0 : TString desc = DataSourceDescriptor(dataSourceName);
271 :
272 0 : if ( desc.Length()==0 )
273 : {
274 0 : AliError(Form("Could not find data source named : %s",dataSourceName));
275 0 : return;
276 : }
277 :
278 0 : TString dsname = Descriptor2Name(desc);
279 :
280 0 : assert(dsname==dataSourceName);
281 :
282 0 : TString dataSourceType = DataSourceType(dataSourceName);
283 :
284 0 : TString newDescriptor = Descriptor2ID(desc);
285 :
286 0 : newDescriptor += fgkSeparatorBetweenDescriptorParts;
287 0 : newDescriptor += dsname;
288 :
289 : // at this stage the descriptor is back to "URI NAME"
290 : // now we add the existing ranges and replace the one corresponding to dim
291 : // (or all if dim="") by the default range(s) (if any is defined)
292 :
293 0 : newDescriptor += fgkSeparatorBetweenDescriptorParts;
294 :
295 0 : if ( strlen(dimensionName) == 0 )
296 : {
297 : // use all the default ranges for this data source
298 0 : TString defaultRange = GetDefaultRange(dataSourceType,"");
299 0 : newDescriptor += defaultRange;
300 0 : }
301 : else
302 : {
303 : // replace only the default range for dimensionName
304 0 : TString ranges = DataSourceRanges(dataSourceName);
305 :
306 0 : TObjArray* r = ranges.Tokenize(fgkSeparatorWithinPart);
307 0 : TString defaultRange = GetDefaultRange(dataSourceType,dimensionName);
308 :
309 0 : for ( Int_t i = 0; i <= r->GetLast(); ++i )
310 : {
311 0 : TObjString* sr = static_cast<TObjString*>(r->At(i));
312 :
313 0 : TString val = sr->String();
314 :
315 0 : if ( TupleFirst(sr->String(),fgkSeparatorWithinRange)==dimensionName )
316 : {
317 0 : if ( defaultRange.Length() )
318 : {
319 0 : val = defaultRange;
320 : }
321 : }
322 0 : newDescriptor += fgkSeparatorWithinPart;
323 0 : newDescriptor += val;
324 0 : }
325 :
326 0 : delete r;
327 0 : }
328 :
329 0 : Int_t index = GetDataSourceIndex(dataSourceName);
330 :
331 0 : Set(Form(fgkDataSourceKey,index),newDescriptor.Data());
332 0 : }
333 :
334 : //_____________________________________________________________________________
335 : Int_t AliMUONPainterEnv::GetDataSourceIndex(const char* dataSourceName) const
336 : {
337 0 : for ( Int_t i = 0; i < NumberOfDataSources(); ++i )
338 : {
339 0 : TString desc = DataSourceDescriptor(i);
340 :
341 0 : if ( Descriptor2Name(desc) == dataSourceName )
342 : {
343 0 : return i;
344 : }
345 0 : }
346 0 : return -1;
347 0 : }
348 :
349 : //_____________________________________________________________________________
350 : TString
351 : AliMUONPainterEnv::GetDefaultRange(const char* dataSourceType, const char* dimensionName) const
352 : {
353 : /// Get the default range for a given dimension
354 : /// if dimensionName="" return all the defined default ranges for this data source type
355 :
356 0 : TString defaultRanges = String(fgkDefaultRangeKey,"");
357 :
358 0 : TString rv;
359 :
360 0 : TObjArray* r = defaultRanges.Tokenize(fgkSeparatorWithinPart);
361 :
362 0 : for ( Int_t ir = 0; ir <= r->GetLast(); ++ir )
363 : {
364 0 : TObjString* s = static_cast<TObjString*>(r->At(ir));
365 :
366 0 : TObjArray* a = s->String().Tokenize(fgkSeparatorWithinRange);
367 0 : if ( a->GetLast() != 3 )
368 : {
369 0 : AliError(Form("Malformed %s string : %s",fgkDefaultRangeKey,s->String().Data()));
370 0 : continue;
371 : }
372 :
373 0 : TString typeName = static_cast<TObjString*>(a->At(0))->String();
374 :
375 0 : if (typeName==dataSourceType)
376 : {
377 0 : TString dimName = static_cast<TObjString*>(a->At(1))->String();
378 :
379 0 : if ( dimName == dimensionName || strlen(dimensionName) == 0 )
380 : {
381 0 : for ( Int_t i = 1; i <= 3; ++i )
382 : {
383 0 : rv += static_cast<TObjString*>(a->At(i))->String();
384 0 : if ( i < 3 )
385 : {
386 0 : rv += fgkSeparatorWithinRange;
387 : }
388 : }
389 0 : if ( ir < r->GetLast() )
390 : {
391 0 : rv += fgkSeparatorWithinPart;
392 : }
393 : }
394 0 : }
395 0 : delete a;
396 0 : }
397 :
398 0 : delete r;
399 :
400 : return rv;
401 0 : }
402 :
403 : //_____________________________________________________________________________
404 : TString AliMUONPainterEnv::ID2Origin(const char* dataSourceID)
405 : {
406 : /// From ID = ORIGIN|URI|TYPE return ORIGIN
407 0 : return TupleFirst(dataSourceID,fgkSeparatorWithinPart);
408 0 : }
409 :
410 : //_____________________________________________________________________________
411 : TString AliMUONPainterEnv::ID2URI(const char* dataSourceID)
412 : {
413 : /// From ID = ORIGIN|URI|TYPE return URI
414 0 : return TupleMiddle(dataSourceID,fgkSeparatorWithinPart);
415 0 : }
416 :
417 : //_____________________________________________________________________________
418 : TString AliMUONPainterEnv::ID2Type(const char* dataSourceID)
419 : {
420 : /// From ID = ORIGIN|URI|TYPE return TYPE
421 0 : return TupleLast(dataSourceID,fgkSeparatorWithinPart);
422 0 : }
423 :
424 : //_____________________________________________________________________________
425 : Int_t
426 : AliMUONPainterEnv::Integer(const char* resourceName, Int_t defaultValue) const
427 : {
428 : /// Retrieve the value associated with a given source, as an integer
429 :
430 0 : return fEnv->GetValue(resourceName,defaultValue);
431 : }
432 :
433 : //_____________________________________________________________________________
434 : Int_t
435 : AliMUONPainterEnv::NumberOfDataSources() const
436 : {
437 0 : return Integer(fgkNumberOfDataSourcesKey);
438 : }
439 :
440 : //_____________________________________________________________________________
441 : void
442 : AliMUONPainterEnv::Print(Option_t* opt) const
443 : {
444 0 : fEnv->Print(opt);
445 0 : }
446 :
447 : //_____________________________________________________________________________
448 : Bool_t AliMUONPainterEnv::Ranges2DimensionRange(const char* ranges,
449 : const char* dimensionName,
450 : Double_t& xmin,
451 : Double_t& xmax)
452 : {
453 0 : xmin = std::numeric_limits<double>::max();
454 0 : xmax = std::numeric_limits<double>::min();
455 :
456 0 : TString dims;
457 :
458 0 : TObjArray* a = TString(ranges).Tokenize(fgkSeparatorWithinPart);
459 :
460 0 : for ( Int_t i = 0; i <= a->GetLast(); ++i )
461 : {
462 0 : TString drange = static_cast<TObjString*>(a->At(i))->String();
463 : // drange should be of the form dimname/xmin/xmax
464 :
465 0 : TString bname = TupleFirst(drange,fgkSeparatorWithinRange);
466 :
467 0 : if ( bname == dimensionName )
468 : {
469 0 : xmin = TupleMiddle(drange,fgkSeparatorWithinRange).Atof();
470 0 : xmax = TupleLast(drange,fgkSeparatorWithinRange).Atof();
471 0 : break;
472 : }
473 0 : }
474 :
475 0 : return (xmin<xmax);
476 0 : }
477 :
478 : //_____________________________________________________________________________
479 : void
480 : AliMUONPainterEnv::Save()
481 : {
482 : /// Save the resource file
483 0 : fEnv->WriteFile(gSystem->ExpandPathName(Form("$HOME/%s",fEnv->GetRcName())));
484 0 : }
485 :
486 : //_____________________________________________________________________________
487 : void
488 : AliMUONPainterEnv::Set(const char* resourceName, Int_t value)
489 : {
490 : /// Set an integer resource
491 0 : fEnv->SetValue(resourceName,Form("%d",value));
492 0 : }
493 :
494 : //_____________________________________________________________________________
495 : void
496 : AliMUONPainterEnv::Set(const char* resourceName, const char* value)
497 : {
498 : /// Set a string resource
499 0 : fEnv->SetValue(resourceName,value);
500 0 : }
501 :
502 : //_____________________________________________________________________________
503 : void
504 : AliMUONPainterEnv::Set(const char* resourceName, Double_t value)
505 : {
506 : /// Set a double resource
507 :
508 0 : fEnv->SetValue(resourceName,Form("%g",value));
509 0 : }
510 :
511 : //_____________________________________________________________________________
512 : void AliMUONPainterEnv::SetDefaultRange(const char* dataSourceType, const char* dimensionName,
513 : Double_t xmin, Double_t xmax)
514 : {
515 : /// Set the default range of a given dimension for a data source type
516 :
517 0 : TString defaultRanges = String(fgkDefaultRangeKey,"");
518 :
519 0 : TObjArray* a = defaultRanges.Tokenize(fgkSeparatorWithinPart);
520 0 : TString newRange;
521 0 : TString def = Form("%s%s%s%s%g%s%g",
522 0 : dataSourceType,fgkSeparatorWithinRange,
523 : dimensionName,fgkSeparatorWithinRange,
524 : xmin,fgkSeparatorWithinRange,
525 : xmax);
526 : Bool_t replace(kFALSE);
527 :
528 0 : for ( Int_t i = 0 ; i<= a->GetLast(); ++i )
529 : {
530 0 : TObjString* s = static_cast<TObjString*>(a->At(i));
531 :
532 0 : TString dim = TupleSecond(s->String(),fgkSeparatorWithinRange);
533 :
534 0 : if ( dim == dimensionName )
535 : {
536 : replace = kTRUE;
537 0 : newRange += Form("%s%s%s%s%g%s%g",
538 0 : dataSourceType,fgkSeparatorWithinRange,
539 : dimensionName,fgkSeparatorWithinRange,
540 : xmin,fgkSeparatorWithinRange,
541 : xmax);
542 : }
543 : else
544 : {
545 0 : newRange += s->String();
546 : }
547 :
548 0 : newRange += fgkSeparatorWithinPart;
549 0 : }
550 :
551 0 : if (!replace)
552 : {
553 0 : newRange += def;
554 : }
555 :
556 0 : delete a;
557 :
558 0 : Set(fgkDefaultRangeKey,newRange.Data());
559 0 : }
560 :
561 : //_____________________________________________________________________________
562 : void AliMUONPainterEnv::SetDimensionRange(const char* dataSourceName, const char* dimensionName, Double_t xmin, Double_t xmax)
563 : {
564 : /// Replace i-th source dimension range by xmin,xmax
565 :
566 0 : TString desc = DataSourceDescriptor(dataSourceName);
567 0 : TString name = Descriptor2Name(desc);
568 0 : TString oldRanges = Descriptor2Ranges(desc);
569 :
570 0 : TObjArray* a = oldRanges.Tokenize(fgkSeparatorWithinPart);
571 :
572 0 : TString newRanges;
573 :
574 0 : for ( Int_t i = 0; i <= a->GetLast(); ++i )
575 : {
576 0 : TString drange = static_cast<TObjString*>(a->At(i))->String();
577 : // drange should be of the form dimname/xmin/xmax
578 :
579 0 : TString bname = TupleFirst(drange,fgkSeparatorWithinRange);
580 :
581 0 : if ( bname == dimensionName )
582 : {
583 0 : newRanges += Form("%s%s%g%s%g",bname.Data(),fgkSeparatorWithinRange,
584 : xmin,fgkSeparatorWithinRange,xmax);
585 : }
586 : else
587 : {
588 0 : newRanges += drange;
589 : }
590 0 : if ( i < a->GetLast() )
591 : {
592 0 : newRanges += fgkSeparatorWithinPart;
593 : }
594 0 : }
595 :
596 0 : delete a;
597 :
598 0 : AliInfo(Form("oldRanges=%s desc=%s newRanges=%s",oldRanges.Data(),desc.Data(),newRanges.Data()));
599 :
600 0 : AddDataSource(Form("%s%s%s%s%s",Descriptor2ID(desc).Data(),
601 0 : fgkSeparatorBetweenDescriptorParts,
602 0 : name.Data(),
603 0 : fgkSeparatorBetweenDescriptorParts,
604 0 : newRanges.Data()));
605 0 : }
606 :
607 : //_____________________________________________________________________________
608 : TString
609 : AliMUONPainterEnv::String(const char* resourceName, const char* defaultValue) const
610 : {
611 : /// Retrieve the value associated with a given source, as a string
612 :
613 0 : return fEnv->GetValue(resourceName,defaultValue);
614 : }
615 :
616 : //_____________________________________________________________________________
617 : TString AliMUONPainterEnv::TupleFirst(const TString& tuple, const char* sep)
618 : {
619 : /// Assuming tuple = aaa;bbb;....;yyy;zzz returns aaa
620 0 : Ssiz_t index = tuple.First(sep[0]);
621 0 : return tuple(0,index);
622 0 : }
623 :
624 : //_____________________________________________________________________________
625 : TString AliMUONPainterEnv::TupleSecond(const TString& tuple, const char* sep)
626 : {
627 : /// Assuming tuple = aaa;bbb;....;yyy;zzz returns bbb
628 0 : return TupleFirst(TupleMiddle(tuple,sep),sep);
629 0 : }
630 :
631 : //_____________________________________________________________________________
632 : TString AliMUONPainterEnv::TupleMiddle(const TString& tuple, const char* sep)
633 : {
634 : /// Assuming tuple = aaa;bbb;....;yyy;zzz returns bbb;....;yyy
635 0 : Ssiz_t i1 = tuple.First(sep[0]);
636 0 : Ssiz_t i2 = tuple.Last(sep[0]);
637 0 : return tuple(i1+1,i2-1);
638 0 : }
639 :
640 : //_____________________________________________________________________________
641 : TString AliMUONPainterEnv::TupleLast(const TString& tuple, const char* sep)
642 : {
643 : /// Assuming tuple = aaa;bbb;....;yyy;zzz returns zzz
644 0 : Ssiz_t index = tuple.Last(sep[0]);
645 0 : return tuple(index+1,tuple.Length()-index-1);
646 0 : }
647 :
|