--- /dev/null
+// $Id$
+//**************************************************************************
+//* This file is property of and copyright by the ALICE HLT Project *
+//* ALICE Experiment at CERN, All rights reserved. *
+//* *
+//* Primary Authors: Matthias Richter <Matthias.Richter@ift.uib.no> *
+//* Jochen Thaeder <jochen@thaeder.de> *
+//* for The ALICE HLT Project. *
+//* *
+//* 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. *
+//**************************************************************************
+
+/// @file AliHLTTRDTriggerComponent.cxx
+/// @author Felix Rettig, Stefan Kirsch
+/// @date 2012-08-16
+/// @brief
+
+#include <cstdlib>
+#include "TSystem.h"
+#include "TObjArray.h"
+#include "TObjString.h"
+#include "TFile.h"
+#include "TH1I.h"
+#include "TH2I.h"
+#include "AliESDtrack.h"
+#include "AliESDEvent.h"
+#include "AliHLTTRDDefinitions.h"
+#include "AliHLTTriggerDecision.h"
+#include "AliHLTDomainEntry.h"
+#include "AliHLTLogging.h"
+#include "AliHLTErrorGuard.h"
+#include "AliHLTGlobalBarrelTrack.h"
+#include "AliESDtrackCuts.h"
+//#include "AliHLTESDTrackCuts.h"
+#include "AliGeomManager.h"
+#include "AliHLTComponentBenchmark.h"
+#include "AliHLTTRDTriggerComponent.h"
+#include "AliTRDonlineTrackingDataContainer.h"
+#include "AliTRDpadPlane.h"
+
+ClassImp(AliHLTTRDTriggerComponent)
+
+#define LogError( ... ) { HLTError(__VA_ARGS__); if (fDebugLevel >= 1) { DbgLog("ERROR", __VA_ARGS__); } }
+#define LogInfo( ... ) { HLTInfo(__VA_ARGS__); if (fDebugLevel >= 1) { DbgLog("INFO", __VA_ARGS__); } }
+#define LogInspect( ... ) { HLTDebug(__VA_ARGS__); if (fDebugLevel >= 1) { DbgLog("INSPECT", __VA_ARGS__); } }
+#define LogDebug( ... ) { if (fDebugLevel >= 1) { HLTInfo(__VA_ARGS__); DbgLog("DEBUG", __VA_ARGS__); } }
+
+AliHLTTRDTriggerComponent::AliHLTTRDTriggerComponent() :
+ AliHLTTrigger(),
+ fName(),
+ fRefTrackSelectionEtaLimit(0.9),
+ fRefTrackSelectionVertexXYLimit(20.),
+ fRefTrackSelectionVertexZLimit(30.),
+ fRefTrackSelectionPtThreshold(0.7),
+ fMatchRatingThreshold(0.25),
+ fElectronTriggerPtThresholdHSE(3.),
+ fElectronTriggerPIDThresholdHSE(144),
+ fElectronTriggerPtThresholdHQU(2.),
+ fElectronTriggerPIDThresholdHQU(164),
+ fApplyRefTrackCuts(kFALSE),
+ fElectronTriggerOnL1TrgOnly(kFALSE),
+ fHistoMode(1),
+ fDebugLevel(0),
+ fExtendedHistos(kFALSE),
+ fEventRendering(kFALSE),
+ fPushHistos(kFALSE),
+ fWriteHistos(kFALSE),
+ fEventId(fgkInvalidEventId),
+ fRunNumber(-1),
+ fChunkId(NULL),
+ fSectorsWithData(0),
+ fIsMinBiasEvent(kFALSE),
+ fIsTRDElectronEvent(kFALSE),
+ fESDtracksPresent(kFALSE),
+ fHLTtracksPresent(kFALSE),
+ fTRDGeometry(NULL),
+ fEsdEvent(NULL),
+ fTrackingData(NULL),
+ fHLTTracks(NULL),
+ fRefTrackCuts(NULL),
+#ifdef __TRDHLTDEBUG
+ fEventDisplay(NULL),
+ fBenchmark(NULL),
+#endif
+ fHistArray(NULL),
+ fHistMatchRating(NULL),
+ fHistMatchRatingByPt(NULL),
+ fHistMatchRatingByPid(NULL),
+ fHistTrackPt(NULL),
+ fHistTrackPtMatched(NULL),
+ fHistTrackPtCorr(NULL),
+ fHistTrackPid(NULL),
+ fHistTrackPidMatched(NULL),
+ fHistElectronCandidatePt(NULL),
+ fHistElectronCandidateMatchedPt(NULL),
+ fHistElectronCandidatePid(NULL),
+ fHistElectronCandidateMatchedPid(NULL),
+ fHistRefTrackPid(NULL),
+ fHistMatchedRefTrackPid(NULL),
+ fHistPIDvsTruncPID(NULL),
+ fHistElectronFalsePIDvsTruncPID(NULL),
+ fHistElectronConfirmedPIDvsTruncPID(NULL),
+ fHistTrackMatchingCombinations(NULL),
+ fHistElectronTriggerBaseMinBias(NULL),
+ fHistElectronTriggerBaseTrdL1(NULL)
+{
+}
+
+const char* AliHLTTRDTriggerComponent::fgkDefaultOCDBEntry = "HLT/ConfigHLT/TRDTrigger";
+const char* AliHLTTRDTriggerComponent::fgkTriggerDecisionElectronHSE = "TRD-ELECTRON-HSE";
+const char* AliHLTTRDTriggerComponent::fgkTriggerDecisionElectronHQU = "TRD-ELECTRON-HQU";
+
+AliHLTTRDTriggerComponent::~AliHLTTRDTriggerComponent()
+{
+}
+
+const char* AliHLTTRDTriggerComponent::GetTriggerName() const
+{
+ if (!fName.IsNull())
+ return fName.Data();
+ else
+ return "TRDTriggerComponent";
+}
+
+AliHLTComponent* AliHLTTRDTriggerComponent::Spawn()
+{
+ return new AliHLTTRDTriggerComponent;
+}
+
+int AliHLTTRDTriggerComponent::DoInit(int argc, const char** argv)
+{
+ int iResult = 0;
+
+ do {
+
+ fChunkId = new TString("XXXXX");
+#ifdef __TRDHLTDEBUG
+ if (fChunkId){
+ // chunk identification for debug output
+ *fChunkId = gSystem->WorkingDirectory();
+ fChunkId->Remove(0, fChunkId->Last('/') + 1);
+ if (fChunkId->Contains("hlt_trd_comp"))
+ *fChunkId = "L";
+ } else {
+ iResult = -ENOMEM;
+ break;
+ }
+#endif
+
+ AliGeomManager::LoadGeometry();
+
+ fTRDGeometry = new AliTRDgeometry();
+ if (!fTRDGeometry) {
+ iResult = -ENOMEM;
+ break;
+ }
+
+ fTrackingData = new AliTRDonlineTrackingDataContainer();
+ if (!fTrackingData) {
+ iResult = -ENOMEM;
+ break;
+ }
+
+ fHLTTracks = new vector<AliHLTGlobalBarrelTrack>;
+ if (!fHLTTracks) {
+ iResult = -ENOMEM;
+ break;
+ }
+
+ fRefTrackCuts = new AliESDtrackCuts("AliESDtrackCuts", "No track cuts");
+ if (fRefTrackCuts){
+ // fRefTrackCuts = AliESDtrackCuts::GetStandardITSTPCTrackCuts2011(kTRUE, 0);
+ fRefTrackCuts = AliESDtrackCuts::GetStandardTPCOnlyTrackCuts();
+ fRefTrackCuts->SetEtaRange(-0.8, 0.8);
+ } else {
+ iResult = -ENOMEM;
+ break;
+ }
+
+ fHistArray = new TObjArray(25);
+ if(!fHistArray)
+ return -ENOMEM;
+ fHistArray->SetOwner(kTRUE);
+
+ fHistMatchRating = new TH1I("trdtrg_match_rating", "Match rating distribution HLT tracks vs. GTU track;match rating;abundance;",
+ 1./0.02, 0., 1.);
+ fHistArray->AddLast(fHistMatchRating);
+
+ fHistMatchRatingByPt = new TH2I("trdtrg_match_rating_pt", "Match rating distribution HLT tracks vs. GTU track by p_{T};match rating m;p_{T}^{TRD,online} (GeV/c)",
+ 1./0.02, 0., 1., 20./0.02, 0., 20.);
+ fHistArray->AddLast(fHistMatchRatingByPt);
+
+ fHistMatchRatingByPid = new TH2I("trdtrg_match_rating_pid", "Match rating distribution HLT tracks vs. GTU track by PID;match rating m;PID (a.u.)",
+ 1./0.02, 0., 1., 256, 0, 256);
+ fHistArray->AddLast(fHistMatchRatingByPid);
+
+ fHistTrackPt = new TH1I("trdtrg_track_pt", "GTU track p_{T};GTU track p_{T} (GeV/c);abundance", 200, -20, 20.);
+ fHistArray->AddLast(fHistTrackPt);
+
+ fHistTrackPtMatched = new TH1I("trdtrg_matched_track_pt", "matched GTU track p_{T};GTU track p_{T} (GeV/c);abundance", 200, -20, 20.);
+ fHistArray->AddLast(fHistTrackPtMatched);
+
+ fHistTrackPtCorr = new TH2I("trdtrg_track_pt_corr", "HLT vs. GTU track p_{T};p_{T}^{HLT} (GeV/c);p_{T}^{GTU} (GeV/c)",
+ 400, -40., 40., 400, -40., 40.);
+ fHistArray->AddLast(fHistTrackPtCorr);
+
+ fHistTrackPid = new TH1I("trdtrg_track_pid", "GTU track PID;GTU track PID (a.u.);abundance", 256, 0, 256);
+ fHistArray->AddLast(fHistTrackPid);
+
+ fHistTrackPidMatched = new TH1I("trdtrg_matched_track_pid", "matched GTU track PID;GTU track PID (a.u.);abundance", 256, 0, 256);
+ fHistArray->AddLast(fHistTrackPidMatched);
+
+ fHistTrackMatchingCombinations = new TH2I("trdtrg_matching_combinations", "HLT-GTU track matching combinations;set;combinations to check;",
+ 10, 0, 10, 2000, 0, 10000);
+ fHistArray->AddLast(fHistTrackMatchingCombinations);
+
+ fHistElectronTriggerBaseMinBias = new TH1I("trdtrg_electron_trigger_base_mb", "min. bias base numbers for electron trigger analysis;set;abundance;",
+ 10, 0, 10);
+ fHistElectronTriggerBaseMinBias->GetXaxis()->SetBinLabel(1, "min. bias events");
+ fHistElectronTriggerBaseMinBias->GetXaxis()->SetBinLabel(2, "TRD L1 electron triggered");
+ fHistElectronTriggerBaseMinBias->GetXaxis()->SetBinLabel(3, "TRD HLT electron triggered");
+ fHistArray->AddLast(fHistElectronTriggerBaseMinBias);
+
+ fHistElectronTriggerBaseTrdL1 = new TH1I("trdtrg_electron_trigger_base_l1", "TRD L1 base numbers for electron trigger analysis;set;abundance;",
+ 10, 0, 10);
+ fHistElectronTriggerBaseTrdL1->GetXaxis()->SetBinLabel(1, "TRD L1 electron triggered");
+ fHistElectronTriggerBaseTrdL1->GetXaxis()->SetBinLabel(2, "TRD HLT electron triggered");
+ fHistArray->AddLast(fHistElectronTriggerBaseTrdL1);
+
+ fHistElectronCandidatePt = new TH1I("trdtrg_electron_candidate_pt", "GTU electron candidate p_{T};GTU track p_{T} (GeV/c);abundance", 200, -20, 20.);
+ fHistArray->AddLast(fHistElectronCandidatePt);
+
+ fHistElectronCandidateMatchedPt = new TH1I("trdtrg_electron_candidate_matched_pt", "matching GTU electron candidate p_{T};GTU track p_{T} (GeV/c);abundance", 200, -20, 20.);
+ fHistArray->AddLast(fHistElectronCandidateMatchedPt);
+
+ fHistElectronCandidatePid = new TH1I("trdtrg_electron_candidate_pid", "GTU electron candidate PID;GTU track PID (a.u.);abundance", 256, 0, 256);
+ fHistArray->AddLast(fHistElectronCandidatePid);
+
+ fHistElectronCandidateMatchedPid = new TH1I("trdtrg_electron_candidate_matched_pid", "matching GTU electron candidate PID;GTU track PID (a.u.);abundance", 256, 0, 256);
+ fHistArray->AddLast(fHistElectronCandidateMatchedPid);
+
+ } while (0);
+
+ if (iResult < 0){
+
+ if (fHistArray) delete fHistArray;
+ fHistArray = NULL;
+
+ if (fTRDGeometry) delete fTRDGeometry;
+ fTRDGeometry = NULL;
+
+ if (fRefTrackCuts) delete fRefTrackCuts;
+ fRefTrackCuts = NULL;
+
+ if (fHLTTracks) delete fHLTTracks;
+ fHLTTracks = NULL;
+
+ if (fTrackingData) delete fTrackingData;
+ fTrackingData = NULL;
+
+ if (fChunkId) delete fChunkId;
+ fChunkId = NULL;
+
+ }
+
+ // check if the -triggername argument is used, the trigger name determines the following initialization
+ vector<const char*> remainingArgs;
+ for (int i = 0; i < argc; ++i) {
+ if (strcmp(argv[i], "-triggername") == 0) {
+ if (++i < argc){
+ fName = argv[i];
+ } else {
+ LogError("invalid parameter for argument '-triggername', string expected");
+ return -EINVAL;
+ }
+ continue;
+ }
+ remainingArgs.push_back(argv[i]);
+ }
+
+ TString cdbPath;
+ if (!fName.IsNull()) {
+ cdbPath = "HLT/ConfigHLT/";
+ cdbPath += fName;
+ } else {
+ cdbPath = fgkDefaultOCDBEntry;
+ }
+
+ LogInfo("cdbPath = <%s>", cdbPath.Data());
+ iResult = ConfigureFromCDBObject(cdbPath);
+
+ if (iResult >= 0 && argc > 0)
+ iResult = ConfigureFromArgumentString(remainingArgs.size(), &(remainingArgs[0]));
+
+ return iResult;
+}
+
+int AliHLTTRDTriggerComponent::DoDeinit()
+{
+
+#ifdef __TRDHLTDEBUG
+ if (fEventDisplay) delete fEventDisplay;
+ fEventDisplay = NULL;
+#endif
+
+ if ((fHistoMode == 1) && (fWriteHistos)){
+ TFile out("trg_out/trg_hists.root", "RECREATE");
+ if (!out.IsZombie()) {
+ out.cd();
+ UInt_t numHists = fHistArray->GetEntries();
+ for (UInt_t iHist = 0; iHist < numHists; ++iHist)
+ if (fHistArray->At(iHist))
+ fHistArray->At(iHist)->Write();
+ out.Close();
+ }
+ }
+
+ if (fHistArray) delete fHistArray;
+ fHistArray = NULL;
+
+ if (fRefTrackCuts) delete fRefTrackCuts;
+ fRefTrackCuts = NULL;
+
+ if (!fHLTTracks) delete fHLTTracks;
+ fHLTTracks = NULL;
+
+ if (fTrackingData) delete fTrackingData;
+ fTrackingData = NULL;
+
+ if (fTRDGeometry) delete fTRDGeometry;
+ fTRDGeometry = NULL;
+
+ if (fChunkId) delete fChunkId;
+ fChunkId = NULL;
+
+ return 0;
+}
+
+int AliHLTTRDTriggerComponent::Reconfigure(const char* cdbEntry, const char* /*chainId*/)
+{
+ TString cdbPath;
+ if (!cdbEntry || cdbEntry[0] == 0) {
+ if (!fName.IsNull()) {
+ cdbPath = "HLT/ConfigHLT/";
+ cdbPath += fName;
+ } else {
+ cdbPath = fgkDefaultOCDBEntry;
+ }
+ } else
+ cdbPath = cdbEntry;
+
+ return ConfigureFromCDBObject(cdbPath);
+}
+
+int AliHLTTRDTriggerComponent::ReadPreprocessorValues(const char* /*modules*/)
+{
+ return 0;
+}
+
+Int_t AliHLTTRDTriggerComponent::ConfigureFromCDBObject(TString /*cdbPath*/)
+{
+ return 0;
+}
+
+int AliHLTTRDTriggerComponent::ScanConfigurationArgument(int argc, const char** argv)
+{
+
+ if (argc <= 0)
+ return 0;
+
+ UShort_t iArg = 0;
+ TString argument(argv[iArg]);
+
+ if (!argument.CompareTo("-match-sel-eta")){
+ if (++iArg >= argc) return -EPROTO;
+ argument = argv[iArg];
+ fRefTrackSelectionEtaLimit = argument.Atof();
+ LogInfo("ref track selection eta limit set to %.1f.", fRefTrackSelectionEtaLimit);
+ return 2;
+ }
+
+ if (!argument.CompareTo("-match-sel-vxy")){
+ if (++iArg >= argc) return -EPROTO;
+ argument = argv[iArg];
+ fRefTrackSelectionVertexXYLimit = argument.Atof();
+ LogInfo("ref track selection vertex xy limit set to %.1f.", fRefTrackSelectionVertexXYLimit);
+ return 2;
+ }
+
+ if (!argument.CompareTo("-match-sel-vz")){
+ if (++iArg >= argc) return -EPROTO;
+ argument = argv[iArg];
+ fRefTrackSelectionVertexZLimit = argument.Atof();
+ LogInfo("ref track selection vertex z limit set to %.1f.", fRefTrackSelectionVertexZLimit);
+ return 2;
+ }
+
+ if (!argument.CompareTo("-match-sel-pt")){
+ if (++iArg >= argc) return -EPROTO;
+ argument = argv[iArg];
+ fRefTrackSelectionPtThreshold = argument.Atof();
+ LogInfo("ref track selection pt threshold set to %.1f GeV/c.", fRefTrackSelectionPtThreshold);
+ return 2;
+ }
+
+ if (!argument.CompareTo("-match-rating")){
+ if (++iArg >= argc) return -EPROTO;
+ argument = argv[iArg];
+ fMatchRatingThreshold = argument.Atof();
+ LogInfo("match rating threshold set to %.2f GeV/c.", fMatchRatingThreshold);
+ return 2;
+ }
+
+ if (!argument.CompareTo("-histo-mode")){
+ if (++iArg >= argc) return -EPROTO;
+ argument = argv[iArg];
+ fHistoMode = argument.Atoi();
+ LogInfo("histo mode set to %d", fHistoMode);
+ return 2;
+ }
+
+ if (!argument.CompareTo("-trghse")){
+ LogInfo("TRD HLT electron trigger HSE enabled.");
+ return 1;
+ }
+
+ if (!argument.CompareTo("-hse-pt")){
+ if (++iArg >= argc) return -EPROTO;
+ argument = argv[iArg];
+ fElectronTriggerPtThresholdHSE = argument.Atof();
+ LogInfo("pt threshold for HSE trigger set to %.1f GeV/c.", fElectronTriggerPtThresholdHSE);
+ return 2;
+ }
+
+ if (!argument.CompareTo("-hse-pid")){
+ if (++iArg >= argc) return -EPROTO;
+ argument = argv[iArg];
+ fElectronTriggerPIDThresholdHSE = argument.Atof();
+ LogInfo("PID threshold for HSE trigger set to %d.", fElectronTriggerPIDThresholdHSE);
+ return 2;
+ }
+
+ if (!argument.CompareTo("-trghqu")){
+ LogInfo("TRD HLT electron trigger HQU enabled.");
+ return 1;
+ }
+
+ if (!argument.CompareTo("-hqu-pt")){
+ if (++iArg >= argc) return -EPROTO;
+ argument = argv[iArg];
+ fElectronTriggerPtThresholdHQU = argument.Atof();
+ LogInfo("pt threshold for HQU trigger set to %.1f GeV/c.", fElectronTriggerPtThresholdHQU);
+ return 2;
+ }
+
+ if (!argument.CompareTo("-hqu-pid")){
+ if (++iArg >= argc) return -EPROTO;
+ argument = argv[iArg];
+ fElectronTriggerPIDThresholdHQU = argument.Atof();
+ LogInfo("PID threshold for HQU trigger set to %.1f GeV/c.", fElectronTriggerPIDThresholdHQU);
+ return 2;
+ }
+
+ if (!argument.CompareTo("-l1-only")){
+ LogInfo("evaluation of electron trigger only for events with TRD L1 electron trigger enabled.");
+ fElectronTriggerOnL1TrgOnly = kTRUE;
+ return 1;
+ }
+
+ if (!argument.CompareTo("-histo-ext")){
+ LogInfo("extended histogramming enabled.");
+ fExtendedHistos = kTRUE; // enable extended histogramming, for debugging/tuning only!
+
+ if (!fHistRefTrackPid){
+ fHistRefTrackPid = new TH2I("trdtrg_reftrack_pid", "TPC dE/dx by p_{T} for matching GTU tracks;p_{T} (GeV/c);dE/dx (a. u.)",
+ 500, 0., 10., 500, 0., 500);
+ fHistArray->AddLast(fHistRefTrackPid);
+ }
+
+ if (!fHistMatchedRefTrackPid){
+ fHistMatchedRefTrackPid = new TH2I("trdtrg_matched_reftrack_pid", "TPC dE/dx by p_{T} for matching GTU tracks;p_{T} (GeV/c);dE/dx (a. u.)",
+ 500, 0., 10., 500, 0., 500);
+ fHistArray->AddLast(fHistMatchedRefTrackPid);
+ }
+
+ if (!fHistPIDvsTruncPID){
+ fHistPIDvsTruncPID = new TH2I("trdtrg_pid_trunc_pid", "GTU track PID vs. truncated PID;PID (a.u.);truncated PID (a. u.)",
+ 256, 0., 256., 256, 0., 256.);
+ fHistArray->AddLast(fHistPIDvsTruncPID);
+ }
+
+ if (!fHistElectronFalsePIDvsTruncPID){
+ fHistElectronFalsePIDvsTruncPID = new TH2I("trdtrg_electron_false_pid_trunc_pid", "false electron PID vs. truncated PID;PID (a.u.);truncated PID (a. u.)",
+ 256, 0., 256., 256, 0., 256.);
+ fHistArray->AddLast(fHistElectronFalsePIDvsTruncPID);
+ }
+
+ if (!fHistElectronConfirmedPIDvsTruncPID){
+ fHistElectronConfirmedPIDvsTruncPID = new TH2I("trdtrg_electron_confirmed_pid_trunc_pid", "confirmed electron PID vs. truncated PID;PID (a.u.);truncated PID (a. u.)",
+ 256, 0., 256., 256, 0., 256.);
+ fHistArray->AddLast(fHistElectronConfirmedPIDvsTruncPID);
+ }
+
+ return 1;
+ }
+
+ if (!argument.CompareTo("-ref-cuts")){
+ LogInfo("ref track cuts for matching enabled.");
+ fApplyRefTrackCuts = kTRUE;
+ return 1;
+ }
+
+ if (!argument.CompareTo("-push-histograms")){
+ LogInfo("pushing of histograms enabled.");
+ fPushHistos = kTRUE; // enable histogram pushing, for debugging/tuning only!
+ return 1;
+ }
+
+ if (!argument.CompareTo("-write-histograms")){
+ LogInfo("writing of histograms enabled.");
+ fWriteHistos = kTRUE; // enable histogram writing, for debugging/tuning only!
+ return 1;
+ }
+
+ if (!argument.CompareTo("-render")){
+#ifdef __TRDHLTDEBUG
+ LogInfo("rendering of interesting events enabled.");
+ if (!fEventDisplay)
+ fEventDisplay = new AliTRDtrackingEventDisplay();
+ LogInfo("event rendering activated. this is for debugging only!");
+ fEventRendering = kTRUE; // enable event rendering, for debugging/tuning only!
+#endif
+ return 1;
+ }
+
+ if (!argument.CompareTo("-debug")){
+ if (++iArg >= argc) return -EPROTO;
+ argument = argv[iArg];
+ fDebugLevel = argument.Atoi();
+ LogInfo("debug level set to %d.", fDebugLevel);
+ return 2;
+ }
+
+ if (!argument.CompareTo("-ref-pt")){
+ if (++iArg >= argc) return -EPROTO;
+ argument = argv[iArg];
+ Float_t minPt, maxPt;
+ fRefTrackCuts->GetPtRange(minPt, maxPt);
+ maxPt = argument.Atof();
+ fRefTrackCuts->SetPtRange(minPt, maxPt);
+ LogInfo("ref track pt range set to %.1f .. %.1f GeV/c.", minPt, maxPt);
+ return 2;
+ }
+
+ if (!argument.CompareTo("-ref-tdca")){
+ if (++iArg >= argc) return -EPROTO;
+ argument = argv[iArg];
+ fRefTrackCuts->SetMaxDCAToVertexXY(argument.Atof());
+ LogInfo("ref track DCA transverse threshold set to %.3f", argument.Atof());
+ return 2;
+ }
+
+ if (!argument.CompareTo("-ref-ldca")){
+ if (++iArg >= argc) return -EPROTO;
+ argument = argv[iArg];
+ fRefTrackCuts->SetMaxDCAToVertexZ(argument.Atof());
+ LogInfo("ref track longitudinal DCA threshold set to %.3f", argument.Atof());
+ return 2;
+ }
+
+ return 1;
+}
+
+void AliHLTTRDTriggerComponent::ScanTriggerClasses(const char* firedTriggerClasses) {
+
+ fIsMinBiasEvent = kFALSE;
+
+ TString trg(firedTriggerClasses);
+ if (trg.Index("CINT7WU-S-NOPF-ALL") >= 0)
+ fIsMinBiasEvent = kTRUE;
+
+ if (trg.Index("CINT8WU-S-NOPF-ALL") >= 0)
+ fIsMinBiasEvent = kTRUE;
+
+}
+
+Bool_t AliHLTTRDTriggerComponent::CheckRefTrackCuts(AliESDtrack* track){
+
+ // cuts by cut class
+ if (fApplyRefTrackCuts)
+ return fRefTrackCuts->AcceptTrack(track) ? kTRUE : kFALSE;
+
+ // simple custom cuts
+ Float_t dcaToVertexXY, dcaToVertexZ;
+ track->GetImpactParametersTPC(dcaToVertexXY, dcaToVertexZ);
+ // LogDebug("IMPACT TPC %.4f %.4f", dcaToVertexXY, dcaToVertexZ);
+
+ if ((dcaToVertexXY > fRefTrackSelectionVertexXYLimit) || (dcaToVertexZ >= fRefTrackSelectionVertexZLimit))
+ return kFALSE;
+
+ if (TMath::Abs(track->Eta()) > fRefTrackSelectionEtaLimit)
+ return kFALSE;
+
+ return kTRUE;
+}
+
+
+void AliHLTTRDTriggerComponent::DbgLog(const char* prefix, ...){
+#ifdef __TRDHLTDEBUG
+ AliHLTEventID_t eventNumber = fEventId;
+ printf("TRDHLTGM %s-%s-%s: [TRG] %s",
+ (fRunNumber >= 0) ? Form("%06d", fRunNumber) : "XXXXXX",
+ fChunkId->Data(),
+ (eventNumber != fgkInvalidEventId) ? Form("%05llu", eventNumber) : "XXXXX",
+ (strlen(prefix) > 0) ? Form("<%s> ", prefix) : "");
+#endif
+ va_list args;
+ va_start(args, prefix);
+ char* fmt = va_arg(args, char*);
+ vprintf(fmt, args);
+ printf("\n");
+ va_end(args);
+}
+
+int AliHLTTRDTriggerComponent::PrepareESDData(){
+
+ int result = 0;
+ fESDtracksPresent = kFALSE;
+
+ // check access to ESD event data
+ const TObject* obj = GetFirstInputObject(kAliHLTAllDataTypes, "AliESDEvent");
+ fEsdEvent = dynamic_cast<AliESDEvent*>(const_cast<TObject*>(obj));
+
+ if (fEsdEvent) {
+ fEsdEvent->GetStdContent();
+ fRunNumber = fEsdEvent->GetRunNumber();
+ fESDtracksPresent = kTRUE;
+ unsigned int numTracks = fEsdEvent->GetNumberOfTracks();
+
+ // process trigger classes
+ ScanTriggerClasses(fEsdEvent->GetFiredTriggerClasses().Data());
+
+ LogDebug("ESD event data: %d ESD tracks [event num: %d] [minbias: %d (fired:%s)]",
+ numTracks, fEsdEvent->GetEventNumberInFile(), fIsMinBiasEvent, fEsdEvent->GetFiredTriggerClasses().Data());
+
+ // process ESD tracks
+ if ((fDebugLevel >= 2) || fExtendedHistos){
+ AliESDtrack* esdTrack;
+ TString paramStr("");
+ for (unsigned int iTrack = 0; iTrack < numTracks; ++iTrack) {
+ esdTrack = fEsdEvent->GetTrack(iTrack);
+
+ if (fExtendedHistos){
+ fHistRefTrackPid->Fill(esdTrack->Pt(), esdTrack->GetTPCsignal());
+ }
+
+ if (fDebugLevel >= 2){
+ paramStr = "";
+ if (esdTrack){
+
+ if (esdTrack->GetInnerParam())
+ paramStr += "I";
+
+ if (esdTrack->GetOuterParam())
+ paramStr += "O";
+
+ LogDebug("ESD track %4d - pt: %+.2fGeV/c [params: S%s]", iTrack, esdTrack->GetSignedPt(), paramStr.Data());
+ } else
+ LogError("ESD data for track %d invalid", iTrack);
+ }
+
+ } // loop over ESD tracks
+ }
+
+ fTrackingData->SetGtuPtMultiplierFromMagField(fEsdEvent->GetMagneticField()); // used for sign correction
+
+ result = 1;
+
+ }
+
+ return result;
+
+}
+
+int AliHLTTRDTriggerComponent::PrepareHLTData(){
+
+ int iResult = 0;
+ UInt_t numHLTTracks = 0;
+ fHLTtracksPresent = kFALSE;
+
+ if (!fHLTTracks){
+ LogError("HLT track vector instance not available.");
+ return 0;
+ }
+
+ fHLTTracks->clear();
+
+ for (const AliHLTComponentBlockData *pBlock = GetFirstInputBlock(kAliHLTDataTypeTrack | kAliHLTDataOriginTPC);
+ pBlock != NULL; pBlock = GetNextInputBlock()) {
+ LogDebug("#hlttrk - data block with HLT raw tracks received");
+ fHLTtracksPresent = kTRUE;
+
+ // vector<AliHLTGlobalBarrelTrack> hltTracks;
+ if ((iResult = AliHLTGlobalBarrelTrack::ConvertTrackDataArray(reinterpret_cast<const AliHLTTracksData*>(pBlock->fPtr), pBlock->fSize, *fHLTTracks)) >= 0) {
+ for (vector<AliHLTGlobalBarrelTrack>::iterator element = fHLTTracks->begin();
+ element != fHLTTracks->end(); element++) {
+
+ numHLTTracks++;
+ //## AliHLTGlobalBarrelTrack -> AliKalmanTrack -> AliExternalTrackParam
+
+ } // loop over HLT tracks
+ }
+ } // loop over data blocks
+
+ LogDebug("#hlttrk - %d HLT raw tracks found", numHLTTracks);
+
+ return iResult;
+
+}
+
+int AliHLTTRDTriggerComponent::PrepareTRDData() {
+
+ int result = 1;
+
+ fSectorsWithData = 0;
+ fTrackingData->Clear();
+ for (const AliHLTComponentBlockData* datablock = GetFirstInputBlock(AliHLTTRDDefinitions::fgkOnlineDataType);
+ datablock != NULL;
+ datablock = GetNextInputBlock())
+ {
+ fSectorsWithData |= datablock->fSpecification;
+ fTrackingData->Decompress(datablock->fPtr, datablock->fSize, kTRUE);
+ }
+
+ fTrackingData->SetGtuPtMultiplierFromMagField(GetBz()); // used for sign correction
+
+ fTrackingData->PrintSummary("trigger component");
+
+ return result;
+
+}
+
+int AliHLTTRDTriggerComponent::MatchTRDTracksESD(){
+
+ if (!fEsdEvent) {
+ LogError("ESD event data not available in MatchTRDTracks().");
+ return 0;
+ }
+
+ if (fHistoMode == 0){
+ UInt_t numHists = fHistArray->GetEntries();
+ for (UInt_t iHist = 0; iHist < numHists; ++iHist)
+ if (fHistArray->At(iHist))
+ dynamic_cast<TH1*>(fHistArray->At(iHist))->Reset();
+ }
+
+ int result = 1;
+ unsigned int numRefTracks = fEsdEvent->GetNumberOfTracks();
+ unsigned int numGtuTracks;
+ Int_t refTrackIndices[fkMaxRefTracksPerStack];
+ UInt_t refTrackCount = 0;
+ Bool_t isRelevant;
+ Double_t distY, distZ;
+ Double_t matchRating;
+ Double_t bestMatchRating;
+ Int_t bestMatchRefIndex;
+ AliESDtrack* refTrack = NULL;
+ UInt_t numComparisonsDone = 0;
+ UInt_t numUnmatchedTracks = 0;
+ UInt_t numMatchedTracks = 0;
+ Double_t magField = fEsdEvent->GetMagneticField();
+
+ for (UShort_t iStack = 0; iStack < fkTRDStacks; ++iStack) {
+ numGtuTracks = fTrackingData->GetNumTracks(iStack);
+ refTrackCount = 0;
+
+ // preselect ESD relevant ESD tracks
+ for (UInt_t iRefTrack = 0; iRefTrack < numRefTracks; ++iRefTrack) {
+ refTrack = fEsdEvent->GetTrack(iRefTrack);
+ isRelevant = (refTrack->Pt() >= fRefTrackSelectionPtThreshold); //## implement properly
+ if (isRelevant){
+ if (refTrackCount < fkMaxRefTracksPerStack)
+ refTrackIndices[refTrackCount++] = iRefTrack;
+ else {
+ LogError("number of HLT tracks exceeding limit of %d. Skipping some tracks.", fkMaxRefTracksPerStack);
+ break;
+ }
+ }
+ }
+
+ // try to match GTU track with ref tracks
+ for (UInt_t iGtuTrack = 0; iGtuTrack < numGtuTracks; ++iGtuTrack) {
+ bestMatchRating = 0.;
+ bestMatchRefIndex = -1;
+ Double_t gpt = fTrackingData->GetTrackPt(iStack, iGtuTrack);
+ UShort_t gpid = fTrackingData->GetTrackPID(iStack, iGtuTrack);
+ UShort_t layerMask = fTrackingData->GetTrackLayerMask(iStack, iGtuTrack);
+
+ Float_t trklLocalY[fkTRDLayers];
+ Int_t trklBinZ[fkTRDLayers];
+ for (UShort_t iLayer = 0; iLayer < fkTRDLayers; ++iLayer){
+ if ((layerMask >> iLayer) & 1){
+ trklLocalY[iLayer] = fTrackingData->GetTrackTrackletLocalY(iStack, iGtuTrack, iLayer);
+ trklBinZ[iLayer] = fTrackingData->GetTrackTrackletBinZ(iStack, iGtuTrack, iLayer);
+ }
+ }
+
+ for (UInt_t iRefTrack = 0; iRefTrack < refTrackCount; ++iRefTrack) {
+ refTrack = fEsdEvent->GetTrack(refTrackIndices[iRefTrack]);
+
+// if (!CheckRefTrackCuts(refTrack))
+// continue;
+
+ numComparisonsDone++;
+
+// if ((!refTrack->GetOuterParam()) && (!refTrack->GetInnerParam())) // use tracks with TPC outer param only (all HLT tracks have it anyways)
+// continue;
+
+ Int_t distRes = EstimateTrackDistance(refTrack, iStack, layerMask, trklLocalY, trklBinZ,
+ magField, &distY, &distZ);
+
+ if (fDebugLevel >= 3){
+ printf("CHECKMATCH = %i distY %.2f distZ %.2f pt: %.2f %.2f\n",
+ distRes, distY, distZ, gpt, refTrack->GetSignedPt());
+ }
+
+ if (distRes == 0){
+ matchRating = RateTrackMatch(distY, distZ, gpt, refTrack->GetSignedPt());
+ } else {
+ matchRating = 0.;
+ }
+
+ if ((matchRating >= fMatchRatingThreshold) && (matchRating > bestMatchRating)) {
+ bestMatchRefIndex = refTrackIndices[iRefTrack];
+ bestMatchRating = matchRating;
+ } else if (matchRating > bestMatchRating)
+ bestMatchRating = matchRating;
+
+// DbgLog("", Form("#match - comparing GTU track %d in S%02d-%d with ref track %d: [gpt: %+5.2f rpt: %+5.2f] dy: %.1f dz: %.1f rating: %.1f",
+// iGtuTrack, iStack/5, iStack%5, refTrackIndices[iRefTrack],
+// fTrackingData->GetTrackPt(iStack, iGtuTrack), refTrack->GetSignedPt(),
+// distY, distZ, matchRating));
+
+ } // loop over ref tracks in stack
+
+ fHistMatchRating->Fill(bestMatchRating);
+ fHistMatchRatingByPt->Fill(bestMatchRating, TMath::Abs(gpt));
+ fHistMatchRatingByPid->Fill(bestMatchRating, gpid);
+ fHistTrackPt->Fill(gpt);
+ fHistTrackPid->Fill(gpid);
+
+ if (fExtendedHistos){
+ fHistMatchedRefTrackPid->Fill(refTrack->Pt(), refTrack->GetTPCsignal());
+ }
+
+ if (bestMatchRefIndex >= 0){
+ // GTU track has matching reference track
+ refTrack = fEsdEvent->GetTrack(bestMatchRefIndex);
+ Double_t rpt = refTrack->GetSignedPt();
+ LogDebug("#match - match found: rating %.2f, gpt: %+5.2f, rpt: %+5.2f (%i) -> diff: %.2f%%",
+ bestMatchRating,gpt, rpt, bestMatchRefIndex, (gpt - rpt)/rpt*100.);
+ fTrackingData->SetTrackAddInfo(iStack, iGtuTrack, bestMatchRefIndex);
+ if (fDebugLevel >= 3){
+ LogDebug("#match-info rating: %.2f gpt: %+.2f matchref: %d rpt: %+.2f gpid: %d S%02d-%d %d rpid: %.3f",
+ bestMatchRating, gpt, bestMatchRefIndex, rpt, gpid,
+ iStack/5, iStack%5, iGtuTrack, refTrack->GetTPCsignal());
+ }
+ numMatchedTracks++;
+
+ fHistTrackPtMatched->Fill(gpt);
+ fHistTrackPtCorr->Fill(rpt, gpt);
+ fHistTrackPidMatched->Fill(gpid);
+
+ } else {
+ if (fDebugLevel >= 3){
+ LogDebug("#match-info rating: %.2f gpt: %+.2f no ref matching gpid: %d S%02d-%d %d",
+ bestMatchRating, gpt, gpid,
+ iStack/5, iStack%5, iGtuTrack);
+ }
+ numUnmatchedTracks++;
+ }
+
+ } // loop over gtu tracks in stack
+
+ } // loop over stacks
+
+ LogInfo("#match - %d matched GTU tracks, %d unmatched",
+ numMatchedTracks, numUnmatchedTracks);
+
+ fHistTrackMatchingCombinations->Fill(0., (Double_t)(numRefTracks * fTrackingData->GetNumTracks())); // index 0: full combinatorics
+ fHistTrackMatchingCombinations->Fill(1., numComparisonsDone); // index 1: track matching comparisons actually done
+
+ return result;
+
+}
+
+int AliHLTTRDTriggerComponent::MatchTRDTracksHLT(){
+
+ if (!fHLTTracks){
+ LogError("HLT track data available.");
+ return 0;
+ }
+
+ Double_t magField = GetBz();
+ unsigned int numGtuTracks;
+ unsigned int numHLTTracks = 0;
+ Bool_t isRelevant;
+ Double_t distY, distZ;
+ Double_t matchRating;
+ Double_t bestMatchRating;
+ Int_t bestMatchRefIndex;
+ UInt_t numComparisonsDone = 0;
+ UInt_t numUnmatchedTracks = 0;
+ UInt_t numMatchedTracks = 0;
+
+ Bool_t hltTrackPreSel[fkMaxRefTracks];
+ UInt_t iHltTrack;
+
+ for (UShort_t iStack = 0; iStack < fkTRDStacks; ++iStack) {
+ numGtuTracks = fTrackingData->GetNumTracks(iStack);
+
+ // preselect relevant HLT tracks
+ iHltTrack = 0;
+ for (vector<AliHLTGlobalBarrelTrack>::iterator element = fHLTTracks->begin();
+ element != fHLTTracks->end(); element++) {
+ numHLTTracks++;
+ isRelevant = (element->Pt() >= fRefTrackSelectionPtThreshold); //## implement properly
+
+ //## use cuts here
+ hltTrackPreSel[iHltTrack++] = isRelevant;
+ if (iHltTrack >= fkMaxRefTracks)
+ LogError("maximum number of HLT tracks exceeded.");
+ } // loop over HLT tracks;
+
+ // search for matching HLT track for each GTU track
+ for (UInt_t iGtuTrack = 0; iGtuTrack < numGtuTracks; ++iGtuTrack) {
+ bestMatchRating = 0.;
+ bestMatchRefIndex = -1;
+ Double_t gpt = fTrackingData->GetTrackPt(iStack, iGtuTrack);
+ UShort_t gpid = fTrackingData->GetTrackPID(iStack, iGtuTrack);
+ UShort_t layerMask = fTrackingData->GetTrackLayerMask(iStack, iGtuTrack);
+
+ Float_t trklLocalY[fkTRDLayers];
+ Int_t trklBinZ[fkTRDLayers];
+ for (UShort_t iLayer = 0; iLayer < fkTRDLayers; ++iLayer){
+ if ((layerMask >> iLayer) & 1){
+ trklLocalY[iLayer] = fTrackingData->GetTrackTrackletLocalY(iStack, iGtuTrack, iLayer);
+ trklBinZ[iLayer] = fTrackingData->GetTrackTrackletBinZ(iStack, iGtuTrack, iLayer);
+ }
+ }
+
+ iHltTrack = 0;
+ for (vector<AliHLTGlobalBarrelTrack>::iterator element = fHLTTracks->begin();
+ element != fHLTTracks->end(); element++) {
+ if (!hltTrackPreSel[iHltTrack]){
+ iHltTrack++;
+ continue;
+ }
+
+ // compare GTU track and relevant HLT track
+ numComparisonsDone++;
+
+ AliHLTGlobalBarrelTrack hltPar(*element);
+ Int_t distRes = EstimateTrackDistance(&hltPar, iStack, layerMask, trklLocalY, trklBinZ,
+ magField, &distY, &distZ);
+
+ if (fDebugLevel >= 3){
+ printf("CHECKMATCH = %i distY %.2f distZ %.2f pt: %.2f %.2f\n",
+ distRes, distY, distZ, gpt, element->GetSignedPt());
+ }
+
+ if (distRes == 0){
+ matchRating = RateTrackMatch(distY, distZ, gpt, element->GetSignedPt());
+ } else {
+ matchRating = 0.;
+ }
+
+ if ((matchRating >= fMatchRatingThreshold) && (matchRating > bestMatchRating)) {
+ bestMatchRefIndex = iHltTrack;
+ bestMatchRating = matchRating;
+ } else if (matchRating > bestMatchRating)
+ bestMatchRating = matchRating;
+
+
+ iHltTrack++;
+ } // loop over HLT tracks;
+
+ fHistMatchRating->Fill(bestMatchRating);
+ fHistMatchRatingByPt->Fill(bestMatchRating, TMath::Abs(gpt));
+ fHistMatchRatingByPid->Fill(bestMatchRating, gpid);
+ fHistTrackPt->Fill(gpt);
+ fHistTrackPid->Fill(gpid);
+
+ if (bestMatchRefIndex >= 0){
+ // GTU track has matching reference track
+ Double_t rpt = fHLTTracks->at(bestMatchRefIndex).GetSignedPt();
+ LogDebug("#match - match found: rating %.2f, gpt: %+5.2f, rpt: %+5.2f (%i) -> diff: %.2f%%",
+ bestMatchRating,gpt, rpt, bestMatchRefIndex, (gpt - rpt)/rpt*100.);
+ fTrackingData->SetTrackAddInfo(iStack, iGtuTrack, bestMatchRefIndex);
+
+// if (fExtendedHistos){
+// fHistMatchedRefTrackPid->Fill(element->Pt(), element->GetTPCsignal());
+// }
+//
+// if (fDebugLevel >= 3){
+// LogDebug("#match-info rating: %.2f gpt: %+.2f matchref: %d rpt: %+.2f gpid: %d S%02d-%d %d rpid: %.3f",
+// bestMatchRating, gpt, bestMatchRefIndex, rpt, gpid,
+// iStack/5, iStack%5, iGtuTrack, refTrack->GetTPCsignal());
+// }
+ numMatchedTracks++;
+
+ fHistTrackPtMatched->Fill(gpt);
+ fHistTrackPtCorr->Fill(rpt, gpt);
+ fHistTrackPidMatched->Fill(gpid);
+
+ } else {
+ if (fDebugLevel >= 3){
+ LogDebug("#match-info rating: %.2f gpt: %+.2f no ref matching gpid: %d S%02d-%d %d",
+ bestMatchRating, gpt, gpid,
+ iStack/5, iStack%5, iGtuTrack);
+ }
+ numUnmatchedTracks++;
+ }
+
+ } // loop over gtu tracks
+ } // loop over stacks
+
+ LogInfo("#match - %d matched GTU tracks, %d unmatched (%d comparisons)",
+ numMatchedTracks, numUnmatchedTracks, numComparisonsDone);
+
+ fHistTrackMatchingCombinations->Fill(0., (Double_t)(numHLTTracks * fTrackingData->GetNumTracks())); // index 0: full combinatorics
+ fHistTrackMatchingCombinations->Fill(1., numComparisonsDone); // index 1: track matching comparisons actually done
+
+ return kTRUE;
+}
+
+int AliHLTTRDTriggerComponent::MatchTRDTracks(){
+
+ if (!fEsdEvent) {
+ LogError("ESD event data not available in MatchTRDTracks().");
+ return 0;
+ }
+
+ if (fHistoMode == 0){
+ UInt_t numHists = fHistArray->GetEntries();
+ for (UInt_t iHist = 0; iHist < numHists; ++iHist)
+ if (fHistArray->At(iHist))
+ dynamic_cast<TH1*>(fHistArray->At(iHist))->Reset();
+ }
+
+ int result = 1;
+ unsigned int numRefTracks = fEsdEvent->GetNumberOfTracks();
+ unsigned int numGtuTracks;
+ Int_t refTrackIndices[fkMaxRefTracksPerStack];
+ UInt_t refTrackCount = 0;
+ Bool_t isRelevant;
+ Double_t distY, distZ;
+ Double_t matchRating;
+ Double_t bestMatchRating;
+ Int_t bestMatchRefIndex;
+ AliESDtrack* refTrack;
+ UInt_t numComparisonsDone = 0;
+ UInt_t numUnmatchedTracks = 0;
+ UInt_t numMatchedTracks = 0;
+
+ for (UShort_t iStack = 0; iStack < fkTRDStacks; ++iStack) {
+ numGtuTracks = fTrackingData->GetNumTracks(iStack);
+ refTrackCount = 0;
+
+ // preselect ESD relevant ESD tracks
+ for (UInt_t iRefTrack = 0; iRefTrack < numRefTracks; ++iRefTrack) {
+ refTrack = fEsdEvent->GetTrack(iRefTrack);
+ isRelevant = (refTrack->Pt() >= fRefTrackSelectionPtThreshold);
+ if (isRelevant){
+ if (refTrackCount < fkMaxRefTracksPerStack)
+ refTrackIndices[refTrackCount++] = iRefTrack;
+ else {
+ LogError("number of HLT tracks exceeding limit of %d. Skipping some tracks.", fkMaxRefTracksPerStack);
+ break;
+ }
+ }
+ }
+
+ // try to match GTU track with ref tracks
+ for (UInt_t iGtuTrack = 0; iGtuTrack < numGtuTracks; ++iGtuTrack) {
+ bestMatchRating = 0.;
+ bestMatchRefIndex = -1;
+ Double_t gpt = fTrackingData->GetTrackPt(iStack, iGtuTrack);
+ UShort_t gpid = fTrackingData->GetTrackPID(iStack, iGtuTrack);
+ UShort_t layerMask = fTrackingData->GetTrackLayerMask(iStack, iGtuTrack);
+
+ for (UInt_t iRefTrack = 0; iRefTrack < refTrackCount; ++iRefTrack) {
+ refTrack = fEsdEvent->GetTrack(refTrackIndices[iRefTrack]);
+
+ if (!CheckRefTrackCuts(refTrack))
+ continue;
+
+ numComparisonsDone++;
+
+// if ((!refTrack->GetOuterParam()) && (!refTrack->GetInnerParam())) // use tracks with TPC outer param only (all HLT tracks have it anyways)
+// continue;
+
+ Float_t trklLocalY[fkTRDLayers];
+ Int_t trklBinZ[fkTRDLayers];
+ for (UShort_t iLayer = 0; iLayer < fkTRDLayers; ++iLayer){
+ if ((layerMask >> iLayer) & 1){
+ trklLocalY[iLayer] = fTrackingData->GetTrackTrackletLocalY(iStack, iGtuTrack, iLayer);
+ trklBinZ[iLayer] = fTrackingData->GetTrackTrackletBinZ(iStack, iGtuTrack, iLayer);
+ }
+ }
+
+ Int_t distRes = EstimateTrackDistance(refTrack, iStack, layerMask, trklLocalY, trklBinZ,
+ fEsdEvent->GetMagneticField(), &distY, &distZ);
+
+ if (distRes == 0){
+ matchRating = RateTrackMatch(distY, distZ, gpt, refTrack->GetSignedPt());
+ } else {
+ matchRating = 0.;
+ }
+
+ if ((matchRating >= fMatchRatingThreshold) && (matchRating > bestMatchRating)) {
+ bestMatchRefIndex = refTrackIndices[iRefTrack];
+ bestMatchRating = matchRating;
+ } else if (matchRating > bestMatchRating)
+ bestMatchRating = matchRating;
+
+// DbgLog("", Form("#match - comparing GTU track %d in S%02d-%d with ref track %d: [gpt: %+5.2f rpt: %+5.2f] dy: %.1f dz: %.1f rating: %.1f",
+// iGtuTrack, iStack/5, iStack%5, refTrackIndices[iRefTrack],
+// fTrackingData->GetTrackPt(iStack, iGtuTrack), refTrack->GetSignedPt(),
+// distY, distZ, matchRating));
+
+ } // loop over ref tracks in stack
+
+ fHistMatchRating->Fill(bestMatchRating);
+ fHistMatchRatingByPt->Fill(bestMatchRating, TMath::Abs(gpt));
+ fHistMatchRatingByPid->Fill(bestMatchRating, gpid);
+ fHistTrackPt->Fill(gpt);
+ fHistTrackPid->Fill(gpid);
+
+ if (bestMatchRefIndex >= 0){
+ // GTU track has matching reference track
+ refTrack = fEsdEvent->GetTrack(bestMatchRefIndex);
+ Double_t rpt = refTrack->GetSignedPt();
+ LogDebug("#match - match found: rating %.2f, gpt: %+5.2f, rpt: %+5.2f (%i) -> diff: %.2f%%",
+ bestMatchRating,gpt, rpt, bestMatchRefIndex, (gpt - rpt)/rpt*100.);
+ fTrackingData->SetTrackAddInfo(iStack, iGtuTrack, bestMatchRefIndex);
+
+ if (fExtendedHistos){
+ fHistMatchedRefTrackPid->Fill(refTrack->Pt(), refTrack->GetTPCsignal());
+ }
+
+ if (fDebugLevel >= 3){
+ LogDebug("#match-info rating: %.2f gpt: %+.2f matchref: %d rpt: %+.2f gpid: %d S%02d-%d %d rpid: %.3f",
+ bestMatchRating, gpt, bestMatchRefIndex, rpt, gpid,
+ iStack/5, iStack%5, iGtuTrack, refTrack->GetTPCsignal());
+ }
+ numMatchedTracks++;
+
+ fHistTrackPtMatched->Fill(gpt);
+ fHistTrackPtCorr->Fill(rpt, gpt);
+ fHistTrackPidMatched->Fill(gpid);
+
+ } else {
+ if (fDebugLevel >= 3){
+ LogDebug("#match-info rating: %.2f gpt: %+.2f no ref matching gpid: %d S%02d-%d %d",
+ bestMatchRating, gpt, gpid,
+ iStack/5, iStack%5, iGtuTrack);
+ }
+ numUnmatchedTracks++;
+ }
+
+ } // loop over gtu tracks in stack
+
+ } // loop over stacks
+
+ LogInfo("#match - %d matched GTU tracks, %d unmatched",
+ numMatchedTracks, numUnmatchedTracks);
+
+ fHistTrackMatchingCombinations->Fill(0., (Double_t)(numRefTracks * fTrackingData->GetNumTracks())); // index 0: full combinatorics
+ fHistTrackMatchingCombinations->Fill(1., numComparisonsDone); // index 1: track matching comparisons actually done
+
+ return result;
+}
+
+void AliHLTTRDTriggerComponent::DumpTrackingData(){
+
+ if (fTrackingData->GetNumTracklets() + fTrackingData->GetNumTracks() == 0)
+ return;
+
+ TString trklStr("");
+ TString matchStr("");
+ UShort_t layerMask;
+
+// for (UShort_t iSector = 0; iSector < 18; ++iSector){
+// if (fTrackingData->GetSectorTrgWord(iSector) != ((UInt_t)0x2345352 ^ ((UInt_t)iSector + 34)))
+// LogError("invalid sector trigger word in sector %02d: trg word is 0x%08x, should be 0x%08x",
+// iSector, fTrackingData->GetSectorTrgWord(iSector), ((UInt_t)0x2345352 ^ ((UInt_t)iSector + 34)));
+// for (UShort_t iStack = 0; iStack < 5; ++iStack){
+// ULong64_t dwl = ((ULong64_t)0xaffe << 16) | (ULong64_t)iSector << 8 | iStack;
+// ULong64_t dw = (((ULong64_t)0xbead << 16) | (ULong64_t)iSector << 8 | iStack) | ((ULong64_t)dwl << 32);
+// if (fTrackingData->GetStackTrgWord(iSector, iStack) != dw)
+// LogError("stack %02d-%d trg word is 0x%016llx, should be 0x%016llx",
+// iSector, iStack, fTrackingData->GetStackTrgWord(iSector, iStack), dw);
+// }
+// }
+
+ for (UShort_t iStack = 0; iStack < fkTRDStacks; ++iStack){
+ for (Int_t iTrk = 0; iTrk < fTrackingData->GetNumTracks(iStack); ++iTrk){
+
+ layerMask = fTrackingData->GetTrackLayerMask(iStack, iTrk);
+
+ trklStr = Form("trkl: ");
+ for (Short_t iLayer = 5; iLayer >= 0; --iLayer){
+ if ((layerMask >> iLayer) & 1)
+ trklStr += Form("0x%08x (%+8.3f) ",
+ fTrackingData->GetTrackTrackletWord(iStack, iTrk, iLayer),
+ fTrackingData->GetTrackTrackletLocalY(iStack, iTrk, iLayer));
+ else
+ trklStr += "--------------------- ";
+ } // loop over layers
+ trklStr.Remove(trklStr.Length() - 2, 2);
+
+ if (fTrackingData->GetTrackAddInfo(iStack, iTrk) >= 0){
+ Double_t rpt = (fESDtracksPresent) ? fEsdEvent->GetTrack(fTrackingData->GetTrackAddInfo(iStack, iTrk))->GetSignedPt() :
+ fHLTTracks->at(fTrackingData->GetTrackAddInfo(iStack, iTrk)).GetSignedPt();
+ matchStr = Form("mpt: %+7.2f", rpt);
+ } else
+ matchStr = "unmatched";
+
+ if (fDebugLevel >= 3){
+
+ printf("###DOTDA EV%04llu GTU TRACK - S%02d-%d pt: %+7.2f pid: %3d lm: 0x%02x %s %s\n",
+ fEventId,
+ iStack/5, iStack%5, fTrackingData->GetTrackPt(iStack, iTrk), fTrackingData->GetTrackPID(iStack, iTrk),
+ layerMask, trklStr.Data(),
+ matchStr.Data());
+
+ printf("###DOTDB EV%04llu GTU TRACK - S%02d-%d pt: %+7.2f pid: %3d lm: 0x%02x %s\n",
+ fEventId,
+ iStack/5, iStack%5, fTrackingData->GetTrackPt(iStack, iTrk), fTrackingData->GetTrackPID(iStack, iTrk),
+ layerMask, trklStr.Data());
+ }
+
+
+ // paranoia checks
+ for (Short_t iLayer = 5; iLayer >= 0; --iLayer){
+ if (((layerMask >> iLayer) & 1) && (fTrackingData->GetTrackTrackletWord(iStack, iTrk, iLayer) == 0x10001000))
+ LogError("invalid layer mask / tracklet value combination A");
+
+ if ((((layerMask >> iLayer) & 1) == 0) && (fTrackingData->GetTrackTrackletWord(iStack, iTrk, iLayer) != 0x10001000))
+ LogError("invalid layer mask / tracklet value combination B");
+ }
+
+ } // loop over tracks in stack
+ } // loop over stacks
+
+}
+
+void AliHLTTRDTriggerComponent::AssignTrackInfo(TString* infoStr, const UInt_t stack, const UInt_t trackIndex, const char* flagStr) {
+
+ TString flags(flagStr);
+ Bool_t appendRefData = kFALSE;
+
+ if (fTrackingData->GetTrackAddInfo(stack, trackIndex) >= 0){
+ appendRefData = kTRUE;
+ if (flags.First('M') < 0)
+ flags += "M";
+ }
+
+ *infoStr = Form("EXCH-TRK-INFO DS<%s> CH<%s> EV%05llu SEC%02d-%d-%d gpt: %+6.1f gpid: %3d flags: %s",
+ "TRDHLTTRG",
+ fChunkId->Data(), fEventId,
+ stack/5, stack%5, trackIndex,
+ fTrackingData->GetTrackPt(stack, trackIndex),
+ fTrackingData->GetTrackPID(stack, trackIndex), flags.Data());
+
+ if (appendRefData){
+ Double_t rpt = (fESDtracksPresent) ? fEsdEvent->GetTrack(fTrackingData->GetTrackAddInfo(stack, trackIndex))->GetSignedPt() :
+ fHLTTracks->at(fTrackingData->GetTrackAddInfo(stack, trackIndex)).GetSignedPt();
+ *infoStr += Form(" rpt: %+6.1f", rpt);
+ }
+
+}
+
+#ifdef __TRDHLTDEBUG
+void AliHLTTRDTriggerComponent::RenderEvent(const Bool_t showGtuTracks, const Bool_t showTracklets, const Bool_t showRefTracks) {
+
+ if ((!fEventDisplay) || (!fEsdEvent))
+ return;
+
+ LogDebug("rendering event");
+
+ const Float_t refTrackPtDisplayThreshold = 0.7;
+ const Float_t trackPtEmphasizeThreshold = 1.8;
+
+ fEventDisplay->Reset();
+ fEventDisplay->SetMagField(fEsdEvent->GetMagneticField());
+ for (UInt_t iDet = 0; iDet < fkTRDStacks*fkTRDLayers; ++iDet)
+ fEventDisplay->SetChamberState(iDet/fkTRDLayers, iDet%6, ((fSectorsWithData >> (iDet/30)) & 1) );
+
+ if (showTracklets){
+ for (UShort_t iDet = 0; iDet < fkTRDStacks*fkTRDLayers; ++iDet){
+ UInt_t numTrkl = fTrackingData->GetNumTracklets(iDet);
+ for (UInt_t iTrkl = 0; iTrkl < numTrkl; ++iTrkl){
+ fEventDisplay->AddTracklet(fTrackingData->GetTracklet(iDet, iTrkl));
+ }
+ }
+ }
+
+ if (showGtuTracks){
+ for (UShort_t iStack = 0; iStack < fkTRDStacks; ++iStack){
+ for (Int_t iTrk = 0; iTrk < fTrackingData->GetNumTracks(iStack); ++iTrk){
+ AliESDTrdTrack* track = fTrackingData->GetTrack(iStack, iTrk);
+ Int_t trkIndex = fEventDisplay->AddTrack(track, (TMath::Abs(track->Pt()) >= trackPtEmphasizeThreshold) ? (kMagenta + 2) : kMagenta, 1, 1);
+ if (fTrackingData->GetTrackAddInfo(iStack, iTrk) >= 0)
+ fEventDisplay->SetTrackTrackletStyle(trkIndex, kRed, 12);
+ else
+ fEventDisplay->SetTrackTrackletStyle(trkIndex, kViolet - 5, 12);
+ }
+ }
+ }
+
+ unsigned int numRefTracks = fEsdEvent->GetNumberOfTracks();
+ unsigned int numRefTracksRendered = 0;
+ if (showRefTracks){
+ // check for some marks for rendering
+ UShort_t marks[40000];
+ memset(marks, 0, sizeof(UShort_t)*40000);
+ for (UShort_t iStack = 0; iStack < fkTRDStacks; ++iStack){
+ for (Int_t iTrk = 0; iTrk < fTrackingData->GetNumTracks(iStack); ++iTrk){
+ if (fTrackingData->GetTrackAddInfo(iStack, iTrk) >= 0){
+ marks[fTrackingData->GetTrackAddInfo(iStack, iTrk)] |= 1;
+ if (
+ (fTrackingData->GetTrackPID(iStack, iTrk) >= fElectronTriggerPIDThresholdHQU) &&
+ (TMath::Abs(fTrackingData->GetTrackPt(iStack, iTrk)) >= fElectronTriggerPtThresholdHQU))
+ marks[fTrackingData->GetTrackAddInfo(iStack, iTrk)] |= 2;
+ }
+ }
+ }
+
+ // add to rendering
+ for (unsigned int iTrack = 0; iTrack < numRefTracks; ++iTrack){
+ AliESDtrack* track = fEsdEvent->GetTrack(iTrack);
+ if ((track->Pt() >= refTrackPtDisplayThreshold) || (marks[iTrack] != 0)){
+ Color_t color = (track->Pt() >= trackPtEmphasizeThreshold) ? (kGray + 2) : kGray;
+ UShort_t width = 1;
+ UShort_t style = 1;
+ if (marks[iTrack] & 0x2){
+ color = kRed + 1;
+ width = 6;
+ }
+ if (!CheckRefTrackCuts(track))
+ style = 2;
+
+ fEventDisplay->AddTrack(track, color, width, style);
+ numRefTracksRendered++;
+ }
+ }
+ }
+
+ if (!fEventDisplay->IsEmpty()){
+ fEventDisplay->SetTitle("");
+ fEventDisplay->SetSetupText("HLT", Form("%.1f#scale[0.5]{ }/#scale[0.5]{ }%.1f",
+ refTrackPtDisplayThreshold, trackPtEmphasizeThreshold));
+ fEventDisplay->SetBottomText(Form("%05i-%s-%05llu",
+ fRunNumber, fChunkId->Data(), fEventId));
+ fEventDisplay->SetBottomTextRight(Form("%d (%d) HLT tracks, %d tracklets, %d GTU tracks",
+ numRefTracks,
+ numRefTracksRendered,
+ fTrackingData->GetNumTracklets(),
+ fTrackingData->GetNumTracks()));
+ fEventDisplay->SetLook(AliTRDtrackingEventDisplay::dmMediumLight);
+ fEventDisplay->SetDisplayMode(AliTRDtrackingEventDisplay::dmFullXY);
+ fEventDisplay->SaveToFile(Form("display/event-%s-%05llu.eps",
+ fChunkId->Data(), fEventId));
+ }
+
+}
+#endif
+
+Bool_t AliHLTTRDTriggerComponent::TRDElectronTrigger(const char *ident, const Double_t minPt, const UShort_t minPID){
+
+ LogDebug("Electron trigger processing (%s: pt>=%.1f, pid>=%d)...", ident, minPt, minPID);
+
+ UInt_t numTracks;
+ Bool_t highPtElectronSeenGTU = kFALSE;
+ Bool_t highPtElectronSeen = kFALSE;
+ UInt_t truncMeanPID = 0;
+ TString trackExchangeInfo("");
+ TString flags("");
+
+ UInt_t trdSectorTrgContribs = 0;
+ for (UShort_t iSector = 0; iSector < fkTRDSectors; ++iSector)
+ trdSectorTrgContribs |= fTrackingData->GetSectorTrgContribs(iSector);
+ if ((trdSectorTrgContribs >> 5) & 0x3)
+ fIsTRDElectronEvent = kTRUE;
+ else
+ fIsTRDElectronEvent = kFALSE;
+
+ if (fIsMinBiasEvent)
+ fHistElectronTriggerBaseMinBias->Fill(0.);
+
+ if (fIsTRDElectronEvent)
+ fHistElectronTriggerBaseTrdL1->Fill(0.);
+
+ if ((fElectronTriggerOnL1TrgOnly) && (!fIsTRDElectronEvent)){
+ // evaluate trigger for events with TRD L1 electron trigger fired
+ DbgLog("skipping %s electron trigger evaluation for event, because no TRD trigger flag set (ctbs: 0x%02x)",
+ ident, trdSectorTrgContribs);
+ return 0;
+ }
+
+ for (UShort_t iStack = 0; iStack < fkTRDStacks; ++iStack){
+ numTracks = fTrackingData->GetNumTracks(iStack);
+ for (UInt_t iTrk = 0; iTrk < numTracks; ++iTrk){
+ Double_t gpt = fTrackingData->GetTrackPt(iStack, iTrk);
+ Bool_t trdElectronCandidate = kFALSE;
+ Bool_t hltElectronCandidate = kFALSE;
+
+ // re-evaluate GTU only decision for comparison
+ if (
+ (TMath::Abs(gpt) >= minPt) &&
+ (fTrackingData->GetTrackPID(iStack, iTrk) >= minPID)
+ ) {
+ trdElectronCandidate = kTRUE;
+ highPtElectronSeenGTU = kTRUE;
+ fHistElectronCandidatePt->Fill(gpt);
+ fHistElectronCandidatePid->Fill(fTrackingData->GetTrackPID(iStack, iTrk));
+
+ if (fExtendedHistos){
+
+ // idea to be checked
+ truncMeanPID = 0;
+ Short_t minLyr = -1;
+ UShort_t minValue = 255;
+ Short_t maxLyr = -1;
+ UShort_t maxValue = 0;
+ UShort_t lyrCount = 0;
+ UInt_t layerMask = fTrackingData->GetTrackLayerMask(iStack, iTrk);
+
+ // scan for min & max values
+ for (UShort_t iLayer = 0; iLayer < fkTRDLayers; ++iLayer){
+ if ((layerMask >> iLayer) & 1){
+ if (fTrackingData->GetTrackTrackletPID(iStack, iTrk, iLayer) < minValue){
+ minValue = fTrackingData->GetTrackTrackletPID(iStack, iTrk, iLayer);
+ minLyr = iLayer;
+ }
+ if (fTrackingData->GetTrackTrackletPID(iStack, iTrk, iLayer) > maxValue){
+ maxValue = fTrackingData->GetTrackTrackletPID(iStack, iTrk, iLayer);
+ maxLyr = iLayer;
+ }
+ }
+ } // loop over layers
+
+ // calculate trunc mean
+ for (UShort_t iLayer = 0; iLayer < fkTRDLayers; ++iLayer){
+ if (((layerMask >> iLayer) & 1) && (iLayer != minLyr) && (iLayer != maxLyr)){
+ truncMeanPID += fTrackingData->GetTrackTrackletPID(iStack, iTrk, iLayer);
+ lyrCount++;
+ }
+ } // loop over layers
+ truncMeanPID = TMath::Nint((Double_t)(truncMeanPID)/(Double_t)(lyrCount));
+
+ fHistPIDvsTruncPID->Fill(fTrackingData->GetTrackPID(iStack, iTrk), truncMeanPID);
+ if (fTrackingData->GetTrackAddInfo(iStack, iTrk) < 0)
+ fHistElectronFalsePIDvsTruncPID->Fill(fTrackingData->GetTrackPID(iStack, iTrk), truncMeanPID);
+
+ }
+
+ LogInspect("#hlt-trd-trg - GTU flagged %s %s high-pt electron seen in S%02d-%d: pt: %+6.1f pid: %d [id: S%02d-%d-%d] [trunc-pid: %d]",
+ (fTrackingData->GetTrackAddInfo(iStack, iTrk) < 0) ? "unmatched" : "matched", ident,
+ iStack/5, iStack%5,
+ gpt, fTrackingData->GetTrackPID(iStack, iTrk),
+ iStack/5, iStack%5, iTrk,
+ truncMeanPID);
+ }
+
+ // evaluate HLT-level trigger decision using match information
+ if (
+ (fTrackingData->GetTrackAddInfo(iStack, iTrk) >= 0) &&
+ (TMath::Abs(gpt) >= minPt) &&
+ (fTrackingData->GetTrackPID(iStack, iTrk) >= minPID)
+ ) {
+ hltElectronCandidate = kTRUE;
+ highPtElectronSeen = kTRUE;
+
+ fHistElectronCandidateMatchedPt->Fill(gpt);
+ fHistElectronCandidateMatchedPid->Fill(fTrackingData->GetTrackPID(iStack, iTrk));
+
+ if (fExtendedHistos){
+ fHistElectronConfirmedPIDvsTruncPID->Fill(fTrackingData->GetTrackPID(iStack, iTrk), truncMeanPID);
+ }
+
+ Double_t rpt = (fESDtracksPresent) ? fEsdEvent->GetTrack(fTrackingData->GetTrackAddInfo(iStack, iTrk))->GetSignedPt() :
+ fHLTTracks->at(fTrackingData->GetTrackAddInfo(iStack, iTrk)).GetSignedPt();
+ LogInspect("#hlt-trd-trg - HLT matched %s high-pt electron seen in S%02d-%d: gpt: %+6.1f gpid: %d rpt: %+6.1f [id: S%02d-%d-%d]",
+ ident, iStack/5, iStack%5, fTrackingData->GetTrackPt(iStack, iTrk), fTrackingData->GetTrackPID(iStack, iTrk),
+ rpt, iStack/5, iStack%5, iTrk);
+ }
+
+ // log output for subsequent offline analysis
+ if ((fDebugLevel >= 3) && (trdElectronCandidate || hltElectronCandidate)){
+ trackExchangeInfo = "";
+ flags = "";
+ if (trdElectronCandidate)
+ flags += "G";
+ if (hltElectronCandidate)
+ flags += "H";
+ AssignTrackInfo(&trackExchangeInfo, iStack, iTrk, flags.Data());
+ LogDebug("%s\n", trackExchangeInfo.Data());
+ }
+
+ } // loop over tracks in stack
+ } // loop over stacks
+
+ if (highPtElectronSeenGTU || highPtElectronSeen){
+ LogInspect("#hlt-trd-trg - event triggered by %s electron trigger (TRD L1: %d, TRD HLT: %d)",
+ ident, highPtElectronSeenGTU, highPtElectronSeen);
+ }
+
+ if (highPtElectronSeenGTU){
+ if (fIsMinBiasEvent)
+ fHistElectronTriggerBaseMinBias->Fill(1.);
+ }
+
+ if (highPtElectronSeen){
+ if (fIsMinBiasEvent)
+ fHistElectronTriggerBaseMinBias->Fill(2.);
+ if (fIsTRDElectronEvent)
+ fHistElectronTriggerBaseTrdL1->Fill(1.);
+ }
+
+ return (highPtElectronSeen) ? kTRUE : kFALSE;
+}
+
+
+int AliHLTTRDTriggerComponent::DoTrigger()
+{
+
+ fEsdEvent = NULL;
+ fRunNumber = -1;
+ int iResult = 0;
+ UShort_t firedTriggers = 0;
+
+ const AliHLTComponentEventData* hltEventData = GetEventData();
+ fEventId = hltEventData->fEventID;
+ LogDebug("### START DoTrigger [event id: %llu, %d blocks, size: %d]",
+ fEventId, hltEventData->fBlockCnt, hltEventData->fStructSize);
+
+// LogDebug("### START DoTrigger [event id: %llu, %d blocks, size: %d]",
+// fEventId, hltEventData->fBlockCnt, hltEventData->fStructSize);
+
+ if (!IsDataEvent()) { // process data events only
+ IgnoreEvent();
+ LogDebug("### END DoTrigger [event id: %llu, %d blocks, size: %d] (skipped: no data event)",
+ fEventId, hltEventData->fBlockCnt, hltEventData->fStructSize);
+ return iResult;
+ }
+
+ fTrackingData->SetLogPrefix(Form("TRDHLTGM XXXXXX-%05llu: [TRG] {TrkDat} ", fEventId));
+
+ do {
+
+ // access to TRD specific data from AliHLTTRDPreprocessorComponent
+ if (!PrepareTRDData()){
+ LogError("access to TRD data failed. Skipping event...");
+ break;
+ }
+
+ if (fTrackingData->GetNumTracks() + fTrackingData->GetNumTracklets() == 0) {
+ LogDebug("no trigger-relevant TRD information, skipping further event processing");
+ break;
+ }
+
+ // access to ESD data
+ if (!PrepareESDData()){
+ LogInfo("access to ESD event data failed.");
+ }
+
+ // access to alternative HLT data
+ if (!fESDtracksPresent){
+ if (!PrepareHLTData()){
+ LogError("access to HLT event data failed.");
+ }
+ }
+
+ // match TRD and HLT tracks
+ if (fESDtracksPresent){
+ if (!MatchTRDTracksESD()){
+ LogError("matching TRD tracks to ESD tracks failed. Skipping event...");
+ break;
+ }
+ } else if (fHLTtracksPresent){
+ if (!MatchTRDTracksHLT()){
+ LogError("matching TRD tracks to HLT tracks failed. Skipping event...");
+ break;
+ }
+ } else {
+ LogError("No HLT track information available. Skipping event...");
+ break;
+ }
+
+// if (!MatchTRDTracks()){
+// LogError("matching TRD tracks to TPC tracks failed. Skipping event...");
+// break;
+// }
+
+ if (fDebugLevel >= 1)
+ DumpTrackingData();
+
+ // evaluate electron trigger conditions
+ if (TRDElectronTrigger("HSE", fElectronTriggerPtThresholdHSE, fElectronTriggerPIDThresholdHSE))
+ firedTriggers |= fkElectronTriggerHSE;
+
+ if (TRDElectronTrigger("HQU", fElectronTriggerPtThresholdHQU, fElectronTriggerPIDThresholdHQU))
+ firedTriggers |= fkElectronTriggerHQU;
+
+ break;
+
+ } while (1);
+
+
+ // trigger decision
+ TString description("");
+ if (firedTriggers & fkElectronTriggerHSE){
+ if (description.Length() > 0)
+ description += " ";
+ description += fgkTriggerDecisionElectronHSE;
+ }
+
+ if (firedTriggers & fkElectronTriggerHQU){
+ if (description.Length() > 0)
+ description += " ";
+ description += fgkTriggerDecisionElectronHQU;
+ }
+
+ SetDescription(description.Data());
+ AliHLTTriggerDecision decision((firedTriggers) ? kTRUE : kFALSE,
+ GetTriggerName(),
+ GetReadoutList(),
+ GetDescription()
+ );
+ TriggerEvent(&decision, kAliHLTDataTypeTObject | kAliHLTDataOriginOut);
+
+ if (firedTriggers){
+ LogInspect("TRD HLT trigger fired for event: description: >%s<, flags: 0x%04x",
+ description.Data(), firedTriggers);
+#ifdef __TRDHLTDEBUG
+ if (fEventRendering)
+ RenderEvent();
+#endif
+ } else {
+ LogDebug("TRD HLT trigger did not fire for event");
+ }
+
+ if (fPushHistos){
+ PushBack(fHistArray, (kAliHLTDataTypeTObjArray | kAliHLTDataOriginTRD), 0x3fffff);
+ }
+
+ LogDebug("### END DoTrigger [event id: %llu, %d blocks, size: %d]",
+ fEventId, hltEventData->fBlockCnt, hltEventData->fStructSize);
+
+ return iResult;
+}
+
+Bool_t AliHLTTRDTriggerComponent::TrackPlaneIntersect(AliExternalTrackParam *trk, Double_t pnt[3], Double_t norm[3], Double_t mag){
+
+ UInt_t its = 0;
+ Double_t r = 290.;
+ Double_t dist = 99999, dist_prev = 99999;
+ Double_t x[3] = {0., 0., 0.};
+ Bool_t ret = kTRUE;
+
+ dist = (x[0] - pnt[0]) * norm[0] + (x[1] - pnt[1]) *norm[1] + (x[2] - pnt[2]) * norm[2];
+
+ while(TMath::Abs(dist) > 0.1) {
+
+ trk->GetXYZAt(r, mag, x);
+
+ if ((x[0] * x[0] + x[1] * x[1]) < 100.) { // extrapolation to radius failed
+ ret = kFALSE;
+ break;
+ }
+
+ //distance between current track position and plane
+ dist_prev = TMath::Abs(dist);
+ dist = (x[0] - pnt[0]) * norm[0] + (x[1] - pnt[1]) * norm[1];
+ r -= dist;
+ its++;
+ if(TMath::Abs(dist) >= dist_prev ||
+ (r > 380.) || (r < 100.)){
+ ret = kFALSE;
+ break;
+ }
+ }
+
+ for (Int_t i=0; i<3; i++){
+ if(ret)
+ pnt[i] = x[i];
+ else
+ pnt[i] = 0.;
+ }
+
+ return kTRUE;
+}
+
+
+Double_t AliHLTTRDTriggerComponent::RateTrackMatch(Double_t distY, Double_t distZ, Double_t rpt, Double_t gpt){
+
+ // maximum limits for spatial distance
+ if ((distY > 5.) || (distZ > 20.))
+ return 0.;
+
+ // same pt sign required
+ if ((rpt * gpt) < 0.)
+ return 0.;
+
+ Double_t rating_distY = -0.1 * distY + 1.;
+ Double_t rating_distZ = -0.025 * distZ + 1.;
+ Double_t rating_ptDiff = 1. - TMath::Abs((TMath::Abs(rpt) > 0.000001) ? ((gpt-rpt)/rpt) : 0.);
+
+ if (rating_ptDiff < 0.)
+ rating_ptDiff = 0.2;
+
+ Double_t total = rating_distY * rating_distZ * rating_ptDiff;
+
+// DbgLog("", Form("#matching: rating: dy: %.3f dz: %.3f dpt: %.3f -> total: %.3f",
+// rating_distY, rating_distZ, rating_ptDiff, total));
+
+ if (total > 1.)
+ LogError("track match rating exceeds limit of 1.0: %.3f", total);
+
+ return total;
+}
+
+Int_t AliHLTTRDTriggerComponent::EstimateTrackDistance(AliESDtrack *esd_track,
+ const UShort_t stack,
+ const UShort_t layerMask,
+ const Float_t trklLocalY[6], const Int_t trklBinZ[6],
+ Double_t mag, Double_t *ydist, Double_t *zdist){
+ if (!esd_track)
+ return -3;
+
+ AliExternalTrackParam* refParam = NULL;
+ if (esd_track->GetOuterParam())
+ refParam = new AliExternalTrackParam(*(esd_track->GetOuterParam()));
+ if (!refParam)
+ refParam = new AliExternalTrackParam(*(esd_track));
+
+ Int_t res = EstimateTrackDistance(refParam, stack, layerMask, trklLocalY, trklBinZ, mag, ydist, zdist);
+
+ if (refParam)
+ delete refParam;
+
+ return res;
+
+}
+
+Int_t AliHLTTRDTriggerComponent::EstimateTrackDistance(AliExternalTrackParam *refParam,
+ const UShort_t stack,
+ const UShort_t layerMask,
+ const Float_t trklLocalY[6], const Int_t trklBinZ[6],
+ Double_t mag, Double_t *ydist, Double_t *zdist){
+
+ Float_t diff_y = 0;
+ Float_t diff_z = 0;
+ Int_t nLayers = 0;
+ Double_t xtrkl[3];
+ Double_t ptrkl[3];
+ Double_t ptrkl2[3];
+ UInt_t trklDet;
+ UShort_t trklLayer;
+ UInt_t stack_gtu;
+ UShort_t stackInSector;
+
+ AliTRDpadPlane* padPlane;
+
+ for (UShort_t iLayer = 0; iLayer < 6; iLayer++){
+ if ((layerMask >> iLayer) & 1){
+ trklDet = stack*6 + iLayer;
+ trklLayer = iLayer;
+ stack_gtu = stack;
+ stackInSector = stack % 5;
+
+ // local coordinates of the outer end point of the tracklet
+ xtrkl[0] = AliTRDgeometry::AnodePos();
+ xtrkl[1] = trklLocalY[iLayer];
+
+ padPlane = fTRDGeometry->GetPadPlane(trklLayer, stackInSector);
+ if(stackInSector == 2){ // corrected version by Felix Muecke
+ xtrkl[2] = padPlane->GetRowPos(trklBinZ[iLayer]) - (padPlane->GetRowSize(trklBinZ[iLayer]))/2. - padPlane->GetRowPos(6);
+ } else {
+ xtrkl[2] = padPlane->GetRowPos(trklBinZ[iLayer]) - (padPlane->GetRowSize(trklBinZ[iLayer]))/2. - padPlane->GetRowPos(8);
+ }
+
+ // transform to global coordinates
+ TGeoHMatrix *matrix = fTRDGeometry->GetClusterMatrix(trklDet);
+ if (!matrix){
+ LogError("invalid TRD cluster matrix in EstimateTrackDistance for detector %i", trklDet);
+ return -5;
+ }
+ matrix->LocalToMaster(xtrkl, ptrkl);
+ fTRDGeometry->RotateBack((stack/5) * 30, ptrkl, ptrkl2); // ptrkl2 now contains the global position of the outer end point of the tracklet
+
+ // calculate parameterization of plane representing the tracklets layer
+ Double_t layer_zero_local[3] = {0., 0., 0.};
+ Double_t layer_zero_global[3], layer_zero_global2[3];
+
+ matrix->LocalToMaster(layer_zero_local, layer_zero_global);
+ fTRDGeometry->RotateBack(trklDet, layer_zero_global, layer_zero_global2); // layer_zero_global2 points to chamber origin in global coords
+
+ Double_t layer_ref_local[3] = {AliTRDgeometry::AnodePos(), 0., 0.};
+ Double_t layer_ref_global[3], layer_ref_global2[3];
+
+ matrix->LocalToMaster(layer_ref_local, layer_ref_global);
+ fTRDGeometry->RotateBack(trklDet, layer_ref_global, layer_ref_global2); // layer_ref_global2 points to center anode pos within plane in global coords
+
+ Double_t n0[3] = {layer_ref_global2[0]-layer_zero_global2[0],
+ layer_ref_global2[1]-layer_zero_global2[1],
+ layer_ref_global2[2]-layer_zero_global2[2]};
+
+ Double_t n_len = TMath::Sqrt(n0[0]*n0[0] + n0[1]*n0[1] + n0[2]*n0[2]);
+ if (n_len == 0.){ // This should never happen
+ //printf("<ERROR> divison by zero in estimate_track_distance!");
+ n_len = 1.;
+ }
+ Double_t n[3] = {n0[0]/n_len, n0[1]/n_len, n0[2]/n_len}; // normal vector of plane
+
+ Bool_t isects = TrackPlaneIntersect(refParam, layer_ref_global2, n, mag); // find intersection point between track and TRD layer
+
+ if (isects == kFALSE){ // extrapolation fails, because track never reaches the TRD radius
+ return -1;
+ }
+
+ Double_t m[2] = {ptrkl2[0] - layer_ref_global2[0], ptrkl2[1] - layer_ref_global2[1]};
+ Double_t len_m = TMath::Sqrt(m[0]*m[0] + m[1]*m[1]);
+ diff_y += len_m;
+ diff_z += TMath::Abs(ptrkl2[2] - layer_ref_global2[2]);
+ nLayers++;
+ }
+ }
+
+ if (nLayers > 0){
+ *ydist = diff_y / nLayers;
+ *zdist = diff_z / nLayers;
+ return 0;
+ } else {
+ LogError("invalid number of contributing layers (%d) in EstimateTrackDistance()", nLayers);
+ return -4;
+ }
+}