ROOT logo
/**************************************************************************
 * 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.                  *
 **************************************************************************/

/* $Id$ */

/// \ingroup macros
/// \file MUONAlignment.C
/// \brief Macro for MUON alignment using physics tracks. 
///
/// The macro uses the AliMUONAlignment class to calculate the alignment parameters.
/// An array for the alignment parameters is created and can be filled with
/// initial values that will be used as starting values by the alignment
/// algorithm.
///
/// By default the macro run over galice.root in the working directory. If a file list
/// of galice.root is provided as third argument the macro will run over all files.
/// The macro loop over the files, events and tracks. For each track
/// AliMUONAlignment::ProcessTrack(AliMUONTrack * track) and then
/// AliMUONAlignment::LocalFit(Int_t iTrack, Double_t *lTrackParam, Int_t
/// lSingleFit) are called. After all tracks have been procesed and fitted
/// AliMUONAlignment::GlobalFit(Double_t *parameters,Double_t *errors,Double_t *pulls)
/// is called. The array parameters contains the obatained misalignement parameters.
/// A realigned geometry is generated in a local CDB.
///
/// \author: B. Becker and J. Castillo

#if !defined(__CINT__) || defined(__MAKECINT__)

#include "AliMUONAlignment.h"
#include "AliMUONTrack.h"
#include "AliMUONRecoParam.h"
#include "AliMUONTrackParam.h"
#include "AliMUONGeometryTransformer.h"
#include "AliMUONESDInterface.h"
#include "AliMUONCDB.h"

#include "AliESDEvent.h"
#include "AliESDMuonTrack.h"
#include "AliCDBManager.h"
#include "AliCDBMetaData.h"
#include "AliCDBId.h"
#include "AliGeomManager.h"

#include <TString.h>
#include <TError.h>
#include <TH1.h>
#include <TGraphErrors.h>
#include <TFile.h>
#include <TTree.h>
#include <TClonesArray.h>
#include <Riostream.h>

#include <fstream>

#endif

