ROOT logo
/**************************************************************************
* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
*                                                                        *
* Author: The ALICE Off-line Project.                                    *
* Contributors are mentioned in the code where appropriate.              *
*                                                                        *
* Permission to use, copy, modify and distribute this software and its   *
* documentation strictly for non-commercial purposes is hereby granted   *
* without fee, provided that the above copyright notice appears in all   *
* copies and that both the copyright notice and this permission notice   *
* appear in the supporting documentation. The authors make no claims     *
* about the suitability of this software for any purpose. It is          *
* provided "as is" without express or implied warranty.                  *
**************************************************************************/

// $Id$

#include "AliMUONPreClusterFinder.h"

#include "AliCodeTimer.h"

#include "AliMUONCluster.h"
#include "AliMUONPad.h"
#include "AliMUONVDigit.h"
#include "AliMUONVDigitStore.h"

#include "AliMpArea.h"
#include "AliMpConstants.h"
#include "AliMpVSegmentation.h"

#include "AliLog.h"

#include <Riostream.h>
#include <TObjArray.h>
#include <TVector2.h>

//-----------------------------------------------------------------------------
/// \class AliMUONPreClusterFinder
///
/// Implementation of AliMUONVClusterFinder
///
/// This class simply find adjacent pads to form clusters
///
/// \author Laurent Aphecetche
//-----------------------------------------------------------------------------

ClassImp(AliMUONPreClusterFinder)

//_____________________________________________________________________________
AliMUONPreClusterFinder::AliMUONPreClusterFinder()
: AliMUONVClusterFinder(),
  fClusters("AliMUONCluster"),
  fPads(0x0),
  fDetElemId(0),
  fArea(),
  fShouldAbort(kFALSE)
{
  /// ctor
}

//_____________________________________________________________________________
AliMUONPreClusterFinder::~AliMUONPreClusterFinder()
{
  /// dtor : note we're owner of the clusters, but not of the pads
}

//_____________________________________________________________________________
Bool_t
AliMUONPreClusterFinder::UsePad(const AliMUONPad& pad)
{
  /// Add a pad to the list of pads to be considered
  if ( pad.DetElemId() != fDetElemId )
  {
    AliError(Form("Cannot add pad from DE %d to this cluster finder which is "
                  "currently dealing with DE %d",pad.DetElemId(),fDetElemId));
    return kFALSE;
  }
  
  fPads[pad.Cathode()]->Add(new AliMUONPad(pad)); 
  // FIXME: should set the ClusterId of that new pad to be -1
  return kTRUE;
}

//_____________________________________________________________________________
Bool_t
AliMUONPreClusterFinder::Prepare(Int_t detElemId,
                                 TObjArray* pads[2],
                                 const AliMpArea& area)
{
  /// Prepare for clustering, by giving access to segmentations and digit lists

  fClusters.Delete();
  
  fPads = pads;
  fDetElemId = detElemId;
  fArea = area;
  
  fShouldAbort = kFALSE;
  
  return kTRUE;
}

//_____________________________________________________________________________
void
AliMUONPreClusterFinder::AddPad(AliMUONCluster& cluster, AliMUONPad* pad)
{
  /// Add a pad to a cluster
  
  if ( cluster.IsMonoCathode() && cluster.Multiplicity() > 199 ) 
  {
    /// FIXME : we should at that point really find a better way to remove "bad" preclusters,
    /// like e.g. computing the charge dispersion (the lower, the most probably we have noise cluster)
    /// and/or mean charge per pad (if too close to LowestPadCharge, again that's a noise cluster...
    /// *BUT* this needs carefull testing !
    fShouldAbort = kTRUE;
    return;
  }
  
  AliMUONPad* addedPad = cluster.AddPad(*pad);
  
  Int_t cathode = pad->Cathode();
  TObjArray& padArray = *fPads[cathode];
  // WARNING: this Remove method uses the AliMUONPad::IsEqual if that method is
  // present (otherwise just compares pointers) : so that one must be correct
  // if implemented !
  TObject* o = padArray.Remove(pad);
//  if (!o)
//  {
//    AliFatal("Oups. Could not remove pad from pads to consider. Aborting as anyway "
//             " we'll get an infinite loop. Please check the AliMUONPad::IsEqual method"
//             " as the first suspect for failed remove");
//  }  
  delete o;
  
  TIter next(&padArray);
  AliMUONPad* testPad;

  while ( ( testPad = static_cast<AliMUONPad*>(next())))
  {
    if ( AliMUONPad::AreNeighbours(*testPad,*addedPad) )
    {
      AddPad(cluster,testPad);
    }
  }
}

