]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/MUON/OfflineInterface/AliHLTMUONRecHitsSource.cxx
Changed AliRunLoader::GetRunLoader() into AliRunLoader::Instance()
[u/mrichter/AliRoot.git] / HLT / MUON / OfflineInterface / AliHLTMUONRecHitsSource.cxx
1 /**************************************************************************
2  * This file is property of and copyright by the ALICE HLT Project        *
3  * All rights reserved.                                                   *
4  *                                                                        *
5  * Primary Authors:                                                       *
6  *   Artur Szostak <artursz@iafrica.com>                                  *
7  *                                                                        *
8  * Permission to use, copy, modify and distribute this software and its   *
9  * documentation strictly for non-commercial purposes is hereby granted   *
10  * without fee, provided that the above copyright notice appears in all   *
11  * copies and that both the copyright notice and this permission notice   *
12  * appear in the supporting documentation. The authors make no claims     *
13  * about the suitability of this software for any purpose. It is          *
14  * provided "as is" without express or implied warranty.                  *
15  **************************************************************************/
16
17 /* $Id$ */
18
19 ///
20 /// @file   AliHLTMUONRecHitsSource.cxx
21 /// @author Artur Szostak <artursz@iafrica.com>
22 /// @date   
23 /// @brief  Implementation of the AliHLTMUONRecHitsSource component.
24 ///
25
26 #include "AliHLTMUONRecHitsSource.h"
27 #include "AliHLTMUONConstants.h"
28 #include "AliHLTMUONUtils.h"
29 #include "AliHLTMUONDataBlockWriter.h"
30 #include "AliMUONMCDataInterface.h"
31 #include "AliMUONDataInterface.h"
32 #include "AliMUONHit.h"
33 #include "AliMUONVCluster.h"
34 #include "AliMUONConstants.h"
35 #include "AliMUONVClusterStore.h"
36 #include "AliMUONVHitStore.h"
37 #include "mapping/AliMpCDB.h"
38 #include "mapping/AliMpDEManager.h"
39 #include "mapping/AliMpDetElement.h"
40 #include <cstdlib>
41 #include <cstdio>
42 #include <cerrno>
43 #include <cassert>
44 #include <new>
45
46 ClassImp(AliHLTMUONRecHitsSource);
47
48
49 AliHLTMUONRecHitsSource::AliHLTMUONRecHitsSource() :
50         AliHLTOfflineDataSource(),
51         fMCDataInterface(NULL),
52         fDataInterface(NULL),
53         fSelection(kWholePlane),
54         fCurrentEventIndex(0)
55 {
56         ///
57         /// Default constructor.
58         ///
59
60         for (Int_t i = 0; i < AliMUONConstants::NTrackingCh(); i++)
61                 fServeChamber[i] = false;
62 }
63
64
65 AliHLTMUONRecHitsSource::~AliHLTMUONRecHitsSource()
66 {
67         ///
68         /// Default destructor.
69         ///
70         
71         if (fMCDataInterface != NULL) delete fMCDataInterface;
72         if (fDataInterface != NULL) delete fDataInterface;
73 }
74
75
76 int AliHLTMUONRecHitsSource::DoInit(int argc, const char** argv)
77 {
78         ///
79         /// Inherited from AliHLTComponent.
80         /// Parses the command line parameters and initialises the component.
81         ///
82         
83         HLTInfo("Initialising dHLT reconstructed hit source component.");
84
85         if (fMCDataInterface != NULL)
86         {
87                 delete fMCDataInterface;
88                 fMCDataInterface = NULL;
89         }
90         if (fDataInterface != NULL)
91         {
92                 delete fDataInterface;
93                 fDataInterface = NULL;
94         }
95         
96         // Parse the command line arguments:
97         bool simdata = false;
98         bool recdata = false;
99         bool chamberWasSet = false;
100         fCurrentEventIndex = 0;
101         bool firstEventSet = false;
102         bool eventNumLitSet = false;
103         
104         for (int i = 0; i < argc; i++)
105         {
106                 if (strcmp(argv[i], "-simdata") == 0)
107                 {
108                         simdata = true;
109                 }
110                 else if (strcmp(argv[i], "-recdata") == 0)
111                 {
112                         recdata = true;
113                 }
114                 else if (strcmp(argv[i], "-plane") == 0)
115                 {
116                         i++;
117                         if (i >= argc)
118                         {
119                                 Logging(kHLTLogError,
120                                         "AliHLTMUONRecHitsSource::DoInit",
121                                         "Missing parameter",
122                                         "Expected one of 'left', 'right' or 'all' after '-plane'."
123                                 );
124                                 return -EINVAL;
125                         }
126                         if (strcmp(argv[i], "left") == 0)
127                                 fSelection = kLeftPlane;
128                         else if (strcmp(argv[i], "right") == 0)
129                                 fSelection = kRightPlane;
130                         else if (strcmp(argv[i], "all") == 0)
131                                 fSelection = kWholePlane;
132                         else
133                         {
134                                 Logging(kHLTLogError,
135                                         "AliHLTMUONRecHitsSource::DoInit",
136                                         "Invalid parameter",
137                                         "The parameter '%s' is invalid and must be one of 'left',"
138                                           " 'right' or 'all'.",
139                                         argv[i]
140                                 );
141                                 return -EINVAL;
142                         }
143                 }
144                 else if (strcmp(argv[i], "-chamber") == 0)
145                 {
146                         i++;
147                         if (i >= argc)
148                         {
149                                 Logging(kHLTLogError,
150                                         "AliHLTMUONRecHitsSource::DoInit",
151                                         "Missing parameter",
152                                         "Expected a chamber number, range eg. '1-10' or list eg."
153                                           " '1,2,3' after '-chamber'."
154                                 );
155                                 return -EINVAL;
156                         }
157                         int result = ParseChamberString(argv[i]);
158                         if (result != 0) return result;
159                         chamberWasSet = true;
160                 }
161                 else if (strcmp(argv[i], "-firstevent") == 0)
162                 {
163                         if (eventNumLitSet)
164                         {
165                                 HLTWarning("The -firstevent flag is overridden by a"
166                                         " previous use of -event_number_literal."
167                                 );
168                         }
169                         i++;
170                         if (i >= argc)
171                         {
172                                 HLTError("Expected a positive number after -firstevent.");
173                                 return -EINVAL;
174                         }
175                         char* end = NULL;
176                         long num = strtol(argv[i], &end, 0);
177                         if ((end != NULL and *end != '\0') or num < 0) // Check if the conversion is OK.
178                         {
179                                 HLTError(
180                                         "Expected a positive number after -firstevent"
181                                         " but got: %s", argv[i]
182                                 );
183                                 return -EINVAL;
184                         }
185                         fCurrentEventIndex = Int_t(num);
186                         firstEventSet = true;
187                 }
188                 else if (strcmp(argv[i], "-event_number_literal") == 0)
189                 {
190                         if (firstEventSet)
191                         {
192                                 HLTWarning("The -event_number_literal option will"
193                                         " override -firstevent."
194                                 );
195                         }
196                         fCurrentEventIndex = -1;
197                         eventNumLitSet = true;
198                 }
199                 else
200                 {
201                         Logging(kHLTLogError,
202                                 "AliHLTMUONRecHitsSource::DoInit",
203                                 "Unknown argument",
204                                 "The argument '%s' is invalid.",
205                                 argv[i]
206                         );
207                         return -EINVAL;
208                 }
209         }
210
211         // Check the parameters we have parsed.
212         if (simdata and recdata)
213         {
214                 Logging(kHLTLogError,
215                         "AliHLTMUONRecHitsSource::DoInit",
216                         "Invalid arguments",
217                         "Cannot have both -simdata and -recdata set."
218                 );
219                 return -EINVAL;
220         }
221         
222         if (not simdata and not recdata)
223         {
224                 Logging(kHLTLogError,
225                         "AliHLTMUONRecHitsSource::DoInit",
226                         "Missing arguments",
227                         "Must have either -simdata or -recdata specified."
228                 );
229                 return -EINVAL;
230         }
231         
232         if (not chamberWasSet)
233         {
234                 Logging(kHLTLogInfo,
235                         "AliHLTMUONRecHitsSource::DoInit",
236                         "Setting Parameters",
237                         "No chambers were selected so we will publish for all chambers."
238                 );
239                 for (Int_t i = 0; i < AliMUONConstants::NTrackingCh(); i++)
240                         fServeChamber[i] = true;
241         }
242         
243         // Must load the mapping data for AliMpDetElement::GetDdlId()
244         // to return useful information later on.
245         AliMpCDB::LoadDDLStore();
246                 
247         // Now we can initialise the data interface objects and loaders.
248         if (simdata)
249         {
250                 Logging(kHLTLogDebug,
251                         "AliHLTMUONRecHitsSource::DoInit",
252                         "Data interface",
253                         "Loading simulated GEANT hits with AliMUONMCDataInterface."
254                 );
255
256                 try
257                 {
258                         fMCDataInterface = new AliMUONMCDataInterface("galice.root");
259                 }
260                 catch (const std::bad_alloc&)
261                 {
262                         Logging(kHLTLogError,
263                                 "AliHLTMUONRecHitsSource::DoInit",
264                                 "Out of memory",
265                                 "Not enough memory to allocate AliMUONMCDataInterface."
266                         );
267                         return -ENOMEM;
268                 }
269         }
270         else if (recdata)
271         {
272                 Logging(kHLTLogDebug,
273                         "AliHLTMUONRecHitsSource::DoInit",
274                         "Data interface",
275                         "Loading reconstructed clusters with AliMUONDataInterface."
276                 );
277                 
278                 try
279                 {
280                         fDataInterface = new AliMUONDataInterface("galice.root");
281                 }
282                 catch (const std::bad_alloc&)
283                 {
284                         Logging(kHLTLogError,
285                                 "AliHLTMUONRecHitsSource::DoInit",
286                                 "Out of memory",
287                                 "Not enough memory to allocate AliMUONDataInterface."
288                         );
289                         return -ENOMEM;
290                 }
291         }
292         
293         // Check that the fCurrentEventIndex number falls within the correct range.
294         UInt_t maxevent = 0;
295         if (fMCDataInterface != NULL)
296                 maxevent = UInt_t(fMCDataInterface->NumberOfEvents());
297         else if (fDataInterface != NULL)
298                 maxevent = UInt_t(fDataInterface->NumberOfEvents());
299         if (fCurrentEventIndex != -1 and UInt_t(fCurrentEventIndex) >= maxevent and maxevent != 0)
300         {
301                 fCurrentEventIndex = 0;
302                 HLTWarning(Form("The selected first event number (%d) was larger than"
303                         " the available number of events (%d). Resetting the event"
304                         " counter to zero.", fCurrentEventIndex, maxevent
305                 ));
306         }
307         
308         return 0;
309 }
310
311
312 int AliHLTMUONRecHitsSource::DoDeinit()
313 {
314         ///
315         /// Inherited from AliHLTComponent. Performs a cleanup of the component.
316         ///
317         
318         HLTInfo("Deinitialising dHLT reconstructed hit source component.");
319         
320         if (fMCDataInterface != NULL)
321         {
322                 delete fMCDataInterface;
323                 fMCDataInterface = NULL;
324         }
325         if (fDataInterface != NULL)
326         {
327                 delete fDataInterface;
328                 fDataInterface = NULL;
329         }
330         return 0;
331 }
332
333
334 const char* AliHLTMUONRecHitsSource::GetComponentID()
335 {
336         ///
337         /// Inherited from AliHLTComponent. Returns the component ID.
338         ///
339         
340         return AliHLTMUONConstants::RecHitsSourceId();
341 }
342
343
344 AliHLTComponentDataType AliHLTMUONRecHitsSource::GetOutputDataType()
345 {
346         ///
347         /// Inherited from AliHLTComponent. Returns the output data type.
348         ///
349         
350         return AliHLTMUONConstants::RecHitsBlockDataType();
351 }
352
353
354 void AliHLTMUONRecHitsSource::GetOutputDataSize(
355                 unsigned long& constBase, double& inputMultiplier
356         )
357 {
358         ///
359         /// Inherited from AliHLTComponent. Returns an estimate of the expected output data size.
360         ///
361         
362         constBase = sizeof(AliHLTMUONRecHitsBlockStruct)
363                 + 256*16*sizeof(AliHLTMUONRecHitStruct);
364         inputMultiplier = 0;
365 }
366
367
368 AliHLTComponent* AliHLTMUONRecHitsSource::Spawn()
369 {
370         ///
371         /// Inherited from AliHLTComponent. Creates a new object instance.
372         ///
373         
374         return new AliHLTMUONRecHitsSource();
375 }
376
377
378 int AliHLTMUONRecHitsSource::GetEvent(
379                 const AliHLTComponentEventData& evtData,
380                 AliHLTComponentTriggerData& /*trigData*/,
381                 AliHLTUInt8_t* outputPtr, 
382                 AliHLTUInt32_t& size,
383                 AliHLTComponentBlockDataList& outputBlocks
384         )
385 {
386         ///
387         /// Inherited from AliHLTOfflineDataSource. Creates new event data blocks.
388         ///
389         
390         assert( fMCDataInterface != NULL or fDataInterface != NULL );
391         
392         if (not IsDataEvent()) return 0;  // ignore non data events.
393
394         // Check the size of the event descriptor structure.
395         if (evtData.fStructSize < sizeof(AliHLTComponentEventData))
396         {
397                 Logging(kHLTLogError,
398                         "AliHLTMUONRecHitsSource::GetEvent",
399                         "Invalid event descriptor",
400                         "The event descriptor (AliHLTComponentEventData) size is"
401                           " smaller than expected. It claims to be %d bytes, but"
402                           " we expect it to be %d bytes.",
403                         evtData.fStructSize,
404                         sizeof(AliHLTComponentEventData)
405                 );
406                 size = 0; // Important to tell framework that nothing was generated.
407                 return -EINVAL;
408         }
409         
410         // Use the fEventID as the event number to load if fCurrentEventIndex == -1,
411         // check it and load that event with the runloader.
412         // If fCurrentEventIndex is a positive number then use it instead and
413         // increment it.
414         UInt_t eventnumber = UInt_t(evtData.fEventID);
415         UInt_t maxevent = 0;
416         if (fMCDataInterface != NULL)
417                 maxevent = UInt_t(fMCDataInterface->NumberOfEvents());
418         else if (fDataInterface != NULL)
419                 maxevent = UInt_t(fDataInterface->NumberOfEvents());
420         if (fCurrentEventIndex != -1)
421         {
422                 eventnumber = UInt_t(fCurrentEventIndex);
423                 fCurrentEventIndex++;
424                 if (UInt_t(fCurrentEventIndex) >= maxevent)
425                         fCurrentEventIndex = 0;
426         }
427         if ( eventnumber >= maxevent )
428         {
429                 Logging(kHLTLogError,
430                         "AliHLTMUONRecHitsSource::GetEvent",
431                         "Bad event ID",
432                         "The event number (%d) is larger than the available number"
433                           " of events on file (%d).",
434                         eventnumber,
435                         maxevent
436                 );
437                 size = 0; // Important to tell framework that nothing was generated.
438                 return -EINVAL;
439         }
440         
441         // Create and initialise a new data block.
442         AliHLTMUONRecHitsBlockWriter block(outputPtr, size);
443         if (not block.InitCommonHeader())
444         {
445                 Logging(kHLTLogError,
446                         "AliHLTMUONRecHitsSource::GetEvent",
447                         "Buffer too small",
448                         "There is not enough buffer space to create a new data block."
449                           " We require at least %d bytes but the buffer is only %d bytes.",
450                         sizeof(AliHLTMUONRecHitsBlockWriter::HeaderType),
451                         block.BufferSize()
452                 );
453                 size = 0; // Important to tell framework that nothing was generated.
454                 return -ENOBUFS;
455         }
456         
457         // Initialise the DDL list containing the DDLs which contributed to the
458         // data block. These are required to create the specification word later.
459         bool ddlList[22];
460         for (Int_t i = 0; i < 22; i++)
461                 ddlList[i] = false;
462         
463         if (fMCDataInterface != NULL)
464         {
465                 Logging(kHLTLogDebug,
466                         "AliHLTMUONRecHitsSource::GetEvent",
467                         "Filling hits",
468                         "Filling data block with GEANT hits for event %d.",
469                         eventnumber
470                 );
471                 
472                 // Loop over all tracks, extract the hits and write them to the
473                 // data block.
474                 Int_t ntracks = fMCDataInterface->NumberOfTracks(eventnumber);
475                 for (Int_t i = 0; i < ntracks; ++i)
476                 {
477                         AliMUONVHitStore* hitStore = fMCDataInterface->HitStore(eventnumber,i);
478                         AliMUONHit* hit;
479                         TIter next(hitStore->CreateIterator());
480                         while ( ( hit = static_cast<AliMUONHit*>(next()) ) )
481                         {
482                                 // Select only hits on selected chambers.
483                                 Int_t chamber = hit->Chamber() - 1;
484                                 if (chamber > AliMUONConstants::NTrackingCh()) continue;
485                                 if (not fServeChamber[chamber]) continue;
486                                 
487                                 // Only select hits from the given part of the plane
488                                 if (fSelection == kLeftPlane and not (hit->Xref() < 0)) continue;
489                                 if (fSelection == kRightPlane and not (hit->Xref() >= 0)) continue;
490                                 
491                                 AliHLTMUONRecHitStruct* rechit = block.AddEntry();
492                                 if (rechit == NULL)
493                                 {
494                                         Logging(kHLTLogError,
495                                                 "AliHLTMUONRecHitsSource::GetEvent",
496                                                 "Buffer overflow",
497                                                 "There is not enough buffer space to add more hits."
498                                                   " We overflowed the buffer which is only %d bytes.",
499                                                 block.BufferSize()
500                                         );
501                                         size = 0; // Important to tell framework that nothing was generated.
502                                         return -ENOBUFS;
503                                 }
504                                 
505                                 rechit->fX = hit->Xref();
506                                 rechit->fY = hit->Yref();
507                                 rechit->fZ = hit->Zref();
508                                 
509                                 // Workout which DDL this hit will be readout of.
510                                 AliMpDetElement* de = AliMpDEManager::GetDetElement(hit->DetElemId());
511                                 if (de != NULL and (0 <= de->GetDdlId() and de->GetDdlId() < 22))
512                                         ddlList[de->GetDdlId()] = true;
513                                 else
514                                         Logging(kHLTLogError,
515                                                 "AliHLTMUONRecHitsSource::GetEvent",
516                                                 "No DDL ID",
517                                                 "Could not find the DDL ID from which readout would take place."
518                                         );
519                         }
520                 }
521         }
522         else if (fDataInterface != NULL)
523         {
524                 Logging(kHLTLogDebug,
525                         "AliHLTMUONRecHitsSource::GetEvent",
526                         "Filling hits",
527                         "Filling data block with reconstructed raw clusters for event %d.",
528                         eventnumber
529                 );
530                 
531                 AliMUONVClusterStore* clusterStore = fDataInterface->ClusterStore(eventnumber);
532     
533                 // Loop over selected chambers and extract the raw clusters.
534                 for (Int_t chamber = 0; chamber < AliMUONConstants::NTrackingCh(); chamber++)
535                 {
536                         // Select only hits on selected chambers.
537                         if (not fServeChamber[chamber]) continue;
538                         
539                         TIter next(clusterStore->CreateChamberIterator(chamber,chamber));
540                         AliMUONVCluster* cluster;
541                         while ( ( cluster = static_cast<AliMUONVCluster*>(next()) ) )
542                         {
543                                 // Only select hits from the given part of the plane
544                                 if (fSelection == kLeftPlane and not (cluster->GetX() < 0)) continue;
545                                 if (fSelection == kRightPlane and not (cluster->GetX() >= 0)) continue;
546                         
547                                 AliHLTMUONRecHitStruct* rechit = block.AddEntry();
548                                 if (rechit == NULL)
549                                 {
550                                         Logging(kHLTLogError,
551                                                 "AliHLTMUONRecHitsSource::GetEvent",
552                                                 "Buffer overflow",
553                                                 "There is not enough buffer space to add more hits."
554                                                   " We overflowed the buffer which is only %d bytes.",
555                                                 block.BufferSize()
556                                         );
557                                         size = 0; // Important to tell framework that nothing was generated.
558                                         return -ENOBUFS;
559                                 }
560                                 
561                                 rechit->fX = cluster->GetX();
562                                 rechit->fY = cluster->GetY();
563                                 rechit->fZ = cluster->GetZ();
564                                 
565                                 // Workout which DDL this hit will be readout of.
566                                 AliMpDetElement* de = AliMpDEManager::GetDetElement(cluster->GetDetElemId());
567                                 if (de != NULL and (0 <= de->GetDdlId() and de->GetDdlId() < 22))
568                                         ddlList[de->GetDdlId()] = true;
569                                 else
570                                         Logging(kHLTLogError,
571                                                 "AliHLTMUONRecHitsSource::GetEvent",
572                                                 "No DDL ID",
573                                                 "Could not find the DDL ID from which readout would take place."
574                                         );
575                         }
576                 }
577         }
578         else
579         {
580                 Logging(kHLTLogError,
581                         "AliHLTMUONRecHitsSource::GetEvent",
582                         "Missing data interface",
583                         "Neither AliMUONDataInterface nor AliMUONMCDataInterface were created."
584                 );
585                 size = 0; // Important to tell framework that nothing was generated.
586                 return -EFAULT;
587         }
588         
589         AliHLTComponentBlockData bd;
590         FillBlockData(bd);
591         bd.fPtr = outputPtr;
592         bd.fOffset = 0;
593         bd.fSize = block.BytesUsed();
594         bd.fDataType = AliHLTMUONConstants::RecHitsBlockDataType();
595         bd.fSpecification = AliHLTMUONUtils::PackSpecBits(ddlList);
596         outputBlocks.push_back(bd);
597         size = block.BytesUsed();
598
599         return 0;
600 }
601
602
603 int AliHLTMUONRecHitsSource::ParseChamberString(const char* str)
604 {
605         ///
606         /// Parses a string with the following format:
607         ///   <number>|<number>-<number>[,<number>|<number>-<number>]...
608         /// For example: 1  1,2,3  1-2   1,2-4,5  etc...
609         /// Flags in the fServeChamber will be set to 'true' for all appropriate
610         /// values parsed.
611         /// @param str  The string to parse.
612         /// @return  Zero on success and EINVAL if there is a parse error.
613         ///
614         
615         char* end = const_cast<char*>(str);
616         long lastChamber = -1;
617         do
618         {
619                 // Parse the next number.
620                 char* current = end;
621                 long chamber = strtol(current, &end, 0);
622                 
623                 // Check for parse errors of the number.
624                 if (current == end)
625                 {
626                         Logging(kHLTLogError,
627                                 "AliHLTMUONRecHitsSource::GetEvent",
628                                 "Parse error",
629                                 "Expected a number in the range [1..%d] but got '%s'.",
630                                 AliMUONConstants::NTrackingCh(), current
631                         );
632                         return -EINVAL;
633                 }
634                 if (chamber < 1 or AliMUONConstants::NTrackingCh() < chamber)
635                 {
636                         Logging(kHLTLogError,
637                                 "AliHLTMUONRecHitsSource::GetEvent",
638                                 "Parse error",
639                                 "Got the chamber number %d which is outside the valid range of [1..%d].",
640                                 chamber, AliMUONConstants::NTrackingCh()
641                         );
642                         return -EINVAL;
643                 }
644                 
645                 // Skip any whitespace after the number
646                 while (*end != '\0' and (*end == ' ' or *end == '\t' or *end == '\r' or *end == '\n')) end++;
647                 
648                 // Check if we are dealing with a list or range, or if we are at
649                 // the end of the string.
650                 if (*end == '-')
651                 {
652                         lastChamber = chamber;
653                         end++;
654                         continue;
655                 }
656                 else if (*end == ',')
657                 {
658                         assert( 1 <= chamber and chamber <= 10 );
659                         fServeChamber[chamber-1] = true;
660                         end++;
661                 }
662                 else if (*end == '\0')
663                 {
664                         assert( 1 <= chamber and chamber <= 10 );
665                         fServeChamber[chamber-1] = true;
666                 }
667                 else
668                 {
669                         Logging(kHLTLogError,
670                                 "AliHLTMUONRecHitsSource::GetEvent",
671                                 "Parse error",
672                                 "Could not understand parameter list '%s'. Expected '-', ','"
673                                   " or end of line but got '%c' at character %d.",
674                                 str, *end, (int)(end - str) +1
675                         );
676                         return -EINVAL;
677                 }
678                 
679                 // Set the range of chambers to publish for.
680                 if (lastChamber > 0)
681                 {
682                         Int_t min, max;
683                         if (lastChamber < chamber)
684                         {
685                                 min = lastChamber;
686                                 max = chamber;
687                         }
688                         else
689                         {
690                                 min = chamber;
691                                 max = lastChamber;
692                         }
693                         assert( min >= 1 );
694                         assert( max <= 10 );
695                         for (Int_t i = min; i <= max; i++)
696                                 fServeChamber[i-1] = true;
697                 }
698                 lastChamber = -1;
699         }
700         while (*end != '\0');
701         return 0;
702 }