ROOT logo
// $Id$
// Main authors: Matevz Tadel & Alja Mrak-Tadel: 2006, 2007

/**************************************************************************
 * Copyright(c) 1998-2008, ALICE Experiment at CERN, all rights reserved. *
 * See http://aliceinfo.cern.ch/Offline/AliRoot/License.html for          *
 * full copyright notice.                                                 *
 **************************************************************************/

#include "AliEveTPCData.h"

#include <EveDet/AliEveTPCSectorData.h>

#include <AliSimDigits.h>
#include <AliTPCParam.h>
#include <AliTPCRawStreamV3.h>
#include <TTree.h>

//==============================================================================
//==============================================================================
// AliEveTPCData
//==============================================================================

//______________________________________________________________________________
//
// A central manager for TPC data of an event.  Can read digits (from
// a tree: LoadDigits()) and raw-data (via AliRawReader: LoadRaw()).
//
// The sector data is stored in 36 AliEveTPCSectorData objects.
// Sectors 0 - 17: +z side, 18 - 35: -z side.
// No separation of inner/outer segments, use row numbers for addressing.
//
// Threshold application and pedestal subtraction can be performed at
// load time: use SetLoadThreshold(thresh) and SetLoadPedestal(ped).
//
// For raw-data (loaded using LoadRaw) pedestals can be calculated
// automatically per pad. Use SetAutoPedestal(kTRUE) to activate it.
// You might still want to set load threshold (default iz zero).
//

ClassImp(AliEveTPCData)

AliEveTPCData::AliEveTPCData() :
  fSectors(36), fSectorBlockSize(65536),
  fLoadThreshold(0), fLoadPedestal(0), fAutoPedestal(kFALSE)
{
  // Constructor.

  AliEveTPCSectorData::InitStatics();
}

AliEveTPCData::~AliEveTPCData()
{
  // Destructor, deletes all sector-data.

  DeleteAllSectors();
}

/******************************************************************************/

void AliEveTPCData::CreateSector(Int_t sector)
{
  // Create sector-data for sector if it does not exist already.

  if (fSectors[sector] == 0)
    fSectors[sector] = new AliEveTPCSectorData(sector, fSectorBlockSize);
}

void AliEveTPCData::CreateAllSectors()
{
  // Create all 36 sectors.

  for (Int_t s=0; s<36; ++s)
    CreateSector(s);
}

void AliEveTPCData::DropAllSectors()
{
  // Drop data of all existing sectors.

  for (Int_t s=0; s<36; ++s) {
    if (fSectors[s] != 0)
      fSectors[s]->DropData();
  }
}

void AliEveTPCData::DeleteAllSectors()
{
  // Delete all sector-data.

  for (Int_t s=0; s<36; ++s) {
    delete fSectors[s];
    fSectors[s] = 0;
  }
}

/******************************************************************************/

AliEveTPCSectorData* AliEveTPCData::GetSectorData(Int_t sector, Bool_t spawnSectors)
{
  // Get sector-data for sector. If spawnSectors is true, the
  // sector-data is created if it does not exist already.

  if (sector < 0 || sector > 35) return 0;
  if (fSectors[sector] == 0 && spawnSectors)
    CreateSector(sector);
  return fSectors[sector];
}

/******************************************************************************/

