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),
53 // Default constructor
58 //______________________________________________________________________________
59 AliAlignmentTracks::AliAlignmentTracks(TChain *esdchain):
61 fPointsFilename("AliTrackPoints.root"),
66 fIsIndexBuilt(kFALSE),
73 // Constructor in the case
74 // the user provides an already
75 // built TChain with ESD trees
81 //______________________________________________________________________________
82 AliAlignmentTracks::AliAlignmentTracks(const char *esdfilename, const char *esdtreename):
83 fESDChain(new TChain(esdtreename)),
84 fPointsFilename("AliTrackPoints.root"),
89 fIsIndexBuilt(kFALSE),
96 // Constructor in the case
97 // the user provides a single ESD file
98 // or a directory containing ESD files
99 fESDChain->Add(esdfilename);
106 //______________________________________________________________________________
107 AliAlignmentTracks::~AliAlignmentTracks()
110 if (fESDChain) delete fESDChain;
118 if (fPointsFile) fPointsFile->Close();
121 //______________________________________________________________________________
122 void AliAlignmentTracks::AddESD(TChain *esdchain)
124 // Add a chain with ESD files
126 fESDChain->Add(esdchain);
128 fESDChain = esdchain;
131 //______________________________________________________________________________
132 void AliAlignmentTracks::AddESD(const char *esdfilename, const char *esdtreename)
134 // Add a single file or
135 // a directory to the chain
136 // with the ESD files
138 fESDChain->AddFile(esdfilename,TChain::kBigNumber,esdtreename);
140 fESDChain = new TChain(esdtreename);
141 fESDChain->Add(esdfilename);
145 //______________________________________________________________________________
146 void AliAlignmentTracks::ProcessESD()
148 // Analyzes and filters ESD tracks
149 // Stores the selected track space points
150 // into the output file
152 if (!fESDChain) return;
155 fESDChain->SetBranchAddress("ESD",&esd);
157 // Open the output file
158 if (fPointsFilename.Data() == "") {
159 AliWarning("Incorrect output filename!");
163 TFile *pointsFile = TFile::Open(fPointsFilename,"RECREATE");
164 if (!pointsFile || !pointsFile->IsOpen()) {
165 AliWarning(Form("Can't open %s !",fPointsFilename.Data()));
169 TTree *pointsTree = new TTree("spTree", "Tree with track space point arrays");
170 const AliTrackPointArray *array = 0;
171 pointsTree->Branch("SP","AliTrackPointArray", &array);
173 while (fESDChain->GetEntry(ievent++)) {
175 Int_t ntracks = esd->GetNumberOfTracks();
176 for (Int_t itrack=0; itrack < ntracks; itrack++) {
177 AliESDtrack * track = esd->GetTrack(itrack);
178 if (!track) continue;
180 // UInt_t status = AliESDtrack::kITSpid;
181 // status|=AliESDtrack::kTPCpid;
182 // status|=AliESDtrack::kTRDpid;
183 // if ((track->GetStatus() & status) != status) continue;
185 if (track->GetP() < 0.5) continue;
187 array = track->GetTrackPointArray();
192 if (!pointsTree->Write()) {
193 AliWarning("Can't write the tree with track point arrays!");
200 //______________________________________________________________________________
201 void AliAlignmentTracks::ProcessESD(TSelector *selector)
203 AliWarning(Form("ESD processing based on selector is not yet implemented (%p) !",selector));
206 //______________________________________________________________________________
207 void AliAlignmentTracks::BuildIndex()
209 // Build index of points tree entries
210 // Used for access based on the volume IDs
211 if (fIsIndexBuilt) return;
213 fIsIndexBuilt = kTRUE;
215 // Dummy object is created in order
216 // to initialize the volume paths
217 AliAlignObjAngles alobj;
219 TFile *fPointsFile = TFile::Open(fPointsFilename);
220 if (!fPointsFile || !fPointsFile->IsOpen()) {
221 AliWarning(Form("Can't open %s !",fPointsFilename.Data()));
225 // AliTrackPointArray* array = new AliTrackPointArray;
226 AliTrackPointArray* array = 0;
227 fPointsTree = (TTree*) fPointsFile->Get("spTree");
229 AliWarning("No pointsTree found!");
232 fPointsTree->SetBranchAddress("SP", &array);
234 Int_t nArrays = fPointsTree->GetEntries();
235 for (Int_t iArray = 0; iArray < nArrays; iArray++)
237 fPointsTree->GetEvent(iArray);
238 if (!array) continue;
239 for (Int_t ipoint = 0; ipoint < array->GetNPoints(); ipoint++) {
240 UShort_t volId = array->GetVolumeID()[ipoint];
241 // check if the volId is valid
242 if (!AliAlignObj::GetVolPath(volId)) {
243 AliError(Form("The volume id %d has no default volume path !",
248 Int_t layerId = AliAlignObj::VolUIDToLayer(volId,modId)
249 - AliAlignObj::kFirstLayer;
250 if (!fArrayIndex[layerId][modId]) {
251 //first entry for this volume
252 fArrayIndex[layerId][modId] = new TArrayI(1000);
255 Int_t size = fArrayIndex[layerId][modId]->GetSize();
256 // If needed allocate new size
257 if (fLastIndex[layerId][modId] >= size)
258 fArrayIndex[layerId][modId]->Set(size + 1000);
261 // Check if the index is already filled
262 Bool_t fillIndex = kTRUE;
263 if (fLastIndex[layerId][modId] != 0) {
264 if ((*fArrayIndex[layerId][modId])[fLastIndex[layerId][modId]-1] == iArray)
267 // Fill the index array and store last filled index
269 (*fArrayIndex[layerId][modId])[fLastIndex[layerId][modId]] = iArray;
270 fLastIndex[layerId][modId]++;
277 //______________________________________________________________________________
278 void AliAlignmentTracks::InitIndex()
280 // Initialize the index arrays
281 Int_t nLayers = AliAlignObj::kLastLayer - AliAlignObj::kFirstLayer;
282 fLastIndex = new Int_t*[nLayers];
283 fArrayIndex = new TArrayI**[nLayers];
284 for (Int_t iLayer = 0; iLayer < (AliAlignObj::kLastLayer - AliAlignObj::kFirstLayer); iLayer++) {
285 fLastIndex[iLayer] = new Int_t[AliAlignObj::LayerSize(iLayer + AliAlignObj::kFirstLayer)];
286 fArrayIndex[iLayer] = new TArrayI*[AliAlignObj::LayerSize(iLayer + AliAlignObj::kFirstLayer)];
287 for (Int_t iModule = 0; iModule < AliAlignObj::LayerSize(iLayer + AliAlignObj::kFirstLayer); iModule++) {
288 fLastIndex[iLayer][iModule] = 0;
289 fArrayIndex[iLayer][iModule] = 0;
294 //______________________________________________________________________________
295 void AliAlignmentTracks::ResetIndex()
297 // Reset the value of the last filled index
298 // Do not realocate memory
300 fIsIndexBuilt = kFALSE;
302 for (Int_t iLayer = 0; iLayer < AliAlignObj::kLastLayer - AliAlignObj::kFirstLayer; iLayer++) {
303 for (Int_t iModule = 0; iModule < AliAlignObj::LayerSize(iLayer + AliAlignObj::kFirstLayer); iModule++) {
304 fLastIndex[iLayer][iModule] = 0;
309 //______________________________________________________________________________
310 void AliAlignmentTracks::DeleteIndex()
312 // Delete the index arrays
313 // Called by the destructor
314 for (Int_t iLayer = 0; iLayer < (AliAlignObj::kLastLayer - AliAlignObj::kFirstLayer); iLayer++) {
315 for (Int_t iModule = 0; iModule < AliAlignObj::LayerSize(iLayer + AliAlignObj::kFirstLayer); iModule++) {
316 if (fArrayIndex[iLayer][iModule]) {
317 delete fArrayIndex[iLayer][iModule];
318 fArrayIndex[iLayer][iModule] = 0;
321 delete [] fLastIndex[iLayer];
322 delete [] fArrayIndex[iLayer];
324 delete [] fLastIndex;
325 delete [] fArrayIndex;
328 //______________________________________________________________________________
329 Bool_t AliAlignmentTracks::ReadAlignObjs(const char *alignObjFileName, const char* arrayName)
331 // Read alignment object from a file
332 // To be replaced by a call to CDB
333 AliWarning(Form("Method not yet implemented (%s in %s) !",arrayName,alignObjFileName));
338 //______________________________________________________________________________
339 void AliAlignmentTracks::InitAlignObjs()
341 // Initialize the alignment objects array
342 Int_t nLayers = AliAlignObj::kLastLayer - AliAlignObj::kFirstLayer;
343 fAlignObjs = new AliAlignObj**[nLayers];
344 for (Int_t iLayer = 0; iLayer < (AliAlignObj::kLastLayer - AliAlignObj::kFirstLayer); iLayer++) {
345 fAlignObjs[iLayer] = new AliAlignObj*[AliAlignObj::LayerSize(iLayer + AliAlignObj::kFirstLayer)];
346 for (Int_t iModule = 0; iModule < AliAlignObj::LayerSize(iLayer + AliAlignObj::kFirstLayer); iModule++) {
347 UShort_t volid = AliAlignObj::LayerToVolUID(iLayer+ AliAlignObj::kFirstLayer,iModule);
348 fAlignObjs[iLayer][iModule] = new AliAlignObjAngles("",volid,0,0,0,0,0,0);
353 //______________________________________________________________________________
354 void AliAlignmentTracks::ResetAlignObjs()
356 // Reset the alignment objects array
357 for (Int_t iLayer = 0; iLayer < (AliAlignObj::kLastLayer - AliAlignObj::kFirstLayer); iLayer++) {
358 for (Int_t iModule = 0; iModule < AliAlignObj::LayerSize(iLayer + AliAlignObj::kFirstLayer); iModule++)
359 fAlignObjs[iLayer][iModule]->SetPars(0,0,0,0,0,0);
363 //______________________________________________________________________________
364 void AliAlignmentTracks::DeleteAlignObjs()
366 // Delete the alignment objects array
367 for (Int_t iLayer = 0; iLayer < (AliAlignObj::kLastLayer - AliAlignObj::kFirstLayer); iLayer++) {
368 for (Int_t iModule = 0; iModule < AliAlignObj::LayerSize(iLayer + AliAlignObj::kFirstLayer); iModule++)
369 if (fAlignObjs[iLayer][iModule])
370 delete fAlignObjs[iLayer][iModule];
371 delete [] fAlignObjs[iLayer];
373 delete [] fAlignObjs;
377 void AliAlignmentTracks::AlignDetector(AliAlignObj::ELayerID firstLayer,
378 AliAlignObj::ELayerID lastLayer,
379 AliAlignObj::ELayerID layerRangeMin,
380 AliAlignObj::ELayerID layerRangeMax,
383 // Align detector volumes within
384 // a given layer range
385 // (could be whole detector).
386 // Tracks are fitted only within
387 // the range defined by the user.
389 for (Int_t iLayer = firstLayer; iLayer < lastLayer; iLayer++)
390 nModules += AliAlignObj::LayerSize(iLayer);
391 TArrayI volIds(nModules);
394 for (Int_t iLayer = firstLayer; iLayer < lastLayer; iLayer++) {
395 for (Int_t iModule = 0; iModule < AliAlignObj::LayerSize(iLayer); iModule++) {
396 UShort_t volId = AliAlignObj::LayerToVolUID(iLayer,iModule);
397 volIds.AddAt(volId,modnum);
402 while (iterations > 0) {
403 AlignVolumes(&volIds,0x0,layerRangeMin,layerRangeMax);
408 //______________________________________________________________________________
409 void AliAlignmentTracks::AlignLayer(AliAlignObj::ELayerID layer,
410 AliAlignObj::ELayerID layerRangeMin,
411 AliAlignObj::ELayerID layerRangeMax,
414 // Align detector volumes within
416 // Tracks are fitted only within
417 // the range defined by the user.
418 Int_t nModules = AliAlignObj::LayerSize(layer);
419 TArrayI volIds(nModules);
420 for (Int_t iModule = 0; iModule < nModules; iModule++) {
421 UShort_t volId = AliAlignObj::LayerToVolUID(layer,iModule);
422 volIds.AddAt(volId,iModule);
425 while (iterations > 0) {
426 AlignVolumes(&volIds,0x0,layerRangeMin,layerRangeMax);
431 //______________________________________________________________________________
432 void AliAlignmentTracks::AlignVolume(UShort_t volId, UShort_t volIdFit,
435 // Align single detector volume to
437 // Tracks are fitted only within
438 // the second volume.
440 volIds.AddAt(volId,0);
441 TArrayI volIdsFit(1);
442 volIdsFit.AddAt(volIdFit,0);
444 while (iterations > 0) {
445 AlignVolumes(&volIds,&volIdsFit);
450 //______________________________________________________________________________
451 void AliAlignmentTracks::AlignVolumes(const TArrayI *volids, const TArrayI *volidsfit,
452 AliAlignObj::ELayerID layerRangeMin,
453 AliAlignObj::ELayerID layerRangeMax,
456 // Align a set of detector volumes.
457 // Tracks are fitted only within
458 // the range defined by the user
459 // (by layerRangeMin and layerRangeMax)
460 // or within the set of volidsfit
461 // Repeat the procedure 'iterations' times
463 Int_t nVolIds = volids->GetSize();
465 AliError("Volume IDs array is empty!");
469 // Load only the tracks with at least one
470 // space point in the set of volume (volids)
472 AliTrackPointArray **points;
473 // Start the iterations
474 while (iterations > 0) {
475 Int_t nArrays = LoadPoints(volids, points);
476 if (nArrays == 0) return;
478 AliTrackResiduals *minimizer = CreateMinimizer();
479 minimizer->SetNTracks(nArrays);
480 minimizer->InitAlignObj();
481 AliTrackFitter *fitter = CreateFitter();
482 for (Int_t iArray = 0; iArray < nArrays; iArray++) {
483 if (!points[iArray]) continue;
484 fitter->SetTrackPointArray(points[iArray], kFALSE);
485 if (fitter->Fit(volids,volidsfit,layerRangeMin,layerRangeMax) == kFALSE) continue;
486 AliTrackPointArray *pVolId,*pTrack;
487 fitter->GetTrackResiduals(pVolId,pTrack);
488 minimizer->AddTrackPointArrays(pVolId,pTrack);
490 minimizer->Minimize();
492 // Update the alignment object(s)
493 if (fDoUpdate) for (Int_t iVolId = 0; iVolId < nVolIds; iVolId++) {
494 UShort_t volid = (*volids)[iVolId];
496 AliAlignObj::ELayerID iLayer = AliAlignObj::VolUIDToLayer(volid,iModule);
497 AliAlignObj *alignObj = fAlignObjs[iLayer-AliAlignObj::kFirstLayer][iModule];
498 *alignObj *= *minimizer->GetAlignObj();
502 UnloadPoints(nArrays, points);
508 //______________________________________________________________________________
509 Int_t AliAlignmentTracks::LoadPoints(const TArrayI *volids, AliTrackPointArray** &points)
511 // Load track point arrays with at least
512 // one space point in a given set of detector
513 // volumes (array volids).
514 // Use the already created tree index for
518 AliError("Tree with the space point arrays not initialized!");
523 Int_t nVolIds = volids->GetSize();
525 AliError("Volume IDs array is empty!");
531 for (Int_t iVolId = 0; iVolId < nVolIds; iVolId++) {
532 UShort_t volid = (*volids)[iVolId];
534 AliAlignObj::ELayerID iLayer = AliAlignObj::VolUIDToLayer(volid,iModule);
536 // In case of empty index
537 if (fLastIndex[iLayer-AliAlignObj::kFirstLayer][iModule] == 0) {
538 AliWarning(Form("There are no space-points belonging to the volume which is to be aligned (Volume ID =%d)!",volid));
541 nArrays += fLastIndex[iLayer-AliAlignObj::kFirstLayer][iModule];
545 AliError("There are no space-points belonging to all of the volumes which are to be aligned!");
550 AliTrackPointArray* array = 0;
551 fPointsTree->SetBranchAddress("SP", &array);
553 // Allocate the pointer to the space-point arrays
554 points = new AliTrackPointArray*[nArrays];
555 for (Int_t i = 0; i < nArrays; i++) points[i] = 0x0;
557 // Init the array used to flag already loaded tree entries
558 Bool_t *indexUsed = new Bool_t[fPointsTree->GetEntries()];
559 for (Int_t i = 0; i < fPointsTree->GetEntries(); i++)
560 indexUsed[i] = kFALSE;
562 // Start the loop over the volume ids
564 for (Int_t iVolId = 0; iVolId < nVolIds; iVolId++) {
565 UShort_t volid = (*volids)[iVolId];
567 AliAlignObj::ELayerID iLayer = AliAlignObj::VolUIDToLayer(volid,iModule);
569 Int_t nArraysId = fLastIndex[iLayer-AliAlignObj::kFirstLayer][iModule];
570 TArrayI *index = fArrayIndex[iLayer-AliAlignObj::kFirstLayer][iModule];
573 for (Int_t iArrayId = 0; iArrayId < nArraysId; iArrayId++) {
576 Int_t entry = (*index)[iArrayId];
577 if (indexUsed[entry] == kTRUE) continue;
578 fPointsTree->GetEvent(entry);
580 AliWarning("Wrong space point array index!");
583 indexUsed[entry] = kTRUE;
585 // Get the space-point array
586 Int_t nPoints = array->GetNPoints();
587 points[iArray] = new AliTrackPointArray(nPoints);
588 for (Int_t iPoint = 0; iPoint < nPoints; iPoint++) {
589 array->GetPoint(p,iPoint);
591 AliAlignObj::ELayerID layer = AliAlignObj::VolUIDToLayer(p.GetVolumeID(),modnum);
592 // check if the layer id is valid
593 if ((layer < AliAlignObj::kFirstLayer) ||
594 (layer >= AliAlignObj::kLastLayer)) {
595 AliError(Form("Layer index is invalid: %d (%d -> %d) !",
596 layer,AliAlignObj::kFirstLayer,AliAlignObj::kLastLayer-1));
599 if ((modnum >= AliAlignObj::LayerSize(layer)) ||
601 AliError(Form("Module number inside layer %d is invalid: %d (0 -> %d)",
602 layer,modnum,AliAlignObj::LayerSize(layer)));
606 // Misalignment is introduced here
607 // Switch it off in case of real
610 AliAlignObj *misalignObj = fMisalignObjs[layer-AliAlignObj::kFirstLayer][modnum];
612 misalignObj->Transform(p);
614 // End of misalignment
616 AliAlignObj *alignObj = fAlignObjs[layer-AliAlignObj::kFirstLayer][modnum];
617 alignObj->Transform(p);
618 points[iArray]->AddPoint(iPoint,&p);
630 //______________________________________________________________________________
631 void AliAlignmentTracks::UnloadPoints(Int_t n, AliTrackPointArray **points)
633 // Unload track point arrays for a given
635 for (Int_t iArray = 0; iArray < n; iArray++)
636 delete points[iArray];
640 //______________________________________________________________________________
641 AliTrackFitter *AliAlignmentTracks::CreateFitter()
643 // Check if the user has already supplied
644 // a track fitter object.
645 // If not, create a default one.
647 fTrackFitter = new AliTrackFitterRieman;
652 //______________________________________________________________________________
653 AliTrackResiduals *AliAlignmentTracks::CreateMinimizer()
655 // Check if the user has already supplied
656 // a track residuals minimizer object.
657 // If not, create a default one.
659 fMinimizer = new AliTrackResidualsChi2;
664 //______________________________________________________________________________
665 Bool_t AliAlignmentTracks::Misalign(const char *misalignObjFileName, const char* arrayName)
667 // The method reads from a file a set of AliAlignObj which are
668 // then used to apply misalignments directly on the track
669 // space-points. The method is supposed to be used only for
670 // fast development and debugging of the alignment algorithms.
671 // Be careful not to use it in the case of 'real' alignment
672 // scenario since it will bias the results.
674 // Initialize the misalignment objects array
675 Int_t nLayers = AliAlignObj::kLastLayer - AliAlignObj::kFirstLayer;
676 fMisalignObjs = new AliAlignObj**[nLayers];
677 for (Int_t iLayer = 0; iLayer < (AliAlignObj::kLastLayer - AliAlignObj::kFirstLayer); iLayer++) {
678 fMisalignObjs[iLayer] = new AliAlignObj*[AliAlignObj::LayerSize(iLayer + AliAlignObj::kFirstLayer)];
679 for (Int_t iModule = 0; iModule < AliAlignObj::LayerSize(iLayer + AliAlignObj::kFirstLayer); iModule++)
680 fMisalignObjs[iLayer][iModule] = 0x0;
683 // Open the misliagnment file and load the array with
684 // misalignment objects
685 TFile* inFile = TFile::Open(misalignObjFileName,"READ");
686 if (!inFile || !inFile->IsOpen()) {
687 AliError(Form("Could not open misalignment file %s !",misalignObjFileName));
691 TClonesArray* array = ((TClonesArray*) inFile->Get(arrayName));
693 AliError(Form("Could not find misalignment array %s in the file %s !",arrayName,misalignObjFileName));
699 // Store the misalignment objects for further usage
700 Int_t nObjs = array->GetEntriesFast();
701 AliAlignObj::ELayerID layerId; // volume layer
702 Int_t modId; // volume ID inside the layer
703 for(Int_t i=0; i<nObjs; i++)
705 AliAlignObj* alObj = (AliAlignObj*)array->UncheckedAt(i);
706 alObj->GetVolUID(layerId,modId);
707 fMisalignObjs[layerId-AliAlignObj::kFirstLayer][modId] = alObj;