Fix coverity defect
[u/mrichter/AliRoot.git] / MUON / AliMUONSimpleClusterServer.cxx
CommitLineData
d08b5461 1/**************************************************************************
2* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3* *
4* Author: The ALICE Off-line Project. *
5* Contributors are mentioned in the code where appropriate. *
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
16// $Id$
17
18#include "AliMUONSimpleClusterServer.h"
19
9bf6860b 20#include "AliCodeTimer.h"
21#include "AliLog.h"
d08b5461 22#include "AliMUONCluster.h"
9bf6860b 23#include "AliMUONConstants.h"
d08b5461 24#include "AliMUONGeometryTransformer.h"
25#include "AliMUONPad.h"
9bf6860b 26#include "AliMUONTriggerTrackToTrackerClusters.h"
d08b5461 27#include "AliMUONVCluster.h"
28#include "AliMUONVClusterFinder.h"
29#include "AliMUONVClusterStore.h"
30#include "AliMUONVDigitStore.h"
35be7ed7 31#include "AliMUONRecoParam.h"
d08b5461 32#include "AliMpArea.h"
33#include "AliMpDEIterator.h"
34#include "AliMpDEManager.h"
35#include "AliMpExMap.h"
e5b8601d 36#include "AliMpExMapIterator.h"
9bf6860b 37#include "AliMpPad.h"
d08b5461 38#include "AliMpSegmentation.h"
39#include "AliMpVSegmentation.h"
d08b5461 40#include <Riostream.h>
9e41a340 41#include <TObjArray.h>
d08b5461 42#include <TString.h>
9bf6860b 43#include <float.h>
7deb8eb0 44
d08b5461 45/// \class AliMUONSimpleClusterServer
46///
47/// Implementation of AliMUONVClusterServer interface
48///
49///
50/// \author Laurent Aphecetche, Subatech
51
52/// \cond CLASSIMP
53ClassImp(AliMUONSimpleClusterServer)
54/// \endcond
55
56namespace
57{
58 TString AsString(const AliMpArea& area)
59 {
60 return Form("(X,Y)=(%7.3f,%7.3f) (DX,DY)=(%7.3f,%7.3f)",
6e97fbb8 61 area.GetPositionX(),
62 area.GetPositionY(),
63 area.GetDimensionX(), /// TBCL was Y !!!
64 area.GetDimensionY());
d08b5461 65 }
66}
67
68//_____________________________________________________________________________
9bf6860b 69AliMUONSimpleClusterServer::AliMUONSimpleClusterServer(AliMUONVClusterFinder* clusterFinder,
d08b5461 70 const AliMUONGeometryTransformer& transformer)
2e2d0c44 71: AliMUONVClusterServer(),
72 fDigitStore(0x0),
d08b5461 73 fClusterFinder(clusterFinder),
72dae9ff 74 fkTransformer(transformer),
d08b5461 75 fPads(),
9bf6860b 76 fTriggerTrackStore(0x0),
77 fBypass(0x0)
d08b5461 78{
79 /// Ctor
9bf6860b 80 /// Note that we take ownership of the clusterFinder
d08b5461 81
630711ed 82 fPads[0] = new AliMpExMap;
83 fPads[1] = new AliMpExMap;
7deb8eb0 84
e5b8601d 85 fPadsIterator[0] = fPads[0]->CreateIterator();
86 fPadsIterator[1] = fPads[1]->CreateIterator();
d08b5461 87}
88
89//_____________________________________________________________________________
90AliMUONSimpleClusterServer::~AliMUONSimpleClusterServer()
91{
92 /// Dtor
9bf6860b 93 delete fClusterFinder;
d08b5461 94 delete fPads[0];
95 delete fPads[1];
e5b8601d 96 delete fPadsIterator[0];
97 delete fPadsIterator[1];
9bf6860b 98 delete fBypass;
d08b5461 99}
100
101//_____________________________________________________________________________
102Int_t
103AliMUONSimpleClusterServer::Clusterize(Int_t chamberId,
104 AliMUONVClusterStore& clusterStore,
35be7ed7 105 const AliMpArea& area,
106 const AliMUONRecoParam* recoParam)
d08b5461 107{
108 /// Area is in absolute coordinate. If not valid, means clusterize all
109 /// the chamber.
110 ///
111 /// We first find out the list of DE that have a non-zero overlap with area,
112 /// and then use the clusterfinder to find clusters in those areas (and DE).
113
99c136e1 114 AliCodeTimerAuto(Form("Chamber %d",chamberId),0);
9bf6860b 115
116 if ( fTriggerTrackStore && chamberId >= 6 )
117 {
118 return fBypass->GenerateClusters(chamberId,clusterStore);
119 }
120
35be7ed7 121 if (!recoParam) {
122 AliError("Reconstruction parameters are missing: unable to clusterize");
123 return 0;
124 }
125
d08b5461 126 AliMpDEIterator it;
127
128 it.First(chamberId);
129
130 Int_t nofAddedClusters(0);
131 Int_t fNCluster = clusterStore.GetSize();
132
133 AliDebug(1,Form("chamberId = %2d NofClusters before = %d searchArea=%s",
134 chamberId,fNCluster,AsString(area).Data()));
135
136 while ( !it.IsDone() )
137 {
138 Int_t detElemId = it.CurrentDEId();
139
9e41a340 140 TObjArray* pads[2] =
d08b5461 141 {
9e41a340 142 static_cast<TObjArray*>(fPads[0]->GetValue(detElemId)),
143 static_cast<TObjArray*>(fPads[1]->GetValue(detElemId))
d08b5461 144 };
145
146 if ( ( pads[0] && pads[0]->GetLast()>=0 ) ||
147 ( pads[1] && pads[1]->GetLast()>=0 ) )
148 {
149 AliMpArea deArea; // area in DE-local-coordinates
150 Bool_t ok(kTRUE);
151
152 if ( area.IsValid() )
153 {
154 ok = Overlap(detElemId,area,deArea);
155 }
156
157 if ( ok )
158 {
2e2d0c44 159 const AliMpVSegmentation* seg[2] =
d08b5461 160 { AliMpSegmentation::Instance()->GetMpSegmentation(detElemId,AliMp::kCath0),
161 AliMpSegmentation::Instance()->GetMpSegmentation(detElemId,AliMp::kCath1)
162 };
110edb51 163
164 fClusterFinder->SetChargeHints(recoParam->LowestPadCharge(),
165 recoParam->LowestClusterCharge());
166
2e2d0c44 167 if ( fClusterFinder->NeedSegmentation() )
168 {
9bf6860b 169 fClusterFinder->Prepare(detElemId,pads,deArea,seg);
d08b5461 170 }
171 else
172 {
9bf6860b 173 fClusterFinder->Prepare(detElemId,pads,deArea);
d08b5461 174 }
175
176 AliDebug(1,Form("Clusterizing DE %04d with %3d pads (cath0) and %3d pads (cath1)",
177 detElemId,
178 (pads[0] ? pads[0]->GetLast()+1 : 0),
179 (pads[1] ? pads[1]->GetLast()+1 : 0)));
180
181 AliMUONCluster* cluster;
182
9bf6860b 183 while ( ( cluster = fClusterFinder->NextCluster() ) )
d08b5461 184 {
185 // add new cluster to the store with information to build its ID
186 // increment the number of clusters into the store
35be7ed7 187 AliMUONVCluster* rawCluster = clusterStore.Add(chamberId, detElemId, fNCluster++);
d08b5461 188
189 ++nofAddedClusters;
190
191 // fill array of Id of digits attached to this cluster
192 Int_t nPad = cluster->Multiplicity();
193 if (nPad < 1) AliWarning("no pad attached to the cluster");
194
195 for (Int_t iPad=0; iPad<nPad; iPad++)
196 {
197 AliMUONPad *pad = cluster->Pad(iPad);
89b4e052 198
199 // skip virtual pads
200 if (!pad->IsReal()) continue;
201
202 rawCluster->AddDigitId(pad->GetUniqueID());
d08b5461 203 }
204
205 // fill charge and other cluster informations
206 rawCluster->SetCharge(cluster->Charge());
89b4e052 207 rawCluster->SetChi2(cluster->Chi2());
d08b5461 208
209 Double_t xg, yg, zg;
72dae9ff 210 fkTransformer.Local2Global(detElemId,
d08b5461 211 cluster->Position().X(), cluster->Position().Y(),
212 0, xg, yg, zg);
213 rawCluster->SetXYZ(xg, yg, zg);
35be7ed7 214 rawCluster->SetErrXY(recoParam->GetDefaultNonBendingReso(chamberId),recoParam->GetDefaultBendingReso(chamberId));
d08b5461 215
91b67b6f 216 // Set MC label
217 if (fDigitStore && fDigitStore->HasMCInformation())
218 {
219 rawCluster->SetMCLabel(FindMCLabel(*cluster, detElemId, seg));
220 }
221
2e2d0c44 222 AliDebug(1,Form("Adding RawCluster detElemId %4d mult %2d charge %e (xl,yl,zl)=(%e,%e,%e) (xg,yg,zg)=(%e,%e,%e) label %d",
89b4e052 223 detElemId,rawCluster->GetNDigits(),rawCluster->GetCharge(),
d08b5461 224 cluster->Position().X(),cluster->Position().Y(),0.0,
2e2d0c44 225 xg,yg,zg,rawCluster->GetMCLabel()));
d08b5461 226 }
227 }
228 }
229 it.Next();
230 }
231
232 AliDebug(1,Form("chamberId = %2d NofClusters after = %d",chamberId,fNCluster));
91b67b6f 233
d08b5461 234 return nofAddedClusters;
235}
236
9bf6860b 237
d08b5461 238//_____________________________________________________________________________
239void
240AliMUONSimpleClusterServer::Global2Local(Int_t detElemId, const AliMpArea& globalArea,
241 AliMpArea& localArea) const
242{
243 /// Convert a global area in local area for a given DE
244
245 Double_t xl,yl,zl;
246
ad30b53f 247 Int_t chamberId = AliMpDEManager::GetChamberId(detElemId);
248 if ( chamberId < 0 ) {
249 AliErrorStream() << "Cannot get chamberId from detElemId=" << detElemId << endl;
250 return;
251 }
252 Double_t zg = AliMUONConstants::DefaultChamberZ(chamberId);
d08b5461 253
72dae9ff 254 fkTransformer.Global2Local(detElemId,
6e97fbb8 255 globalArea.GetPositionX(),globalArea.GetPositionY(),zg,
d08b5461 256 xl,yl,zl);
257
6e97fbb8 258 localArea = AliMpArea(xl,yl, globalArea.GetDimensionX(), globalArea.GetDimensionY());
d08b5461 259}
260
261//_____________________________________________________________________________
262Bool_t
263AliMUONSimpleClusterServer::Overlap(Int_t detElemId,
264 const AliMpArea& area,
265 AliMpArea& deArea) const
266{
267 /// Check whether (global) area overlaps with the given DE.
268 /// If it is, set deArea to the overlap region and convert it
269 /// in the local coordinate system of that DE.
270
271 Bool_t overlap(kFALSE);
272
72dae9ff 273 AliMpArea* globalDEArea = fkTransformer.GetDEArea(detElemId);
9bf6860b 274
275 if (!globalDEArea) return kFALSE;
d08b5461 276
277 AliMpArea overlapArea;
278
279 if ( area.Overlap(*globalDEArea) )
280 {
281 overlapArea = area.Intersect(*globalDEArea);
282 Global2Local(detElemId,overlapArea,deArea);
283 overlap = kTRUE;
284 }
285 else
286 {
287 deArea = AliMpArea();
288 }
289
290 AliDebug(1,Form("DE %04d area %s globalDEArea %s overlapArea %s deArea %s overlap=%d",
291 detElemId,
292 AsString(area).Data(),
293 AsString(*globalDEArea).Data(),
294 AsString(overlapArea).Data(),
295 AsString(deArea).Data(),
296 overlap));
297
298 return overlap;
299}
300
301//_____________________________________________________________________________
9e41a340 302TObjArray*
d08b5461 303AliMUONSimpleClusterServer::PadArray(Int_t detElemId, Int_t cathode) const
304{
305 /// Return array for given cathode of given DE
306
9e41a340 307 return static_cast<TObjArray*>(fPads[cathode]->GetValue(detElemId));
d08b5461 308}
309
310//_____________________________________________________________________________
9bf6860b 311Bool_t
312AliMUONSimpleClusterServer::UseTriggerTrackStore(AliMUONVTriggerTrackStore* trackStore)
313{
314 /// Tells us to use trigger track store, and thus to bypass St45 clusters
315 fTriggerTrackStore = trackStore; // not owner
316 delete fBypass;
72dae9ff 317 fBypass = new AliMUONTriggerTrackToTrackerClusters(fkTransformer,fTriggerTrackStore);
9bf6860b 318 return kTRUE;
319}
320
321//_____________________________________________________________________________
d08b5461 322void
2e2d0c44 323AliMUONSimpleClusterServer::UseDigits(TIter& next, AliMUONVDigitStore* digitStore)
d08b5461 324{
325 /// Convert digitStore into two arrays of AliMUONPads
2e2d0c44 326
327 fDigitStore = digitStore;
328
e5b8601d 329 // Clear pads arrays in the maps
330 for ( Int_t i=0; i<2; i++ ) {
331 fPadsIterator[i]->Reset();
332 Int_t key; TObject* obj;
333 while ( ( obj = fPadsIterator[i]->Next(key) ) ) {
334 //cout << "clearing array for detElemId " << key << " ";
335 obj->Clear();
336 }
337 }
338
d08b5461 339 AliMUONVDigit* d;
d08b5461 340 while ( ( d = static_cast<AliMUONVDigit*>(next()) ) )
341 {
342 if ( ! d->Charge() > 0 ) continue; // skip void digits.
4750f29d 343 if ( ! d->IsTracker() ) continue; // skip trigger digits
d08b5461 344 Int_t ix = d->PadX();
345 Int_t iy = d->PadY();
346 Int_t cathode = d->Cathode();
347 Int_t detElemId = d->DetElemId();
348 const AliMpVSegmentation* seg = AliMpSegmentation::Instance()->
349 GetMpSegmentation(detElemId,AliMp::GetCathodType(cathode));
168e9c4d 350 AliMpPad pad = seg->PadByIndices(ix,iy);
d08b5461 351
9e41a340 352 TObjArray* padArray = PadArray(detElemId,cathode);
d08b5461 353 if (!padArray)
354 {
9e41a340 355 padArray = new TObjArray(100);
ed90feae 356 padArray->SetOwner(kTRUE);
d08b5461 357 fPads[cathode]->Add(detElemId,padArray);
358 }
359
9e41a340 360 AliMUONPad* mpad = new AliMUONPad(detElemId,cathode,
6e97fbb8 361 ix,iy,pad.GetPositionX(),pad.GetPositionY(),
362 pad.GetDimensionX(),pad.GetDimensionY(),
d08b5461 363 d->Charge());
9e41a340 364 if ( d->IsSaturated() ) mpad->SetSaturated(kTRUE);
365 mpad->SetUniqueID(d->GetUniqueID());
366 padArray->Add(mpad);
d08b5461 367 }
368}
369
370//_____________________________________________________________________________
2e2d0c44 371Int_t
372AliMUONSimpleClusterServer::FindMCLabel(const AliMUONCluster& cluster, Int_t detElemId, const AliMpVSegmentation* seg[2]) const
373{
374 /// Find the label of the most contributing MC track (-1 in case of failure)
375 /// The data member fDigitStore must be set
376
377 // --- get the digit (if any) located at the cluster position on both cathods ---
378 Int_t nTracks[2] = {0, 0};
379 AliMUONVDigit* digit[2] = {0x0, 0x0};
380 for (Int_t iCath = 0; iCath < 2; iCath++) {
6e97fbb8 381 AliMpPad pad
382 = seg[AliMp::GetCathodType(iCath)]->PadByPosition(cluster.Position().X(), cluster.Position().Y(),kFALSE);
2e2d0c44 383 if (pad.IsValid()) {
168e9c4d 384 digit[iCath] = fDigitStore->FindObject(detElemId, pad.GetManuId(), pad.GetManuChannel(), iCath);
2e2d0c44 385 if (digit[iCath]) nTracks[iCath] = digit[iCath]->Ntracks();
386 }
387 }
388
389 if (nTracks[0] + nTracks[1] == 0) return -1;
390
391 // --- build the list of contributing tracks and of the associated charge ---
392 Int_t* trackId = new Int_t[nTracks[0] + nTracks[1]];
393 Float_t* trackCharge = new Float_t[nTracks[0] + nTracks[1]];
394 Int_t nTracksTot = 0;
395
396 // fill with contributing tracks on first cathod
397 for (Int_t iTrack1 = 0; iTrack1 < nTracks[0]; iTrack1++) {
398 trackId[iTrack1] = digit[0]->Track(iTrack1);
399 trackCharge[iTrack1] = digit[0]->TrackCharge(iTrack1);
400 }
401 nTracksTot = nTracks[0];
402
403 // complement with contributing tracks on second cathod
404 for (Int_t iTrack2 = 0; iTrack2 < nTracks[1]; iTrack2++) {
405 Int_t trackId2 = digit[1]->Track(iTrack2);
406 // check if track exist
407 Bool_t trackExist = kFALSE;
408 for (Int_t iTrack1 = 0; iTrack1 < nTracks[0]; iTrack1++) {
409 if (trackId2 == trackId[iTrack1]) {
410 // complement existing track
411 trackCharge[iTrack1] += digit[1]->TrackCharge(iTrack2);
412 trackExist = kTRUE;
413 break;
414 }
415 }
416 // add the new track
417 if (!trackExist) {
418 trackId[nTracksTot] = trackId2;
419 trackCharge[nTracksTot] = digit[1]->TrackCharge(iTrack2);
420 nTracksTot++;
421 }
422 }
423
424 // --- Find the most contributing track ---
425 Int_t mainTrackId = -1;
426 Float_t maxCharge = 0.;
427 for (Int_t iTrack = 0; iTrack < nTracksTot; iTrack++) {
428 if (trackCharge[iTrack] > maxCharge) {
429 mainTrackId = trackId[iTrack];
430 maxCharge = trackCharge[iTrack];
431 }
432 }
433
434 delete[] trackId;
435 delete[] trackCharge;
436
437 return mainTrackId;
438}
439
440//_____________________________________________________________________________
d08b5461 441void
442AliMUONSimpleClusterServer::Print(Option_t*) const
443{
444 /// Printout for debug only
445
446 AliMpDEIterator it;
447
448 it.First();
449
450 while ( !it.IsDone() )
451 {
452 Int_t detElemId = it.CurrentDEId();
453
454 // printout the number of pads / de, and number of used pads / de
455
456 if ( ( PadArray(detElemId,0) && PadArray(detElemId,0)->GetLast() >= 0 ) ||
457 ( PadArray(detElemId,1) && PadArray(detElemId,1)->GetLast() >= 0 ) )
458 {
459 cout << Form("---- DE %04d",detElemId) << endl;
460
461 for ( Int_t cathode = 0; cathode < 2; ++cathode )
462 {
463 cout << Form(" -- Cathode %1d",cathode) << endl;
464
9e41a340 465 TObjArray* padArray = PadArray(detElemId,cathode);
d08b5461 466
467 if (!padArray)
468 {
469 cout << "no pad array" << endl;
470 }
471 else if ( padArray->GetLast() < 0 )
472 {
473 cout << "no pads" << endl;
474 }
475 else
476 {
477 TIter next(padArray);
478 AliMUONPad* pad;
479 while ( ( pad = static_cast<AliMUONPad*>(next()) ) )
480 {
481 pad->Print("full");
482 }
483 }
484 }
485 }
486 it.Next();
487 }
488}
489
490