/************************************************************************** * 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. * **************************************************************************/ //----------------------------------------------------------------- // Implementation of the alignment steering class // It provides an access to the track space points // written along the esd tracks. The class enables // the user to plug any track fitter (deriving from // AliTrackFitter class) and minimization fo the // track residual sums (deriving from the AliTrackResiduals). //----------------------------------------------------------------- #include #include #include "AliAlignmentTracks.h" #include "AliTrackPointArray.h" #include "AliAlignObjAngles.h" #include "AliTrackFitterRieman.h" #include "AliTrackResidualsChi2.h" #include "AliESD.h" #include "AliLog.h" ClassImp(AliAlignmentTracks) //______________________________________________________________________________ AliAlignmentTracks::AliAlignmentTracks(): fESDChain(0), fPointsFilename("AliTrackPoints.root"), fPointsFile(0), fPointsTree(0), fLastIndex(0), fArrayIndex(0), fIsIndexBuilt(kFALSE), fTrackFitter(0), fMinimizer(0) { // Default constructor InitIndex(); InitAlignObjs(); } //______________________________________________________________________________ AliAlignmentTracks::AliAlignmentTracks(TChain *esdchain): fESDChain(esdchain), fPointsFilename("AliTrackPoints.root"), fPointsFile(0), fPointsTree(0), fLastIndex(0), fArrayIndex(0), fIsIndexBuilt(kFALSE), fTrackFitter(0), fMinimizer(0) { // Constructor in the case // the user provides an already // built TChain with ESD trees InitIndex(); InitAlignObjs(); } //______________________________________________________________________________ AliAlignmentTracks::AliAlignmentTracks(const char *esdfilename, const char *esdtreename): fPointsFilename("AliTrackPoints.root"), fPointsFile(0), fPointsTree(0), fLastIndex(0), fArrayIndex(0), fIsIndexBuilt(kFALSE), fTrackFitter(0), fMinimizer(0) { // Constructor in the case // the user provides a single ESD file // or a directory containing ESD files fESDChain = new TChain(esdtreename); fESDChain->Add(esdfilename); InitIndex(); InitAlignObjs(); } //______________________________________________________________________________ AliAlignmentTracks::AliAlignmentTracks(const AliAlignmentTracks &alignment): TObject(alignment) { // Copy constructor // not implemented AliWarning("Copy constructor not implemented!"); } //______________________________________________________________________________ AliAlignmentTracks& AliAlignmentTracks::operator= (const AliAlignmentTracks& alignment) { // Asignment operator // not implemented if(this==&alignment) return *this; AliWarning("Asignment operator not implemented!"); ((TObject *)this)->operator=(alignment); return *this; } //______________________________________________________________________________ AliAlignmentTracks::~AliAlignmentTracks() { // Destructor if (fESDChain) delete fESDChain; DeleteIndex(); DeleteAlignObjs(); delete fTrackFitter; delete fMinimizer; if (fPointsFile) fPointsFile->Close(); } //______________________________________________________________________________ void AliAlignmentTracks::AddESD(TChain *esdchain) { // Add a chain with ESD files if (fESDChain) fESDChain->Add(esdchain); else fESDChain = esdchain; } //______________________________________________________________________________ void AliAlignmentTracks::AddESD(const char *esdfilename, const char *esdtreename) { // Add a single file or // a directory to the chain // with the ESD files if (fESDChain) fESDChain->AddFile(esdfilename,TChain::kBigNumber,esdtreename); else { fESDChain = new TChain(esdtreename); fESDChain->Add(esdfilename); } } //______________________________________________________________________________ void AliAlignmentTracks::ProcessESD() { // Analyzes and filters ESD tracks // Stores the selected track space points // into the output file if (!fESDChain) return; AliESD *esd = 0; fESDChain->SetBranchAddress("ESD",&esd); // Open the output file if (fPointsFilename.Data() == "") { AliWarning("Incorrect output filename!"); return; } TFile *pointsFile = TFile::Open(fPointsFilename,"RECREATE"); if (!pointsFile || !pointsFile->IsOpen()) { AliWarning(Form("Can't open %s !",fPointsFilename.Data())); return; } TTree *pointsTree = new TTree("spTree", "Tree with track space point arrays"); AliTrackPointArray *array = 0; pointsTree->Branch("SP","AliTrackPointArray", &array); Int_t ievent = 0; while (fESDChain->GetEntry(ievent++)) { if (!esd) break; Int_t ntracks = esd->GetNumberOfTracks(); for (Int_t itrack=0; itrack < ntracks; itrack++) { AliESDtrack * track = esd->GetTrack(itrack); if (!track) continue; UInt_t status = AliESDtrack::kITSpid; status|=AliESDtrack::kTPCpid; status|=AliESDtrack::kTRDpid; if ((track->GetStatus() & status) != status) continue; if (track->GetP() < 0.5) continue; array = track->GetTrackPointArray(); pointsTree->Fill(); } } if (!pointsTree->Write()) { AliWarning("Can't write the tree with track point arrays!"); return; } pointsFile->Close(); } //______________________________________________________________________________ void AliAlignmentTracks::ProcessESD(TSelector *selector) { AliWarning(Form("ESD processing based on selector is not yet implemented (%p) !",selector)); } //______________________________________________________________________________ void AliAlignmentTracks::BuildIndex() { // Build index of points tree entries // Used for access based on the volume IDs if (fIsIndexBuilt) ResetIndex(); else fIsIndexBuilt = kTRUE; TFile *fPointsFile = TFile::Open(fPointsFilename); if (!fPointsFile || !fPointsFile->IsOpen()) { AliWarning(Form("Can't open %s !",fPointsFilename.Data())); return; } // AliTrackPointArray* array = new AliTrackPointArray; AliTrackPointArray* array = 0; TTree* pointsTree = (TTree*) fPointsFile->Get("spTree"); if (!pointsTree) { AliWarning("No pointsTree found!"); return; } pointsTree->SetBranchAddress("SP", &array); Int_t nArrays = pointsTree->GetEntries(); for (Int_t iArray = 0; iArray < nArrays; iArray++) { pointsTree->GetEvent(iArray); if (!array) continue; for (Int_t ipoint = 0; ipoint < array->GetNPoints(); ipoint++) { UShort_t volId = array->GetVolumeID()[ipoint]; Int_t modId; Int_t layerId = AliAlignObj::VolUIDToLayer(volId,modId) - AliAlignObj::kFirstLayer; if (!fArrayIndex[layerId][modId]) { //first entry for this volume fArrayIndex[layerId][modId] = new TArrayI(1000); } else { Int_t size = fArrayIndex[layerId][modId]->GetSize(); // If needed allocate new size if (fLastIndex[layerId][modId] >= size) fArrayIndex[layerId][modId]->Set(size + 1000); } // Check if the index is already filled Bool_t fillIndex = kTRUE; if (fLastIndex[layerId][modId] != 0) { if ((*fArrayIndex[layerId][modId])[fLastIndex[layerId][modId]-1] == iArray) fillIndex = kFALSE; } // Fill the index array and store last filled index if (fillIndex) { (*fArrayIndex[layerId][modId])[fLastIndex[layerId][modId]] = iArray; fLastIndex[layerId][modId]++; } } } } // //______________________________________________________________________________ // void AliAlignmentTracks::BuildIndexLayer(AliAlignObj::ELayerID layer) // { // } // //______________________________________________________________________________ // void AliAlignmentTracks::BuildIndexVolume(UShort_t volid) // { // } //______________________________________________________________________________ void AliAlignmentTracks::InitIndex() { // Initialize the index arrays Int_t nLayers = AliAlignObj::kLastLayer - AliAlignObj::kFirstLayer; fLastIndex = new Int_t*[nLayers]; fArrayIndex = new TArrayI**[nLayers]; for (Int_t iLayer = 0; iLayer < (AliAlignObj::kLastLayer - AliAlignObj::kFirstLayer); iLayer++) { fLastIndex[iLayer] = new Int_t[AliAlignObj::LayerSize(iLayer)]; fArrayIndex[iLayer] = new TArrayI*[AliAlignObj::LayerSize(iLayer)]; for (Int_t iModule = 0; iModule < AliAlignObj::LayerSize(iLayer); iModule++) { fLastIndex[iLayer][iModule] = 0; fArrayIndex[iLayer][iModule] = 0; } } } //______________________________________________________________________________ void AliAlignmentTracks::ResetIndex() { // Reset the value of the last filled index // Do not realocate memory for (Int_t iLayer = AliAlignObj::kFirstLayer; iLayer < AliAlignObj::kLastLayer; iLayer++) { for (Int_t iModule = 0; iModule < AliAlignObj::LayerSize(iLayer); iModule++) { fLastIndex[iLayer][iModule] = 0; } } } //______________________________________________________________________________ void AliAlignmentTracks::DeleteIndex() { // Delete the index arrays // Called by the destructor for (Int_t iLayer = 0; iLayer < (AliAlignObj::kLastLayer - AliAlignObj::kFirstLayer); iLayer++) { for (Int_t iModule = 0; iModule < AliAlignObj::LayerSize(iLayer); iModule++) { if (fArrayIndex[iLayer][iModule]) { delete fArrayIndex[iLayer][iModule]; fArrayIndex[iLayer][iModule] = 0; } } delete [] fLastIndex[iLayer]; delete [] fArrayIndex[iLayer]; } delete [] fLastIndex; delete [] fArrayIndex; } //______________________________________________________________________________ Bool_t AliAlignmentTracks::ReadAlignObjs(const char *alignobjfilename) { // Read alignment object from a file // To be replaced by a call to CDB AliWarning(Form("Method not yet implemented (%s) !",alignobjfilename)); return kFALSE; } //______________________________________________________________________________ void AliAlignmentTracks::InitAlignObjs() { // Initialize the alignment objects array Int_t nLayers = AliAlignObj::kLastLayer - AliAlignObj::kFirstLayer; fAlignObjs = new AliAlignObj**[nLayers]; for (Int_t iLayer = 0; iLayer < (AliAlignObj::kLastLayer - AliAlignObj::kFirstLayer); iLayer++) { fAlignObjs[iLayer] = new AliAlignObj*[AliAlignObj::LayerSize(iLayer)]; for (Int_t iModule = 0; iModule < AliAlignObj::LayerSize(iLayer); iModule++) fAlignObjs[iLayer][iModule] = new AliAlignObjAngles; } } //______________________________________________________________________________ void AliAlignmentTracks::ResetAlignObjs() { // Reset the alignment objects array for (Int_t iLayer = 0; iLayer < (AliAlignObj::kLastLayer - AliAlignObj::kFirstLayer); iLayer++) { for (Int_t iModule = 0; iModule < AliAlignObj::LayerSize(iLayer); iModule++) fAlignObjs[iLayer][iModule]->SetPars(0,0,0,0,0,0); } } //______________________________________________________________________________ void AliAlignmentTracks::DeleteAlignObjs() { // Delete the alignment objects array for (Int_t iLayer = 0; iLayer < (AliAlignObj::kLastLayer - AliAlignObj::kFirstLayer); iLayer++) { for (Int_t iModule = 0; iModule < AliAlignObj::LayerSize(iLayer); iModule++) if (fAlignObjs[iLayer][iModule]) delete fAlignObjs[iLayer][iModule]; delete [] fAlignObjs[iLayer]; } delete [] fAlignObjs; } //______________________________________________________________________________ void AliAlignmentTracks::Align(Int_t iterations) { // This method is just an example // how one can user AlignLayer and // AlignVolume methods to construct // a custom alignment procedure while (iterations > 0) { // First inward pass AlignLayer(AliAlignObj::kTPC1); AlignLayer(AliAlignObj::kSSD2); AlignLayer(AliAlignObj::kSSD1); AlignLayer(AliAlignObj::kSDD2); AlignLayer(AliAlignObj::kSDD1); AlignLayer(AliAlignObj::kSPD2); AlignLayer(AliAlignObj::kSPD1); // Outward pass AlignLayer(AliAlignObj::kSPD2); AlignLayer(AliAlignObj::kSDD1); AlignLayer(AliAlignObj::kSDD2); AlignLayer(AliAlignObj::kSSD1); AlignLayer(AliAlignObj::kSSD2); AlignLayer(AliAlignObj::kTPC1); AlignLayer(AliAlignObj::kTPC2); AlignLayer(AliAlignObj::kTRD1); AlignLayer(AliAlignObj::kTRD2); AlignLayer(AliAlignObj::kTRD3); AlignLayer(AliAlignObj::kTRD4); AlignLayer(AliAlignObj::kTRD5); AlignLayer(AliAlignObj::kTRD6); AlignLayer(AliAlignObj::kTOF); // Again inward AlignLayer(AliAlignObj::kTRD6); AlignLayer(AliAlignObj::kTRD5); AlignLayer(AliAlignObj::kTRD4); AlignLayer(AliAlignObj::kTRD3); AlignLayer(AliAlignObj::kTRD2); AlignLayer(AliAlignObj::kTRD1); AlignLayer(AliAlignObj::kTPC2); } } //______________________________________________________________________________ void AliAlignmentTracks::AlignLayer(AliAlignObj::ELayerID layer, AliAlignObj::ELayerID layerRangeMin, AliAlignObj::ELayerID layerRangeMax, Int_t iterations) { // Align detector volumes within // a given layer. // Tracks are fitted only within // the range defined by the user. while (iterations > 0) { for (Int_t iModule = 0; iModule < AliAlignObj::LayerSize(layer); iModule++) { UShort_t volId = AliAlignObj::LayerToVolUID(layer,iModule); AlignVolume(volId,layerRangeMin,layerRangeMax); } iterations--; } } //______________________________________________________________________________ void AliAlignmentTracks::AlignVolume(UShort_t volid, AliAlignObj::ELayerID layerRangeMin, AliAlignObj::ELayerID layerRangeMax) { // Align a single detector volume. // Tracks are fitted only within // the range defined by the user. // First take the alignment object to be updated Int_t iModule; AliAlignObj::ELayerID iLayer = AliAlignObj::VolUIDToLayer(volid,iModule); AliAlignObj *alignObj = fAlignObjs[iLayer][iModule]; // Then load only the tracks with at least one // space point in the volume (volid) BuildIndex(); AliTrackPointArray **points; Int_t nArrays = LoadPoints(volid, points); if (nArrays == 0) return; AliTrackResiduals *minimizer = CreateMinimizer(); minimizer->SetNTracks(nArrays); minimizer->SetAlignObj(alignObj); AliTrackFitter *fitter = CreateFitter(); for (Int_t iArray = 0; iArray < nArrays; iArray++) { fitter->SetTrackPointArray(points[iArray], kFALSE); AliTrackPointArray *pVolId = 0, *pTrack = 0; fitter->Fit(volid,pVolId,pTrack,layerRangeMin,layerRangeMax); minimizer->AddTrackPointArrays(pVolId,pTrack); } minimizer->Minimize(); UnloadPoints(nArrays, points); } //______________________________________________________________________________ Int_t AliAlignmentTracks::LoadPoints(UShort_t volid, AliTrackPointArray** &points) { // Load track point arrays with at least // one space point in a given detector // volume (volid). // Use the already created tree index for // fast access. Int_t iModule; AliAlignObj::ELayerID iLayer = AliAlignObj::VolUIDToLayer(volid,iModule); Int_t nArrays = fLastIndex[iLayer][iModule]; // In case of empty index if (nArrays == 0) { points = 0; return 0; } if (!fPointsTree) { AliWarning("Tree with the space point arrays not initialized!"); points = 0; return 0; } AliAlignObj *alignObj = fAlignObjs[iLayer][iModule]; TGeoHMatrix m; alignObj->GetMatrix(m); Double_t *rot = m.GetRotationMatrix(); Double_t *tr = m.GetTranslation(); AliTrackPointArray* array = 0; fPointsTree->SetBranchAddress("SP", &array); points = new AliTrackPointArray*[nArrays]; TArrayI *index = fArrayIndex[iLayer][iModule]; AliTrackPoint p; Float_t xyz[3],cov[6]; Float_t newxyz[3]; for (Int_t iArray = 0; iArray < nArrays; iArray++) { fPointsTree->GetEvent((*index)[iArray]); if (!array) { AliWarning("Wrong space point array index!"); continue; } Int_t nPoints = array->GetNPoints(); points[iArray] = new AliTrackPointArray(nPoints); for (Int_t iPoint = 0; iPoint < nPoints; iPoint++) { array->GetPoint(p,iPoint); p.GetXYZ(xyz,cov); for (Int_t i = 0; i < 3; i++) newxyz[i] = tr[i] + xyz[0]*rot[3*i] + xyz[1]*rot[3*i+1] + xyz[2]*rot[3*i+2]; p.SetXYZ(newxyz,cov); points[iArray]->AddPoint(iPoint,&p); } } return nArrays; } //______________________________________________________________________________ void AliAlignmentTracks::UnloadPoints(Int_t n, AliTrackPointArray **points) { // Unload track point arrays for a given // detector volume for (Int_t iArray = 0; iArray < n; iArray++) delete points[iArray]; delete [] points; } //______________________________________________________________________________ AliTrackFitter *AliAlignmentTracks::CreateFitter() { // Check if the user has already supplied // a track fitter object. // If not, create a default one. if (!fTrackFitter) fTrackFitter = new AliTrackFitterRieman; return fTrackFitter; } //______________________________________________________________________________ AliTrackResiduals *AliAlignmentTracks::CreateMinimizer() { // Check if the user has already supplied // a track residuals minimizer object. // If not, create a default one. if (!fMinimizer) fMinimizer = new AliTrackResidualsChi2; return fMinimizer; }