Preprocessor classes for SPD (Paul Nilsson)
authormasera <masera@f7af4fe6-9843-0410-8265-dc069ae4e863>
Tue, 11 Oct 2005 12:31:50 +0000 (12:31 +0000)
committermasera <masera@f7af4fe6-9843-0410-8265-dc069ae4e863>
Tue, 11 Oct 2005 12:31:50 +0000 (12:31 +0000)
ITS/AliITSBadChannelsAuxSPD.cxx [new file with mode: 0644]
ITS/AliITSBadChannelsAuxSPD.h [new file with mode: 0644]
ITS/AliITSBadChannelsSPD.cxx [new file with mode: 0644]
ITS/AliITSBadChannelsSPD.h [new file with mode: 0644]
ITS/AliITSChannelSPD.cxx [new file with mode: 0644]
ITS/AliITSChannelSPD.h [new file with mode: 0644]
ITS/AliITSPreprocessorSPD.cxx [new file with mode: 0644]
ITS/AliITSPreprocessorSPD.h [new file with mode: 0644]
ITS/ITSbaseLinkDef.h
ITS/libITSbase.pkg

diff --git a/ITS/AliITSBadChannelsAuxSPD.cxx b/ITS/AliITSBadChannelsAuxSPD.cxx
new file mode 100644 (file)
index 0000000..5459b06
--- /dev/null
@@ -0,0 +1,411 @@
+/**************************************************************************
+ * 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.                  *
+ **************************************************************************/
+
+/*
+$Log$
+*/
+
+///////////////////////////////////////////////////////////////////////////
+// AliITSBadChannelsAuxSPD implementation by P. Nilsson 2005
+// AUTHOR/CONTACT: Paul.Nilsson@cern.ch
+//
+// Auxiliary algorithms for the SPD
+//
+// This class contains converter methods and general algorithms for
+// handling digit <-> channel convertions and methods for identifying
+// changes (diff's) in arrays of bad channels, and for finding channels
+// or digits in arrays of bad channels.
+//
+// The Diff algorithm can be used to check if there are any changes among
+// the noisy channels. It returns two arrays, one with noisy channels
+// are no longer visible (less likely to happen) and one with newly found
+// noisy channels (more likely to happen).
+//
+// The Find algorithms looks for a given digit or channel in an array of
+// known channels. It can be used by the clustering algorithms to check
+// if a given digit that is about to be clustered, is in fact a known
+// noisy channel. It should not be used in a normal cluster.
+//
+// Examples - Converters
+//
+// root [0] AliITSdigitSPD *d = new AliITSdigitSPD();
+// root [1] d->SetCoord1(1);
+// root [2] d->SetCoord2(2);
+// root [3] d->SetSignal(1);
+// root [4] AliITSBadChannelsAuxSPD *aux = new AliITSBadChannelsAuxSPD();
+// root [5] AliITSChannelSPD *c = aux->CreateChannelFromDigit(d);
+// root [6] cout << c->GetColumn() << endl;
+// 1
+// root [7] cout << c->GetRow() << endl;
+// 2
+// root [8] AliITSdigitSPD *d2 = aux->CreateDigitFromChannel(c);
+// root [9] cout << d2->GetCoord1() << endl;
+// 1
+// root [10] cout << d2->GetCoord2() << endl;
+// 2
+// root [11] cout << d2->GetSignal() << endl;
+// 1
+// root [12] delete d2;
+// root [13] delete d;
+// root [14] delete c;
+//
+// The signal member of the digit is not a member of the channel class.
+// It is artificially introduced by the CreateDigitFromChannel method and
+// is per default set to 1.
+///////////////////////////////////////////////////////////////////////////
+
+#include "AliITSBadChannelsAuxSPD.h"
+
+ClassImp(AliITSBadChannelsAuxSPD)
+
+//__________________________________________________________________________
+AliITSBadChannelsAuxSPD::AliITSBadChannelsAuxSPD(void)
+{
+  // Default constructor
+}
+
+//__________________________________________________________________________
+Bool_t AliITSBadChannelsAuxSPD::Diff(TObjArray *&inputArray1, TObjArray *&inputArray2,
+                                    TObjArray *&outputArray1, TObjArray *&outputArray2) const
+{
+  // Make a diff between the input TObjArrays
+  // 
+  // Input: Two input TObjArrays of AliITSChannelSPD objects to be tested, two output TObjArrays corresponding
+  //        to 
+  // Output: Two output TObjArrays where outputArray1 contains the AliITSChannelSPD objects from inputArray1
+  //         that are not in inputArray2, vice versa for outputArray2.
+  // Return: kTRUE if the arrays differ
+
+  Bool_t status = kFALSE;
+
+  const Int_t kInputArray1Size = inputArray1->GetEntries();
+  const Int_t kInputArray2Size = inputArray2->GetEntries();
+  AliITSChannelSPD *ch1 = 0;
+  AliITSChannelSPD *ch2 = 0;
+  Bool_t found = kFALSE;
+
+  Int_t i = 0, j = 0;
+
+  // Pass 1
+  Int_t lastFoundAtJ = -1;
+  for (i = 0; i < kInputArray1Size; i++)
+    {
+      // Get the next channel from array 1
+      ch1 = (AliITSChannelSPD *) inputArray1->At(i);
+
+      // Is ch1 also in array 2?
+      for (j = lastFoundAtJ + 1; j < kInputArray2Size; j++)
+        {
+          ch2 = (AliITSChannelSPD *) inputArray2->At(j);
+          if (*ch1 == *ch2)
+            {
+              // Abort, go to next i
+              found = kTRUE;
+              lastFoundAtJ = j;
+              break;
+            }
+        }
+
+      // If ch1 was not found in array 2, store it
+      if (!found)
+        {
+          outputArray1->Add(ch1);
+        }
+      else
+        {
+          found = kFALSE;
+        }
+    }
+
+  // Pass 2
+  lastFoundAtJ = -1;
+  for (i = 0; i < kInputArray2Size; i++)
+    {
+      // Get the next channel from array 2
+      ch2 = (AliITSChannelSPD *) inputArray2->At(i);
+
+      // Is ch2 also in array 1?
+      for (j = lastFoundAtJ + 1; j < kInputArray1Size; j++)
+        {
+          ch1 = (AliITSChannelSPD *) inputArray1->At(j);
+          if (*ch1 == *ch2)
+            {
+              // Abort, go to next i
+              found = kTRUE;
+              lastFoundAtJ = j;
+              break;
+            }
+        }
+
+      // If ch1 was not found in array 1, store it
+      if (!found)
+        {
+          outputArray2->Add(ch2);
+        }
+      else
+        {
+          found = kFALSE;
+        }
+    }
+
+  if (outputArray1->GetEntries() > 0 || outputArray2->GetEntries() > 0) status = kTRUE;
+
+  return status;
+}
+
+//__________________________________________________________________________
+Bool_t AliITSBadChannelsAuxSPD::Find(AliITSChannelSPD *&channel, TObjArray *&array) const
+{
+  // Find the channel in the array
+  //
+  // Input: AliITSChannelSPD channel object, TObjArray of AliITSChannelSPD channel objects
+  // Ouput: (none)
+  // Return: kTRUE if channel is found in the array, kFALSE otherwise
+
+  Bool_t status = kFALSE;
+
+  // Loop over all channels in the array
+  Int_t channelNr = 0;
+  const Int_t kN = array->GetEntries();
+  while (channelNr < kN)
+    {
+      if (*channel == *(AliITSChannelSPD *)array->At(channelNr))
+       {
+         status = kTRUE;
+         break;
+       }
+
+      // Go to next channel
+      channelNr++;
+    }
+
+  return status;
+}
+
+//__________________________________________________________________________
+Bool_t AliITSBadChannelsAuxSPD::Find(AliITSdigitSPD *&digit, TObjArray *&array) const
+{
+  // Find the digit in the array
+  //
+  // WARNING: Using AliITSdigitSPD digits in this way is roughly 10% slower than to use AliITSChannelSPD channels
+  //
+  // Input: AliITSdigitSPD digit object, TObjArray of AliITSChannelSPD channel objects
+  // Ouput: (none)
+  // Return: kTRUE if digit is found in the array, kFALSE otherwise
+
+  Bool_t status = kFALSE;
+
+  AliITSChannelSPD *channel = 0;
+  const Int_t kN = array->GetEntries();
+  Int_t channelNr = 0;
+  Int_t column = digit->GetCoord1();
+  Int_t row = digit->GetCoord1();
+
+  // Loop over all channels in the array
+  while (channelNr < kN)
+    {
+      channel = (AliITSChannelSPD *)array->At(channelNr);
+      if ( (channel->GetColumn() == column) && (channel->GetRow() == row) )
+       {
+         status = kTRUE;
+         break;
+       }
+
+      // Go to next channel
+      channelNr++;
+    }
+
+  return status;
+}
+
+//__________________________________________________________________________
+AliITSdigitSPD* AliITSBadChannelsAuxSPD::CreateDigitFromChannel(const AliITSChannelSPD *&channel) const
+{
+  // Create a digit from a channel
+  //
+  // Input: AliITSChannelSPD object
+  // Ouput: (none)
+  // Return: AliITSdigitSPD object
+
+  AliITSdigitSPD *digit = new AliITSdigitSPD();
+
+  digit->SetCoord1(channel->GetColumn());
+  digit->SetCoord2(channel->GetRow());
+  digit->SetSignal(1);
+
+  return digit;
+}
+
+//__________________________________________________________________________
+AliITSChannelSPD* AliITSBadChannelsAuxSPD::CreateChannelFromDigit(const AliITSdigitSPD *&digit) const
+{
+  // Create a channel from a digit
+  //
+  // Input: AliITSdigitSPD object
+  // Ouput: (none)
+  // Return: AliITSChannelSPD object
+
+  AliITSChannelSPD *channel = new AliITSChannelSPD();
+
+  channel->SetColumn(digit->GetCoord1());
+  channel->SetRow(digit->GetCoord2());
+
+  return channel;
+}
+
+//__________________________________________________________________________
+Int_t AliITSBadChannelsAuxSPD::GetNumberOfBadChannels(Int_t* &badChannelsArray, Int_t* &indexArray, Int_t size) const
+{
+  // Get the total number of bad channels
+
+  Int_t n = 0;
+
+  // Loop over all modules
+  for (Int_t module = 0; module < size; module++)
+    {
+      // Get the module size (i.e. the number of bad channels)
+      n += badChannelsArray[indexArray[module]];
+    }
+
+  return n;
+}
+
+//__________________________________________________________________________
+Bool_t AliITSBadChannelsAuxSPD::CreateHTMLReport(char *name, Int_t* &badChannelsArray, Int_t* &indexArray,
+                                                const Int_t indexArraySize, TString *buffer, Bool_t tags)
+{
+  // Create an HTML report from the bad channels array
+  //
+  // Input : file name, badChannelsArray, indexArray, size of indexArray (i.e. number of modules),
+  //         tags boolean (if true, html tags will be added; if false, only formatted text will be created)
+  // Output: TString (buffer) containing the html code/ASCII text
+  // Return: kTRUE if a report has been created
+
+  Bool_t status = kFALSE;
+
+  Int_t totalNumberOfBadChannels = 0;
+  Int_t numberOfModulesWithBadChannels = 0;
+
+  if (tags)
+    {
+      buffer->Append("<html>");
+      buffer->Append("<head><title>SPD bad channels</title></head>\n");
+      buffer->Append("<body>\n");
+    }
+
+  buffer->Append("HTML report for file: ");
+  buffer->Append(name);
+
+  tags ? buffer->Append("<br>\n<br>\n") : buffer->Append("\n\n");
+
+  char temp[10];
+
+  // Loop over all modules
+  for (Int_t module = 0; module < indexArraySize; module++)
+    {
+      // Get the start position of the data
+      Int_t position = indexArray[module];
+
+      // Get the module size (i.e. the number of bad channels)
+      Int_t size = badChannelsArray[position++];
+
+      // Only continue if there are bad channels in this module
+      if (size > 0)
+       {
+         // There are bad channels in this file
+         status = kTRUE;
+         numberOfModulesWithBadChannels++;
+         totalNumberOfBadChannels += size;
+
+         // Create report
+         buffer->Append("SPD module = ");
+         sprintf(temp,"%d",module);
+         buffer->Append(temp);
+         buffer->Append("<br>\n");
+         buffer->Append("Number of bad channels = ");
+         sprintf(temp,"%d",size);
+         buffer->Append(temp);
+
+         tags ? buffer->Append("<br>\n") : buffer->Append("\n");
+
+         buffer->Append("(column, row) = ");
+
+         // Get all bad channels
+         Int_t i = 0;
+         while (i < size)
+           {
+             // Create and add the current channel
+             buffer->Append("(");
+             sprintf(temp,"%d",badChannelsArray[position++]);
+             buffer->Append(temp);
+             buffer->Append(", ");
+             sprintf(temp,"%d",badChannelsArray[position++]);
+             buffer->Append(temp);
+             buffer->Append(")");
+
+             if (i < size - 1)
+               {
+                 buffer->Append(", ");
+               }
+             else
+               {
+                 tags ? buffer->Append("<br>\n") : buffer->Append("\n");
+               }
+
+             // Go to next bad channel
+             i++;
+           }
+
+         tags ? buffer->Append("<br>\n") : buffer->Append("\n");
+
+       } // if size > 0
+    } // end loop over modules
+
+  if (!status)
+    {
+      buffer->Append("(Data does not contain any known bad channels)");
+    }
+
+  tags ? buffer->Append("<br>\n") : buffer->Append("\n");
+
+  buffer->Append("Total number of bad channels = ");
+  sprintf(temp,"%d",totalNumberOfBadChannels);
+  buffer->Append(temp);
+
+  tags ? buffer->Append("<br>\n") : buffer->Append("\n");
+
+  buffer->Append("Number of modules with bad channels = ");
+  sprintf(temp,"%d",numberOfModulesWithBadChannels);
+  buffer->Append(temp);
+
+  tags ? buffer->Append("<br>\n") : buffer->Append("\n");
+
+  buffer->Append("Number of modules = ");
+  sprintf(temp,"%d",indexArraySize);
+  buffer->Append(temp);
+
+  if (tags)
+    {
+      buffer->Append("<br>\n");
+      buffer->Append("</body>\n");
+      buffer->Append("</html>");
+    }
+  else
+    {
+      buffer->Append("\n");
+    }
+
+  return status;
+}
diff --git a/ITS/AliITSBadChannelsAuxSPD.h b/ITS/AliITSBadChannelsAuxSPD.h
new file mode 100644 (file)
index 0000000..b6ce8ff
--- /dev/null
@@ -0,0 +1,48 @@
+#ifndef ALIITSBADCHANNELSAUXSPD_H
+#define ALIITSBADCHANNELSAUXSPD_H
+
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+ * See cxx source for full Copyright notice                               */
+
+/* $Id$ */
+
+/////////////////////////////////////////////////////////
+// AliITSBadChannelsAuxSPD declaration by P. Nilsson 2005
+// AUTHOR/CONTACT: Paul.Nilsson@cern.ch                  
+//
+// Auxiliary algorithms for the SPD
+/////////////////////////////////////////////////////////
+
+
+#include <TObjArray.h>
+#include <TString.h>
+#include "AliITSChannelSPD.h"
+#include "AliITSdigitSPD.h"
+
+class AliITSBadChannelsAuxSPD {
+
+ public:
+
+  AliITSBadChannelsAuxSPD(void);                             // Default constructor
+  virtual ~AliITSBadChannelsAuxSPD(void) { };                 // Default destructor
+
+  // General algorithms
+  Bool_t Diff(TObjArray *&in1, TObjArray *&in2, TObjArray *&out1, TObjArray *&out2) const; // Diff algorithm
+  Bool_t Find(AliITSChannelSPD *&channel, TObjArray *&array) const; // Find a channel in the array
+  Bool_t Find(AliITSdigitSPD *&digit, TObjArray *&array) const;     // Find a digit in the array
+  Int_t GetNumberOfBadChannels(Int_t* &array, Int_t* &indexArray, Int_t size) const; // Get the number of bad channels
+
+  // Converters
+  AliITSdigitSPD* CreateDigitFromChannel(const AliITSChannelSPD *&channel) const; // Create a digit from a channel
+  AliITSChannelSPD* CreateChannelFromDigit(const AliITSdigitSPD *&digit) const;   // Create a channel from a digit
+
+  // Miscellanious
+  Bool_t CreateHTMLReport(char *name, Int_t* &array, Int_t* &indexArray,    // Create an HTML report
+                         const Int_t indexSize, TString *buffer, Bool_t tags);
+
+ protected:
+
+  ClassDef(AliITSBadChannelsAuxSPD,1)
+};
+
+#endif
diff --git a/ITS/AliITSBadChannelsSPD.cxx b/ITS/AliITSBadChannelsSPD.cxx
new file mode 100644 (file)
index 0000000..8c7ee25
--- /dev/null
@@ -0,0 +1,219 @@
+/**************************************************************************
+ * 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.                  *
+ **************************************************************************/
+
+/*
+$Log$
+*/
+
+///////////////////////////////////////////////////////////////////////////
+// AliITSBadChannelsSPD implementation by P. Nilsson 2005
+// AUTHOR/CONTACT: Paul.Nilsson@cern.ch
+//
+// The class is used by the AliITSPreprocessorSPD class to store the
+// final noisy and dead channel objects in the calibration database for
+// the SPD.
+//
+// An instance of this container class contains all the "bad" channels,
+// i.e. the noisy or dead channels of the SPD. It contains TObjArrays
+// for each module of the SPD (240 in total for ALICE, and 6 for the 2004
+// joint ITS beam test. The instance object should, once filled with data,
+// be stored in the calibration database. This is done by the SPD
+// preprocessor.
+///////////////////////////////////////////////////////////////////////////
+
+#include "AliITSBadChannelsSPD.h"
+
+ClassImp(AliITSBadChannelsSPD)
+
+//__________________________________________________________________________
+AliITSBadChannelsSPD::AliITSBadChannelsSPD(void) :
+  fIndexArraySize(0),
+  fBadChannelsArraySize(0),
+  fIndexArray(0x0),
+  fBadChannelsArray(0x0)
+{
+  // Default constructor
+}
+
+//__________________________________________________________________________
+AliITSBadChannelsSPD::AliITSBadChannelsSPD(const AliITSBadChannelsSPD &bc) :
+  TObject(bc)
+{
+  // Default copy constructor
+
+  // Copy array sizes
+  fIndexArraySize = bc.fIndexArraySize;
+  fBadChannelsArraySize = bc.fBadChannelsArraySize;
+
+  // Create new arrays
+  fIndexArray = new Int_t[fIndexArraySize];
+  fBadChannelsArray = new Int_t[fBadChannelsArraySize];
+
+  // Copy arrays
+  for (Int_t i = 0; i < fIndexArraySize; i++)
+    {
+      fIndexArray[i] = bc.fIndexArray[i];
+    }
+  for (Int_t i = 0; i < fBadChannelsArraySize; i++)
+    {
+      fBadChannelsArray[i] = bc.fBadChannelsArray[i];
+    }
+}
+
+//__________________________________________________________________________
+AliITSBadChannelsSPD::~AliITSBadChannelsSPD(void)
+{
+  // Default destructor
+
+  delete [] fIndexArray;
+  fIndexArray = 0;
+  delete [] fBadChannelsArray;
+  fBadChannelsArray = 0;
+}
+
+//__________________________________________________________________________
+AliITSBadChannelsSPD& AliITSBadChannelsSPD::operator=(const AliITSBadChannelsSPD &bc)
+{
+  // Assignment operator
+  
+  // Guard against self-assignment
+  if (this != &bc)
+    {
+      // Copy array sizes
+      fIndexArraySize = bc.fIndexArraySize;
+      fBadChannelsArraySize = bc.fBadChannelsArraySize;
+
+      delete [] fIndexArray;
+      fIndexArray = new Int_t[fIndexArraySize];
+
+      delete [] fBadChannelsArray;
+      fBadChannelsArray = new Int_t[fBadChannelsArraySize];
+
+      // Copy arrays
+      for (Int_t i = 0; i < fIndexArraySize; i++)
+       {
+         fIndexArray[i] = bc.fIndexArray[i];
+       }
+      for (Int_t i = 0; i < fBadChannelsArraySize; i++)
+       {
+         fBadChannelsArray[i] = bc.fBadChannelsArray[i];
+       }
+    }
+
+  return *this;
+}
+
+
+//__________________________________________________________________________
+void AliITSBadChannelsSPD::Put(Int_t* &badChannelsArray, const Int_t &badChannelsArraySize,
+                              Int_t* &indexArray, const Int_t &indexArraySize)
+{
+  // Add the bad channels and index arrays
+
+  fIndexArraySize = indexArraySize;
+  fBadChannelsArraySize = badChannelsArraySize;
+
+  fIndexArray = new Int_t[fIndexArraySize];
+  fBadChannelsArray = new Int_t[fBadChannelsArraySize];
+
+  // Copy the arrays
+  for (Int_t i = 0; i < fIndexArraySize; i++)
+    {
+      fIndexArray[i] = indexArray[i];
+    }
+  for (Int_t i = 0; i < fBadChannelsArraySize; i++)
+    {
+      fBadChannelsArray[i] = badChannelsArray[i];
+    }
+
+}
+
+//__________________________________________________________________________
+Bool_t AliITSBadChannelsSPD::Get(Int_t* &badChannelsArray, Int_t* &indexArray) const
+{
+  // Get the bad channels and the index arrays
+
+  Bool_t status = kTRUE;
+
+  // Set the array pointers
+  if (fIndexArraySize > 0)
+    {
+      badChannelsArray = fBadChannelsArray;
+      indexArray = fIndexArray;
+    }
+  else
+    {
+      status = kFALSE;
+    }
+
+  return status;
+}
+
+//__________________________________________________________________________
+Int_t* AliITSBadChannelsSPD::CreateModuleArray(const Int_t module) const
+{
+  // Create an Int_t array for a given module
+
+  Int_t *moduleArray = 0;
+
+  const Int_t kSize = AliITSBadChannelsSPD::GetModuleArraySize(module);
+  if (kSize > 0)
+    {
+      // Create a new array
+      moduleArray = new Int_t[kSize];
+
+      // Copy the module data into the module array from the bad channels array
+      const Int_t kPosition = fIndexArray[module];
+      for (Int_t index = 0; index < kSize; index++)
+       {
+         moduleArray[index] = fBadChannelsArray[kPosition + index];
+       }
+    }
+
+  return moduleArray;
+}
+
+//__________________________________________________________________________
+TObjArray* AliITSBadChannelsSPD::CreateModuleObjArray(const Int_t module) const
+{
+  // Create a TObjArray for a given module
+
+  TObjArray *moduleArray = 0;
+
+  const Int_t kSize = AliITSBadChannelsSPD::GetModuleObjArraySize(module);
+  if (kSize > 0)
+    {
+      // Create a new array
+      moduleArray = new TObjArray(kSize);
+
+      // Copy the module data into the module array from the bad channels array
+
+      // Get the start position of the data (skip the number of bad channels, i.e. the first stored number)
+      Int_t position = fIndexArray[module] + 1;
+
+      Int_t i = 0;
+      while (i < kSize)
+       {
+         // Create and add the current channel
+         AliITSChannelSPD *channel = new AliITSChannelSPD(fBadChannelsArray[position++], fBadChannelsArray[position++]);
+         moduleArray->Add(channel);
+
+         // Go to next bad channel
+         i++;
+       }
+    }
+
+  return moduleArray;
+}
diff --git a/ITS/AliITSBadChannelsSPD.h b/ITS/AliITSBadChannelsSPD.h
new file mode 100644 (file)
index 0000000..4af28c0
--- /dev/null
@@ -0,0 +1,60 @@
+#ifndef ALIITSBADCHANNELSSPD_H
+#define ALIITSBADCHANNELSSPD_H
+
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+ * See cxx source for full Copyright notice                               */
+
+/* $Id$ */
+
+///////////////////////////////////////////////////////////////////////////
+// AliITSBadChannelsSPD declaration by P. Nilsson 2005
+// AUTHOR/CONTACT: Paul.Nilsson@cern.ch
+//
+// The class is used by the AliITSPreprocessorSPD class to store the
+// final noisy and dead channel objects in the calibration database for
+// the SPD.
+//
+// (See the source file for more information)
+///////////////////////////////////////////////////////////////////////////
+
+
+#include "TObjArray.h"
+#include "AliITSChannelSPD.h"
+
+class AliITSBadChannelsSPD: public TObject {
+
+ public:
+
+  AliITSBadChannelsSPD(void);                          // Default constructor
+  AliITSBadChannelsSPD(const AliITSBadChannelsSPD &bc); // Default copy constructor
+  virtual ~AliITSBadChannelsSPD(void);                  // Default destructor
+  AliITSBadChannelsSPD& operator=(const AliITSBadChannelsSPD& bc); // Assignment operator
+
+  void Put(Int_t* &array, const Int_t &arraySize,       // Add new arrays to the collection
+          Int_t* &index, const Int_t &indexSize);
+  Bool_t Get(Int_t* &array, Int_t* &index) const;       // Retrieve the stored arrays (true if non empty arrays)
+
+  Int_t GetIndexArraySize(void) const                   // Return the size of the index array
+    { return fIndexArraySize; };
+  Int_t GetBadChannelsArraySize(void) const             // Return the size of the bad channels array
+    { return fBadChannelsArraySize; };
+
+  Int_t* CreateModuleArray(const Int_t module) const;   // Create an array with sequential data for a given module
+  Int_t GetModuleArraySize(const Int_t module) const    // Return array size for a given module
+    { return (2*fBadChannelsArray[fIndexArray[module]] + 1); };
+
+  TObjArray* CreateModuleObjArray(const Int_t module) const; // Create a TObjArray with data for a given module
+  Int_t GetModuleObjArraySize(const Int_t module) const      // Return TObjArray size for a given module
+    { return (fBadChannelsArray[fIndexArray[module]]); };
+
+ protected:
+
+  Int_t fIndexArraySize;                                // Size of the index array
+  Int_t fBadChannelsArraySize;                          // Size of the bad channels array
+  Int_t *fIndexArray;                                   //[fIndexArraySize]
+  Int_t *fBadChannelsArray;                             //[fBadChannelsArraySize]
+
+  ClassDef(AliITSBadChannelsSPD,1)
+};
+
+#endif
diff --git a/ITS/AliITSChannelSPD.cxx b/ITS/AliITSChannelSPD.cxx
new file mode 100644 (file)
index 0000000..488deb7
--- /dev/null
@@ -0,0 +1,95 @@
+/**************************************************************************
+ * 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.                  *
+ **************************************************************************/
+
+/*
+$Log$
+*/
+
+///////////////////////////////////////////////////////////////////////////
+// AliITSChannelSPD implementation by P. Nilsson 2005
+// AUTHOR/CONTACT: Paul.Nilsson@cern.ch
+//
+// Objects of this class are stored in TObjArrays and should be
+// interpreted as "bad" channels, i.e. either noisy or dead channels
+// depending on where they are stored.
+//
+// A channel has the structure:
+//
+//                           Int_t fColumn:    Column in the SPD module
+//                           Int_t fRow:       Row in the SPD module
+//
+// The class is used by the AliITSPreprocessorSPD class to store noisy
+// and dead channels in the calibration database for the SPD.
+//
+// A channel can be compared with other channels (the equality operator
+// is defined). This is e.g. useful for the clustering algorithm. A noisy
+// channel should not be used in the clustering
+///////////////////////////////////////////////////////////////////////////
+
+#include "AliITSChannelSPD.h"
+
+ClassImp(AliITSChannelSPD)
+
+//__________________________________________________________________________
+AliITSChannelSPD::AliITSChannelSPD(void) :
+fColumn(-1),
+fRow(-1)
+{
+  // Default constructor
+}
+
+
+//__________________________________________________________________________
+AliITSChannelSPD::AliITSChannelSPD(const AliITSChannelSPD &ch) :
+  TObject(ch)
+{
+  // Copy constructor
+
+  fColumn = ch.fColumn;
+  fRow = ch.fRow;
+}
+
+//__________________________________________________________________________
+AliITSChannelSPD& AliITSChannelSPD::operator=(const AliITSChannelSPD &ch)
+{
+  // Assignment operator
+  
+  // Guard against self-assignment
+  if (this != &ch)
+    {
+      // Copy the data members
+      fColumn = ch.fColumn;
+      fRow = ch.fRow;
+    }
+  return *this;
+}
+
+//__________________________________________________________________________
+Bool_t AliITSChannelSPD::operator==(const AliITSChannelSPD &channel) const
+{
+  // Equality operator
+  // For comparisons between AliITSChannelSPD objects
+
+  return ( ((fColumn == channel.fColumn) && (fRow == channel.fRow)) );
+}
+
+//__________________________________________________________________________
+AliITSChannelSPD::AliITSChannelSPD(const Int_t column, const Int_t row)
+{
+  // Constructor for already existing channel
+
+  fColumn = column;
+  fRow = row;
+}
diff --git a/ITS/AliITSChannelSPD.h b/ITS/AliITSChannelSPD.h
new file mode 100644 (file)
index 0000000..6c9b3e9
--- /dev/null
@@ -0,0 +1,45 @@
+#ifndef ALIITSCHANNELSPD_H
+#define ALIITSCHANNELSPD_H
+
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+ * See cxx source for full Copyright notice                               */
+
+/* $Id$ */
+
+///////////////////////////////////////////////////////////////////////////
+// AliITSChannelSPD declaration by P. Nilsson 2005
+// AUTHOR/CONTACT: Paul.Nilsson@cern.ch
+//
+// Objects of this class are stored in a TObjArray and should be
+// interpreted as "bad" channels, i.e. either noisy or dead channels
+// depending on where they are stored
+///////////////////////////////////////////////////////////////////////////
+
+#include <TObject.h>
+
+class AliITSChannelSPD: public TObject {
+
+ public:
+
+  AliITSChannelSPD(void);                                  // Default constructor
+  AliITSChannelSPD(const Int_t column, const Int_t row);    // Constructor for already existing "bad" channel
+  AliITSChannelSPD(const AliITSChannelSPD &ch);             // Copy constructor
+  virtual ~AliITSChannelSPD(void) { };                      // Default destructor
+  AliITSChannelSPD& operator=(const AliITSChannelSPD &ch);  // Assignment operator
+  Bool_t operator==(const AliITSChannelSPD &channel) const; // Equivalence operator
+
+  // Getters and setters
+  Int_t GetColumn(void) const { return fColumn; };          // Get column
+  Int_t GetRow(void) const { return fRow; };                // Get row
+  void SetColumn(Int_t c) { fColumn = c; };                 // Set column
+  void SetRow(Int_t r) { fRow = r; };                       // Set row
+
+ protected:
+
+  Int_t fColumn;                                            // SPD column (real range [0,31], but not checked)
+  Int_t fRow;                                               // SPD row (real range [0,255] but not checked)
+
+  ClassDef(AliITSChannelSPD,1)
+};
+
+#endif
diff --git a/ITS/AliITSPreprocessorSPD.cxx b/ITS/AliITSPreprocessorSPD.cxx
new file mode 100644 (file)
index 0000000..0c2fcc7
--- /dev/null
@@ -0,0 +1,1377 @@
+/**************************************************************************
+ * 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.                  *
+ **************************************************************************/
+
+/*
+$Log$
+*/
+
+///////////////////////////////////////////////////////////////////////////
+// AliITSPreprocessorSPD implementation by P. Nilsson 2005
+// MAIN AUTHOR/CONTACT: Paul.Nilsson@cern.ch
+//
+// The purpose of this class is to provide algorithms for identification
+// of "bad channels" such as dead channels and noisy channels in the SPD
+//
+// Examples on how to use this class can be found in the macros:
+//
+// .findNoisyChannels.C (Locate and store noisy channels in the CDB)
+// .readNoisyChannels.C (Read noisy channels from the CDB)
+// .findDeadChannels.C  (Locate and store dead channels in the CDB)
+// .readDeadChannels.C  (Read dead channels from the CDB)
+///////////////////////////////////////////////////////////////////////////
+
+#include "AliITSPreprocessorSPD.h"
+
+ClassImp(AliITSPreprocessorSPD)
+
+
+//__________________________________________________________________________
+AliITSPreprocessorSPD::AliITSPreprocessorSPD(void):
+  fITSLoader(0x0),
+  fRunLoader(0x0),
+  fThresholdRatio(5.),
+  fThreshold(5),
+  fMaximumNumberOfEvents(1000000),
+  fHighestModuleNumber(0),
+  fSelectedAlgorithm(kOptimizedForRealData),
+  fGeometryMode(kALICEGeometry),
+  fNumberOfBadChannels(0),
+  fInit(kFALSE),
+  fVMEMode(kFALSE),
+  fDigitsHistogram(0),
+  fBadChannelsObjArray(0),
+  fBadChannelsIntArray(0),
+  fBadChannelsIndexArray(0),
+  fBadChannelsContainer(0)
+{
+  // Default constructor for the SPD preprocessor
+  //
+  // Initialization has to be done by hand using Set* methods and the Open method
+  //
+  // Input :
+  // Output:
+  // Return: <empty/uninitialized AliITSPreprocessorSPD object>
+}
+
+
+//__________________________________________________________________________
+AliITSPreprocessorSPD::AliITSPreprocessorSPD(const char *fileName, const char *mode,
+                                            const char *fileNameg, const Int_t maxNumberOfEvents):
+  fITSLoader(0x0),
+  fRunLoader(0x0),
+  fInit(kFALSE)
+{
+  // Standard constructor for the SPD preprocessor
+  //
+  // Input : Name of digit file
+  // Output: fInit
+  // Return: Initialized SPD preprocessor object
+
+  // Initialize
+  AliITSPreprocessorSPD::Init();
+  AliITSPreprocessorSPD::SetMaximumNumberOfEvents(maxNumberOfEvents);
+
+  // Open and read the galice and digit files
+  if (!AliITSPreprocessorSPD::Open(fileName, mode, fileNameg))
+    {
+      AliError("Failed to open file");
+      fInit = kFALSE;
+    }
+}
+
+
+//__________________________________________________________________________
+AliITSPreprocessorSPD::AliITSPreprocessorSPD(const AliITSPreprocessorSPD &prep) :
+  TTask(prep)
+{
+  // Default copy constructor
+  // Notice that only pointer addresses are copied!
+  // Memory allocations of new objects are not done.
+
+  fITSLoader = prep.fITSLoader;
+  fRunLoader = prep.fRunLoader;
+  fThresholdRatio = prep.fThresholdRatio;
+  fThreshold = prep.fThreshold;
+  fMaximumNumberOfEvents = prep.fMaximumNumberOfEvents;
+  fHighestModuleNumber = prep.fHighestModuleNumber;
+  fSelectedAlgorithm = prep.fSelectedAlgorithm;
+  fGeometryMode = prep.fGeometryMode;
+  fNumberOfBadChannels = prep.fNumberOfBadChannels;
+  fInit = prep.fInit;
+  fVMEMode = prep.fVMEMode;
+  fDigitsHistogram = prep.fDigitsHistogram;
+  fBadChannelsObjArray = prep.fBadChannelsObjArray;
+  fBadChannelsIntArray = prep.fBadChannelsIntArray;
+  fBadChannelsIndexArray = prep.fBadChannelsIndexArray;
+  fBadChannelsContainer = prep.fBadChannelsContainer;
+}
+
+
+//__________________________________________________________________________
+AliITSPreprocessorSPD& AliITSPreprocessorSPD::operator=(const AliITSPreprocessorSPD &prep)
+{
+  // Assignment operator
+
+  AliError("Not implemented");
+
+  if (this != &prep) { } // Do not delete this line
+
+  return *this;
+}
+
+
+//__________________________________________________________________________
+AliITSPreprocessorSPD::~AliITSPreprocessorSPD(void)
+{
+  // Destructor for the SPD preprocessor
+
+  if (fDigitsHistogram)
+    {
+      // try fDigitsHistogram->Delete(); if the following crashes
+      for (UInt_t module = 0; module < fNumberOfModules; module++)
+       {
+         (*fDigitsHistogram)[module]->Delete();
+       }
+      delete fDigitsHistogram;
+      fDigitsHistogram = 0;
+    }
+
+  if (fNumberOfBadChannels)
+    {
+      delete [] fNumberOfBadChannels;
+      fNumberOfBadChannels = 0;
+    }
+
+  if (fBadChannelsIntArray)
+    {
+      delete [] fBadChannelsIntArray;
+      fBadChannelsIntArray = 0;
+    }
+
+  if (fBadChannelsIndexArray)
+    {
+      delete [] fBadChannelsIndexArray;
+      fBadChannelsIndexArray = 0;
+    }
+
+  if (fBadChannelsObjArray)
+    {
+      fBadChannelsObjArray->Delete();
+      delete fBadChannelsObjArray;
+      fBadChannelsObjArray = 0;
+    }
+
+  delete fRunLoader;
+  fRunLoader = 0;
+
+  delete fBadChannelsContainer;
+  fBadChannelsContainer = 0;
+}
+
+
+//__________________________________________________________________________
+void AliITSPreprocessorSPD::Init(void)
+{
+  // Initialization of the SPD preprocessor
+  //
+  // Input : (void)
+  // Output: Several logistical variables
+  // Return: (void)
+
+  // Default maximum number of events per histogram
+  fMaximumNumberOfEvents = 1000000;
+
+  // Default noisy channel removal algorithm
+  fSelectedAlgorithm = kOptimizedForRealData;
+
+  // Default noisy channel threshold and threshold ratio
+  // (threshold for current bin content divided by the average neighboring bin contents)
+  fThreshold = 10;
+  fThresholdRatio = 5.;
+
+  // Set default geometry mode (ALICE geometry). This also sets fNumberOfModules
+  AliITSPreprocessorSPD::SetGeometryMode(kALICEGeometry);
+
+  // The highest module number with found bad channels
+  fHighestModuleNumber = 0;
+
+  // Assume input is not from a VME file
+  fVMEMode = kFALSE;
+
+  // Initialization is complete
+  fInit = kTRUE;
+}
+
+
+//__________________________________________________________________________
+void AliITSPreprocessorSPD::SetGeometryMode(UInt_t mode)
+{
+  // Set the geometry mode
+  //
+  // Input : Geometry mode (either kTestBeamGeometry or kALICEGeometry)
+  // Output: 
+  // Return: (void)
+
+  fGeometryMode = mode;
+
+  // In case of an input VME file, the number of modules has already been fixed.
+  // Do not try to change it
+  if (!fVMEMode)
+    {
+      if (mode == kALICEGeometry)
+       {
+         fNumberOfModules = kNumberOfSPDModules;
+       }
+      else if (mode == kTestBeamGeometry)
+       {
+         fNumberOfModules = kNumberOfTestBeamSPDModules;
+       }
+      else
+       {
+         AliError("Unknown geometry mode, defaults to ALICE geometry");
+         fNumberOfModules = kNumberOfSPDModules;
+       }
+    }
+}
+
+
+//__________________________________________________________________________
+void AliITSPreprocessorSPD::SetFakeNoisyChannel(Int_t module, Int_t column, Int_t row)
+{
+  // Introduce a fake noisy channel in the hit histograms
+  //
+  // Input : Module, column and row numbers
+  // Output: Updated hit histograms
+  // Return: (void)
+
+  if ((UInt_t)module < fNumberOfModules)
+    {
+      ((TH2F*)(*fDigitsHistogram)[module])->Fill(column, row, 1000000);
+    }
+  else
+    {
+      AliError("No such module number");
+    }
+}
+
+
+//__________________________________________________________________________
+Bool_t AliITSPreprocessorSPD::Open(const char *fileName, const char *mode, const char *fileNameg)
+{
+  // Open digit file
+  //
+  // Input : Name and mode of ITS digit file, name of galice file
+  // Output: Digits
+  // Return: kTRUE if loaders succeed
+
+  Bool_t status = kFALSE;
+  Bool_t status0 = kFALSE;
+  Bool_t status1 = kFALSE;
+  Bool_t status2 = kFALSE;
+  Bool_t status3 = kFALSE;
+
+  // Only proceed if initialization has been done
+  if (fInit)
+    {
+      TString m = (TString)mode;
+      if (m == "daq" || m == "DAQ")
+        {
+          // Open the data file and get the run loader
+          fRunLoader = AliRunLoader::Open(fileNameg);
+          if (fRunLoader)
+            {
+              // Get the gAlice object
+              status0 = AliITSPreprocessorSPD::GetgAlice();
+
+              // Get the ITS digits
+              if (status0) status1 = AliITSPreprocessorSPD::GetITSDigits(fileName);
+
+              // Create the test beam object
+              if (status1) status2 = AliITSPreprocessorSPD::CreateGeometryObj();
+
+             // Fill histograms with DAQ digits
+             if (status2) status3 = AliITSPreprocessorSPD::FillHistograms();
+
+              status = status0 & status1 & status2 & status3;
+            }
+          else
+            {
+              AliError("Failed to get the run loader");
+            }
+        }
+      else if (m == "vme" || m == "VME")
+        {
+         // Open the VME file that contains histograms with fired channels as read by the stand-alone VME system
+         TFile *vmeFile = TFile::Open(fileName);
+
+         if (!vmeFile->IsOpen())
+           {
+             AliError("Could not open VME input file");
+           }
+         else
+           {
+             // Get the histograms from the VME file that contains all fired channels
+             status0 = AliITSPreprocessorSPD::GetVMEHistograms(vmeFile);
+
+             // Create the test beam object
+             if (status0) status1 = AliITSPreprocessorSPD::CreateGeometryObj();
+           }
+
+         // This boolean will be used to override any attempts of changing the number of modules by the user
+         // with the SetGeometryMode method. For VME files the number of modules will entirely be determined by
+         // the input VME root file, i.e. by the number of histograms in this file
+         fVMEMode = kTRUE;
+
+         status = status0 & status1;
+        }
+      else
+        {
+          AliError("Unknown filetype - assuming DAQ file");
+        }
+
+      // At this stage, the final number of modules will be known (safe to define arrays)
+      // In case data is read from a VME root file, it will not be known before
+      if (status)
+       {
+         // Create the arrays for bookkeeping and storing the noisy channels
+         if (!fBadChannelsObjArray)
+           {
+             fBadChannelsObjArray = new TObjArray();
+           }
+         if (!fBadChannelsIndexArray)
+           {
+             // This array will contain the begin and end indices for each module, i.e. where to begin
+             // and stop reading the fBadChannelsObjArray for a certain module.
+             // The last position of the array will contain the end index of the last module
+             fBadChannelsIndexArray = new Int_t[fNumberOfModules + 1];
+             for (UInt_t module = 0; module < fNumberOfModules + 1; module++)
+               {
+                 fBadChannelsIndexArray[module] = 0;
+               }
+           }
+       }
+    }
+  else
+    {
+      AliError("SPD preprocessor not initialized. Can't load digits");
+    }
+
+  return status;
+}
+
+
+//__________________________________________________________________________
+Bool_t AliITSPreprocessorSPD::GetgAlice(void)
+{
+  // Get the gAlice object
+  //
+  // Input : (void)
+  // Output: gAlice object
+  // Return: kTRUE if the gAlice object was found
+
+  Bool_t status = kTRUE;
+
+  // Load gAlice
+  fRunLoader->LoadgAlice();
+  if (!fRunLoader->GetAliRun())
+    {
+      AliError("gAlice not found on file. Aborting.");
+      status = kFALSE;
+    }
+
+  return status;
+}
+
+
+//__________________________________________________________________________
+Bool_t AliITSPreprocessorSPD::GetVMEHistograms(TFile *vmeFile)
+{
+  // Get pre-filled digit histograms from input VME file
+  //
+  // Input : pointer to VME file
+  // Output: 
+  // Return: kTRUE if histograms are found on file
+
+  Bool_t status = kFALSE;
+
+  // Get the file directory
+  TDirectory *dir = (TDirectory *)vmeFile;
+
+  // Get the number of keys (histograms in this case corresponding to modules/ladders)
+  fNumberOfModules = dir->GetNkeys();
+  if ((fNumberOfModules > 0) && (fNumberOfModules <= kNumberOfSPDModules))
+    {
+      status = kTRUE;
+
+      // Create bad channel histograms
+      fDigitsHistogram = new TObjArray(fNumberOfModules);
+
+      // Create a key iterator
+      TIter nextkey(dir->GetListOfKeys());
+      TKey *key = 0;
+
+      // Loop over all objects, read them in to memory one by one
+      UInt_t module = 0;
+      while ( (key = (TKey *)nextkey()) )
+       {
+         (*fDigitsHistogram)[module++] = (TH2F *)key->ReadObj();
+
+         // For safety
+         if (module > fNumberOfModules)
+           {
+             AliError("Wrong number of keys in VME file");
+             status = kFALSE;
+             break;
+           }
+       }
+    }
+  else
+    {
+      AliError("Wrong number of histograms in VME file");
+    }
+  return status;
+}
+
+//__________________________________________________________________________
+Bool_t AliITSPreprocessorSPD::GetITSDigits(const char *fileName)
+{
+  // Get the ITS digits
+  //
+  // Input : name of digits file
+  // Output: fITSLoader object, ITS digits
+  // Return: kTRUE if loader succeed
+
+  Bool_t status = kTRUE;
+
+  // Load the gAlice and the header
+  fRunLoader->LoadgAlice();
+  fRunLoader->LoadHeader();
+
+  // Get the ITS loader
+  fITSLoader = (AliITSLoader*) fRunLoader->GetLoader("ITSLoader");
+  if (!fITSLoader)
+    {
+      AliError("ITS loader not found");
+      status = kFALSE;
+    }
+  else
+    {
+      // Open the digits file
+      fITSLoader->SetDigitsFileName(fileName);
+    }
+
+  return status;
+}
+
+
+//__________________________________________________________________________
+TClonesArray* AliITSPreprocessorSPD::CreateDigitsArray(void) const
+{
+  // Creation of the digits array
+  //
+  // Input : (void)
+  // Output:
+  // Return: Pointer to the SPD digits array
+
+  // Create an array for 5 chips with 8192 channels each
+  TClonesArray *digitsArray = new TClonesArray("AliITSdigitSPD", kNumberOfChannels);
+
+  return digitsArray;
+}
+
+
+//__________________________________________________________________________
+Bool_t AliITSPreprocessorSPD::CreateGeometryObj(void)
+{
+  // Creation of the geometry object
+  //
+  // This object is used to get the number of SPD half-staves
+  //
+  // Input : (void)
+  // Output: fGeometryObj
+  // Return: kTRUE if fGeometryObj has been created
+
+  Bool_t status = true;
+
+  // Create geometry object
+  // fGeometryObj = new ...
+  // if (!fGeometryObj) status = kFALSE;
+
+  // Get SPD parameters
+  // fNumberOfColumns = fGeometryObject->GetNumberOfColumns();
+  // fNumberOfRows = fGeometryObject->GetNumberOfRows();
+
+  fNumberOfColumns = kNumberOfColumns;
+  fNumberOfRows = kNumberOfRows;
+
+  return status;
+}
+
+
+//__________________________________________________________________________
+void AliITSPreprocessorSPD::CreateHistograms(void)
+{
+  // Create the noisy channel histograms
+  //
+  // Input : (void)
+  // Output: Noisy channel histograms
+  // Return: (void)
+
+  TString moduleName;
+  char n[4]; // For storing the module number (maximum module number is 240)
+
+  // Create noisy channel histograms
+  fDigitsHistogram = new TObjArray(fNumberOfModules);
+
+  for (UInt_t i = 0; i < fNumberOfModules; i++)
+    {
+      // Histogram name
+      moduleName = "module_";
+      sprintf(n,"%d",i);
+      moduleName.Append(n);
+
+      (*fDigitsHistogram)[i] = new TH2F(moduleName,"Digits",
+                                       fNumberOfColumns,-.5,(1.*fNumberOfColumns - .5),
+                                       fNumberOfRows,-.5,(1.*fNumberOfRows - .5));
+    }
+}
+
+
+//__________________________________________________________________________
+Bool_t AliITSPreprocessorSPD::FillHistograms(void)
+{
+  // Fill the histograms with digits (hit positions of unclustered hits)
+  //
+  // (There is one digit histogram per SPD module, i.e. a half-stave, 10 chips)
+  //
+  // Input : No arguments (Empty digit histograms)
+  // Output: Filled digit histograms
+  // Return: kTRUE if histograms are filled with digits, kFALSE otherwise
+
+  AliInfo("Filling noisy channel histograms");
+
+  Bool_t status = kTRUE;
+  AliITSdigitSPD *digitSPD = 0;
+  UInt_t row;
+  UInt_t column;
+  TBranch *digitsSPDBranch;
+  TTree *digitsTree;
+
+  // Get the digits
+  fITSLoader->LoadDigits("read");
+
+  // Create noisy channel histograms
+  AliITSPreprocessorSPD::CreateHistograms();
+
+  // Create an empty SPD digits array
+  TClonesArray *digitsArraySPD = AliITSPreprocessorSPD::CreateDigitsArray();
+
+  // Get number of events
+  UInt_t numberOfEvents = (fRunLoader->TreeE()) ? static_cast<UInt_t>(fRunLoader->TreeE()->GetEntries()) : 0;
+
+  // Make sure we don't try to analyze more data than there actually is
+  if (numberOfEvents < fMaximumNumberOfEvents)
+    {
+      fMaximumNumberOfEvents = numberOfEvents;
+    }
+
+  // Loop over all digits and put them in the corresponding histograms
+  if (numberOfEvents > 0)
+    {
+      for (UInt_t event = 0; event < fMaximumNumberOfEvents; event++)
+       {
+         // Get the current event
+         fRunLoader->GetEvent(event);
+
+         // Get the ITS digits tree
+         digitsTree = fITSLoader->TreeD();
+
+         // Disable all branches except the SPD branch to speed up the reading process
+         digitsTree->SetBranchStatus("ITSDigitsSPD",1);
+         digitsTree->SetBranchStatus("ITSDigitsSDD",0);
+         digitsTree->SetBranchStatus("ITSDigitsSSD",0);
+
+         // Reset the SPD digits array to make sure it is empty
+         digitsArraySPD->Clear();
+
+         // Get the SPD digits branch and set the address
+         digitsSPDBranch = digitsTree->GetBranch("ITSDigitsSPD");
+
+         digitsSPDBranch->SetAddress(&digitsArraySPD);
+
+         if (event%100 == 0) AliInfo(Form("Event #%d", event));
+
+         // Loop over all modules
+         UInt_t numberOfDigits = 0;
+         for (UInt_t module = 0; module < fNumberOfModules; module++)
+           {
+             // Get event data for current module
+             digitsTree->GetEvent(module);
+
+             // Get the number of entries
+             numberOfDigits = digitsArraySPD->GetEntries();
+
+             // Loop over all digits
+             for (UInt_t digit = 0; digit < numberOfDigits; digit++)
+               {
+                 // Get the current digit
+                 digitSPD = (AliITSdigitSPD*) digitsArraySPD->At(digit);
+                 row = digitSPD->GetCoord1();
+                 column = digitSPD->GetCoord2();
+
+                 // Fill the digits histogram
+                 ((TH2F*)(*fDigitsHistogram)[module])->Fill(column, row);
+
+               } // end digit loop
+           } // end module loop
+       } // end event loop
+    } // end numberOfEvents > 0
+  else
+    {
+      status = kFALSE;
+    }
+
+  // Cleanup
+  delete digitsArraySPD;
+  digitsArraySPD = 0;
+
+  return status;
+}
+
+
+//__________________________________________________________________________
+Bool_t AliITSPreprocessorSPD::FindDeadChannels(void)
+{
+  // Locate dead channels
+  //
+  // Input : Filled hit histograms
+  // Output: TObjArray (fBadChannelsObjArray) with all identified dead channels
+  // Return: kTRUE if dead channels have been found
+
+  Bool_t status = kFALSE;
+
+  // Proceed only if properly initialized
+  if (fInit)
+    {
+      if (fVMEMode)
+       {
+         // Initialize counters
+         fNumberOfBadChannels = new Int_t[fNumberOfModules];
+         for (UInt_t module = 0; module < fNumberOfModules; module++)
+           {
+             fNumberOfBadChannels[module] = 0;
+           }
+
+         // Loop over all modules (intentional modularization - DCS will occationally want to
+         // look for noisy channels in certain modules, but not all)
+         fIndex = 0; // Global bad channels array counter (must be reset here)
+         for (UInt_t module = 0; module < fNumberOfModules; module++)
+           {
+             status |= AliITSPreprocessorSPD::FindDeadChannelsInModule(module);
+           }
+       }
+      else
+       {
+         AliError("Dead channels can only be found in data taken with stand-alone VME system");
+       }
+    }
+  else
+    {
+      AliError("Not properly initialized");
+    }
+
+  return status;
+}
+
+
+//__________________________________________________________________________
+Bool_t AliITSPreprocessorSPD::FindDeadChannelsInModule(UInt_t module)
+{
+  // Locate dead channels
+  // This method assumes that the preprocessor is operator in VME mode.
+  // The algorithm is very simple. It assumes that the data was taken in
+  // a mode where all working SPD pixels should respond as being hit.
+  // fThreshold is used as the limit where everything below this value will
+  // be considered as "dead".
+  //
+  // Input : Filled hit histograms
+  // Output: TObjArray (fBadChannelsObjArray) with all identified noisy channels
+  // Return: kTRUE if dead channels have been found
+
+  // Store the index number for this module
+  fBadChannelsIndexArray[module] = fIndex++;
+
+  UInt_t xBin, numberOfXBins;
+  UInt_t yBin, numberOfYBins;
+  Float_t binContent;
+
+  numberOfXBins = ((TH2F*)(*fDigitsHistogram)[module])->GetNbinsX();
+  numberOfYBins = ((TH2F*)(*fDigitsHistogram)[module])->GetNbinsY();
+
+  // Loop over all bins in this histogram
+  for (xBin = 1; xBin <= numberOfXBins; xBin++)
+    for (yBin = 1; yBin <= numberOfYBins; yBin++)
+      {
+       binContent = ((TH2F*)(*fDigitsHistogram)[module])->GetBinContent(xBin, yBin);
+
+       // Store this channel/bin if outside accepted limits
+       // A channel has to fire MORE times than the fThreshold value, or it will
+       // be considered as "dead"
+       if (binContent <= fThreshold)
+         {
+           // Store the dead channel in the array
+           // The channel object will be deleted in the destructor using the TObjArray Delete() method
+           // (The array will assume ownership of the channel object)
+           AliITSChannelSPD *channel = new AliITSChannelSPD((Int_t)(xBin - 1), (Int_t)(yBin - 1));
+
+           // Store the noisy channel in the array
+           fBadChannelsObjArray->Add(channel);
+
+           // Keep track of the number of bad channels in this module
+           fNumberOfBadChannels[module]++;
+           fIndex += 2;
+
+           // Keep track of the highest module number
+           if (module > fHighestModuleNumber) fHighestModuleNumber = module;
+
+           AliInfo(Form("New dead pixel in (m,c,r) = (%d,%d,%d)", module, xBin - 1, yBin - 1));
+         }
+      } // end bin loop
+
+  return (fNumberOfBadChannels[module] > 0);
+}
+
+
+//__________________________________________________________________________
+Bool_t AliITSPreprocessorSPD::FindNoisyChannels(void)
+{
+  // Locate noisy channels by searching through the digit histograms
+  // (There is one digit histogram per SPD module, i.e. a half-stave, 5 chips)
+  //
+  // Input : Digits
+  // Output: TObjArray (fBadChannelsObjArray) with all identified noisy channels
+  // Return: kTRUE if noisy channels have been found
+
+  Bool_t status = kFALSE;
+
+  // Proceed only if properly initialized
+  if (fInit)
+    {
+      // (For testing purposes, noisy channels can be inserted here)
+      // SetFakeNoisyChannel(4,10,10);
+
+      // Initialize counters
+      fNumberOfBadChannels = new Int_t[fNumberOfModules];
+      for (UInt_t module = 0; module < fNumberOfModules; module++)
+       {
+         fNumberOfBadChannels[module] = 0;
+       }
+
+      // Scan through all the histogram bins and search for average filling deviations
+      if ((fSelectedAlgorithm == kOptimizedForRealData) || (fSelectedAlgorithm == kOptimizedForRealDataRMS))
+       {
+         // Noisy channel algorithm optimized for real data..........................
+         // Histograms can have any shape (both thresholds and quotients are used)
+         // This algorithm can be used to find noisy channels even if the data was
+         // taken with beam. All channels outside accepted limits (set by fThreshold
+         // and fThresholdRatio) will be marked as noisy
+
+         if (fSelectedAlgorithm == kOptimizedForRealData)
+           {
+             AliInfo("Searching for noisy channels (optimized for real data)");
+           }
+         else
+           {
+             AliInfo("Searching for noisy channels (optimized for real data, RMS version)");
+           }
+
+         // Loop over all modules (intentional modularization - DCS will occationally want to
+         // look for noisy channels in certain modules, but not all)
+         fIndex = 0; // Global bad channels array counter (must be reset here)
+         for (UInt_t module = 0; module < fNumberOfModules; module++)
+           {
+             status |= AliITSPreprocessorSPD::FindNoisyChannelsInModuleAlgo0(module);
+           }
+       } // end algorithm 0
+      else
+       {
+         // Noisy channel algorithm optimized for calibration data...........................
+         // Histograms will/should only contain noisy channels (only thresholds are used)
+         // Calibration histograms should have no background. The calibration data
+         // should have been taken without beam. All channels outside accepted limits
+         // (set by fThreshold) will be marked as noisy
+
+         AliInfo("Searching for noisy channels (optimized for calibration data)");
+
+         // Loop over all modules (intentional modularization - DCS will occationally want to
+         // look for noisy channels in certain modules, but not all)
+         fIndex = 0; // Global bad channels array counter (must be reset here)
+         for (UInt_t module = 0; module < fNumberOfModules; module++)
+           {
+             status |= AliITSPreprocessorSPD::FindNoisyChannelsInModuleAlgo1(module);
+           }
+       } // end algorithm 1
+    } // end if fInit
+  else
+    {
+      AliError("Not properly initialized");
+    }
+
+  return status;
+}
+
+
+//__________________________________________________________________________
+Bool_t AliITSPreprocessorSPD::FindNoisyChannelsInModuleAlgo0(UInt_t module)
+{
+  // Locate the noisy channels in a module (optimized for real data)
+  //
+  // For each channel in these histograms, the algorithm checks the average
+  // filling of the neighboring 3, 5 or 8 channels (depending on the location
+  // of the channel in question; corner, border or inside), or compares with the
+  // RMS of the neighbors. If the average is "much" lower, the channel will be
+  // considered to be noisy. The default noisy-to-normal fraction is stored in the
+  // fThresholdRatio varible. It can be set with the SetThresholdRatio method.
+  // The channel also has to have fired more than a certain minimum, fThreshold.
+  // It can be set with the SetThreshold method.
+  //
+  // To avoid difficulties with noisy channels that occur in pairs, the
+  // neighboring channel with largest number of fillings will be removed from
+  // the average calculation.
+  //
+  // NOTE: Since this method modifies the fBadChannelsObjArray and fBadChannelsIndexArray
+  //       it is essential to initialize the fIndex counter before calling this module
+  //       the first time. The bad channel data does not have to be ordered per module
+  //       in the fBadChannelsObjArray, but the indices of where the data of a certain module
+  //       starts has to be correct. A wrong fIndex can lead to segmentation violation
+  //
+  // Input : module number, filled digit histograms
+  // Output: TObjArray (fBadChannelsObjArray) with all identified noisy channels,
+  //         Int_t[] (fBadChannelsIndexArray) with fBadChannelsObjArray module indices,
+  //         number of noisy channels in this module (global variable fNumberOfBadChannels[module])
+  // Return: kTRUE if there are noisy channels in this module
+
+  // Store the index number for this module
+  fBadChannelsIndexArray[module] = fIndex++;
+
+  UInt_t xBin, numberOfXBins;
+  UInt_t yBin, numberOfYBins;
+  UInt_t neighborXBin;
+  UInt_t neighborYBin;
+  UInt_t numberOfNeighboringBins;
+  Float_t binContent;
+  Float_t sumBinContent;
+  Float_t neighborBinContent;
+  Float_t maxBinContent;
+  Float_t averageBinContent;
+  Float_t ratio;
+
+  numberOfXBins = (UInt_t)((TH2F*)(*fDigitsHistogram)[module])->GetNbinsX();
+  numberOfYBins = (UInt_t)((TH2F*)(*fDigitsHistogram)[module])->GetNbinsY();
+
+  // Loop over all bins in this histogram
+  for (xBin = 1; xBin <= numberOfXBins; xBin++)
+    for (yBin = 1; yBin <= numberOfYBins; yBin++)
+      {
+       numberOfNeighboringBins = 0;
+       averageBinContent = 0.;
+       sumBinContent = 0.;
+       binContent = ((TH2F*)(*fDigitsHistogram)[module])->GetBinContent(xBin, yBin);
+       maxBinContent = 0.;
+
+       // Calculate the average pixel level on the surrounding pixels
+       for (neighborXBin = xBin - 1; neighborXBin <= xBin + 1; neighborXBin++)
+         for (neighborYBin = yBin - 1; neighborYBin <= yBin + 1; neighborYBin++)
+           {
+             if ( !((neighborXBin == xBin) && (neighborYBin == yBin)) )
+               {
+                 // Only update the number of neighboring bins when we are not on the border
+                 if ((neighborXBin > 0) && (neighborXBin <= numberOfXBins+1) &&
+                     (neighborYBin > 0) && (neighborYBin <= numberOfYBins+1))
+                   {
+                     neighborBinContent =
+                       ((TH2F*)(*fDigitsHistogram)[module])->GetBinContent(neighborXBin, neighborYBin);
+
+                     if (fSelectedAlgorithm == kOptimizedForRealDataRMS)
+                       {
+                         // RMS
+                         sumBinContent += neighborBinContent*neighborBinContent;
+                       }
+                     else
+                       {
+                         // Geometrical mean
+                         sumBinContent += neighborBinContent;
+                       }
+
+                     if (neighborBinContent > maxBinContent) maxBinContent = neighborBinContent;
+
+                     numberOfNeighboringBins++;
+                   }
+               }
+           }
+
+       // Calculate the average. Remove the largest neighboring bin
+       // (Correction for potential clusters of noisy channels)
+       if (fSelectedAlgorithm == kOptimizedForRealDataRMS)
+         {
+           // Square the max bin content before removing it from the average calculation
+           maxBinContent *= maxBinContent;
+
+           // RMS
+           averageBinContent = sqrt((sumBinContent - maxBinContent)/(Float_t)(numberOfNeighboringBins - 1));
+         }
+       else
+         {
+           // Geometrical mean
+           averageBinContent = (sumBinContent - maxBinContent)/(Float_t)(numberOfNeighboringBins - 1);
+         }
+
+       // Store this channel/bin if outside accepted limits
+       // The threshold ratio is the threshold for the current bin content divided by the
+       // average neighboring bin contents. The threshold bin content is the minimum number of
+       // times a channel has to have fired to be called noisy
+       ratio = (averageBinContent > 0) ? binContent/averageBinContent : 0.;
+       if ( ((ratio >= fThresholdRatio) || (ratio == 0.)) && (binContent >= fThreshold) )
+         {
+           // Store the noisy channel in the array
+           // The channel object will be deleted in the destructor using the TObjArray Delete() method
+           // (The array will assume ownership of the channel object)
+           AliITSChannelSPD *channel = new AliITSChannelSPD((Int_t)(xBin - 1), (Int_t)(yBin - 1));
+
+           // Store the noisy channel in the array
+           fBadChannelsObjArray->Add(channel);
+
+           // Keep track of the number of bad channels in this module
+           fNumberOfBadChannels[module]++;
+           fIndex += 2;
+
+           // Keep track of the highest module number
+           if (module > fHighestModuleNumber) fHighestModuleNumber = module;
+
+           AliInfo(Form("New noisy pixel in (m,c,r) = (%d,%d,%d)", module, xBin - 1, yBin - 1));
+           AliInfo(Form("- Noisy pixel fired %d times, average neighborhood: %f",(Int_t)binContent,averageBinContent));
+         }
+      } // end bin loop
+
+  return (fNumberOfBadChannels[module] > 0);
+}
+
+
+//__________________________________________________________________________
+Bool_t AliITSPreprocessorSPD::FindNoisyChannelsInModuleAlgo1(UInt_t module)
+{
+  // Locate the noisy channels in a module (optimized for calibration data)
+  //
+  // This algorithm locates noisy channels by assuming original data was taken
+  // in calibration mode. This should be done without beam and will thus only
+  // contain data corresponding to background and noisy channels. The latter
+  // should be clearly visible in this data so this algorithm simply assumes
+  // that all histogram bins that are filled more than fThreshold times are
+  // noisy.
+  //
+  // NOTE: Since this method modifies the fBadChannelsObjArray and fBadChannelsIndexArray
+  //       it is essential to initialize the fIndex counter before calling this module
+  //       the first time. The bad channel data does not have to be ordered per module
+  //       in the fBadChannelsObjArray, but the indices of where the data of a certain module
+  //       starts has to be correct. A wrong fIndex can lead to segmentation violation
+  //
+  // Input : module number, filled digit histograms
+  // Output: TObjArray (fBadChannelsObjArray) with all identified noisy channels,
+  //         Int_t[] (fBadChannelsIndexArray) with fBadChannelsObjArray module indices,
+  //         number of noisy channels in this module (global variable fNumberOfBadChannels[module])
+  // Return: kTRUE if there are noisy channels in this module
+
+  // Store the index number for this module
+  fBadChannelsIndexArray[module] = fIndex++;
+
+  UInt_t xBin, numberOfXBins;
+  UInt_t yBin, numberOfYBins;
+  Float_t binContent;
+
+  numberOfXBins = ((TH2F*)(*fDigitsHistogram)[module])->GetNbinsX();
+  numberOfYBins = ((TH2F*)(*fDigitsHistogram)[module])->GetNbinsY();
+
+  // Loop over all bins in this histogram
+  for (xBin = 1; xBin <= numberOfXBins; xBin++)
+    for (yBin = 1; yBin <= numberOfYBins; yBin++)
+      {
+       binContent = ((TH2F*)(*fDigitsHistogram)[module])->GetBinContent(xBin, yBin);
+
+       // Store this channel/bin if outside accepted limits
+       // The threshold bin content is the minimum number of times a channel has to have
+       // fired to be called noisy
+       if (binContent >= fThreshold)
+         {
+           // Store the noisy channel in the array
+           // The channel object will be deleted in the destructor using the TObjArray Delete() method
+           // (The array will assume ownership of the channel object)
+           AliITSChannelSPD *channel = new AliITSChannelSPD((Int_t)(xBin - 1), (Int_t)(yBin - 1));
+
+           // Store the noisy channel in the array
+           fBadChannelsObjArray->Add(channel);
+
+           // Keep track of the number of bad channels in this module
+           fNumberOfBadChannels[module]++;
+           fIndex += 2;
+
+           // Keep track of the highest module number
+           if (module > fHighestModuleNumber) fHighestModuleNumber = module;
+
+           AliInfo(Form("New noisy pixel in (m,c,r) = (%d,%d,%d)", module, xBin - 1, yBin - 1));
+           AliInfo(Form("- Noisy pixel fired %d times",(Int_t)binContent));
+         }
+      } // end bin loop
+
+  return (fNumberOfBadChannels[module] > 0);
+}
+
+
+//__________________________________________________________________________
+void AliITSPreprocessorSPD::PrintChannels(void)
+{
+  // Print all found bad channels to stdout
+  //
+  // Input : fBadChannelsObjArray
+  // Output: (dump to stdout)
+  // Return: (void)
+
+  Int_t i = 0;
+  Int_t j = 0;
+  AliITSChannelSPD *channel = 0;
+
+  // Print the bad channels stores in the array
+  AliInfo("\nModule #\tColumn #\tRow #\n------------------------------------------------");
+  for (UInt_t module = 0; module < fNumberOfModules; module++)
+    {
+      j = 0;
+      while (j < fNumberOfBadChannels[module])
+       {
+         channel = (AliITSChannelSPD *) fBadChannelsObjArray->At(i++);
+         std::cout << module << "\t\t" << channel->GetColumn() << "\t\t" << channel->GetRow() << std::endl;
+
+         // Go to next bad channel
+         j++;
+       }
+    }
+
+  AliInfo(Form("%d bad channels were found", fBadChannelsObjArray->GetEntries()));
+}
+
+
+//__________________________________________________________________________
+void AliITSPreprocessorSPD::MarkNoisyChannels(void)
+{
+  // WARNING: THIS METHOD DOESN'T WORK!!!
+  //
+  // Mark all identified noisy channels
+  //
+  // Input : List of noisy channels, original digits tree
+  // Output: New digits tree containing SPD digits marked when noisy
+  // Return: (void)
+  //
+  // The original digits tree (digitsTree) is cloned except for the SPD branch (ITSDigitSPD).
+  // This branch is then redefined for each event and will contain all the original
+  // information. All known noisy channels will be marked by using the TObject status bits
+  // according to the following scheme. Dead channels are included for completeness. Note
+  // that a dead channel will NEVER show up among digits..
+  //
+  // Interpretation of digit status bits (LSB):
+  // Dead channel   Noisy channel   |  Integer
+  // -----------------------------------------
+  //      0               0         |     0
+  //      0               1         |     1
+  //      1               0         |     2
+  //
+  // meaning e.g. that a channel that is noisy will have the first bit set in its status bits
+
+  // Do not continue unless we are processing DAQ data
+  if (!fVMEMode)
+    {
+      AliInfo("Marking bad channels");
+
+      // Create the storage container that will be used to access the bad channels
+      if (!fBadChannelsContainer)
+       {
+         // Add the bad channels array to the storage container
+         // (ownership is passed to the AliRunDataStorage object)
+         fBadChannelsContainer = new AliITSBadChannelsSPD();
+
+         // Convert the bad channels from TObjArray to Int_t[]
+         AliITSPreprocessorSPD::ConvertObjToIntArray();
+
+         // Store the arrays in the bad channels container object
+         const Int_t kBadChannelsArraySize =
+           2*fBadChannelsObjArray->GetEntries() + fNumberOfModules;
+         fBadChannelsContainer->Put(fBadChannelsIntArray, kBadChannelsArraySize,
+                                    fBadChannelsIndexArray, fNumberOfModules);
+       }
+
+      // Create the bad channels helper object
+      // (will be used to find a bad channel within a TObjArray)
+      AliITSBadChannelsAuxSPD *aux = new AliITSBadChannelsAuxSPD();
+
+      AliITSdigitSPD *digitSPD = 0;
+      UInt_t numberOfDigits;
+      Int_t newDigit[3];
+      Bool_t mark = kFALSE;
+
+      TBranch *digitsBranch = 0;
+      TTree *digitsTree;
+
+      // Create an empty SPD digit array
+      TObjArray *digitsArraySPD = new TObjArray();
+
+      // Get the digits in update mode (we want to modify them if there are noisy channels)
+      fITSLoader->UnloadDigits();
+      fITSLoader->LoadDigits("update");
+
+      // Get the number of events
+      UInt_t numberOfEvents = (fRunLoader->TreeE()) ? static_cast<UInt_t>(fRunLoader->TreeE()->GetEntries()) : 0;
+
+      // Loop over all events
+      for (UInt_t event = 0; event < numberOfEvents; event++)
+       {
+         if (event%100 == 0) AliInfo(Form("Event #%d", event));
+
+         // Get the current event
+         fRunLoader->GetEvent(event);
+
+         // Get the ITS digits tree
+         digitsTree = fITSLoader->TreeD();
+
+         // Get SPD branch that will contain all digits with marked noisy channels
+         digitsBranch = digitsTree->GetBranch("ITSDigitsSPD");
+         digitsBranch->SetAddress(&digitsArraySPD);
+
+         // Get the stored number of modules
+         UInt_t numberOfModules = (Int_t)digitsTree->GetEntries();
+         TObjArray **newDigitsArraySPD = new TObjArray*[numberOfModules];
+
+         Int_t *digitNumber = new Int_t[numberOfModules];
+         for (UInt_t m = 0; m < numberOfModules; m++)
+           {
+             newDigitsArraySPD[m] = new TObjArray();
+             digitNumber[m] = 0;
+           }
+
+         AliInfo(Form("ent = %d", (Int_t)digitsTree->GetEntries()));
+
+         // Reset the SPD digit arrays to make sure they are empty
+         digitsArraySPD->Clear();
+
+         // Get the SPD digits branch from the original digits tree and set the address
+         digitsBranch = digitsTree->GetBranch("ITSDigitsSPD");
+         digitsBranch->SetAddress(&digitsArraySPD);
+
+         // Loop over all modules
+         for (UInt_t module = 0; module < fNumberOfModules; module++)
+           {
+             // Get event data for current module
+             digitsTree->GetEvent(module);
+
+             // Get the hits in the current module
+             TObjArray *moduleObjArray = fBadChannelsContainer->CreateModuleObjArray(module);
+
+             // Get the number of entries
+             numberOfDigits = digitsArraySPD->GetEntries();
+
+             // Loop over all digits and all channels
+             for (UInt_t digit = 0; digit < numberOfDigits; digit++)
+               {
+                 // Get the current digit
+                 digitSPD = (AliITSdigitSPD*) digitsArraySPD->At(digit);
+                 newDigit[0] = digitSPD->GetCoord1(); // row
+                 newDigit[1] = digitSPD->GetCoord2(); // column
+                 newDigit[2] = digitSPD->GetSignal(); // signal
+
+                 // Check if this channel is noisy
+                 // (Compare with all stored channels in the bad channels array)
+                 if (aux->Find(digitSPD, moduleObjArray))
+                   {
+                     // Set the mark flag and break the loop
+                     mark = kTRUE;
+                   }
+
+                 // Store this digit in the SPD digits array using a placement new operation
+                 new ((*newDigitsArraySPD[module])[digitNumber[module]]) AliITSdigitSPD(newDigit);
+
+                 // Mark it if noisy and store in the noisy channel array
+                 if (mark)
+                   {
+                     // Store this digit in the marked SPD digits array using a placement new operation
+                     //new ((*badChannels[m])[numberOfBadChannels[m]]) AliITSChannelSPD(newBadChannel);
+                     //new ((*newDigitsArraySPD[module])[digitNumber[module]]) AliITSdigitSPD(newDigit);
+
+                     // Mark the original channel as noisy
+                     ((*newDigitsArraySPD[module])[digitNumber[module]])->SetBit(kNoisyChannel);
+
+                     mark = kFALSE;
+                   }
+
+                 digitNumber[module]++;
+
+               } // end digit loop
+
+             // Cleanup
+             delete moduleObjArray;
+             moduleObjArray = 0;
+
+           } // end module loop
+
+         digitsBranch->Reset();
+         digitsBranch->ResetAddress();
+
+         // Cleanup
+         delete digitsArraySPD;
+         digitsArraySPD = 0;
+         digitsTree->Reset();
+
+         // WHY THIS RANGE?????????????????????????????????????????????????????????????????????
+         for (UInt_t n = 0; n < event; n++)
+           {
+             digitsTree->SetBranchAddress("ITSDigitsSPD", &newDigitsArraySPD[n]);
+             digitsTree->Fill();
+           }
+
+         digitsTree->AutoSave();
+
+         // Cleanup
+         for (UInt_t n = 0; n < event; n++)
+           {
+             delete newDigitsArraySPD[n];
+           }
+         delete [] newDigitsArraySPD;
+         newDigitsArraySPD = 0;
+         delete [] digitNumber;
+         digitNumber = 0;
+         delete digitsTree;
+         digitsTree = 0;
+
+       } // end loop over all events
+
+      // Unload the digits
+      fITSLoader->UnloadDigits();
+
+      // Cleanup
+      delete aux;
+      aux = 0;
+    }
+}
+
+
+
+//__________________________________________________________________________
+Bool_t AliITSPreprocessorSPD::Store(AliCDBId &id, AliCDBMetaData *md)
+{
+  // Store the bad channels object in the calibration database
+  // (See the corresponding run macro for further explanations)
+  //
+  // Input : fBadChannelsObjArray (now containing all found bad channels), object meta data
+  // Output: Database file containing the bad channels
+  // Return: kTRUE if successful
+
+  Bool_t status = kFALSE;
+
+  AliInfo("Storing bad channels");
+
+  // Add the bad channels array to the storage container
+  // (ownership is passed to the AliRunDataStorage object)
+  fBadChannelsContainer = new AliITSBadChannelsSPD();
+
+  // Convert the bad channels from TObjArray to Int_t[]
+  AliITSPreprocessorSPD::ConvertObjToIntArray();
+
+  // Store the arrays in the bad channels container object
+  const Int_t kBadChannelsArraySize =
+    2*fBadChannelsObjArray->GetEntries() + fNumberOfModules;
+  fBadChannelsContainer->Put(fBadChannelsIntArray, kBadChannelsArraySize,
+                            fBadChannelsIndexArray, fNumberOfModules);
+
+  // Store the container
+ if(!AliCDBManager::Instance()->IsDefaultStorageSet()) {
+       AliError("No storage set!");
+       return status;
+  }
+  
+  if (AliCDBManager::Instance()->GetDefaultStorage()->Put(fBadChannelsContainer, id, md))
+    {
+      AliInfo("Bad channels object stored in database");
+      status = kTRUE;
+    }
+  else
+    {
+      AliError("Failed to store object in database");
+    }
+
+  return status;
+}
+
+
+//__________________________________________________________________________
+void AliITSPreprocessorSPD::ConvertObjToIntArray(void)
+{
+  // Convert the bad channel TObjArray to an Int_t array
+  //
+  // Input : fBadChannelsObjArray (now containing all found bad channels)
+  // Output: fBadChannelsIntArray
+  // Return: (void)
+  //
+  // Data encoding:
+  //                The TObjArray of this class (fBadChannelsObjArray) is converted to a sequential
+  //                Int_t array (fBadChannelsIntArray) in this method. For each module, the first
+  //                stored number is the number of bad channels in the current module. This is
+  //                followed by all the columns and rows of the bad channels:
+  //
+  //                badChannelsArray =
+  //                | N(m) | col0 | row0 | .. | colN(m) | N(m+1) | col0 | row0 | ...
+  //                .   .......... module m .........   .   .... module m+1 ......
+  //
+  //                The bad channels index array (fBadChannelsIndexArray) contains the indices of
+  //                the badChannelsArray, i.e. where the bad channels in certain module starts:
+  //
+  //                fBadChannelsObjArray =
+  //                | i0 | i1 | .. | iM | (where M = the number of SPD modules)
+  //
+  //                e.g. i1 corresponds to the index of the badChannelsArray where N(1) is stored,
+  //                i.e. the number of bad channels for module 1
+
+  const Int_t kBadChannelsArraySize =
+    2*fBadChannelsObjArray->GetEntries() + fNumberOfModules;
+  fBadChannelsIntArray = new Int_t[kBadChannelsArraySize]; // Will be deleted in dtor
+  AliITSChannelSPD *channel = 0;
+  Int_t i = 0;
+  Int_t j = 0;
+  Int_t k = 0;
+
+  // Loop over all modules
+  for (UInt_t module = 0; module < fNumberOfModules; module++)
+    {
+      // Encode the number of bad channels of the current module
+      fBadChannelsIntArray[k++] = fNumberOfBadChannels[module];
+
+      // The columns and rows of the fBadChannelsObjArray will be stored sequentially
+      // in the Int_t array
+      j = 0;
+      while (j < fNumberOfBadChannels[module])
+       {
+         channel = (AliITSChannelSPD *) fBadChannelsObjArray->At(i++);
+         fBadChannelsIntArray[k++] = channel->GetColumn();
+         fBadChannelsIntArray[k++] = channel->GetRow();
+
+         // Go to next bad channel
+         j++;
+       }
+    }
+}
diff --git a/ITS/AliITSPreprocessorSPD.h b/ITS/AliITSPreprocessorSPD.h
new file mode 100644 (file)
index 0000000..4701b6e
--- /dev/null
@@ -0,0 +1,155 @@
+#ifndef ALIITSPREPROCESSORSPD_H
+#define ALIITSPREPROCESSORSPD_H
+
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+ * See cxx source for full Copyright notice                               */
+
+/* $Id$ */
+
+///////////////////////////////////////////////////////////////////////////
+// AliITSPreprocessorSPD declaration by P. Nilsson 2005
+// AUTHOR/CONTACT: Paul.Nilsson@cern.ch
+//
+// The purpose of this class is to provide algorithms for identification
+// of "bad channels" such as dead channels and noisy channels in the SPD
+///////////////////////////////////////////////////////////////////////////
+
+// #include "AliITSGeometry.h"
+#include <TTask.h>
+#include <TString.h>
+#include <TTree.h>
+#include <TBranch.h>
+#include <TH2F.h>
+#include <TClonesArray.h>
+#include <TObjArray.h>
+#include <TFile.h>
+#include <TCollection.h>
+#include <TKey.h>
+#include <TDirectory.h>
+
+#include "AliRun.h"
+#include "AliRunLoader.h"
+#include "AliITSLoader.h"
+#include "AliITSdigitSPD.h"
+#include "AliITSBadChannelsSPD.h"
+#include "AliITSBadChannelsAuxSPD.h"
+#include "AliITSChannelSPD.h"
+#include "AliCDBId.h"
+#include "AliCDBManager.h"
+#include "AliCDBStorage.h"
+#include "AliCDBMetaData.h"
+#include "AliCDBLocal.h"
+#include "AliLog.h"
+
+class AliITSPreprocessorSPD : public TTask {
+
+ public:
+
+  AliITSPreprocessorSPD(void);                                         // Default constructor
+  AliITSPreprocessorSPD(const char *fileName, const char *mode,        // Standard constructor
+                       const char *fileNameg, const Int_t maxNumberOfEvents);
+  AliITSPreprocessorSPD(const AliITSPreprocessorSPD &prep);            // Default copy constructor
+  AliITSPreprocessorSPD& operator=(const AliITSPreprocessorSPD &prep); // Assignment operator
+  virtual ~AliITSPreprocessorSPD(void);                                // Virtual destructor
+
+  void Init(void);                                      // Initialization of the SPD preprocessor
+  Bool_t Open(const char *fileName, const char *mode,   // Open the input file (of either "daq" or "vme" type)
+             const char *fileNameg);                   // and the galice file
+  Bool_t FindDeadChannels(void);                        // Find dead channels
+  Bool_t FindDeadChannelsInModule(UInt_t module);       // Find dead channels in a module
+  Bool_t FindNoisyChannels(void);                       // Locate the noisy channels among the digits
+  Bool_t FindNoisyChannelsInModuleAlgo0(UInt_t module); // Locate the noisy channels in a module (for real data)
+  Bool_t FindNoisyChannelsInModuleAlgo1(UInt_t module); // Locate the noisy channels in a module (for calibration data)
+  Bool_t Store(AliCDBId &Id, AliCDBMetaData *md);               // Write the final object to the calibration database
+                                                        // Returns kTRUE if successful
+  Bool_t GetVMEHistograms(TFile *vmeFile);              // Get pre-filled digit histograms from input VME file
+  void MarkNoisyChannels(void);                         // Mark all found noisy channels among the digits
+  void PrintChannels(void);                             // Print all found bad channels to stdout
+
+  // Getters and setters
+  void SetMaximumNumberOfEvents(UInt_t n)      // Set the maximum number of events
+    { fMaximumNumberOfEvents = n; };           // (filling of noisy channel histograms will stop)
+  UInt_t GetMaximumNumberOfEvents(void) const  // Get the maximum number of events
+    { return fMaximumNumberOfEvents; };
+
+  void SetGeometryMode(UInt_t mode);           // Set the geometry mode
+  UInt_t GetGeometryMode(void) const           // Get the geometry mode
+    { return fGeometryMode; };                 // (kALICEGeometry is default, alt is kTestBeamGeometry)
+
+  void SetThreshold(UInt_t t)                  // Set the noisy channel threshold
+    { fThreshold = t; };                       // (A channel has to fire mode times than this value to be noisy)
+  void SetThreshold(Double_t t)                // Set the noisy channel threshold (overloaded)
+    { fThreshold = (UInt_t)t; };               // (A channel has to fire mode times than this value to be noisy)
+  UInt_t GetThreshold(void) const              // Get the noisy channel threshold
+    { return fThreshold; };                    // (A channel has to fire mode times than this value to be noisy)
+
+  void SetThresholdRatio(Double_t r)           // Set the noisy channel threshold ratio
+    { fThresholdRatio = r; };                  // (threshold to average neighboring channels)
+  Double_t GetThresholdRatio(void) const       // Get the noisy channel threshold ratio
+    { return fThresholdRatio; };               // (threshold to average neighboring channels)
+
+  void SelectAlgorithm(UInt_t a)               // Select algorithm for read data or calibration data
+    { fSelectedAlgorithm = a; };               // (either kOptimizedForRealData or kOptimizedForCalibrationData)
+  UInt_t GetSelectedAlgorithm(void) const      // Get the selected algorithm for read data or calibration data
+    { return fSelectedAlgorithm; };            // (either kOptimizedForRealData or kOptimizedForCalibrationData)
+
+  // Geometry mode constants
+  enum { kTestBeamGeometry, kALICEGeometry };
+
+  // Algorithm constants
+  enum { kOptimizedForRealData, kOptimizedForRealDataRMS, kOptimizedForCalibrationData };
+
+  // Noisy/dead pixel encoding (0001b, 0010b) used with the digit TObject statusbit
+  enum { kNoisyChannel = 1, kDeadChannel = 2 };
+
+  // Replace later with reading from geometry object
+  // During the 2004 test beam, 4 modules were used but had internal hardware addresses of 0,1,4,5
+  enum { kNumberOfTestBeamSPDModules = 6, kNumberOfSPDModules = 240 };
+  enum { kNumberOfColumns = 160, kNumberOfRows = 256 }; // In one module/ladder
+  enum { kNumberOfChannels = 40960 }; // 5*8192
+
+ private:
+
+  void ConvertObjToIntArray(void);             // Convert the bad channel TObjArray to an Int_t array
+  void SetFakeNoisyChannel(Int_t module, Int_t column, Int_t row);
+                                               // For testing purposes it is possible to add fake noisy channels
+                                               // to the noisy pixel tree. These will be added to the hit histograms
+  void CreateHistograms(void);                 // Create digit histograms
+  void CreateNoisyChannelsTree(void);          // Create noisy channels tree
+  TClonesArray *CreateDigitsArray(void) const; // Create the SPD digits array
+  Bool_t CreateGeometryObj(void);              // Creation of geometry object
+  Bool_t GetITSDigits(const char *fileName);   // Get the ITS digits
+  Bool_t GetgAlice(void);                      // Get the gAlice object
+  Bool_t FillHistograms(void);                 // Fill the histograms with digits
+  void SetNumberOfModules(UInt_t n)            // Set the number of modules
+    { fNumberOfModules = n; };
+  UInt_t GetNumberOfModules(void) const        // Get the number of modules
+    { return fNumberOfModules; };
+
+  // AliITSGeometry *fGeometryObj;             //! Pointer to the geometry object
+  AliITSLoader *fITSLoader;                    //! ITS loader
+  AliRunLoader *fRunLoader;                    //! Run Loader
+  Double_t fThresholdRatio;                    //! Noisy channel ratio
+  UInt_t fThreshold;                           //! Noisy channel threshold
+  UInt_t fMaximumNumberOfEvents;               //! Maximum number of events per histograms
+  UInt_t fNumberOfModules;                     //! Number of modules, used for digit histograms
+  UInt_t fHighestModuleNumber;                 //! The highest module number with found bad channels
+  UInt_t fNumberOfColumns;                     //! Number of SPD columns
+  UInt_t fNumberOfRows;                        //! Number of SPD rows
+  UInt_t fSelectedAlgorithm;                   //! Removal algorithm selection, either set to
+                                               //! kOptimizedForRealData or kOptimizedForCalibrationData
+  UInt_t fGeometryMode;                        //! Geometry mode (kALICEGeometry is default, alt is kTestBeamGeometry)
+  Int_t *fNumberOfBadChannels;                 //! Total number of bad channels counter
+  Int_t fIndex;                                //! Bad channels array index to be stored in fBadChannelsIndexArray
+  Bool_t fInit;                                //! Initialization boolean (true when histograms are created)
+  Bool_t fVMEMode;                             //! Initialization boolean (true when using a VME file as input)
+  TObjArray *fDigitsHistogram;                 //! Digits histogram array
+  TObjArray *fBadChannelsObjArray;             //! Bad channels array (size unknown initially)
+  Int_t *fBadChannelsIntArray;                 //! Bad channels array
+  Int_t *fBadChannelsIndexArray;               //! Indices for the bad channels
+  AliITSBadChannelsSPD *fBadChannelsContainer; //! Container object for database storage
+
+  ClassDef(AliITSPreprocessorSPD,1)
+};
+
+#endif
index 2ad9780..22fc431 100644 (file)
 #pragma link C++ class AliITSRawStreamSSD+;
 #pragma link C++ class AliITSRawStreamSSDv1+;
 #pragma link C++ class AliITSEventHeader+;
+// SPD preprocessing
+#pragma link C++ class AliITSBadChannelsAuxSPD+;
+#pragma link C++ class AliITSBadChannelsSPD+;
+#pragma link C++ class AliITSChannelSPD+;
+#pragma link C++ class AliITSPreprocessorSPD+;
 
 
 #endif
index b7a284b..7b9ca31 100644 (file)
@@ -33,7 +33,11 @@ SRCS =       AliITSgeom.cxx \
                AliITSRawStreamSPD.cxx \
                AliITSEventHeader.cxx \
                AliITSRawStreamSSDv1.cxx \
-               AliITSRawData.cxx 
+               AliITSRawData.cxx  \
+               AliITSBadChannelsAuxSPD.cxx \
+               AliITSBadChannelsSPD.cxx  \
+               AliITSChannelSPD.cxx  \
+               AliITSPreprocessorSPD.cxx  \
 
 HDRS:=  $(SRCS:.cxx=.h)