]> git.uio.no Git - u/mrichter/AliRoot.git/blobdiff - FMD/AliFMDRawWriter.cxx
ALIROOT-5486 Add method to get trigger deviation sign
[u/mrichter/AliRoot.git] / FMD / AliFMDRawWriter.cxx
index 603a44abbc8125505903704d02a02a3e4a381491..1bd500224c4ee535afd79a6d0cc0f4491125f277 100644 (file)
 // ALTRO format.  See the Exec member function for more information on
 // that format.  
 //
-#include <AliLog.h>            // ALILOG_H
+// #include <AliLog.h>         // ALILOG_H
+#include "AliFMDDebug.h"        // Better debug macros
 #include <AliLoader.h>         // ALILOADER_H
-#include <AliAltroBuffer.h>     // ALIALTROBUFFER_H
+#include <AliAltroBufferV3.h>   // ALIALTROBUFFER_H
 #include "AliFMD.h"            // ALIFMD_H
 #include "AliFMDParameters.h"  // ALIFMDPARAMETERS_H
 #include "AliFMDDigit.h"       // ALIFMDDIGIT_H
 #include "AliFMDAltroMapping.h" // ALIFMDALTROMAPPING_H
 // #include "AliFMDAltroIO.h"   // ALIFMDALTROWRITER_H
 #include <TArrayI.h>           // ROOT_TArrayI
+#include <TArrayF.h>           // ROOT_TArrayI
+#include <TArrayC.h>           // ROOT_TArrayI
 #include <TClonesArray.h>      // ROOT_TClonesArray
+#include <TTree.h>
 // #include <fstream>
+#include "AliDAQ.h"
 
 //____________________________________________________________________
 ClassImp(AliFMDRawWriter)
@@ -58,9 +63,13 @@ ClassImp(AliFMDRawWriter)
 //____________________________________________________________________
 AliFMDRawWriter::AliFMDRawWriter(AliFMD* fmd) 
   : TTask("FMDRawWriter", "Writer of Raw ADC values from the FMD"),
-    fFMD(fmd)
+    fFMD(fmd),
+    fSampleRate(0), 
+    fChannelsPerAltro(0), 
+    fThreshold(0)
 {
   // CTOR 
+  AliFMDDebug(5, ("Created AliFMDRawWriter object"));
 }
 
 
@@ -125,23 +134,25 @@ AliFMDRawWriter::Exec(Option_t*)
   // Note, that this method assumes that the digits are ordered. 
   // 
   AliLoader* loader = fFMD->GetLoader();
-  loader->LoadDigits();
+  loader->LoadDigits("READ");
   TTree* digitTree = loader->TreeD();
   if (!digitTree) {
-    Error("Digits2Raw", "no digit tree");
+    AliError("no digit tree");
     return;
   }
   
-  TClonesArray* digits = new TClonesArray("AliFMDDigit", 1000);
   fFMD->SetTreeAddress();
-  TBranch* digitBranch = digitTree->GetBranch(fFMD->GetName());
-  if (!digitBranch) {
-    Error("Digits2Raw", "no branch for %s", fFMD->GetName());
-    return;
-  }
-  digitBranch->SetAddress(&digits);
+  TClonesArray* digits = fFMD->Digits(); 
+  // new TClonesArray("AliFMDDigit", 1000);
+  // TBranch* digitBranch = digitTree->GetBranch(fFMD->GetName());
+  // if (!digitBranch) {
+  //   AliError(Form("no branch for %s", fFMD->GetName()));
+  //   return;
+  // }
+  // digitBranch->SetAddress(&digits);
   
   Int_t nEvents = Int_t(digitTree->GetEntries());
+  AliFMDDebug(5, ("Got a total of %5d events from tree", nEvents));
   for (Int_t event = 0; event < nEvents; event++) {
     fFMD->ResetDigits();
     digitTree->GetEvent(event);
@@ -150,118 +161,265 @@ AliFMDRawWriter::Exec(Option_t*)
     WriteDigits(digits);
   }
   loader->UnloadDigits();
+  //delete digits;
 }
 
 #if 1
 //____________________________________________________________________
