Line data Source code
1 : /**************************************************************************
2 : * This file is property of and copyright by the ALICE HLT Project *
3 : * All rights reserved. *
4 : * *
5 : * Primary Authors: Markus Fasel *
6 : * *
7 : * Permission to use, copy, modify and distribute this software and its *
8 : * documentation strictly for non-commercial purposes is hereby granted *
9 : * without fee, provided that the above copyright notice appears in all *
10 : * copies and that both the copyright notice and this permission notice *
11 : * appear in the supporting documentation. The authors make no claims *
12 : * about the suitability of this software for any purpose. It is *
13 : * provided "as is" without express or implied warranty. *
14 : **************************************************************************/
15 : #include <vector>
16 :
17 : #include "AliEMCALTriggerTypes.h"
18 : #include "AliEMCALGeometry.h"
19 : #include "AliEMCALTriggerBitConfig.h"
20 : #include "AliEMCALTriggerMapping.h"
21 : #include "AliEMCALTriggerTypes.h"
22 : #include "AliEMCALTriggerAlgorithm.h"
23 : #include "AliEMCALTriggerDataGrid.h"
24 : #include "AliEMCALTriggerPatchFinder.h"
25 : #include "AliEMCALTriggerPatchInfo.h"
26 : #include "AliEMCALTriggerRawPatch.h"
27 : #include "AliEMCALTriggerConstants.h"
28 :
29 : #include "AliHLTCaloDigitDataStruct.h"
30 : #include "AliHLTCaloTriggerPatchContainerStruct.h"
31 : #include "AliHLTCaloTriggerPatchDataStruct.h"
32 : #include "AliHLTEMCALGeometry.h"
33 : #include "AliHLTEMCALTriggerMaker.h"
34 :
35 6 : ClassImp(AliHLTEMCALTriggerMaker)
36 :
37 : AliHLTEMCALTriggerMaker::AliHLTEMCALTriggerMaker() :
38 0 : TObject(),
39 0 : AliHLTLogging(),
40 0 : fTriggerPatchDataPtr(NULL),
41 0 : fkGeometryPtr(NULL),
42 27 : fPatchFinder(NULL),
43 0 : fL0PatchFinder(NULL),
44 0 : fADCValues(NULL),
45 0 : fADCOfflineValues(NULL),
46 0 : fL0Amplitudes(NULL),
47 0 : fTriggerBitMasks(NULL),
48 0 : fLevel0TimeMap(NULL),
49 0 : fTRUIndexMap(NULL),
50 0 : fTriggerBitConfig(NULL),
51 0 : fJetPatchSize(8),
52 0 : fJetSubregionSize(4),
53 0 : fGammaPatchSize(2),
54 0 : fGammaSubregionSize(1),
55 0 : fBkgPatchSize(8),
56 0 : fBkgSubregionSize(4),
57 0 : fL0MinTime(7),
58 0 : fL0MaxTime(10),
59 0 : fBufferSize(0),
60 0 : fBkgThresholdOnline(-0.1),
61 0 : fBkgThresholdOffline(-0.1),
62 0 : fRunBkgAlgorithm(kTRUE),
63 0 : fLevel0ThresholdOnline(0),
64 0 : fLevel0ThresholdOffline(0)
65 0 : {
66 0 : fTriggerBitConfig = new AliEMCALTriggerBitConfigNew;
67 0 : memset(fJetThresholdOnline, 0, sizeof(Float_t) * kNthresholds);
68 0 : memset(fJetThresholdOffline, 0, sizeof(Float_t) * kNthresholds);
69 0 : memset(fGammaThresholdOnline, 0, sizeof(Float_t) * kNthresholds);
70 0 : memset(fGammaThresholdOffline, 0, sizeof(Float_t) * kNthresholds);
71 0 : }
72 :
73 0 : AliHLTEMCALTriggerMaker::~AliHLTEMCALTriggerMaker() {
74 0 : if(fTriggerBitConfig) delete fTriggerBitConfig;
75 0 : if(fPatchFinder) delete fPatchFinder;
76 0 : if(fL0PatchFinder) delete fL0PatchFinder;
77 0 : if(fADCValues) delete fADCValues;
78 0 : if(fADCOfflineValues) delete fADCOfflineValues;
79 0 : if(fL0Amplitudes) delete fL0Amplitudes;
80 0 : if(fTriggerBitMasks) delete fTriggerBitMasks;
81 0 : if(fLevel0TimeMap) delete fLevel0TimeMap;
82 0 : }
83 :
84 : void AliHLTEMCALTriggerMaker::ResetADC(){
85 0 : fADCValues->Reset();
86 0 : fADCOfflineValues->Reset();
87 0 : fL0Amplitudes->Reset();
88 0 : fTriggerBitMasks->Reset();
89 0 : fLevel0TimeMap->Reset();
90 0 : }
91 :
92 : void AliHLTEMCALTriggerMaker::AddDigit(const AliHLTCaloDigitDataStruct *digit){
93 : /*
94 : * TODO Crosscheck
95 : */
96 0 : Int_t fastorIndex;
97 0 : fkGeometryPtr->GetGeometryPtr()->GetTriggerMapping()->GetFastORIndexFromCellIndex(fkGeometryPtr->GetGeometryPtr()->GetAbsCellIdFromCellIndexes(digit->fModule, digit->fX, digit->fZ), fastorIndex);
98 0 : int globCol, globRow;
99 0 : fkGeometryPtr->GetGeometryPtr()->GetTriggerMapping()->GetPositionInEMCALFromAbsFastORIndex(fastorIndex, globCol, globRow);
100 0 : (*fADCOfflineValues)(globCol, globRow) += digit->fEnergy/EMCALTrigger::kEMCL1ADCtoGeV;
101 0 : }
102 :
103 : void AliHLTEMCALTriggerMaker::SetADC(Int_t col, Int_t row, Float_t adc){
104 0 : (*fADCValues)(col, row) = adc;
105 0 : }
106 :
107 : void AliHLTEMCALTriggerMaker::SetL0Amplitude(Int_t col, Int_t row, Float_t amp){
108 0 : (*fL0Amplitudes)(col, row) = amp*4; // to compensate for the last two bits that are chopped away in the hardware chain
109 0 : }
110 :
111 : void AliHLTEMCALTriggerMaker::SetL0Time(Int_t col, Int_t row, UChar_t time){
112 0 : (*fLevel0TimeMap)(col, row) = time;
113 0 : }
114 :
115 : void AliHLTEMCALTriggerMaker::SetBitMask(Int_t col, Int_t row, Int_t bitMask){
116 0 : (*fTriggerBitMasks)(col, row) = bitMask;
117 0 : }
118 :
119 : Int_t AliHLTEMCALTriggerMaker::FindPatches(){
120 : /*
121 : if(availableSize < sizeof(AliHLTCaloTriggerPatchDataStruct)){
122 : HLTError("Not enough space to write new trigger patches");
123 : return -1;
124 : }
125 : */
126 :
127 : //AliHLTUInt32_t mysize = availableSize;
128 0 : std::vector<AliEMCALTriggerRawPatch> foundpatches = fPatchFinder->FindPatches(*fADCValues, *fADCOfflineValues);
129 : Int_t patchcount = 0;
130 : AliHLTCaloTriggerPatchDataStruct *next = NULL;
131 0 : for(std::vector<AliEMCALTriggerRawPatch>::iterator patchiter = foundpatches.begin(); patchiter != foundpatches.end(); ++patchiter){
132 0 : if(fBufferSize < sizeof(AliHLTCaloTriggerPatchDataStruct)){
133 0 : HLTWarning("Buffer exceeded after %d trigger patches", patchcount);
134 0 : break;
135 : }
136 0 : if(HasPHOSOverlap(*patchiter)) continue;
137 0 : next = fTriggerPatchDataPtr + 1;
138 : // Set offline bits
139 : // Note: trigger patch can contain more than one patch type
140 : UInt_t offlinebits = 0, onlinebitmask = 0;
141 0 : if(patchiter->GetPatchSize() == fGammaPatchSize){
142 : onlinebitmask = 1 << kL1GammaHigh | 1 << kL1GammaLow | 1 << (kL1GammaHigh + kTriggerTypeEnd) | 1 << (kL1GammaLow + kTriggerTypeEnd);
143 0 : if(patchiter->GetADC() > fGammaThresholdOnline[kHighThreshold]) SETBIT(offlinebits, AliEMCALTriggerPatchInfo::kRecalcOffset + fTriggerBitConfig->GetGammaHighBit());
144 0 : if(patchiter->GetOfflineADC() > fGammaThresholdOffline[kHighThreshold]) SETBIT(offlinebits, AliEMCALTriggerPatchInfo::kOfflineOffset + fTriggerBitConfig->GetGammaHighBit());
145 0 : if(patchiter->GetADC() > fGammaThresholdOnline[kLowThreshold]) SETBIT(offlinebits, AliEMCALTriggerPatchInfo::kRecalcOffset + fTriggerBitConfig->GetGammaLowBit());
146 0 : if(patchiter->GetOfflineADC() > fGammaThresholdOffline[kLowThreshold]) SETBIT(offlinebits, AliEMCALTriggerPatchInfo::kOfflineOffset + fTriggerBitConfig->GetGammaLowBit());
147 : }
148 0 : if (patchiter->GetPatchSize() == fJetPatchSize){
149 : onlinebitmask = 1 << kL1JetHigh | 1 << kL1JetLow | 1 << (kL1JetHigh + kTriggerTypeEnd) | 1 << (kL1JetLow + kTriggerTypeEnd);
150 0 : if(patchiter->GetADC() > fJetThresholdOnline[kHighThreshold]) SETBIT(offlinebits, AliEMCALTriggerPatchInfo::kRecalcOffset + fTriggerBitConfig->GetJetHighBit());
151 0 : if(patchiter->GetOfflineADC() > fJetThresholdOffline[kHighThreshold]) SETBIT(offlinebits, AliEMCALTriggerPatchInfo::kOfflineOffset + fTriggerBitConfig->GetJetHighBit());
152 0 : if(patchiter->GetADC() > fJetThresholdOnline[kLowThreshold]) SETBIT(offlinebits, AliEMCALTriggerPatchInfo::kRecalcOffset + fTriggerBitConfig->GetJetLowBit());
153 0 : if(patchiter->GetOfflineADC() > fJetThresholdOffline[kLowThreshold]) SETBIT(offlinebits, AliEMCALTriggerPatchInfo::kOfflineOffset + fTriggerBitConfig->GetJetLowBit());
154 : }
155 0 : if (patchiter->GetPatchSize() == fBkgPatchSize){
156 0 : if(patchiter->GetADC() > fBkgThresholdOnline) SETBIT(offlinebits, AliEMCALTriggerPatchInfo::kRecalcOffset + fTriggerBitConfig->GetBkgBit());
157 0 : if(patchiter->GetOfflineADC() > fBkgThresholdOffline) SETBIT(offlinebits, AliEMCALTriggerPatchInfo::kOfflineOffset + fTriggerBitConfig->GetBkgBit());
158 : }
159 0 : MakeHLTPatch(*patchiter, *fTriggerPatchDataPtr, offlinebits, onlinebitmask, 0);
160 0 : fTriggerPatchDataPtr = next;
161 0 : patchcount++;
162 0 : fBufferSize -= sizeof(AliHLTCaloTriggerPatchDataStruct);
163 0 : }
164 :
165 : // Do Level0 patches as well
166 0 : std::vector<AliEMCALTriggerRawPatch> l0patches = fL0PatchFinder->FindPatches(*fL0Amplitudes, *fADCOfflineValues);
167 0 : for(std::vector<AliEMCALTriggerRawPatch>::iterator patchit = l0patches.begin(); patchit != l0patches.end(); ++patchit){
168 0 : if(fBufferSize < sizeof(AliHLTCaloTriggerPatchDataStruct)){
169 0 : HLTWarning("Buffer exceeded after %d trigger patches", patchcount);
170 0 : break;
171 : }
172 0 : if(HasPHOSOverlap(*patchit)) continue;
173 0 : ELevel0TriggerStatus_t L0trigger = CheckForL0(patchit->GetColStart(), patchit->GetRowStart());
174 : // Check that it is a valid L0 patch candidate, i.e. all FastORs in the same TRU
175 0 : if (L0trigger == kNotLevel0) continue;
176 : Int_t onlinebits(0), offlinebits(0);
177 0 : if (L0trigger == kLevel0Fired) SETBIT(onlinebits, fTriggerBitConfig->GetLevel0Bit()+fTriggerBitConfig->GetTriggerTypesEnd());
178 : // No requirement on L0 time for offline and recalc patches, only they have to be in the same TRU
179 0 : if (patchit->GetADC() > fLevel0ThresholdOnline) SETBIT(offlinebits, AliEMCALTriggerPatchInfo::kRecalcOffset + fTriggerBitConfig->GetLevel0Bit());
180 0 : if (patchit->GetOfflineADC() > fLevel0ThresholdOffline) SETBIT(offlinebits, AliEMCALTriggerPatchInfo::kOfflineOffset + fTriggerBitConfig->GetLevel0Bit());
181 0 : if (!(offlinebits || onlinebits)) continue;
182 0 : next = fTriggerPatchDataPtr + 1;
183 0 : MakeHLTPatch(*patchit, *fTriggerPatchDataPtr, offlinebits, 0, onlinebits);
184 0 : fTriggerPatchDataPtr = next;
185 0 : patchcount++;
186 0 : fBufferSize -= sizeof(AliHLTCaloTriggerPatchDataStruct);
187 0 : }
188 : return patchcount;
189 0 : }
190 :
191 : void AliHLTEMCALTriggerMaker::Initialise(const AliHLTEMCALGeometry *geo){
192 0 : fkGeometryPtr = geo;
193 :
194 : // Allocate
195 0 : fADCValues = new AliEMCALTriggerDataGrid<float>;
196 0 : fADCValues->Allocate(48, fkGeometryPtr->GetGeometryPtr()->GetNTotalTRU() * 2);
197 :
198 0 : fADCOfflineValues = new AliEMCALTriggerDataGrid<float>;
199 0 : fADCOfflineValues->Allocate(48, fkGeometryPtr->GetGeometryPtr()->GetNTotalTRU() * 2);
200 :
201 0 : fL0Amplitudes = new AliEMCALTriggerDataGrid<float>;
202 0 : fL0Amplitudes->Allocate(48, fkGeometryPtr->GetGeometryPtr()->GetNTotalTRU() * 2);
203 :
204 0 : fTriggerBitMasks = new AliEMCALTriggerDataGrid<int>;
205 0 : fTriggerBitMasks->Allocate(48, fkGeometryPtr->GetGeometryPtr()->GetNTotalTRU() * 2);
206 :
207 0 : fLevel0TimeMap = new AliEMCALTriggerDataGrid<unsigned char>;
208 0 : fLevel0TimeMap->Allocate(48, fkGeometryPtr->GetGeometryPtr()->GetNTotalTRU() * 2);
209 :
210 0 : fPatchFinder = new AliEMCALTriggerPatchFinder<float>;
211 0 : InitializeLevel1PatchFinders(false);
212 0 : if(fkGeometryPtr->GetGeometryPtr()->GetNumberOfSuperModules() > 12){
213 0 : InitializeLevel1PatchFinders(true);
214 0 : }
215 :
216 0 : fL0PatchFinder = new AliEMCALTriggerPatchFinder<float>;
217 0 : InitializeLevel0PatchFinders(false);
218 0 : if(fkGeometryPtr->GetGeometryPtr()->GetNumberOfSuperModules() > 12){
219 0 : InitializeLevel0PatchFinders(true);
220 0 : }
221 :
222 0 : InitializeLookupTables();
223 0 : }
224 :
225 : void AliHLTEMCALTriggerMaker::InitializeLevel1PatchFinders(Bool_t isDCAL){
226 0 : Int_t rowMin = isDCAL ? 64 : 0, rowMax = isDCAL ? 103 : 63;
227 0 : AliEMCALTriggerAlgorithm<float> *gammatrigger = new AliEMCALTriggerAlgorithm<float>(rowMin, rowMax, 0);
228 0 : gammatrigger->SetThresholds(0, 0);
229 0 : gammatrigger->SetPatchSize(fGammaPatchSize);
230 0 : gammatrigger->SetSubregionSize(fGammaSubregionSize);
231 0 : fPatchFinder->AddTriggerAlgorithm(gammatrigger);
232 0 : AliEMCALTriggerAlgorithm<float> *jettrigger = new AliEMCALTriggerAlgorithm<float>(rowMin, rowMax, 0);
233 0 : jettrigger->SetThresholds(0, 0);
234 0 : jettrigger->SetPatchSize(fJetPatchSize);
235 0 : jettrigger->SetSubregionSize(fJetSubregionSize);
236 0 : fPatchFinder->AddTriggerAlgorithm(jettrigger);
237 0 : if(fRunBkgAlgorithm){
238 0 : AliEMCALTriggerAlgorithm<float> *jetmedian = new AliEMCALTriggerAlgorithm<float>(rowMin, rowMax, 0);
239 0 : jetmedian->SetThresholds(-1, -1);
240 0 : jetmedian->SetPatchSize(fBkgPatchSize);
241 0 : jetmedian->SetSubregionSize(fBkgSubregionSize);
242 0 : fPatchFinder->AddTriggerAlgorithm(jetmedian);
243 0 : }
244 0 : }
245 :
246 : void AliHLTEMCALTriggerMaker::InitializeLevel0PatchFinders(Bool_t isDCAL){
247 0 : AliEMCALTriggerAlgorithm<float> *l0trigger = new AliEMCALTriggerAlgorithm<float>(isDCAL ? 64 : 0, isDCAL ? 103 : 63, 0);
248 0 : l0trigger->SetThresholds(0, 0);
249 0 : l0trigger->SetPatchSize(2);
250 0 : l0trigger->SetSubregionSize(1);
251 0 : fL0PatchFinder->AddTriggerAlgorithm(l0trigger);
252 0 : }
253 :
254 : void AliHLTEMCALTriggerMaker::MakeHLTPatch(const AliEMCALTriggerRawPatch &input, AliHLTCaloTriggerPatchDataStruct &output, UInt_t offlinebits, UInt_t onlinebitmask, UInt_t level0bits) const {
255 0 : output.fCol = input.GetColStart();
256 0 : output.fRow = input.GetRowStart();
257 0 : output.fSize = input.GetPatchSize();
258 0 : output.fADC = input.GetADC();
259 0 : output.fOfflineADC = input.GetOfflineADC();
260 0 : Int_t onlinebits = (*fTriggerBitMasks)(output.fCol, output.fRow) & onlinebitmask;
261 0 : output.fBitMask = input.GetBitmask() | onlinebits | offlinebits | level0bits;
262 0 : }
263 :
264 : void AliHLTEMCALTriggerMaker::InitializeLookupTables(){
265 0 : fTRUIndexMap = new AliEMCALTriggerDataGrid<int>;
266 0 : fTRUIndexMap->Allocate(48, fkGeometryPtr->GetGeometryPtr()->GetNTotalTRU() * 2);
267 0 : int absFastor, truid, adc;
268 0 : for(int icol = 0; icol < 48; icol++){
269 0 : for(int irow = 0; irow < fkGeometryPtr->GetGeometryPtr()->GetNTotalTRU() * 2; irow++){
270 0 : fkGeometryPtr->GetGeometryPtr()->GetAbsFastORIndexFromPositionInEMCAL(icol, irow, absFastor);
271 0 : fkGeometryPtr->GetGeometryPtr()->GetTRUFromAbsFastORIndex(absFastor, truid, adc);
272 0 : (*fTRUIndexMap)(icol, irow) = truid;
273 : }
274 : }
275 0 : }
276 :
277 : AliHLTEMCALTriggerMaker::ELevel0TriggerStatus_t AliHLTEMCALTriggerMaker::CheckForL0(Int_t col, Int_t row) const {
278 : ELevel0TriggerStatus_t result = kLevel0Candidate;
279 :
280 0 : if(col < 0 || row < 0){
281 0 : AliError(Form("Patch outside range [col %d, row %d]", col, row));
282 0 : return kNotLevel0;
283 : }
284 0 : Int_t truref = (*fTRUIndexMap)(col, row), trumod(-1);
285 : const Int_t kColsEta = 48;
286 0 : const int kNRowsPhi = fkGeometryPtr->GetGeometryPtr()->GetNTotalTRU() * 2;
287 0 : for(int ipos = 0; ipos < 2; ipos++){
288 0 : if(row + ipos >= kNRowsPhi) continue; // boundary check
289 0 : for(int jpos = 0; jpos < 2; jpos++){
290 0 : if(col + jpos >= kColsEta) continue; // boundary check
291 : // Check whether we are in the same TRU
292 0 : trumod = (*fTRUIndexMap)(col + jpos, row + ipos);
293 0 : if(trumod != truref) {
294 : result = kNotLevel0;
295 0 : return result;
296 : }
297 0 : if(col + jpos >= kColsEta) AliError(Form("Boundary error in col [%d, %d + %d]", col + jpos, col, jpos));
298 0 : if(row + ipos >= kNRowsPhi) AliError(Form("Boundary error in row [%d, %d + %d]", row + ipos, row, ipos));
299 : }
300 : }
301 0 : if (result == kLevel0Candidate) {
302 0 : Char_t l0times = (*fLevel0TimeMap)(col,row);
303 0 : if(l0times > fL0MinTime && l0times < fL0MaxTime) result = kLevel0Fired;
304 0 : }
305 0 : return result;
306 0 : }
307 :
308 : bool AliHLTEMCALTriggerMaker::HasPHOSOverlap(const AliEMCALTriggerRawPatch &patch) const {
309 : const int kEtaMinPhos = 16, kEtaMaxPhos = 31, kPhiMinPhos = 64, kPhiMaxPhos = 99;
310 0 : if(patch.GetRowStart() + patch.GetPatchSize() -1 < kPhiMinPhos) return false; // EMCAL Patch
311 0 : if(patch.GetRowStart() > kPhiMaxPhos) return false; // DCAL 1/3 supermodule
312 0 : if(patch.GetColStart() + patch.GetPatchSize() -1 < kEtaMinPhos) return false;
313 0 : if(patch.GetColStart() > kEtaMaxPhos) return false;
314 0 : return true;
315 0 : }
|