//_____________________________________________________________________________
Bool_t
AreOverlapping(const AliMUONPad& pad, const AliMUONCluster& cluster)
{
  /// Whether the pad overlaps with the cluster
  
  static Double_t precision = 1E-4; // cm
  static TVector2 precisionAdjustment(precision,precision);//-precision,-precision);
  for ( Int_t i = 0; i < cluster.Multiplicity(); ++i )
  {
    AliMUONPad* testPad = cluster.Pad(i);
    // Note: we use negative precision numbers, meaning
    // the area of the pads will be *increased* by these small numbers
    // prior to check the overlap by the AreOverlapping method,
    // so pads touching only by the corners will be considered as
    // overlapping.    
    if ( AliMUONPad::AreOverlapping(*testPad,pad,precisionAdjustment) )
    {
      return kTRUE;
    }
  }
  return kFALSE;
}

//_____________________________________________________________________________
AliMUONPad*
AliMUONPreClusterFinder::GetNextPad(Int_t cathode) const
{
/// Return the next unused pad of given cathode, which is within fArea

  TIter next(fPads[cathode]);
  
  if ( !fArea.IsValid() )
  {
    return static_cast<AliMUONPad*>(next());
  }
  else
  {
    AliMUONPad* pad;
    while ( ( pad = static_cast<AliMUONPad*>(next())) )
    {
      AliMpArea padArea(pad->X(), pad->Y(), pad->DX(), pad->DY());
      
      if (fArea.Overlap(padArea)) return pad;

    }
    return 0x0;
  }
}

//_____________________________________________________________________________
AliMUONCluster* 
AliMUONPreClusterFinder::NewCluster()
{
  /// Create a new (empty) cluster
  Int_t id = fClusters.GetLast()+1;
  AliMUONCluster* cluster = new (fClusters[id]) AliMUONCluster;
  cluster->SetUniqueID(id);
  return cluster;
}

//_____________________________________________________________________________
void 
AliMUONPreClusterFinder::RemoveCluster(AliMUONCluster* cluster)
{
  /// Remove a cluster
  /// Note that we are *not* releasing the pads, so they won't be used further on
  fClusters.Remove(cluster);
  fClusters.Compress();
}