void AliEveTPCData::LoadDigits(TTree* tree, Bool_t spawnSectors)
{
  // Load data from TTree of AliSimDigits.
  // If spawnSectors is false only sectors that have been created previously
  // via CreateSector() are loaded.
  // If spawnSectors is true sectors are created if data for them is encountered.

  AliSimDigits digit, *digitPtr = &digit;
  tree->GetBranch("Segment")->SetAddress(&digitPtr);

  Int_t sector, row, pad, curPad;
  Short_t time, signal;
  Bool_t  inFill = kFALSE;
  AliEveTPCSectorData* secData = 0;

  Int_t numEnt = (Int_t) tree->GetEntries();
  for (Int_t ent=0; ent<numEnt; ent++) {
    tree->GetEntry(ent);
    AliEveTPCSectorData::GetParam().AdjustSectorRow(digit.GetID(), sector, row);
    if (sector >= 36) {
      sector -= 36;
      row    += AliEveTPCSectorData::GetInnSeg().GetNRows();
    }
    secData = GetSectorData(sector, spawnSectors);
    if (secData == 0)
      continue;

    if (digit.First() == kFALSE)
      continue;
    curPad = -1;
    do {
      pad    = digit.CurrentColumn();
      time   = digit.CurrentRow();
      signal = digit.CurrentDigit();

      if (pad != curPad) {
	if (inFill)
	  secData->EndPad(fAutoPedestal, fLoadThreshold);
	secData->BeginPad(row, pad, kFALSE);
	curPad = pad;
	inFill = kTRUE;
      }
      if (fAutoPedestal) {
	secData->RegisterData(time, signal);
      } else {
	signal -= fLoadPedestal;
	if (signal >= fLoadThreshold)
	  secData->RegisterData(time, signal);
      }

    } while (digit.Next());
    if (inFill) {
      secData->EndPad(fAutoPedestal, fLoadThreshold);
      inFill = kFALSE;
    }
  }
}

