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 **************************************************************************/
18 //-----------------------------------------------------------------------------
19 /// \class AliMUONAlignmentTask
20 /// AliAnalysisTask to align the MUON spectrometer.
21 /// The Task reads as input ESDs and feeds the MUONTracks to AliMUONAlignment.
22 /// The alignment itself is performed by AliMillePede2.
23 /// A OCDB entry is written with the alignment parameters.
25 /// \author Javier Castillo, CEA/Saclay - Irfu/SPhN
26 /// \author Hugo Pereira Da Costa, CEA/Saclay - Irfu/SPhN
27 //-----------------------------------------------------------------------------
29 // this class header must always come first
30 #include "AliMUONAlignmentTask.h"
32 // local header must come before system headers
33 #include "AliAnalysisManager.h"
34 #include "AliAlignObjMatrix.h"
35 #include "AliAODInputHandler.h"
36 #include "AliAODHandler.h"
37 #include "AliAODEvent.h"
38 #include "AliAODHeader.h"
39 #include "AliCDBEntry.h"
40 #include "AliESDInputHandler.h"
41 #include "AliESDEvent.h"
42 #include "AliESDMuonTrack.h"
43 #include "AliCDBStorage.h"
44 #include "AliCDBManager.h"
45 #include "AliGRPManager.h"
46 #include "AliCDBMetaData.h"
48 #include "AliGeomManager.h"
51 #include "AliMillePedeRecord.h"
53 #include "AliMUONCDB.h"
54 #include "AliMUONAlignment.h"
55 #include "AliMUONConstants.h"
56 #include "AliMUONRecoParam.h"
57 #include "AliMUONTrack.h"
58 #include "AliMUONTrackExtrap.h"
59 #include "AliMUONTrackParam.h"
60 #include "AliMUONGeometryTransformer.h"
61 #include "AliMUONESDInterface.h"
71 #include <TGraphErrors.h>
74 #include <TClonesArray.h>
75 #include <TGeoGlobalMagField.h>
76 #include <TGeoManager.h>
77 #include <Riostream.h>
80 ClassImp(AliMUONAlignmentTask)
83 //________________________________________________________________________
84 AliMUONAlignmentTask::AliMUONAlignmentTask( const char *name ):
85 AliAnalysisTaskSE(name),
86 fReadRecords( kFALSE ),
87 fWriteRecords( kFALSE ),
88 fDoAlignment( kTRUE ),
89 fMergeAlignmentCDBs( kTRUE ),
90 fForceBField( kFALSE ),
95 fNewAlignStorage( "local://ReAlignOCDB" ),
96 fOldGeoTransformer(0x0),
97 fNewGeoTransformer(0x0),
98 fLoadOCDBOnce(kFALSE),
108 /// Default Constructor
109 // Define input and output slots here
110 // Input slot #0 works with a TChain
111 DefineInput(0, TChain::Class());
113 // initialize parameters ...
114 for(Int_t k=0;k<AliMUONAlignment::fNGlobal;k++)
121 // create alignment object
122 fAlign = new AliMUONAlignment();
124 // create old geometry transformer
125 fOldGeoTransformer = new AliMUONGeometryTransformer();
129 //________________________________________________________________________
130 AliMUONAlignmentTask::~AliMUONAlignmentTask()
134 delete fOldGeoTransformer;
135 delete fNewGeoTransformer;
138 //________________________________________________________________________
139 void AliMUONAlignmentTask::LocalInit()
142 Local initialization, called once per task on the client machine
143 where the analysis train is assembled
146 /* must run alignment when reading records */
147 if( fReadRecords && !fDoAlignment )
150 AliInfo( "Automatically setting fDoAlignment to kTRUE because fReadRecords is kTRUE" );
151 SetDoAlignment( kTRUE );
155 // print configuration
156 if( fRunNumberMin > 0 || fRunNumberMax > 0 )
157 { AliInfo( Form( "run range: %i - %i", fRunNumberMin, fRunNumberMax ) ); }
159 AliInfo( Form( "fReadRecords: %s", (fReadRecords ? "kTRUE":"kFALSE" ) ) );
160 AliInfo( Form( "fWriteRecords: %s", (fWriteRecords ? "kTRUE":"kFALSE" ) ) );
161 AliInfo( Form( "fDoAlignment: %s", (fDoAlignment ? "kTRUE":"kFALSE" ) ) );
165 // merge alignment DB flag is irrelevant if not actually performing the alignemnt
166 AliInfo( Form( "fMergeAlignmentCDBs: %s", (fMergeAlignmentCDBs ? "kTRUE":"kFALSE" ) ) );
170 if( !fDefaultStorage.IsNull() ) AliInfo( Form( "fDefaultStorage: %s", fDefaultStorage.Data() ) );
171 if( !fOldAlignStorage.IsNull() ) AliInfo( Form( "fOldAlignStorage: %s", fOldAlignStorage.Data() ) );
175 // new alignment storage is irrelevant if not actually performing the alignemnt
176 if( !fNewAlignStorage.IsNull() ) AliInfo( Form( "fNewAlignStorage: %s", fNewAlignStorage.Data() ) );
177 else AliFatal( "Invalid new alignment storage path" );
182 // following flags are only relevant if not reading records
183 if( fForceBField ) AliInfo( Form( "fBFieldOn: %s", (fBFieldOn ? "kTRUE":"kFALSE" ) ) );
184 else AliInfo( "fBFieldOn: from GRP" );
187 // consistency checks between flags
188 /* need at least one of the flags set to true */
189 if( !( fReadRecords || fWriteRecords || fDoAlignment ) )
190 { AliFatal( "Need at least one of the three flags fReadRecords, fWriteRecords and fDoAlignment set to kTRUE" ); }
192 /* cannot read and write records at the same time */
193 if( fReadRecords && fWriteRecords )
194 { AliFatal( "Cannot set both fReadRecords and fWriteRecords to kTRUE at the same time" ); }
198 warning, counting chambers from 1.
199 this must be done before calling the Init method
204 fAlign->FixChamber(1);
205 fAlign->FixChamber(10);
209 AliInfo( "Not fixing detector elements, since alignment is not required" );
216 // Do alignment with magnetic field off
217 fAlign->SetBFieldOn( fBFieldOn );
219 // Set expected resolution (see AliMUONAlignment)
220 fAlign->SetSigmaXY(0.15,0.10);
222 // initialize global parameters to provided values
223 fAlign->InitGlobalParameters(fParameters);
227 //________________________________________________________________________
228 void AliMUONAlignmentTask::UserCreateOutputObjects()
231 // connect AOD output
234 AliAODHandler* handler = dynamic_cast<AliAODHandler*>( AliAnalysisManager::GetAnalysisManager()->GetOutputEventHandler() );
238 // get AOD output handler and add Branch
239 fRecords = new TClonesArray( "AliMillePedeRecord", 0 );
240 fRecords->SetName( "records" );
241 handler->AddBranch("TClonesArray", &fRecords);
245 } else AliFatal( "Error: invalid output event handler" );
251 //________________________________________________________________________
252 void AliMUONAlignmentTask::UserExec(Option_t *)
255 // do nothing if run number not in range
256 if( fRunNumberMin > 0 && fCurrentRunNumber < fRunNumberMin ) return;
257 if( fRunNumberMax > 0 && fCurrentRunNumber > fRunNumberMax ) return;
259 // increase event count
263 if( fWriteRecords && fRecords )
272 AliAODEvent* lAOD( dynamic_cast<AliAODEvent*>(InputEvent() ) );
277 AliInfo("Error: AOD event not available");
282 TClonesArray* records = static_cast<TClonesArray*>( lAOD->FindListObject( "records" ) );
285 AliInfo( "Unable to read object name \"records\"" );
289 // get number of records and print
290 const Int_t lRecordsCount( records->GetEntriesFast() );
291 fTrackTot += lRecordsCount;
294 for( Int_t index = 0; index < lRecordsCount; ++index )
297 if( AliMillePedeRecord* record = dynamic_cast<AliMillePedeRecord*>( records->UncheckedAt(index) ) )
300 fAlign->ProcessTrack( record );
304 { AliInfo( Form( "Processed %i Tracks and %i were fitted.", fTrackTot, fTrackOk ) ); }
306 } else AliInfo( Form( "Invalid record at %i", index ) );
312 /// Main loop, called for each event
313 AliESDEvent* lESD( dynamic_cast<AliESDEvent*>(InputEvent()) );
318 AliInfo("Error: ESD event not available");
322 Int_t nTracks = Int_t(lESD->GetNumberOfMuonTracks());
323 for( Int_t iTrack = 0; iTrack < nTracks; iTrack++ )
326 AliESDMuonTrack* esdTrack = lESD->GetMuonTrack(iTrack);
327 if (!esdTrack->ContainTrackerData()) continue;
328 if (!esdTrack->ContainTriggerData()) continue;
330 Double_t invBenMom = esdTrack->GetInverseBendingMomentum();
331 if (TMath::Abs(invBenMom)<=1.04)
335 AliMUONESDInterface::ESDToMUON(*esdTrack, track);
337 // process track and retrieve corresponding records, for storage
338 const AliMillePedeRecord* lRecords( fAlign->ProcessTrack( &track, fDoAlignment ) );
342 if( fWriteRecords && fRecords )
344 new((*fRecords)[fRecordCount]) AliMillePedeRecord( *lRecords );
353 { AliInfo( Form( "Processed %i Tracks and %i were fitted.", fTrackTot, fTrackOk ) ); }
355 // Post final data. Write histo list to a file with option "RECREATE"
356 // PostData(1,fList);
361 if( fWriteRecords && fRecordCount > 0 )
363 AliAODHandler* handler = dynamic_cast<AliAODHandler*>( AliAnalysisManager::GetAnalysisManager()->GetOutputEventHandler() );
366 AliAODEvent* aod = handler->GetAOD();
367 AliAODHeader* header = dynamic_cast<AliAODHeader*>(aod->GetHeader());
368 if(!header) AliFatal("Not a standard AOD");
369 header->SetRunNumber(lESD->GetRunNumber());
370 AliAnalysisManager::GetAnalysisManager()->GetOutputEventHandler()->SetFillAOD(kTRUE);
372 } else AliInfo( "Error: invalid output event handler" );
380 //________________________________________________________________________
381 void AliMUONAlignmentTask::FinishTaskOutput()
384 /// Called once per task on the client machine at the end of the analysis.
385 AliInfo( Form( "Processed %i tracks.", fTrackTot ) );
386 AliInfo( Form( "Accepted %i tracks.", fTrackOk ) );
388 // stop here if no alignment is to be performed
389 if( !fDoAlignment ) return;
391 AliLog::SetGlobalLogLevel(AliLog::kInfo);
393 // Perform global fit
394 fAlign->GlobalFit(fParameters,fErrors,fPulls);
395 Int_t idOffset = 0; // 400
396 Int_t lSDetElemCh = 0;
398 for( Int_t iDE=0; iDE<AliMUONAlignment::fgNDetElem; iDE++ )
401 Int_t detElemId = idOffset+100;
404 for(Int_t iCh=0; iCh<9; iCh++)
407 lSDetElemCh += AliMUONAlignment::fgNDetElemCh[iCh];
408 if (iDE>=lSDetElemCh)
411 detElemId -= AliMUONAlignment::fgNDetElemCh[iCh];
418 // Post final data. Write histo list to a file with option "RECREATE"
419 // PostData(1,fList);
421 // store misalignments from OCDB into old transformers
422 if( fMergeAlignmentCDBs )
423 { SaveMisAlignmentData( fOldGeoTransformer ); }
426 fNewGeoTransformer = fAlign->ReAlign( fOldGeoTransformer, fParameters, true );
428 // Generate realigned data in local cdb
429 const TClonesArray* array = fNewGeoTransformer->GetMisAlignmentData();
431 // 100 mum residual resolution for chamber misalignments?
432 fAlign->SetAlignmentResolution( array, -1, 0.01, 0.01, 0.004, 0.003 );
435 AliLog::SetGlobalDebugLevel(2);
437 // recover default storage full name (raw:// cannot be used to set specific storage)
438 AliCDBManager* cdbManager = AliCDBManager::Instance();
440 // unload old alignment path
441 if( cdbManager->GetEntryCache()->Contains("MUON/Align/Data") )
442 { cdbManager->UnloadFromCache("MUON/Align/Data"); }
444 // load new alignment path
445 if( !fNewAlignStorage.IsNull() ) cdbManager->SetSpecificStorage("MUON/Align/Data",fNewAlignStorage.Data());
448 TString defaultStorage(cdbManager->GetDefaultStorage()->GetType());
449 if (defaultStorage == "alien") defaultStorage += Form("://folder=%s", cdbManager->GetDefaultStorage()->GetBaseFolder().Data());
450 else defaultStorage += Form("://%s", cdbManager->GetDefaultStorage()->GetBaseFolder().Data());
451 cdbManager->SetSpecificStorage("MUON/Align/Data",defaultStorage.Data());
455 // create new DB entry
456 AliCDBMetaData* cdbData = new AliCDBMetaData();
457 cdbData->SetResponsible("Dimuon Offline project");
458 cdbData->SetComment("MUON alignment objects with residual misalignment");
459 AliCDBId id("MUON/Align/Data", 0, AliCDBRunRange::Infinity());
460 cdbManager->Put(const_cast<TClonesArray*>(array), id, cdbData);
464 //________________________________________________________________________
465 void AliMUONAlignmentTask::NotifyRun()
468 /// run number (re)initialization
470 // propagate run number to fAlign
471 if( fAlign ) fAlign->SetRunNumber( fCurrentRunNumber );
474 if (fOCDBLoaded && fLoadOCDBOnce)
476 AliError(Form("OCDB already loaded %d %d",fOCDBLoaded,fLoadOCDBOnce));
480 AliCDBManager* cdbManager = AliCDBManager::Instance();
482 // Initialize default storage
483 if( !( cdbManager->IsDefaultStorageSet() || fDefaultStorage.IsNull() ) )
486 AliInfo( Form( "Initializing default storage: %s", fDefaultStorage.Data() ) );
487 cdbManager->SetDefaultStorage(fDefaultStorage.Data());
489 } else if( !fDefaultStorage.IsNull() ) {
491 AliInfo( "Default storage already set. Ignoring fDefaultStorage" );
495 AliInfo( "Default storage already set" );
499 // Initialize run number
500 if( cdbManager->GetRun() < 0 )
502 AliInfo( Form( "Setting run number: %i", fCurrentRunNumber ) );
503 cdbManager->SetRun(fCurrentRunNumber);
506 // following initialization is not needed when reading records
510 // load magnetic field if needed
511 if( !TGeoGlobalMagField::Instance()->IsLocked() )
514 AliInfo( "Loading magnetic field" );
515 if( !AliMUONCDB::LoadField() )
517 AliError( "Failed to load magnetic field" );
521 } else { AliInfo( "Magnetic field already locked" ); }
523 // checking magnitic field
526 AliInfo( "Reading magnetic field setup from GRP" );
528 // decide bFieldOn value base on dipole current
529 // propagete to Alignment class
531 AliMagF* magF = dynamic_cast<AliMagF*>( TGeoGlobalMagField::Instance()->GetField() );
532 fBFieldOn = TMath::Abs( magF->GetFactorDip() ) > 1e-5;
533 fAlign->SetBFieldOn( fBFieldOn );
534 AliInfo( Form( "Dipole magnetic field factor: %.2f", magF->GetFactorDip() ) );
535 AliInfo( Form( "fBFieldOn = %s", (fBFieldOn ? "kTRUE":"kFALSE") ) );
538 AliInfo( "Loading muon mapping" );
539 if( !AliMUONCDB::LoadMapping(kFALSE) )
541 AliError( "Failed to load muon mapping" );
545 AliInfo( "Assigning field to Track extrapolator" );
546 AliMUONTrackExtrap::SetField();
550 // load geometry if needed
551 if( !AliGeomManager::GetGeometry() )
554 // reset existing geometry/alignment if any
555 if( cdbManager->GetEntryCache()->Contains("GRP/Geometry/Data") )
557 AliInfo( "Unloading GRP/Geometry/Data" );
558 cdbManager->UnloadFromCache("GRP/Geometry/Data");
561 if( cdbManager->GetEntryCache()->Contains("MUON/Align/Data") )
563 AliInfo( Form( "Unloading MUON/Align/Data from %s", cdbManager->GetSpecificStorage( "MUON/Align/Data" )->GetBaseFolder().Data() ) );
564 cdbManager->UnloadFromCache("MUON/Align/Data");
567 // get original geometry transformer
568 AliInfo( "Loading geometry" );
569 AliGeomManager::LoadGeometry();
570 if (!AliGeomManager::GetGeometry())
572 AliError("Failed to load geometry");
576 if (!fOldAlignStorage.IsNull())
579 AliInfo( Form( "Initializing MUON/Align/Data using: %s", fOldAlignStorage.Data() ) );
580 cdbManager->SetSpecificStorage("MUON/Align/Data",fOldAlignStorage.Data());
584 // recover default storage full name (raw:// cannot be used to set specific storage)
585 TString defaultStorage(cdbManager->GetDefaultStorage()->GetType());
586 if (defaultStorage == "alien") defaultStorage += Form("://folder=%s", cdbManager->GetDefaultStorage()->GetBaseFolder().Data());
587 else defaultStorage += Form("://%s", cdbManager->GetDefaultStorage()->GetBaseFolder().Data());
589 AliInfo( Form( "Re-initializing MUON/Align/Data using: %s", defaultStorage.Data() ) );
590 cdbManager->SetSpecificStorage("MUON/Align/Data",defaultStorage.Data());
594 AliInfo("Loading muon Alignment objects");
595 AliGeomManager::ApplyAlignObjsFromCDB("MUON");
597 } else { AliInfo( "Geometry already initialized - fOldAlignStorage ignored" ); }
599 // update geometry transformer and pass to Alignment object
600 AliInfo("Loading muon geometry in transformer");
601 fOldGeoTransformer->LoadGeometryData();
602 fAlign->SetGeometryTransformer(fOldGeoTransformer);
608 //_____________________________________________________________________________________
609 void AliMUONAlignmentTask::SaveMisAlignmentData( AliMUONGeometryTransformer* transformer ) const
613 transformer->ClearMisAlignmentData();
615 // load MUON/Align/Data from OCDB
616 AliCDBManager* cdbManager = AliCDBManager::Instance();
617 AliCDBEntry* cdbEntry = cdbManager->Get( "MUON/Align/Data" );
621 AliError( "unable to load entry for path MUON/Align/Data" );
626 // get TClonesArray and check
627 TClonesArray* misArray = (TClonesArray*)cdbEntry->GetObject();
631 AliError( "unable to load old misalignment array" );
636 // loop over stored entries
637 for (Int_t index=0; index<misArray->GetEntriesFast(); ++index )
640 // load matrix and check
641 AliAlignObjMatrix* matrix = (AliAlignObjMatrix*) misArray->At( index );
644 AliError( Form( "unable to load matrix for index %i", index ) );
649 AliGeomManager::ELayerID layerId;
651 matrix->GetVolUID( layerId, moduleId);
653 // make sure ELayerID is correct
654 assert( layerId == AliGeomManager::kMUON );
657 // AliInfo( Form( "Found matrix for %s %i", matrix->GetSymName(), moduleId ) );
660 TGeoHMatrix misMatrix;
661 matrix->GetMatrix(misMatrix);
663 // add to geometry transformer
664 // need the detector element
665 // "detElement->GetId()"
666 // see fOldGeoTransformer->GetMisAlignmentData( ... )
668 if( TString( matrix->GetSymName() ).Contains( "DE" ) ) transformer->AddMisAlignDetElement( moduleId, misMatrix);
669 else transformer->AddMisAlignModule( moduleId, misMatrix);