//_____________________________________________________________________________
AliMUONCluster* 
AliMUONPreClusterFinder::NextCluster()
{
  /// Builds the next cluster, and returns it.
  
  // Start a new cluster
  
  AliMUONPad* pad = GetNextPad(0);
  
  AliMUONCluster* cluster(0x0);
  
  if (!pad) // protection against no pad in first cathode, which might happen
  {
    // try other cathode
    pad = GetNextPad(1);
    if (!pad) 
    {
      return 0x0;
    }
    else
    {
      cluster = NewCluster();
      // Builds (recursively) a cluster on second cathode only
      AddPad(*cluster,pad);
    }
  }
  else
  {
    // Builds (recursively) a cluster on first cathode only
    
    cluster = NewCluster();
    AddPad(*cluster,pad);
    
    if ( !ShouldAbort() ) 
    {
      // On the 2nd cathode, only add pads overlapping with the current cluster
      TObjArray& padArray = *fPads[1];
      TIter next(&padArray);
      AliMUONPad* testPad;
      
      while ( ( testPad = static_cast<AliMUONPad*>(next())) && !ShouldAbort() )
      {
        if (AreOverlapping(*testPad,*cluster) )
        {
          AddPad(*cluster,testPad);
        }
      }
    }
  }
  
  if ( ShouldAbort() ) 
  {
    AliCodeTimerAuto(Form("Skipping a precluster in DE %d because it got too many pads",fDetElemId),0);
    RemoveCluster(cluster);
    return NextCluster();
  }
  
  if ( cluster->Multiplicity() <= 1 )
  {
    if ( cluster->Multiplicity() == 0 ) 
    {
      // no pad is suspicious
      AliWarning("Got an empty cluster...");
    }
    // else only 1 pad (not suspicious, but kind of useless, probably noise)
    // so we remove it from our list
    RemoveCluster(cluster);
    // then proceed further
    return NextCluster();
  }
  
  return cluster;
}
 AliMUONPreClusterFinder.cxx:1
 AliMUONPreClusterFinder.cxx:2
 AliMUONPreClusterFinder.cxx:3
 AliMUONPreClusterFinder.cxx:4
 AliMUONPreClusterFinder.cxx:5
 AliMUONPreClusterFinder.cxx:6
 AliMUONPreClusterFinder.cxx:7
 AliMUONPreClusterFinder.cxx:8
 AliMUONPreClusterFinder.cxx:9
 AliMUONPreClusterFinder.cxx:10
 AliMUONPreClusterFinder.cxx:11
 AliMUONPreClusterFinder.cxx:12
 AliMUONPreClusterFinder.cxx:13
 AliMUONPreClusterFinder.cxx:14
 AliMUONPreClusterFinder.cxx:15
 AliMUONPreClusterFinder.cxx:16
 AliMUONPreClusterFinder.cxx:17
 AliMUONPreClusterFinder.cxx:18
 AliMUONPreClusterFinder.cxx:19
 AliMUONPreClusterFinder.cxx:20
 AliMUONPreClusterFinder.cxx:21
 AliMUONPreClusterFinder.cxx:22
 AliMUONPreClusterFinder.cxx:23
 AliMUONPreClusterFinder.cxx:24
 AliMUONPreClusterFinder.cxx:25
 AliMUONPreClusterFinder.cxx:26
 AliMUONPreClusterFinder.cxx:27
 AliMUONPreClusterFinder.cxx:28
 AliMUONPreClusterFinder.cxx:29
 AliMUONPreClusterFinder.cxx:30
 AliMUONPreClusterFinder.cxx:31
 AliMUONPreClusterFinder.cxx:32
 AliMUONPreClusterFinder.cxx:33
 AliMUONPreClusterFinder.cxx:34
 AliMUONPreClusterFinder.cxx:35
 AliMUONPreClusterFinder.cxx:36
 AliMUONPreClusterFinder.cxx:37
 AliMUONPreClusterFinder.cxx:38
 AliMUONPreClusterFinder.cxx:39
 AliMUONPreClusterFinder.cxx:40
 AliMUONPreClusterFinder.cxx:41
 AliMUONPreClusterFinder.cxx:42
 AliMUONPreClusterFinder.cxx:43
 AliMUONPreClusterFinder.cxx:44
 AliMUONPreClusterFinder.cxx:45
 AliMUONPreClusterFinder.cxx:46
 AliMUONPreClusterFinder.cxx:47
 AliMUONPreClusterFinder.cxx:48
 AliMUONPreClusterFinder.cxx:49
 AliMUONPreClusterFinder.cxx:50
 AliMUONPreClusterFinder.cxx:51
 AliMUONPreClusterFinder.cxx:52
 AliMUONPreClusterFinder.cxx:53
 AliMUONPreClusterFinder.cxx:54
 AliMUONPreClusterFinder.cxx:55
 AliMUONPreClusterFinder.cxx:56
 AliMUONPreClusterFinder.cxx:57
 AliMUONPreClusterFinder.cxx:58
 AliMUONPreClusterFinder.cxx:59
 AliMUONPreClusterFinder.cxx:60
 AliMUONPreClusterFinder.cxx:61
 AliMUONPreClusterFinder.cxx:62
 AliMUONPreClusterFinder.cxx:63
 AliMUONPreClusterFinder.cxx:64
 AliMUONPreClusterFinder.cxx:65
 AliMUONPreClusterFinder.cxx:66
 AliMUONPreClusterFinder.cxx:67
 AliMUONPreClusterFinder.cxx:68
 AliMUONPreClusterFinder.cxx:69
 AliMUONPreClusterFinder.cxx:70
 AliMUONPreClusterFinder.cxx:71
 AliMUONPreClusterFinder.cxx:72
 AliMUONPreClusterFinder.cxx:73
 AliMUONPreClusterFinder.cxx:74
 AliMUONPreClusterFinder.cxx:75
 AliMUONPreClusterFinder.cxx:76
 AliMUONPreClusterFinder.cxx:77
 AliMUONPreClusterFinder.cxx:78
 AliMUONPreClusterFinder.cxx:79
 AliMUONPreClusterFinder.cxx:80
 AliMUONPreClusterFinder.cxx:81
 AliMUONPreClusterFinder.cxx:82
 AliMUONPreClusterFinder.cxx:83
 AliMUONPreClusterFinder.cxx:84
 AliMUONPreClusterFinder.cxx:85
 AliMUONPreClusterFinder.cxx:86
 AliMUONPreClusterFinder.cxx:87
 AliMUONPreClusterFinder.cxx:88
 AliMUONPreClusterFinder.cxx:89
 AliMUONPreClusterFinder.cxx:90
 AliMUONPreClusterFinder.cxx:91
 AliMUONPreClusterFinder.cxx:92
 AliMUONPreClusterFinder.cxx:93
 AliMUONPreClusterFinder.cxx:94
 AliMUONPreClusterFinder.cxx:95
 AliMUONPreClusterFinder.cxx:96
 AliMUONPreClusterFinder.cxx:97
 AliMUONPreClusterFinder.cxx:98
 AliMUONPreClusterFinder.cxx:99
 AliMUONPreClusterFinder.cxx:100
 AliMUONPreClusterFinder.cxx:101
 AliMUONPreClusterFinder.cxx:102
 AliMUONPreClusterFinder.cxx:103
 AliMUONPreClusterFinder.cxx:104
 AliMUONPreClusterFinder.cxx:105
 AliMUONPreClusterFinder.cxx:106
 AliMUONPreClusterFinder.cxx:107
 AliMUONPreClusterFinder.cxx:108
 AliMUONPreClusterFinder.cxx:109
 AliMUONPreClusterFinder.cxx:110
 AliMUONPreClusterFinder.cxx:111
 AliMUONPreClusterFinder.cxx:112
 AliMUONPreClusterFinder.cxx:113
 AliMUONPreClusterFinder.cxx:114
 AliMUONPreClusterFinder.cxx:115
 AliMUONPreClusterFinder.cxx:116
 AliMUONPreClusterFinder.cxx:117
 AliMUONPreClusterFinder.cxx:118
 AliMUONPreClusterFinder.cxx:119
 AliMUONPreClusterFinder.cxx:120
 AliMUONPreClusterFinder.cxx:121
 AliMUONPreClusterFinder.cxx:122
 AliMUONPreClusterFinder.cxx:123
 AliMUONPreClusterFinder.cxx:124
 AliMUONPreClusterFinder.cxx:125
 AliMUONPreClusterFinder.cxx:126
 AliMUONPreClusterFinder.cxx:127
 AliMUONPreClusterFinder.cxx:128
 AliMUONPreClusterFinder.cxx:129
 AliMUONPreClusterFinder.cxx:130
 AliMUONPreClusterFinder.cxx:131
 AliMUONPreClusterFinder.cxx:132
 AliMUONPreClusterFinder.cxx:133
 AliMUONPreClusterFinder.cxx:134
 AliMUONPreClusterFinder.cxx:135
 AliMUONPreClusterFinder.cxx:136
 AliMUONPreClusterFinder.cxx:137
 AliMUONPreClusterFinder.cxx:138
 AliMUONPreClusterFinder.cxx:139
 AliMUONPreClusterFinder.cxx:140
 AliMUONPreClusterFinder.cxx:141
 AliMUONPreClusterFinder.cxx:142
 AliMUONPreClusterFinder.cxx:143
 AliMUONPreClusterFinder.cxx:144
 AliMUONPreClusterFinder.cxx:145
 AliMUONPreClusterFinder.cxx:146
 AliMUONPreClusterFinder.cxx:147
 AliMUONPreClusterFinder.cxx:148
 AliMUONPreClusterFinder.cxx:149
 AliMUONPreClusterFinder.cxx:150
 AliMUONPreClusterFinder.cxx:151
 AliMUONPreClusterFinder.cxx:152
 AliMUONPreClusterFinder.cxx:153
 AliMUONPreClusterFinder.cxx:154
 AliMUONPreClusterFinder.cxx:155
 AliMUONPreClusterFinder.cxx:156
 AliMUONPreClusterFinder.cxx:157
 AliMUONPreClusterFinder.cxx:158
 AliMUONPreClusterFinder.cxx:159
 AliMUONPreClusterFinder.cxx:160
 AliMUONPreClusterFinder.cxx:161
 AliMUONPreClusterFinder.cxx:162
 AliMUONPreClusterFinder.cxx:163
 AliMUONPreClusterFinder.cxx:164
 AliMUONPreClusterFinder.cxx:165
 AliMUONPreClusterFinder.cxx:166
 AliMUONPreClusterFinder.cxx:167
 AliMUONPreClusterFinder.cxx:168
 AliMUONPreClusterFinder.cxx:169
 AliMUONPreClusterFinder.cxx:170
 AliMUONPreClusterFinder.cxx:171
 AliMUONPreClusterFinder.cxx:172
 AliMUONPreClusterFinder.cxx:173
 AliMUONPreClusterFinder.cxx:174
 AliMUONPreClusterFinder.cxx:175
 AliMUONPreClusterFinder.cxx:176
 AliMUONPreClusterFinder.cxx:177
 AliMUONPreClusterFinder.cxx:178
 AliMUONPreClusterFinder.cxx:179
 AliMUONPreClusterFinder.cxx:180
 AliMUONPreClusterFinder.cxx:181
 AliMUONPreClusterFinder.cxx:182
 AliMUONPreClusterFinder.cxx:183
 AliMUONPreClusterFinder.cxx:184
 AliMUONPreClusterFinder.cxx:185
 AliMUONPreClusterFinder.cxx:186
 AliMUONPreClusterFinder.cxx:187
 AliMUONPreClusterFinder.cxx:188
 AliMUONPreClusterFinder.cxx:189
 AliMUONPreClusterFinder.cxx:190
 AliMUONPreClusterFinder.cxx:191
 AliMUONPreClusterFinder.cxx:192
 AliMUONPreClusterFinder.cxx:193
 AliMUONPreClusterFinder.cxx:194
 AliMUONPreClusterFinder.cxx:195
 AliMUONPreClusterFinder.cxx:196
 AliMUONPreClusterFinder.cxx:197
 AliMUONPreClusterFinder.cxx:198
 AliMUONPreClusterFinder.cxx:199
 AliMUONPreClusterFinder.cxx:200
 AliMUONPreClusterFinder.cxx:201
 AliMUONPreClusterFinder.cxx:202
 AliMUONPreClusterFinder.cxx:203
 AliMUONPreClusterFinder.cxx:204
 AliMUONPreClusterFinder.cxx:205
 AliMUONPreClusterFinder.cxx:206
 AliMUONPreClusterFinder.cxx:207
 AliMUONPreClusterFinder.cxx:208
 AliMUONPreClusterFinder.cxx:209
 AliMUONPreClusterFinder.cxx:210
 AliMUONPreClusterFinder.cxx:211
 AliMUONPreClusterFinder.cxx:212
 AliMUONPreClusterFinder.cxx:213
 AliMUONPreClusterFinder.cxx:214
 AliMUONPreClusterFinder.cxx:215
 AliMUONPreClusterFinder.cxx:216
 AliMUONPreClusterFinder.cxx:217
 AliMUONPreClusterFinder.cxx:218
 AliMUONPreClusterFinder.cxx:219
 AliMUONPreClusterFinder.cxx:220
 AliMUONPreClusterFinder.cxx:221
 AliMUONPreClusterFinder.cxx:222
 AliMUONPreClusterFinder.cxx:223
 AliMUONPreClusterFinder.cxx:224
 AliMUONPreClusterFinder.cxx:225
 AliMUONPreClusterFinder.cxx:226
 AliMUONPreClusterFinder.cxx:227
 AliMUONPreClusterFinder.cxx:228
 AliMUONPreClusterFinder.cxx:229
 AliMUONPreClusterFinder.cxx:230
 AliMUONPreClusterFinder.cxx:231
 AliMUONPreClusterFinder.cxx:232
 AliMUONPreClusterFinder.cxx:233
 AliMUONPreClusterFinder.cxx:234
 AliMUONPreClusterFinder.cxx:235
 AliMUONPreClusterFinder.cxx:236
 AliMUONPreClusterFinder.cxx:237
 AliMUONPreClusterFinder.cxx:238
 AliMUONPreClusterFinder.cxx:239
 AliMUONPreClusterFinder.cxx:240
 AliMUONPreClusterFinder.cxx:241
 AliMUONPreClusterFinder.cxx:242
 AliMUONPreClusterFinder.cxx:243
 AliMUONPreClusterFinder.cxx:244
 AliMUONPreClusterFinder.cxx:245
 AliMUONPreClusterFinder.cxx:246
 AliMUONPreClusterFinder.cxx:247
 AliMUONPreClusterFinder.cxx:248
 AliMUONPreClusterFinder.cxx:249
 AliMUONPreClusterFinder.cxx:250
 AliMUONPreClusterFinder.cxx:251
 AliMUONPreClusterFinder.cxx:252
 AliMUONPreClusterFinder.cxx:253
 AliMUONPreClusterFinder.cxx:254
 AliMUONPreClusterFinder.cxx:255
 AliMUONPreClusterFinder.cxx:256
 AliMUONPreClusterFinder.cxx:257
 AliMUONPreClusterFinder.cxx:258
 AliMUONPreClusterFinder.cxx:259
 AliMUONPreClusterFinder.cxx:260
 AliMUONPreClusterFinder.cxx:261
 AliMUONPreClusterFinder.cxx:262
 AliMUONPreClusterFinder.cxx:263
 AliMUONPreClusterFinder.cxx:264
 AliMUONPreClusterFinder.cxx:265
 AliMUONPreClusterFinder.cxx:266
 AliMUONPreClusterFinder.cxx:267
 AliMUONPreClusterFinder.cxx:268
 AliMUONPreClusterFinder.cxx:269
 AliMUONPreClusterFinder.cxx:270
 AliMUONPreClusterFinder.cxx:271
 AliMUONPreClusterFinder.cxx:272
 AliMUONPreClusterFinder.cxx:273
 AliMUONPreClusterFinder.cxx:274
 AliMUONPreClusterFinder.cxx:275
 AliMUONPreClusterFinder.cxx:276
 AliMUONPreClusterFinder.cxx:277
 AliMUONPreClusterFinder.cxx:278
 AliMUONPreClusterFinder.cxx:279
 AliMUONPreClusterFinder.cxx:280
 AliMUONPreClusterFinder.cxx:281
 AliMUONPreClusterFinder.cxx:282
 AliMUONPreClusterFinder.cxx:283
 AliMUONPreClusterFinder.cxx:284
 AliMUONPreClusterFinder.cxx:285
 AliMUONPreClusterFinder.cxx:286
 AliMUONPreClusterFinder.cxx:287
 AliMUONPreClusterFinder.cxx:288
 AliMUONPreClusterFinder.cxx:289
 AliMUONPreClusterFinder.cxx:290
 AliMUONPreClusterFinder.cxx:291