1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
16 //-----------------------------------------------------------------
17 // Implementation of the alignment steering class
18 // It provides an access to the track space points
19 // written along the esd tracks. The class enables
20 // the user to plug any track fitter (deriving from
21 // AliTrackFitter class) and minimization fo the
22 // track residual sums (deriving from the AliTrackResiduals).
23 //-----------------------------------------------------------------
28 #include "AliAlignmentTracks.h"
29 #include "AliTrackPointArray.h"
30 #include "AliAlignObjAngles.h"
31 #include "AliTrackFitterRieman.h"
32 #include "AliTrackResidualsChi2.h"
36 ClassImp(AliAlignmentTracks)
38 //______________________________________________________________________________
39 AliAlignmentTracks::AliAlignmentTracks():
41 fPointsFilename("AliTrackPoints.root"),
46 fIsIndexBuilt(kFALSE),
52 // Default constructor
57 //______________________________________________________________________________
58 AliAlignmentTracks::AliAlignmentTracks(TChain *esdchain):
60 fPointsFilename("AliTrackPoints.root"),
65 fIsIndexBuilt(kFALSE),
71 // Constructor in the case
72 // the user provides an already
73 // built TChain with ESD trees
79 //______________________________________________________________________________
80 AliAlignmentTracks::AliAlignmentTracks(const char *esdfilename, const char *esdtreename):
81 fPointsFilename("AliTrackPoints.root"),
86 fIsIndexBuilt(kFALSE),
92 // Constructor in the case
93 // the user provides a single ESD file
94 // or a directory containing ESD files
95 fESDChain = new TChain(esdtreename);
96 fESDChain->Add(esdfilename);
102 //______________________________________________________________________________
103 AliAlignmentTracks::AliAlignmentTracks(const AliAlignmentTracks &alignment):
108 AliWarning("Copy constructor not implemented!");
111 //______________________________________________________________________________
112 AliAlignmentTracks& AliAlignmentTracks::operator= (const AliAlignmentTracks& alignment)
114 // Asignment operator
116 if(this==&alignment) return *this;
118 AliWarning("Asignment operator not implemented!");
120 ((TObject *)this)->operator=(alignment);
125 //______________________________________________________________________________
126 AliAlignmentTracks::~AliAlignmentTracks()
129 if (fESDChain) delete fESDChain;
137 if (fPointsFile) fPointsFile->Close();
140 //______________________________________________________________________________
141 void AliAlignmentTracks::AddESD(TChain *esdchain)
143 // Add a chain with ESD files
145 fESDChain->Add(esdchain);
147 fESDChain = esdchain;
150 //______________________________________________________________________________
151 void AliAlignmentTracks::AddESD(const char *esdfilename, const char *esdtreename)
153 // Add a single file or
154 // a directory to the chain
155 // with the ESD files
157 fESDChain->AddFile(esdfilename,TChain::kBigNumber,esdtreename);
159 fESDChain = new TChain(esdtreename);
160 fESDChain->Add(esdfilename);
164 //______________________________________________________________________________
165 void AliAlignmentTracks::ProcessESD()
167 // Analyzes and filters ESD tracks
168 // Stores the selected track space points
169 // into the output file
171 if (!fESDChain) return;
174 fESDChain->SetBranchAddress("ESD",&esd);
176 // Open the output file
177 if (fPointsFilename.Data() == "") {
178 AliWarning("Incorrect output filename!");
182 TFile *pointsFile = TFile::Open(fPointsFilename,"RECREATE");
183 if (!pointsFile || !pointsFile->IsOpen()) {
184 AliWarning(Form("Can't open %s !",fPointsFilename.Data()));
188 TTree *pointsTree = new TTree("spTree", "Tree with track space point arrays");
189 const AliTrackPointArray *array = 0;
190 pointsTree->Branch("SP","AliTrackPointArray", &array);
192 while (fESDChain->GetEntry(ievent++)) {
194 Int_t ntracks = esd->GetNumberOfTracks();
195 for (Int_t itrack=0; itrack < ntracks; itrack++) {
196 AliESDtrack * track = esd->GetTrack(itrack);
197 if (!track) continue;
199 // UInt_t status = AliESDtrack::kITSpid;
200 // status|=AliESDtrack::kTPCpid;
201 // status|=AliESDtrack::kTRDpid;
202 // if ((track->GetStatus() & status) != status) continue;
204 if (track->GetP() < 0.5) continue;
206 array = track->GetTrackPointArray();
211 if (!pointsTree->Write()) {
212 AliWarning("Can't write the tree with track point arrays!");
219 //______________________________________________________________________________
220 void AliAlignmentTracks::ProcessESD(TSelector *selector)
222 AliWarning(Form("ESD processing based on selector is not yet implemented (%p) !",selector));
225 //______________________________________________________________________________
226 void AliAlignmentTracks::BuildIndex()
228 // Build index of points tree entries
229 // Used for access based on the volume IDs
230 if (fIsIndexBuilt) return;
232 fIsIndexBuilt = kTRUE;
234 // Dummy object is created in order
235 // to initialize the volume paths
236 AliAlignObjAngles alobj;
238 TFile *fPointsFile = TFile::Open(fPointsFilename);
239 if (!fPointsFile || !fPointsFile->IsOpen()) {
240 AliWarning(Form("Can't open %s !",fPointsFilename.Data()));
244 // AliTrackPointArray* array = new AliTrackPointArray;
245 AliTrackPointArray* array = 0;
246 fPointsTree = (TTree*) fPointsFile->Get("spTree");
248 AliWarning("No pointsTree found!");
251 fPointsTree->SetBranchAddress("SP", &array);
253 Int_t nArrays = fPointsTree->GetEntries();
254 for (Int_t iArray = 0; iArray < nArrays; iArray++)
256 fPointsTree->GetEvent(iArray);
257 if (!array) continue;
258 for (Int_t ipoint = 0; ipoint < array->GetNPoints(); ipoint++) {
259 UShort_t volId = array->GetVolumeID()[ipoint];
260 // check if the volId is valid
261 if (!AliAlignObj::GetVolPath(volId)) {
262 AliError(Form("The volume id %d has no default volume path !",
267 Int_t layerId = AliAlignObj::VolUIDToLayer(volId,modId)
268 - AliAlignObj::kFirstLayer;
269 if (!fArrayIndex[layerId][modId]) {
270 //first entry for this volume
271 fArrayIndex[layerId][modId] = new TArrayI(1000);
274 Int_t size = fArrayIndex[layerId][modId]->GetSize();
275 // If needed allocate new size
276 if (fLastIndex[layerId][modId] >= size)
277 fArrayIndex[layerId][modId]->Set(size + 1000);
280 // Check if the index is already filled
281 Bool_t fillIndex = kTRUE;
282 if (fLastIndex[layerId][modId] != 0) {
283 if ((*fArrayIndex[layerId][modId])[fLastIndex[layerId][modId]-1] == iArray)
286 // Fill the index array and store last filled index
288 (*fArrayIndex[layerId][modId])[fLastIndex[layerId][modId]] = iArray;
289 fLastIndex[layerId][modId]++;
296 //______________________________________________________________________________
297 void AliAlignmentTracks::InitIndex()
299 // Initialize the index arrays
300 Int_t nLayers = AliAlignObj::kLastLayer - AliAlignObj::kFirstLayer;
301 fLastIndex = new Int_t*[nLayers];
302 fArrayIndex = new TArrayI**[nLayers];
303 for (Int_t iLayer = 0; iLayer < (AliAlignObj::kLastLayer - AliAlignObj::kFirstLayer); iLayer++) {
304 fLastIndex[iLayer] = new Int_t[AliAlignObj::LayerSize(iLayer + AliAlignObj::kFirstLayer)];
305 fArrayIndex[iLayer] = new TArrayI*[AliAlignObj::LayerSize(iLayer + AliAlignObj::kFirstLayer)];
306 for (Int_t iModule = 0; iModule < AliAlignObj::LayerSize(iLayer + AliAlignObj::kFirstLayer); iModule++) {
307 fLastIndex[iLayer][iModule] = 0;
308 fArrayIndex[iLayer][iModule] = 0;
313 //______________________________________________________________________________
314 void AliAlignmentTracks::ResetIndex()
316 // Reset the value of the last filled index
317 // Do not realocate memory
319 fIsIndexBuilt = kFALSE;
321 for (Int_t iLayer = 0; iLayer < AliAlignObj::kLastLayer - AliAlignObj::kFirstLayer; iLayer++) {
322 for (Int_t iModule = 0; iModule < AliAlignObj::LayerSize(iLayer + AliAlignObj::kFirstLayer); iModule++) {
323 fLastIndex[iLayer][iModule] = 0;
328 //______________________________________________________________________________
329 void AliAlignmentTracks::DeleteIndex()
331 // Delete the index arrays
332 // Called by the destructor
333 for (Int_t iLayer = 0; iLayer < (AliAlignObj::kLastLayer - AliAlignObj::kFirstLayer); iLayer++) {
334 for (Int_t iModule = 0; iModule < AliAlignObj::LayerSize(iLayer + AliAlignObj::kFirstLayer); iModule++) {
335 if (fArrayIndex[iLayer][iModule]) {
336 delete fArrayIndex[iLayer][iModule];
337 fArrayIndex[iLayer][iModule] = 0;
340 delete [] fLastIndex[iLayer];
341 delete [] fArrayIndex[iLayer];
343 delete [] fLastIndex;
344 delete [] fArrayIndex;
347 //______________________________________________________________________________
348 Bool_t AliAlignmentTracks::ReadAlignObjs(const char *alignObjFileName, const char* arrayName)
350 // Read alignment object from a file
351 // To be replaced by a call to CDB
352 AliWarning(Form("Method not yet implemented (%s in %s) !",arrayName,alignObjFileName));
357 //______________________________________________________________________________
358 void AliAlignmentTracks::InitAlignObjs()
360 // Initialize the alignment objects array
361 Int_t nLayers = AliAlignObj::kLastLayer - AliAlignObj::kFirstLayer;
362 fAlignObjs = new AliAlignObj**[nLayers];
363 for (Int_t iLayer = 0; iLayer < (AliAlignObj::kLastLayer - AliAlignObj::kFirstLayer); iLayer++) {
364 fAlignObjs[iLayer] = new AliAlignObj*[AliAlignObj::LayerSize(iLayer + AliAlignObj::kFirstLayer)];
365 for (Int_t iModule = 0; iModule < AliAlignObj::LayerSize(iLayer + AliAlignObj::kFirstLayer); iModule++) {
366 UShort_t volid = AliAlignObj::LayerToVolUID(iLayer+ AliAlignObj::kFirstLayer,iModule);
367 fAlignObjs[iLayer][iModule] = new AliAlignObjAngles("",volid,0,0,0,0,0,0);
372 //______________________________________________________________________________
373 void AliAlignmentTracks::ResetAlignObjs()
375 // Reset the alignment objects array
376 for (Int_t iLayer = 0; iLayer < (AliAlignObj::kLastLayer - AliAlignObj::kFirstLayer); iLayer++) {
377 for (Int_t iModule = 0; iModule < AliAlignObj::LayerSize(iLayer + AliAlignObj::kFirstLayer); iModule++)
378 fAlignObjs[iLayer][iModule]->SetPars(0,0,0,0,0,0);
382 //______________________________________________________________________________
383 void AliAlignmentTracks::DeleteAlignObjs()
385 // Delete the alignment objects array
386 for (Int_t iLayer = 0; iLayer < (AliAlignObj::kLastLayer - AliAlignObj::kFirstLayer); iLayer++) {
387 for (Int_t iModule = 0; iModule < AliAlignObj::LayerSize(iLayer + AliAlignObj::kFirstLayer); iModule++)
388 if (fAlignObjs[iLayer][iModule])
389 delete fAlignObjs[iLayer][iModule];
390 delete [] fAlignObjs[iLayer];
392 delete [] fAlignObjs;
396 void AliAlignmentTracks::AlignDetector(AliAlignObj::ELayerID firstLayer,
397 AliAlignObj::ELayerID lastLayer,
398 AliAlignObj::ELayerID layerRangeMin,
399 AliAlignObj::ELayerID layerRangeMax,
402 // Align detector volumes within
403 // a given layer range
404 // (could be whole detector).
405 // Tracks are fitted only within
406 // the range defined by the user.
408 for (Int_t iLayer = firstLayer; iLayer < lastLayer; iLayer++)
409 nModules += AliAlignObj::LayerSize(iLayer);
410 TArrayI volIds(nModules);
413 for (Int_t iLayer = firstLayer; iLayer < lastLayer; iLayer++) {
414 for (Int_t iModule = 0; iModule < AliAlignObj::LayerSize(iLayer); iModule++) {
415 UShort_t volId = AliAlignObj::LayerToVolUID(iLayer,iModule);
416 volIds.AddAt(volId,modnum);
421 while (iterations > 0) {
422 AlignVolumes(&volIds,0x0,layerRangeMin,layerRangeMax);
427 //______________________________________________________________________________
428 void AliAlignmentTracks::AlignLayer(AliAlignObj::ELayerID layer,
429 AliAlignObj::ELayerID layerRangeMin,
430 AliAlignObj::ELayerID layerRangeMax,
433 // Align detector volumes within
435 // Tracks are fitted only within
436 // the range defined by the user.
437 Int_t nModules = AliAlignObj::LayerSize(layer);
438 TArrayI volIds(nModules);
439 for (Int_t iModule = 0; iModule < nModules; iModule++) {
440 UShort_t volId = AliAlignObj::LayerToVolUID(layer,iModule);
441 volIds.AddAt(volId,iModule);
444 while (iterations > 0) {
445 AlignVolumes(&volIds,0x0,layerRangeMin,layerRangeMax);
450 //______________________________________________________________________________
451 void AliAlignmentTracks::AlignVolume(UShort_t volId, UShort_t volIdFit,
454 // Align single detector volume to
456 // Tracks are fitted only within
457 // the second volume.
459 volIds.AddAt(volId,0);
460 TArrayI volIdsFit(1);
461 volIdsFit.AddAt(volIdFit,0);
463 while (iterations > 0) {
464 AlignVolumes(&volIds,&volIdsFit);
469 //______________________________________________________________________________
470 void AliAlignmentTracks::AlignVolumes(const TArrayI *volids, const TArrayI *volidsfit,
471 AliAlignObj::ELayerID layerRangeMin,
472 AliAlignObj::ELayerID layerRangeMax,
475 // Align a set of detector volumes.
476 // Tracks are fitted only within
477 // the range defined by the user
478 // (by layerRangeMin and layerRangeMax)
479 // or within the set of volidsfit
480 // Repeat the procedure 'iterations' times
482 Int_t nVolIds = volids->GetSize();
484 AliError("Volume IDs array is empty!");
488 // Load only the tracks with at least one
489 // space point in the set of volume (volids)
491 AliTrackPointArray **points;
492 // Start the iterations
493 while (iterations > 0) {
494 Int_t nArrays = LoadPoints(volids, points);
495 if (nArrays == 0) return;
497 AliTrackResiduals *minimizer = CreateMinimizer();
498 minimizer->SetNTracks(nArrays);
499 minimizer->InitAlignObj();
500 AliTrackFitter *fitter = CreateFitter();
501 for (Int_t iArray = 0; iArray < nArrays; iArray++) {
502 if (!points[iArray]) continue;
503 fitter->SetTrackPointArray(points[iArray], kFALSE);
504 if (fitter->Fit(volids,volidsfit,layerRangeMin,layerRangeMax) == kFALSE) continue;
505 AliTrackPointArray *pVolId,*pTrack;
506 fitter->GetTrackResiduals(pVolId,pTrack);
507 minimizer->AddTrackPointArrays(pVolId,pTrack);
509 minimizer->Minimize();
511 // Update the alignment object(s)
512 if (fDoUpdate) for (Int_t iVolId = 0; iVolId < nVolIds; iVolId++) {
513 UShort_t volid = (*volids)[iVolId];
515 AliAlignObj::ELayerID iLayer = AliAlignObj::VolUIDToLayer(volid,iModule);
516 AliAlignObj *alignObj = fAlignObjs[iLayer-AliAlignObj::kFirstLayer][iModule];
517 *alignObj *= *minimizer->GetAlignObj();
521 UnloadPoints(nArrays, points);
527 //______________________________________________________________________________
528 Int_t AliAlignmentTracks::LoadPoints(const TArrayI *volids, AliTrackPointArray** &points)
530 // Load track point arrays with at least
531 // one space point in a given set of detector
532 // volumes (array volids).
533 // Use the already created tree index for
537 AliError("Tree with the space point arrays not initialized!");
542 Int_t nVolIds = volids->GetSize();
544 AliError("Volume IDs array is empty!");
550 for (Int_t iVolId = 0; iVolId < nVolIds; iVolId++) {
551 UShort_t volid = (*volids)[iVolId];
553 AliAlignObj::ELayerID iLayer = AliAlignObj::VolUIDToLayer(volid,iModule);
555 // In case of empty index
556 if (fLastIndex[iLayer-AliAlignObj::kFirstLayer][iModule] == 0) {
557 AliWarning(Form("There are no space-points belonging to the volume which is to be aligned (Volume ID =%d)!",volid));
560 nArrays += fLastIndex[iLayer-AliAlignObj::kFirstLayer][iModule];
564 AliError("There are no space-points belonging to all of the volumes which are to be aligned!");
569 AliTrackPointArray* array = 0;
570 fPointsTree->SetBranchAddress("SP", &array);
572 // Allocate the pointer to the space-point arrays
573 points = new AliTrackPointArray*[nArrays];
574 for (Int_t i = 0; i < nArrays; i++) points[i] = 0x0;
576 // Init the array used to flag already loaded tree entries
577 Bool_t *indexUsed = new Bool_t[fPointsTree->GetEntries()];
578 for (Int_t i = 0; i < fPointsTree->GetEntries(); i++)
579 indexUsed[i] = kFALSE;
581 // Start the loop over the volume ids
583 for (Int_t iVolId = 0; iVolId < nVolIds; iVolId++) {
584 UShort_t volid = (*volids)[iVolId];
586 AliAlignObj::ELayerID iLayer = AliAlignObj::VolUIDToLayer(volid,iModule);
588 Int_t nArraysId = fLastIndex[iLayer-AliAlignObj::kFirstLayer][iModule];
589 TArrayI *index = fArrayIndex[iLayer-AliAlignObj::kFirstLayer][iModule];
592 for (Int_t iArrayId = 0; iArrayId < nArraysId; iArrayId++) {
595 Int_t entry = (*index)[iArrayId];
596 if (indexUsed[entry] == kTRUE) continue;
597 fPointsTree->GetEvent(entry);
599 AliWarning("Wrong space point array index!");
602 indexUsed[entry] = kTRUE;
604 // Get the space-point array
605 Int_t nPoints = array->GetNPoints();
606 points[iArray] = new AliTrackPointArray(nPoints);
607 for (Int_t iPoint = 0; iPoint < nPoints; iPoint++) {
608 array->GetPoint(p,iPoint);
610 AliAlignObj::ELayerID layer = AliAlignObj::VolUIDToLayer(p.GetVolumeID(),modnum);
611 // check if the layer id is valid
612 if ((layer < AliAlignObj::kFirstLayer) ||
613 (layer >= AliAlignObj::kLastLayer)) {
614 AliError(Form("Layer index is invalid: %d (%d -> %d) !",
615 layer,AliAlignObj::kFirstLayer,AliAlignObj::kLastLayer-1));
618 if ((modnum >= AliAlignObj::LayerSize(layer)) ||
620 AliError(Form("Module number inside layer %d is invalid: %d (0 -> %d)",
621 layer,modnum,AliAlignObj::LayerSize(layer)));
625 // Misalignment is introduced here
626 // Switch it off in case of real
629 AliAlignObj *misalignObj = fMisalignObjs[layer-AliAlignObj::kFirstLayer][modnum];
631 misalignObj->Transform(p);
633 // End of misalignment
635 AliAlignObj *alignObj = fAlignObjs[layer-AliAlignObj::kFirstLayer][modnum];
636 alignObj->Transform(p);
637 points[iArray]->AddPoint(iPoint,&p);
649 //______________________________________________________________________________
650 void AliAlignmentTracks::UnloadPoints(Int_t n, AliTrackPointArray **points)
652 // Unload track point arrays for a given
654 for (Int_t iArray = 0; iArray < n; iArray++)
655 delete points[iArray];
659 //______________________________________________________________________________
660 AliTrackFitter *AliAlignmentTracks::CreateFitter()
662 // Check if the user has already supplied
663 // a track fitter object.
664 // If not, create a default one.
666 fTrackFitter = new AliTrackFitterRieman;
671 //______________________________________________________________________________
672 AliTrackResiduals *AliAlignmentTracks::CreateMinimizer()
674 // Check if the user has already supplied
675 // a track residuals minimizer object.
676 // If not, create a default one.
678 fMinimizer = new AliTrackResidualsChi2;
683 //______________________________________________________________________________
684 Bool_t AliAlignmentTracks::Misalign(const char *misalignObjFileName, const char* arrayName)
686 // The method reads from a file a set of AliAlignObj which are
687 // then used to apply misalignments directly on the track
688 // space-points. The method is supposed to be used only for
689 // fast development and debugging of the alignment algorithms.
690 // Be careful not to use it in the case of 'real' alignment
691 // scenario since it will bias the results.
693 // Initialize the misalignment objects array
694 Int_t nLayers = AliAlignObj::kLastLayer - AliAlignObj::kFirstLayer;
695 fMisalignObjs = new AliAlignObj**[nLayers];
696 for (Int_t iLayer = 0; iLayer < (AliAlignObj::kLastLayer - AliAlignObj::kFirstLayer); iLayer++) {
697 fMisalignObjs[iLayer] = new AliAlignObj*[AliAlignObj::LayerSize(iLayer + AliAlignObj::kFirstLayer)];
698 for (Int_t iModule = 0; iModule < AliAlignObj::LayerSize(iLayer + AliAlignObj::kFirstLayer); iModule++)
699 fMisalignObjs[iLayer][iModule] = 0x0;
702 // Open the misliagnment file and load the array with
703 // misalignment objects
704 TFile* inFile = TFile::Open(misalignObjFileName,"READ");
705 if (!inFile || !inFile->IsOpen()) {
706 AliError(Form("Could not open misalignment file %s !",misalignObjFileName));
710 TClonesArray* array = ((TClonesArray*) inFile->Get(arrayName));
712 AliError(Form("Could not find misalignment array %s in the file %s !",arrayName,misalignObjFileName));
718 // Store the misalignment objects for further usage
719 Int_t nObjs = array->GetEntriesFast();
720 AliAlignObj::ELayerID layerId; // volume layer
721 Int_t modId; // volume ID inside the layer
722 for(Int_t i=0; i<nObjs; i++)
724 AliAlignObj* alObj = (AliAlignObj*)array->UncheckedAt(i);
725 alObj->GetVolUID(layerId,modId);
726 fMisalignObjs[layerId-AliAlignObj::kFirstLayer][modId] = alObj;