ROOT logo
/**************************************************************************
 * This file is property of and copyright by the ALICE HLT Project        * 
 * All rights reserved.                                                   *
 *                                                                        *
 * Primary Authors:                                                       *
 *   Artur Szostak <artursz@iafrica.com>                                  *
 *                                                                        *
 * 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.                  *
 **************************************************************************/

// Simple macro to generate N-tuple for performance analysis.
// This macro must be compiled and run like so from within the aliroot command
// prompt:
//   root [0] gSystem->Load("libAliHLTMUON.so");
//   root [0] .x MakeHitsTable.C+

#include "TVector3.h"
#include "TSystem.h"
#include "TROOT.h"
#include "TParticle.h"
#include "TArrayF.h"
#include "TStopwatch.h"
#include "TNtuple.h"
#include "TFile.h"
#include "TError.h"

#include "AliCDBManager.h"
#include "AliLoader.h"
#include "AliRunLoader.h"
#include "AliStack.h"
#include "AliRun.h"
#include "AliMUON.h"
#include "AliMUONMCDataInterface.h"
#include "AliMUONHit.h"
#include "AliHLTMUONEvent.h"
#include "AliHLTMUONRootifierComponent.h"
#include "AliHLTMUONRecHit.h"
#include "AliHLTMUONTriggerRecord.h"

#include <cstdlib>
#include <vector>
#include <iostream>
using std::cout;
using std::cerr;
using std::endl;


