Bogdan: fix calculation of squared momentum.
[u/mrichter/AliRoot.git] / EVE / Alieve / MUONData.cxx
CommitLineData
3626c858 1//
2// Sources:
3//
4// GetTrackerMapping = AliMUONDigitMaker::GetMapping
5// GetTriggerMapping = AliMUONDigitMaker::TriggerDigits
6// GetTriggerChamber = AliMUONDigitMaker::GetTriggerChamber
7// LoadRawTracker = MUONRawStreamTracker.C
8// LoadRawTrigger = MUONRawStreamTrigger.C
9//
10
11#include "MUONData.h"
12
13#include <Alieve/MUONChamberData.h>
14#include <Alieve/EventAlieve.h>
15
16#include <AliRawReader.h>
17#include <AliRawReaderFile.h>
18#include <AliRawReaderDate.h>
19#include <AliRawReaderRoot.h>
20
361fa326 21#include <AliLog.h>
3626c858 22
eadce74d 23#include <AliMUONHit.h>
24#include <AliMUONRawCluster.h>
3626c858 25#include <AliMUONDigit.h>
26#include <AliMUONRawStreamTracker.h>
27#include <AliMUONRawStreamTrigger.h>
28#include <AliMUONDDLTracker.h>
29#include <AliMUONBlockHeader.h>
30#include <AliMUONDspHeader.h>
31#include <AliMUONBusStruct.h>
32#include <AliMUONDDLTrigger.h>
33#include <AliMUONDarcHeader.h>
34#include <AliMUONRegHeader.h>
35#include <AliMUONLocalStruct.h>
36#include <AliMUONTriggerCrateStore.h>
37#include <AliMUONTriggerCrate.h>
38#include <AliMUONLocalTriggerBoard.h>
39#include <AliMUONTriggerCircuit.h>
361fa326 40#include <mapping/AliMpDDLStore.h>
3626c858 41#include <mapping/AliMpVSegmentation.h>
42#include <mapping/AliMpSegmentation.h>
43#include <mapping/AliMpPad.h>
44#include <mapping/AliMpDEManager.h>
45
46#include "TTree.h"
47#include "TString.h"
3626c858 48#include "TClonesArray.h"
49
50using namespace Reve;
51using namespace Alieve;
52
53//______________________________________________________________________
54// MUONData
55//
56
57ClassImp(MUONData)
58
59AliRawReader* MUONData::fgRawReader = 0;
60AliMUONRawStreamTracker* MUONData::fgRawStreamTracker = 0;
61AliMUONRawStreamTrigger* MUONData::fgRawStreamTrigger = 0;
361fa326 62AliMpDDLStore* MUONData::fgBusPatchManager = 0;
3626c858 63
64//______________________________________________________________________
65MUONData::MUONData() :
eadce74d 66 fChambers(14),
67 fNTrackList(0)
3626c858 68{
69 //
70 // Constructor
71 //
72
eadce74d 73 for (Int_t i = 0; i < 100; i++) {
74 fTrackList[i] = -1;
75 }
76
3626c858 77 CreateAllChambers();
78
79}
80
81//______________________________________________________________________
82MUONData::~MUONData()
83{
84 //
85 // Destructor
86 //
87
88 DeleteAllChambers();
89
3626c858 90}
91
eadce74d 92//______________________________________________________________________
93void MUONData::Reset()
94{
95 //
96 // Reset data
97 //
98
99 //DropAllChambers();
100
101 fNTrackList = 0;
102 for (Int_t i = 0; i < 100; i++) {
103 fTrackList[i] = -1;
104 }
105
106}
107
3626c858 108//______________________________________________________________________
109MUONData::MUONData(const MUONData &mdata) :
e4204218 110 TObject(mdata),
111 Reve::ReferenceCount()
3626c858 112{
113 //
114 // Copy constructor
115 //
116
117}
118
119//______________________________________________________________________
120MUONData& MUONData::operator=(const MUONData &mdata)
121{
122 //
123 // Assignment operator
124 //
125
126 if (this != &mdata) {
127
128 }
129
130 return *this;
131
132}
133
134//______________________________________________________________________
135void MUONData::CreateChamber(Int_t chamber)
136{
137 //
138 // create data for the chamber with id=chamber (0 to 13)
139 //
140
141 if (fChambers[chamber] == 0)
142 fChambers[chamber] = new MUONChamberData(chamber);
143
144}
145
146//______________________________________________________________________
147void MUONData::CreateAllChambers()
148{
149 //
150 // create all 14 chambers data
151 //
152
153 for (Int_t c = 0; c < 14; ++c)
154 CreateChamber(c);
155
156}
157
158//______________________________________________________________________
159void MUONData::DropAllChambers()
160{
161 //
162 // release data from all chambers
163 //
164
165 for (Int_t c = 0; c < 14; ++c) {
166
167 if (fChambers[c] != 0)
168 fChambers[c]->DropData();
169
170 }
171
172}
173
174//______________________________________________________________________
175void MUONData::DeleteAllChambers()
176{
177 //
178 // delete all chambers data
179 //
180
181 for (Int_t c = 0; c < 14; ++c) {
182
183 delete fChambers[c];
184 fChambers[c] = 0;
185
186 }
187
188}
189
eadce74d 190//______________________________________________________________________
191void MUONData::RegisterTrack(Int_t track)
192{
193 //
194 // register (in a list) a track with hits in the chambers
195 //
196
197 if (fNTrackList >= 100) {
198 cout << "Maximum of registered tracks reached..." << endl;
199 return;
200 }
201
202 Bool_t inList = kFALSE;
203 for (Int_t i = 0; i < fNTrackList; i++) {
204 if (track == fTrackList[i]) {
205 inList = kTRUE;
206 break;
207 }
208 }
209 if (!inList) {
210 fTrackList[fNTrackList] = track;
211 fNTrackList++;
212 }
213
214}
215
3626c858 216//______________________________________________________________________
217void MUONData::LoadDigits(TTree* tree)
218{
219 //
220 // load digits from the TreeD
221 //
222
223 Char_t branchname[30];
224 TClonesArray *digits = 0;
225 Int_t ndigits;
226 AliMUONDigit *mdig;
227 Int_t cathode, detElemId, ix, iy, charge;
228
229 for (Int_t c = 0; c < 14; ++c) {
230
231 if (fChambers[c] == 0) continue;
232 sprintf(branchname,"MUONDigits%d",c+1);
233 tree->SetBranchAddress(branchname,&digits);
234 tree->GetEntry(0);
235
236 ndigits = digits->GetEntriesFast();
237
238 for (Int_t id = 0; id < ndigits; id++) {
239 mdig = (AliMUONDigit*)digits->UncheckedAt(id);
240
241 cathode = mdig->Cathode();
242 ix = mdig->PadX();
243 iy = mdig->PadY();
244 detElemId = mdig->DetElemId();
245 charge = (Int_t)mdig->Signal();
246
3626c858 247 fChambers[c]->RegisterDigit(detElemId,cathode,ix,iy,charge);
eadce74d 248
3626c858 249 } // end digits loop
250
251 }
252
253}
254
2674c15a 255//______________________________________________________________________
eadce74d 256void MUONData::LoadRecPoints(TTree* tree)
2674c15a 257{
258 //
259 // load reconstructed points from the TreeR
260 // load local trigger information
261 //
262
eadce74d 263 Char_t branchname[30];
264 TClonesArray *clusters = 0;
265 Int_t nclusters;
266 AliMUONRawCluster *mcls;
267 Int_t detElemId;
268 Float_t clsX, clsY, clsZ, charge;
269
270 for (Int_t c = 0; c < 10; ++c) {
271
272 if (fChambers[c] == 0) continue;
273 sprintf(branchname,"MUONRawClusters%d",c+1);
274 tree->SetBranchAddress(branchname,&clusters);
275 tree->GetEntry(0);
276
277 nclusters = clusters->GetEntriesFast();
278
279 for (Int_t ic = 0; ic < nclusters; ic++) {
280 mcls = (AliMUONRawCluster*)clusters->UncheckedAt(ic);
281
282 detElemId = mcls->GetDetElemId();
283 for (Int_t icath = 0; icath < 2; icath++) {
284 clsX = mcls->GetX(icath);
285 clsY = mcls->GetY(icath);
286 clsZ = mcls->GetZ(icath);
287 charge = mcls->GetCharge(icath);
288
289 fChambers[c]->RegisterCluster(detElemId,icath,clsX,clsY,clsZ,charge);
290 }
291
292 }
293
294 }
295
296}
297
298//______________________________________________________________________
299void MUONData::LoadHits(TTree* tree)
300{
301 //
302 // load simulation hits from the TreeH
303 //
304
305 TClonesArray *hits = 0;
306 AliMUONHit *mhit;
307 Int_t cha, detElemId, nhits, ntracks;
308 Float_t hitX, hitY, hitZ;
309
310 ntracks = tree->GetEntries();
311 tree->SetBranchAddress("MUONHits",&hits);
312
313 for (Int_t it = 0; it < ntracks; it++) {
314
315 tree->GetEvent(it);
316 nhits = hits->GetEntriesFast();
317
318 for (Int_t ih = 0; ih < nhits; ih++) {
319
320 mhit = (AliMUONHit*)hits->UncheckedAt(ih);
321 hitX = mhit->X();
322 hitY = mhit->Y();
323 hitZ = mhit->Z();
324 detElemId = mhit->DetElemId();
325 cha = mhit->Chamber();
326
327 RegisterTrack(mhit->GetTrack());
328
329 fChambers[cha-1]->RegisterHit(detElemId,hitX,hitY,hitZ);
330
331 }
332 }
333
2674c15a 334}
335
3626c858 336//______________________________________________________________________
337void MUONData::LoadRaw(TString fileName)
338{
339 //
340 // load raw data from fileName; tracker and trigger data
341 //
342
343 if (fgRawReader == 0) {
344 // check extention to choose the rawdata file format
345 if (fileName.EndsWith("/")) {
346 fgRawReader = new AliRawReaderFile(fileName); // DDL files
347 } else if (fileName.EndsWith(".root")) {
348 fgRawReader = new AliRawReaderRoot(fileName); // ROOT file
349 } else if (!fileName.IsNull()) {
350 fgRawReader = new AliRawReaderDate(fileName); // DATE file
351 }
352 fgRawStreamTracker = new AliMUONRawStreamTracker(fgRawReader);
353 fgRawStreamTrigger = new AliMUONRawStreamTrigger(fgRawReader);
361fa326 354 fgBusPatchManager = AliMpDDLStore::Instance();
3626c858 355 }
356
357 LoadRawTracker();
358 LoadRawTrigger();
359
360}
361
362//______________________________________________________________________
363void MUONData::LoadRawTracker()
364{
365 //
366 // load raw data for the tracking chambers
367 //
368
369 fgRawReader->RewindEvents();
370
371 AliMUONDigit* digit = new AliMUONDigit();
372
373 Int_t maxEvent = 1000;
374 Int_t minDDL = 0, maxDDL = 19;
375 Int_t cathode, detElemId, ix, iy, iChamber;
376
377 AliMUONDDLTracker* ddlTracker = 0x0;
378 AliMUONBlockHeader* blkHeader = 0x0;
379 AliMUONDspHeader* dspHeader = 0x0;
380 AliMUONBusStruct* busStruct = 0x0;
381
382 Int_t iEvent = 0;
383 Int_t dataSize, buspatchId;
384
385 Event* aevent = Alieve::gEvent;
386
387 while (fgRawReader->NextEvent()) {
388
389 if (iEvent != aevent->GetEventId()) {
390 iEvent++;
391 continue;
392 }
393
394 if (iEvent == maxEvent)
395 break;
396
397 // read DDL while < 20 DDL
398 while(fgRawStreamTracker->NextDDL()) {
399
400 if (fgRawStreamTracker->GetDDL() < minDDL ||
401 fgRawStreamTracker->GetDDL() > maxDDL)
402 continue;
403
404 //printf("\niDDL %d\n", fgRawStreamTracker->GetDDL());
405
406 ddlTracker = fgRawStreamTracker->GetDDLTracker();
407
408 // loop over block structure
409 Int_t nBlock = ddlTracker->GetBlkHeaderEntries();
410 for(Int_t iBlock = 0; iBlock < nBlock ;iBlock++){
411
412 blkHeader = ddlTracker->GetBlkHeaderEntry(iBlock);
413 //printf("Block Total length %d\n",blkHeader->GetTotalLength());
414
415 // loop over DSP structure
416 Int_t nDsp = blkHeader->GetDspHeaderEntries();
417 for(Int_t iDsp = 0; iDsp < nDsp ;iDsp++){ //DSP loop
418
419 dspHeader = blkHeader->GetDspHeaderEntry(iDsp);
420 // printf("Dsp length %d even word %d\n",dspHeader->GetTotalLength(), dspHeader->GetEventWord());
421
422 // loop over BusPatch structure
423 Int_t nBusPatch = dspHeader->GetBusPatchEntries();
424 for(Int_t iBusPatch = 0; iBusPatch < nBusPatch; iBusPatch++) {
425
426 busStruct = dspHeader->GetBusPatchEntry(iBusPatch);
427
428 //printf("busPatchId %d", busStruct->GetBusPatchId());
429 //printf(" BlockId %d", busStruct->GetBlockId());
430 //printf(" DspId %d\n", busStruct->GetDspId());
431
432 // loop over data
433 dataSize = busStruct->GetLength();
434 buspatchId = busStruct->GetBusPatchId();
435 for (Int_t iData = 0; iData < dataSize; iData++) {
436
437 Int_t manuId = busStruct->GetManuId(iData);
438 Int_t channelId = busStruct->GetChannelId(iData);
439 Int_t charge = busStruct->GetCharge(iData);
440 //printf("manuId: %d, channelId: %d charge: %d\n", manuId, channelId, charge);
441 // set digit charge
442 digit->SetSignal(charge);
443 digit->SetPhysicsSignal(charge);
444 digit->SetADC(charge);
445 // Get Back the hits at pads
446 Int_t error;
447 error = GetTrackerMapping(buspatchId,manuId,channelId,digit);
448 if (error) {
449 printf("Mapping Error\n");
450 continue;
451 }
452
453 cathode = digit->Cathode();
454 ix = digit->PadX();
455 iy = digit->PadY();
456 detElemId = digit->DetElemId();
457 charge = (Int_t)digit->Signal();
458 iChamber = detElemId/100 - 1;
459
460 fChambers[iChamber]->RegisterDigit(detElemId,cathode,ix,iy,charge);
461
462 } // iData
463 } // iBusPatch
464 } // iDsp
465 } // iBlock
466 } // NextDDL
467
468 break;
469
470 } // end event loop
471
472 delete digit;
473
474}
475
476//______________________________________________________________________
477void MUONData::LoadRawTrigger()
478{
479 //
480 // load raw data for the trigger chambers
481 //
482
483 fgRawReader->RewindEvents();
484
485 Int_t maxEvent = 1000;
486 Int_t minDDL = 0, maxDDL = 1;
487 Int_t detElemId, iChamber, cathode, charge, ix, iy;
488
489 AliMUONDDLTrigger* ddlTrigger = 0x0;
490 AliMUONDarcHeader* darcHeader = 0x0;
491 AliMUONRegHeader* regHeader = 0x0;
492 AliMUONLocalStruct* localStruct = 0x0;
493
494 // crate manager
495 AliMUONTriggerCrateStore* crateManager = new AliMUONTriggerCrateStore();
496 crateManager->ReadFromFile();
497
498 // Loop over events
499 Int_t iEvent = 0;
500 TList digitList;
501
502 Event* aevent = Alieve::gEvent;
503
504 while (fgRawReader->NextEvent()) {
505
506 if (iEvent != aevent->GetEventId()) {
507 iEvent++;
508 continue;
509 }
510
511 if (iEvent == maxEvent)
512 break;
513
514 // read DDL while < 2 DDL
515 while(fgRawStreamTrigger->NextDDL()) {
516
517 if (fgRawStreamTrigger->GetDDL() < minDDL ||
518 fgRawStreamTrigger->GetDDL() > maxDDL)
519 continue;
520
521 //printf("\niDDL %d\n", fgRawStreamTrigger->GetDDL());
522
523 ddlTrigger = fgRawStreamTrigger->GetDDLTrigger();
524 darcHeader = ddlTrigger->GetDarcHeader();
525
526 //printf("Global output %x\n", (Int_t)darcHeader->GetGlobalOutput());
527
528 // loop over regional structures
529 Int_t nReg = darcHeader->GetRegHeaderEntries();
530 for(Int_t iReg = 0; iReg < nReg ;iReg++){ //REG loop
531
532 //printf("RegionalId %d\n", iReg);
533
534 regHeader = darcHeader->GetRegHeaderEntry(iReg);
535 // printf("Reg length %d\n",regHeader->GetHeaderLength());
536
537 // crate info
538 AliMUONTriggerCrate* crate = crateManager->Crate(fgRawStreamTrigger->GetDDL(), iReg);
539 TObjArray *boards = crate->Boards();
540
541 // loop over local structures
542 Int_t nLocal = regHeader->GetLocalEntries();
543 for(Int_t iLocal = 0; iLocal < nLocal; iLocal++) {
544
545 localStruct = regHeader->GetLocalEntry(iLocal);
546
547 // check if trigger
548 if (localStruct->GetTriggerY() == 0) { // no empty data
549
550 // local trigger circuit number
551 AliMUONLocalTriggerBoard* localBoard = (AliMUONLocalTriggerBoard*)boards->At(iLocal+1);
552
553 //printf("LocalId %d\n", localStruct->GetId());
554 /*
555 Int_t iLocCard = localBoard->GetNumber();
556 Int_t loStripX = (Int_t)localStruct->GetXPos();
557 Int_t loStripY = (Int_t)localStruct->GetYPos();
558 Int_t loDev = (Int_t)localStruct->GetXDev();
559 */
560 //printf("iLocCard: %d, XPos: %d, YPos: %d Dev: %d\n", iLocCard, loStripX, loStripY, loDev);
561
562 digitList.Clear();
563 if ( GetTriggerMapping(localBoard, localStruct, digitList) ) {
564 for (Int_t iEntry = 0; iEntry < digitList.GetEntries(); iEntry++) {
565
566 AliMUONDigit* digit = (AliMUONDigit*)digitList.At(iEntry);
567 cathode = digit->Cathode();
568 ix = digit->PadX();
569 iy = digit->PadY();
570 detElemId = digit->DetElemId();
571 charge = (Int_t)digit->Signal();
572 iChamber = detElemId/100 - 1;
573
574 //printf("cha %d deid %d cath %1d ix %d iy %d q %d \n",iChamber,detElemId,cathode,ix,iy,charge);
575
576 fChambers[iChamber]->RegisterDigit(detElemId,cathode,ix,iy,charge);
577
578 }
579
580 }
581
582 }
583 } // iLocal
584 } // iReg
585 } // NextDDL
586
587 break;
588
589 } // end event loop
590
591 delete crateManager;
592
593}
594
595//______________________________________________________________________
596Int_t MUONData::GetTrackerMapping(Int_t buspatchId, UShort_t manuId, UChar_t channelId, AliMUONDigit* digit)
597{
598 //
599 // decode digits mapping for the tracking chambers
600 //
601
602 // getting DE from buspatch
603 Int_t detElemId = fgBusPatchManager->GetDEfromBus(buspatchId);
604 //AliDebug(3,Form("detElemId: %d busPatchId %d\n", detElemId, buspatchId));
605
606 const AliMpVSegmentation* seg = AliMpSegmentation::Instance()->GetMpSegmentationByElectronics(detElemId, manuId);
607 AliMpPad pad = seg->PadByLocation(AliMpIntPair(manuId,channelId),kTRUE);
608
609 if (!pad.IsValid())
610 {
611 printf("No pad for detElemId: %d, busPatchId %d, manuId: %d, channelId: %d\n",detElemId, buspatchId, manuId, channelId);
612
613 return 1;
614 } // return error
615
616 // Getting padX, padY and cathode number.
617 Int_t padX = pad.GetIndices().GetFirst();
618 Int_t padY = pad.GetIndices().GetSecond();
619 Int_t iCath = AliMpDEManager::GetCathod(detElemId,seg->PlaneType());
620
621 // storing into digits
622 digit->SetPadX(padX);
623 digit->SetPadY(padY);
624 digit->SetCathode(iCath);
625 digit->SetDetElemId(detElemId);
626 digit->SetElectronics(manuId,channelId);
627
628 //printf("detElemId: %d, busPatchId %d, manuId: %d, channelId: %d, padx: %d pady %d\n",detElemId, buspatchId, manuId, channelId, padX, padY);
629
630 return 0;
631
632}
633
634//______________________________________________________________________
635Int_t MUONData::GetTriggerMapping(AliMUONLocalTriggerBoard* localBoard,
636 AliMUONLocalStruct* localStruct,
637 TList& digitList)
638{
639 //
640 // decode digits mapping for the trigger chambers
641 //
642
643 Int_t detElemId;
644 Int_t nBoard;
645 Int_t iCath = -1;
646 Int_t iChamber = 0;
647 Int_t xyPattern = 0;
648
649 // loop over x1-4 and y1-4
650 for (Int_t icase = 0; icase < 8; icase++) {
651
652 // get chamber, cathode and associated trigger response pattern
653 GetTriggerChamber(localStruct, xyPattern, iChamber, iCath, icase);
654
655 if (!xyPattern) continue;
656
657 // get detElemId
658 AliMUONTriggerCircuit triggerCircuit;
659 detElemId = triggerCircuit.DetElemId(iChamber, localBoard->GetName());
660 nBoard = localBoard->GetNumber();
661
361fa326 662 const AliMpVSegmentation* seg
663 = AliMpSegmentation::Instance()
664 ->GetMpSegmentation(detElemId, AliMp::GetCathodType(iCath));
3626c858 665
666 // loop over the 16 bits of pattern
667 for (Int_t ibitxy = 0; ibitxy < 16; ibitxy++) {
668
669 if ((xyPattern >> ibitxy) & 0x1) {
670
671 // not quite sure about this
672 Int_t offset = 0;
673 if (iCath && localBoard->GetSwitch(6)) offset = -8;
674
675 AliMpPad pad = seg->PadByLocation(AliMpIntPair(nBoard,ibitxy+offset),kTRUE);
676
677 AliMUONDigit* digit = new AliMUONDigit();
678 if (!pad.IsValid()) {
679 AliWarning(Form("No pad for detElemId: %d, nboard %d, ibitxy: %d\n",
680 detElemId, nBoard, ibitxy));
681 continue;
682 } //
683
684 Int_t padX = pad.GetIndices().GetFirst();
685 Int_t padY = pad.GetIndices().GetSecond();
686
687 // file digit
688 digit->SetSignal(1);
689 digit->SetPadX(padX);
690 digit->SetPadY(padY);
691 digit->SetCathode(iCath);
692 digit->SetDetElemId(detElemId);
693 digit->SetElectronics(nBoard, ibitxy);
694 digitList.Add(digit);
695
696 }// xyPattern
697 }// ibitxy
698 }// case
699
700 return 1;
701
702}
703
704//____________________________________________________________________
705void MUONData::GetTriggerChamber(AliMUONLocalStruct* localStruct, Int_t& xyPattern, Int_t& iChamber, Int_t& iCath, Int_t icase)
706{
707 //
708 // extract digits pattern
709 //
710
711 // get chamber & cathode number, (chamber starts at 0 !)
712 switch(icase) {
713 case 0:
714 xyPattern = localStruct->GetX1();
715 iCath = 0;
716 iChamber = 10;
717 break;
718 case 1:
719 xyPattern = localStruct->GetX2();
720 iCath = 0;
721 iChamber = 11;
722 break;
723 case 2:
724 xyPattern = localStruct->GetX3();
725 iCath = 0;
726 iChamber = 12;
727 break;
728 case 3:
729 xyPattern = localStruct->GetX4();
730 iCath = 0;
731 iChamber = 13;
732 break;
733 case 4:
734 xyPattern = localStruct->GetY1();
735 iCath = 1;
736 iChamber = 10;
737 break;
738 case 5:
739 xyPattern = localStruct->GetY2();
740 iCath = 1;
741 iChamber = 11;
742 break;
743 case 6:
744 xyPattern = localStruct->GetY3();
745 iCath = 1;
746 iChamber = 12;
747 break;
748 case 7:
749 xyPattern = localStruct->GetY4();
750 iCath = 1;
751 iChamber = 13;
752 break;
753 }
754
755}
756
eadce74d 757//______________________________________________________________________
758Int_t MUONData::GetTrack(Int_t index)
759{
760 //
761 // return track stack number for "index"-th track with hits in the chambers
762 //
763
764 if (index < 100) {
765 return fTrackList[index];
766 } else {
767 return -1;
768 }
769
770}
771
3626c858 772//______________________________________________________________________
773MUONChamberData* MUONData::GetChamberData(Int_t chamber)
774{
775 //
776 // return chamber data
777 //
778
779 if (chamber < 0 || chamber > 13) return 0;
780
781 //if (fChambers[chamber] == 0) CreateChamber(chamber);
782
783 return fChambers[chamber];
784
785}