From 0ee00e25a01ba289dea16eb05e5d7649a0e1ddcf Mon Sep 17 00:00:00 2001 From: hristov Date: Mon, 3 Apr 2006 14:53:09 +0000 Subject: [PATCH] Adding TRD trigger (B.Vulpescu) --- STEER/AliESD.cxx | 8 +- STEER/AliESD.h | 9 + STEER/AliESDTrdTrack.cxx | 101 ++ STEER/AliESDTrdTrack.h | 67 ++ STEER/AliEventTag.cxx | 2 +- STEER/ESDLinkDef.h | 1 + STEER/libESD.pkg | 2 +- TRD/AliTRDReconstructor.cxx | 114 +- TRD/AliTRDmcm.cxx | 802 ++++++++++++++ TRD/AliTRDmcm.h | 98 ++ TRD/AliTRDmcmTracklet.cxx | 420 ++++++++ TRD/AliTRDmcmTracklet.h | 98 ++ TRD/AliTRDtrigParam.cxx | 185 ++++ TRD/AliTRDtrigParam.h | 108 ++ TRD/AliTRDtrigger.cxx | 1622 +++++++++++++++++++++++++++++ TRD/AliTRDtrigger.h | 311 ++++++ TRD/AliTRDzmaps.h | 1146 ++++++++++++++++++++ TRD/Calib/PIDLQ/Run0_0_v0_s1.root | Bin 0 -> 34326 bytes TRD/TRDdEdxHistogramsV1_BV.root | Bin 0 -> 56039 bytes TRD/TRDrecLinkDef.h | 8 + TRD/libTRDrec.pkg | 6 +- 21 files changed, 5102 insertions(+), 6 deletions(-) create mode 100644 STEER/AliESDTrdTrack.cxx create mode 100644 STEER/AliESDTrdTrack.h create mode 100644 TRD/AliTRDmcm.cxx create mode 100644 TRD/AliTRDmcm.h create mode 100644 TRD/AliTRDmcmTracklet.cxx create mode 100644 TRD/AliTRDmcmTracklet.h create mode 100644 TRD/AliTRDtrigParam.cxx create mode 100644 TRD/AliTRDtrigParam.h create mode 100644 TRD/AliTRDtrigger.cxx create mode 100644 TRD/AliTRDtrigger.h create mode 100644 TRD/AliTRDzmaps.h create mode 100644 TRD/Calib/PIDLQ/Run0_0_v0_s1.root create mode 100644 TRD/TRDdEdxHistogramsV1_BV.root diff --git a/STEER/AliESD.cxx b/STEER/AliESD.cxx index 1c80105616a..4e96fac2c28 100644 --- a/STEER/AliESD.cxx +++ b/STEER/AliESD.cxx @@ -35,9 +35,9 @@ AliESD::AliESD(): fMagneticField(0), fZDCN1Energy(0), fZDCP1Energy(0), - fZDCEMEnergy(0), fZDCN2Energy(0), fZDCP2Energy(0), + fZDCEMEnergy(0), fZDCParticipants(0), fT0zVertex(0), fPrimaryVertex(), @@ -46,6 +46,7 @@ AliESD::AliESD(): fHLTHoughTracks("AliESDHLTtrack",15000), fMuonTracks("AliESDMuonTrack",30), fPmdTracks("AliESDPmdTrack",3000), + fTrdTracks("AliESDTrdTrack",300), fV0s("AliESDv0",200), fCascades("AliESDcascade",20), fKinks("AliESDkink",4000), @@ -71,6 +72,7 @@ AliESD::~AliESD() fHLTHoughTracks.Delete(); fMuonTracks.Delete(); fPmdTracks.Delete(); + fTrdTracks.Delete(); fV0s.Delete(); fCascades.Delete(); fKinks.Delete(); @@ -109,9 +111,9 @@ void AliESD::Reset() fMagneticField=0; fZDCN1Energy=0; fZDCP1Energy=0; - fZDCEMEnergy=0; fZDCN2Energy=0; fZDCP2Energy=0; + fZDCEMEnergy=0; fZDCParticipants=0; fT0zVertex=0; fPrimaryVertex.Reset(); @@ -120,6 +122,7 @@ void AliESD::Reset() fHLTHoughTracks.Clear(); fMuonTracks.Clear(); fPmdTracks.Clear(); + fTrdTracks.Clear(); fV0s.Clear(); fCascades.Clear(); fCaloClusters.Clear(); @@ -155,6 +158,7 @@ void AliESD::Print(Option_t *) const printf(" emcal %d\n", GetNumberOfEMCALClusters()); printf(" muon %d\n", GetNumberOfMuonTracks()); printf(" pmd %d\n", GetNumberOfPmdTracks()); + printf(" trd %d\n", GetNumberOfTrdTracks()); printf(" v0 %d\n", GetNumberOfV0s()); printf(" cascades %d\n)", GetNumberOfCascades()); printf(" kinks %d\n)", GetNumberOfKinks()); diff --git a/STEER/AliESD.h b/STEER/AliESD.h index ebc0f6e3dbe..fc6c304121a 100644 --- a/STEER/AliESD.h +++ b/STEER/AliESD.h @@ -19,6 +19,7 @@ #include "AliESDMuonTrack.h" #include "AliESDPmdTrack.h" +#include "AliESDTrdTrack.h" #include "AliESDVertex.h" #include "AliESDcascade.h" #include "AliESDkink.h" @@ -55,6 +56,9 @@ public: AliESDPmdTrack *GetPmdTrack(Int_t i) const { return (AliESDPmdTrack *)fPmdTracks.UncheckedAt(i); } + AliESDTrdTrack *GetTrdTrack(Int_t i) const { + return (AliESDTrdTrack *)fTrdTracks.UncheckedAt(i); + } Int_t AddTrack(const AliESDtrack *t) { AliESDtrack * track = new(fTracks[fTracks.GetEntriesFast()]) AliESDtrack(*t); @@ -74,6 +78,9 @@ public: void AddPmdTrack(const AliESDPmdTrack *t) { new(fPmdTracks[fPmdTracks.GetEntriesFast()]) AliESDPmdTrack(*t); } + void AddTrdTrack(const AliESDTrdTrack *t) { + new(fTrdTracks[fTrdTracks.GetEntriesFast()]) AliESDTrdTrack(*t); + } AliESDv0 *GetV0(Int_t i) const { return (AliESDv0 *)fV0s.UncheckedAt(i); @@ -131,6 +138,7 @@ public: Int_t GetNumberOfHLTHoughTracks() const {return fHLTHoughTracks.GetEntriesFast();} Int_t GetNumberOfMuonTracks() const {return fMuonTracks.GetEntriesFast();} Int_t GetNumberOfPmdTracks() const {return fPmdTracks.GetEntriesFast();} + Int_t GetNumberOfTrdTracks() const {return fTrdTracks.GetEntriesFast();} Int_t GetNumberOfV0s() const {return fV0s.GetEntriesFast();} Int_t GetNumberOfCascades() const {return fCascades.GetEntriesFast();} Int_t GetNumberOfKinks() const {return fKinks.GetEntriesFast();} @@ -197,6 +205,7 @@ protected: TClonesArray fHLTHoughTracks; // HLT ESD tracks from Hough Transform method TClonesArray fMuonTracks; // MUON ESD tracks TClonesArray fPmdTracks; // PMD ESD tracks + TClonesArray fTrdTracks; // TRD ESD tracks (triggered) TClonesArray fV0s; // V0 vertices TClonesArray fCascades; // Cascade vertices TClonesArray fKinks; // Kinks diff --git a/STEER/AliESDTrdTrack.cxx b/STEER/AliESDTrdTrack.cxx new file mode 100644 index 00000000000..0c9449cde25 --- /dev/null +++ b/STEER/AliESDTrdTrack.cxx @@ -0,0 +1,101 @@ +/************************************************************************** + * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. * + * * + * Author: The ALICE Off-line Project. * + * Contributors are mentioned in the code where appropriate. * + * * + * Permission to use, copy, modify and distribute this software and its * + * documentation strictly for non-commercial purposes is hereby granted * + * without fee, provided that the above copyright notice appears in all * + * copies and that both the copyright notice and this permission notice * + * appear in the supporting documentation. The authors make no claims * + * about the suitability of this software for any purpose. It is * + * provided "as is" without express or implied warranty. * + **************************************************************************/ + +/////////////////////////////////////////////////////////////////////////////// +// +// The TRD trigger stores the found tracks as ESDTrdTrack objects in the ESD +// +/////////////////////////////////////////////////////////////////////////////// + +#include "AliESDTrdTrack.h" + +ClassImp(AliESDTrdTrack) + +//_____________________________________________________________________________ +AliESDTrdTrack::AliESDTrdTrack(): + TObject(), + fYproj(0), + fZproj(0), + fSlope(0), + fDetector(-1), + fNtracklets(0), + fNplanes(0), + fNclusters(0), + fPt(0), + fPhi(0), + fEta(0), + fLabel(-1), + fPID(0), + fIsElectron(kFALSE) +{ + + // + // Default constructor + // + +} + +//_____________________________________________________________________________ +AliESDTrdTrack::AliESDTrdTrack(const AliESDTrdTrack& track): + TObject(track), + fYproj(track.fYproj), + fZproj(track.fZproj), + fSlope(track.fSlope), + fDetector(track.fDetector), + fNtracklets(track.fNtracklets), + fNplanes(track.fNplanes), + fNclusters(track.fNclusters), + fPt(track.fPt), + fPhi(track.fPhi), + fEta(track.fEta), + fLabel(track.fLabel), + fPID(track.fPID), + fIsElectron(track.fIsElectron) +{ + + // + // Copy contructor + // + +} + +//_____________________________________________________________________________ +AliESDTrdTrack& AliESDTrdTrack::operator=(const AliESDTrdTrack& track) +{ + // + // Equal operator + // + + if (this == &track) + return *this; + + fYproj = track.fYproj; + fZproj = track.fZproj; + fSlope = track.fSlope; + fDetector = track.fDetector; + fNtracklets = track.fNtracklets; + fNplanes = track.fNplanes; + fNclusters = track.fNclusters; + fPt = track.fPt; + fPhi = track.fPhi; + fEta = track.fEta; + fLabel = track.fLabel; + fPID = track.fPID; + fIsElectron = track.fIsElectron; + + return *this; + +} + diff --git a/STEER/AliESDTrdTrack.h b/STEER/AliESDTrdTrack.h new file mode 100644 index 00000000000..248f85fe175 --- /dev/null +++ b/STEER/AliESDTrdTrack.h @@ -0,0 +1,67 @@ +#ifndef ALIESDTRDTRACK_H +#define ALIESDTRDTRACK_H + +// +// Tracks from the TRD Global Tracking Unit (GTU, trigger) +// + +#include "TObject.h" + +class AliESDTrdTrack : public TObject { + + public: + + AliESDTrdTrack(); + virtual ~AliESDTrdTrack(){}; + AliESDTrdTrack(const AliESDTrdTrack& track); + AliESDTrdTrack& operator=(const AliESDTrdTrack& track); + + Float_t GetYproj() { return fYproj; }; + Float_t GetZproj() { return fZproj; }; + Float_t GetSlope() { return fSlope; }; + Int_t GetDetector() { return fDetector; }; + Int_t GetTracklets() { return fNtracklets; }; + Int_t GetPlanes() { return fNplanes; }; + Int_t GetClusters() { return fNclusters; }; + Float_t GetPt() { return fPt; }; + Float_t GetPhi() { return fPhi; }; + Float_t GetEta() { return fEta; }; + Int_t GetLabel() { return fLabel; }; + Float_t GetPID() { return fPID; }; + Bool_t IsElectron() { return fIsElectron; } + + void SetYproj(Float_t val) { fYproj = val; }; + void SetZproj(Float_t val) { fZproj = val; }; + void SetSlope(Float_t val) { fSlope = val; }; + void SetDetector(Int_t det) { fDetector = det; }; + void SetTracklets(Int_t val) { fNtracklets = val; }; + void SetPlanes(Int_t val) { fNplanes = val; }; + void SetClusters(Int_t val) { fNclusters = val; }; + void SetPt(Float_t val) { fPt = val; }; + void SetPhi(Float_t val) { fPhi = val; }; + void SetEta(Float_t val) { fEta = val; }; + void SetLabel(Int_t val) { fLabel = val; }; + void SetPID(Float_t val) { fPID = val; }; + void SetIsElectron(Bool_t val) { fIsElectron = val; }; + + protected: + + Float_t fYproj; // Average values calculated + Float_t fZproj; // from the tracklets + Float_t fSlope; // + Int_t fDetector; // First detector in the module + Int_t fNtracklets; // Number of tracklets + Int_t fNplanes; // Number of TRD planes + Int_t fNclusters; // Total number of clusters + Float_t fPt; // Transverse momentum + Float_t fPhi; // Phi angle at the vertex + Float_t fEta; // Eta at the vertex + Int_t fLabel; // Track label + Float_t fPID; // PID electron likelihood + Bool_t fIsElectron; // Electron flag + + ClassDef(AliESDTrdTrack,1) + +}; + +#endif diff --git a/STEER/AliEventTag.cxx b/STEER/AliEventTag.cxx index 5107b01837f..154d564f263 100644 --- a/STEER/AliEventTag.cxx +++ b/STEER/AliEventTag.cxx @@ -43,9 +43,9 @@ ClassImp(AliEventTag) fTriggerInfo(-10), fZDCNeutron1Energy(-10.0), fZDCProton1Energy(-10.0), - fZDCEMEnergy(-10.0), fZDCNeutron2Energy(-10.0), fZDCProton2Energy(-10.0), + fZDCEMEnergy(-10.0), fT0VertexZ(-10.0), fNumberOfTracks(-10), fNumberOfPositiveTracks(-10), diff --git a/STEER/ESDLinkDef.h b/STEER/ESDLinkDef.h index d9fabc3c3e9..d366084f6e6 100644 --- a/STEER/ESDLinkDef.h +++ b/STEER/ESDLinkDef.h @@ -14,6 +14,7 @@ #pragma link C++ class AliESDtrack+; #pragma link C++ class AliESDMuonTrack+; #pragma link C++ class AliESDPmdTrack+; +#pragma link C++ class AliESDTrdTrack+; #pragma link C++ class AliESDHLTtrack+; #pragma link C++ class AliESDv0+; #pragma link C++ class AliESDcascade+; diff --git a/STEER/libESD.pkg b/STEER/libESD.pkg index b296b3645f2..67b028cb375 100644 --- a/STEER/libESD.pkg +++ b/STEER/libESD.pkg @@ -1,6 +1,6 @@ SRCS = AliESD.cxx \ AliESDtrack.cxx \ - AliESDMuonTrack.cxx AliESDPmdTrack.cxx AliESDHLTtrack.cxx \ + AliESDMuonTrack.cxx AliESDPmdTrack.cxx AliESDTrdTrack.cxx AliESDHLTtrack.cxx \ AliESDv0.cxx AliESDcascade.cxx AliVertex.cxx AliESDVertex.cxx \ AliESDpid.cxx AliESDkink.cxx AliESDV0MI.cxx \ AliESDCaloCluster.cxx \ diff --git a/TRD/AliTRDReconstructor.cxx b/TRD/AliTRDReconstructor.cxx index 6ef49234b4d..501081a3ef0 100644 --- a/TRD/AliTRDReconstructor.cxx +++ b/TRD/AliTRDReconstructor.cxx @@ -30,6 +30,11 @@ #include #include "AliRawReader.h" #include "AliLog.h" +#include "AliTRDtrigger.h" +#include "AliTRDtrigParam.h" +#include "AliRun.h" +#include "AliESDTrdTrack.h" +#include "AliESD.h" ClassImp(AliTRDReconstructor) @@ -56,6 +61,34 @@ void AliTRDReconstructor::Reconstruct(AliRunLoader* runLoader) const } loader->UnloadRecPoints(); + + // Trigger (tracklets, LTU) + + AliTRDtrigger trdTrigger("Trigger","Trigger class"); + + AliTRDtrigParam *trigp = new AliTRDtrigParam("TRDtrigParam","TRD Trigger parameters"); + + if (runLoader->GetAliRun() == 0x0) runLoader->LoadgAlice(); + gAlice = runLoader->GetAliRun(); + Double_t x[3] = { 0.0, 0.0, 0.0 }; + Double_t b[3]; + gAlice->Field(x,b); // b[] is in kilo Gauss + Float_t field = b[2] * 0.1; // Tesla + Info("Reconstruct","Trigger set for magnetic field = %f Tesla \n",field); + + trigp->SetField(field); + trigp->Init(); + trdTrigger.SetParameter(trigp); + + for (Int_t iEvent = 0; iEvent < nEvents; iEvent++) { + trdTrigger.Open(runLoader->GetFileName(), iEvent); + trdTrigger.ReadDigits(); + trdTrigger.MakeTracklets(); + trdTrigger.WriteTracklets(-1); + } + + loader->UnloadTracks(); + } //_____________________________________________________________________________ @@ -82,6 +115,34 @@ void AliTRDReconstructor::Reconstruct(AliRunLoader* runLoader, } loader->UnloadRecPoints(); + + // Trigger (tracklets, LTU) + + AliTRDtrigger trdTrigger("Trigger","Trigger class"); + + AliTRDtrigParam *trigp = new AliTRDtrigParam("TRDtrigParam","TRD Trigger parameters"); + + if (runLoader->GetAliRun() == 0x0) runLoader->LoadgAlice(); + gAlice = runLoader->GetAliRun(); + Double_t x[3] = { 0.0, 0.0, 0.0 }; + Double_t b[3]; + gAlice->Field(x,b); // b[] is in kilo Gauss + Float_t field = b[2] * 0.1; // Tesla + Info("Reconstruct","Trigger set for magnetic field = %f Tesla \n",field); + + trigp->SetField(field); + trigp->Init(); + trdTrigger.SetParameter(trigp); + + for (Int_t iEvent = 0; iEvent < nEvents; iEvent++) { + trdTrigger.Open(runLoader->GetFileName(), iEvent); + trdTrigger.ReadDigits(rawReader); + trdTrigger.MakeTracklets(); + trdTrigger.WriteTracklets(-1); + } + + loader->UnloadTracks(); + } //_____________________________________________________________________________ @@ -94,7 +155,7 @@ AliTracker* AliTRDReconstructor::CreateTracker(AliRunLoader* runLoader) const } //_____________________________________________________________________________ -void AliTRDReconstructor::FillESD(AliRunLoader* /*runLoader*/, +void AliTRDReconstructor::FillESD(AliRunLoader* runLoader, AliESD* esd) const { // make PID @@ -106,6 +167,57 @@ void AliTRDReconstructor::FillESD(AliRunLoader* /*runLoader*/, }; AliTRDpidESD trdPID(parTRD); trdPID.MakePID(esd); + + // Trigger (tracks, GTU) + + AliTRDtrigger trdTrigger("Trigger","Trigger class"); + + AliTRDtrigParam *trigp = new AliTRDtrigParam("TRDtrigParam","TRD Trigger parameters"); + + if (runLoader->GetAliRun() == 0x0) runLoader->LoadgAlice(); + gAlice = runLoader->GetAliRun(); + Double_t x[3] = { 0.0, 0.0, 0.0 }; + Double_t b[3]; + gAlice->Field(x,b); // b[] is in kilo Gauss + Float_t field = b[2] * 0.1; // Tesla + Info("FillESD","Trigger set for magnetic field = %f Tesla \n",field); + + trigp->SetField(field); + trigp->Init(); + + trdTrigger.SetParameter(trigp); + trdTrigger.SetRunLoader(runLoader); + trdTrigger.Init(); + + Int_t iEvent = runLoader->GetEventNumber(); + runLoader->GetEvent(iEvent); + trdTrigger.ReadTracklets(runLoader); + + AliESDTrdTrack *TrdTrack = new AliESDTrdTrack(); + AliTRDgtuTrack *GtuTrack; + + Int_t nTracks = trdTrigger.GetNumberOfTracks(); + for (Int_t iTrack = 0; iTrack < nTracks; iTrack++) { + + GtuTrack = trdTrigger.GetTrack(iTrack); + + TrdTrack->SetYproj(GtuTrack->GetYproj()); + TrdTrack->SetZproj(GtuTrack->GetZproj()); + TrdTrack->SetSlope(GtuTrack->GetSlope()); + TrdTrack->SetDetector(GtuTrack->GetDetector()); + TrdTrack->SetTracklets(GtuTrack->GetTracklets()); + TrdTrack->SetPlanes(GtuTrack->GetPlanes()); + TrdTrack->SetClusters(GtuTrack->GetClusters()); + TrdTrack->SetPt(GtuTrack->GetPt()); + TrdTrack->SetPhi(GtuTrack->GetPhi()); + TrdTrack->SetEta(GtuTrack->GetEta()); + TrdTrack->SetLabel(GtuTrack->GetLabel()); + TrdTrack->SetPID(GtuTrack->GetPID()); + + esd->AddTrdTrack(TrdTrack); + + } + } diff --git a/TRD/AliTRDmcm.cxx b/TRD/AliTRDmcm.cxx new file mode 100644 index 00000000000..2e751dabbbd --- /dev/null +++ b/TRD/AliTRDmcm.cxx @@ -0,0 +1,802 @@ +/************************************************************************** + * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. * + * * + * Author: The ALICE Off-line Project. * + * Contributors are mentioned in the code where appropriate. * + * * + * Permission to use, copy, modify and distribute this software and its * + * documentation strictly for non-commercial purposes is hereby granted * + * without fee, provided that the above copyright notice appears in all * + * copies and that both the copyright notice and this permission notice * + * appear in the supporting documentation. The authors make no claims * + * about the suitability of this software for any purpose. It is * + * provided "as is" without express or implied warranty. * + **************************************************************************/ + +/* +$Log$ +Revision 1.1.1.1 2004/08/19 14:58:11 vulpescu +CVS head + +Revision 1.1.1.1 2004/08/18 07:47:17 vulpescu +test + +*/ + +#include +#include + +#include "AliTRDmcm.h" +#include "AliTRDtrigParam.h" + +ClassImp(AliTRDmcm) + +//_____________________________________________________________________________ +AliTRDmcm::AliTRDmcm() +{ + + // + // AliTRDmcm default constructor + // + + fTrigParam = 0; + + fNtrk = 0; + for (Int_t i = 0; i < kMaxTrackletsPerMCM; i++) { + fTrkIndex[i] = 0; + } + fRobId = 0; + fChaId = 0; + fRow = 0; + fColFirst = 0; + fColLast = 0; + for (Int_t i = 0; i < kMcmCol; i++) { + fPadHits[i] = 0; + for (Int_t j = 0; j < kMcmTBmax; j++) { + fADC[i][j] = 0.0; + fIsClus[i][j] = kFALSE; + } + } + fPadThr = 0; + fClusThr = 0; + fTime1 = 0; + fTime2 = 0; + fNtrkSeeds = 0; + for (Int_t i = 0; i < kMaxTrackletsPerMCM; i++) { + fSeedCol[i] = -1; + } + + fR1 = 0.0; + fR2 = 0.0; + fC1 = 0.0; + fC2 = 0.0; + fPedestal = 0.0; + + fId = 0; + +} + +//_____________________________________________________________________________ +AliTRDmcm::AliTRDmcm(AliTRDtrigParam *trigp, const Int_t id) +{ + // + // AliTRDmcm constructor + // + + fTrigParam = trigp; + + fNtrk = 0; + for (Int_t i = 0; i < kMaxTrackletsPerMCM; i++) { + fTrkIndex[i] = 0; + } + fRobId = 0; + fChaId = 0; + fRow = 0; + fColFirst = 0; + fColLast = 0; + for (Int_t i = 0; i < kMcmCol; i++) { + fPadHits[i] = 0; + for (Int_t j = 0; j < kMcmTBmax; j++) { + fADC[i][j] = 0.0; + fIsClus[i][j] = kFALSE; + } + } + fPadThr = fTrigParam->GetPadThr(); + fClusThr = fTrigParam->GetClusThr(); + fTime1 = fTrigParam->GetTime1(); + fTime2 = fTrigParam->GetTime2(); + fNtrkSeeds = 0; + for (Int_t i = 0; i < kMaxTrackletsPerMCM; i++) { + fSeedCol[i] = -1; + } + + fR1 = 0.0; + fR2 = 0.0; + fC1 = 0.0; + fC2 = 0.0; + fPedestal = 0.0; + + fTrigParam->GetFilterParam(fR1,fR2,fC1,fC2,fPedestal); + + fId = id; + +} + +//_____________________________________________________________________________ +AliTRDmcm::~AliTRDmcm() +{ + + // + // AliTRDmcm destructor + // + +} + +//_____________________________________________________________________________ +void AliTRDmcm::AddTrk(const Int_t id) +{ + // + // Add a tracklet index + // + + fTrkIndex[fNtrk] = id; + fNtrk++; + + return; + +} + +//_____________________________________________________________________________ +void AliTRDmcm::Reset() +{ + // + // Reset MCM data + // + + for (Int_t i = 0; i < kMcmCol; i++) { + fPadHits[i] = 0; + for (Int_t j = 0; j < kMcmTBmax; j++) { + fADC[i][j] = 0.0; + fIsClus[i][j] = kFALSE; + } + } + for (Int_t i = 0; i < kMaxTrackletsPerMCM; i++) { + fSeedCol[i] = -1; + } + +} + +//_____________________________________________________________________________ +Bool_t AliTRDmcm::Run() +{ + // + // Run MCM + // + + if ( fTrigParam->GetDebugLevel() > 1 ) printf("AliTRDmcm::Run MCM %d\n",Id()); + + Float_t Amp[3] = {0.0, 0.0, 0.0}; + Int_t nClus; + Int_t ClusCol[kMcmCol/2]; + Float_t ClusAmp[kMcmCol/2]; + Float_t VeryLarge; + Int_t ClusMin = -1; + + for (Int_t iTime = fTime1; iTime <= fTime2; iTime++) { // main TB loop + + // find clusters... + nClus = 0; + for (Int_t iCol = 1; iCol < (kMcmCol-1); iCol++) { + Amp[0] = fADC[iCol-1][iTime]; + Amp[1] = fADC[iCol ][iTime]; + Amp[2] = fADC[iCol+1][iTime]; + if (IsCluster(Amp)) { + fIsClus[iCol][iTime] = kTRUE; + ClusCol[nClus] = iCol; + ClusAmp[nClus] = Amp[0]+Amp[1]+Amp[2]; + nClus++; + if (nClus == kMcmCol/2) { + printf("Too many clusters in time bin %2d MCM %d...\n",iTime,Id()); + //return kFALSE; + break; + } + } + } + + // ...but no more than six... + if (nClus > (Int_t)kSelClus) { + for (Int_t j = kSelClus/2; j < nClus-kSelClus/2; j++) { + fIsClus[ClusCol[j]][iTime] = kFALSE; + } + } + + // ...and take the largest four. + + Int_t nClusPlus = nClus - kMaxClus; + for (Int_t iPlus = 0; iPlus < nClusPlus; iPlus++ ) { + VeryLarge = 1.E+10; + for (Int_t i = 0; i < nClus; i++) { + if (fIsClus[ClusCol[i]][iTime]) { + if (ClusAmp[i] <= VeryLarge) { + VeryLarge = ClusAmp[i]; + ClusMin = i; + } + } + } + fIsClus[ClusCol[ClusMin]][iTime] = kFALSE; + } + + AddTimeBin(iTime); + + } // end main TB loop + + if (fTrigParam->GetDebugLevel() > 1) { + for (Int_t i = fTime1; i <= fTime2; i++) { + printf("%2d: ",i); + for (Int_t j = 0; j < kMcmCol; j++) { + printf("%1d ",fIsClus[j][i]); + } + printf("\n"); + } + printf("PadHits: "); + for (Int_t iPad = 0; iPad < kMcmCol; iPad++) { + printf("%2d ",fPadHits[iPad]); + } + printf("\n"); + } + + if ((fNtrkSeeds = CreateSeeds())) { + + return kTRUE; + + } + + return kFALSE; + +} +//_____________________________________________________________________________ +Int_t AliTRDmcm::CreateSeeds() +{ + // + // Make column seeds (from Falk Lesser, ex KIP) + // + + if ( fTrigParam->GetDebugLevel() > 1 ) printf("AliTRDmcm::CreateSeeds MCM %d \n",Id()); + + Int_t nSeeds = 0; + + // working array for hit sums + Int_t fHit2padSum[2][kMcmCol]; + + // initialize the array + for( Int_t i = 0; i < 2; i++ ) { + for( Int_t j = 0; j < kMcmCol; j++ ) { + if( i == 0 ) { + fHit2padSum[i][j] = j; + } else { + fHit2padSum[i][j] = -1; + } + } + } + + Int_t Sum10 = fTrigParam->GetSum10(); + Int_t Sum12 = fTrigParam->GetSum12(); + + // build the 2padSum + Int_t Nsum2seed = 0; + for( Int_t i = 0; i < kMcmCol; i++ ) { + if( i < (kMcmCol-1) ) { + if( (fPadHits[i] >= Sum10) && ((fPadHits[i] + fPadHits[i+1]) >= Sum12) ) { + fHit2padSum[1][i] = fPadHits[i] + fPadHits[i+1]; + } else { + fHit2padSum[1][i] = -1; + } + } else { + if ( fPadHits[i] >= Sum12 ) { + fHit2padSum[1][i] = fPadHits[i]; + } else { + fHit2padSum[1][i] = -1; + } + } + if (fHit2padSum[1][i] > 0) Nsum2seed++; + } + + if (fTrigParam->GetDebugLevel() > 1) { + printf("fHit2padSum: "); + for( Int_t i = 0; i < kMcmCol; i++ ) { + printf("%2d ",fHit2padSum[0][i]); + } + printf("\n"); + printf(" "); + for( Int_t i = 0; i < kMcmCol; i++ ) { + printf("%2d ",fHit2padSum[1][i]); + } + printf("\n"); + } + + // sort the sums in decreasing order of the amplitude + Sort(kMcmCol,&fHit2padSum[0][0],&fHit2padSum[1][0],1); + + if (fTrigParam->GetDebugLevel() > 1) { + printf("fHit2padSum: "); + for( Int_t i = 0; i < kMcmCol; i++ ) { + printf("%2d ",fHit2padSum[0][i]); + } + printf("\n"); + printf(" "); + for( Int_t i = 0; i < kMcmCol; i++ ) { + printf("%2d ",fHit2padSum[1][i]); + } + printf("\n"); + } + + // arrange (maximum number of) candidates in increasing order of the column number + nSeeds = TMath::Min(Nsum2seed,kMaxTrackletsPerMCM); + Sort(nSeeds,&fHit2padSum[1][0],&fHit2padSum[0][0],0); + + for (Int_t i = 0; i < nSeeds; i++) { + fSeedCol[i] = fHit2padSum[0][i]; + } + + if (fTrigParam->GetDebugLevel() > 1) { + printf("Found %d seeds before multiple rejection. \n",nSeeds); + printf("fHit2padSum: "); + for( Int_t i = 0; i < kMcmCol; i++ ) { + printf("%2d ",fHit2padSum[0][i]); + } + printf("\n"); + printf(" "); + for( Int_t i = 0; i < kMcmCol; i++ ) { + printf("%2d ",fHit2padSum[1][i]); + } + printf("\n"); + } + + // reject multiple found tracklets + Int_t imax = nSeeds-1; + for (Int_t i = 0; i < imax; i++) { + + if ((fHit2padSum[0][i]+1) == fHit2padSum[0][i+1]) { + nSeeds--; + if (fHit2padSum[1][i] >= fHit2padSum[1][i+1]) { + if (fTrigParam->GetDebugLevel() > 1) + printf("Reject seed %1d in col %02d. \n",i,fHit2padSum[0][i+1]); + fSeedCol[i+1] = -1; + } else { + if (fTrigParam->GetDebugLevel() > 1) + printf("Reject seed %1d in col %02d. \n",i,fHit2padSum[0][i]); + fSeedCol[i] = -1; + } + } + + } + + if ( fTrigParam->GetDebugLevel() > 1 ) { + printf("Found %d seeds in MCM %d ",nSeeds,Id()); + for (Int_t i = 0; i < (imax+1); i++) { + if (fSeedCol[i] >= 0) printf(", %02d ",fSeedCol[i]); + } + printf("\n"); + } + + return nSeeds; + +} + +//_____________________________________________________________________________ +void AliTRDmcm::Sort(Int_t nel, Int_t *x1, Int_t *x2, Int_t dir) +{ + + // Sort two parallel vectors (x1[nel], x2[nel]) after the second one (x2) + // in the direction: dir = 0 ascending order + // dir = 1 descending order + + Bool_t sort; + Int_t tmp1, tmp2; + + if ( dir == 0 ) { + + do { + sort = kTRUE; + for ( Int_t i = 0; i < (nel-1); i++ ) + if ( x2[i+1] < x2[i] ) { + tmp2 = x2[i]; + x2[i] = x2[i+1]; + x2[i+1] = tmp2; + tmp1 = x1[i]; + x1[i] = x1[i+1]; + x1[i+1] = tmp1; + sort = kFALSE; + } + } while ( sort == kFALSE ); + + } + + if ( dir == 1 ) { + + do { + sort = kTRUE; + for ( Int_t i = 0; i < (nel-1); i++ ) + if ( x2[i+1] > x2[i] ) { + tmp2 = x2[i]; + x2[i] = x2[i+1]; + x2[i+1] = tmp2; + tmp1 = x1[i]; + x1[i] = x1[i+1]; + x1[i+1] = tmp1; + sort = kFALSE; + } + } while ( sort == kFALSE ); + + } + +} + +//_____________________________________________________________________________ +void AliTRDmcm::AddTimeBin(const Int_t iTime) +{ + // + // Build column seeds + // + + for (Int_t iPad = 1; iPad < (kMcmCol-1); iPad++) { + if (fIsClus[iPad][iTime]) { + fPadHits[iPad]++; + } + } + +} + +//_____________________________________________________________________________ +Bool_t AliTRDmcm::IsCluster(Float_t amp[3]) +{ + // + // Find if the amplitudes amp[0], amp[1], amp[2] are a cluster + // + + // -> shape + if (amp[0] > amp[1] || amp[2] > amp[1]) return kFALSE; + + // -> cluster amplitude + if ((amp[0]+amp[1]+amp[2]) < fClusThr) return kFALSE; + + // -> pad amplitude + if (amp[0] < fPadThr && amp[2] < fPadThr) return kFALSE; + + return kTRUE; + +} + +//_____________________________________________________________________________ +void AliTRDmcm::Filter(Int_t nexp, Int_t ftype) +{ + // + // exponential filter + // + + Double_t sour[kMcmTBmax]; + Double_t Dtarg[kMcmTBmax]; + Int_t Itarg[kMcmTBmax]; + + switch(ftype) { + + case 0: + + for (Int_t iCol = 0; iCol < kMcmCol; iCol++) { + for (Int_t iTime = 0; iTime < kMcmTBmax; iTime++) { + sour[iTime] = fADC[iCol][iTime]; + } + DeConvExpA(sour,Dtarg,kMcmTBmax,nexp); + for (Int_t iTime = 0; iTime < kMcmTBmax; iTime++) { + //fADC[iCol][iTime] = (Int_t)TMath::Max(0.0,Dtarg[iTime]); + fADC[iCol][iTime] = TMath::Max(0.0,Dtarg[iTime]); + } + } + break; + + case 1: + + for (Int_t iCol = 0; iCol < kMcmCol; iCol++) { + for (Int_t iTime = 0; iTime < kMcmTBmax; iTime++) { + sour[iTime] = fADC[iCol][iTime]; + } + DeConvExpD(sour,Itarg,kMcmTBmax,nexp); + for (Int_t iTime = 0; iTime < kMcmTBmax; iTime++) { + fADC[iCol][iTime] = Itarg[iTime]; + } + } + break; + + case 2: + + for (Int_t iCol = 0; iCol < kMcmCol; iCol++) { + for (Int_t iTime = 0; iTime < kMcmTBmax; iTime++) { + sour[iTime] = fADC[iCol][iTime]; + } + DeConvExpMI(sour,Dtarg,kMcmTBmax); + for (Int_t iTime = 0; iTime < kMcmTBmax; iTime++) { + //fADC[iCol][iTime] = (Int_t)TMath::Max(0.0,Dtarg[iTime]); + fADC[iCol][iTime] = TMath::Max(0.0,Dtarg[iTime]); + } + } + break; + + default: + + printf("Invalid filter type %d ! \n",ftype); + return; + + } + +} + +//_____________________________________________________________________________ +void AliTRDmcm::DeConvExpA(Double_t *source, Double_t *target, Int_t n, Int_t nexp) +{ + + Double_t rates[2]; + Double_t coefficients[2]; + + // initialize (coefficient = alpha, rates = lambda) + + // FilterOpt.C (aliroot@pel:/homel/aliroot/root/work/beamt/CERN02) + Double_t R1, R2, C1, C2; + R1 = (Double_t)fR1; + R2 = (Double_t)fR2; + C1 = (Double_t)fC1; + C2 = (Double_t)fC2; + + coefficients[0] = C1; + coefficients[1] = C2; + + Double_t Dt = 0.100; + rates[0] = TMath::Exp(-Dt/(R1)); + rates[1] = TMath::Exp(-Dt/(R2)); + + Int_t i, k; + Double_t reminder[2]; + Double_t correction, result; + + /* attention: computation order is important */ + correction=0.0; + for ( k=0; k 0x0FFF ) { + correction = 0x0FFF; + } else { + correction = (rem1 + rem2) & 0x0FFF; + } + + fTailPed = iFactor - correction; + + for (Int_t i=0; i> 11) ); + if ( h1 > 0x0FFF ) { + h1 = 0x0FFF; + } else { + h1 &= 0x0FFF; + } + + h2 = ( rem2 + ((iAlpha_s * result) >> 11)); + if ( h2 > 0x0FFF ) { + h2 = 0x0FFF; + } else { + h2 &= 0x0FFF; + } + + rem1 = (iLambda_l * h1 ) >> 11; + rem2 = (iLambda_s * h2 ) >> 11; + + if ( (rem1 + rem2) > 0x0FFF ) { + correction = 0x0FFF; + } else { + correction = (rem1 + rem2) & 0x0FFF; + } + } + +} + +//_____________________________________________________________________________ +void AliTRDmcm::DeConvExpMI(Double_t *source, Double_t *target, Int_t n) { + + Double_t Sig1[100], Sig2[100], Sig3[100];//, Sig4[100]; + for (Int_t i = 0; i < n; i++) Sig1[i] = source[i]; + + Float_t Dt = 0.100; + + //Float_t lambda0 = 9.8016*Dt; // short + //Float_t lambda1 = 1.0778*Dt; // long + + Float_t lambda0 = (1.0/fR2)*Dt; + Float_t lambda1 = (1.0/fR1)*Dt; + + TailMakerSpline(Sig1,Sig2,lambda0,n); + TailCancelationMI(Sig2,Sig3,0.7,lambda1,n); + + for (Int_t i = 0; i < n; i++) target[i] = Sig3[i]; + +} + +//______________________________________________________________________________ +void AliTRDmcm::TailMakerSpline(Double_t *ampin, Double_t *ampout, Double_t lambda, Int_t n) { + + Double_t l = TMath::Exp(-lambda*0.5); + // + // + Double_t in[1000]; + Double_t out[1000]; + // initialize in[] and out[] goes 0 ... 2*n+19 + for (Int_t i=0; i=0; i--){ + out[i] = in[i] + temp; + temp = l*(temp+in[i]); + } + + // + for (int i=0;i + +const Int_t kMaxTrackletsPerMCM = 4; +const Int_t kMcmCol = 21; +const Int_t kMcmTBmax = 60; +const Int_t kSelClus = 6; +const Int_t kMaxClus = 4; + +class AliTRDtrigParam; + +class AliTRDmcm : public TObject { + + public: + + AliTRDmcm(); + AliTRDmcm(AliTRDtrigParam *trigp, const Int_t id); + virtual ~AliTRDmcm(); + + Int_t Ntrk() { return fNtrk; }; + Int_t *GetTrkIndex() { return &fTrkIndex[0]; }; + Int_t GetRobId() { return fRobId; }; + Int_t GetChaId() { return fChaId; }; + void SetRobId(const Int_t id) { fRobId = id; }; + void SetChaId(const Int_t id) { fChaId = id; }; + void SetRow(const Int_t row) { fRow = row; }; + Int_t GetRow() { return fRow; }; + void SetColRange(const Int_t colf, const Int_t coll) { fColFirst = colf; fColLast = coll; }; + void GetColRange(Int_t &colf, Int_t &coll) { colf = fColFirst; coll = fColLast; }; + void AddTrk(const Int_t id); + void SetADC(const Int_t icol, const Int_t itb, const Float_t adc) + { fADC[icol][itb] = adc; }; + Float_t GetADC(const Int_t icol, const Int_t itb) { return fADC[icol][itb]; }; + void Reset(); + Bool_t Run(); + void SetCluster(const Int_t icol, const Int_t itb) { fIsClus[icol][itb] = kTRUE; }; + void UnSetCluster(const Int_t icol, const Int_t itb) { fIsClus[icol][itb] = kFALSE; }; + Bool_t IsCluster(Float_t amp[3]); + void AddTimeBin(const Int_t itime); + Int_t CreateSeeds(); + void Sort(const Int_t nel, Int_t *x1, Int_t *x2, Int_t dir); + Int_t GetNtrkSeeds() { return fNtrkSeeds; }; + Int_t *GetSeedCol() { return &fSeedCol[0]; }; + Int_t *GetPadHits() { return &fPadHits[0]; }; + Bool_t IsCluster(const Int_t icol, const Int_t itim) { return fIsClus[icol][itim]; }; + + void Filter(Int_t nexp, Int_t ftype = 0); + void DeConvExpA(Double_t *source, Double_t *target, Int_t n, Int_t nexp); + void DeConvExpD(Double_t *source, Int_t *target, Int_t n, Int_t nexp); + void DeConvExpMI(Double_t *source, Double_t *target, Int_t n); + void TailMakerSpline(Double_t *ampin, Double_t *ampout, Double_t lambda, Int_t n); + void TailCancelationMI(Double_t *ampin, Double_t *ampout, Double_t norm, Double_t lambda, Int_t n); + + Int_t Id() { return fId; }; + + protected: + + AliTRDtrigParam *fTrigParam; //! pointer to the trigger parameters class + + Int_t fNtrk; // number of found tracklets + Int_t fTrkIndex[kMaxTrackletsPerMCM]; // index of found tracklets + Int_t fRobId; // ROB id + Int_t fChaId; // Chamber id + Int_t fRow; // pad row number (0-11 or 0-15) + Int_t fColFirst; // first pad column + Int_t fColLast; // last pad column (<) + Float_t fADC[kMcmCol][kMcmTBmax]; //! array with MCM ADC values + Bool_t fIsClus[kMcmCol][kMcmTBmax]; //! flag of a cluster maximum + Int_t fTime1; // first time bin for tracking (incl.) + Int_t fTime2; // last time bin for tracking (incl.) + Float_t fClusThr; // cluster threshold + Float_t fPadThr; // pad threshold + Int_t fPadHits[kMcmCol]; // hit counter in pads + Int_t fNtrkSeeds; // number of found seeds + Int_t fSeedCol[kMaxTrackletsPerMCM]; // column number of found tracklet seeds + Float_t fR1; // filter parameters (1 = long, 2 = short component) + Float_t fR2; // + Float_t fC1; // + Float_t fC2; // + Float_t fPedestal; // + + Int_t fId; // dummy id + + ClassDef(AliTRDmcm,1) // TRD mcm + +}; + +#endif diff --git a/TRD/AliTRDmcmTracklet.cxx b/TRD/AliTRDmcmTracklet.cxx new file mode 100644 index 00000000000..4155d74d51c --- /dev/null +++ b/TRD/AliTRDmcmTracklet.cxx @@ -0,0 +1,420 @@ +/************************************************************************** + * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. * + * * + * Author: The ALICE Off-line Project. * + * Contributors are mentioned in the code where appropriate. * + * * + * Permission to use, copy, modify and distribute this software and its * + * documentation strictly for non-commercial purposes is hereby granted * + * without fee, provided that the above copyright notice appears in all * + * copies and that both the copyright notice and this permission notice * + * appear in the supporting documentation. The authors make no claims * + * about the suitability of this software for any purpose. It is * + * provided "as is" without express or implied warranty. * + **************************************************************************/ + +#include +#include +#include + +#include "AliTRDcalibDB.h" +#include "AliTRDCommonParam.h" +#include "AliTRDpadPlane.h" +#include "AliTRDgeometry.h" + +#include "AliTRDmcmTracklet.h" + +ClassImp(AliTRDmcmTracklet) + +//_____________________________________________________________________________ +AliTRDmcmTracklet::AliTRDmcmTracklet() +{ + + // + // AliTRDmcmTracklet default constructor + // + + fDetector = -1; + fRow = -1; + + for (Int_t time = 0; time < kNtimeBins; time++) { + for (Int_t icl = 0; icl < kNclsPads; icl++) { + fADC[time][icl] = 0; + } + for (Int_t it = 0; it < kNdict; it++) { + fTrack[time][it] = -1; + } + fTime[time] = 0; + fCol[time] = 0; + } + + fNclusters = 0; + fN = 0; + fTrackLabel = -1; + + fGPos = 0; + fGAmp = 0; + + fSlope = 0.0; + fOffset = 0.0; + fTime0 = 0.0; + fRowz = 0.0; + fPt = 0.0; + fdQdl = 0.0; + +} + +//_____________________________________________________________________________ +AliTRDmcmTracklet::AliTRDmcmTracklet(Int_t det, Int_t row, Int_t n) +{ + + // + // AliTRDmcmTracklet default constructor + // + + fDetector = det; + fRow = row; + + for (Int_t time = 0; time < kNtimeBins; time++) { + for (Int_t icl = 0; icl < kNclsPads; icl++) { + fADC[time][icl] = 0; + } + for (Int_t it = 0; it < kNdict; it++) { + fTrack[time][it] = -1; + } + fTime[time] = 0; + fCol[time] = 0; + } + + fNclusters = 0; + + fN = n; + + fTrackLabel = -1; + + fGPos = new TGraph(0); + fGAmp = new TGraph(0); + + fSlope = 0.0; + fOffset = 0.0; + fTime0 = 0.0; + fRowz = 0.0; + fPt = 0.0; + fdQdl = 0.0; + +} + +//_____________________________________________________________________________ +AliTRDmcmTracklet::~AliTRDmcmTracklet() +{ + + // + // AliTRDmcmTracklet destructor + // + +} + +//_____________________________________________________________________________ +void AliTRDmcmTracklet::MakeTrackletGraph(AliTRDgeometry *geo, Float_t field) +{ + + // + // Tracklet graph of positions (global coordinates, rotated [cm]) + // + + if (!geo) { + Error("MakeTrackletGraph","No geometry."); + return; + } + + AliTRDCommonParam* commonParam = AliTRDCommonParam::Instance(); + if (!commonParam) + { + Error("MakeTrackletGraph","No common params."); + return; + } + + AliTRDcalibDB* calibration = AliTRDcalibDB::Instance(); + if (!calibration) + { + Error("MakeTrackletGraph","No instance of AliTRDcalibDB."); + return; + } + + Int_t iplan, icham; + + iplan = geo->GetPlane(fDetector); + icham = geo->GetChamber(fDetector); + + AliTRDpadPlane *padPlane = commonParam->GetPadPlane(iplan,icham); + + Float_t SamplFreq = calibration->GetSamplingFrequency(); + + Int_t time, col; + Float_t amp[3]; + Float_t Xpos, Ypos, Xzero, ColSize, TimeBinSize; + Float_t vDrift, OmegaTau, LorentzAngle, ThetaSlope; + Float_t TiltingAngle; + Int_t npg = 0; + + for (Int_t icl = 0; icl < fNclusters; icl++) { + + time = GetClusterTime(icl); + + amp[0] = GetClusterADC(icl)[0]; + amp[1] = GetClusterADC(icl)[1]; + amp[2] = GetClusterADC(icl)[2]; + + col = GetClusterCol(icl); + + if (amp[0] < 0.0 || amp[1] < 0.0 || amp[2] < 0.0) continue; + + Ypos = GetClusY(amp,iplan); + + ColSize = padPlane->GetColSize(col); + vDrift = calibration->GetVdrift(fDetector,col,fRow); + TimeBinSize = vDrift/SamplFreq; + + // From v4-03-Release to HEAD28Mar06 the sign has changed from "-" to "+" + // due to a change in the digitizer + OmegaTau = +TMath::Sign(1.0,(Double_t)field)*GetOmegaTau(vDrift,TMath::Abs(field)); + LorentzAngle = TMath::ATan(OmegaTau)*180.0/TMath::Pi(); + + Xpos = (time+0.5) * TimeBinSize; + Xpos = geo->GetTime0(iplan) - Xpos; + + Ypos = padPlane->GetColPos(col) - (Ypos + 0.5) * ColSize; + + // ExB correction + Xzero = geo->GetTime0(iplan); + Ypos = Ypos + (Xpos-Xzero) * OmegaTau; + + // tilted pads correction + ThetaSlope = - padPlane->GetRowPos(fRow)/geo->GetTime0(iplan); + TiltingAngle = padPlane->GetTiltingAngle()/180.0*TMath::Pi(); + Ypos = Ypos - (Xpos-Xzero) * ThetaSlope * TMath::Sin(TiltingAngle); + + fGPos->SetPoint(npg,(Double_t)Xpos,(Double_t)Ypos); + npg++; + + } + + fGPos->Set(npg); + + fTime0 = geo->GetTime0(iplan) - AliTRDgeometry::CdrHght() - 0.5*AliTRDgeometry::CamHght(); + fRowz = 0.5*(padPlane->GetRowPos(fRow) + padPlane->GetRowPos(fRow+1)); + + Double_t xMin = 0, xMax = 0, x, y; + fGPos->GetPoint(0 ,x,y); xMax = x + 0.1; + fGPos->GetPoint(npg-1,x,y); xMin = x - 0.1; + + TF1 *line = new TF1("line","[0]+x*[1]",xMin,xMax); + fGPos->Fit(line,"WRQ0"); + + fOffset = line->Eval(fTime0); + fSlope = TMath::ATan(line->GetParameter(1))*180.0/TMath::Pi(); + + line->Delete(); + + Float_t fX = fTime0; + Float_t fY = fOffset; + + Float_t infSlope = TMath::ATan(fY/fX)/TMath::Pi()*180.0; + Float_t alpha = fSlope - infSlope; + Float_t R = TMath::Sqrt(fX*fX + fY*fY)/(2.0*TMath::Sin(alpha/180.0*TMath::Pi())); + + fPt = 0.3 * field * 0.01 * R; + + return; + +} + +//_____________________________________________________________________________ +void AliTRDmcmTracklet::MakeClusAmpGraph() +{ + // + // Tracklet graph of cluster charges + // + + AliTRDcalibDB* calibration = AliTRDcalibDB::Instance(); + if (!calibration) + { + Error("MakeClusAmpGraph","No instance of AliTRDcalibDB."); + return; + } + + Int_t time; + Float_t amp[3]; + Int_t npg = 0; + fdQdl = 0.0; + for (Int_t icl = 0; icl < fNclusters; icl++) { + + time = GetClusterTime(icl); + + amp[0] = GetClusterADC(icl)[0]; + amp[1] = GetClusterADC(icl)[1]; + amp[2] = GetClusterADC(icl)[2]; + + fGAmp->SetPoint(npg,(Double_t)(time+0.5),(Double_t)(amp[0]+amp[1]+amp[2])); + npg++; + + fdQdl += amp[0]+amp[1]+amp[2]; + + } + + fGAmp->Set(npg); + + fdQdl /= (Float_t)npg; + + return; + +} + +//_____________________________________________________________________________ +Float_t AliTRDmcmTracklet::GetClusY(Float_t *adc, Int_t pla) +{ + // + // Cluster position in the phi direction in pad units (relative to the pad border) + // + + Float_t Ypos = 0.0; + + Float_t A0 = adc[0]; + Float_t A1 = adc[1]; + Float_t A2 = adc[2]; + + Float_t T1, T2, W1 ,W2; + + Float_t W = 1.0; // pad units + + Float_t Sigma = 0.0; + + switch(pla) { + case 0: + Sigma = 0.515; break; + case 1: + Sigma = 0.501; break; + case 2: + Sigma = 0.491; break; + case 3: + Sigma = 0.481; break; + case 4: + Sigma = 0.471; break; + case 5: + Sigma = 0.463; break; + default: + Error("GetClusY","Wrong plane number."); + return 0.0; + } + + Sigma *= W; + + T1 = 0.0; + W1 = 0.0; + if( A0 > 0 ) { + W1 = A0*A0; + //W1 = A0; + T1 = W1*((Sigma*Sigma)/W*TMath::Log(A1/A0)-0.5*W); + } + T2 = 0.0; + W2 = 0.0; + if( A2 > 0 ) { + W2 = A2*A2; + //W2 = A2; + T2 = W2*((Sigma*Sigma)/W*TMath::Log(A2/A1)+0.5*W); + } + + Ypos = W*(T1+T2)/(W1+W2); // range: -0.5*W ... +0.5*W + + return Ypos; + +} + +//_____________________________________________________________________________ +void AliTRDmcmTracklet::CookLabel(Float_t frac) +{ + // + // Cook the track label from cluster labels + // + + const Int_t kMaxTracks = 10; + Int_t trackLabel[kMaxTracks]; + Int_t trackCount[kMaxTracks]; + for (Int_t it = 0; it < kMaxTracks; it++) { + trackLabel[it] = -1; + trackCount[it] = 0; + } + + Bool_t counted; + Int_t label, nTracks = 0; + for (Int_t icl = 0; icl < fNclusters; icl++) { + + for (Int_t id = 0; id < kNdict; id++) { + + if (fTrack[icl][id] == -1) continue; + + label = fTrack[icl][id]; + + counted = kFALSE; + for (Int_t it = 0; it < nTracks; it++) { + if (label == trackLabel[it]) { + trackCount[it]++; + counted = kTRUE; + break; + } + } + if (!counted) { + trackLabel[nTracks] = label; + trackCount[nTracks]++; + nTracks++; + if (nTracks == kMaxTracks) { + Warning("CookLabel","Too many tracks for this tracklet."); + nTracks--; + break; + } + } + + } + + } + + for (Int_t it = 0; it < kMaxTracks; it++) { + if (trackCount[it] >= (Int_t)(frac*fNclusters)) { + fTrackLabel = trackLabel[it]; + break; + } + } + +} + +//_____________________________________________________________________________ +Float_t AliTRDmcmTracklet::GetOmegaTau(Float_t vdrift, Float_t field) +{ + // + // Returns omega*tau (tan(Lorentz-angle)) for a given drift velocity + // and a B-field for Xe/CO2 (15%). + // The values are according to a GARFIELD simulation. + // + + // + // Copy of the "AliTRDcalibDB" function, taking as argument the magnetic field too + // + + const Int_t kNb = 5; + Float_t p0[kNb] = { 0.004810, 0.007412, 0.010252, 0.013409, 0.016888 }; + Float_t p1[kNb] = { 0.054875, 0.081534, 0.107333, 0.131983, 0.155455 }; + Float_t p2[kNb] = { -0.008682, -0.012896, -0.016987, -0.020880, -0.024623 }; + Float_t p3[kNb] = { 0.000155, 0.000238, 0.000330, 0.000428, 0.000541 }; + + Int_t ib = ((Int_t) (10 * (field - 0.15))); + ib = TMath::Max( 0,ib); + ib = TMath::Min(kNb,ib); + + Float_t alphaL = p0[ib] + + p1[ib] * vdrift + + p2[ib] * vdrift*vdrift + + p3[ib] * vdrift*vdrift*vdrift; + + return TMath::Tan(alphaL); + +} diff --git a/TRD/AliTRDmcmTracklet.h b/TRD/AliTRDmcmTracklet.h new file mode 100644 index 00000000000..c79ebde26a1 --- /dev/null +++ b/TRD/AliTRDmcmTracklet.h @@ -0,0 +1,98 @@ +#ifndef ALITRDMCMTRACKLET_H +#define ALITRDMCMTRACKLET_H +/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. * + * See cxx source for full Copyright notice */ + +/////////////////////////////////////////////////////// +// Tracklet object (MCM/TRIGGER) // +/////////////////////////////////////////////////////// + +#include + +const Int_t kNclsPads = 3; +const Int_t kNtimeBins = 30; +const Int_t kNdict = 3; + +class TGraph; + +class AliTRDgeometry; + +class AliTRDmcmTracklet : public TObject { + + public: + + AliTRDmcmTracklet(); + AliTRDmcmTracklet(Int_t det, Int_t row, Int_t n); + virtual ~AliTRDmcmTracklet(); + + void AddCluster(Int_t icol, Int_t itb, Float_t *adc, Int_t *track) { + if (fNclusters >= kNtimeBins) return; + for (Int_t icl = 0; icl < kNclsPads; icl++) { + //fADC[fNclusters][icl] = (Int_t)adc[icl]; + fADC[fNclusters][icl] = adc[icl]; + } + fTrack[fNclusters][0] = track[0]; + fTrack[fNclusters][1] = track[1]; + fTrack[fNclusters][2] = track[2]; + fTime[fNclusters] = itb; + fCol[fNclusters] = icol; + fNclusters++; + }; + + Float_t *GetClusterADC(Int_t icl) { return fADC[icl]; }; + Int_t GetClusterTime(Int_t icl) { return fTime[icl]; }; + Int_t GetClusterCol(Int_t icl) { return fCol[icl]; }; + + TGraph *GetTrackletGraph() { return fGPos; }; + TGraph *GetClusAmpGraph() { return fGAmp; }; + + virtual void MakeTrackletGraph(AliTRDgeometry *geo = 0, Float_t field = 0); + virtual void MakeClusAmpGraph(); + + Float_t GetClusY(Float_t *adc, Int_t pla); + + Int_t GetNumber() { return fN; }; + + void CookLabel(Float_t frac); + Int_t GetLabel() { return fTrackLabel; }; + + Int_t GetNclusters() { return fNclusters; }; + Int_t GetDetector() { return fDetector; }; + Int_t GetRow() { return fRow; }; + Float_t GetOffset() { return fOffset; }; + Float_t GetSlope() { return fSlope; }; + Float_t GetTime0() { return fTime0; }; + Float_t GetRowz() { return fRowz; }; + Float_t GetPt() { return fPt; }; + Float_t GetdQdl() { return fdQdl; }; + + Float_t GetOmegaTau(Float_t vdrift, Float_t field); + + protected: + + Int_t fDetector; // TRD detector number (0 ... 539) + Int_t fRow; // Row number in the detector + Float_t fADC[kNtimeBins][kNclsPads]; // Array of ADC values in a pad group + Int_t fTrack[kNtimeBins][kNdict]; //! Array of track dictionary values + Int_t fTrackLabel; // Cooked track label + Int_t fTime[kNtimeBins]; // Array of time bin values + Int_t fCol[kNtimeBins]; // Array of pad column values + Int_t fNclusters; // Number of clusters in the tracklet + + Int_t fN; // Tracklet number + + TGraph *fGPos; //! Positions + TGraph *fGAmp; //! Amplitudes + + Float_t fTime0; // X position at the entrance window + Float_t fRowz; // Z position of the row center + Float_t fSlope; // Slope [deg] + Float_t fOffset; // Offset + Float_t fPt; // Transverse momentum + Float_t fdQdl; // Charge per unit length + + ClassDef(AliTRDmcmTracklet,1) // Track segment for the TRD (Tracklet) + +}; + +#endif diff --git a/TRD/AliTRDtrigParam.cxx b/TRD/AliTRDtrigParam.cxx new file mode 100644 index 00000000000..2683df98a98 --- /dev/null +++ b/TRD/AliTRDtrigParam.cxx @@ -0,0 +1,185 @@ +/************************************************************************** + * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. * + * * + * Author: The ALICE Off-line Project. * + * Contributors are mentioned in the code where appropriate. * + * * + * Permission to use, copy, modify and distribute this software and its * + * documentation strictly for non-commercial purposes is hereby granted * + * without fee, provided that the above copyright notice appears in all * + * copies and that both the copyright notice and this permission notice * + * appear in the supporting documentation. The authors make no claims * + * about the suitability of this software for any purpose. It is * + * provided "as is" without express or implied warranty. * + **************************************************************************/ + +/////////////////////////////////////////////////////////////////////////////// +// // +// TRD trigger parameters class // +// // +/////////////////////////////////////////////////////////////////////////////// + +#include "AliTRDgeometry.h" + +#include "AliTRDtrigParam.h" + +ClassImp(AliTRDtrigParam) + +//_____________________________________________________________________________ +AliTRDtrigParam::AliTRDtrigParam():TNamed() +{ + // + // AliTRDtrigParam default constructor + // + + fDebug = 0; + fTime1 = 0; + fTime2 = 0; + fClusThr = 0; + fPadThr = 0; + fSum10 = 0; + fSum12 = 0; + fTCOn = 0; + fTCnexp = 0; + fFilterType = 0; + fR1 = 0; + fR2 = 0; + fC1 = 0; + fC2 = 0; + fPedestal = 0; + fDeltaY = 0.0; + fDeltaS = 0.0; + fXprojPlane = 0.0; + fField = 0.0; + fLtuPtCut = 0.0; + fGtuPtCut = 0.0; + +} + +//_____________________________________________________________________________ +AliTRDtrigParam::AliTRDtrigParam(const Text_t *name, const Text_t *title) + :TNamed(name,title) +{ + // + // AliTRDtrigParam constructor + // + + fDebug = 0; + fTime1 = 2; + fTime2 = 22; + fClusThr = 10.0; + fPadThr = 1; + fSum10 = 2; + fSum12 = 10; + fTCOn = 1; + fTCnexp = 1; + fFilterType = 0; + fR1 = 0.0; + fR2 = 0.0; + fC1 = 0.0; + fC2 = 0.0; + fPedestal = 0.0; + fDeltaY = 2.0; + fDeltaS = 2.5; + fXprojPlane = 0.0; + fField = 0.0; + fLtuPtCut = 2.3; + fGtuPtCut = 3.0; + + // PASA.v.4 + + if (fTCnexp == 1) { + fR1 = 1.1563; + fR2 = 0.1299; + fC1 = 0.0657; + fC2 = 0.0000; + } + + if (fTCnexp == 2) { + fR1 = 1.1563; + fR2 = 0.1299; + fC1 = 0.1141; + fC2 = 0.6241; + } + +} + +//_____________________________________________________________________________ +AliTRDtrigParam::AliTRDtrigParam(const AliTRDtrigParam &p):TNamed(p) +{ + // + // AliTRDtrigParam copy constructor + // + + ((AliTRDtrigParam &) p).Copy(*this); + +} + +//_____________________________________________________________________________ +AliTRDtrigParam::~AliTRDtrigParam() +{ + // + // AliTRDtrigParam destructor + // +} + +//_____________________________________________________________________________ +AliTRDtrigParam &AliTRDtrigParam::operator=(const AliTRDtrigParam &p) +{ + // + // Assignment operator + // + + if (this != &p) ((AliTRDtrigParam &) p).Copy(*this); + return *this; + +} + +//_____________________________________________________________________________ +void AliTRDtrigParam::Copy(TObject &p) const +{ + // + // Copy function + // + + ((AliTRDtrigParam &) p).fDebug = fDebug; + ((AliTRDtrigParam &) p).fTime1 = fTime1; + ((AliTRDtrigParam &) p).fTime2 = fTime2; + ((AliTRDtrigParam &) p).fClusThr = fClusThr; + ((AliTRDtrigParam &) p).fPadThr = fPadThr; + ((AliTRDtrigParam &) p).fSum10 = fSum10; + ((AliTRDtrigParam &) p).fSum12 = fSum12; + ((AliTRDtrigParam &) p).fTCOn = fTCOn; + ((AliTRDtrigParam &) p).fTCnexp = fTCnexp; + ((AliTRDtrigParam &) p).fFilterType = fFilterType; + ((AliTRDtrigParam &) p).fR1 = fR1; + ((AliTRDtrigParam &) p).fR2 = fR2; + ((AliTRDtrigParam &) p).fC1 = fC1; + ((AliTRDtrigParam &) p).fC2 = fC2; + ((AliTRDtrigParam &) p).fPedestal = fPedestal; + ((AliTRDtrigParam &) p).fDeltaY = fDeltaY; + ((AliTRDtrigParam &) p).fDeltaS = fDeltaS; + ((AliTRDtrigParam &) p).fXprojPlane = fXprojPlane; + ((AliTRDtrigParam &) p).fField = fField; + ((AliTRDtrigParam &) p).fLtuPtCut = fLtuPtCut; + ((AliTRDtrigParam &) p).fGtuPtCut = fGtuPtCut; + +} + +//_____________________________________________________________________________ +void AliTRDtrigParam::Init() +{ + // + // Initialize the other parameters + // + + Float_t fXplane0, fXplane5; + + fXplane0 = AliTRDgeometry::GetTime0(0) - AliTRDgeometry::CdrHght() - 0.5*AliTRDgeometry::CamHght(); + + fXplane5 = AliTRDgeometry::GetTime0(5) - AliTRDgeometry::CdrHght() - 0.5*AliTRDgeometry::CamHght(); + + fXprojPlane = 0.5 * (fXplane0 + fXplane5); + +} + diff --git a/TRD/AliTRDtrigParam.h b/TRD/AliTRDtrigParam.h new file mode 100644 index 00000000000..179b6fef27c --- /dev/null +++ b/TRD/AliTRDtrigParam.h @@ -0,0 +1,108 @@ +#ifndef ALITRDTRIGPARAM_H +#define ALITRDTRIGPARAM_H +/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. * + * See cxx source for full Copyright notice */ + +/////////////////////////////////////////////////////////////////////////////// +// // +// TRD trigger parameters class // +// // +/////////////////////////////////////////////////////////////////////////////// + +#include + +class AliTRDtrigParam : public TNamed { + + public: + + AliTRDtrigParam(); + AliTRDtrigParam(const Text_t* name, const Text_t* title); + AliTRDtrigParam(const AliTRDtrigParam &p); + virtual ~AliTRDtrigParam(); + AliTRDtrigParam &operator=(const AliTRDtrigParam &p); + + virtual void Copy(TObject &p) const; + virtual void Init(); + + void SetTimeRange(const Int_t time1, const Int_t time2) { fTime1 = time1; fTime2 = time2; }; + Int_t GetTime1() const { return fTime1; }; + Int_t GetTime2() const { return fTime2; }; + void SetClusThr(const Float_t clth) { fClusThr = clth; }; + void SetPadThr(const Float_t path) { fPadThr = path; }; + Float_t GetClusThr() const { return fClusThr; }; + Float_t GetPadThr() const { return fPadThr; }; + void SetSum10(const Int_t sum) { fSum10 = sum; }; + void SetSum12(const Int_t sum) { fSum12 = sum; }; + Int_t GetSum10() const { return fSum10; }; + Int_t GetSum12() const { return fSum12; }; + + void SetTailCancelation(Int_t tcOn = 0) { fTCOn = tcOn; }; + void SetNexponential(Int_t nexp = 1) { fTCnexp = nexp; }; + void SetFilterType(Int_t ftype = 0) { fFilterType = ftype; }; + void SetFilterParam(Float_t r1, Float_t r2, Float_t c1, Float_t c2, Float_t ped) + { fR1 = r1; fR2 = r2; fC1 = c1; fC2 = c2; fPedestal = ped; }; + + Int_t GetTailCancelation() const { return fTCOn; }; + Int_t GetNexponential() const { return fTCnexp; }; + Int_t GetFilterType() const { return fFilterType; }; + void GetFilterParam(Float_t &r1, Float_t &r2, Float_t &c1, Float_t &c2, Float_t &ped) const { + r1 = fR1; r2 = fR2; c1 = fC1; c2 = fC2; ped = fPedestal; + }; + + void SetADCnoise(const Float_t adcn) { fADCnoise = adcn; }; + Float_t GetADCnoise() { return fADCnoise; }; + + void SetDebugLevel(const Int_t deb) { fDebug = deb; }; + Int_t GetDebugLevel() { return fDebug; }; + + void SetDeltaY(Float_t dy) { fDeltaY = dy; }; + Float_t GetDeltaY() { return fDeltaY; }; + void SetDeltaS(Float_t ds) { fDeltaS = ds; }; + Float_t GetDeltaS() { return fDeltaS; }; + + Float_t GetXprojPlane() { return fXprojPlane; }; + + void SetField(Float_t b) { fField = b; }; + Float_t GetField() { return fField; }; + + void SetLtuPtCut(Float_t ptcut) { fLtuPtCut = ptcut; }; + Float_t GetLtuPtCut() { return fLtuPtCut; }; + + void SetGtuPtCut(Float_t ptcut) { fGtuPtCut = ptcut; }; + Float_t GetGtuPtCut() { return fGtuPtCut; }; + + protected: + + Int_t fDebug; // debugging flag + + Int_t fTime1; // first time bin for tracking (incl.) + Int_t fTime2; // last time bin for tracking (incl.) + Float_t fClusThr; // cluster threshold + Float_t fPadThr; // pad threshold + Int_t fSum10; // MCM CreateSeeds: Min_Thr_Left_Neighbour + Int_t fSum12; // MCM CreateSeeds: Min_Sum_From_Two_Neighbours + Int_t fTCOn; // tail cancelation flag + Int_t fTCnexp; // number of exp in filter + Int_t fFilterType; // filter type (0=A - analog, 1=D - digital) + Float_t fR1; // filter parameters (1 = long, 2 = short component) + Float_t fR2; // + Float_t fC1; // + Float_t fC2; // + Float_t fPedestal; // + Float_t fADCnoise; // ADC noise (not contained in the digitizer) + + Float_t fDeltaY; // Y (offset) matching window in the GTU + Float_t fDeltaS; // Slope matching window in the GTU + + Float_t fXprojPlane; // Projection plane (X) for GTU matching + + Float_t fLtuPtCut; // Local pt cut + Float_t fGtuPtCut; // Global pt cut + + Float_t fField; // Magnetic field + + ClassDef(AliTRDtrigParam,1) // TRD trigger parameter class + +}; + +#endif diff --git a/TRD/AliTRDtrigger.cxx b/TRD/AliTRDtrigger.cxx new file mode 100644 index 00000000000..c66342ced43 --- /dev/null +++ b/TRD/AliTRDtrigger.cxx @@ -0,0 +1,1622 @@ +/************************************************************************** + * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. * + * * + * Author: The ALICE Off-line Project. * + * Contributors are mentioned in the code where appropriate. * + * * + * Permission to use, copy, modify and distribute this software and its * + * documentation strictly for non-commercial purposes is hereby granted * + * without fee, provided that the above copyright notice appears in all * + * copies and that both the copyright notice and this permission notice * + * appear in the supporting documentation. The authors make no claims * + * about the suitability of this software for any purpose. It is * + * provided "as is" without express or implied warranty. * + **************************************************************************/ + +/////////////////////////////////////////////////////////////////////////////// +// // +// TRD trigger class // +// // +/////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include + +#include "AliLog.h" +#include "AliRun.h" +#include "AliRunLoader.h" +#include "AliLoader.h" +#include "AliHeader.h" +#include "AliRawReader.h" + +#include "AliTRDdigitsManager.h" +#include "AliTRDgeometry.h" +#include "AliTRDdataArrayI.h" +#include "AliTRDcalibDB.h" +#include "AliTRDCommonParam.h" +#include "Cal/AliTRDCalPIDLQ.h" +#include "AliTRDrawData.h" + +#include "AliTRDtrigger.h" +#include "AliTRDmcmTracklet.h" +#include "AliTRDtrigParam.h" +#include "AliTRDmcm.h" + +ClassImp(AliTRDtrigger) +ClassImp(AliTRDltuTracklet) +ClassImp(AliTRDgtuTrack) +ClassImp(AliTRDmodule) + +//_____________________________________________________________________________ +AliTRDltuTracklet::AliTRDltuTracklet(Int_t det, + Int_t row, + Float_t rowz, + Float_t slope, + Float_t offset, + Float_t time, + Int_t ncl, + Int_t label, + Float_t q) +{ + // + // AliTRDltuTracklet constructor + // + + fDetector = det; + fRow = row; + fRowz = rowz; + fSlope = slope; + fX = time; + fY = offset; + fNclusters = ncl; + fLabel = label; + fQ = q; + +} + +//_____________________________________________________________________________ +Float_t AliTRDltuTracklet::GetPt(Float_t field) +{ + // transverse momentum calculation + // curvature R = (fX*fX + fY*fY) / (2 * sin(alpha)) + // alpha = angle deviation from "infinite momentum" + // + // consistent with AliTRDmcmTracklet::GetPt(...) + + Float_t InfSlope = TMath::ATan(fY/fX)/TMath::Pi()*180.0; + Float_t alpha = fSlope - InfSlope; + Float_t R = TMath::Sqrt(fX*fX + fY*fY)/(2.0*TMath::Sin(alpha/180.0*TMath::Pi())); + + Float_t Pt = 0.3 * field * 0.01 * R; + + return Pt; + +} + +//_____________________________________________________________________________ +Int_t AliTRDltuTracklet::Compare(const TObject * o) const +{ + // + // compare two LTU tracklets according to the intercept point Y1 + // + + AliTRDltuTracklet *ltutrk = (AliTRDltuTracklet*)o; + + if (fRow != ltutrk->fRow) return +1; + if (fDetector != ltutrk->fDetector) return +1; + + if (fY < ltutrk->fY) return -1; + if (fY == ltutrk->fY) return 0; + + return 1; + +} + +//_____________________________________________________________________________ +Float_t AliTRDltuTracklet::GetYproj(Float_t xpl) +{ + + Float_t Yproj; + + Yproj = fY + TMath::Tan(fSlope/180.0*TMath::Pi()) * (xpl - fX); + + return Yproj; + +} + +//_____________________________________________________________________________ +Float_t AliTRDltuTracklet::GetZproj(Float_t xpl) +{ + + Float_t Zproj; + + Zproj = fRowz * xpl / fX; + + return Zproj; + +} + +//_____________________________________________________________________________ +AliTRDgtuTrack::AliTRDgtuTrack() +{ + + fYproj = 0.0; + fZproj = 0.0; + fSlope = 0.0; + fDetector = -1; + fNtracklets = 0; + fNplanes = 0; + fNclusters = 0; + fPt = 0.0; + fPhi = 0.0; + fEta = 0.0; + fLabel = -1; + fPID = 0.0; + fIsElectron = kFALSE; + + fTracklets = new TObjArray(400); + +} + +//_____________________________________________________________________________ +AliTRDgtuTrack::AliTRDgtuTrack(const AliTRDgtuTrack& track): + TObject(track), + fYproj(track.fYproj), + fZproj(track.fZproj), + fSlope(track.fSlope), + fDetector(track.fDetector), + fNtracklets(track.fNtracklets), + fNplanes(track.fNplanes), + fNclusters(track.fNclusters), + fPt(track.fPt), + fPhi(track.fPhi), + fEta(track.fEta), + fLabel(track.fLabel), + fPID(track.fPID), + fIsElectron(track.fIsElectron) +{ + // + // copy contructor + // + + fTracklets = NULL; + +} + +//_____________________________________________________________________________ +void AliTRDgtuTrack::AddTracklet(AliTRDltuTracklet *trk) +{ + + Tracklets()->Add(trk); + +} + +//_____________________________________________________________________________ +AliTRDltuTracklet* AliTRDgtuTrack::GetTracklet(Int_t pos) +{ + + if (fTracklets == 0) return 0; + void * trk = fTracklets->UncheckedAt(pos); + if (trk == 0) return 0; + + return (AliTRDltuTracklet*)trk; + +} + +//_____________________________________________________________________________ +Int_t AliTRDgtuTrack::Compare(const TObject * o) const +{ + + AliTRDgtuTrack *gtutrack = (AliTRDgtuTrack*)o; + + if (fYproj < gtutrack->GetYproj()) return -1; + if (fYproj == gtutrack->GetYproj()) return 0; + + return +1; + +} + +//_____________________________________________________________________________ +void AliTRDgtuTrack::Reset() +{ + + fYproj = 0.0; + fZproj = 0.0; + fSlope = 0.0; + fDetector = -1; + fNtracklets = 0; + fNplanes = 0; + fNclusters = 0; + fPt = 0.0; + fPhi = 0.0; + fEta = 0.0; + fLabel = -1; + fPID = 0.0; + fIsElectron = kFALSE; + +} + +//_____________________________________________________________________________ +void AliTRDgtuTrack::Track(Float_t xpl, Float_t field) +{ + + AliTRDltuTracklet *trk; + Int_t nTracklets = GetNtracklets(); + Float_t fC[kNmaxTrk][3]; // X, Y, Z coordinates of segments + + fYproj = 0.0; + fZproj = 0.0; + fSlope = 0.0; + fNclusters = 0; + fNplanes = 0; + fNtracklets = GetNtracklets(); + Int_t InDetector[kNplan]; + for (Int_t i = 0; i < kNplan; i++) InDetector[i] = -1; + Int_t iDet, nDet = 0; + Bool_t NewDetector; + for (Int_t i = 0; i < nTracklets; i++) { + + trk = GetTracklet(i); + fYproj += trk->GetYproj(xpl); + fZproj += trk->GetZproj(xpl); + fSlope += trk->GetSlope(); + fNclusters += trk->GetNclusters(); + iDet = trk->GetDetector(); + + NewDetector = kTRUE; + for (Int_t id = 0; id < nDet; id++) { + if (iDet == InDetector[id]) { + NewDetector = kFALSE; + break; + } + } + if (NewDetector) { + InDetector[nDet++] = iDet; + fNplanes++; + } + + fC[i][0] = trk->GetTime0(); + fC[i][1] = trk->GetOffset(); + fC[i][2] = trk->GetRowz(); + + } + fYproj /= (Float_t)nTracklets; + fZproj /= (Float_t)nTracklets; + fSlope /= (Float_t)nTracklets; + + Float_t X[kNmaxTrk+1], Y[kNmaxTrk+1], Z[kNmaxTrk+1]; + Bool_t count[kNmaxTrk]; + for (Int_t i = 0; i < kNmaxTrk; i++) count[i] = kFALSE; + + Int_t iXmin = -1; + Int_t j = 0; + X[0] = Y[0] = Z[0] = 0.0; + while (j < nTracklets) { + iXmin = -1; + for (Int_t i = 0; i < nTracklets; i++) { + if (count[i]) continue; + if (iXmin == -1) { + iXmin = i; + continue; + } + if (fC[i][0] < fC[iXmin][0]) iXmin = i; + } + X[j+1] = fC[iXmin][0]; + Y[j+1] = fC[iXmin][1]; + Z[j+1] = fC[iXmin][2]; + j++; + count[iXmin] = kTRUE; + } + + TMatrixD smatrix(2,2); + TMatrixD sums(2,1); + TMatrixD res(2,1); + Double_t x, y; + Float_t A, B; + + smatrix.Zero(); + sums.Zero(); + for (Int_t i = 0; i < nTracklets; i++) { + x = (Double_t)X[i+1]; + y = (Double_t)Y[i+1]; + smatrix(0,0) += 1.0; + smatrix(1,1) += x*x; + smatrix(0,1) += x; + smatrix(1,0) += x; + sums(0,0) += y; + sums(1,0) += x*y; + } + res = smatrix.Invert() * sums; + A = res(0,0); + B = res(1,0); + + Float_t dist = AliTRDgeometry::GetTime0(1) - AliTRDgeometry::GetTime0(0); + + Float_t fX1 = X[1] + dist * (Float_t)(nTracklets-1)/6.0; + Float_t fY1 = A + B * fX1; + Float_t fX2 = X[nTracklets] - dist * (Float_t)(nTracklets-1)/6.0; + Float_t fY2 = A + B * fX2; + Float_t D12 = TMath::Sqrt((fX2-fX1)*(fX2-fX1)+(fY2-fY1)*(fY2-fY1)); + Float_t Alpha = TMath::ATan(fY2/fX2) - TMath::ATan(fY1/fX1); + Float_t R = (D12/2.0)/TMath::Sin(Alpha); + + fPt = 0.3 * field * 0.01 * R; + + Float_t D1 = fX1*fX1+fY1*fY1; + Float_t D2 = fX2*fX2+fY2*fY2; + Float_t D = fX1*fY2-fX2*fY1; + + Float_t Xc = (D1*fY2-D2*fY1)/(2*D); + Float_t Yc = (D2*fX1-D1*fX2)/(2*D); + + if (Yc != 0.0) { + fPhi = TMath::ATan(Xc/Yc); + } else { + fPhi = TMath::PiOver2(); + } + + fPhi *= 180.0/TMath::Pi(); + + smatrix.Zero(); + sums.Zero(); + for (Int_t i = 0; i < nTracklets+1; i++) { + x = (Double_t)Z[i]; + y = (Double_t)X[i]; + smatrix(0,0) += 1.0; + smatrix(1,1) += x*x; + smatrix(0,1) += x; + smatrix(1,0) += x; + sums(0,0) += y; + sums(1,0) += x*y; + } + res = smatrix.Invert() * sums; + A = res(0,0); + B = res(1,0); + Float_t theta = TMath::ATan(B); + + if (theta < 0.0) theta = TMath::Pi() + theta; + + if (theta == 0.0) { + fEta = 0.0; + } else { + fEta = -TMath::Log(TMath::Tan(theta/2.0)); + } + +} + +//_____________________________________________________________________________ +void AliTRDgtuTrack::MakePID() +{ + + // + // Electron likelihood signal + // + + AliTRDcalibDB* calibration = AliTRDcalibDB::Instance(); + if (!calibration) + { + Error("MakePID","No instance of AliTRDcalibDB."); + return; + } + const AliTRDCalPIDLQ *pd = calibration->GetPIDLQObject(); + + AliTRDltuTracklet *trk; + Int_t nTracklets = GetNtracklets(); + Int_t det, pla; + Float_t sl, th, q, probPio = 1.0, probEle = 1.0; + for (Int_t i = 0; i < nTracklets; i++) { + + trk = GetTracklet(i); + + sl = TMath::Abs(trk->GetSlope()); // tracklet inclination in X-y plane + th = trk->GetRowz()/trk->GetTime0(); // tracklet inclination in X-z plane + th = TMath::ATan(TMath::Abs(th)); + + q = trk->GetQ() + * TMath::Cos(sl/180.0*TMath::Pi()) + * TMath::Cos(th/180.0*TMath::Pi()); + + det = trk->GetDetector(); + pla = trk->GetPlane(det); + + // unclear yet factor to match the PS distributions = 5.8 + // not explained only by the tail filter ... + + // AliRoot v4-03-07 , v4-03-Release + //q = q * 5.8; + + // Temporary (B. Vulpescu): + // The charge distributions do not match the new changes in simulation (A. Bercuci), + // which are nevertheless now in agreement with the beam tests. + // Some tricks will be used to still have reasonable results + // To match the existing charge distributions, the charge per layer has to be modified + // as folows: + /* + if (k == 0) { + // electrons + q = 4.3 * q + 95.0; + } else { + // others + q = 4.2 * q + 70.0; + } + */ + // Since at tracking time we have no information on the particle type, we will modify + // instead the charge distributions accordingly. This will slow down the sampling. + // The modified distributions are in TRDdEdxHistogramsV1_BV.root and the CDB has + // been regenerated with AliTRDCreateDummyCDB.C + // The new PIDLQ data base has the version : + // I-AliCDBLocal::Get: CDB object retrieved: path "TRD/Calib/PIDLQ"; run range [0,0]; + // version v0_s1 + + probEle *= pd->GetProbability(0,TMath::Abs(fPt),q); + probPio *= pd->GetProbability(2,TMath::Abs(fPt),q); + + } + + if ((probEle+probPio) > 0.0) { + fPID = probEle/(probEle+probPio); + } else { + fPID = 0.0; + } + + // Thresholds for LQ cut at 90% electron efficiency (from AliRoot v4-03-07) + // P [GeV/c] fPIDcut (between 0 and 1) + // 2 0.925 + // 3 0.915 + // 4 0.875 + // 5 0.855 + // 6 0.845 + // 8 0.785 + // 10 0.735 + // + // PIDcut = 0.978 - 0.024 * P[GeV/c] + //Float_t PIDcut = 0.978 - 0.024 * TMath::Abs(fPt); + + // HEAD28Mar06 with modified distributions (A. Bercuci changes, P. Shukla distributions) + Float_t PIDcut = 0.829 - 0.032 * TMath::Abs(fPt); + + fIsElectron = kFALSE; + if (fPID >= PIDcut) { + fIsElectron = kTRUE; + } + +} + +//_____________________________________________________________________________ +void AliTRDgtuTrack::CookLabel() +{ + + // + // Cook the track label from tracklets labels + // + + AliTRDltuTracklet *trk; + + const Int_t kMaxTracks = 10; + Int_t trackLabel[kMaxTracks]; + Int_t trackCount[kMaxTracks]; + for (Int_t it = 0; it < kMaxTracks; it++) { + trackLabel[it] = -1; + trackCount[it] = 0; + } + + Bool_t counted; + Int_t label, nTracks = 0; + for (Int_t itrk = 0; itrk < fNtracklets; itrk++) { + + trk = GetTracklet(itrk); + + if (trk->GetLabel() == -1) continue; + + label = trk->GetLabel(); + + counted = kFALSE; + for (Int_t it = 0; it < nTracks; it++) { + if (label == trackLabel[it]) { + trackCount[it]++; + counted = kTRUE; + break; + } + } + if (!counted) { + trackLabel[nTracks] = label; + trackCount[nTracks]++; + nTracks++; + if (nTracks == kMaxTracks) { + Warning("CookLabel","Too many tracks for this tracklet."); + nTracks--; + break; + } + } + + } + + Float_t frac = 4.0/5.0; + for (Int_t it = 0; it < kMaxTracks; it++) { + if (trackCount[it] >= (Int_t)(frac*fNtracklets)) { + fLabel = trackLabel[it]; + break; + } + } + +} + +//_____________________________________________________________________________ +AliTRDmodule::AliTRDmodule(AliTRDtrigParam *trigp) +{ + + // + // AliTRDmodule default constructor + // + + fDeltaY = trigp->GetDeltaY(); + fDeltaS = trigp->GetDeltaS(); + fXprojPlane = trigp->GetXprojPlane(); + fField = trigp->GetField(); + fLTUtrk = 0; + fGTUtrk = 0; + fTracklets = new TObjArray(400); + fTracks = new TObjArray(400); + +} + +//_____________________________________________________________________________ +void AliTRDmodule::Reset() +{ + + ResetTracklets(); + ResetTracks(); + + fLTUtrk = 0; + fGTUtrk = 0; + fTracklets = new TObjArray(400); + fTracks = new TObjArray(400); + +} + +//_____________________________________________________________________________ +void AliTRDmodule::ResetTracks() +{ + + if (fTracks) { + + AliTRDgtuTrack *trk; + for (Int_t i = 0; i < GetNtracks(); i++) { + + trk = GetTrack(i); + trk->Reset(); + + } + + fTracks->Delete(); + + } + +} + +//_____________________________________________________________________________ +AliTRDgtuTrack* AliTRDmodule::GetTrack(Int_t pos) +{ + + if (fTracks == 0) return 0; + void * trk = fTracks->UncheckedAt(pos); + if (trk == 0) return 0; + + return (AliTRDgtuTrack*)trk; + +} + +//_____________________________________________________________________________ +void AliTRDmodule::RemoveTrack(Int_t pos) +{ + + if (fTracks == 0) return; + fTracks->RemoveAt(pos); + fTracks->Compress(); + +} + +//_____________________________________________________________________________ +void AliTRDmodule::AddTracklet(Int_t det, + Int_t row, + Float_t rowz, + Float_t slope, + Float_t offset, + Float_t time, + Int_t ncl, + Int_t label, + Float_t q) +{ + + fLTUtrk = new AliTRDltuTracklet(det,row,rowz,slope,offset,time,ncl,label,q); + + Tracklets()->Add(fLTUtrk); + +} + +//_____________________________________________________________________________ +AliTRDltuTracklet* AliTRDmodule::GetTracklet(Int_t pos) +{ + + if (fTracklets == 0) return 0; + void * trk = fTracklets->UncheckedAt(pos); + if (trk == 0) return 0; + + return (AliTRDltuTracklet*)trk; + +} + +//_____________________________________________________________________________ +void AliTRDmodule::RemoveTracklet(Int_t pos) +{ + + if (fTracklets == 0) return; + fTracklets->RemoveAt(pos); + fTracklets->Compress(); + +} + +//_____________________________________________________________________________ +void AliTRDmodule::RemoveMultipleTracklets() +{ + + Float_t OffDiffMin = 0.5; // [cm] + + AliTRDltuTracklet *trk; + Int_t Det1, Det2, Row1, Row2, Ncl1, Ncl2, Label1, Label2; + Float_t Off1, Off2; + Int_t itrk = 0; + while (itrk < (GetNtracklets()-1)) { + + trk = GetTracklet(itrk ); + + Det1 = trk->GetDetector(); + Row1 = trk->GetRow(); + Off1 = trk->GetOffset(); + Ncl1 = trk->GetNclusters(); + Label1 = trk->GetLabel(); + + trk = GetTracklet(itrk+1); + + Det2 = trk->GetDetector(); + Row2 = trk->GetRow(); + Off2 = trk->GetOffset(); + Ncl2 = trk->GetNclusters(); + Label2 = trk->GetLabel(); + + if (Det1 == Det2 && Row1 == Row2) { + if ((Off2-Off1) < OffDiffMin) { + if (Ncl1 < Ncl2) { + RemoveTracklet(itrk ); + } else { + RemoveTracklet(itrk+1); + } + } + } + + itrk++; + + } + +} + +//_____________________________________________________________________________ +void AliTRDmodule::SortZ(Int_t cha) +{ + + InitZLUT(); + + AliTRDltuTracklet *trk; + Int_t row, pla, det; + for (Int_t iTrk = 0; iTrk < GetNtracklets(); iTrk++) { + + trk = GetTracklet(iTrk); + + row = trk->GetRow(); + det = trk->GetDetector(); + pla = trk->GetPlane(det); + + for (Int_t iZchan = 0; iZchan < kNsubZchan; iZchan++) { + if (fZChannelMap[cha][iZchan][pla][row] == 1) { + fZtrkid[pla][fZnchan[pla][iZchan]][iZchan] = iTrk; + fZnchan[pla][iZchan]++; + } + } + + } + +} + +//_____________________________________________________________________________ +void AliTRDmodule::InitZLUT() +{ + + for (Int_t iPlan = 0; iPlan < AliTRDgeometry::Nplan(); iPlan++) { + for (Int_t i = 0; i < kNsubZchan; i++) { + fZnchan[iPlan][i] = 0; + for (Int_t j = 0; j < kNmaxZchan; j++) { + fZtrkid[iPlan][j][i] = -1; + } + } + } + +} + +//_____________________________________________________________________________ +void AliTRDmodule::FindTracks() +{ + + for (Int_t iZchan = 0; iZchan < kNsubZchan; iZchan++) { + FindTracksCombi(iZchan); + } + +} + +//_____________________________________________________________________________ +void AliTRDmodule::FindTracksCombi(Int_t zchan) +{ + + // + // find tracks by pure combinatorics... + // + + static Int_t TrkTrack[12]; + + Int_t nTracklets, nPlanes; + Int_t Ntrk1, TrkId1, Ntrk2, TrkId2; + Float_t Y1, Y1min, Y1max, S1, Z1, S1min, S1max, Y2, S2, Z2; + AliTRDltuTracklet *Trk1; + AliTRDltuTracklet *Trk2; + AliTRDltuTracklet *Trk ; + + Bool_t IsPlane[kNplan]; + + for (Int_t iPlan1 = 0; iPlan1 < kNplan; iPlan1++) { + + Ntrk1 = fZnchan[iPlan1][zchan]; + + for (Int_t iTrk1 = 0; iTrk1 < Ntrk1; iTrk1++) { + + for (Int_t iPlan = 0; iPlan < kNplan; iPlan++) IsPlane[iPlan] = kFALSE; + + TrkId1 = fZtrkid[iPlan1][iTrk1][zchan]; + + nTracklets = 0; + for (Int_t iList = 0; iList < kNmaxTrk; iList++) { + TrkTrack[iList] = -1; + } + + TrkTrack[nTracklets++] = TrkId1; + + IsPlane[iPlan1] = kTRUE; + + Trk1 = GetTracklet(TrkId1); + + Y1 = Trk1->GetYproj(fXprojPlane); + Y1min = Y1 - fDeltaY; + Y1max = Y1 + fDeltaY; + S1 = Trk1->GetSlope(); + S1min = S1 - fDeltaS; + S1max = S1 + fDeltaS; + Z1 = Trk1->GetZproj(fXprojPlane); + + for (Int_t iPlan2 = 0; iPlan2 < kNplan; iPlan2++) { + + if (iPlan2 == iPlan1) continue; + + Ntrk2 = fZnchan[iPlan2][zchan]; + + for (Int_t iTrk2 = 0; iTrk2 < Ntrk2; iTrk2++) { + + TrkId2 = fZtrkid[iPlan2][iTrk2][zchan]; + + if (TrkId2 == TrkId1) continue; + + Trk2 = GetTracklet(TrkId2); + + Y2 = Trk2->GetYproj(fXprojPlane); + S2 = Trk2->GetSlope(); + Z2 = Trk2->GetZproj(fXprojPlane); + + if ((Y1min < Y2 && Y2 < Y1max) && + (S1min < S2 && S2 < S1max)) { + + if (nTracklets >= kNmaxTrk) { + Warning("FindTracksCombi","Too many tracklets for this track."); + } else { + TrkTrack[nTracklets++] = TrkId2; + IsPlane[iPlan2] = kTRUE; + } + + } + + } // end trk 2 + + } // end plan 2 + + nPlanes = 0; + for (Int_t iPlan = 0; iPlan < kNplan; iPlan++) { + nPlanes += (Int_t)IsPlane[iPlan]; + } + + if (nPlanes >= 4) { + + Int_t Cha1, Cha2, Npoints1, Npoints2; + for (Int_t iList = 0; iList < (nTracklets-1); iList++) { + + if (TrkTrack[iList] == -1 || TrkTrack[iList+1] == -1) continue; + Trk1 = GetTracklet(TrkTrack[iList ]); + Trk2 = GetTracklet(TrkTrack[iList+1]); + + Cha1 = Trk1->GetDetector(); + Cha2 = Trk2->GetDetector(); + if (Cha1 != Cha2) continue; + + Npoints1 = Trk1->GetNclusters(); + Npoints2 = Trk2->GetNclusters(); + + if (Npoints1 == Npoints2) { + TrkTrack[iList] = -1; + } else { + if (Npoints1 > Npoints2) TrkTrack[iList+1] = -1; + if (Npoints1 < Npoints2) TrkTrack[iList ] = -1; + } + + } + + fGTUtrk = new AliTRDgtuTrack(); + for (Int_t iList = 0; iList < nTracklets; iList++) { + if (TrkTrack[iList] == -1) continue; + Trk = GetTracklet(TrkTrack[iList]); + fGTUtrk->AddTracklet(Trk); + } + fGTUtrk->Track(fXprojPlane,fField); + AddTrack(); + } + + } // end trk 1 + + } // end plan 1 + +} + +//_____________________________________________________________________________ +void AliTRDmodule::AddTrack() +{ + + Tracks()->Add(fGTUtrk); + +} + +//_____________________________________________________________________________ +void AliTRDmodule::RemoveMultipleTracks() +{ + + AliTRDgtuTrack *trk1; + AliTRDgtuTrack *trk2; + + Float_t Yproj1, Yproj2, Alpha1, Alpha2; + Int_t ntrk1, ntrk2; + Int_t iTrack = 0; + + while (iTrack < (GetNtracks()-1)) { + + trk1 = GetTrack(iTrack ); + trk2 = GetTrack(iTrack+1); + + ntrk1 = trk1->GetNtracklets(); + Yproj1 = trk1->GetYproj(); + Alpha1 = trk1->GetSlope(); + ntrk2 = trk2->GetNtracklets(); + Yproj2 = trk2->GetYproj(); + Alpha2 = trk2->GetSlope(); + + if (TMath::Abs(Yproj1-Yproj2) < fDeltaY && TMath::Abs(Alpha1-Alpha2) < fDeltaS) { + if (ntrk1 < ntrk2) { + RemoveTrack(iTrack ); + } else { + RemoveTrack(iTrack+1); + } + } else { + iTrack++; + } + + } + +} + +//_____________________________________________________________________________ +AliTRDtrigger::AliTRDtrigger(): + TNamed(), + fTracks("AliTRDgtuTrack",0) +{ + // + // AliTRDtrigger default constructor + // + + fDigitsManager = NULL; + fTrackletTree = NULL; + fTracklets = NULL; + + fNROB = 0; + fTrigParam = NULL; + fMCM = NULL; + fTrk = NULL; + fGTUtrk = NULL; + + fNtracklets = 0; + + fDigits = NULL; + fTrack0 = NULL; + fTrack1 = NULL; + fTrack2 = NULL; + + fModule = NULL; + + fNPrimary = 0; + +} + +//_____________________________________________________________________________ +AliTRDtrigger::AliTRDtrigger(const Text_t *name, const Text_t *title): + TNamed(name,title), + fTracks("AliTRDgtuTrack",1000) +{ + // + // AliTRDtrigger constructor + // + + fDigitsManager = new AliTRDdigitsManager(); + fTrackletTree = NULL; + fTracklets = new TObjArray(400); + + fNROB = 0; + fTrigParam = NULL; + fMCM = NULL; + fTrk = NULL; + fGTUtrk = NULL; + + fNtracklets = 0; + + fDigits = NULL; + fTrack0 = NULL; + fTrack1 = NULL; + fTrack2 = NULL; + + fModule = NULL; + + fNPrimary = 0; + +} + +//_____________________________________________________________________________ +AliTRDtrigger::AliTRDtrigger(const AliTRDtrigger &p):TNamed(p) +{ + // + // AliTRDtrigger copy constructor + // + + ((AliTRDtrigger &) p).Copy(*this); + +} + +///_____________________________________________________________________________ +AliTRDtrigger::~AliTRDtrigger() +{ + // + // AliTRDtrigger destructor + // + + if (fTracklets) { + fTracklets->Delete(); + delete fTracklets; + } + + fTracks.Delete(); + +} + +//_____________________________________________________________________________ +AliTRDtrigger &AliTRDtrigger::operator=(const AliTRDtrigger &p) +{ + // + // Assignment operator + // + + if (this != &p) ((AliTRDtrigger &) p).Copy(*this); + return *this; + +} + +//_____________________________________________________________________________ +void AliTRDtrigger::Copy(TObject &) const +{ + // + // Copy function + // + + AliFatal("Not implemented"); + +} + +//_____________________________________________________________________________ +void AliTRDtrigger::Init() +{ + + fModule = new AliTRDmodule(fTrigParam); + /* + AliHeader *header = fRunLoader->GetHeader(); + fNPrimary = header->GetNprimary(); + */ + fTracks.Clear(); + +} + +//_____________________________________________________________________________ +Bool_t AliTRDtrigger::Open(const Char_t *name, Int_t nEvent) +{ + // + // Opens the AliROOT file. + // + + TString evfoldname = AliConfig::GetDefaultEventFolderName(); + fRunLoader = AliRunLoader::GetRunLoader(evfoldname); + + if (!fRunLoader) + fRunLoader = AliRunLoader::Open(name); + + if (!fRunLoader) { + Error("Open","Can not open session for file %s.",name); + return kFALSE; + } + + // Open input + + if (fRunLoader->GetAliRun() == 0x0) fRunLoader->LoadgAlice(); + gAlice = fRunLoader->GetAliRun(); + + if (!(gAlice)) { + fRunLoader->LoadgAlice(); + gAlice = fRunLoader->GetAliRun(); + if (!(gAlice)) { + Error("Open","Could not find AliRun object."); + return kFALSE; + } + } + + // Import the Trees for the event nEvent in the file + fRunLoader->GetEvent(nEvent); + + // Open output + + TObjArray *ioArray = 0; + + AliLoader* loader = fRunLoader->GetLoader("TRDLoader"); + loader->MakeTree("T"); + fTrackletTree = loader->TreeT(); + fTrackletTree->Branch("TRDmcmTracklet","TObjArray",&ioArray,32000,0); + + fRunLoader->LoadHeader(); + + Init(); + + return kTRUE; + +} + + +//_____________________________________________________________________________ +Bool_t AliTRDtrigger::ReadDigits() +{ + // + // Reads the digits arrays from the input aliroot file + // + + if (!fRunLoader) { + Error("ReadDigits","Can not find the Run Loader"); + return kFALSE; + } + + AliLoader* loader = fRunLoader->GetLoader("TRDLoader"); + if (!loader->TreeD()) loader->LoadDigits(); + + return (fDigitsManager->ReadDigits(loader->TreeD())); + +} + +//_____________________________________________________________________________ +Bool_t AliTRDtrigger::ReadDigits(AliRawReader* rawReader) +{ + // + // Reads the digits arrays from the ddl file + // + + AliTRDrawData *raw = new AliTRDrawData(); + raw->SetDebug(1); + + fDigitsManager = raw->Raw2Digits(rawReader); + + return kTRUE; + +} + +//_____________________________________________________________________________ +Bool_t AliTRDtrigger::ReadTracklets(AliRunLoader *rl) +{ + // + // Reads the tracklets find the tracks + // + + Int_t idet; + + AliLoader *loader = rl->GetLoader("TRDLoader"); + loader->LoadTracks(); + fTrackletTree = loader->TreeT(); + + TBranch *branch = fTrackletTree->GetBranch("TRDmcmTracklet"); + if (!branch) { + Error("ReadTracklets","Can't get the branch !"); + return kFALSE; + } + TObjArray *tracklets = new TObjArray(400); + branch->SetAddress(&tracklets); + + Int_t nEntries = (Int_t) fTrackletTree->GetEntries(); + Int_t iEntry, itrk; + Int_t iStack, iStackPrev = -1; + + for (iEntry = 0; iEntry < nEntries; iEntry++) { + fTrackletTree->GetEvent(iEntry); + + for (itrk = 0; itrk < tracklets->GetEntriesFast(); itrk++){ + + fTrk = (AliTRDmcmTracklet*)tracklets->UncheckedAt(itrk); + + idet = fTrk->GetDetector(); + + iStack = idet / (AliTRDgeometry::Nplan()); + if (iStackPrev != iStack) { + if (iStackPrev == -1) { + iStackPrev = iStack; + } else { + MakeTracks(idet-AliTRDgeometry::Nplan()); + ResetTracklets(); + iStackPrev = iStack; + } + } + + Tracklets()->Add(fTrk); + + if (iEntry == (nEntries-1) && itrk == (tracklets->GetEntriesFast()-1)) { + idet++; + MakeTracks(idet-AliTRDgeometry::Nplan()); + ResetTracklets(); + } + + } + + } + + loader->UnloadTracks(); + + return kTRUE; + +} + +//_____________________________________________________________________________ +Bool_t AliTRDtrigger::MakeTracklets() +{ + + AliTRDcalibDB* calibration = AliTRDcalibDB::Instance(); + if (!calibration) + { + Error("MakeTracklets","No instance of AliTRDcalibDB."); + return kFALSE; + } + + AliTRDCommonParam* commonParam = AliTRDCommonParam::Instance(); + if (!commonParam) + { + Error("MakeTracklets","No common params."); + return kFALSE; + } + + AliTRDgeometry *geo = AliTRDgeometry::GetGeometry(fRunLoader); + + Int_t chamBeg = 0; + Int_t chamEnd = AliTRDgeometry::Ncham(); + Int_t planBeg = 0; + Int_t planEnd = AliTRDgeometry::Nplan(); + Int_t sectBeg = 0; + Int_t sectEnd = AliTRDgeometry::Nsect(); + + fMCM = new AliTRDmcm(fTrigParam,0); + + Int_t time, col, row, col1, col2; + Float_t amp; + Int_t idet, iStack, iStackPrev; + iStack = -1; + iStackPrev = -1; + for (Int_t isect = sectBeg; isect < sectEnd; isect++) { + + for (Int_t icham = chamBeg; icham < chamEnd; icham++) { + + // number of ROBs in the chamber + if( icham == 2 ) { + fNROB = 6; + } else { + fNROB = 8; + } + + for (Int_t iplan = planBeg; iplan < planEnd; iplan++) { + + idet = geo->GetDetector(iplan,icham,isect); + ResetTracklets(); + /* + iStack = idet / (AliTRDgeometry::Nplan()); + if (iStackPrev != iStack) { + if (iStackPrev == -1) { + iStackPrev = iStack; + } else { + MakeTracks(idet-AliTRDgeometry::Nplan()); + ResetTracklets(); + iStackPrev = iStack; + } + } + */ + Int_t nRowMax = commonParam->GetRowMax(iplan,icham,isect); + Int_t nColMax = commonParam->GetColMax(iplan); + Int_t nTimeTotal = calibration->GetNumberOfTimeBins(); + + // Get the digits + fDigits = fDigitsManager->GetDigits(idet); + fDigits->Expand(); + fTrack0 = fDigitsManager->GetDictionary(idet,0); + fTrack0->Expand(); + fTrack1 = fDigitsManager->GetDictionary(idet,1); + fTrack1->Expand(); + fTrack2 = fDigitsManager->GetDictionary(idet,2); + fTrack2->Expand(); + + + for (Int_t iRob = 0; iRob < fNROB; iRob++) { + + for (Int_t iMcm = 0; iMcm < kNMCM; iMcm++) { + + fMCM->Reset(); + + fMCM->SetRobId(iRob); + fMCM->SetChaId(idet); + + SetMCMcoordinates(iMcm); + + row = fMCM->GetRow(); + + if (row < 0 || row > nRowMax) { + Error("MakeTracklets","MCM row number out of range."); + } + + fMCM->GetColRange(col1,col2); + + for (time = 0; time < nTimeTotal; time++) { + for (col = col1; col < col2; col++) { + if (col >= 0 && col < nColMax) { + amp = TMath::Abs(fDigits->GetDataUnchecked(row,col,time)); + } else { + amp = 0.0; + } + fMCM->SetADC(col-col1,time,amp); + + } + } + + if (fTrigParam->GetTailCancelation()) { + fMCM->Filter(fTrigParam->GetNexponential(),fTrigParam->GetFilterType()); + } + + if (fMCM->Run()) { + + for (Int_t iSeed = 0; iSeed < kMaxTrackletsPerMCM; iSeed++) { + + if (fMCM->GetSeedCol()[iSeed] < 0) continue; + + if ( fTrigParam->GetDebugLevel() > 1 ) + printf("Add tracklet %d in col %02d \n",fNtracklets,fMCM->GetSeedCol()[iSeed]); + + if ( fTrigParam->GetDebugLevel() == -1 ) { + printf("Add tracklet %d in col %02d \n",fNtracklets,fMCM->GetSeedCol()[iSeed]); + for (time = 0; time < nTimeTotal; time++) { + for (col = 0; col < kMcmCol; col++) { + printf("%03.0f ",fMCM->GetADC(col,time)); + } + printf("\n"); + } + } + + AddTracklet(idet,row,iSeed,fNtracklets++); + + } + + } + + } + + + } + + // Compress the arrays + fDigits->Compress(1,0); + fTrack0->Compress(1,0); + fTrack1->Compress(1,0); + fTrack2->Compress(1,0); + + WriteTracklets(idet); + + } + } + } + /* + idet++; + MakeTracks(idet-AliTRDgeometry::Nplan()); + ResetTracklets(); + */ + return kTRUE; + +} + +//_____________________________________________________________________________ +void AliTRDtrigger::SetMCMcoordinates(Int_t imcm) +{ + + Int_t robid = fMCM->GetRobId(); + + // setting the Row and Col range + + const Int_t kNcolRob = 2; // number of ROBs per chamber in column direction + const Int_t kNmcmRob = 4; // number of MCMs per ROB in column/row direction + + Int_t mcmid = imcm%(kNmcmRob*kNmcmRob); + + if (robid%kNcolRob == 0) { + + if ( mcmid%kNmcmRob == 0 ) { + fMCM->SetColRange(18*0-1,18*1-1+2+1); + } + if ( mcmid%kNmcmRob == 1 ) { + fMCM->SetColRange(18*1-1,18*2-1+2+1); + } + if ( mcmid%kNmcmRob == 2 ) { + fMCM->SetColRange(18*2-1,18*3-1+2+1); + } + if ( mcmid%kNmcmRob == 3 ) { + fMCM->SetColRange(18*3-1,18*4-1+2+1); + } + + } else { + + if ( mcmid%kNmcmRob == 0 ) { + fMCM->SetColRange(18*4-1,18*5-1+2+1); + } + if ( mcmid%kNmcmRob == 1 ) { + fMCM->SetColRange(18*5-1,18*6-1+2+1); + } + if ( mcmid%kNmcmRob == 2 ) { + fMCM->SetColRange(18*6-1,18*7-1+2+1); + } + if ( mcmid%kNmcmRob == 3 ) { + fMCM->SetColRange(18*7-1,18*8-1+2+1); + } + + } + + fMCM->SetRow(kNmcmRob*(robid/kNcolRob)+mcmid/kNmcmRob); + +} + +//_____________________________________________________________________________ +void AliTRDtrigger::AddTracklet(Int_t det, Int_t row, Int_t seed, Int_t n) +{ + + Float_t field = fTrigParam->GetField(); + AliTRDgeometry *geo = (AliTRDgeometry*)AliTRDgeometry::GetGeometry(fRunLoader); + + AliTRDcalibDB* calibration = AliTRDcalibDB::Instance(); + if (!calibration) + { + Error("AddTracklets","No instance of AliTRDcalibDB."); + return; + } + + Int_t nTimeTotal = calibration->GetNumberOfTimeBins(); + + fTrk = new AliTRDmcmTracklet(det,row,n); + + Int_t iCol, iCol1, iCol2, track[3]; + iCol = fMCM->GetSeedCol()[seed]; // 0....20 (MCM) + fMCM->GetColRange(iCol1,iCol2); // range in the pad plane + + Float_t Amp[3]; + for (Int_t iTime = 0; iTime < nTimeTotal; iTime++) { + + Amp[0] = fMCM->GetADC(iCol-1,iTime); + Amp[1] = fMCM->GetADC(iCol ,iTime); + Amp[2] = fMCM->GetADC(iCol+1,iTime); + + // extract track contribution only from the central pad + track[0] = fTrack0->GetDataUnchecked(row,iCol+iCol1,iTime); + track[1] = fTrack1->GetDataUnchecked(row,iCol+iCol1,iTime); + track[2] = fTrack2->GetDataUnchecked(row,iCol+iCol1,iTime); + + if (fMCM->IsCluster(iCol,iTime)) { + + fTrk->AddCluster(iCol+iCol1,iTime,Amp,track); + + } else if ((iCol+1+1) < kMcmCol) { + + Amp[0] = fMCM->GetADC(iCol-1+1,iTime); + Amp[1] = fMCM->GetADC(iCol +1,iTime); + Amp[2] = fMCM->GetADC(iCol+1+1,iTime); + + if (fMCM->IsCluster(iCol+1,iTime)) { + + // extract track contribution only from the central pad + track[0] = fTrack0->GetDataUnchecked(row,iCol+1+iCol1,iTime); + track[1] = fTrack1->GetDataUnchecked(row,iCol+1+iCol1,iTime); + track[2] = fTrack2->GetDataUnchecked(row,iCol+1+iCol1,iTime); + + fTrk->AddCluster(iCol+1+iCol1,iTime,Amp,track); + + } + + } else { + } + + } + + fTrk->CookLabel(0.8); + /* + if (fTrk->GetLabel() >= fNPrimary) { + Info("AddTracklet","Only primaries are stored!"); + return; + } + */ + // LTU Pt cut + fTrk->MakeTrackletGraph(geo,field); + fTrk->MakeClusAmpGraph(); + if (TMath::Abs(fTrk->GetPt()) < fTrigParam->GetLtuPtCut()) return; + + Tracklets()->Add(fTrk); + +} + +//_____________________________________________________________________________ +Bool_t AliTRDtrigger::WriteTracklets(Int_t det) +{ + // + // Fills TRDmcmTracklet branch in the tree with the Tracklets + // found in detector = det. For det=-1 writes the tree. + // + + if ((det < -1) || (det >= AliTRDgeometry::Ndet())) { + Error("WriteTracklets","Unexpected detector index %d.",det); + return kFALSE; + } + + TBranch *branch = fTrackletTree->GetBranch("TRDmcmTracklet"); + if (!branch) { + TObjArray *ioArray = 0; + branch = fTrackletTree->Branch("TRDmcmTracklet","TObjArray",&ioArray,32000,0); + } + + if ((det >= 0) && (det < AliTRDgeometry::Ndet())) { + + Int_t nTracklets = Tracklets()->GetEntriesFast(); + TObjArray *detTracklets = new TObjArray(400); + + for (Int_t i = 0; i < nTracklets; i++) { + AliTRDmcmTracklet *trk = (AliTRDmcmTracklet *) Tracklets()->UncheckedAt(i); + + if (det == trk->GetDetector()) { + detTracklets->AddLast(trk); + } + else { + } + } + + branch->SetAddress(&detTracklets); + fTrackletTree->Fill(); + + delete detTracklets; + + return kTRUE; + + } + + if (det == -1) { + + Info("WriteTracklets","Writing the Tracklet tree %s for event %d." + ,fTrackletTree->GetName(),fRunLoader->GetEventNumber()); + + AliLoader* loader = fRunLoader->GetLoader("TRDLoader"); + loader->WriteTracks("OVERWRITE"); + + return kTRUE; + + } + + return kFALSE; + +} + +//_____________________________________________________________________________ +void AliTRDtrigger::MakeTracks(Int_t det) +{ + // + // Create GTU tracks per module (stack of 6 chambers) + // + + fModule->Reset(); + + AliTRDCommonParam* commonParam = AliTRDCommonParam::Instance(); + if (!commonParam) + { + Error("MakeTracks","No common params."); + return; + } + + Int_t nRowMax, iplan, icham, isect, row; + + AliTRDgeometry *geo = (AliTRDgeometry*)AliTRDgeometry::GetGeometry(fRunLoader); + + if ((det < 0) || (det >= AliTRDgeometry::Ndet())) { + Error("MakeTracks","Unexpected detector index %d.",det); + return; + } + + Int_t nTracklets = Tracklets()->GetEntriesFast(); + + AliTRDmcmTracklet *trk; + for (Int_t i = 0; i < nTracklets; i++) { + + trk = (AliTRDmcmTracklet *) Tracklets()->UncheckedAt(i); + + iplan = geo->GetPlane(trk->GetDetector()); + icham = geo->GetChamber(trk->GetDetector()); + isect = geo->GetSector(trk->GetDetector()); + + nRowMax = commonParam->GetRowMax(iplan,icham,isect); + row = trk->GetRow(); + + fModule->AddTracklet(trk->GetDetector(), + row, + trk->GetRowz(), + trk->GetSlope(), + trk->GetOffset(), + trk->GetTime0(), + trk->GetNclusters(), + trk->GetLabel(), + trk->GetdQdl()); + + } + + fModule->SortTracklets(); + fModule->RemoveMultipleTracklets(); + fModule->SortZ((Int_t)geo->GetChamber(det)); + fModule->FindTracks(); + fModule->SortTracks(); + fModule->RemoveMultipleTracks(); + + Int_t nModTracks = fModule->GetNtracks(); + AliTRDgtuTrack *gtutrk; + for (Int_t i = 0; i < nModTracks; i++) { + gtutrk = (AliTRDgtuTrack*)fModule->GetTrack(i); + if (TMath::Abs(gtutrk->GetPt()) < fTrigParam->GetGtuPtCut()) continue; + gtutrk->CookLabel(); + gtutrk->MakePID(); + AddTrack(gtutrk,det); + } + +} + + diff --git a/TRD/AliTRDtrigger.h b/TRD/AliTRDtrigger.h new file mode 100644 index 00000000000..672dd4b9012 --- /dev/null +++ b/TRD/AliTRDtrigger.h @@ -0,0 +1,311 @@ +#ifndef ALITRDTRIGGER_H +#define ALITRDTRIGGER_H +/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. * + * See cxx source for full Copyright notice */ + +/////////////////////////////////////////////////////////////////////////////// +// // +// TRD trigger class // +// // +/////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include + +#include "AliTRDzmaps.h" +#include "AliRunLoader.h" +#include "AliLoader.h" + +const Int_t kNplan = 6; +const Int_t kNmaxZchan = 100; // max number of tracklets per subchannel +const Int_t kNsubZchan = 16; // total number of subchannels +const Int_t kNmaxTrk = 12; // max number of tracklets in one track (6*2) + +class AliTRDltuTracklet : public TObject { + + public: + + AliTRDltuTracklet(Int_t det, + Int_t row, + Float_t rowz, + Float_t slope, + Float_t offset, + Float_t time, + Int_t ncl, + Int_t label, + Float_t q); + ~AliTRDltuTracklet(){}; + + Bool_t IsSortable() const { return kTRUE; } + virtual Int_t Compare(const TObject *o) const; + Int_t GetDetector() { return fDetector; }; + Int_t GetPlane(Int_t det) { return ((Int_t) (det % kNplan)); }; + Int_t GetRow() { return fRow; }; + Int_t GetNclusters(){ return fNclusters; }; + Float_t GetSlope() { return fSlope; }; + Float_t GetOffset() { return fY; }; + Float_t GetTime0() { return fX; }; + Float_t GetRowz() { return fRowz; }; + virtual Float_t GetYproj(Float_t xpl); + virtual Float_t GetZproj(Float_t xpl); + Int_t GetLabel() { return fLabel; }; + Float_t GetPt(Float_t field); + Float_t GetQ() { return fQ; }; + + protected: + + Float_t fX; // distance vertex to entrance window + Float_t fY; // tracklet offset at entrance window + Float_t fSlope; + Float_t fRowz; + Int_t fDetector; + Int_t fRow; + Int_t fNclusters; + Int_t fLabel; + Float_t fQ; // charge sum divided by number of clusters + + ClassDef(AliTRDltuTracklet,1) + +}; + +class AliTRDltuTracklet; + +class AliTRDgtuTrack : public TObject { + + public: + + AliTRDgtuTrack(); + AliTRDgtuTrack(const AliTRDgtuTrack& track); + ~AliTRDgtuTrack(){}; + + Bool_t IsSortable() const { return kTRUE; } + virtual Int_t Compare(const TObject *o) const; + + virtual void Reset(); + void ResetTracklets() { if(fTracklets) fTracklets->Delete(); }; + virtual void AddTracklet(AliTRDltuTracklet *trk); + virtual AliTRDltuTracklet *GetTracklet(Int_t pos); + TObjArray *Tracklets() { + if(!fTracklets) fTracklets = new TObjArray(400); return fTracklets; + }; + Int_t GetNtracklets() { + if (fTracklets) return fTracklets->GetEntriesFast(); + return 0; + }; + Float_t GetYproj() { return fYproj; }; + Float_t GetZproj() { return fZproj; }; + Float_t GetSlope() { return fSlope; }; + Int_t GetTracklets() { return fNtracklets; }; + Int_t GetPlanes() { return fNplanes; }; + Int_t GetClusters() { return fNclusters; }; + Float_t GetPt() { return fPt; }; + Float_t GetPhi() { return fPhi; }; + Float_t GetEta() { return fEta; }; + Int_t GetLabel() { return fLabel; }; + + virtual void Track(Float_t xpl, Float_t field); + + virtual void CookLabel(); + + void SetDetector(Int_t det) { fDetector = det; }; + Int_t GetDetector() { return fDetector; }; + + virtual void MakePID(); + Float_t GetPID() { return fPID; }; + + Bool_t IsElectron() { return fIsElectron; }; + + protected: + + TObjArray *fTracklets; //! Array of LTU tracklets + + Float_t fYproj; // Average values calculated + Float_t fZproj; // from the tracklets + Float_t fSlope; + + Int_t fDetector; // First detector in the module + + Int_t fNtracklets; // Number of tracklets + Int_t fNplanes; // Number of TRD planes + Int_t fNclusters; // Total number of clusters + + Float_t fPt; // Transverse momentum + Float_t fPhi; // Phi angle at the vertex + Float_t fEta; // Eta at the vertex + Int_t fLabel; // Track label + Float_t fPID; // PID electron likelihood + Bool_t fIsElectron; // Electron flag + + ClassDef(AliTRDgtuTrack,1) + +}; + +class AliTRDgtuTrack; +class AliTRDtrigParam; + +class AliTRDmodule : public TObject { + + public: + + AliTRDmodule(AliTRDtrigParam *trigp); + + virtual void Reset(); + + virtual void AddTracklet(Int_t det, + Int_t row, + Float_t rowz, + Float_t slope, + Float_t offset, + Float_t time, + Int_t ncl, + Int_t label, + Float_t q); + + TObjArray *Tracklets() { + if(!fTracklets) fTracklets = new TObjArray(400); return fTracklets; + }; + + void ResetTracklets() { if(fTracklets) fTracklets->Delete(); }; + void SortTracklets() { if(fTracklets) fTracklets->Sort(); }; + virtual AliTRDltuTracklet *GetTracklet(Int_t pos); + virtual void RemoveMultipleTracklets(); + virtual void RemoveTracklet(Int_t pos); + Int_t GetNtracklets() { + if (fTracklets) return fTracklets->GetEntriesFast(); + return 0; + }; + + virtual void AddTrack(); + + TObjArray *Tracks() { + if(!fTracks) fTracks = new TObjArray(400); return fTracks; + }; + + virtual void ResetTracks(); + void SortTracks() { if(fTracks) fTracks->Sort(); }; + virtual AliTRDgtuTrack *GetTrack(Int_t pos); + virtual void RemoveMultipleTracks(); + virtual void RemoveTrack(Int_t pos); + Int_t GetNtracks() { + if (fTracks) return fTracks->GetEntriesFast(); + return 0; + }; + + virtual void SortZ(Int_t cha); + virtual void InitZLUT(); + virtual void FindTracks(); + virtual void FindTracksCombi(Int_t zchan); + + protected: + + Float_t fXprojPlane; //! X (time) coordinate of the + // projection plane + Float_t fField; //! Magnetic field + TObjArray *fTracklets; //! Array of LTU tracklets + TObjArray *fTracks; //! Array of GTU tracks + + Int_t fZnchan[kNplan][kNsubZchan]; //! number of LTU tracklets in each + // subchannel + Int_t fZtrkid[kNplan][kNmaxZchan][kNsubZchan]; //! list of LTU tracklet id's for + // each subchannel + + Float_t fDeltaY; // Y (offset) matching window in the GTU + Float_t fDeltaS; // Slope matching window in the GTU + + AliTRDltuTracklet *fLTUtrk; //! Current LTU tracklet + AliTRDgtuTrack *fGTUtrk; //! Current GTU track + + ClassDef(AliTRDmodule,1) + +}; + +class AliTRDdigitsManager; +class AliTRDdataArrayI; + +class AliRunLoader; +class AliRawReader; + +class AliTRDmcmTracklet; +class AliTRDmcm; +class AliTRDmodule; + +class TTree; + +class AliTRDtrigger : public TNamed { + + public: + + enum { kNMCM = 16 }; + + AliTRDtrigger(); + AliTRDtrigger(const Text_t* name, const Text_t* title); + AliTRDtrigger(const AliTRDtrigger &p); + virtual ~AliTRDtrigger(); + + AliTRDtrigger &operator=(const AliTRDtrigger &p); + virtual void Copy(TObject &p) const; + + virtual void Init(); + + void SetRunLoader(AliRunLoader *rl) { fRunLoader = rl; }; + virtual Bool_t Open(const Char_t *name, Int_t nEvent = 0); + virtual Bool_t ReadDigits(); + virtual Bool_t ReadDigits(AliRawReader* rawReader); + virtual Bool_t MakeTracklets(); + virtual Bool_t WriteTracklets(Int_t det); + virtual Bool_t ReadTracklets(AliRunLoader *rl); + + virtual void AddTracklet(Int_t det, Int_t row, Int_t seed, Int_t n); + TObjArray *Tracklets() { + if(!fTracklets) fTracklets = new TObjArray(400); return fTracklets; + }; + void ResetTracklets() { if(fTracklets) fTracklets->Delete(); }; + virtual void SetMCMcoordinates(Int_t imcm); + virtual void SetParameter(AliTRDtrigParam *trigp) { fTrigParam = trigp; }; + AliTRDtrigParam *GetParameter() { return fTrigParam; }; + + virtual void MakeTracks(Int_t det); + + AliTRDgtuTrack *GetTrack(Int_t i) const { + return (AliTRDgtuTrack *)fTracks.UncheckedAt(i); + } + void AddTrack(const AliTRDgtuTrack *t, Int_t det) { + AliTRDgtuTrack * track = new(fTracks[fTracks.GetEntriesFast()]) AliTRDgtuTrack(*t); + track->SetDetector(det); + } + Int_t GetNumberOfTracks() const {return fTracks.GetEntriesFast();} + + Int_t GetNPrimary() { return fNPrimary; }; + + protected: + + AliTRDtrigParam *fTrigParam; //! Trigger class parameters + AliRunLoader *fRunLoader; //! Run Loader + AliTRDdigitsManager *fDigitsManager; //! TRD digits manager + TTree *fTrackletTree; //! Tree with tracklets + TObjArray *fTracklets; //! Array of tracklets + + Int_t fNROB; //! Number of ROBs in the current chamber + AliTRDmcm *fMCM; //! Current MCM + AliTRDmcmTracklet *fTrk; //! Current tracklet + AliTRDmodule *fModule; //! Current module + AliTRDgtuTrack *fGTUtrk; //! Current GTU track + + Int_t fNtracklets; //! Tracklets counter + + AliTRDdataArrayI *fDigits; //! Array with digits + AliTRDdataArrayI *fTrack0; //! Track dictionary 0 + AliTRDdataArrayI *fTrack1; //! Track dictionary 1 + AliTRDdataArrayI *fTrack2; //! Track dictionary 2 + + Int_t fNPrimary; //! Number of primary tracks + + TClonesArray fTracks; //! Array of GTU tracks + + ClassDef(AliTRDtrigger,1) // TRD trigger class + +}; + +#endif diff --git a/TRD/AliTRDzmaps.h b/TRD/AliTRDzmaps.h new file mode 100644 index 00000000000..03b1f8d75bd --- /dev/null +++ b/TRD/AliTRDzmaps.h @@ -0,0 +1,1146 @@ +#ifndef ALITRDZMAPS_H +#define ALITRDZMAPS_H + +/////////////////////////////////////////////////////// +// Z maps for Z-sorting channels // +/////////////////////////////////////////////////////// + +/* This file has been generated by zChannelGen.cxx */ + +/* Access as: ZChannelMap[chamber][channel][plane][row] */ + +const Int_t fZChannelMap[5][16][6][16] = { + +{ /* --- Chamber 0 --- */ + +/* x . . . . . . . . . . . . . . . */ +/* x . . . . . . . . . . . . . . . */ +/* X . . . . . . . . . . . . . . . */ +/* x x . . . . . . . . . . . . . . */ +/* x . . . . . . . . . . . . . . . */ +/* . . . . . . . . . . . . . . . . */ + +{{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, + +/* x x . . . . . . . . . . . . . . */ +/* x x . . . . . . . . . . . . . . */ +/* . X . . . . . . . . . . . . . . */ +/* . x x . . . . . . . . . . . . . */ +/* x x . . . . . . . . . . . . . . */ +/* x . . . . . . . . . . . . . . . */ + +{{1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, + +/* . x x . . . . . . . . . . . . . */ +/* . x x . . . . . . . . . . . . . */ +/* . . X . . . . . . . . . . . . . */ +/* . . x x . . . . . . . . . . . . */ +/* . x x . . . . . . . . . . . . . */ +/* x x . . . . . . . . . . . . . . */ + +{{0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, + +/* . . x x . . . . . . . . . . . . */ +/* . . x x . . . . . . . . . . . . */ +/* . . . X . . . . . . . . . . . . */ +/* . . . x x . . . . . . . . . . . */ +/* . . x x . . . . . . . . . . . . */ +/* x x x . . . . . . . . . . . . . */ + +{{0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, + +/* . . . x x x . . . . . . . . . . */ +/* . . . x x x . . . . . . . . . . */ +/* . . . . X . . . . . . . . . . . */ +/* . . . . x x . . . . . . . . . . */ +/* . . . x x . . . . . . . . . . . */ +/* . x x x . . . . . . . . . . . . */ + +{{0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, + +/* . . . . x x x . . . . . . . . . */ +/* . . . . x x x . . . . . . . . . */ +/* . . . . . X . . . . . . . . . . */ +/* . . . . x x x . . . . . . . . . */ +/* . . . . x x . . . . . . . . . . */ +/* . . x x x . . . . . . . . . . . */ + +{{0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, + +/* . . . . . x x x . . . . . . . . */ +/* . . . . . x x x . . . . . . . . */ +/* . . . . . . X . . . . . . . . . */ +/* . . . . . x x x . . . . . . . . */ +/* . . . . . x x . . . . . . . . . */ +/* . . . x x x . . . . . . . . . . */ + +{{0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, + +/* . . . . . . x x x . . . . . . . */ +/* . . . . . . x x x . . . . . . . */ +/* . . . . . . . X . . . . . . . . */ +/* . . . . . . x x x . . . . . . . */ +/* . . . . . . x x . . . . . . . . */ +/* . . . . x x x . . . . . . . . . */ + +{{0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, + +/* . . . . . . . x x x . . . . . . */ +/* . . . . . . . x x x . . . . . . */ +/* . . . . . . . . X . . . . . . . */ +/* . . . . . . . x x x . . . . . . */ +/* . . . . . . . x x . . . . . . . */ +/* . . . . . x x x . . . . . . . . */ + +{{0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0}}, + +/* . . . . . . . . x x x . . . . . */ +/* . . . . . . . . x x x . . . . . */ +/* . . . . . . . . . X . . . . . . */ +/* . . . . . . . . x x x . . . . . */ +/* . . . . . . . . x x . . . . . . */ +/* . . . . . . x x x . . . . . . . */ + +{{0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0}}, + +/* . . . . . . . . . x x x . . . . */ +/* . . . . . . . . . x x x . . . . */ +/* . . . . . . . . . . X . . . . . */ +/* . . . . . . . . . x x x . . . . */ +/* . . . . . . . . . x x . . . . . */ +/* . . . . . . . x x x . . . . . . */ + +{{0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0}}, + +/* . . . . . . . . . . x x x . . . */ +/* . . . . . . . . . . x x x . . . */ +/* . . . . . . . . . . . X . . . . */ +/* . . . . . . . . . . x x x . . . */ +/* . . . . . . . . . . x x . . . . */ +/* . . . . . . . . . x x . . . . . */ + +{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0}}, + +/* . . . . . . . . . . . x x x . . */ +/* . . . . . . . . . . . x x x . . */ +/* . . . . . . . . . . . . X . . . */ +/* . . . . . . . . . . . x x x . . */ +/* . . . . . . . . . . . x x . . . */ +/* . . . . . . . . . . x x . . . . */ + +{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0}}, + +/* . . . . . . . . . . . . x x x . */ +/* . . . . . . . . . . . . x x x . */ +/* . . . . . . . . . . . . . X . . */ +/* . . . . . . . . . . . . x x x . */ +/* . . . . . . . . . . . . x x . . */ +/* . . . . . . . . . . . x x . . . */ + +{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0}}, + +/* . . . . . . . . . . . . . x x x */ +/* . . . . . . . . . . . . . x x x */ +/* . . . . . . . . . . . . . . X . */ +/* . . . . . . . . . . . . . x x x */ +/* . . . . . . . . . . . . . x x . */ +/* . . . . . . . . . . . . x x . . */ + +{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0}}, + +/* . . . . . . . . . . . . . . x x */ +/* . . . . . . . . . . . . . . x x */ +/* . . . . . . . . . . . . . . . X */ +/* . . . . . . . . . . . . . . x x */ +/* . . . . . . . . . . . . . . x x */ +/* . . . . . . . . . . . . . x x . */ + +{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0}}}, + +{ /* --- Chamber 1 --- */ + +/* x x . . . . . . . . . . . . . . */ +/* x x . . . . . . . . . . . . . . */ +/* X . . . . . . . . . . . . . . . */ +/* x x . . . . . . . . . . . . . . */ +/* x . . . . . . . . . . . . . . . */ +/* . . . . . . . . . . . . . . . . */ + +{{1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, + +/* x x x . . . . . . . . . . . . . */ +/* x x x . . . . . . . . . . . . . */ +/* . X . . . . . . . . . . . . . . */ +/* x x x . . . . . . . . . . . . . */ +/* x x . . . . . . . . . . . . . . */ +/* x . . . . . . . . . . . . . . . */ + +{{1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, + +/* . x x x . . . . . . . . . . . . */ +/* . x x x . . . . . . . . . . . . */ +/* . . X . . . . . . . . . . . . . */ +/* . x x x . . . . . . . . . . . . */ +/* . x x . . . . . . . . . . . . . */ +/* x x . . . . . . . . . . . . . . */ + +{{0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, + +/* . . x x x . . . . . . . . . . . */ +/* . . x x x . . . . . . . . . . . */ +/* . . . X . . . . . . . . . . . . */ +/* . . x x . . . . . . . . . . . . */ +/* . . x x . . . . . . . . . . . . */ +/* . x x . . . . . . . . . . . . . */ + +{{0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, + +/* . . . . x x . . . . . . . . . . */ +/* . . . . x x . . . . . . . . . . */ +/* . . . . X . . . . . . . . . . . */ +/* . . . x x . . . . . . . . . . . */ +/* . . . x x . . . . . . . . . . . */ +/* . . x x x . . . . . . . . . . . */ + +{{0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, + +/* . . . . . x x . . . . . . . . . */ +/* . . . . . x x . . . . . . . . . */ +/* . . . . . X . . . . . . . . . . */ +/* . . . . x x . . . . . . . . . . */ +/* . . . . x x . . . . . . . . . . */ +/* . . . x x x . . . . . . . . . . */ + +{{0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, + +/* . . . . . . x x . . . . . . . . */ +/* . . . . . . x x . . . . . . . . */ +/* . . . . . . X . . . . . . . . . */ +/* . . . . . x x . . . . . . . . . */ +/* . . . . . x x . . . . . . . . . */ +/* . . . . x x x . . . . . . . . . */ + +{{0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, + +/* . . . . . . . x x . . . . . . . */ +/* . . . . . . . x x . . . . . . . */ +/* . . . . . . . X . . . . . . . . */ +/* . . . . . . x x . . . . . . . . */ +/* . . . . . . x x . . . . . . . . */ +/* . . . . . x x x . . . . . . . . */ + +{{0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0}}, + +/* . . . . . . . . x x . . . . . . */ +/* . . . . . . . . x x . . . . . . */ +/* . . . . . . . . X . . . . . . . */ +/* . . . . . . . x x . . . . . . . */ +/* . . . . . . . x x . . . . . . . */ +/* . . . . . . x x x . . . . . . . */ + +{{0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0}}, + +/* . . . . . . . . . x x . . . . . */ +/* . . . . . . . . . x x . . . . . */ +/* . . . . . . . . . X . . . . . . */ +/* . . . . . . . . x x . . . . . . */ +/* . . . . . . . . x x . . . . . . */ +/* . . . . . . . x x x . . . . . . */ + +{{0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0}}, + +/* . . . . . . . . . . x x . . . . */ +/* . . . . . . . . . . x x . . . . */ +/* . . . . . . . . . . X . . . . . */ +/* . . . . . . . . . x x . . . . . */ +/* . . . . . . . . . x x . . . . . */ +/* . . . . . . . . x x x . . . . . */ + +{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0}}, + +/* . . . . . . . . . . . x x . . . */ +/* . . . . . . . . . . . x x . . . */ +/* . . . . . . . . . . . X . . . . */ +/* . . . . . . . . . . x x . . . . */ +/* . . . . . . . . . . x x . . . . */ +/* . . . . . . . . . x x x . . . . */ + +{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0}}, + +/* . . . . . . . . . . . . x x . . */ +/* . . . . . . . . . . . . x x . . */ +/* . . . . . . . . . . . . X . . . */ +/* . . . . . . . . . . . x x . . . */ +/* . . . . . . . . . . . x x . . . */ +/* . . . . . . . . . . x x x . . . */ + +{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0}}, + +/* . . . . . . . . . . . . . x x . */ +/* . . . . . . . . . . . . . x x . */ +/* . . . . . . . . . . . . . X . . */ +/* . . . . . . . . . . . . x x . . */ +/* . . . . . . . . . . . . x x . . */ +/* . . . . . . . . . . . x x x . . */ + +{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0}}, + +/* . . . . . . . . . . . . . . x x */ +/* . . . . . . . . . . . . . . x x */ +/* . . . . . . . . . . . . . . X . */ +/* . . . . . . . . . . . . . x x . */ +/* . . . . . . . . . . . . . x x . */ +/* . . . . . . . . . . . . x x x . */ + +{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0}}, + +/* . . . . . . . . . . . . . . . x */ +/* . . . . . . . . . . . . . . . x */ +/* . . . . . . . . . . . . . . . X */ +/* . . . . . . . . . . . . . . x x */ +/* . . . . . . . . . . . . . . x x */ +/* . . . . . . . . . . . . . x x x */ + +{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1}}}, + +{ /* --- Chamber 2 --- */ + +/* x x . . . . . . . . . . */ +/* x x . . . . . . . . . . */ +/* X . . . . . . . . . . . */ +/* x . . . . . . . . . . . */ +/* x . . . . . . . . . . . */ +/* x . . . . . . . . . . . */ + +{{1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, + +/* . x x . . . . . . . . . */ +/* . x x . . . . . . . . . */ +/* . X . . . . . . . . . . */ +/* x x . . . . . . . . . . */ +/* x x . . . . . . . . . . */ +/* x x . . . . . . . . . . */ + +{{0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, + +/* . . x x . . . . . . . . */ +/* . . x x . . . . . . . . */ +/* . . X . . . . . . . . . */ +/* . x x . . . . . . . . . */ +/* . x x . . . . . . . . . */ +/* . x x . . . . . . . . . */ + +{{0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, + +/* . . . x x . . . . . . . */ +/* . . . x x . . . . . . . */ +/* . . . X . . . . . . . . */ +/* . . x x x . . . . . . . */ +/* . . x x x . . . . . . . */ +/* . . x x x . . . . . . . */ + +{{0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, + +/* . . . x x x . . . . . . */ +/* . . . x x x . . . . . . */ +/* . . . . X . . . . . . . */ +/* . . . x x x . . . . . . */ +/* . . . x x x . . . . . . */ +/* . . . x x x . . . . . . */ + +{{0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, + +/* . . . . x x x . . . . . */ +/* . . . . x x x . . . . . */ +/* . . . . . X . . . . . . */ +/* . . . . x x x . . . . . */ +/* . . . . x x x . . . . . */ +/* . . . . x x x . . . . . */ + +{{0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, + +/* . . . . . x x x . . . . */ +/* . . . . . x x x . . . . */ +/* . . . . . . X . . . . . */ +/* . . . . . x x x . . . . */ +/* . . . . . x x x . . . . */ +/* . . . . . x x x . . . . */ + +{{0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0}}, + +/* . . . . . . x x x . . . */ +/* . . . . . . x x x . . . */ +/* . . . . . . . X . . . . */ +/* . . . . . . x x x . . . */ +/* . . . . . . x x x . . . */ +/* . . . . . . x x x . . . */ + +{{0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0}}, + +/* . . . . . . . x x . . . */ +/* . . . . . . . x x . . . */ +/* . . . . . . . . X . . . */ +/* . . . . . . . x x x . . */ +/* . . . . . . . x x x . . */ +/* . . . . . . . x x x . . */ + +{{0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0}}, + +/* . . . . . . . . x x . . */ +/* . . . . . . . . x x . . */ +/* . . . . . . . . . X . . */ +/* . . . . . . . . . x x . */ +/* . . . . . . . . . x x . */ +/* . . . . . . . . . x x . */ + +{{0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0}}, + +/* . . . . . . . . . x x . */ +/* . . . . . . . . . x x . */ +/* . . . . . . . . . . X . */ +/* . . . . . . . . . . x x */ +/* . . . . . . . . . . x x */ +/* . . . . . . . . . . x x */ + +{{0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0}}, + +/* . . . . . . . . . . x x */ +/* . . . . . . . . . . x x */ +/* . . . . . . . . . . . X */ +/* . . . . . . . . . . . x */ +/* . . . . . . . . . . . x */ +/* . . . . . . . . . . . x */ + +{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0}}, + +/* . . . . . . . . . . . . */ +/* . . . . . . . . . . . . */ +/* . . . . . . . . . . . . */ +/* . . . . . . . . . . . . */ +/* . . . . . . . . . . . . */ +/* . . . . . . . . . . . . */ + +{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, + +/* . . . . . . . . . . . . */ +/* . . . . . . . . . . . . */ +/* . . . . . . . . . . . . */ +/* . . . . . . . . . . . . */ +/* . . . . . . . . . . . . */ +/* . . . . . . . . . . . . */ + +{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, + +/* . . . . . . . . . . . . */ +/* . . . . . . . . . . . . */ +/* . . . . . . . . . . . . */ +/* . . . . . . . . . . . . */ +/* . . . . . . . . . . . . */ +/* . . . . . . . . . . . . */ + +{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, + +/* . . . . . . . . . . . . */ +/* . . . . . . . . . . . . */ +/* . . . . . . . . . . . . */ +/* . . . . . . . . . . . . */ +/* . . . . . . . . . . . . */ +/* . . . . . . . . . . . . */ + +{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, + +{ /* --- Chamber 3 --- */ + +/* x . . . . . . . . . . . . . . . */ +/* x . . . . . . . . . . . . . . . */ +/* X . . . . . . . . . . . . . . . */ +/* x x . . . . . . . . . . . . . . */ +/* x x . . . . . . . . . . . . . . */ +/* x x x . . . . . . . . . . . . . */ + +{{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, + +/* x x . . . . . . . . . . . . . . */ +/* x x . . . . . . . . . . . . . . */ +/* . X . . . . . . . . . . . . . . */ +/* . x x . . . . . . . . . . . . . */ +/* . x x . . . . . . . . . . . . . */ +/* . x x x . . . . . . . . . . . . */ + +{{1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, + +/* . x x . . . . . . . . . . . . . */ +/* . x x . . . . . . . . . . . . . */ +/* . . X . . . . . . . . . . . . . */ +/* . . x x . . . . . . . . . . . . */ +/* . . x x . . . . . . . . . . . . */ +/* . . x x x . . . . . . . . . . . */ + +{{0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, + +/* . . x x . . . . . . . . . . . . */ +/* . . x x . . . . . . . . . . . . */ +/* . . . X . . . . . . . . . . . . */ +/* . . . x x . . . . . . . . . . . */ +/* . . . x x . . . . . . . . . . . */ +/* . . . x x x . . . . . . . . . . */ + +{{0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, + +/* . . . x x . . . . . . . . . . . */ +/* . . . x x . . . . . . . . . . . */ +/* . . . . X . . . . . . . . . . . */ +/* . . . . x x . . . . . . . . . . */ +/* . . . . x x . . . . . . . . . . */ +/* . . . . x x x . . . . . . . . . */ + +{{0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, + +/* . . . . x x . . . . . . . . . . */ +/* . . . . x x . . . . . . . . . . */ +/* . . . . . X . . . . . . . . . . */ +/* . . . . . x x . . . . . . . . . */ +/* . . . . . x x . . . . . . . . . */ +/* . . . . . x x x . . . . . . . . */ + +{{0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0}}, + +/* . . . . . x x . . . . . . . . . */ +/* . . . . . x x . . . . . . . . . */ +/* . . . . . . X . . . . . . . . . */ +/* . . . . . . x x . . . . . . . . */ +/* . . . . . . x x . . . . . . . . */ +/* . . . . . . x x x . . . . . . . */ + +{{0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0}}, + +/* . . . . . . x x . . . . . . . . */ +/* . . . . . . x x . . . . . . . . */ +/* . . . . . . . X . . . . . . . . */ +/* . . . . . . . x x . . . . . . . */ +/* . . . . . . . x x . . . . . . . */ +/* . . . . . . . x x x . . . . . . */ + +{{0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0}}, + +/* . . . . . . . x x . . . . . . . */ +/* . . . . . . . x x . . . . . . . */ +/* . . . . . . . . X . . . . . . . */ +/* . . . . . . . . x x . . . . . . */ +/* . . . . . . . . x x . . . . . . */ +/* . . . . . . . . x x x . . . . . */ + +{{0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0}}, + +/* . . . . . . . . x x . . . . . . */ +/* . . . . . . . . x x . . . . . . */ +/* . . . . . . . . . X . . . . . . */ +/* . . . . . . . . . x x . . . . . */ +/* . . . . . . . . . x x . . . . . */ +/* . . . . . . . . . x x x . . . . */ + +{{0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0}}, + +/* . . . . . . . . . x x . . . . . */ +/* . . . . . . . . . x x . . . . . */ +/* . . . . . . . . . . X . . . . . */ +/* . . . . . . . . . . x x . . . . */ +/* . . . . . . . . . . x x . . . . */ +/* . . . . . . . . . . x x x . . . */ + +{{0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0}}, + +/* . . . . . . . . . . x x . . . . */ +/* . . . . . . . . . . x x . . . . */ +/* . . . . . . . . . . . X . . . . */ +/* . . . . . . . . . . . x x . . . */ +/* . . . . . . . . . . . x x . . . */ +/* . . . . . . . . . . . x x x . . */ + +{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0}}, + +/* . . . . . . . . . . . x x x . . */ +/* . . . . . . . . . . . x x x . . */ +/* . . . . . . . . . . . . X . . . */ +/* . . . . . . . . . . . . x x . . */ +/* . . . . . . . . . . . . x x . . */ +/* . . . . . . . . . . . . . x x . */ + +{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0}}, + +/* . . . . . . . . . . . . x x x . */ +/* . . . . . . . . . . . . x x x . */ +/* . . . . . . . . . . . . . X . . */ +/* . . . . . . . . . . . . x x x . */ +/* . . . . . . . . . . . . . x x . */ +/* . . . . . . . . . . . . . . x x */ + +{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1}}, + +/* . . . . . . . . . . . . . x x x */ +/* . . . . . . . . . . . . . x x x */ +/* . . . . . . . . . . . . . . X . */ +/* . . . . . . . . . . . . . x x x */ +/* . . . . . . . . . . . . . . x x */ +/* . . . . . . . . . . . . . . . x */ + +{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}}, + +/* . . . . . . . . . . . . . . x x */ +/* . . . . . . . . . . . . . . x x */ +/* . . . . . . . . . . . . . . . X */ +/* . . . . . . . . . . . . . . x x */ +/* . . . . . . . . . . . . . . . x */ +/* . . . . . . . . . . . . . . . . */ + +{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, + +{ /* --- Chamber 4 --- */ + +/* x x . . . . . . . . . . . . . . */ +/* x x . . . . . . . . . . . . . . */ +/* X . . . . . . . . . . . . . . . */ +/* x x . . . . . . . . . . . . . . */ +/* x x . . . . . . . . . . . . . . */ +/* . x x . . . . . . . . . . . . . */ + +{{1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, + +/* x x x . . . . . . . . . . . . . */ +/* x x x . . . . . . . . . . . . . */ +/* . X . . . . . . . . . . . . . . */ +/* x x x . . . . . . . . . . . . . */ +/* . x x . . . . . . . . . . . . . */ +/* . . x x . . . . . . . . . . . . */ + +{{1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, + +/* . x x x . . . . . . . . . . . . */ +/* . x x x . . . . . . . . . . . . */ +/* . . X . . . . . . . . . . . . . */ +/* . x x x . . . . . . . . . . . . */ +/* . . x x . . . . . . . . . . . . */ +/* . . . x x . . . . . . . . . . . */ + +{{0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, + +/* . . x x x . . . . . . . . . . . */ +/* . . x x x . . . . . . . . . . . */ +/* . . . X . . . . . . . . . . . . */ +/* . . x x x . . . . . . . . . . . */ +/* . . . x x . . . . . . . . . . . */ +/* . . . . x x . . . . . . . . . . */ + +{{0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, + +/* . . . x x x . . . . . . . . . . */ +/* . . . x x x . . . . . . . . . . */ +/* . . . . X . . . . . . . . . . . */ +/* . . . x x x . . . . . . . . . . */ +/* . . . . x x . . . . . . . . . . */ +/* . . . . . x x . . . . . . . . . */ + +{{0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, + +/* . . . . x x x . . . . . . . . . */ +/* . . . . x x x . . . . . . . . . */ +/* . . . . . X . . . . . . . . . . */ +/* . . . . x x x . . . . . . . . . */ +/* . . . . . x x . . . . . . . . . */ +/* . . . . . . x x x . . . . . . . */ + +{{0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0}}, + +/* . . . . . x x x . . . . . . . . */ +/* . . . . . x x x . . . . . . . . */ +/* . . . . . . X . . . . . . . . . */ +/* . . . . . x x x . . . . . . . . */ +/* . . . . . . x x . . . . . . . . */ +/* . . . . . . . x x x . . . . . . */ + +{{0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0}}, + +/* . . . . . . x x x . . . . . . . */ +/* . . . . . . x x x . . . . . . . */ +/* . . . . . . . X . . . . . . . . */ +/* . . . . . . x x x . . . . . . . */ +/* . . . . . . . x x . . . . . . . */ +/* . . . . . . . . x x x . . . . . */ + +{{0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0}}, + +/* . . . . . . . x x x . . . . . . */ +/* . . . . . . . x x x . . . . . . */ +/* . . . . . . . . X . . . . . . . */ +/* . . . . . . . x x x . . . . . . */ +/* . . . . . . . . x x . . . . . . */ +/* . . . . . . . . . x x x . . . . */ + +{{0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0}}, + +/* . . . . . . . . x x x . . . . . */ +/* . . . . . . . . x x x . . . . . */ +/* . . . . . . . . . X . . . . . . */ +/* . . . . . . . . x x x . . . . . */ +/* . . . . . . . . . x x . . . . . */ +/* . . . . . . . . . . x x x . . . */ + +{{0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0}}, + +/* . . . . . . . . . x x x . . . . */ +/* . . . . . . . . . x x x . . . . */ +/* . . . . . . . . . . X . . . . . */ +/* . . . . . . . . . x x x . . . . */ +/* . . . . . . . . . . x x . . . . */ +/* . . . . . . . . . . . x x x . . */ + +{{0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0}}, + +/* . . . . . . . . . . x x x . . . */ +/* . . . . . . . . . . x x x . . . */ +/* . . . . . . . . . . . X . . . . */ +/* . . . . . . . . . . x x . . . . */ +/* . . . . . . . . . . . x x . . . */ +/* . . . . . . . . . . . . x x x . */ + +{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0}}, + +/* . . . . . . . . . . . . x x . . */ +/* . . . . . . . . . . . . x x . . */ +/* . . . . . . . . . . . . X . . . */ +/* . . . . . . . . . . . x x . . . */ +/* . . . . . . . . . . . . x x . . */ +/* . . . . . . . . . . . . . x x x */ + +{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1}}, + +/* . . . . . . . . . . . . . x x . */ +/* . . . . . . . . . . . . . x x . */ +/* . . . . . . . . . . . . . X . . */ +/* . . . . . . . . . . . . x x . . */ +/* . . . . . . . . . . . . . x x . */ +/* . . . . . . . . . . . . . . x x */ + +{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1}}, + +/* . . . . . . . . . . . . . . x x */ +/* . . . . . . . . . . . . . . x x */ +/* . . . . . . . . . . . . . . X . */ +/* . . . . . . . . . . . . . x x . */ +/* . . . . . . . . . . . . . . x x */ +/* . . . . . . . . . . . . . . . x */ + +{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}}, + +/* . . . . . . . . . . . . . . . x */ +/* . . . . . . . . . . . . . . . x */ +/* . . . . . . . . . . . . . . . X */ +/* . . . . . . . . . . . . . . x x */ +/* . . . . . . . . . . . . . . . x */ +/* . . . . . . . . . . . . . . . . */ + +{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}} + +}; + +#endif diff --git a/TRD/Calib/PIDLQ/Run0_0_v0_s1.root b/TRD/Calib/PIDLQ/Run0_0_v0_s1.root new file mode 100644 index 0000000000000000000000000000000000000000..fdb2891d5d1414777f41d6e553fd2f34db106fc4 GIT binary patch literal 34326 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

#~Br$ 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 UN062Nzl8=5BY?n}EAH9<0Rp`ZIRF3v literal 0 HcmV?d00001 diff --git a/TRD/TRDdEdxHistogramsV1_BV.root b/TRD/TRDdEdxHistogramsV1_BV.root new file mode 100644 index 0000000000000000000000000000000000000000..dad1c19c4f85ec5bac3b95ce1e04c83bf3f6cd3b GIT binary patch literal 56039 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