-void
+Long_t
 AliFMDRawWriter::WriteDigits(TClonesArray* digits)
 {
   // WRite an array of digits to disk file 
   Int_t nDigits = digits->GetEntries();
-  if (nDigits < 1) return;
+  if (nDigits < 1) return 0;
+  AliFMDDebug(5, ("Got a total of %5d digits from tree", nDigits));
 
   AliFMDParameters* pars = AliFMDParameters::Instance();
   UShort_t threshold    = 0;
-  UInt_t   prevddl      = 0;
+  UShort_t factor       = 0;
+  UInt_t   prevddl      = 0xFFFF;
   UInt_t   prevaddr     = 0xFFF;
   // UShort_t prevStrip    = 0;
   
   // Which channel number in the ALTRO channel we're at 
   UShort_t nWords       = 0;
   UShort_t preSamples   = 0;
-  
-  // How many times the ALTRO Samples one VA1_ALICE channel 
-  Int_t sampleRate      = 1;
+  UShort_t sampleRate   = 0;
   
   // A buffer to hold 1 ALTRO channel - Normally, one ALTRO channel
   // holds 128 VA1_ALICE channels, sampled at a rate of `sampleRate' 
   TArrayI data(pars->GetChannelsPerAltro() * 8);
+  TArrayF peds(pars->GetChannelsPerAltro() * 8);
+  TArrayF noise(pars->GetChannelsPerAltro() * 8);
 
   // The Altro buffer 
-  AliAltroBuffer* altro = 0;
-    
+  AliAltroBufferV3* altro = 0;
+  
+  Int_t  totalWords = 0;
+  Int_t  nCounts    = 0;
+  Long_t nBits      = 0;
+
   // Loop over the digits in the event.  Note, that we assume the
   // the digits are in order in the branch.   If they were not, we'd
   // have to cache all channels before we could write the data to
   // the ALTRO buffer, or we'd have to set up a map of the digits. 
+  UShort_t oldDet = 1000;
   for (Int_t i = 0; i < nDigits; i++) {
     // Get the digit
     AliFMDDigit* digit = static_cast<AliFMDDigit*>(digits->At(i));
-
     UShort_t det    = digit->Detector();
     Char_t   ring   = digit->Ring();
     UShort_t sector = digit->Sector();
     UShort_t strip  = digit->Strip();
-    UInt_t   ddl;
-    UInt_t   addr;  
-    threshold       = pars->GetZeroSuppression(det, ring, sector, strip);
-    if (!pars->Detector2Hardware(det, ring, sector, strip, ddl, addr)) {
-      AliError(Form("Failed to get hardware address for FMD%d%c[%2d,%3d]", 
-                   det, ring, sector, strip));
-      continue;
-    }
-    if (addr != prevaddr) {
-      // Flush a channel to output 
-      AliDebug(15, Form("Now hardware address 0x%x from FMD%d%c[%2d,%3d] "
-                       "(board 0x%x, chip 0x%x, channel 0x%x), flushing old "
-                       "channel at 0x%x with %d words", 
-                       addr, det, ring, sector, strip, 
-                       (addr >> 7), (addr >> 4) & 0x7, addr & 0xf, 
-                       prevaddr, nWords));
-      if (altro) altro->WriteChannel(prevaddr,nWords,data.fArray,threshold);
-      nWords   = preSamples;
-      prevaddr = addr;
-      for (size_t i = 0; i < nWords; i++) data[i] = digit->Count(0);
+    UShort_t ddl, addr, time;
+
+    AliFMDDebug(15, ("Processing digit # %5d FMD%d%c[%2d,%3d]", 
+                   i, det, ring, sector, strip));
+    threshold  = pars->GetZeroSuppression(det, ring, sector, strip);
+    sampleRate = pars->GetSampleRate(det, ring, sector, strip);
+    preSamples = pars->GetPreSamples(det, ring, sector, strip);
+    factor     = UShort_t(pars->GetPedestalFactor());
+
+    if (det != oldDet) {
+      AliFMDDebug(5, ("Got new detector: %d (was %d)", det, oldDet));
+      oldDet = det;      
     }
-    if (ddl != prevddl) {
-      AliDebug(15, Form("FMD: New DDL, was %d, now %d", prevddl, ddl));
-      // If an altro exists, delete the object, flushing the data to
-      // disk, and closing the file. 
-      if (altro) { 
-       // When the first argument is false, we write the real
-       // header. 
-       AliDebug(15, Form("Closing output"));
-       altro->Flush();
-       altro->WriteDataHeader(kFALSE, kFALSE);
-       delete altro;
-       altro = 0;
+    AliFMDDebug(15, ("Sample rate is %d", sampleRate));
+    
+    for (UShort_t j = 0; j < sampleRate; j++) { 
+      if (!pars->Detector2Hardware(det,ring,sector,strip,j,ddl,addr,time)){
+       AliError(Form("Failed to get hardware address for FMD%d%c[%2d,%3d]-%d", 
+                     det, ring, sector, strip, j));
+       continue;
       }
-      prevddl = ddl;
-      // Need to open a new DDL! 
-      TString filename(Form("%s_%d.ddl", fFMD->GetName(),  ddl));
-      AliDebug(15, Form("New altro buffer with DDL file %s", filename.Data()));
-      // Create a new altro buffer - a `1' as the second argument
-      // means `write mode' 
-      altro = new AliAltroBuffer(filename.Data());
-      altro->SetMapping(pars->GetAltroMap());      
-      // Write a dummy (first argument is true) header to the DDL
-      // file - later on, when we close the file, we write the real
-      // header
-      altro->WriteDataHeader(kTRUE, kFALSE);
-    }
     
-    // Store the counts of the ADC in the channel buffer 
-    sampleRate = pars->GetSampleRate(det, ring, sector, strip);
-    for (int s = 0; s < sampleRate; s++) {
-      data[nWords] = digit->Count(s);
+      AliFMDDebug(10, ("FMD%d%c[%2d,%3d]-%d-> 0x%x/0x%x/%04d", 
+                      det, ring, sector, strip, j, ddl, addr, time));
+      if (addr != prevaddr) {
+       // Flush a channel to output 
+       AliFMDDebug(5, ("Now hardware address 0x%x from FMD%d%c[%2d,%3d]-%d"
+                        "(b: 0x%02x, a: 0x%01x, c: 0x%02x, t: %04d), "
+                        "flushing old channel at 0x%x with %d words", 
+                        addr, det, ring, sector, strip, j,
+                        (addr >> 7), (addr >> 4) & 0x7, addr & 0xf, 
+                        time, prevaddr, nWords));
+       totalWords += nWords;
+       ZeroSuppress(data.fArray, nWords, peds.fArray, noise.fArray, threshold);
+       if (altro) 
+         /*nBits+=*/altro->WriteChannel(prevaddr,nWords,data.fArray,threshold);
+       data.Reset(-1);
+       peds.Reset(0);
+       noise.Reset(0);
+       nWords   = 0;
+       prevaddr = addr;
+      }
+      if (ddl != prevddl) {
+       AliFMDDebug(10, ("FMD: New DDL, was %d, now %d", prevddl, ddl));
+       // If an altro exists, delete the object, flushing the data to
+       // disk, and closing the file. 
+       if (altro) { 
+         // When the first argument is false, we write the real
+         // header. 
+         AliFMDDebug(15, ("Closing output"));
+         WriteRCUTrailer(altro, prevddl, threshold > 0, factor, sampleRate); 
+    
+         delete altro;
+         altro = 0;
+       }
+       prevddl = ddl;
+       // Need to open a new DDL! 
+       TString filename(AliDAQ::DdlFileName(fFMD ? fFMD->GetName() : "FMD",  ddl));
+       AliFMDDebug(5, ("New altro buffer with DDL file %s", filename.Data()));
+       // Create a new altro buffer - a `1' as the second argument
+       // means `write mode' 
+       altro = new AliAltroBufferV3(filename.Data());
+       altro->SetMapping(pars->GetAltroMap());      
+       // Write a dummy (first argument is true) header to the DDL
+       // file - later on, when we close the file, we write the real
+       // header
+       altro->WriteDataHeader(kTRUE, kFALSE);
+      }
+    
+      // Get the pedestal value 
+      peds[time]  = pars->GetPedestal(det, ring, sector, strip);
+      noise[time] = pars->GetPedestalWidth(det, ring, sector, strip);
+
+      // Store the counts of the ADC in the channel buffer 
+      AliFMDDebug(15, ("Storing FMD%d%c[%02d,%03d]-%d in timebin %d (%d)",
+                     det, ring, sector, strip, j, time, preSamples));
+      data[time] = digit->Count(j);
       nWords++;
+      nCounts++;
+      if (time == preSamples) {
+       AliFMDDebug(15, ("Filling in %4d for %d presamples", 
+                       data[time], preSamples));
+       for (int k = 0; k < preSamples; k++) { 
+         peds[k]  = peds[time];
+         noise[k] = noise[time];
+         data[k]  = data[time];
+       }
+       nWords += preSamples;
+      }
     }
   }
   // Finally, we need to close the final ALTRO buffer if it wasn't
   // already 
   if (altro) {
-    if (nWords > 0) altro->WriteChannel(prevaddr,nWords,data.fArray,threshold);
-    altro->Flush();
-    altro->WriteDataHeader(kFALSE, kFALSE);
+    ZeroSuppress(data.fArray, nWords, peds.fArray, noise.fArray, threshold);
+    if (nWords > 0) 
+      /* nBits += */ altro->WriteChannel(prevaddr,nWords,data.fArray,threshold);
+    WriteRCUTrailer(altro, prevddl, threshold > 0, factor, sampleRate); 
     delete altro;
   }
+  AliFMDDebug(5, ("Wrote a total of %d words in %ld bytes for %d counts", 
+                 nWords, nBits / 8, nCounts));
+  return nBits;
 }
+//____________________________________________________________________
+void
+AliFMDRawWriter::WriteRCUTrailer(AliAltroBufferV3* altro,
+                                UInt_t ddl,
+                                Bool_t zs,
+                                UShort_t factor,
+                                UShort_t rate) const
+{
+  // Flush and write the data header
+  altro->Flush();
+  altro->WriteDataHeader(kFALSE, kFALSE);
+    
+  // Set parameters in RCU trailer. 
+  // Zero-suppression flag
+  altro->SetZeroSupp(zs); // bool
+  // WARNING: We store the noise factor in the 2nd baseline
+  // filters excluded post samples, since we'll never use that
+  // mode. 
+  // altro->SetNPostsamples(factor); // 
+  altro->SetNNonZSPostsamples(factor);
+  // WARNING: We store the sample rate in the number of pre-trigger
+  // samples, since we'll never use that mode.
+  altro->SetNPretriggerSamples(rate); // fSampleRate[ddl]
+  // Active front-end cars 
+  altro->SetActiveFECsA((ddl == 0 ? 0x1 : 0x3));
+  altro->SetActiveFECsB((ddl == 0 ? 0x1 : 0x3));
+
+  // Calculate number of samples 
+  altro->SetNSamplesPerCh(rate * 128);
+  AliDebug(5,Form("Writing RCU trailer @ DDL %d w/zs=%d, factor=%d, rate=%d",
+                 ddl, zs > 0, factor, rate));
+  altro->WriteRCUTrailer(ddl);
+}
+
+//____________________________________________________________________
+void
+AliFMDRawWriter::ZeroSuppress(Int_t*& data, Int_t nWords, 
+                             const Float_t* peds, 
+                             const Float_t* noise, UShort_t threshold) const
+{
+  // Simulate the ALTRO zero-suppression filter.  The data passed in
+  // the first array is modified, such that all suppressed channels
+  // are set to some value below threshold.  
+  // 
+  // If threshold == 0 zero suppression is considered disabled, and no
+  // action is taken. 
+  if (threshold <= 0) return;
+
+  // const Short_t width  = 3;
+  // If fPedSubtract is false, compare data-(ped+f*noise), if true
+  // always modify data by -(ped+f*noise), and force negative values
+  // to zero.
+  Bool_t   pedSubtract = AliFMDParameters::Instance()->IsZSPedSubtract();
+  UShort_t pre         = AliFMDParameters::Instance()->GetZSPreSamples();
+  UShort_t post        = AliFMDParameters::Instance()->GetZSPostSamples();
+  Float_t  factor      = AliFMDParameters::Instance()->GetPedestalFactor();
+  
+  TArrayC mask(nWords+1);
+  for (Short_t i = 0; i < nWords; i++) { 
+    Float_t            val     = data[i] - peds[i] - factor * noise[i];
+    if (val < 0.5)     val     = 0;
+    if (pedSubtract)   data[i] = Int_t(val) & 0x3FF;
+
+    mask[i] = (val > threshold ? 1 : 0);
+    AliFMDDebug(10, ("Comparing sample %d %d-%f-%f*%f=%f to %d -> %s", 
+                    i, data[i], peds[i], factor, noise[i], val, threshold, 
+                   (mask[i] ? "above" : "below")));
+  }
+  
+  for (Short_t i = 0; i < nWords; i++) { 
+    if (mask[i]) { // Signal above, so do nothing 
+      AliFMDDebug(10, ("Sample %d, above", i));
+      if (i < nWords-1 && !mask[i+1]) { 
+       // After a valid sample.  Increase the pointer to the next
+       // possible data, thereby skipping over the post-samples 
+       AliFMDDebug(10, ("At sample %d, next is below, skipping %d to %d", 
+                       i, post, i+post));
+       i += post;
+      }
+      continue;
+    }
+    
+    Short_t lookahead = TMath::Min(Short_t(nWords), Short_t(i+pre));
+    AliFMDDebug(10, ("Sample %d, below, look to %d", i, lookahead));
+    if (mask[lookahead] && pre > 0) { 
+      AliFMDDebug(10, ("Sample %d is a pre-sample to %d", i, lookahead));
+      // We're in a presample, so don't modify the data, and increase
+      // counter by the number of pre-samples 
+      i += pre-1;
+      continue;
+    }
+    
+    // This sample must be surpressed 
+    data[i] = threshold - 1;
+  }
+}
+
 #else
 //____________________________________________________________________
 void
 AliFMDRawWriter::WriteDigits(TClonesArray* digits)
 {
+  // 
+  // Write digits to file 
+  //
   Int_t nDigits = digits->GetEntries();
   if (nDigits < 1) return;
 
@@ -285,11 +443,11 @@ AliFMDRawWriter::WriteDigits(TClonesArray* digits)
                    det, ring, sector, strip));
       continue;
     }
-    AliDebug(40, Form("Got DDL=%d and address=%d from FMD%d%c[%2d,%3d]", 
+    AliFMDDebug(40, ("Got DDL=%d and address=%d from FMD%d%c[%2d,%3d]", 
                     thisDDL, thisHwaddr, det, ring, sector, strip));
     // Check if we're still in the same channel
     if (thisHwaddr != hwaddr) {
-      AliDebug(30, Form("Now hardware address 0x%x from FMD%d%c[%2d,%3d] "
+      AliFMDDebug(30, ("Now hardware address 0x%x from FMD%d%c[%2d,%3d] "
                       "(board 0x%x, chip 0x%x, channel 0x%x)",
                       thisHwaddr, det, ring, sector, strip, 
                       (thisHwaddr >> 7), (thisHwaddr >> 4) & 0x7, 
@@ -300,7 +458,7 @@ AliFMDRawWriter::WriteDigits(TClonesArray* digits)
     // Check if we're still in the same detector (DDL)
     if (ddl != thisDDL) {
       if (writer) {
-       AliDebug(1, Form("Closing altro writer %p", writer));
+       AliFMDDebug(1, ("Closing altro writer %p", writer));
        if ((ret = writer->Close()) < 0) {
          AliError(Form("Error: %s", writer->ErrorString(ret)));
          return;
@@ -316,10 +474,12 @@ AliFMDRawWriter::WriteDigits(TClonesArray* digits)
     // If we haven't got a writer (either because none were made so
     // far, or because we've switch DDL), make one. 
     if (!writer) {
-      AliDebug(1, Form("Opening new ALTRO writer w/file FMD_%d.ddl", ddl));
-      file   = new std::ofstream(Form("FMD_%d.ddl", ddl));
+      AliFMDDebug(1, ("Opening new ALTRO writer w/file %s", 
+                     AliDAQ::DdlFileName("FMD",ddl)));
+      file   = new std::ofstream(AliDAQ::DdlFileName("FMD",ddl));
       if (!file || !*file) {
-       AliFatal(Form("Failed to open file FMD_%d.ddl", ddl));
+       AliFatal(Form("Failed to open file %s", 
+                     AliDAQ::DdlFileName("FMD",ddl)));
        return;
       }
       writer  = new AliFMDAltroWriter(*file);
@@ -348,3 +508,4 @@ AliFMDRawWriter::WriteDigits(TClonesArray* digits)
 // 
 // EOF
 //
+