void AliEveTPCData::LoadRaw(AliTPCRawStreamV3& input, Bool_t spawnSectors, Bool_t warn)
{
  // Load data from AliTPCRawStreamV3.
  // If spawnSectors is false only sectors that have been created previously
  // via CreateSector() are loaded.
  // If spawnSectors is true sectors are created if data for them is encountered.

  static const TEveException kEH("AliEveTPCData::LoadRaw ");

  Int_t   sector = -1, row = -1, pad = -1, rowOffset = 0;
  Short_t time,  signal;
  Bool_t  inFill       = kFALSE;
  Short_t pdrwCnt      = 9999; // Count time-bins in padrow; needed to detect more than 1024 time-bins per padrow.
  Short_t lastTime     = 9999; // Last time-bin stored; needed to check for out-of-order time bins.
  Bool_t  pdrwCntWarn  = kFALSE;
  Bool_t  lastTimeWarn = kFALSE;
  AliEveTPCSectorData* secData = 0;

  Short_t threshold = fLoadThreshold;

  while (input.NextDDL()) {
    if (input.IsNewSector()) {
      if (inFill) {
	secData->EndPad(fAutoPedestal, threshold);
	inFill = kFALSE;
      }
      sector = input.GetSector();
      if (sector >= 36) {
	sector -= 36;
	rowOffset = AliEveTPCSectorData::GetInnSeg().GetNRows();
      } else {
	rowOffset = 0;
      }
      secData = GetSectorData(sector, spawnSectors);
    }
    if (secData == 0)
      continue;

    while (input.NextChannel()) {
      if (input.IsNewPad()) {
	if (inFill) {
	  secData->EndPad(fAutoPedestal, threshold);
	  inFill = kFALSE;
	}
	row = input.GetRow() + rowOffset;
	pad = input.GetPad();

	if (pad >= AliEveTPCSectorData::GetNPadsInRow(row) || pad < 0) {
	  if (warn) {
	    Warning(kEH.Data(), "pad out of range (row=%d, pad=%d, maxpad=%d).",
		    row, pad, AliEveTPCSectorData::GetNPadsInRow(row));
	  }
	  continue;
	}

	threshold = fLoadThreshold;

	secData->BeginPad(row, pad, kTRUE);
	inFill   = kTRUE;
	pdrwCnt  = 0;     pdrwCntWarn  = kFALSE;
	lastTime = 1024;  lastTimeWarn = kFALSE;
      }

      while (input.NextBunch()) {
	const UShort_t *signalarr = input.GetSignals();

	Int_t starttime = input.GetStartTimeBin();
	for (Int_t i = 0; i < input.GetBunchLength(); i++) {
	  time   = starttime--;;
	  signal = signalarr[i];
	  ++pdrwCnt;
	  if (pdrwCnt > 1024) {
	    if (pdrwCntWarn == kFALSE) {
	      if (warn)
		Warning(kEH.Data(), "more than 1024 time-bins (row=%d, pad=%d, time=%d).\nFurther warnings of this type will be suppressed for this padrow.",
			row, pad, time);
	      pdrwCntWarn = kTRUE;
	    }
	    continue;
	  }
	  if (time >= lastTime) {
	    if (lastTimeWarn == kFALSE) {
	      if (warn)
		Warning(kEH.Data(), "time out of order (row=%d, pad=%d, time=%d, lastTime=%d).\nFurther warnings of this type will be suppressed for this padrow.",
			row, pad, time, lastTime);
	      lastTimeWarn = kTRUE;
	    }
	    continue;
	  }
	  lastTime = time;
	  if (fAutoPedestal) {
	    secData->RegisterData(time, signal);
	  } else {
	    signal -= fLoadPedestal;
	    if (signal > threshold)
	      secData->RegisterData(time, signal);
	  }
	}
      }
    }
  }

  if (inFill) {
    secData->EndPad(fAutoPedestal, threshold);
    inFill = kFALSE;
  }
}
 AliEveTPCData.cxx:1
 AliEveTPCData.cxx:2
 AliEveTPCData.cxx:3
 AliEveTPCData.cxx:4
 AliEveTPCData.cxx:5
 AliEveTPCData.cxx:6
 AliEveTPCData.cxx:7
 AliEveTPCData.cxx:8
 AliEveTPCData.cxx:9
 AliEveTPCData.cxx:10
 AliEveTPCData.cxx:11
 AliEveTPCData.cxx:12
 AliEveTPCData.cxx:13
 AliEveTPCData.cxx:14
 AliEveTPCData.cxx:15
 AliEveTPCData.cxx:16
 AliEveTPCData.cxx:17
 AliEveTPCData.cxx:18
 AliEveTPCData.cxx:19
 AliEveTPCData.cxx:20
 AliEveTPCData.cxx:21
 AliEveTPCData.cxx:22
 AliEveTPCData.cxx:23
 AliEveTPCData.cxx:24
 AliEveTPCData.cxx:25
 AliEveTPCData.cxx:26
 AliEveTPCData.cxx:27
 AliEveTPCData.cxx:28
 AliEveTPCData.cxx:29
 AliEveTPCData.cxx:30
 AliEveTPCData.cxx:31
 AliEveTPCData.cxx:32
 AliEveTPCData.cxx:33
 AliEveTPCData.cxx:34
 AliEveTPCData.cxx:35
 AliEveTPCData.cxx:36
 AliEveTPCData.cxx:37
 AliEveTPCData.cxx:38
 AliEveTPCData.cxx:39
 AliEveTPCData.cxx:40
 AliEveTPCData.cxx:41
 AliEveTPCData.cxx:42
 AliEveTPCData.cxx:43
 AliEveTPCData.cxx:44
 AliEveTPCData.cxx:45
 AliEveTPCData.cxx:46
 AliEveTPCData.cxx:47
 AliEveTPCData.cxx:48
 AliEveTPCData.cxx:49
 AliEveTPCData.cxx:50
 AliEveTPCData.cxx:51
 AliEveTPCData.cxx:52
 AliEveTPCData.cxx:53
 AliEveTPCData.cxx:54
 AliEveTPCData.cxx:55
 AliEveTPCData.cxx:56
 AliEveTPCData.cxx:57
 AliEveTPCData.cxx:58
 AliEveTPCData.cxx:59
 AliEveTPCData.cxx:60
 AliEveTPCData.cxx:61
 AliEveTPCData.cxx:62
 AliEveTPCData.cxx:63
 AliEveTPCData.cxx:64
 AliEveTPCData.cxx:65
 AliEveTPCData.cxx:66
 AliEveTPCData.cxx:67
 AliEveTPCData.cxx:68
 AliEveTPCData.cxx:69
 AliEveTPCData.cxx:70
 AliEveTPCData.cxx:71
 AliEveTPCData.cxx:72
 AliEveTPCData.cxx:73
 AliEveTPCData.cxx:74
 AliEveTPCData.cxx:75
 AliEveTPCData.cxx:76
 AliEveTPCData.cxx:77
 AliEveTPCData.cxx:78
 AliEveTPCData.cxx:79
 AliEveTPCData.cxx:80
 AliEveTPCData.cxx:81
 AliEveTPCData.cxx:82
 AliEveTPCData.cxx:83
 AliEveTPCData.cxx:84
 AliEveTPCData.cxx:85
 AliEveTPCData.cxx:86
 AliEveTPCData.cxx:87
 AliEveTPCData.cxx:88
 AliEveTPCData.cxx:89
 AliEveTPCData.cxx:90
 AliEveTPCData.cxx:91
 AliEveTPCData.cxx:92
 AliEveTPCData.cxx:93
 AliEveTPCData.cxx:94
 AliEveTPCData.cxx:95
 AliEveTPCData.cxx:96
 AliEveTPCData.cxx:97
 AliEveTPCData.cxx:98
 AliEveTPCData.cxx:99
 AliEveTPCData.cxx:100
 AliEveTPCData.cxx:101
 AliEveTPCData.cxx:102
 AliEveTPCData.cxx:103
 AliEveTPCData.cxx:104
 AliEveTPCData.cxx:105
 AliEveTPCData.cxx:106
 AliEveTPCData.cxx:107
 AliEveTPCData.cxx:108
 AliEveTPCData.cxx:109
 AliEveTPCData.cxx:110
 AliEveTPCData.cxx:111
 AliEveTPCData.cxx:112
 AliEveTPCData.cxx:113
 AliEveTPCData.cxx:114
 AliEveTPCData.cxx:115
 AliEveTPCData.cxx:116
 AliEveTPCData.cxx:117
 AliEveTPCData.cxx:118
 AliEveTPCData.cxx:119
 AliEveTPCData.cxx:120
 AliEveTPCData.cxx:121
 AliEveTPCData.cxx:122
 AliEveTPCData.cxx:123
 AliEveTPCData.cxx:124
 AliEveTPCData.cxx:125
 AliEveTPCData.cxx:126
 AliEveTPCData.cxx:127
 AliEveTPCData.cxx:128
 AliEveTPCData.cxx:129
 AliEveTPCData.cxx:130
 AliEveTPCData.cxx:131
 AliEveTPCData.cxx:132
 AliEveTPCData.cxx:133
 AliEveTPCData.cxx:134
 AliEveTPCData.cxx:135
 AliEveTPCData.cxx:136
 AliEveTPCData.cxx:137
 AliEveTPCData.cxx:138
 AliEveTPCData.cxx:139
 AliEveTPCData.cxx:140
 AliEveTPCData.cxx:141
 AliEveTPCData.cxx:142
 AliEveTPCData.cxx:143
 AliEveTPCData.cxx:144
 AliEveTPCData.cxx:145
 AliEveTPCData.cxx:146
 AliEveTPCData.cxx:147
 AliEveTPCData.cxx:148
 AliEveTPCData.cxx:149
 AliEveTPCData.cxx:150
 AliEveTPCData.cxx:151
 AliEveTPCData.cxx:152
 AliEveTPCData.cxx:153
 AliEveTPCData.cxx:154
 AliEveTPCData.cxx:155
 AliEveTPCData.cxx:156
 AliEveTPCData.cxx:157
 AliEveTPCData.cxx:158
 AliEveTPCData.cxx:159
 AliEveTPCData.cxx:160
 AliEveTPCData.cxx:161
 AliEveTPCData.cxx:162
 AliEveTPCData.cxx:163
 AliEveTPCData.cxx:164
 AliEveTPCData.cxx:165
 AliEveTPCData.cxx:166
 AliEveTPCData.cxx:167
 AliEveTPCData.cxx:168
 AliEveTPCData.cxx:169
 AliEveTPCData.cxx:170
 AliEveTPCData.cxx:171
 AliEveTPCData.cxx:172
 AliEveTPCData.cxx:173
 AliEveTPCData.cxx:174
 AliEveTPCData.cxx:175
 AliEveTPCData.cxx:176
 AliEveTPCData.cxx:177
 AliEveTPCData.cxx:178
 AliEveTPCData.cxx:179
 AliEveTPCData.cxx:180
 AliEveTPCData.cxx:181
 AliEveTPCData.cxx:182
 AliEveTPCData.cxx:183
 AliEveTPCData.cxx:184
 AliEveTPCData.cxx:185
 AliEveTPCData.cxx:186
 AliEveTPCData.cxx:187
 AliEveTPCData.cxx:188
 AliEveTPCData.cxx:189
 AliEveTPCData.cxx:190
 AliEveTPCData.cxx:191
 AliEveTPCData.cxx:192
 AliEveTPCData.cxx:193
 AliEveTPCData.cxx:194
 AliEveTPCData.cxx:195
 AliEveTPCData.cxx:196
 AliEveTPCData.cxx:197
 AliEveTPCData.cxx:198
 AliEveTPCData.cxx:199
 AliEveTPCData.cxx:200
 AliEveTPCData.cxx:201
 AliEveTPCData.cxx:202
 AliEveTPCData.cxx:203
 AliEveTPCData.cxx:204
 AliEveTPCData.cxx:205
 AliEveTPCData.cxx:206
 AliEveTPCData.cxx:207
 AliEveTPCData.cxx:208
 AliEveTPCData.cxx:209
 AliEveTPCData.cxx:210
 AliEveTPCData.cxx:211
 AliEveTPCData.cxx:212
 AliEveTPCData.cxx:213
 AliEveTPCData.cxx:214
 AliEveTPCData.cxx:215
 AliEveTPCData.cxx:216
 AliEveTPCData.cxx:217
 AliEveTPCData.cxx:218
 AliEveTPCData.cxx:219
 AliEveTPCData.cxx:220
 AliEveTPCData.cxx:221
 AliEveTPCData.cxx:222
 AliEveTPCData.cxx:223
 AliEveTPCData.cxx:224
 AliEveTPCData.cxx:225
 AliEveTPCData.cxx:226
 AliEveTPCData.cxx:227
 AliEveTPCData.cxx:228
 AliEveTPCData.cxx:229
 AliEveTPCData.cxx:230
 AliEveTPCData.cxx:231
 AliEveTPCData.cxx:232
 AliEveTPCData.cxx:233
 AliEveTPCData.cxx:234
 AliEveTPCData.cxx:235
 AliEveTPCData.cxx:236
 AliEveTPCData.cxx:237
 AliEveTPCData.cxx:238
 AliEveTPCData.cxx:239
 AliEveTPCData.cxx:240
 AliEveTPCData.cxx:241
 AliEveTPCData.cxx:242
 AliEveTPCData.cxx:243
 AliEveTPCData.cxx:244
 AliEveTPCData.cxx:245
 AliEveTPCData.cxx:246
 AliEveTPCData.cxx:247
 AliEveTPCData.cxx:248
 AliEveTPCData.cxx:249
 AliEveTPCData.cxx:250
 AliEveTPCData.cxx:251
 AliEveTPCData.cxx:252
 AliEveTPCData.cxx:253
 AliEveTPCData.cxx:254
 AliEveTPCData.cxx:255
 AliEveTPCData.cxx:256
 AliEveTPCData.cxx:257
 AliEveTPCData.cxx:258
 AliEveTPCData.cxx:259
 AliEveTPCData.cxx:260
 AliEveTPCData.cxx:261
 AliEveTPCData.cxx:262
 AliEveTPCData.cxx:263
 AliEveTPCData.cxx:264
 AliEveTPCData.cxx:265
 AliEveTPCData.cxx:266
 AliEveTPCData.cxx:267
 AliEveTPCData.cxx:268
 AliEveTPCData.cxx:269
 AliEveTPCData.cxx:270
 AliEveTPCData.cxx:271
 AliEveTPCData.cxx:272
 AliEveTPCData.cxx:273
 AliEveTPCData.cxx:274
 AliEveTPCData.cxx:275
 AliEveTPCData.cxx:276