New RAW I/O. I rolled my own, because I wasn't happy with the old
authorcholm <cholm@f7af4fe6-9843-0410-8265-dc069ae4e863>
Tue, 21 Mar 2006 12:58:10 +0000 (12:58 +0000)
committercholm <cholm@f7af4fe6-9843-0410-8265-dc069ae4e863>
Tue, 21 Mar 2006 12:58:10 +0000 (12:58 +0000)
implementation, and things were missing.   The new implementation can
actually be used in any setting, and is much more flexible.

Some other fixes for various small things, and new macros to make
fake alignment data, etc.

31 files changed:
FMD/AliFMDAlignFaker.cxx
FMD/AliFMDAlignFaker.h
FMD/AliFMDAltroIO.cxx [new file with mode: 0644]
FMD/AliFMDAltroIO.h [new file with mode: 0644]
FMD/AliFMDAltroMapping.cxx
FMD/AliFMDAltroMapping.h
FMD/AliFMDCalibFaker.cxx
FMD/AliFMDDigitizer.cxx
FMD/AliFMDDisplay.cxx
FMD/AliFMDDisplay.h
FMD/AliFMDInput.cxx
FMD/AliFMDParameters.cxx
FMD/AliFMDParameters.h
FMD/AliFMDRawReader.cxx
FMD/AliFMDRawStream.cxx
FMD/AliFMDRawStream.h
FMD/AliFMDRawWriter.cxx
FMD/AliFMDRawWriter.h
FMD/AliFMDReconstructor.cxx
FMD/FMDbaseLinkDef.h
FMD/Reconstruct.C
FMD/Simulate.C
FMD/libFMDbase.pkg
FMD/scripts/ApplyAlignment.C [new file with mode: 0644]
FMD/scripts/Convert2Raw.C [new file with mode: 0644]
FMD/scripts/DisplayHits.C
FMD/scripts/MakeAlignment.C [new file with mode: 0644]
FMD/scripts/RawTest.C
FMD/scripts/ShowRaw.C
FMD/scripts/TestHWMap.C
FMD/scripts/TestRawIO.C [new file with mode: 0644]

index 97931d7..ec63bfc 100644 (file)
@@ -42,6 +42,7 @@
 #include <TGeoManager.h>
 #include <TGeoNode.h>
 #include <TGeoVolume.h>
+#include <TROOT.h>
 
 //====================================================================
 ClassImp(AliFMDAlignFaker)
