]> git.uio.no Git - u/mrichter/AliRoot.git/blobdiff - HLT/TPCLib/AliHLTTPCHWCFSpacePointContainer.cxx
code cleanup, removing unused functionality; fully implemented in the AliHLTTPCDataCo...
[u/mrichter/AliRoot.git] / HLT / TPCLib / AliHLTTPCHWCFSpacePointContainer.cxx
index a6511fdb2f6bb7915608ffa319ba9fa81a919618..1f9eed51838d72a3a0dda2a5d2bb700072716e07 100644 (file)
@@ -25,7 +25,6 @@
 ///         be merged with it in a generic way
 
 #include "AliHLTTPCHWCFSpacePointContainer.h"
-#include "AliHLTTPCDataCompressionComponent.h"
 #include "AliHLTErrorGuard.h"
 #include "AliHLTTPCDefinitions.h"
 #include "AliHLTTPCSpacePointData.h"
 #include "AliHLTTemplates.h"
 #include "AliHLTDataDeflater.h"
 #include "AliRawDataHeader.h"
+#include "AliLog.h"
 #include "TMath.h"
 #include <memory>
 #include <algorithm>
 #include <cmath>
+#include <iostream>
+#include <sstream>
+#include <iomanip>
+
 
 /** ROOT macro for the implementation of ROOT specific class methods */
 ClassImp(AliHLTTPCHWCFSpacePointContainer)
 
-AliHLTTPCHWCFSpacePointContainer::AliHLTTPCHWCFSpacePointContainer()
+AliHLTTPCHWCFSpacePointContainer::AliHLTTPCHWCFSpacePointContainer(int mode)
   : AliHLTSpacePointContainer()
   , fClusters()
   , fSelections()
-  , fDecoders()
+  , fBlocks()
+  , fSingleBlock()
+  , fMode(mode)
+  , fWrittenClusterIds(NULL)
 {
   // see header file for class documentation
   // or
   // refer to README to build package
   // or
   // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
+  if (fMode&kModeSingle) {
+    fSingleBlock.SetDecoder(new AliHLTTPCHWCFData);
+    fSingleBlock.SetGrid(AllocateIndexGrid());
+  }
 }
 
 AliHLTTPCHWCFSpacePointContainer::AliHLTTPCHWCFSpacePointContainer(const AliHLTTPCHWCFSpacePointContainer& c)
   : AliHLTSpacePointContainer(c)
   , fClusters(c.fClusters.begin(), c.fClusters.end())
   , fSelections()
-  , fDecoders()
+  , fBlocks()
+  , fSingleBlock()
+  , fMode(c.fMode)
+  , fWrittenClusterIds(NULL)
 {
   /// copy constructor
 }
@@ -71,6 +85,8 @@ AliHLTTPCHWCFSpacePointContainer& AliHLTTPCHWCFSpacePointContainer::operator=(co
   if (&c==this) return *this;
   AliHLTSpacePointContainer::operator=(c);
   fClusters=c.fClusters;
+  fMode=c.fMode;
+  fWrittenClusterIds=NULL;
 
   return *this;
 }