void MUONAlignment(Int_t nEvents = 100000, char* geoFilename = "geometry.root", TString esdFileName = "AliESDs.root", TString fileList = "")
{
 
  // Import TGeo geometry (needed by AliMUONTrackExtrap::ExtrapToVertex)
  if ( ! AliGeomManager::GetGeometry() ) {
    AliGeomManager::LoadGeometry(geoFilename);
    if (! AliGeomManager::GetGeometry() ) {
      Error("MUONAlignment", "getting geometry from file %s failed", geoFilename);
      return;
    }
  }
  
  // load necessary data from OCDB
  AliCDBManager* cdbManager = AliCDBManager::Instance();
  cdbManager->SetDefaultStorage("local://$ALICE_ROOT/OCDB");
  cdbManager->SetRun(0);
  if (!AliMUONCDB::LoadField()) return;
  AliMUONRecoParam* recoParam = AliMUONCDB::LoadRecoParam();
  if (!recoParam) return;
  
  // reset tracker for restoring initial track parameters at cluster
  AliMUONESDInterface::ResetTracker(recoParam);

  Double_t parameters[4*156];
  Double_t errors[4*156];
  Double_t pulls[4*156];
  for(Int_t k=0;k<4*156;k++) {
    parameters[k]=0.;
    errors[k]=0.;
    pulls[k]=0.;
  }

  Double_t trackParams[8] = {0.,0.,0.,0.,0.,0.,0.,0.};

  // Set initial values here, good guess may help convergence
  // St 1 
  //  Int_t iPar = 0;
  //  parameters[iPar++] =  0.010300 ;  parameters[iPar++] =  0.010600 ;  parameters[iPar++] =  0.000396 ;  

  bool bLoop = kFALSE;
  ifstream sFileList;
  if (fileList.Contains(".list")) {
    cout << "Reading file list: " << fileList.Data() << endl;
    bLoop = kTRUE;

    TString fullListName(".");
    fullListName +="/";
    fullListName +=fileList;
    sFileList.open(fileList.Data());
  }
  
  TH1F *fInvBenMom = new TH1F("fInvBenMom","fInvBenMom",200,-0.1,0.1); 
  TH1F *fBenMom = new TH1F("fBenMom","fBenMom",200,-40,40); 

  AliMUONAlignment* alig = new AliMUONAlignment();
  alig->InitGlobalParameters(parameters);

  AliMUONGeometryTransformer *transform = new AliMUONGeometryTransformer();
  transform->LoadGeometryData();
  alig->SetGeometryTransformer(transform);

  // Do alignment with magnetic field off
  alig->SetBFieldOn(kFALSE);
  
  // Set tracking station to use
  Bool_t bStOnOff[5] = {kTRUE,kTRUE,kTRUE,kTRUE,kTRUE};
  Bool_t bChOnOff[10] = {kTRUE,kTRUE,kTRUE,kTRUE,kTRUE,kTRUE,kTRUE,kTRUE,kTRUE,kTRUE};

  // Set degrees of freedom to align (see AliMUONAlignment)
  alig->AllowVariations(bChOnOff);

  // Fix parameters or add constraints here
//   for (Int_t iSt=0; iSt<5; iSt++)
//     if (!bStOnOff[iSt]) alig->FixStation(iSt+1);
  for (Int_t iCh=0; iCh<10; iCh++)
    if (!bChOnOff[iCh]) alig->FixChamber(iCh+1);

  // Left and right sides of the detector are independent, one can choose to align 
  // only one side
  Bool_t bSpecLROnOff[2] = {kTRUE,kTRUE};
  alig->FixHalfSpectrometer(bChOnOff,bSpecLROnOff);

  alig->SetChOnOff(bChOnOff);
  alig->SetSpecLROnOff(bChOnOff);

  // Here we can fix some detection elements
  alig->FixDetElem(908);
  alig->FixDetElem(1020);

  // Set predifined global constrains: X, Y, P, XvsZ, YvsZ, PvsZ, XvsY, YvsY, PvsY
  Bool_t bVarXYT[9] = {kTRUE,kTRUE,kTRUE,kTRUE,kTRUE,kTRUE,kTRUE,kTRUE,kTRUE};
  Bool_t bDetTLBR[4] = {kFALSE,kTRUE,kFALSE,kTRUE};
  //  alig->AddConstraints(bChOnOff,bVarXYT,bDetTLBR,bSpecLROnOff);


  char cFileName[100];  
    
  Int_t lMaxFile = 1000;
  Int_t iFile = 0;
  Int_t iEvent = 0;
  bool bKeepLoop = kTRUE;
  Int_t iTrackTot=0;
  Int_t iTrackOk=0;

  while(bKeepLoop && iFile<lMaxFile){
    iFile++;
    if (bLoop) {
      sFileList.getline(cFileName,100);
      if (sFileList.eof()) bKeepLoop = kFALSE;
    }
    else {
      sprintf(cFileName,esdFileName.Data());
      bKeepLoop = kFALSE;
    }
    if (!strstr(cFileName,"AliESDs")) continue;      
    cout << "Using file: " << cFileName << endl;
    
    // load ESD event
    TFile* esdFile = TFile::Open(cFileName); // open the file
    if (!esdFile || !esdFile->IsOpen()) {
      cout << "opening ESD file " << cFileName << "failed" << endl;
      continue;
    }
    TTree* esdTree = (TTree*) esdFile->Get("esdTree"); // get the tree
    if (!esdTree) {
      cout << "no ESD tree found" << endl;
      esdFile->Close();
      continue;
    }
    AliESDEvent* esdEvent = new AliESDEvent(); // link ESD event to the tree
    esdEvent->ReadFromTree(esdTree);

    Int_t nevents = esdTree->GetEntries();
    cout << "... with " << nevents << endl;
    for(Int_t event = 0; event < nevents; event++) {
      if (iEvent >= nEvents){
	bKeepLoop = kFALSE;
	break;
      }
      iEvent++;

      if (esdTree->GetEvent(event) <= 0) {
	cout << "fails to read ESD object for event " << event << endl;
	continue;
      }

      Int_t nTracks = Int_t(esdEvent->GetNumberOfMuonTracks());
      if (!event%100) cout << " there are " << nTracks << " tracks in event " << event << endl;
      for (Int_t iTrack = 0; iTrack < nTracks; iTrack++) {
	AliESDMuonTrack* esdTrack = esdEvent->GetMuonTrack(iTrack);
	if (!esdTrack->ContainTrackerData()) continue;
	Double_t invBenMom = esdTrack->GetInverseBendingMomentum();
	fInvBenMom->Fill(invBenMom);
	fBenMom->Fill(1./invBenMom);
	if (TMath::Abs(invBenMom)<=1.04) {
	  AliMUONTrack track;
	  AliMUONESDInterface::ESDToMUON(*esdTrack, track);
	  alig->ProcessTrack(&track);
	  alig->LocalFit(iTrackOk++,trackParams,0);
	}
	iTrackTot++;
      }
    }
    delete esdEvent;
    esdFile->Close();
    cout << "Processed " << iTrackTot << " Tracks so far." << endl;
  }
  alig->GlobalFit(parameters,errors,pulls);

  cout << "Done with GlobalFit " << endl;

  // Store results
  Double_t DEid[156] = {0};
  Double_t MSDEx[156] = {0};
  Double_t MSDEy[156] = {0};
  Double_t MSDEz[156] = {0};
  Double_t MSDEp[156] = {0};
  Double_t DEidErr[156] = {0};
  Double_t MSDExErr[156] = {0};
  Double_t MSDEyErr[156] = {0};
  Double_t MSDEzErr[156] = {0};
  Double_t MSDEpErr[156] = {0};
  Int_t lNDetElem = 4*2+4*2+18*2+26*2+26*2;
  Int_t lNDetElemCh[10] = {4,4,4,4,18,18,26,26,26,26};
  // Int_t lSNDetElemCh[10] = {4,8,12,16,34,52,78,104,130,156};
  Int_t idOffset = 0; // 400
  Int_t lSDetElemCh = 0;
  for(Int_t iDE=0; iDE<lNDetElem; iDE++){
    DEidErr[iDE] = 0.;
    DEid[iDE] = idOffset+100;
    DEid[iDE] += iDE; 
    lSDetElemCh = 0;
    for(Int_t iCh=0; iCh<9; iCh++){
      lSDetElemCh += lNDetElemCh[iCh];
      if (iDE>=lSDetElemCh) {
	DEid[iDE] += 100;
	DEid[iDE] -= lNDetElemCh[iCh];
      }
    }
    MSDEx[iDE]=parameters[4*iDE+0];
    MSDEy[iDE]=parameters[4*iDE+1];
    MSDEz[iDE]=parameters[4*iDE+3];
    MSDEp[iDE]=parameters[4*iDE+2];
    MSDExErr[iDE]=(Double_t)alig->GetParError(4*iDE+0);
    MSDEyErr[iDE]=(Double_t)alig->GetParError(4*iDE+1);
    MSDEzErr[iDE]=(Double_t)alig->GetParError(4*iDE+3);
    MSDEpErr[iDE]=(Double_t)alig->GetParError(4*iDE+2);
  }

  cout << "Let's create graphs ...  " << endl;

  TGraphErrors *gMSDEx = new TGraphErrors(lNDetElem,DEid,MSDEx,DEidErr,MSDExErr); 
  TGraphErrors *gMSDEy = new TGraphErrors(lNDetElem,DEid,MSDEy,DEidErr,MSDEyErr); 
  TGraphErrors *gMSDEz = new TGraphErrors(lNDetElem,DEid,MSDEz,DEidErr,MSDEzErr); 
  TGraphErrors *gMSDEp = new TGraphErrors(lNDetElem,DEid,MSDEp,DEidErr,MSDEpErr); 

  cout << "... graphs created, open file ...  " << endl;

  TFile *hFile = new TFile("measShifts.root","RECREATE");

  cout << "... file opened ...  " << endl;

  gMSDEx->Write("gMSDEx");
  gMSDEy->Write("gMSDEy");
  gMSDEz->Write("gMSDEz");
  gMSDEp->Write("gMSDEp");
  fInvBenMom->Write();
  fBenMom->Write();
  hFile->Close();
  
  cout << "... and closed!" << endl;
  // Re Align
  AliMUONGeometryTransformer *newTransform = alig->ReAlign(transform,parameters,true); 
  newTransform->WriteTransformations("transform2ReAlign.dat");
  
  // Generate realigned data in local cdb
  const TClonesArray* array = newTransform->GetMisAlignmentData();

  // 100 mum residual resolution for chamber misalignments?
  alig->SetAlignmentResolution(array,-1,0.01,0.01,0.004,0.003);

  cdbManager->SetSpecificStorage("MUON/Align/Data","local://ReAlignCDB");
  
  AliCDBMetaData* cdbData = new AliCDBMetaData();
  cdbData->SetResponsible("Dimuon Offline project");
  cdbData->SetComment("MUON alignment objects with residual misalignment");
  AliCDBId id("MUON/Align/Data", 0, AliCDBRunRange::Infinity()); 
  cdbManager->Put(const_cast<TClonesArray*>(array), id, cdbData);

}

 MUONAlignment.C:1
 MUONAlignment.C:2
 MUONAlignment.C:3
 MUONAlignment.C:4
 MUONAlignment.C:5
 MUONAlignment.C:6
 MUONAlignment.C:7
 MUONAlignment.C:8
 MUONAlignment.C:9
 MUONAlignment.C:10
 MUONAlignment.C:11
 MUONAlignment.C:12
 MUONAlignment.C:13
 MUONAlignment.C:14
 MUONAlignment.C:15
 MUONAlignment.C:16
 MUONAlignment.C:17
 MUONAlignment.C:18
 MUONAlignment.C:19
 MUONAlignment.C:20
 MUONAlignment.C:21
 MUONAlignment.C:22
 MUONAlignment.C:23
 MUONAlignment.C:24
 MUONAlignment.C:25
 MUONAlignment.C:26
 MUONAlignment.C:27
 MUONAlignment.C:28
 MUONAlignment.C:29
 MUONAlignment.C:30
 MUONAlignment.C:31
 MUONAlignment.C:32
 MUONAlignment.C:33
 MUONAlignment.C:34
 MUONAlignment.C:35
 MUONAlignment.C:36
 MUONAlignment.C:37
 MUONAlignment.C:38
 MUONAlignment.C:39
 MUONAlignment.C:40
 MUONAlignment.C:41
 MUONAlignment.C:42
 MUONAlignment.C:43
 MUONAlignment.C:44
 MUONAlignment.C:45
 MUONAlignment.C:46
 MUONAlignment.C:47
 MUONAlignment.C:48
 MUONAlignment.C:49
 MUONAlignment.C:50
 MUONAlignment.C:51
 MUONAlignment.C:52
 MUONAlignment.C:53
 MUONAlignment.C:54
 MUONAlignment.C:55
 MUONAlignment.C:56
 MUONAlignment.C:57
 MUONAlignment.C:58
 MUONAlignment.C:59
 MUONAlignment.C:60
 MUONAlignment.C:61
 MUONAlignment.C:62
 MUONAlignment.C:63
 MUONAlignment.C:64
 MUONAlignment.C:65
 MUONAlignment.C:66
 MUONAlignment.C:67
 MUONAlignment.C:68
 MUONAlignment.C:69
 MUONAlignment.C:70
 MUONAlignment.C:71
 MUONAlignment.C:72
 MUONAlignment.C:73
 MUONAlignment.C:74
 MUONAlignment.C:75
 MUONAlignment.C:76
 MUONAlignment.C:77
 MUONAlignment.C:78
 MUONAlignment.C:79
 MUONAlignment.C:80
 MUONAlignment.C:81
 MUONAlignment.C:82
 MUONAlignment.C:83
 MUONAlignment.C:84
 MUONAlignment.C:85
 MUONAlignment.C:86
 MUONAlignment.C:87
 MUONAlignment.C:88
 MUONAlignment.C:89
 MUONAlignment.C:90
 MUONAlignment.C:91
 MUONAlignment.C:92
 MUONAlignment.C:93
 MUONAlignment.C:94
 MUONAlignment.C:95
 MUONAlignment.C:96
 MUONAlignment.C:97
 MUONAlignment.C:98
 MUONAlignment.C:99
 MUONAlignment.C:100
 MUONAlignment.C:101
 MUONAlignment.C:102
 MUONAlignment.C:103
 MUONAlignment.C:104
 MUONAlignment.C:105
 MUONAlignment.C:106
 MUONAlignment.C:107
 MUONAlignment.C:108
 MUONAlignment.C:109
 MUONAlignment.C:110
 MUONAlignment.C:111
 MUONAlignment.C:112
 MUONAlignment.C:113
 MUONAlignment.C:114
 MUONAlignment.C:115
 MUONAlignment.C:116
 MUONAlignment.C:117
 MUONAlignment.C:118
 MUONAlignment.C:119
 MUONAlignment.C:120
 MUONAlignment.C:121
 MUONAlignment.C:122
 MUONAlignment.C:123
 MUONAlignment.C:124
 MUONAlignment.C:125
 MUONAlignment.C:126
 MUONAlignment.C:127
 MUONAlignment.C:128
 MUONAlignment.C:129
 MUONAlignment.C:130
 MUONAlignment.C:131
 MUONAlignment.C:132
 MUONAlignment.C:133
 MUONAlignment.C:134
 MUONAlignment.C:135
 MUONAlignment.C:136
 MUONAlignment.C:137
 MUONAlignment.C:138
 MUONAlignment.C:139
 MUONAlignment.C:140
 MUONAlignment.C:141
 MUONAlignment.C:142
 MUONAlignment.C:143
 MUONAlignment.C:144
 MUONAlignment.C:145
 MUONAlignment.C:146
 MUONAlignment.C:147
 MUONAlignment.C:148
 MUONAlignment.C:149
 MUONAlignment.C:150
 MUONAlignment.C:151
 MUONAlignment.C:152
 MUONAlignment.C:153
 MUONAlignment.C:154
 MUONAlignment.C:155
 MUONAlignment.C:156
 MUONAlignment.C:157
 MUONAlignment.C:158
 MUONAlignment.C:159
 MUONAlignment.C:160
 MUONAlignment.C:161
 MUONAlignment.C:162
 MUONAlignment.C:163
 MUONAlignment.C:164
 MUONAlignment.C:165
 MUONAlignment.C:166
 MUONAlignment.C:167
 MUONAlignment.C:168
 MUONAlignment.C:169
 MUONAlignment.C:170
 MUONAlignment.C:171
 MUONAlignment.C:172
 MUONAlignment.C:173
 MUONAlignment.C:174
 MUONAlignment.C:175
 MUONAlignment.C:176
 MUONAlignment.C:177
 MUONAlignment.C:178
 MUONAlignment.C:179
 MUONAlignment.C:180
 MUONAlignment.C:181
 MUONAlignment.C:182
 MUONAlignment.C:183
 MUONAlignment.C:184
 MUONAlignment.C:185
 MUONAlignment.C:186
 MUONAlignment.C:187
 MUONAlignment.C:188
 MUONAlignment.C:189
 MUONAlignment.C:190
 MUONAlignment.C:191
 MUONAlignment.C:192
 MUONAlignment.C:193
 MUONAlignment.C:194
 MUONAlignment.C:195
 MUONAlignment.C:196
 MUONAlignment.C:197
 MUONAlignment.C:198
 MUONAlignment.C:199
 MUONAlignment.C:200
 MUONAlignment.C:201
 MUONAlignment.C:202
 MUONAlignment.C:203
 MUONAlignment.C:204
 MUONAlignment.C:205
 MUONAlignment.C:206
 MUONAlignment.C:207
 MUONAlignment.C:208
 MUONAlignment.C:209
 MUONAlignment.C:210
 MUONAlignment.C:211
 MUONAlignment.C:212
 MUONAlignment.C:213
 MUONAlignment.C:214
 MUONAlignment.C:215
 MUONAlignment.C:216
 MUONAlignment.C:217
 MUONAlignment.C:218
 MUONAlignment.C:219
 MUONAlignment.C:220
 MUONAlignment.C:221
 MUONAlignment.C:222
 MUONAlignment.C:223
 MUONAlignment.C:224
 MUONAlignment.C:225
 MUONAlignment.C:226
 MUONAlignment.C:227
 MUONAlignment.C:228
 MUONAlignment.C:229
 MUONAlignment.C:230
 MUONAlignment.C:231
 MUONAlignment.C:232
 MUONAlignment.C:233
 MUONAlignment.C:234
 MUONAlignment.C:235
 MUONAlignment.C:236
 MUONAlignment.C:237
 MUONAlignment.C:238
 MUONAlignment.C:239
 MUONAlignment.C:240
 MUONAlignment.C:241
 MUONAlignment.C:242
 MUONAlignment.C:243
 MUONAlignment.C:244
 MUONAlignment.C:245
 MUONAlignment.C:246
 MUONAlignment.C:247
 MUONAlignment.C:248
 MUONAlignment.C:249
 MUONAlignment.C:250
 MUONAlignment.C:251
 MUONAlignment.C:252
 MUONAlignment.C:253
 MUONAlignment.C:254
 MUONAlignment.C:255
 MUONAlignment.C:256
 MUONAlignment.C:257
 MUONAlignment.C:258
 MUONAlignment.C:259
 MUONAlignment.C:260
 MUONAlignment.C:261
 MUONAlignment.C:262
 MUONAlignment.C:263
 MUONAlignment.C:264
 MUONAlignment.C:265
 MUONAlignment.C:266
 MUONAlignment.C:267
 MUONAlignment.C:268
 MUONAlignment.C:269
 MUONAlignment.C:270
 MUONAlignment.C:271
 MUONAlignment.C:272
 MUONAlignment.C:273
 MUONAlignment.C:274
 MUONAlignment.C:275
 MUONAlignment.C:276
 MUONAlignment.C:277
 MUONAlignment.C:278
 MUONAlignment.C:279
 MUONAlignment.C:280
 MUONAlignment.C:281
 MUONAlignment.C:282
 MUONAlignment.C:283
 MUONAlignment.C:284
 MUONAlignment.C:285
 MUONAlignment.C:286
 MUONAlignment.C:287
 MUONAlignment.C:288
 MUONAlignment.C:289
 MUONAlignment.C:290
 MUONAlignment.C:291
 MUONAlignment.C:292
 MUONAlignment.C:293
 MUONAlignment.C:294
 MUONAlignment.C:295
 MUONAlignment.C:296
 MUONAlignment.C:297
 MUONAlignment.C:298
 MUONAlignment.C:299
 MUONAlignment.C:300
 MUONAlignment.C:301
 MUONAlignment.C:302
 MUONAlignment.C:303
 MUONAlignment.C:304
 MUONAlignment.C:305
 MUONAlignment.C:306
 MUONAlignment.C:307
 MUONAlignment.C:308
 MUONAlignment.C:309
 MUONAlignment.C:310
 MUONAlignment.C:311
 MUONAlignment.C:312
 MUONAlignment.C:313
 MUONAlignment.C:314
 MUONAlignment.C:315
 MUONAlignment.C:316
 MUONAlignment.C:317
 MUONAlignment.C:318
 MUONAlignment.C:319
 MUONAlignment.C:320