void MakeHitsTable(
		Int_t firstEvent = 0,
		Int_t lastEvent = -1,
		const char* dHLToutputfile = "output.root",
		Float_t maxSigma = 4., // 4 standard deviations
		Float_t sigmaX = 0.1,  // 1 mm resolution
		Float_t sigmaY = 0.01, // 100 micron resolution
		Float_t sigmaZ = 0.02,  // 200 microns resolution
		Float_t sigmaXtrg = 0.5,  // 5 mm resolution
		Float_t sigmaYtrg = 0.5,  // 5 mm resolution
		Float_t sigmaZtrg = 0.02  // 2 microns resolution
	)
{
	// Setup the CDB default storage and run number if nothing was set.
	AliCDBManager* cdbManager = AliCDBManager::Instance();
	if (cdbManager == NULL)
	{
		cerr << "ERROR: Global CDB manager object does not exist." << endl;
		return;
	}
	if (cdbManager->GetDefaultStorage() == NULL)
	{
		cdbManager->SetDefaultStorage("local://$ALICE_ROOT/OCDB");
	}
	if (cdbManager->GetRun() == -1)
	{
		cdbManager->SetRun(0);
	}
	
	gSystem->Load("libAliHLTMUON.so");
	// Must pree load libAliHLTMUON.so before loading this macro and running it in compiled mode.

	TString fieldnames = "event:isprimary:pdgcode:detelem:chamber:x:y:z:dHLTx:dHLTy:dHLTz";
	TNtuple* table = new TNtuple("hittable", "Table of hits.", fieldnames);
	
	TFile dHLTfile(dHLToutputfile, "READ");

	AliMUONMCDataInterface data;
	AliStack* stack;
	
	Int_t nEvents = data.NumberOfEvents();
	if (lastEvent < 0) lastEvent = nEvents-1;
	for (Int_t event = firstEvent; event <= lastEvent; event++)
	{
		cout << "Processing event: " << event;
		
		char buf[1024];
		char* str = &buf[0];
		sprintf(str, "AliHLTMUONEvent;%d", event+1);
		AliHLTMUONEvent* dHLTevent = dynamic_cast<AliHLTMUONEvent*>( dHLTfile.Get(str) );
		if (dHLTevent == NULL)
		{
			cout << endl;
			cerr << "ERROR: Could not find " << str << " in " << dHLToutputfile << endl;
			continue;
		}
		
		data.GetEvent(event);
		
		stack = data.Stack(event);
		if (stack == NULL)
		{
			cout << endl;
			cerr << "ERROR: Stack is NULL" << endl;
			continue;
		}
		
		Int_t trackcount = data.NumberOfParticles();
		cout << "\ttrackcount = " << trackcount << endl;
		
		TArrayF isPrimary(trackcount);
		TArrayF pdgcode(trackcount);
		
		//cout << "Fill particle data" << endl;
		for (Int_t i = 0; i < trackcount; i++)
		{
			TParticle* p = data.Particle(i);
			isPrimary[i] = stack->IsPhysicalPrimary(i) ? 1 : 0;
			pdgcode[i] = p->GetPdgCode();
		}
		
		TArrayF detElem[14];
		TArrayF chamberNum[14];
		TArrayF hitX[14];
		TArrayF hitY[14];
		TArrayF hitZ[14];
		TArrayF dHLThitX[14];
		TArrayF dHLThitY[14];
		TArrayF dHLThitZ[14];
		for (Int_t i = 0; i < 14; i++)
		{
			detElem[i].Set(trackcount);
			chamberNum[i].Set(trackcount);
			hitX[i].Set(trackcount);
			hitY[i].Set(trackcount);
			hitZ[i].Set(trackcount);
			dHLThitX[i].Set(trackcount);
			dHLThitY[i].Set(trackcount);
			dHLThitZ[i].Set(trackcount);
			for (Int_t j = 0; j < trackcount; j++)
			{
				detElem[i][j] = 0;
				chamberNum[i][j] = 0;
				hitX[i][j] = 0;
				hitY[i][j] = 0;
				hitZ[i][j] = 0;
				dHLThitX[i][j] = 0;
				dHLThitY[i][j] = 0;
				dHLThitZ[i][j] = 0;
			}
		}

		//cout << "Fill hits" << endl;
		for (Int_t i = 0; i < data.NumberOfTracks(); i++)
		for (Int_t j = 0; j < data.NumberOfHits(i); j++)
		{
			AliMUONHit* hit = data.Hit(i, j);
			Int_t chamber = hit->Chamber() - 1;
			if (chamber < 0 || chamber >= 14)
			{
				cerr << "ERROR: Chamber number " << chamber << " is out of range." << endl;
				continue;
			}
			
			//cout << "hit->Track() = " << hit->Track() << endl;
			if (hit->Track() < 0 || hit->Track() >= trackcount)
			{
				cerr << "ERROR: Track number " << hit->Track() << " is out of range. [0.."
					<< trackcount << ")" << endl;
				continue;
			}
			Int_t particleindex = hit->Track();

			detElem[chamber][particleindex] = hit->DetElemId();
			chamberNum[chamber][particleindex] = hit->Chamber();
			hitX[chamber][particleindex] = hit->X();
			hitY[chamber][particleindex] = hit->Y();
			hitZ[chamber][particleindex] = hit->Z();
		} // hits loop
		
		for (Int_t i = 0; i < dHLTevent->Array().GetEntriesFast(); i++)
		{
			if (dHLTevent->Array().At(i)->IsA() != AliHLTMUONRecHit::Class())
				continue;
			AliHLTMUONRecHit* hit = static_cast<AliHLTMUONRecHit*>(dHLTevent->Array().At(i));
			
			// Find the best fitting hit.
			Double_t bestFitQuality = 1e30;
			Int_t bestFitTrack = -1;
			Int_t bestFitCh = -1;
			for (Int_t ti = 0; ti < trackcount; ti++)
			for (Int_t ch = 0; ch < 14; ch++)
			{
				if (hit->Coordinate() == TVector3(0,0,0)) continue;
				if (hitX[ch][ti] == 0 && hitY[ch][ti] == 0 && hitZ[ch][ti] == 0)
					continue;
				TVector3 hV(hitX[ch][ti], hitY[ch][ti], hitZ[ch][ti]);
				TVector3 diff = hV - hit->Coordinate();
				Double_t diffX = diff.X() / sigmaX;
				Double_t diffY = diff.Y() / sigmaY;
				Double_t diffZ = diff.Z() / sigmaZ;
				if (diffX > maxSigma) continue;
				if (diffY > maxSigma) continue;
				if (diffZ > maxSigma) continue;
				Double_t fitQuality = diffX*diffX + diffY*diffY + diffZ*diffZ;

				// Now check the fit quality.
				if (fitQuality < bestFitQuality)
				{
					bestFitQuality = fitQuality;
					bestFitTrack = ti;
					bestFitCh = ch;
				}
			}
			
			if (bestFitTrack < 0 || bestFitCh < 0)
			{
				// No hit was matched so we need to add a fake hit.
				table->Fill(event, -1, 0, -1, -1, 0, 0, 0, hit->X(), hit->Y(), hit->Z());
			}
			else
			{
				// Fill the details about the dHLT track to the best fitting track info.
				dHLThitX[bestFitCh][bestFitTrack] = hit->X();
				dHLThitY[bestFitCh][bestFitTrack] = hit->Y();
				dHLThitZ[bestFitCh][bestFitTrack] = hit->Z();
			}
		}
		
		for (Int_t i = 0; i < dHLTevent->Array().GetEntriesFast(); i++)
		{
			if (dHLTevent->Array().At(i)->IsA() != AliHLTMUONTriggerRecord::Class())
				continue;
			AliHLTMUONTriggerRecord* trigrec = static_cast<AliHLTMUONTriggerRecord*>(dHLTevent->Array().At(i));
			
			for (Int_t n = 11; n <= 14; n++)
			{
				const TVector3& hit = trigrec->Hit(n);
				if (hit == TVector3(0,0,0)) continue;
				Int_t ch = n-1;
				
				// Find the best fitting hit.
				Double_t bestFitQuality = 1e30;
				Int_t bestFitTrack = -1;
				Int_t bestFitCh = -1;
				for (Int_t ti = 0; ti < trackcount; ti++)
				{
					if (hit == TVector3(0,0,0)) continue;
					if (hitX[ch][ti] == 0 && hitY[ch][ti] == 0 && hitZ[ch][ti] == 0)
						continue;
					TVector3 hV(hitX[ch][ti], hitY[ch][ti], hitZ[ch][ti]);
					TVector3 diff = hV - hit;
					Double_t diffX = diff.X() / sigmaXtrg;
					Double_t diffY = diff.Y() / sigmaYtrg;
					Double_t diffZ = diff.Z() / sigmaZtrg;
					if (diffX > maxSigma) continue;
					if (diffY > maxSigma) continue;
					if (diffZ > maxSigma) continue;
					Double_t fitQuality = diffX*diffX + diffY*diffY + diffZ*diffZ;

					// Now check the fit quality.
					if (fitQuality < bestFitQuality)
					{
						bestFitQuality = fitQuality;
						bestFitTrack = ti;
						bestFitCh = ch;
					}
				}
				
				if (bestFitTrack < 0 || bestFitCh < 0)
				{
					// No hit was matched so we need to add a fake hit.
					table->Fill(event, -1, 0, -1, -1, 0, 0, 0, hit.X(), hit.Y(), hit.Z());
				}
				else
				{
					// Fill the details about the dHLT track to the best fitting track info.
					dHLThitX[bestFitCh][bestFitTrack] = hit.X();
					dHLThitY[bestFitCh][bestFitTrack] = hit.Y();
					dHLThitZ[bestFitCh][bestFitTrack] = hit.Z();
				}
			}
		}
		
		//cout << "Fill table" << endl;
		for (Int_t i = 0; i < trackcount; i++)
		for (Int_t j = 0; j < 14; j++)
		{
			//event:isprimary::pdgcode:detelem:chamber:x:y:z:dHLTx:dHLTy:dHLTz
			table->Fill(
					event,
					isPrimary[i],
					pdgcode[i],
					detElem[j][i],
					chamberNum[j][i],
					hitX[j][i],
					hitY[j][i],
					hitZ[j][i],
					dHLThitX[j][i],
					dHLThitY[j][i],
					dHLThitZ[j][i]
				);
		}
		
	} // event loop

	TFile file("hittable.root", "RECREATE");
	file.cd();
	table->Write(table->GetName(), TObject::kOverwrite);

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