@@ -79,12 +95,16 @@ AliHLTTPCHWCFSpacePointContainer::~AliHLTTPCHWCFSpacePointContainer()
 {
   // destructor
   Clear();
+  if (fSingleBlock.GetDecoder()) delete fSingleBlock.GetDecoder();
+  if (fSingleBlock.GetGrid()) delete fSingleBlock.GetGrid();
+  if (fWrittenClusterIds) delete fWrittenClusterIds;
 }
 
 int AliHLTTPCHWCFSpacePointContainer::AddInputBlock(const AliHLTComponentBlockData* pDesc)
 {
   // add input block to the collection
   if (!pDesc) return -EINVAL;
+  int iResult=0;
   int count=0;
   if (pDesc->fDataType!=AliHLTTPCDefinitions::fgkHWClustersDataType) {
     HLTWarning("ignoring data block of type %s", AliHLTComponent::DataType2Text(pDesc->fDataType).c_str());
@@ -93,46 +113,175 @@ int AliHLTTPCHWCFSpacePointContainer::AddInputBlock(const AliHLTComponentBlockDa
   if (!pDesc->fPtr) return -ENODATA;
   if (pDesc->fSize<=sizeof(AliRawDataHeader)) return 0;
 
-  AliHLTUInt32_t *buffer=reinterpret_cast<AliHLTUInt32_t*>(pDesc->fPtr);  
+  AliHLTUInt8_t slice = AliHLTTPCDefinitions::GetMinSliceNr( pDesc->fSpecification );
+  AliHLTUInt8_t part  = AliHLTTPCDefinitions::GetMinPatchNr( pDesc->fSpecification );
+
+  AliHLTUInt32_t decoderIndex=AliHLTTPCSpacePointData::GetID(slice, part, 0);
+
+  AliHLTUInt32_t *buffer=reinterpret_cast<AliHLTUInt32_t*>(pDesc->fPtr);
   // skip the first 8 32-bit CDH words
   buffer += 8;
   UInt_t bufferSize32 = ((Int_t)pDesc->fSize - sizeof(AliRawDataHeader) )/sizeof(AliHLTUInt32_t);
 
-  std::auto_ptr<AliHLTTPCHWCFData> pDecoder(new AliHLTTPCHWCFData);
-  if (!pDecoder.get()) return -ENOMEM;
+  AliHLTTPCHWCFData* pDecoder=NULL;
+  AliHLTSpacePointPropertyGrid* pGrid=NULL;
+  if (fMode&kModeSingle) {
+    pDecoder=fSingleBlock.GetDecoder();
+    pGrid=fSingleBlock.GetGrid();
+  } else {
+    if (fBlocks.find(decoderIndex)!=fBlocks.end()) {
+      HLTError("data block of slice %d partition %d already added, skipping data block", slice, part);
+      return -EEXIST;
+    }
+  }
+
+  if (!pDecoder) {
+    pDecoder=new AliHLTTPCHWCFData;
+    if (!pDecoder) return -ENOMEM;
+  }
 
   if (pDecoder->Init(reinterpret_cast<AliHLTUInt8_t*>(buffer), bufferSize32*sizeof(AliHLTUInt32_t))<0 ||
-      (pDecoder->CheckVersion()<0 && (int)bufferSize32>pDecoder->GetRCUTrailerSize())) {
+      (pDecoder->CheckVersion()<0 && (int)(bufferSize32*sizeof(AliHLTUInt32_t))>pDecoder->GetRCUTrailerSize())) {
     HLTError("data block of type %s corrupted: can not decode format",
             AliHLTComponent::DataType2Text(pDesc->fDataType).c_str());
     return -EBADMSG;
   }
 
-  UInt_t nofClusters=pDecoder->GetNumberOfClusters();
+  if (fMode&kModeSingle && !pGrid) {
+    pGrid=AllocateIndexGrid();
+    if (!pGrid) {
+      delete pDecoder;
+      return -ENOMEM;
+    }
+  }
 
-  AliHLTUInt8_t minslice = AliHLTTPCDefinitions::GetMinSliceNr( pDesc->fSpecification );
-  AliHLTUInt8_t minpart  = AliHLTTPCDefinitions::GetMinPatchNr( pDesc->fSpecification );
+  if (fMode&kModeCreateMap) { // register immediately
+  UInt_t nofClusters=pDecoder->GetNumberOfClusters();
 
   for (UInt_t i=0; i<nofClusters; i++) {
     AliHLTUInt32_t clusterID=~(AliHLTUInt32_t)0;
     // cluster ID from slice, partition and index
-    clusterID=AliHLTTPCSpacePointData::GetID(minslice, minpart, i);
+    clusterID=AliHLTTPCSpacePointData::GetID(slice, part, i);
 
     if (fClusters.find(clusterID)==fClusters.end()) {
       // new cluster
-      fClusters[clusterID]=AliHLTTPCHWCFSpacePointProperties(pDecoder.get(), i);
+      fClusters[clusterID]=AliHLTTPCHWCFSpacePointProperties(pDecoder, i);
       count++;
     } else {
       HLTError("cluster with ID 0x%08x already existing, skipping cluster %d of data block 0x%08x",
               clusterID, i, pDesc->fSpecification);
     }
   }
+  }
 
-  fDecoders.push_back(pDecoder.release());
+  if (pGrid && (iResult=PopulateAccessGrid(pGrid, pDecoder, slice, part))<0) {
+    HLTError("failed to populate access grid for block %s 0x%09x: %d",
+            AliHLTComponent::DataType2Text(pDesc->fDataType).c_str(), pDesc->fSpecification, iResult);
+    return iResult;
+  }
 
+  if (fMode&kModeSingle) {
+    fSingleBlock.SetDecoder(pDecoder);
+    fSingleBlock.SetGrid(pGrid);
+    fSingleBlock.SetId(decoderIndex);
+  } else {
+    fBlocks[decoderIndex]=AliHLTTPCHWCFSpacePointBlock(decoderIndex, pDecoder, pGrid);
+  }
   return count;
 }
 
+AliHLTSpacePointContainer::AliHLTSpacePointPropertyGrid* AliHLTTPCHWCFSpacePointContainer::AllocateIndexGrid()
+{
+  // allocate index grid, one single point to define the dimensions
+  
+  // max 33 padrows, step 1 padrow
+  // max 140 pads, step 2x max delta pad
+  // max 1024 time bins, step 2x max delta time
+  return new AliHLTSpacePointPropertyGrid(33, 1.0,
+                                         140, 2*AliHLTTPCDefinitions::GetMaxClusterDeltaPad(),
+                                         1024, 2*AliHLTTPCDefinitions::GetMaxClusterDeltaTime()
+                                         );
+}
+
+int AliHLTTPCHWCFSpacePointContainer::PopulateAccessGrid(AliHLTSpacePointPropertyGrid* pGrid, AliHLTUInt32_t mask) const
+{
+  // populate an access grid
+  if (!pGrid) return -EINVAL;
+
+  pGrid->Clear();
+  
+  AliHLTUInt8_t slice = AliHLTTPCDefinitions::GetMinSliceNr(mask);
+  AliHLTUInt8_t partition  = AliHLTTPCDefinitions::GetMinPatchNr(mask);
+  AliHLTUInt32_t decoderIndex=AliHLTTPCSpacePointData::GetID(slice, partition, 0);
+  std::map<AliHLTUInt32_t, AliHLTTPCHWCFSpacePointBlock>::const_iterator block=fBlocks.find(decoderIndex);
+  if (block==fBlocks.end()) {
+    HLTError("can not find data block of id 0x%08x", mask);
+    return -ENOENT;
+  }
+  return PopulateAccessGrid(pGrid, block->second.GetDecoder(), slice, partition);
+}
+
+int AliHLTTPCHWCFSpacePointContainer::PopulateAccessGrid(AliHLTSpacePointPropertyGrid* pGrid, AliHLTTPCHWCFData* pDecoder,
+                                                        int slice, int partition) const
+{
+  // populate an access grid
+  if (!pDecoder) return -EINVAL;
+  int iResult=0;
+
+  if (pDecoder->GetNumberOfClusters()==0) return 0;
+  AliHLTTPCHWCFData::iterator cl=pDecoder->begin();
+  for (; cl!=pDecoder->end(); ++cl) {
+    iResult=pGrid->CountSpacePoint(cl.GetPadRow(), cl.GetPad(), cl.GetTime());
+    if (iResult<0)
+      HLTError("CountSpacePoint %f %f %f failed: %d", cl.GetPadRow(), cl.GetPad(), cl.GetTime(), iResult);
+  }
+  
+  int count=0;
+  cl=pDecoder->begin();
+  for (; cl!=pDecoder->end(); ++cl, count++) {
+    AliHLTUInt32_t id=AliHLTTPCSpacePointData::GetID(slice, partition, count);
+    iResult=pGrid->AddSpacePoint(AliHLTSpacePointProperties(id), cl.GetPadRow(), cl.GetPad(), cl.GetTime());
+    if (iResult<0)
+      HLTError("AddSpacePoint 0x%08x %f %f %f failed: %d", id, cl.GetPadRow(), cl.GetPad(), cl.GetTime(), iResult);
+  }
+
+  return 0;
+}
+
+const AliHLTSpacePointContainer::AliHLTSpacePointPropertyGrid* AliHLTTPCHWCFSpacePointContainer::GetSpacePointPropertyGrid(AliHLTUInt32_t mask) const
+{
+  // get the access grid for a data block
+  AliHLTUInt8_t slice = AliHLTTPCDefinitions::GetMinSliceNr(mask);
+  AliHLTUInt8_t part  = AliHLTTPCDefinitions::GetMinPatchNr(mask);
+  AliHLTUInt32_t decoderIndex=AliHLTTPCSpacePointData::GetID(slice, part, 0);
+  std::map<AliHLTUInt32_t, AliHLTTPCHWCFSpacePointBlock>::const_iterator block=fBlocks.find(decoderIndex);
+  if (block==fBlocks.end()) {
+    HLTError("can not find data block of id 0x%08x", mask);
+    return NULL;
+  }
+  return block->second.GetGrid();
+}
+
+int AliHLTTPCHWCFSpacePointContainer::SetSpacePointPropertyGrid(AliHLTUInt32_t mask, AliHLTSpacePointContainer::AliHLTSpacePointPropertyGrid* pGrid)
+{
+  // set the access grid for a data block
+  AliHLTUInt8_t slice = AliHLTTPCDefinitions::GetMinSliceNr(mask);
+  AliHLTUInt8_t part  = AliHLTTPCDefinitions::GetMinPatchNr(mask);
+  AliHLTUInt32_t decoderIndex=AliHLTTPCSpacePointData::GetID(slice, part, 0);
+  std::map<AliHLTUInt32_t, AliHLTTPCHWCFSpacePointBlock>::iterator block=fBlocks.find(decoderIndex);
+  if (block==fBlocks.end()) {
+    HLTError("can not find data block of id 0x%08x", mask);
+    return -ENOENT;
+  }
+  if (block->second.GetGrid()!=NULL && pGrid!=NULL && block->second.GetGrid()!=pGrid) {
+    // there is trouble ahead because this will delete the index grid instance
+    // but it might be an external pointer supposed to be deleted by someone else
+    ALIHLTERRORGUARD(1, "overriding previous instance of index grid, potential memory leak or invalid deallocation ahead");
+  }
+  block->second.SetGrid(pGrid);
+  return 0;
+}
+
 int AliHLTTPCHWCFSpacePointContainer::GetClusterIDs(vector<AliHLTUInt32_t>& tgt) const
 {
   // get array of cluster IDs
@@ -198,7 +347,7 @@ float AliHLTTPCHWCFSpacePointContainer::GetX(AliHLTUInt32_t clusterID) const
   // now extracting the x value from the padrow no.
   //return cl->second.Decoder()->fX;
   int index=AliHLTTPCSpacePointData::GetNumber(cl->first);
-  return AliHLTTPCTransform::Row2X(cl->second.Decoder()->GetPadRow(index));
+  return cl->second.Decoder()->GetPadRow(index);
 }
 
 float AliHLTTPCHWCFSpacePointContainer::GetXWidth(AliHLTUInt32_t clusterID) const
@@ -260,6 +409,16 @@ float AliHLTTPCHWCFSpacePointContainer::GetCharge(AliHLTUInt32_t clusterID) cons
   return cl->second.Decoder()->GetCharge(index);
 }
 
+float AliHLTTPCHWCFSpacePointContainer::GetQMax(AliHLTUInt32_t clusterID) const
+{
+  // get charge
+  std::map<AliHLTUInt32_t, AliHLTTPCHWCFSpacePointProperties>::const_iterator cl=fClusters.find(clusterID);
+  if (cl==fClusters.end() ||
+      cl->second.Decoder()==NULL) return 0.0;
+  int index=AliHLTTPCSpacePointData::GetNumber(cl->first);
+  return cl->second.Decoder()->GetQMax(index);
+}
+
 float AliHLTTPCHWCFSpacePointContainer::GetPhi(AliHLTUInt32_t clusterID) const
 {
   // get charge
@@ -281,18 +440,30 @@ void AliHLTTPCHWCFSpacePointContainer::Clear(Option_t * option)
   }
   fSelections.clear();
 
+  for (std::map<AliHLTUInt32_t, AliHLTTPCHWCFSpacePointBlock>::iterator block=fBlocks.begin();
+       block!=fBlocks.end(); block++) {
+    if (block->second.GetDecoder()) delete block->second.GetDecoder();
+    if (block->second.GetGrid()) delete block->second.GetGrid();
+  }
+  fBlocks.clear();
+
+  if (fSingleBlock.GetDecoder()) fSingleBlock.GetDecoder()->Reset();
+  if (fSingleBlock.GetGrid()) fSingleBlock.GetGrid()->Clear();
+
   AliHLTSpacePointContainer::Clear(option);
 }
 
 void AliHLTTPCHWCFSpacePointContainer::Print(ostream& out, Option_t */*option*/) const
 {
   // print to stream
-  out << "AliHLTTPCHWCFSpacePointContainer::Print" << endl;
-  out << "n clusters: " << fClusters.size() << endl;
+  std::stringstream str;
+  str << "AliHLTTPCHWCFSpacePointContainer::Print" << endl;
+  str << "n clusters: " << fClusters.size() << endl;
   for (std::map<AliHLTUInt32_t, AliHLTTPCHWCFSpacePointProperties>::const_iterator cl=fClusters.begin();
        cl!=fClusters.end(); cl++) {
-    out << " " << cl->first << cl->second << endl;
+    str << " 0x" << hex << setw(8) << setfill('0') << cl->first << dec << cl->second << endl;
   }
+  out << str;
 }
 
 AliHLTSpacePointContainer* AliHLTTPCHWCFSpacePointContainer::SelectByMask(AliHLTUInt32_t mask, bool /*bAlloc*/) const