@@ -141,24 +142,26 @@ AliFMDAlignFaker::Exec(Option_t*)
   // Loop over all entries in geometry to find our nodes. 
   while ((node = static_cast<TGeoNode*>(next()))) {
     const char* name =  node->GetName();
-    if (IS_NODE_HALF(name) && TESTBIT(fMask, kHalves) ||
-       IS_NODE_SENSOR(name) && TESTBIT(fMask, kSensors)) {
-      // Get the path 
-      TString path(Form("/%s", gGeoManager->GetNode(0)->GetName()));
-      Int_t nLevel = next.GetLevel();
-      for (Int_t lvl = 0; lvl <= nLevel; lvl++) {
-       TGeoNode* p = next.GetNode(lvl);
-       if (!p && lvl != 0) {
-         AliWarning(Form("No node at level %d in path %s", lvl, path.Data()));
-         continue;
-       }
-       if (!path.IsNull()) path.Append("/");
-       path.Append(p->GetName());
+    if (!(IS_NODE_HALF(name) && TESTBIT(fMask, kHalves)) &&
+       !(IS_NODE_SENSOR(name) && TESTBIT(fMask, kSensors))) 
+      continue;
+    
+    // Get the path 
+    TString path(Form("/%s", gGeoManager->GetNode(0)->GetName()));
+    Int_t nLevel = next.GetLevel();
+    for (Int_t lvl = 0; lvl <= nLevel; lvl++) {
+      TGeoNode* p = next.GetNode(lvl);
+      if (!p) {
+       if (lvl != 0)
+         AliWarning(Form("No node at level %d in path %s",lvl,path.Data()));
+       continue;
       }
-      Int_t id = node->GetVolume()->GetNumber();
-      if (IS_NODE_HALF(name))   MakeAlignHalf(path, id);
-      if (IS_NODE_SENSOR(name)) MakeAlignSensor(path, id);
+      if (!path.IsNull()) path.Append("/");
+      path.Append(p->GetName());
     }
+    Int_t id = node->GetVolume()->GetNumber();
+    if (IS_NODE_HALF(name))   MakeAlignHalf(path, id);
+    if (IS_NODE_SENSOR(name)) MakeAlignSensor(path, id);
   }
 
   TString t(GetTitle());
@@ -174,7 +177,8 @@ AliFMDAlignFaker::MakeAlign(const TString& path, Int_t id,
                            Double_t transX, Double_t transY, Double_t transZ,
                            Double_t rotX,   Double_t rotY, Double_t rotZ)
 {
-  AliDebug(1, Form("Make alignment for %s (volume %d)", path.Data(), id));
+  AliDebug(1, Form("Make alignment for %s (volume %d): (%f,%f,%f) (%f,%f,%f)", 
+                  path.Data(), id, transX, transY, transZ, rotX, rotY, rotZ));
   Int_t nAlign = fArray->GetEntries();
   AliAlignObjAngles* obj = 
     new ((*fArray)[nAlign]) AliAlignObjAngles(path.Data(), id,0,0,0,0,0,0);
@@ -193,7 +197,7 @@ AliFMDAlignFaker::MakeAlign(const TString& path, Int_t id,
 Bool_t
 AliFMDAlignFaker::MakeAlignHalf(const TString& path, Int_t id)
 {
-  AliDebug(1, Form("Make alignment for half-ring/cone %s", path.Data()));
+  AliDebug(15, Form("Make alignment for half-ring/cone %s", path.Data()));
   Double_t transX = gRandom->Uniform(fHalfTransMin.X(), fHalfTransMax.X());
   Double_t transY = gRandom->Uniform(fHalfTransMin.Y(), fHalfTransMax.Y());
   Double_t transZ = gRandom->Uniform(fHalfTransMin.Z(), fHalfTransMax.Z());
@@ -208,7 +212,7 @@ AliFMDAlignFaker::MakeAlignHalf(const TString& path, Int_t id)
 Bool_t
 AliFMDAlignFaker::MakeAlignSensor(const TString& path, Int_t id)
 {
-  AliDebug(1, Form("Make alignment for sensor %s", path.Data()));
+  AliDebug(15, Form("Make alignment for sensor %s", path.Data()));
   Double_t transX = gRandom->Uniform(fSensorTransMin.X(), fSensorTransMax.X());
   Double_t transY = gRandom->Uniform(fSensorTransMin.Y(), fSensorTransMax.Y());
   Double_t transZ = gRandom->Uniform(fSensorTransMin.Z(), fSensorTransMax.Z());
index 13e09d5..dfd1ea0 100644 (file)
@@ -36,7 +36,7 @@ public:
                   const char* loc="local://cdb");
   virtual ~AliFMDAlignFaker() {}
   void AddAlign(EWhat w) { SETBIT(fMask, w); }
-  void RemoveAlign(EWhat w) { SETBIT(fMask, w); }
+  void RemoveAlign(EWhat w) { CLRBIT(fMask, w); }
   void SetAlign(Int_t mask) { fMask = mask; }
   void SetSensorDisplacement(Double_t x1=0,   Double_t y1=0,   Double_t z1=0,
                             Double_t x2=.01, Double_t y2=.01, Double_t z2=0);
diff --git a/FMD/AliFMDAltroIO.cxx b/FMD/AliFMDAltroIO.cxx
new file mode 100644 (file)
index 0000000..3d7b68a
--- /dev/null
@@ -0,0 +1,454 @@
+/**************************************************************************
+ * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+ *                                                                        *
+ * Author: The ALICE Off-line Project.                                    *
+ * Contributors are mentioned in the code where appropriate.              *
+ *                                                                        *
+ * Permission to use, copy, modify and distribute this software and its   *
+ * documentation strictly for non-commercial purposes is hereby granted   *
+ * without fee, provided that the above copyright notice appears in all   *
+ * copies and that both the copyright notice and this permission notice   *
+ * appear in the supporting documentation. The authors make no claims     *
+ * about the suitability of this software for any purpose. It is          *
+ * provided "as is" without express or implied warranty.                  *
+ **************************************************************************/
+
+/* $Id$ */
+
+//____________________________________________________________________
+//                                                                          
+// Mapping of ALTRO hardware channel to detector coordinates 
+//
+#include "AliFMDAltroIO.h"
+#include <AliRawDataHeader.h>
+#include <AliRawReader.h>
+#include "AliLog.h"
+#include <iostream>
+#include <iomanip>
+#define PRETTY_HEX(N,X) \
+  "  0x" << std::setfill('0') << std::setw(N) << std::hex << X \
+         << std::setfill(' ') << std::dec
+
+//====================================================================
+ClassImp(AliFMDAltroIO)
+#if 0
+  ; // This is here to keep Emacs for indenting the next line
+#endif
+
+//____________________________________________________________________
+const AliFMDAltroIO::W40_t AliFMDAltroIO::fgkTrailerMask = 
+((AliFMDAltroIO::W40_t(0x2aaa) << 26) + (AliFMDAltroIO::W40_t(0xa) << 12));
+
+//____________________________________________________________________
+AliFMDAltroIO::AliFMDAltroIO() 
+  : fBuffer(0), fIBuffer(0)
+{}
+
+//____________________________________________________________________
+const char*
+AliFMDAltroIO::ErrorString(Int_t err)  const
+{
+  switch (err) {
+  case kNoError:    return "No error";                          break;
+  case kBadFile:    return "Bad state after open/close file";   break;
+  case kBadBits:    return "Bad bit offset specified";          break;
+  case kBadRead:    return "Bad state after reading from file"; break;
+  case kBadWrite:   return "Bad state after writing to file";   break;
+  case kBadSeek:    return "Bad state after seeking in file";   break;
+  case kBadTell:    return "Could not tell position in file";   break;
+  case kBadTrailer: return "Bad trailer 40 bit word in file";   break;
+  case kBadFill:    return "Bad fill word in file";             break;
+  }
+  return "Unknown";
+}
+
+
+//____________________________________________________________________
+AliFMDAltroIO::W40_t
+AliFMDAltroIO::ConcatW40(size_t n, const W10_t& w) const
+{
+  if (n > 3) return -kBadBits;
+  return W40_t(w & 0x3ff) << (10 * n);
+}
+
+//____________________________________________________________________
+AliFMDAltroIO::W10_t
+AliFMDAltroIO::ExtractW10(size_t n, const W40_t w) const
+{
+  if (n > 3) return -kBadBits;
+  return (w >> (10 * n)) & 0x3ff;
+}
+
+//====================================================================
+ClassImp(AliFMDAltroReader)
+#if 0
+  ; // This is here to keep Emacs for indenting the next line
+#endif
+
+//____________________________________________________________________
+AliFMDAltroReader::AliFMDAltroReader(std::istream& stream)
+  : fInput(stream)
+  // : fBuffer(buffer), fCurrent(n / 10 * sizeof(char))
+{
+  // fInput.open(filename);
+  if (!fInput)      throw -kBadFile;
+  fBegin   = fInput.tellg();
+  if (fInput.bad()) throw -kBadTell;
+  fInput.seekg(0, std::ios_base::end);
+  if (fInput.bad()) throw -kBadSeek;
+  fCurrent = fInput.tellg();
+  if (fInput.bad()) throw -kBadTell;
+#if 0
+  fInput.seekg(fBegin);
+  size_t i = 0;
+  do {
+    W40_t w = 0;
+    fInput.read((char*)&w, 5);
+    std::cout << std::setw(6) << i << ": " << PRETTY_HEX(10, w) << std::endl;
+    i++;
+  } while (!fInput.eof());
+  fInput.seekg(fCurrent);
+#endif
+}
+
+//____________________________________________________________________
+Int_t
+AliFMDAltroReader::ReadChannel(UShort_t& board, UShort_t& chip, 
+                              UShort_t& channel, UShort_t& last, 
+                              UShort_t* data) 
+{
+  UShort_t hwaddr;
+  Int_t    ret = ReadChannel(hwaddr, last, data);
+  board        = (hwaddr >>  7) & 0x1f;
+  chip         = (hwaddr >>  4) & 0x3;
+  channel      = hwaddr & 0xf;
+  return ret;
+}
+
+//____________________________________________________________________
+Int_t
+AliFMDAltroReader::ReadChannel(UShort_t& hwaddr, UShort_t& last, 
+                              UShort_t* data) 
+{
+  Int_t ret, tmp;
+  AliDebug(15, Form("Reading a channel"));
+  if ((ret = ExtractTrailer(hwaddr, last)) < 0) { 
+    AliError(Form("Failed to read trailer: %s", ErrorString(-ret)));
+    return ret;
+  }
+  AliDebug(15, Form("Now extracting bunches from %d 10 bit words", last));
+  tmp     =  ExtractBunches(last, data); 
+  if (tmp < 0) {
+    AliError(Form("Failed to read bunches: %s", ErrorString(-tmp)));
+    return tmp;
+  }
+  ret     += tmp;
+  last    =  (last == 0 ? 0 : last - 2); 
+  return ret;
+}
+
+//____________________________________________________________________
+Int_t
+AliFMDAltroReader::ExtractTrailer(UShort_t& hwaddr, UShort_t& last)
+{
+  AliDebug(15, "Extracting trailer");
+  W40_t trailer = GetNextW40();
+  if (trailer < 0) {
+    AliError(Form("Trailer 0x%x is bad: %s", trailer, ErrorString(-trailer)));
+    return trailer;
+  }
+  if (!IsTrailer(trailer)) { 
+    AliError(Form("Bad trailer: 0x%08x", trailer));
+    return -kBadTrailer;
+  }
+  last    = (trailer >> 16) & 0x3ff;
+  hwaddr  = (trailer & 0xfff);
+  return 4;
+}
+
+//____________________________________________________________________
+Int_t
+AliFMDAltroReader::ExtractBunches(UShort_t last, UShort_t* data) 
+{
+  Int_t ret;
+  if ((ret = ExtractFillWords(last)) < 0) { 
+    AliError(Form("Failed to read fill words: %s", ErrorString(-ret)));
+    return ret;
+  }
+  while (last > 0) { 
+    Int_t tmp = ExtractBunch(data);
+    if (tmp <= 0) { 
+      AliError(Form("Failed to extract bunch at %d: %s", 
+                   last, ErrorString(-tmp)));
+      return tmp;
+    }
+    ret  += tmp;
+    last -= tmp;
+  }
+  return ret;
+}
+
+//____________________________________________________________________
+Int_t
+AliFMDAltroReader::ExtractFillWords(UShort_t last) 
+{
+  // Number of fill words 
+  size_t nFill = (last % 4 == 0 ? 0 : 4 - last % 4);
+  // Read the fill words 
+  for (size_t i = 3; i >= 4 - nFill; i--) {
+    W10_t f = GetNextW10();
+    if (f != 0x2aa) return -kBadFill;
+  }
+  return nFill;
+}
+
+//____________________________________________________________________
+Int_t
+AliFMDAltroReader::ExtractBunch(UShort_t* data)
+{
+  Int_t ret =  0;
+  W10_t l =  GetNextW10(); 
+  if (l < 0) { 
+    AliError(Form("Failed to read bunch length: %s", ErrorString(-l)));
+    return l;
+  }
+  W10_t t =  GetNextW10(); 
+  if (t < 0) { 
+    AliError(Form("Failed to read bunch time: %s", ErrorString(-t)));
+    return t;
+  }
+  ret     += 2;
+  for (Int_t i = 2; i < l; i++) {
+    W10_t s = GetNextW10();
+    if (s < 0) { 
+      AliError(Form("Failed to read bunch data: %s", ErrorString(-s)));
+      return 2;
+    }
+    AliDebug(50,Form("Assigning to data[%d - (%d - 1)] = 0x%X", t, i, s));
+    data[t - (i-1)] = s;
+    ret++;
+  }
+  return ret;
+}
+
+//____________________________________________________________________
+Bool_t
+AliFMDAltroReader::IsTrailer(W40_t x) 
+{
+  return ((x & fgkTrailerMask) == fgkTrailerMask);
+}
+
+//____________________________________________________________________
+Bool_t
+AliFMDAltroReader::IsBof() 
+{
+  return fCurrent == fBegin;
+}
+
+//____________________________________________________________________
+Int_t
+AliFMDAltroReader::ReadW40() 
+{
+  fInput.seekg(fCurrent-std::istream::pos_type(5));
+  if (fInput.bad()) return -kBadSeek;
+  fCurrent = fInput.tellg();
+  if (fInput.bad()) return -kBadTell;
+  fInput.read((char*)&fBuffer, 5 * sizeof(char));
+  if (fInput.bad()) return -kBadRead;
+  fIBuffer = 4;
+  AliDebug(15, Form("  0x%03x  0x%03x  0x%03x  0x%03x    0x%010x  %6d", 
+                   ExtractW10(3, fBuffer), ExtractW10(2, fBuffer), 
+                   ExtractW10(1, fBuffer), ExtractW10(0, fBuffer), 
+                   fBuffer, fCurrent));
+  return fCurrent;
+}
+
+//____________________________________________________________________
+AliFMDAltroIO::W10_t
+AliFMDAltroReader::GetNextW10()
+{
+  if (fIBuffer <= 0) {
+    Int_t ret;
+    if ((ret = ReadW40()) < 0) return ret;
+  }
+  fIBuffer--;
+  W10_t w10 = ExtractW10(fIBuffer, fBuffer); 
+  return w10;
+}
+
+//____________________________________________________________________
+AliFMDAltroIO::W40_t
+AliFMDAltroReader::GetNextW40() 
+{
+  W40_t w40 = 0;
+  for (Int_t i = 3; i >= 0; i--) {
+    W10_t tmp  =  GetNextW10();
+    W40_t bits =  ConcatW40(i, tmp);
+    if (bits < 0) return bits;
+    w40        += bits;
+  }
+  return w40;
+}
+
+//====================================================================
+ClassImp(AliFMDAltroWriter)
+#if 0
+  ; // This is here to keep Emacs for indenting the next line
+#endif
+
+//____________________________________________________________________
+AliFMDAltroWriter::AliFMDAltroWriter(std::ostream& stream) 
+  : fThreshold(0), fTotal(0), fOutput(stream)
+{
+  AliDebug(15, "New AliFMDAltroWriter object");
+  fTime   = 0;
+  fLength = 0;
+  fLast   = 0;
+  // Write a dummy header
+  fHeader = fOutput.tellp();
+  if (fOutput.bad()) throw -kBadTell;
+  AliRawDataHeader header;
+  fOutput.write((char*)(&header), sizeof(header));
+  if (fOutput.bad()) throw -kBadWrite;
+  fBegin = fOutput.tellp();
+  if (fOutput.bad()) throw -kBadTell;
+}
+
+//____________________________________________________________________
+Int_t
+AliFMDAltroWriter::Flush() 
+{
+  if (fIBuffer == 0) return 0;
+  fOutput.write((char*)&fBuffer, 5 * sizeof(char));
+  if (fOutput.bad()) return -kBadWrite;
+  // for (size_t i = 0; i < 4; i++) 
+  //   std::cout << "\t" << PRETTY_HEX(3, ExtractW10(i, fBuffer));
+  // std::cout << "\t" << PRETTY_HEX(10, fBuffer) << std::endl;
+  fTotal   += 5;
+  fIBuffer =  0;
+  fBuffer  =  0;
+  return 5;
+}
+
+//____________________________________________________________________
+Int_t 
+AliFMDAltroWriter::Close() 
+{
+  Flush();
+  std::ostream::pos_type end = fOutput.tellp();
+  if (fOutput.bad()) return -kBadTell;
+  fOutput.seekp(fHeader, std::ios_base::beg);
+  if (fOutput.bad()) return -kBadSeek;
+  AliRawDataHeader header;
+  header.fSize = (size_t(end) - fHeader);
+  AliDebug(15, Form("Size set to %d (%d)", header.fSize, fTotal));
+  header.SetAttribute(0);
+  fOutput.write((char*)(&header), sizeof(header));
+  if (fOutput.bad()) return -kBadWrite;
+  fOutput.seekp(end);
+  if (fOutput.bad()) return -kBadSeek;
+  return sizeof(header);
+}
+
+
+//____________________________________________________________________
+Int_t
+AliFMDAltroWriter::AddSignal(UShort_t adc) 
+{
+  Int_t ret = 0;
+  if (adc < fThreshold) 
+    ret = AddBunchTrailer();
+  else {
+    ret = AddToBuffer(adc);
+    fLength++;
+  }
+  fTime++;
+  if (ret < 0) AliError(Form("Failed to add signal %x: %s", ErrorString(ret)));
+  return ret;
+}
+
+//____________________________________________________________________
+Int_t
+AliFMDAltroWriter::AddChannelTrailer(UShort_t board, UShort_t chip, 
+                                    UShort_t channel)
+{
+  UInt_t hwaddr = (channel & 0xf)+((chip & 0x3) << 4)+((board & 0x1f) << 7);
+  return AddChannelTrailer(hwaddr);
+}
+
+//____________________________________________________________________
+Int_t
+AliFMDAltroWriter::AddChannelTrailer(UInt_t hwaddr)
+{
+  Int_t ret =0, tmp;
+  if ((tmp = AddBunchTrailer()) < 0) { 
+    AliError(Form("Failed to bad bunch trailer: %s", ErrorString(tmp)));
+    return tmp;
+  }
+  ret += tmp;
+  if ((tmp = AddFillWords())    < 0) { 
+    AliError(Form("Failed to bad fill words: %s", ErrorString(tmp)));
+    return tmp;
+  }
+  ret += tmp;
+  W40_t trailer = (fgkTrailerMask + hwaddr + ((fLast & 0x3ff) << 16));
+  fBuffer = trailer;
+  fIBuffer = 3;
+  ret     += 4;
+  if ((tmp = Flush()) < 0) {
+    AliError(Form("Failed to flush: %s", ErrorString(tmp)));
+    return tmp;
+  }
+  ret     += tmp;
+  fTime   =  0;
+  fLast   =  0;
+  return ret;
+}
+
+//____________________________________________________________________
+Int_t
+AliFMDAltroWriter::AddToBuffer(UShort_t x) 
+{
+  W40_t tmp = ConcatW40(fIBuffer, x);
+  if (tmp < 0) return tmp;
+  fBuffer += tmp;
+  fIBuffer++;
+  fLast++;
+  Int_t ret = 0;
+  if (fIBuffer > 3 && (ret = Flush() < 0)) return ret;
+  return 1;
+}
+
+//____________________________________________________________________
+Int_t
+AliFMDAltroWriter::AddBunchTrailer()
+{
+  if (fLength <= 0) return 0;    
+  Int_t ret = 0, tmp;
+  if ((tmp = AddToBuffer(fTime))     < 0) return tmp;
+  ret += tmp;
+  if ((tmp = AddToBuffer(fLength+2)) < 0) return tmp;
+  ret += tmp;
+  fLength = 0;
+  return ret;
+}
+
+//____________________________________________________________________
+Int_t
+AliFMDAltroWriter::AddFillWords() 
+{
+  Int_t ret = 0, tmp;
+  if (fIBuffer == 0) return ret;
+  for (Int_t i = fIBuffer; i < 4; i++) { 
+    if ((tmp = AddToBuffer(0x2aa)) < 0) return tmp;
+    ret += tmp;
+    fLast--; 
+  }
+  if ((tmp = Flush() < 0)) return tmp;
+  return ret;
+}
+
+//_____________________________________________________________________________
+//
+// EOF
+//
diff --git a/FMD/AliFMDAltroIO.h b/FMD/AliFMDAltroIO.h
new file mode 100644 (file)
index 0000000..bd57928
--- /dev/null
@@ -0,0 +1,233 @@
+#ifndef ALIFMDALTROIO_H
+#define ALIFMDALTROIO_H
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights
+ * reserved. 
+ *
+ * Latest changes by Christian Holm Christensen <cholm@nbi.dk>
+ *
+ * See cxx source for full Copyright notice                               
+ */
+#include <iosfwd>
+#include <TObject.h>
+
+//____________________________________________________________________
+class AliFMDAltroIO  : public TObject
+{
+ public:
+  /** Type of 40 bit words (signed) */
+  typedef long long W40_t;
+  /** Type of 10 bit words (signed) */
+  typedef Int_t W10_t;
+  /** Constructor */
+  AliFMDAltroIO();
+  /** Destructor */
+  virtual ~AliFMDAltroIO() {}
+  /** Error states */
+  enum {
+    /** No error */
+    kNoError,
+    /** Bad state after open/close file */
+    kBadFile,
+    /** Bad bit offset specified */
+    kBadBits, 
+    /** Bad state after reading from file */
+    kBadRead, 
+    /** Bad state after writing to file */
+    kBadWrite, 
+    /** Bad state after seeking in file */
+    kBadSeek, 
+    /** Could not tell position in file */
+    kBadTell, 
+    /** Bad trailer 40 bit word in file */
+    kBadTrailer, 
+    /** Bad fill word in file */
+    kBadFill
+  };
+  /** Trailer mask */
+  static const W40_t  fgkTrailerMask;
+  /** Get error string */ 
+  const char* ErrorString(Int_t err)  const;
+protected:
+  /** I/O Buffer */
+  W40_t fBuffer;
+  /** Pointer into buffer */
+  Int_t fIBuffer;
+
+  /** Concatenate a 10 bit word into a 40 bit word.
+      @param n Offset (0-3)
+      @param w 10 bit word
+      @return @a w at offset @a n in a 40 bit word on success, a
+      negative error code on failure. */
+  virtual W40_t ConcatW40(size_t n, const W10_t& w) const;
+  /** Extract a 10 bit word from a 40 bit word
+      @param n The number 10bit word to extract (0-3)
+      @param w 40 bit word to extract from. 
+      @return The 10 bit word at @a n of @a w on success, or a
+      negative error code otherwise. */
+  virtual W10_t ExtractW10(size_t n, const W40_t w) const;
+
+  ClassDef(AliFMDAltroIO,0);
+};
+
+//____________________________________________________________________
+class AliFMDAltroReader : public AliFMDAltroIO
+{
+public:
+  /** Constructor 
+      @param filename File to read from 
+      @exception Int_t A negative error code in case of failure */
+  AliFMDAltroReader(std::istream& stream);
+  virtual ~AliFMDAltroReader() {}
+  /** Read one channel from the input file.  Note, that channels are
+      read from the back of the file. 
+      @param board   On return, the FEC board number 
+      @param chip    On return, the ALTRO chip number
+      @param channel On return, the ALTRO channel number
+      @param last    On return, the size of the data    
+      @param data    An array to fill with the data.  note, this
+      should be large enough to hold all the data (1024 is the maximum
+      number of timebins that can be read, so that's a safe size). 
+      @return negative error code on failure, 0 if nothing is read, or
+      the number of 10 bit words read. */
+  Int_t ReadChannel(UShort_t& board, UShort_t& chip, UShort_t& channel, 
+                   UShort_t& last,  UShort_t* data);
+  /** Read one channel from the input file.  Note, that channels are
+      read from the back of the file. 
+      @param hwaddr On return, the hardware address 
+      @param last   On return, the size of the data    
+      @param data   An array to fill with the data.  note, this
+      should be large enough to hold all the data (1024 is the maximum
+      number of timebins that can be read, so that's a safe size). 
+      @return negative error code on failure, 0 if nothing is read, or
+      the number of 10 bit words read.  */
+  Int_t ReadChannel(UShort_t& hwaddr, UShort_t& last, UShort_t* data);
+  /** Extract the channel trailer. 
+      @param hwaddr On return, the hardware address 
+      @param last   On return, the size of the data    
+      @return negative error code on failure, 0 if nothing is read, or
+      the number of 10 bit words read. */
+  Int_t ExtractTrailer(UShort_t& hwaddr, UShort_t& last);
+  /** Extract bunches from data section of a channel.  
+      @param last Pointer to last meaning full data entry. 
+      @param data An array to fill with the read data. 
+      @return negative error code on failure, otherwise number of 10
+      bit words read.  */
+  Int_t ExtractBunches(UShort_t last, UShort_t* data);
+  /** Extract possible fill words. 
+      @param last Pointer to last meaning full data entry. 
+      @return Negative error code on failure, otherwise number of fill
+      words read. */
+  Int_t ExtractFillWords(UShort_t last);
+  /** Extract bunch information from data. 
+      @param data An array to fill with the read data. 
+      @return negative error code on failure, otherwise number of 10
+      bit words read.  */
+  Int_t ExtractBunch(UShort_t* data);
+  /** Check if @a x is a valid trailer
+      @param x 40 bit word to check.
+      @return @c true if @a x is a valid trailer */
+  Bool_t IsTrailer(W40_t x);
+  /** @return @c true if we're at the beginning of the file */
+  Bool_t IsBof();
+protected:
+  /** Input stream */
+  std::istream& fInput;
+  /** Current position in file */
+  // std::istream::pos_type 
+  size_t fCurrent;
+  /** High water mark */
+  size_t fBegin;
+  
+  /** Read a 40 bit word from the input. 
+      @return negative error code on failure, current position otherwise. */
+  virtual Int_t ReadW40();
+  /** Get a 10 bit word from the (buffered) input. 
+      @return 10 bit word on success, negative error code on failure. */
+  virtual W10_t GetNextW10();
+  /** Get the next 40 bit word from the (buffered) input. 
+      @return The 40 bit  word, or negative error code on failure */
+  virtual W40_t GetNextW40();
+
+  ClassDef(AliFMDAltroReader,0);
+};
+
+//____________________________________________________________________
+class AliFMDAltroWriter : public AliFMDAltroIO
+{
+public:
+  /** Constructor.
+      @param filename File to read from
+      @exception Int_t A negative error code in case of failure */
+  AliFMDAltroWriter(std::ostream& stream);
+  virtual ~AliFMDAltroWriter() {}
+  /** @param threshold Zero-suppresion threshold */
+  void SetThreshold(UShort_t threshold) { fThreshold = threshold; }
+  /** Close the output, by writing the appropriate header.  The actual
+      stream should be called by the user. 
+      @return  number of bytes written, or negative error code on failure  */
+  Int_t Close();
+  /** Flush buffered output to file (if there is any). 
+      @return  0, or negative error code on failure */
+  Int_t Flush();
+  /** Add a signal to output.   If the signal @a adc is less then the
+      current threshold, a new bunch trailer is written. 
+      @param adc Signal
+      @return 0 on success, or negative error code on failure */
+  Int_t AddSignal(UShort_t adc);
+  /** Write a channel trailer to output. 
+      @param board   The FEC board number (0-31)
+      @param chip    The ALTRO chip number (0-7)
+      @param channel The ALTRO channel number (0-16)
+      @return Number of 10 bit words written, or negative error code
+      on failure  */ 
+  Int_t AddChannelTrailer(UShort_t board, UShort_t chip, UShort_t channel);
+  /** Write a channel trailer to output.  
+      @param hwaddr Hardware address (channel address)
+      @return Number of 10 bit words written, or negative error code
+      on failure */
+  Int_t AddChannelTrailer(UInt_t hwaddr);
+protected:
+  /** Add a value to output buffer. 
+      @param x Value to add. 
+      @return number of 10 bit words written to disk, or negative
+      error code on failure  */ 
+  Int_t AddToBuffer(UShort_t x);
+  /** Add a bunch trailer to output. 
+      @return number of 10 bit words written to disk, or negative
+      error code on failure  */ 
+  Int_t AddBunchTrailer();
+  /** Add fill words as needed to output
+      @return number of 10 bit words written to disk, or negative
+      error code on failure */
+  Int_t AddFillWords();
+  /** Zero suppression threshold */
+  UShort_t fThreshold;
+  /** Current time */
+  UShort_t fTime;
+  /** Current bunch length */
+  UShort_t fLength;
+  /** Last meaning-full data */
+  UShort_t fLast;
+  /** High-water mark (begining of file) */
+  size_t fBegin;
+  /** High-water mark (begining of file) */
+  size_t fHeader;
+  /** Total number of bytes written */
+  Long_t fTotal;
+  /** output stream */
+  std::ostream& fOutput;
+
+  ClassDef(AliFMDAltroWriter,0);
+};
+
+
+
+#endif
+//____________________________________________________________________
+//
+// Local Variables:
+//   mode: C++
+// End:
+//
+// EOF
+//
index d948d5e..cbdf971 100644 (file)
@@ -31,7 +31,6 @@ ClassImp(AliFMDAltroMapping)
 
 //_____________________________________________________________________________
 AliFMDAltroMapping::AliFMDAltroMapping()
-  : AliAltroMapping(0)
 {}
 
 
@@ -239,16 +238,16 @@ AliFMDAltroMapping::Detector2Hardware(UShort_t  det, Char_t    ring,
   UInt_t ncs   =  (ring == 'I' ? 8 : 4);   // Channels per sensor 
   UInt_t bbase =  (ring == 'I' ? 0 : 2);
   UInt_t board =  bbase + sec / nsen;
-  UInt_t lsen  =  (sec - (board - bbase) * nsen);
-  UInt_t altro =  (lsen < 2 * nsa ? 0 : (lsen < 3 * nsa ? 1 : 2));
-  UInt_t sbase =  (lsen < 2 * nsa ? 0 : (lsen < 3 * nsa ? 2*nsa : 3*nsa));
-  UInt_t chan  =  (sec % 2) + (lsen-sbase) / 2 * ncs + 2 * str / 128;
+  UInt_t lsec  =  (sec - (board - bbase) * nsen); // Local sec in half-ring
+  UInt_t altro =  (lsec < 2 * nsa ? 0 : (lsec < 3 * nsa ? 1       : 2));
+  UInt_t sbase =  (altro == 0     ? 0 : altro == 1      ? 2 * nsa : 3 * nsa);
+  UInt_t chan  =  (sec % 2) + (lsec-sbase) / 2 * ncs + 2 * (str / 128);
   AliDebug(40, Form("\n"
                    "  chan = (%d %% 2) + (%d-%d) / %d * %d + 2 * %d / 128\n"
                    "       = %d + %d + %d = %d", 
-                   sec, lsen, sbase, 2, ncs, str, 
-                   (sec % 2), (lsen - sbase) / 2 * ncs, 
-                   2 * str / 128, chan));
+                   sec, lsec, sbase, 2, ncs, str, 
+                   (sec % 2), (lsec - sbase) / 2 * ncs, 
+                   2 * (str / 128), chan));
   addr         =  chan + (altro << 4) + (board << 7);
   
   return kTRUE;
index 769efd1..0ad1ddf 100644 (file)
@@ -29,7 +29,7 @@ public:
                           UInt_t&   ddl, UInt_t&   hwaddr) const;
   Int_t  GetHWAdress(Int_t sector, Int_t str, Int_t ring) const
   {
-    return GetHWAdress(sector, str, ring);
+    return GetHWAddress(sector, str, ring);
   }
   Int_t  GetHWAddress(Int_t sector, Int_t str, Int_t ring) const;
   Int_t  GetPadRow(Int_t hwaddr) const;
index 9c87aef..3296e5b 100644 (file)
@@ -37,6 +37,7 @@
 #include <Riostream.h>
 #include <TSystem.h>
 #include <TMath.h>
+#include <TROOT.h>
 #include <TRandom.h>
 
 //====================================================================
index f175c2d..64f4918 100644 (file)
@@ -261,6 +261,7 @@ Bool_t
 AliFMDBaseDigitizer::Init()
 {
   // Initialization
+  AliFMDParameters::Instance()->Init();
   return kTRUE;
 }
  
index 68953c5..9a804a0 100644 (file)
@@ -82,10 +82,10 @@ AliFMDDisplay::AliFMDDisplay(const char* gAliceFile)
 }
 
 //____________________________________________________________________
-void
+void           
 AliFMDDisplay::ExecuteEvent(Int_t event, Int_t px, Int_t py) 
 {
-  AliInfo(Form("Event %d, at (%d,%d)", px, py));
+  // AliInfo(Form("Event %d, at (%d,%d)", px, py));
   if (px == 0 && py == 0) return;
   if (!fZoomMode && fPad->GetView()) {
     fPad->GetView()->ExecuteRotateView(event, px, py);
@@ -125,10 +125,10 @@ AliFMDDisplay::ExecuteEvent(Int_t event, Int_t px, Int_t py)
 }
 
 //____________________________________________________________________
-Int_t
-AliFMDDisplay::DistanceToPrimitive(Int_t px, Int_t py) 
+Int_t          
+AliFMDDisplay::DistancetoPrimitive(Int_t px, Int_t) 
 {
-  AliInfo(Form("@ (%d,%d)", px, py));
+  // AliInfo(Form("@ (%d,%d)", px, py));
   fPad->SetCursor(kCross);
   Float_t xmin = fPad->GetX1();
   Float_t xmax = fPad->GetX2();
@@ -200,12 +200,14 @@ AliFMDDisplay::End()
 {
   fPad->cd();
   fMarkers->Draw();
+  fPad->cd();
   AppendPad();
-  fPad->Update();
+  // fPad->Update();
   fPad->cd();
-  fCanvas->Modified(kTRUE);
-  fCanvas->Update();
-  fCanvas->cd();
+  // fCanvas->Modified(kTRUE);
+  //fCanvas->Update();
+  // fCanvas->cd();
+  // fPad->cd();
   fWait = kTRUE;
   while (fWait) {
     gApplication->StartIdleing();
index 04ff8e1..1d2af93 100644 (file)
@@ -31,8 +31,8 @@ public:
   void  Zoom() { fZoomMode = kTRUE; }
   void  Pick() { fZoomMode = kFALSE; }
   void  ExecuteEvent(Int_t event, Int_t px, Int_t py);
-  Int_t DistanceToPrimitive(Int_t px, Int_t py);
-  
+  Int_t DistancetoPrimitive(Int_t px, Int_t py);
+  void  Paint(Option_t* option="") { (void)option; }
 
   virtual Bool_t Init();
   virtual Bool_t Begin(Int_t event);
index c22fb59..ce67516 100644 (file)
@@ -37,6 +37,9 @@
 #include "AliFMDRecPoint.h"    // ALIFMDRECPOINT_H
 #include <AliESD.h>
 #include <AliESDFMD.h>
+#include <AliCDBManager.h>
+#include <AliCDBEntry.h>
+#include <AliAlignObjAngles.h>
 #include <TTree.h>              // ROOT_TTree
 #include <TChain.h>             // ROOT_TChain
 #include <TParticle.h>          // ROOT_TParticle
@@ -195,6 +198,25 @@ AliFMDInput::Init()
       Fatal("Init", "No geometry manager found");
       return kFALSE;
     }
+    AliCDBManager* cdb   = AliCDBManager::Instance();
+    AliCDBEntry*   align = cdb->Get("FMD/Align/Data");
+    if (align) {
+      AliInfo("Got alignment data from CDB");
+      TClonesArray* array = dynamic_cast<TClonesArray*>(align->GetObject());
+      if (!array) {
+       AliWarning("Invalid align data from CDB");
+      }
+      else {
+       Int_t nAlign = array->GetEntries();
+       for (Int_t i = 0; i < nAlign; i++) {
+         AliAlignObjAngles* a = static_cast<AliAlignObjAngles*>(array->At(i));
+         if (!a->ApplyToGeometry()) {
+           AliWarning(Form("Failed to apply alignment to %s", 
+                           a->GetVolPath()));
+         }
+       }
+      }
+    }
   }
 
   
index e90e295..d7bff74 100644 (file)
@@ -95,58 +95,117 @@ AliFMDParameters::Init()
   // Initialize the parameters manager.  We need to get stuff from the
   // CDB here. 
   if (fIsInit) return;
+  InitPulseGain();
+  InitPedestal();
+  InitDeadMap();
+  InitSampleRate();
+  InitZeroSuppression();
+  InitAltroMap();
+  fIsInit = kTRUE;
   
+}
+//__________________________________________________________________
+void
+AliFMDParameters::InitPulseGain()
+{
   AliCDBManager* cdb      = AliCDBManager::Instance();
   AliCDBEntry*   gain     = cdb->Get(fgkPulseGain);
-  AliCDBEntry*   pedestal = cdb->Get(fgkPedestal);
-  AliCDBEntry*   deadMap  = cdb->Get(fgkDead);
-  AliCDBEntry*   zeroSup  = cdb->Get(fgkZeroSuppression);
-  AliCDBEntry*   sampRat  = cdb->Get(fgkSampleRate);
-  AliCDBEntry*   hwMap    = cdb->Get(fgkAltroMap);       
+  if (!gain) {
+    AliWarning(Form("No %s found in CDB, perhaps you need to "
+                   "use AliFMDCalibFaker?", fgkPulseGain));
+    return;
+  }
   
-  if (gain) {
-    AliDebug(1, Form("Got gain from CDB"));
-    fPulseGain = dynamic_cast<AliFMDCalibGain*>(gain->GetObject());
-    if (!fPulseGain) 
-      AliWarning("Invalid pulser gain object from CDB");
+  AliDebug(1, Form("Got gain from CDB"));
+  fPulseGain = dynamic_cast<AliFMDCalibGain*>(gain->GetObject());
+  if (!fPulseGain) AliWarning("Invalid pulser gain object from CDB");
+}
+//__________________________________________________________________
+void
+AliFMDParameters::InitPedestal()
+{
+  AliCDBManager* cdb      = AliCDBManager::Instance();
+  AliCDBEntry*   pedestal = cdb->Get(fgkPedestal);
+  if (!pedestal) {
+    AliWarning(Form("No %s found in CDB, perhaps you need to "
+                   "use AliFMDCalibFaker?", fgkPedestal));
+    return;
   }
-  if (pedestal) {
-    AliDebug(1, Form("Got pedestal from CDB"));
-    fPedestal = dynamic_cast<AliFMDCalibPedestal*>(pedestal->GetObject());
-    if (!fPedestal) 
-      AliWarning("Invalid pedestal object from CDB");
+  AliDebug(1, Form("Got pedestal from CDB"));
+  fPedestal = dynamic_cast<AliFMDCalibPedestal*>(pedestal->GetObject());
+  if (!fPedestal) AliWarning("Invalid pedestal object from CDB");
+}
+
+//__________________________________________________________________
+void
+AliFMDParameters::InitDeadMap()
+{
+  AliCDBManager* cdb      = AliCDBManager::Instance();
+  AliCDBEntry*   deadMap  = cdb->Get(fgkDead);
+  if (!deadMap) {
+    AliWarning(Form("No %s found in CDB, perhaps you need to "
+                   "use AliFMDCalibFaker?", fgkDead));
+    return;
   }
-  if (deadMap) {
-    AliDebug(1, Form("Got dead map from CDB"));
-    fDeadMap = dynamic_cast<AliFMDCalibDeadMap*>(deadMap->GetObject());
-    if (!fDeadMap) 
-      AliWarning("Invalid dead map object from CDB");
+  AliDebug(1, Form("Got dead map from CDB"));
+  fDeadMap = dynamic_cast<AliFMDCalibDeadMap*>(deadMap->GetObject());
+  if (!fDeadMap) AliWarning("Invalid dead map object from CDB");
+}
+
+//__________________________________________________________________
+void
+AliFMDParameters::InitZeroSuppression()
+{
+  AliCDBManager* cdb      = AliCDBManager::Instance();
+  AliCDBEntry*   zeroSup  = cdb->Get(fgkZeroSuppression);
+  if (!zeroSup) {
+    AliWarning(Form("No %s found in CDB, perhaps you need to "
+                   "use AliFMDCalibFaker?", fgkZeroSuppression));
+    return;
   }
-  if (zeroSup) {
-    AliDebug(1, Form("Got zero suppression from CDB"));
-    fZeroSuppression = 
-      dynamic_cast<AliFMDCalibZeroSuppression*>(zeroSup->GetObject());
-    if (!fZeroSuppression) 
-      AliWarning("Invalid zero suppression object from CDB");
+  AliDebug(1, Form("Got zero suppression from CDB"));
+  fZeroSuppression = 
+    dynamic_cast<AliFMDCalibZeroSuppression*>(zeroSup->GetObject());
+  if (!fZeroSuppression)AliWarning("Invalid zero suppression object from CDB");
+}
+
+//__________________________________________________________________
+void
+AliFMDParameters::InitSampleRate()
+{
+  AliCDBManager* cdb      = AliCDBManager::Instance();
+  AliCDBEntry*   sampRat  = cdb->Get(fgkSampleRate);
+  if (!sampRat) {
+    AliWarning(Form("No %s found in CDB, perhaps you need to "
+                   "use AliFMDCalibFaker?", fgkSampleRate));
+    return;
   }
-  if (sampRat) {
-    AliDebug(1, Form("Got zero suppression from CDB"));
-    fSampleRate = 
-      dynamic_cast<AliFMDCalibSampleRate*>(sampRat->GetObject());
-    if (!fSampleRate) 
-      AliWarning("Invalid zero suppression object from CDB");
+  AliDebug(1, Form("Got zero suppression from CDB"));
+  fSampleRate = dynamic_cast<AliFMDCalibSampleRate*>(sampRat->GetObject());
+  if (!fSampleRate) AliWarning("Invalid zero suppression object from CDB");
+}
+
+//__________________________________________________________________
+void
+AliFMDParameters::InitAltroMap()
+{
+  AliCDBManager* cdb      = AliCDBManager::Instance();
+  AliCDBEntry*   hwMap    = cdb->Get(fgkAltroMap);       
+  if (!hwMap) {
+    AliWarning(Form("No %s found in CDB, perhaps you need to "
+                   "use AliFMDCalibFaker?", fgkAltroMap));
+    fAltroMap = new AliFMDAltroMapping;
+    return;
   }
-  if (hwMap) {
-    AliDebug(1, Form("Got ALTRO map from CDB"));
-    fAltroMap = dynamic_cast<AliFMDAltroMapping*>(hwMap->GetObject());
-    if (!fAltroMap) 
-      AliWarning("Invalid ALTRO map object from CDB");
+  AliDebug(1, Form("Got ALTRO map from CDB"));
+  fAltroMap = dynamic_cast<AliFMDAltroMapping*>(hwMap->GetObject());
+  if (!fAltroMap) {
+    AliWarning("Invalid ALTRO map object from CDB");
+    fAltroMap = new AliFMDAltroMapping;
   }
-  if (!fAltroMap) fAltroMap = new AliFMDAltroMapping;
-  
-  fIsInit = kTRUE;
 }
 
+
 //__________________________________________________________________
 Float_t
 AliFMDParameters::GetThreshold() const
@@ -174,6 +233,9 @@ AliFMDParameters::GetPulseGain(UShort_t detector, Char_t ring,
       fFixedPulseGain = fVA1MipRange * GetEdepMip() / fAltroChannelSize;
     return fFixedPulseGain;
   }  
+  AliDebug(50, Form("pulse gain for FMD%d%c[%2d,%3d]=%f",
+                   detector, ring, sector, strip,
+                   fPulseGain->Value(detector, ring, sector, strip)));
   return fPulseGain->Value(detector, ring, sector, strip);
 }
 
@@ -183,6 +245,10 @@ AliFMDParameters::IsDead(UShort_t detector, Char_t ring,
                         UShort_t sector, UShort_t strip) const
 {
   if (!fDeadMap) return kFALSE;
+  AliDebug(50, Form("Dead for FMD%d%c[%2d,%3d]=%s",
+                   detector, ring, sector, strip,
+                   fDeadMap->operator()(detector, ring, sector, strip) ? 
+                   "no" : "yes"));
   return fDeadMap->operator()(detector, ring, sector, strip);
 }
 
@@ -193,6 +259,10 @@ AliFMDParameters::GetZeroSuppression(UShort_t detector, Char_t ring,
 {
   if (!fZeroSuppression) return fFixedZeroSuppression;
   // Need to map strip to ALTRO chip. 
+  AliDebug(50, Form("zero sup. for FMD%d%c[%2d,%3d]=%f",
+                   detector, ring, sector, strip,
+                   fZeroSuppression->operator()(detector, ring, 
+                                                sector, strip)));
   return fZeroSuppression->operator()(detector, ring, sector, strip/128);
 }
 
@@ -202,6 +272,7 @@ AliFMDParameters::GetSampleRate(UShort_t ddl) const
 {
   if (!fSampleRate) return fFixedSampleRate;
   // Need to map sector to digitizier card. 
+  AliDebug(50, Form("Sample rate for %d=%d", ddl, fSampleRate->Rate(ddl)));
   return fSampleRate->Rate(ddl);
 }
 
@@ -211,6 +282,9 @@ AliFMDParameters::GetPedestal(UShort_t detector, Char_t ring,
                              UShort_t sector, UShort_t strip) const
 {
   if (!fPedestal) return fFixedPedestal;
+  AliDebug(50, Form("pedestal for FMD%d%c[%2d,%3d]=%f",
+                   detector, ring, sector, strip,
+                   fPedestal->Value(detector, ring, sector, strip)));
   return fPedestal->Value(detector, ring, sector, strip);
 }
 
@@ -220,6 +294,9 @@ AliFMDParameters::GetPedestalWidth(UShort_t detector, Char_t ring,
                                   UShort_t sector, UShort_t strip) const
 {
   if (!fPedestal) return fFixedPedestalWidth;
+  AliDebug(50, Form("pedetal width for FMD%d%c[%2d,%3d]=%f",
+                   detector, ring, sector, strip,
+                   fPedestal->Width(detector, ring, sector, strip)));
   return fPedestal->Width(detector, ring, sector, strip);
 }
   
index a809842..94ee0dd 100644 (file)
@@ -102,6 +102,12 @@ protected:
   AliFMDParameters();
   virtual ~AliFMDParameters() {}
   static AliFMDParameters* fgInstance;   // Static singleton instance
+  void InitPulseGain();
+  void InitPedestal();
+  void InitDeadMap();
+  void InitSampleRate();
+  void InitZeroSuppression();
+  void InitAltroMap();
 
   Bool_t          fIsInit;               // Whether we've been initialised  
 
index 043f74d..96fee2f 100644 (file)
 #include "AliFMDRawStream.h"   // ALIFMDRAWSTREAM_H 
 #include "AliRawReader.h"      // ALIRAWREADER_H 
 #include "AliFMDRawReader.h"   // ALIFMDRAWREADER_H 
+#include "AliFMDAltroIO.h"     // ALIFMDALTROIO_H 
 #include <TArrayI.h>           // ROOT_TArrayI
 #include <TTree.h>             // ROOT_TTree
 #include <TClonesArray.h>      // ROOT_TClonesArray
+#include <iostream>
+#include <iomanip>
+#include <sstream>
+#define PRETTY_HEX(N,X) \
+  "  0x" << std::setfill('0') << std::setw(N) << std::hex << X \
+         << std::setfill(' ') << std::dec
 
 //____________________________________________________________________
 ClassImp(AliFMDRawReader)
@@ -73,6 +80,82 @@ AliFMDRawReader::AliFMDRawReader(AliRawReader* reader, TTree* tree)
 void
 AliFMDRawReader::Exec(Option_t*) 
 {
+  // Read raw data into the digits array, using AliFMDAltroReader. 
+  if (!fReader->ReadHeader()) {
+    Error("ReadAdcs", "Couldn't read header");
+    return;
+  }
+
+  TClonesArray* array = new TClonesArray("AliFMDDigit");
+  fTree->Branch("FMD", &array);
+
+  // Get sample rate 
+  AliFMDParameters* pars = AliFMDParameters::Instance();
+
+  // Select FMD DDL's 
+  fReader->Select(AliFMDParameters::kBaseDDL>>8);
+
+  UShort_t stripMin = 0;
+  UShort_t stripMax = 127;
+  UShort_t preSamp  = 0;
+  
+  do {
+    UChar_t* cdata;
+    if (!fReader->ReadNextData(cdata)) break;
+    size_t   nchar = fReader->GetDataSize();
+    UShort_t ddl   = AliFMDParameters::kBaseDDL + fReader->GetDDLID();
+    UShort_t rate  = pars->GetSampleRate(ddl);
+    AliDebug(1, Form("Reading %d bytes (%d 10bit words) from %d", 
+                    nchar, nchar * 8 / 10, ddl));
+    // Make a stream to read from 
+    std::string str((char*)(cdata), nchar);
+    std::istringstream s(str);
+    // Prep the reader class.
+    AliFMDAltroReader r(s);
+    // Data array is approx twice the size needed. 
+    UShort_t data[2048], hwaddr, last;
+    while (r.ReadChannel(hwaddr, last, data) > 0) {
+      AliDebug(5, Form("Read channel 0x%x of size %d", hwaddr, last));
+      UShort_t det, sec, str;
+      Char_t   ring;
+      if (!pars->Hardware2Detector(ddl, hwaddr, det, ring, sec, str)) {
+       AliError(Form("Failed to detector id from DDL %d "
+                     "and hardware address 0x%x", ddl, hwaddr));
+       continue;
+      }
+      AliDebug(5, Form("DDL 0x%04x, address 0x%03x maps to FMD%d%c[%2d,%3d]", 
+                      ddl, hwaddr, det, ring, sec, str));
+
+      // Loop over the `timebins', and make the digits
+      for (size_t i = 0; i < last; i++) {
+       if (i < preSamp) continue;
+       Int_t n = array->GetEntries();
+       UShort_t curStr = str + stripMin + i / rate;
+       if ((curStr-str) > stripMax) {
+         AliError(Form("Current strip is %d but DB says max is %d", 
+                       curStr, stripMax));
+       }
+       AliDebug(5, Form("making digit for FMD%d%c[%2d,%3d] from sample %4d", 
+                        det, ring, sec, curStr, i));
+       new ((*array)[n]) AliFMDDigit(det, ring, sec, curStr, data[i], 
+                                     (rate >= 2 ? data[i+1] : 0),
+                                     (rate >= 3 ? data[i+2] : 0));
+       if (rate >= 2) i++;
+       if (rate >= 3) i++;
+       }
+       if (r.IsBof()) break;
+    }
+  } while (true);
+  AliDebug(1, Form("Got a grand total of %d digits", array->GetEntries()));
+}
+
+#if 0
+// This is the old method, for comparison.   It's really ugly, and far
+// too convoluted. 
+//____________________________________________________________________
+void
+AliFMDRawReader::Exec(Option_t*) 
+{
   // Read raw data into the digits array
   if (!fReader->ReadHeader()) {
     Error("ReadAdcs", "Couldn't read header");
@@ -109,6 +192,7 @@ AliFMDRawReader::Exec(Option_t*)
 
     count++; 
     Int_t ddl = fReader->GetDDLID();
+    AliDebug(10, Form("Current DDL is %d", ddl));
     if (ddl != oldDDL || input.IsNewStrip() || !next) {
       // Make a new digit, if we have some data (oldDetector == 0,
       // means that we haven't really read anything yet - that is,
@@ -144,16 +228,15 @@ AliFMDRawReader::Exec(Option_t*)
       // If we got a new DDL, it means we have a new detector. 
       if (ddl != oldDDL) {
        if (detector != 0) 
-         AliDebug(10, Form("Read %d channels for FMD%d", 
-                           count + 1, detector));
+         AliDebug(10, Form("Read %d channels for FMD%d", count + 1, detector));
        // Reset counts, and update the DDL cache 
        count       = 0;
        oldDDL      = ddl;
        // Check that we're processing a FMD detector 
        Int_t detId = fReader->GetDetectorID();
        if (detId != (AliFMDParameters::kBaseDDL >> 8)) {
-         Error("ReadAdcs", "Detector ID %d != %d",
-               detId, (AliFMDParameters::kBaseDDL >> 8));
+         AliError(Form("Detector ID %d != %d",
+                       detId, (AliFMDParameters::kBaseDDL >> 8)));
          break;
        }
        // Figure out what detector we're deling with 
@@ -163,7 +246,7 @@ AliFMDRawReader::Exec(Option_t*)
        case 1: detector = 2; break;
        case 2: detector = 3; break;
        default:
-         Error("ReadAdcs", "Unknown DDL 0x%x for FMD", ddl);
+         AliError(Form("Unknown DDL 0x%x for FMD", ddl));
          return;
        }
        AliDebug(10, Form("Reading ADCs for 0x%x  - That is FMD%d",
@@ -183,6 +266,7 @@ AliFMDRawReader::Exec(Option_t*)
   return;
 
 }
+#endif
 
 //____________________________________________________________________
 // 
index 8cfcbfd..c33ad39 100644 (file)
@@ -27,6 +27,9 @@
 //
 #include "AliFMDRawStream.h"           // ALIFMDRAWSTREAM_H
 #include <AliRawReader.h>              // ALIRAWREADER_H
+#include <AliLog.h>
+#include <iomanip>
+#include <iostream>
 
 //____________________________________________________________________
 ClassImp(AliFMDRawStream)
@@ -39,12 +42,180 @@ AliFMDRawStream::AliFMDRawStream(AliRawReader* reader, UShort_t sampleRate)
   : AliAltroRawStream(reader), 
     fSampleRate(sampleRate),
     fPrevTime(-1), 
-    fExplicitSampleRate(kFALSE)
+    fExplicitSampleRate(kFALSE), 
+    fPos(0),
+    fCur(0),
+    fRead(0)
 {
   if (fSampleRate > 0) fExplicitSampleRate = kTRUE;
 }
 
 //_____________________________________________________________________________
+Int_t
+AliFMDRawStream::ReadTrailer(UInt_t& addr, UInt_t& len)
+{
+  if (fPos <= 0) return 0;
+  if (fPos <  4) {
+    AliError("could not read trailer");
+    return -1;
+  }
+  AliDebug(1, Form("Reading a trailer at %d", fPos));
+  Int_t temp = Get10BitWord();
+  if (temp != 0x2AA) {
+    AliError(Form("Incorrect trailer! Expected 0x2AA but got %x!",temp));
+    return -1;
+  }
+  temp = Get10BitWord();
+  if ((temp >> 6) != 0xA) {
+    AliError(Form("Incorrect trailer! Expected 0xA but got %x!",temp >> 6));
+    return -1;
+  }
+
+  len  =  (temp << 4) & 0x3FF;
+  temp =  Get10BitWord();
+  len  |= (temp >> 6);
+  if (((temp >> 2) & 0xF) != 0xA) {
+    AliError(Form("Incorrect trailer! Expected 0xA but got %x!",temp >> 6));
+    return -1;
+  }
+  addr =  (temp & 0x3) << 10;
+  temp =  Get10BitWord();
+  addr |= temp;
+
+  return 4;
+}
+
+//_____________________________________________________________________________
+Int_t 
+AliFMDRawStream::ReadFillWords(UInt_t len)
+{
+  if (len % 4 == 0) return 0;
+  Int_t nFill = (4 - (len % 4)) % 4;
+  AliDebug(1, Form("Reading %d fill words", nFill));
+  for (Int_t i = 0; i < nFill; i++) {
+    UInt_t fill = Get10BitWord();
+    if (fill != 0x2AA) {
+      AliError(Form("Invalid fill! Expected 0x2AA, but got %X!", fill));
+      return -1;
+    }
+  }
+  return nFill;
+}
+
+//_____________________________________________________________________________
+Int_t 
+AliFMDRawStream::ReadBunch(UShort_t* data)
+{
+  AliDebug(1, "Reading a bunch");
+  if (fPos <= 0) {
+    AliError("could not read bunch length");
+    return -1;
+  }
+  UShort_t len  = Get10BitWord();
+  if (fPos <= 0) {
+    AliError("could not read bunch length");
+    return -1;
+  }
+  UShort_t time = Get10BitWord();
+  
+  AliDebug(1, Form("Bunch is %d long and ends at t=%d", len, time));
+  for (UInt_t i = 2; i < len; i++) {
+    Int_t amp = Get10BitWord();
+    if (amp < 0) { 
+      AliError(Form("Bad adc value (%X) !", amp));
+      return -1;
+    }
+    data[time - (i-2)] = amp;
+  }
+  return len;
+}
+
+//_____________________________________________________________________________
+Int_t 
+AliFMDRawStream::ReadIntoBuffer()
+{
+  if (fPos > 0) return kTRUE;
+  do {
+    AliDebug(1, Form("Reading into the buffer"));
+    if (!fRawReader->ReadNextData(fRead)) return -1;
+  } while (fRawReader->GetDataSize() == 0);
+  fPos = (fRawReader->GetDataSize() * 8) / 10;
+  // Skip trailing `0x2AA's - is this needed?  Won't it break the
+  // trailer? 
+#if 0
+  UShort_t skip;
+  while ((skip = Get10BitWord()) != 0x2AA) 
+    AliDebug(1,Form("Skipping one %x", skip));
+#endif
+  fPos++;
+  return fPos;
+}
+
+//_____________________________________________________________________________
+Bool_t 
+AliFMDRawStream::ReadChannel(UInt_t& addr, UInt_t& len, UShort_t* data)
+{
+  Int_t ret = 0;
+  AliDebug(1, "Reading a channel");
+  if ((ret = ReadIntoBuffer())       < 0) return kFALSE;
+  if ((ret = ReadTrailer(addr, len)) < 0) return kFALSE;
+  if ((ret = ReadFillWords(len))     < 0) return kFALSE;
+  Int_t toRead = len;
+  while (toRead > 0) {
+    if ((ret = ReadBunch(data)) < 0) return kFALSE;
+    toRead -= ret;
+  }
+  len -= 2;
+  return kTRUE;
+}
+
+//_____________________________________________________________________________
+Bool_t 
+AliFMDRawStream::DumpData()
+{
+  Int_t ret;
+  if ((ret = ReadIntoBuffer())       < 0) return kFALSE;
+  UShort_t data;
+  Int_t i = 0;
+  while ((data = Get10BitWord()) != 0xffff) {
+    if (i % 4 == 0) {
+      if (i != 0) std::cout << "\n";
+      std::cout << std::setw(6) << i << ":";
+    }
+    std::cout << "  0x" << std::setfill('0') << std::setw(3) 
+             << std::hex << data << std::dec << std::setfill(' ')
+             << std::flush;
+    i++;
+  }
+  return kTRUE;
+}
+
+//_____________________________________________________________________________
+UShort_t 
+AliFMDRawStream::Get10BitWord()
+{
+  // return a word in a 10 bit array as an UShort_t
+  --fPos;
+  if (fPos < 0) { 
+    AliWarning("At high water mark");
+    return 0xFFFF;
+  }
+  Int_t iBit  = fPos * 10;
+  Int_t iByte = iBit / 8;
+  Int_t shift = iBit % 8;
+  // return ((buffer[iByte+1] * 256 + buffer[iByte]) >> shift) & 0x03FF;
+
+  // recalculate the byte numbers and the shift because
+  // the raw data is written as integers where the high bits are filled first
+  // -> little endian is assumed here !
+  Int_t iByteHigh = 4 * (iByte / 4) + 3 - (iByte % 4);
+  iByte++;
+  Int_t iByteLow  = 4 * (iByte / 4) + 3 - (iByte % 4);
+  shift = 6 - shift;
+  return ((fRead[iByteHigh] * 256 + fRead[iByteLow]) >> shift) & 0x03FF;
+}
+
+//_____________________________________________________________________________
 Bool_t 
 AliFMDRawStream::Next()
 {
index 1fd692f..4138747 100644 (file)
@@ -41,13 +41,22 @@ public:
   Short_t Count()       const { return fSignal; }
   Short_t SampleRate()  const { return fSampleRate; }
   
-  virtual Bool_t   Next();
-  
-private:
-  UShort_t fSampleRate;         // # of ALTRO samples per VA1_ALICE clock
-  Int_t    fPrevTime;           // Last time bin
-  Bool_t   fExplicitSampleRate; // True if the sample rate was set externally
+  virtual Bool_t Next();
+  virtual Bool_t ReadChannel(UInt_t& addr, UInt_t& len, UShort_t* data);
+  virtual Bool_t DumpData();
+protected:
+  virtual Int_t    ReadIntoBuffer();
+  virtual Int_t    ReadTrailer(UInt_t& head, UInt_t& len);
+  virtual Int_t    ReadFillWords(UInt_t len);
+  virtual Int_t    ReadBunch(UShort_t* data);
+  virtual UShort_t Get10BitWord();
   
+  UShort_t  fSampleRate;         // # of ALTRO samples per VA1_ALICE clock
+  Int_t     fPrevTime;           // Last time bin
+  Bool_t    fExplicitSampleRate; // True if the sample rate was set externally
+  Int_t     fPos;
+  Int_t     fCur;
+  UChar_t*  fRead;
   ClassDef(AliFMDRawStream, 0) // Read raw FMD Altro data 
 };
 
index 649a17f..fcb7d44 100644 (file)
 #include "AliFMDParameters.h"  // ALIFMDPARAMETERS_H
 #include "AliFMDDigit.h"       // ALIFMDDIGIT_H
 #include "AliFMDRawWriter.h"   // ALIFMDRAWREADER_H 
+#include "AliFMDAltroMapping.h" // ALIFMDALTROMAPPING_H
+#include "AliFMDAltroIO.h"      // ALIFMDALTROWRITER_H
 #include <TArrayI.h>           // ROOT_TArrayI
 #include <TClonesArray.h>      // ROOT_TClonesArray
+#include <fstream>
 
 //____________________________________________________________________
 ClassImp(AliFMDRawWriter)
@@ -136,145 +139,238 @@ AliFMDRawWriter::Exec(Option_t*)
   }
   digitBranch->SetAddress(&digits);
   
-  AliFMDParameters* pars = AliFMDParameters::Instance();
   Int_t nEvents = Int_t(digitTree->GetEntries());
   for (Int_t event = 0; event < nEvents; event++) {
     fFMD->ResetDigits();
     digitTree->GetEvent(event);
     
-    Int_t nDigits = digits->GetEntries();
-    if (nDigits < 1) continue;
+    // Write out the digits
+    WriteDigits(digits);
+  }
+  loader->UnloadDigits();
+}
 
+//____________________________________________________________________
+void
+AliFMDRawWriter::WriteDigits(TClonesArray* digits)
+{
+  Int_t nDigits = digits->GetEntries();
+  if (nDigits < 1) return;
 
-    UShort_t prevDetector = 0;
-    Char_t   prevRing     = '\0';
-    UShort_t prevSector   = 0;
-    // UShort_t prevStrip    = 0;
+  AliFMDParameters*  pars    = AliFMDParameters::Instance();
+  AliFMDAltroWriter* writer  = 0;
+  Int_t          sampleRate  = -1;
+  UShort_t       hwaddr      = 0;
+  UShort_t       ddl         = 0;
+  std::ofstream* file        = 0;
+  Int_t          ret         = 0;
+  for (Int_t i = 0; i < nDigits; i++) {
+    // Get the digit
+    AliFMDDigit* digit = static_cast<AliFMDDigit*>(digits->At(i));
+    UInt_t   thisDDL, thisHwaddr;
+    UShort_t det    = digit->Detector();
+    Char_t   ring   = digit->Ring();
+    UShort_t sector = digit->Sector();
+    UShort_t strip  = digit->Strip();
+    if (!pars->Detector2Hardware(det,ring,sector,strip,thisDDL,thisHwaddr)) {
+      AliError(Form("Failed to get hardware address for FMD%d%c[%2d,%3d]",
+                   det, ring, sector, strip));
+      continue;
+    }
+    AliDebug(40, Form("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] "
+                      "(board 0x%x, chip 0x%x, channel 0x%x)",
+                      thisHwaddr, det, ring, sector, strip, 
+                      (thisHwaddr >> 7), (thisHwaddr >> 4) & 0x7, 
+                      thisHwaddr & 0xf));
+      if (writer) writer->AddChannelTrailer(hwaddr);
+      hwaddr = thisHwaddr;
+    }
+    // Check if we're still in the same detector (DDL)
+    if (ddl != thisDDL) {
+      if (writer) {
+       AliDebug(1, Form("Closing altro writer %p", writer));
+       if ((ret = writer->Close()) < 0) {
+         AliError(Form("Error: %s", writer->ErrorString(ret)));
+         return;
+       }
+       delete writer;
+       writer = 0;
+       file->close();
+       delete file;
+       file = 0;
+      }
+      ddl = thisDDL;
+    }
+    // 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));
+      if (!file || !*file) {
+       AliFatal(Form("Failed to open file FMD_%d.ddl", ddl));
+       return;
+      }
+      writer  = new AliFMDAltroWriter(*file);
+      writer->SetThreshold(pars->GetZeroSuppression(det, ring, sector, strip));
+      sampleRate = pars->GetSampleRate(ddl);
+    }
+    // Write out our signal
+    writer->AddSignal(digit->Count1());
+    if (sampleRate >= 2) writer->AddSignal(digit->Count2());
+    if (sampleRate >= 3) writer->AddSignal(digit->Count3());
+  }
+  if (writer) {
+    writer->AddChannelTrailer(hwaddr);
+    writer->Close();
+    delete writer;
+    file->close();
+    delete file;
+  }
+}
 
-    // The first seen strip number for a channel 
-    UShort_t startStrip   = 0;
+      
     
-    // Which channel number in the ALTRO channel we're at 
-    UShort_t offset       = 0;
+#if 0
+//____________________________________________________________________
+void
+AliFMDRawWriter::WriteDigits(TClonesArray* digits)
+{
+  Int_t nDigits = digits->GetEntries();
+  if (nDigits < 1) return;
 
-    // How many times the ALTRO Samples one VA1_ALICE channel 
-    Int_t sampleRate = 1;
+  AliFMDParameters* pars = AliFMDParameters::Instance();
+  UShort_t prevDetector = 0;
+  Char_t   prevRing     = '\0';
+  UShort_t prevSector   = 0;
+  // UShort_t prevStrip    = 0;
+  
+  // The first seen strip number for a channel 
+  UShort_t startStrip   = 0;
+  
+  // Which channel number in the ALTRO channel we're at 
+  UShort_t offset       = 0;
+  
+  // How many times the ALTRO Samples one VA1_ALICE channel 
+  Int_t sampleRate = 1;
+  
+  // A buffer to hold 1 ALTRO channel - Normally, one ALTRO channel
+  // holds 128 VA1_ALICE channels, sampled at a rate of `sampleRate' 
+  TArrayI channel(fChannelsPerAltro * sampleRate);
 
-    // A buffer to hold 1 ALTRO channel - Normally, one ALTRO channel
-    // holds 128 VA1_ALICE channels, sampled at a rate of `sampleRate' 
-    TArrayI channel(fChannelsPerAltro * sampleRate);
-    
-    // The Altro buffer 
-    AliAltroBuffer* altro = 0;
+  // The Altro buffer 
+  AliAltroBuffer* altro = 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. 
-    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();
-      fThreshold      = pars->GetZeroSuppression(det, ring, sector, strip);
-      if (det != prevDetector) {
-       AliDebug(15, Form("FMD: New DDL, was %d, now %d",
-                         AliFMDParameters::kBaseDDL + prevDetector - 1,
-                         AliFMDParameters::kBaseDDL + det - 1));
-       // 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("New altro: Write channel at %d Strip: %d "
-                           "Sector: %d  Ring: %d", 
-                           i, startStrip, prevSector, prevRing));
-         // TPC to FMD translations 
-         // 
-         //    TPC                FMD
-         //    ----------+-----------
-         //    pad       |      strip
-         //    row       |     sector
-         //    sector    |       ring
-         // 
-         WriteChannel(altro, startStrip, prevSector, prevRing, channel);
-         altro->Flush();
-         altro->WriteDataHeader(kFALSE, kFALSE);
-         delete altro;
-         altro = 0;
-       }
-
-       prevDetector = det;
-       // Need to open a new DDL! 
-       Int_t ddlId = AliFMDParameters::kBaseDDL + det - 1;
-       TString filename(Form("%s_%d.ddl", fFMD->GetName(),  ddlId));
+  // 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. 
+  for (Int_t i = 0; i < nDigits; i++) {
+    // Get the digit
+    AliFMDDigit* digit = static_cast<AliFMDDigit*>(digits->At(i));
 
-       AliDebug(15, Form("New altro buffer with DDL file %s", 
-                         filename.Data()));
-       AliDebug(15, Form("New altro at %d", i));
-       // Create a new altro buffer - a `1' as the second argument
-       // means `write mode' 
-       altro = new AliAltroBuffer(filename.Data(), 1);
-       
-       // 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);
-
-       // Figure out the sample rate 
-       if (fSampleRate > 0) sampleRate = fSampleRate;
-       else {
-         if (digit->Count2() >= 0) sampleRate = 2;
-         if (digit->Count3() >= 0) sampleRate = 3;
-       }
-
-       channel.Set(fChannelsPerAltro * sampleRate);
-       offset     = 0;
-       prevRing   = ring;
-       prevSector = sector;
-       startStrip = strip;
-      }
-      else if (offset == fChannelsPerAltro
-              || digit->Ring() != prevRing 
-              || digit->Sector() != prevSector) {
-       // Force a new Altro channel
-       AliDebug(15, Form("Flushing channel to disk because %s",
-                         (offset == fChannelsPerAltro ? "channel is full" :
-                          (ring != prevRing ? "new ring up" :
-                           "new sector up"))));
-       AliDebug(15, Form("New Channel: Write channel at %d Strip: %d "
+    UShort_t det    = digit->Detector();
+    Char_t   ring   = digit->Ring();
+    UShort_t sector = digit->Sector();
+    UShort_t strip  = digit->Strip();
+    fThreshold      = pars->GetZeroSuppression(det, ring, sector, strip);
+    if (det != prevDetector) {
+      AliDebug(15, Form("FMD: New DDL, was %d, now %d",
+                       AliFMDParameters::kBaseDDL + prevDetector - 1,
+                       AliFMDParameters::kBaseDDL + det - 1));
+      // 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("New altro: Write channel at %d Strip: %d "
                          "Sector: %d  Ring: %d", 
                          i, startStrip, prevSector, prevRing));
+       // TPC to FMD translations 
+       // 
+       //    TPC                FMD
+       //    ----------+-----------
+       //    pad       |      strip
+       //    row       |     sector
+       //    sector    |       ring
+       // 
        WriteChannel(altro, startStrip, prevSector, prevRing, channel);
-       // Reset and update channel variables 
-       channel.Reset(0);
-       offset     = 0; 
-       startStrip = strip;
-       prevRing   = ring;
-       prevSector = sector;
+       altro->Flush();
+       altro->WriteDataHeader(kFALSE, kFALSE);
+       delete altro;
+       altro = 0;
+      }
+      prevDetector = det;
+      // Need to open a new DDL! 
+      Int_t ddlId = AliFMDParameters::kBaseDDL + det - 1;
+      TString filename(Form("%s_%d.ddl", fFMD->GetName(),  ddlId));
+      
+      AliDebug(15, Form("New altro buffer with DDL file %s", 
+                       filename.Data()));
+      AliDebug(15, Form("New altro at %d", i));
+      // Create a new altro buffer - a `1' as the second argument
+      // means `write mode' 
+      altro = new AliAltroBuffer(filename.Data(), 1);
+      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);
+      
+      // Figure out the sample rate 
+      if (fSampleRate > 0) sampleRate = fSampleRate;
+      else {
+       if (digit->Count2() >= 0) sampleRate = 2;
+       if (digit->Count3() >= 0) sampleRate = 3;
       }
 
-      // Store the counts of the ADC in the channel buffer 
-      channel[offset * sampleRate] = digit->Count1();
-      if (sampleRate > 1) 
-       channel[offset * sampleRate + 1] = digit->Count2();
-      if (sampleRate > 2) 
-       channel[offset * sampleRate + 2] = digit->Count3();
-      offset++;
+      channel.Set(fChannelsPerAltro * sampleRate);
+      offset     = 0;
+      prevRing   = ring;
+      prevSector = sector;
+      startStrip = strip;
     }
-    // Finally, we need to close the final ALTRO buffer if it wasn't
-    // already 
-    if (altro) {
-      altro->Flush();
-      altro->WriteDataHeader(kFALSE, kFALSE);
-      delete altro;
+    else if (offset == fChannelsPerAltro
+            || digit->Ring() != prevRing 
+            || digit->Sector() != prevSector) {
+      // Force a new Altro channel
+      AliDebug(15, Form("Flushing channel to disk because %s",
+                       (offset == fChannelsPerAltro ? "channel is full" :
+                        (ring != prevRing ? "new ring up" :
+                         "new sector up"))));
+      AliDebug(15, Form("New Channel: Write channel at %d Strip: %d "
+                       "Sector: %d  Ring: %d", 
+                       i, startStrip, prevSector, prevRing));
+      WriteChannel(altro, startStrip, prevSector, prevRing, channel);
+      // Reset and update channel variables 
+      channel.Reset(0);
+      offset     = 0; 
+      startStrip = strip;
+      prevRing   = ring;
+      prevSector = sector;
     }
+    
+    // Store the counts of the ADC in the channel buffer 
+    channel[offset * sampleRate] = digit->Count1();
+    if (sampleRate > 1) 
+      channel[offset * sampleRate + 1] = digit->Count2();
+    if (sampleRate > 2) 
+      channel[offset * sampleRate + 2] = digit->Count3();
+    offset++;
+  }
+  // Finally, we need to close the final ALTRO buffer if it wasn't
+  // already 
+  if (altro) {
+    altro->Flush();
+    altro->WriteDataHeader(kFALSE, kFALSE);
+    delete altro;
   }
-  loader->UnloadDigits();
 }
+#endif
 
 //____________________________________________________________________
 void
index 0d142a9..8191456 100644 (file)
@@ -22,7 +22,7 @@
 class AliFMD;
 class AliAltroBuffer;
 class TArrayI;
-
+class TClonesArray;
 
 //____________________________________________________________________
 class AliFMDRawWriter : public TTask 
@@ -33,6 +33,7 @@ public:
 
   virtual void Exec(Option_t* option="");
 protected:
+  virtual void WriteDigits(TClonesArray* digits);
   virtual void WriteChannel(AliAltroBuffer* altro, 
                            UShort_t strip, UShort_t sector, Char_t ring, 
                            const TArrayI& data);
index b78398b..c30a7c8 100644 (file)
@@ -198,8 +198,6 @@ AliFMDReconstructor::Init(AliRunLoader* runLoader)
     Warning("Init", "No generator event header - "
            "perhaps we get the vertex from ESD?");
   }
-  // Get the ESD tree 
-  SetESD(new AliESD);
 }
 
 //____________________________________________________________________
@@ -224,7 +222,7 @@ AliFMDReconstructor::Reconstruct(TTree* digitsTree,
   // FIXME: The vertex may not be known yet, so we may have to move
   // some of this to FillESD. 
   AliDebug(1, "Reconstructing from digits in a tree");
-#if 0
+#if 1
   if (fESD) {
     const AliESDVertex* vertex = fESD->GetVertex();
     if (vertex) {
index 0c8efec..a8c16c2 100644 (file)
@@ -25,6 +25,9 @@
 #pragma link C++ class  AliFMDCalibGain+;
 #pragma link C++ class  AliFMDCalibSampleRate+;
 #pragma link C++ class  AliFMDAltroMapping+;
+#pragma link C++ class  AliFMDAltroIO+;
+#pragma link C++ class  AliFMDAltroReader+;
+#pragma link C++ class  AliFMDAltroWriter+;
 
 #else
 # error Not for compilation 
index d52a693..efc5aa8 100644 (file)
 void 
 Reconstruct()
 {
-  AliLog::SetModuleDebugLevel("FMD", 1);
+  AliCDBManager* cdb = AliCDBManager::Instance();
+  cdb->SetDefaultStorage("local://cdb");
+  AliLog::SetModuleDebugLevel("FMD", 2);
   AliReconstruction rec;   
   rec.SetRunLocalReconstruction("FMD");
   rec.SetRunVertexFinder(kFALSE);
   rec.SetRunTracking(""); 
   rec.SetFillESD("FMD"); 
-  // rec.SetInput("./");
+  rec.SetInput("./");
   rec.Run(); 
 }
 
index bb66d05..970442b 100644 (file)
 void
 Simulate()
 {
- AliSimulation sim;
- sim.SetConfigFile("$(ALICE_ROOT)/FMD/Config.C");
- // sim.SetMakeSDigits("FMD");
- sim.SetMakeDigits("FMD");
- sim.SetWriteRawData("FMD");
- // sim.SetMakeDigitsFromHits("FMD");
- TStopwatch w;
- w.Start();
- sim.Run(1); 
- w.Stop();
- w.Print();
+  AliCDBManager* cdb = AliCDBManager::Instance();
+  cdb->SetDefaultStorage("local://cdb");
+  AliSimulation sim;
+  AliCDBEntry* align = cdb->Get("FMD/Align/Data");
+  if (align) {
+    TClonesArray* array = dynamic_cast<TClonesArray*>(align->GetObject());
+    if (array) sim.SetAlignObjArray(array);
+  }
+  sim.SetConfigFile("$(ALICE_ROOT)/FMD/Config.C");
+  // sim.SetMakeSDigits("FMD");
+  sim.SetMakeDigits("FMD"); 
+  sim.SetWriteRawData("FMD"); 
+  // sim.SetMakeDigitsFromHits("FMD"); 
+  TStopwatch w; 
+  w.Start(); 
+  sim.Run(1);  
+  w.Stop(); 
+  w.Print(); 
 }
 
 //
index 9cb54e1..0db92fa 100644 (file)
@@ -9,6 +9,7 @@ SRCS            =  AliFMDDigit.cxx              \
                   AliFMDCalibGain.cxx          \
                   AliFMDCalibSampleRate.cxx    \
                   AliFMDAltroMapping.cxx       \
+                  AliFMDAltroIO.cxx            \
                   AliFMDParameters.cxx         \
                   AliFMDGeometry.cxx           \
                   AliFMDRing.cxx               \
diff --git a/FMD/scripts/ApplyAlignment.C b/FMD/scripts/ApplyAlignment.C
new file mode 100644 (file)
index 0000000..9b72126
--- /dev/null
@@ -0,0 +1,41 @@
+//____________________________________________________________________
+//
+// $Id$
+//
+// Read in the geometry, and get alignment data from CDB, and  apply
+// that to the geometry. 
+//
+void
+ApplyAlignment()
+{
+  gSystem->Load("libFMDutil.so");
+  TGeoManager::Import("geometry.root");
+
+  AliCDBManager* cdb   = AliCDBManager::Instance();
+  cdb->SetDefaultStorage("local://cdb");
+  AliCDBEntry*   align = cdb->Get("FMD/Align/Data");
+  if (align) {
+    Info("ApplyAlignment","Got alignment data from CDB");
+    TClonesArray* array = dynamic_cast<TClonesArray*>(align->GetObject());
+    if (!array) {
+      Warning("ApplyAlignement", "Invalid align data from CDB");
+    }
+    else {
+      Int_t nAlign = array->GetEntries();
+      for (Int_t i = 0; i < nAlign; i++) {
+       AliAlignObjAngles* a = static_cast<AliAlignObjAngles*>(array->At(i));
+       if (!a->ApplyToGeometry()) {
+         Warning("ApplyAlignement", "Failed to apply alignment to %s", 
+                 a->GetVolPath());
+       }
+      }
+    }
+  }
+  TCanvas* c = new TCanvas("Geometry", "Geometry");
+  c->SetFillColor(1);
+  gGeoManager->GetTopVolume()->Draw();
+}
+//____________________________________________________________________
+//
+// EOF
+// 
diff --git a/FMD/scripts/Convert2Raw.C b/FMD/scripts/Convert2Raw.C
new file mode 100644 (file)
index 0000000..8d5c36d
--- /dev/null
@@ -0,0 +1,26 @@
+//____________________________________________________________________
+//
+// $Id$
+//
+// Read in digits, and convert them to raw data files.  This is mainly
+// for testing. 
+//
+void
+Convert2Raw()
+{
+  AliRunLoader* runLoader = 
+    AliRunLoader::Open("galice.root", "Alice", "read");
+  runLoader->LoadgAlice();
+  AliRun* run = runLoader->GetAliRun();
+  AliLoader* fmdLoader = runLoader->GetLoader("FMDLoader");
+  AliFMD* fmd = static_cast<AliFMD*>(run->GetDetector("FMD"));
+  AliLog::SetModuleDebugLevel("FMD", 1);
+
+  AliFMDParameters::Instance()->Init();
+  AliFMDRawWriter rw(fmd);
+  rw.Exec();
+}
+//____________________________________________________________________
+// 
+// EOF
+//
index a0c38dc..0d0c355 100644 (file)
@@ -7,6 +7,8 @@
 void
 DisplayHits()
 {
+  AliCDBManager* cdb = AliCDBManager::Instance();
+  cdb->SetDefaultStorage("local://cdb");
   gSystem->Load("libFMDutil.so");
   AliFMDDisplay* d = new AliFMDDisplay;
   d->AddLoad(AliFMDInput::kHits);
diff --git a/FMD/scripts/MakeAlignment.C b/FMD/scripts/MakeAlignment.C
new file mode 100644 (file)
index 0000000..69f669c
--- /dev/null
@@ -0,0 +1,25 @@
+//____________________________________________________________________
+//
+// $Id$
+//
+// Make fake alignment data.
+//
+void
+MakeAlignment()
+{
+  if (!TGeoManager::Import("geometry.root")) 
+    gAlice->Init("$ALICE_ROOT/FMD/Config.C");
+  AliCDBManager* cdb   = AliCDBManager::Instance();
+  cdb->SetDefaultStorage("local://cdb");
+
+  gSystem->Load("libFMDutil.so");
+  AliFMDAlignFaker f;
+  f.RemoveAlign(AliFMDAlignFaker::kHalves);
+  f.SetSensorDisplacement(0,0,0,0,0,0);
+  f.SetSensorRotation(0,0,0,0,0,0);
+  f.Exec();
+}
+//____________________________________________________________________
+//
+// EOF
+//
index 63fb470..94ec56f 100644 (file)
@@ -47,7 +47,7 @@ RawTest()
     return 0;
   }
   AliFMDRawStream input(reader, sampleRate);
-  reader->Select(AliFMD::kBaseDDL >> 8);
+  reader->Select(AliFMDParameters::kBaseDDL >> 8);
   
   Int_t    oldDDL      = -1;
   Int_t    count       = 0;
index d610cb0..2a55719 100644 (file)
@@ -8,7 +8,8 @@
 void 
 ShowRaw(Int_t det=2,  bool verbose=false, Int_t event=0) 
 {
-  TString file(Form("raw%d/FMD_%d.ddl", event, AliFMD::kBaseDDL + det - 1));
+  TString file(Form("raw%d/FMD_%d.ddl", event, 
+                   AliFMDParameters::kBaseDDL + det - 1));
 
   std::cout << "Reading raw data file " << file << std::endl;
   
@@ -26,9 +27,9 @@ ShowRaw(Int_t det=2,  bool verbose=false, Int_t event=0)
   Int_t numWords,padNum,rowNum,secNum=0;
   Int_t value = 0;
   Int_t zero  = 0;
-  // if (!buff.ReadDataHeader()) {
-  // std::cout<< file << " isn't a valid data file!" << std::endl;
-  // }
+  if (!buff.ReadDataHeader()) {
+    std::cout<< file << " isn't a valid data file!" << std::endl;
+  }
   
   while(buff.ReadTrailerBackward(numWords,padNum,rowNum,secNum)){
     if (verbose) 
index 3b7efed..2fe855e 100644 (file)
@@ -50,8 +50,8 @@ CheckTrans(UShort_t det, Char_t ring, UShort_t sec, UShort_t str,
     Waring("TestHWMap", "Ring Id differ %c != %c", ring, oring);  
   if (sec != osec) 
     Warning("TestHWMap", "Sector # differ %d != %d", sec, osec);
-  if (str != ostr) 
-    Warning("TestHWMap", "Strip # differ %d != %d", str, ostr);
+  if ((str / 128) * 128 != ostr) 
+    Warning("TestHWMap", "Strip # differ %d != %d", (str / 128) * 128, ostr);
 }
 
 //____________________________________________________________________
@@ -59,14 +59,17 @@ void
 TestHWMap()
 {
   AliFMDParameters* param = AliFMDParameters::Instance();
+  param->Init();
+  AliLog::SetModuleDebugLevel("FMD", 1);
   
-  for (UShort_t det = 2; det <= 2; det++) {
+  UInt_t oldddl = 0, oldhwaddr = 0xFFFFFFFF;
+  for (UShort_t det = 1; det <= 3; det++) {
     for (UShort_t rng = 0; rng < 2; rng++) {
       Char_t ring = (rng == 0 ? 'I' : 'O');
       Int_t  nsec = (ring == 'I' ?  20 :  40);
       Int_t  nstr = (ring == 'I' ? 512 : 256);
       for (UShort_t sec = 0; sec < nsec; sec++) {
-       for (UShort_t str = 0; str < nstr; str += 128) {
+       for (UShort_t str = 0; str < nstr; str ++) {
          UInt_t ddl, hwaddr;
          if (!param->Detector2Hardware(det, ring, sec, str, ddl, hwaddr)) {
            Warning("TestHWMap", "detector to hardware failed on %s", 
@@ -80,7 +83,11 @@ TestHWMap()
                    Addr2Str(ddl, hwaddr));
            continue;
          }
-         PrintTrans(det,ring,sec,str,ddl,hwaddr,odet,oring,osec,ostr);
+         if (oldddl != ddl || oldhwaddr != hwaddr) {
+           PrintTrans(det,ring,sec,str,ddl,hwaddr,odet,oring,osec,ostr);
+           oldddl    = ddl;
+           oldhwaddr = hwaddr;
+         }
          CheckTrans(det,ring,sec,str,odet,oring,osec,ostr);
        }// Loop over strips
       } // Loop over sectors
diff --git a/FMD/scripts/TestRawIO.C b/FMD/scripts/TestRawIO.C
new file mode 100644 (file)
index 0000000..cb517cf
--- /dev/null
@@ -0,0 +1,33 @@
+//____________________________________________________________________
+//
+// $Id$
+//
+// Test of AliFMDAltro{Reader,Writer}
+//
+void
+TestRawIO()
+{
+  std::ofstream ofile("foo.dat");
+  AliFMDAltroWriter w(ofile);
+  for (size_t i = 0; i < 16; i++) 
+    w.AddSignal((i << 4)  + i);
+  w.AddChannelTrailer(0xabe);
+  w.Close();
+  ofile.close();
+
+  std::ifstream ifile("foo.dat");
+  AliRawDataHeader h;
+  ifile.read((char*)&h, sizeof(h));
+  AliFMDAltroReader r(ifile);
+  UShort_t hwaddr, last;
+  UShort_t data[1024];
+  int ret = r.ReadChannel(hwaddr, last, data);
+  printf("Read returned %d, w/addr=0x%x, last=%d\n", ret, hwaddr, last);
+  if (ret < 0) return;
+  for (size_t i = 0; i < last; i++)
+    std::cout << i << "\t0x" << std::hex << data[i] << std::endl;
+}
+//____________________________________________________________________
+//
+// EOF
+//