@@ -407,103 +578,249 @@ int AliHLTTPCHWCFSpacePointContainer::Write(AliHLTUInt8_t* outputPtr,
                                            AliHLTComponentBlockDataList&
                                            outputBlocks,
                                            AliHLTDataDeflater* pDeflater,
-                                           const char* /*option*/) const
+                                           const char* option) const
+{
+  /// write blocks to HLT component output
+  AliHLTUInt32_t offset=0;
+  if (outputBlocks.size()>0) {
+    offset=outputBlocks.back().fOffset+outputBlocks.back().fSize;
+  }
+  return Write(outputPtr, size, offset, outputBlocks, pDeflater, option);
+}
+
+int AliHLTTPCHWCFSpacePointContainer::Write(AliHLTUInt8_t* outputPtr,
+                                           AliHLTUInt32_t size,
+                                           AliHLTUInt32_t offset,
+                                           AliHLTComponentBlockDataList&
+                                           outputBlocks,
+                                           AliHLTDataDeflater* pDeflater,
+                                           const char* option) const
+{
+  /// write blocks to HLT component output
+  return WriteSorted(outputPtr, size, offset, outputBlocks, pDeflater, option);
+}
+
+int AliHLTTPCHWCFSpacePointContainer::WriteSorted(AliHLTUInt8_t* outputPtr,
+                                                 AliHLTUInt32_t size,
+                                                 AliHLTUInt32_t offset,
+                                                 AliHLTComponentBlockDataList&
+                                                 outputBlocks,
+                                                 AliHLTDataDeflater* pDeflater,
+                                                 const char* option) const
 {
   /// write blocks to HLT component output
-  if (!outputPtr) return -EINVAL;
+  int iResult=0;
+
+  if (fMode&kModeSingle) {
+    iResult=WriteSorted(outputPtr, size, offset, fSingleBlock.GetDecoder(), fSingleBlock.GetGrid(), fSingleBlock.GetId(), outputBlocks, pDeflater, option);
+  } else {
+    iResult=-ENOENT;
+    for (std::map<AliHLTUInt32_t, AliHLTTPCHWCFSpacePointBlock>::const_iterator block=fBlocks.begin();
+        block!=fBlocks.end(); block++) {
+      AliHLTTPCHWCFData* pDecoder=block->second.GetDecoder();
+      AliHLTSpacePointPropertyGrid* pGrid=block->second.GetGrid();
+      AliHLTUInt32_t mask=block->first;
+      // FIXME: have to propagate the parameter which block is currently to be written
+      // for now the index grid is only set for that one
+      if (!pGrid) continue;
+      iResult=WriteSorted(outputPtr, size, offset, pDecoder, pGrid, mask, outputBlocks, pDeflater, option);
+      break; // only one is supposed to be written
+    }
+    if (iResult==-ENOENT) {
+      HLTError("could not find the index grid of the partition to be written");
+    }
+  }
+  return iResult;
+}
+
+int AliHLTTPCHWCFSpacePointContainer::WriteSorted(AliHLTUInt8_t* outputPtr,
+                                                 AliHLTUInt32_t size,
+                                                 AliHLTUInt32_t offset,
+                                                 AliHLTTPCHWCFData* pDecoder,
+                                                 AliHLTSpacePointPropertyGrid* pGrid,
+                                                 AliHLTUInt32_t mask,
+                                                 AliHLTComponentBlockDataList&
+                                                 outputBlocks,
+                                                 AliHLTDataDeflater* pDeflater,
+                                                 const char* option) const
+{
+  /// write blocks to HLT component output
+  if (!outputPtr || !pDecoder || !pGrid) return -EINVAL;
+  if (pDecoder->GetNumberOfClusters()==0) return 0;
+  if (option) {
+    // this is only for sending mc labels in simulation and testing
+    // no impact to real running
+    if (!fWrittenClusterIds && strcmp(option, "write-cluster-ids")==0) {
+      const_cast<AliHLTTPCHWCFSpacePointContainer*>(this)->fWrittenClusterIds=new vector<AliHLTUInt32_t>;
+    }
+  }
   int iResult=0;
   AliHLTUInt32_t capacity=size;
   size=0;
 
-  for (int slice=0; slice<AliHLTTPCTransform::GetNSlice(); slice++) {
-    for (int part=0; part<AliHLTTPCTransform::GetNPatches(); part++) {
-      AliHLTUInt32_t mask=AliHLTTPCSpacePointData::GetID(slice,part,0);
-      // FIXME: make GetClusterIDs a const function and handle the cast there
-      const vector<AliHLTUInt32_t>* collection=const_cast<AliHLTTPCHWCFSpacePointContainer*>(this)->GetClusterIDs(mask);
-      if (!collection) continue;
-      if (size+sizeof(AliHLTTPCRawClusterData)+collection->size()*sizeof(AliHLTTPCRawCluster)>capacity) {
-       ALIHLTERRORGUARD(1,"too little space to write cluster output block");
-       return -ENOSPC;
+  int slice=AliHLTTPCSpacePointData::GetSlice(mask);
+  int part=AliHLTTPCSpacePointData::GetPatch(mask);
+
+  // Note: the offset parameter is only for the block descriptors, output pointer and size
+  // consider already the offset
+  AliHLTTPCRawClusterData* blockout=reinterpret_cast<AliHLTTPCRawClusterData*>(outputPtr+size);
+  blockout->fVersion=0;
+  blockout->fCount=0;
+
+  if (pDeflater) {
+    pDeflater->Clear();
+    pDeflater->InitBitDataOutput(reinterpret_cast<AliHLTUInt8_t*>(blockout->fClusters), capacity-size-sizeof(AliHLTTPCRawClusterData));
+    blockout->fVersion=pDeflater->GetDeflaterVersion();
+    if (fMode&kModeDifferentialPadTime) blockout->fVersion+=2;
+  }
+
+  unsigned lastPadRow=0;
+  AliHLTUInt64_t lastPad64=0;
+  AliHLTUInt64_t lastTime64=0;
+  AliHLTSpacePointPropertyGrid::iterator clusterID=pGrid->begin();
+  if (clusterID!=pGrid->end()) {
+    for (; clusterID!=pGrid->end(); clusterID++) {
+      if (clusterID.Data().fTrackId>-1) {
+       // this is an assigned cluster, skip
+       // TODO: introduce selectors into AliHLTIndexGrid::begin to loop
+       // consistently over entries, e.g. this check has to be done also
+       // in the forwarding of MC labels in
+       // AliHLTTPCDataCompressionComponent::ForwardMCLabels
+       continue;
+      }
+      if ((unsigned)slice!=AliHLTTPCSpacePointData::GetSlice(clusterID.Data().fId) ||
+         (unsigned)part!=AliHLTTPCSpacePointData::GetPatch(clusterID.Data().fId)) {
+       HLTError("cluster index 0x%08x out of slice %d partition %d", clusterID.Data().fId, slice, part);
       }
-      AliHLTTPCRawClusterData* blockout=reinterpret_cast<AliHLTTPCRawClusterData*>(outputPtr+size);
-      blockout->fVersion=0;
-      blockout->fCount=0;
-
-      if (pDeflater) {
-       pDeflater->Clear();
-       pDeflater->InitBitDataOutput(reinterpret_cast<AliHLTUInt8_t*>(blockout->fClusters), capacity-size-sizeof(AliHLTTPCRawClusterData));
-       blockout->fVersion=pDeflater->GetDeflaterVersion();
+      int index=AliHLTTPCSpacePointData::GetNumber(clusterID.Data().fId);
+      const AliHLTTPCHWCFData::iterator& input=pDecoder->find(index);
+      if (!(input!=pDecoder->end())) continue;
+      if (fWrittenClusterIds) fWrittenClusterIds->push_back(clusterID.Data().fId);
+      int padrow=input.GetPadRow();
+      if (padrow<0) {
+       // something wrong here, padrow is stored in the cluster header
+       // word which has bit pattern 0x3 in bits bit 30 and 31 which was
+       // not recognized
+       ALIHLTERRORGUARD(1, "can not read cluster header word");
+       iResult=-EBADF;
+       break;
       }
 
-      vector<AliHLTUInt32_t>::const_iterator clusterID=collection->begin();
-      if (clusterID!=collection->end()) {
-       std::map<AliHLTUInt32_t, AliHLTTPCHWCFSpacePointProperties>::const_iterator cl=fClusters.find(*clusterID);
-       for (; clusterID!=collection->end(); clusterID++, cl++) {
-         if (cl->first!=*clusterID) cl=fClusters.find(*clusterID);
-         if (cl==fClusters.end() || cl->second.Decoder()==NULL) continue;
-         int index=AliHLTTPCSpacePointData::GetNumber(cl->first);
-         int padrow=cl->second.Decoder()->GetPadRow(index);
-         if (padrow<0) {
-           // something wrong here, padrow is stored in the cluster header
-           // word which has bit pattern 0x3 in bits bit 30 and 31 which was
-           // not recognized
-           ALIHLTERRORGUARD(1, "can not read cluster header word");
-           break;
-         }
+      float pad =input.GetPad();
+      float time =input.GetTime();
+      float sigmaY2=input.GetSigmaY2();
+      float sigmaZ2=input.GetSigmaZ2();
+      if (!pDeflater) {
+       AliHLTTPCRawCluster& c=blockout->fClusters[blockout->fCount];
+       padrow+=AliHLTTPCTransform::GetFirstRow(part);
+       c.SetPadRow(padrow);
+       c.SetCharge(input.GetCharge());
+       c.SetPad(pad);  
+       c.SetTime(time);
+       c.SetSigmaY2(sigmaY2);
+       c.SetSigmaZ2(sigmaZ2);
+       c.SetQMax(input.GetQMax());
+      } else {
+       AliHLTUInt64_t padrow64=input.GetPadRow();
+       if (padrow64==lastPadRow) {
+         padrow64-=lastPadRow;
+       } else if (padrow64>lastPadRow) {
+         padrow64-=lastPadRow;
+         lastPadRow+=padrow64;
+       } else {
+         AliFatal("padrows not ordered");
+       }
 
-         // FIXME: the HW ClusterFinder returns only the sum
-         // sum(q_i*pad_i*pad_i)/sum(q_i)
-         // where the mean needs to be subtracted, not yet in the decoder
-         // but should be implemented there
-         float pad =cl->second.Decoder()->GetPad(index);
-         float time =cl->second.Decoder()->GetTime(index);
-         float sigmaY2=cl->second.Decoder()->GetSigmaY2(index);
-         float sigmaZ2=cl->second.Decoder()->GetSigmaZ2(index);
-         sigmaY2-=pad*pad;
-         sigmaZ2-=time*time;
-
-         if (!pDeflater) {
-           AliHLTTPCRawCluster& c=blockout->fClusters[blockout->fCount];
-           padrow+=AliHLTTPCTransform::GetFirstRow(part);
-           c.SetPadRow(padrow);
-           c.SetCharge(cl->second.Decoder()->GetCharge(index));
-           c.SetPad(pad);  
-           c.SetTime(time);
-           c.SetSigmaY2(sigmaY2);
-           c.SetSigmaZ2(sigmaZ2);
-           c.SetQMax(cl->second.Decoder()->GetQMax(index));
+       AliHLTUInt32_t padType=0;
+       AliHLTUInt32_t signdPad=0;
+       AliHLTUInt64_t pad64=0;
+       if ((fMode&kModeDifferentialPadTime)!=0 && sigmaY2<.00001) {
+         // single pad cluster
+         // use twice the pad position to take account for the 0.5 offset
+         // added in the AliHLTTPCHWCFData decoder in accordance with the
+         // offline definition. Using the factor 2, this offset is not
+         // cut off by rounding
+         pad64=(AliHLTUInt64_t)round(2*pad);
+         padType=1;
+       } else {
+       if (!isnan(pad)) pad64=(AliHLTUInt64_t)round(pad*AliHLTTPCDefinitions::fgkClusterParameterDefinitions[AliHLTTPCDefinitions::kPad].fScale);
+       }
+       if (fMode&kModeDifferentialPadTime && padType==0) {
+         AliHLTUInt64_t dpad64=0;
+         if (pad64<lastPad64) {
+           dpad64=lastPad64-pad64;
+           signdPad=1;
          } else {
-           AliHLTUInt64_t pad64=round(pad*60);
-           AliHLTUInt64_t time64=round(time*25);
-           AliHLTUInt64_t sigmaY264=sigmaY2*10;
-           AliHLTUInt64_t sigmaZ264=sigmaY2*10;
-           pDeflater->OutputParameterBits(AliHLTTPCDataCompressionComponent::kPadRow , cl->second.Decoder()->GetPadRow(index));
-           pDeflater->OutputParameterBits(AliHLTTPCDataCompressionComponent::kPad    , pad64);  
-           pDeflater->OutputParameterBits(AliHLTTPCDataCompressionComponent::kTime   , time64);
-           pDeflater->OutputParameterBits(AliHLTTPCDataCompressionComponent::kSigmaY2, sigmaY264);
-           pDeflater->OutputParameterBits(AliHLTTPCDataCompressionComponent::kSigmaZ2, sigmaZ264);
-           pDeflater->OutputParameterBits(AliHLTTPCDataCompressionComponent::kCharge , cl->second.Decoder()->GetCharge(index));
-           pDeflater->OutputParameterBits(AliHLTTPCDataCompressionComponent::kQMax   , cl->second.Decoder()->GetQMax(index));
+           dpad64=pad64-lastPad64;
+           signdPad=0;
          }
-         blockout->fCount++;
+         lastPad64=pad64;
+         pad64=dpad64;
        }
+       AliHLTUInt32_t signdTime=0;
+       AliHLTUInt64_t time64=0;
+       if (!isnan(time)) time64=(AliHLTUInt64_t)round(time*AliHLTTPCDefinitions::fgkClusterParameterDefinitions[AliHLTTPCDefinitions::kTime].fScale);
+       if (fMode&kModeDifferentialPadTime) {
+         AliHLTUInt64_t dtime64=0;
+         if (time64<lastTime64) {
+           dtime64=lastTime64-time64;
+           signdTime=1;
+         } else {
+           dtime64=time64-lastTime64;
+           signdTime=0;
+         }
+         lastTime64=time64;
+         time64=dtime64;
+       }
+       AliHLTUInt64_t sigmaY264=0;
+       if (!isnan(sigmaY2)) sigmaY264=(AliHLTUInt64_t)round(sigmaY2*AliHLTTPCDefinitions::fgkClusterParameterDefinitions[AliHLTTPCDefinitions::kSigmaY2].fScale);
+       AliHLTUInt64_t sigmaZ264=0;
+       if (!isnan(sigmaZ2)) sigmaZ264=(AliHLTUInt64_t)round(sigmaZ2*AliHLTTPCDefinitions::fgkClusterParameterDefinitions[AliHLTTPCDefinitions::kSigmaZ2].fScale);
+       pDeflater->OutputParameterBits(AliHLTTPCDefinitions::kPadRow , padrow64);
+       pDeflater->OutputParameterBits(AliHLTTPCDefinitions::kPad    , pad64);
+       if (fMode&kModeDifferentialPadTime) pDeflater->OutputBit(padType);
+       if (fMode&kModeDifferentialPadTime && padType==0) pDeflater->OutputBit(signdPad);
+       pDeflater->OutputParameterBits(AliHLTTPCDefinitions::kTime   , time64);
+       if (fMode&kModeDifferentialPadTime) pDeflater->OutputBit(signdTime);
+       if (padType==0) pDeflater->OutputParameterBits(AliHLTTPCDefinitions::kSigmaY2, sigmaY264);
+       pDeflater->OutputParameterBits(AliHLTTPCDefinitions::kSigmaZ2, sigmaZ264);
+       pDeflater->OutputParameterBits(AliHLTTPCDefinitions::kCharge , input.GetCharge());
+       pDeflater->OutputParameterBits(AliHLTTPCDefinitions::kQMax   , input.GetQMax());
       }
-      AliHLTComponent_BlockData bd;
-      AliHLTComponent::FillBlockData(bd);
-      bd.fOffset        = size;
-      if (!pDeflater) {
-       bd.fSize        = sizeof(AliHLTTPCRawClusterData)+blockout->fCount*sizeof(AliHLTTPCRawCluster);
-      } else {
-       pDeflater->Pad8Bits();
-       bd.fSize        = sizeof(AliHLTTPCRawClusterData)+pDeflater->GetBitDataOutputSizeBytes();
-       pDeflater->CloseBitDataOutput();
-      }
+      blockout->fCount++;
+    }
+  }
+  AliHLTComponent_BlockData bd;
+  AliHLTComponent::FillBlockData(bd);
+  bd.fOffset        = size+offset;
+  if (!pDeflater) {
+    bd.fSize        = sizeof(AliHLTTPCRawClusterData)+blockout->fCount*sizeof(AliHLTTPCRawCluster);
+    bd.fDataType    = AliHLTTPCDefinitions::fgkRawClustersDataType;
+  } else {
+    pDeflater->Pad8Bits();
+    bd.fSize        = sizeof(AliHLTTPCRawClusterData)+pDeflater->GetBitDataOutputSizeBytes();
+    pDeflater->CloseBitDataOutput();
+    bd.fDataType    = AliHLTTPCDefinitions::RemainingClustersCompressedDataType();
+  }
+  bd.fSpecification = AliHLTTPCDefinitions::EncodeDataSpecification(slice, slice, part, part);
+  outputBlocks.push_back(bd);
+
+  size += bd.fSize;
+
+  if (fWrittenClusterIds && fWrittenClusterIds->size()>0) {
+    AliHLTComponent::FillBlockData(bd);
+    bd.fOffset        = size+offset;
+    bd.fSize        = fWrittenClusterIds->size()*sizeof(vector<AliHLTUInt32_t>::value_type);
+    if (bd.fSize+size<=capacity) {
+      memcpy(outputPtr+size, &(*fWrittenClusterIds)[0], bd.fSize);
+      bd.fDataType    = AliHLTTPCDefinitions::RemainingClusterIdsDataType();
       bd.fSpecification = AliHLTTPCDefinitions::EncodeDataSpecification(slice, slice, part, part);
-      bd.fDataType      = AliHLTTPCDefinitions::fgkRawClustersDataType;
-      outputBlocks.push_back(bd);
-      
+      outputBlocks.push_back(bd);    
       size += bd.fSize;
+    } else {
+      iResult=-ENOSPC;
     }
+    fWrittenClusterIds->clear();
   }
 
   if (iResult<0) return iResult;
@@ -560,11 +877,18 @@ void AliHLTTPCHWCFSpacePointContainer::AliHLTTPCHWCFSpacePointProperties::Print(
     out << "no data";
     return;
   }
+  std::stringstream str;
   const AliHLTTPCHWCFData* decoder=Decoder();
-  out << " " << decoder->GetPadRow(fIndex) << " " << decoder->GetPad(fIndex) << " " << decoder->GetTime(fIndex)
-      << " " << decoder->GetSigmaY2(fIndex) << " "  << decoder->GetSigmaZ2(fIndex)
-      << " " << decoder->GetCharge(fIndex) << " "  << decoder->GetQMax(fIndex)
+  str.setf(ios::fixed,ios::floatfield);
+  str << " " << setfill(' ') << setw(3) << decoder->GetPadRow(fIndex) 
+      << " " << setw(8) << setprecision(3) << decoder->GetPad(fIndex)
+      << " " << setw(8) << setprecision(3) << decoder->GetTime(fIndex)
+      << " " << setw(8) << setprecision(1) << decoder->GetSigmaY2(fIndex) 
+      << " " << setw(9) << setprecision(1) << decoder->GetSigmaZ2(fIndex)
+      << " " << setw(5) << decoder->GetCharge(fIndex) 
+      << " " << setw(5) << decoder->GetQMax(fIndex)
       << " " << fTrackId << " " << fMCId << " " << fUsed;
+  out << str;
 }
 
 ostream& operator<<(ostream &out, const AliHLTTPCHWCFSpacePointContainer::AliHLTTPCHWCFSpacePointProperties& p)