]> git.uio.no Git - u/mrichter/AliRoot.git/blobdiff - HLT/TPCLib/AliHLTTPCHWCFSpacePointContainer.cxx
ALIROOT-5433 Transition to CDHv3 in HLT
[u/mrichter/AliRoot.git] / HLT / TPCLib / AliHLTTPCHWCFSpacePointContainer.cxx
index f7d8d43788aa90372daefa1004bf8d293d4ac23e..5e90b14dea2b10e7424cd6bea9e4ed996a57e4fa 100644 (file)
 #include "AliHLTComponent.h"
 #include "AliHLTTemplates.h"
 #include "AliHLTDataDeflater.h"
-#include "AliRawDataHeader.h"
+#include "AliHLTCDHWrapper.h"
 #include "AliLog.h"
 #include "TMath.h"
 #include <memory>
 #include <algorithm>
 #include <cmath>
 #include <iostream>
+#include <sstream>
 #include <iomanip>
 
 
@@ -53,15 +54,16 @@ AliHLTTPCHWCFSpacePointContainer::AliHLTTPCHWCFSpacePointContainer(int mode)
   , 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==1) {
+  if (fMode&kModeSingle) {
     fSingleBlock.SetDecoder(new AliHLTTPCHWCFData);
-    fSingleBlock.SetGrid(new AliHLTSpacePointGrid(33, 1.0, 140, 8, 1024, 10));
+    fSingleBlock.SetGrid(AllocateIndexGrid());
   }
 }
 
@@ -72,6 +74,7 @@ AliHLTTPCHWCFSpacePointContainer::AliHLTTPCHWCFSpacePointContainer(const AliHLTT
   , fBlocks()
   , fSingleBlock()
   , fMode(c.fMode)
+  , fWrittenClusterIds(NULL)
 {
   /// copy constructor
 }
@@ -83,6 +86,7 @@ AliHLTTPCHWCFSpacePointContainer& AliHLTTPCHWCFSpacePointContainer::operator=(co
   AliHLTSpacePointContainer::operator=(c);
   fClusters=c.fClusters;
   fMode=c.fMode;
+  fWrittenClusterIds=NULL;
 
   return *this;
 }
@@ -93,6 +97,7 @@ AliHLTTPCHWCFSpacePointContainer::~AliHLTTPCHWCFSpacePointContainer()
   Clear();
   if (fSingleBlock.GetDecoder()) delete fSingleBlock.GetDecoder();
   if (fSingleBlock.GetGrid()) delete fSingleBlock.GetGrid();
+  if (fWrittenClusterIds) delete fWrittenClusterIds;
 }
 
 int AliHLTTPCHWCFSpacePointContainer::AddInputBlock(const AliHLTComponentBlockData* pDesc)
@@ -106,7 +111,8 @@ int AliHLTTPCHWCFSpacePointContainer::AddInputBlock(const AliHLTComponentBlockDa
     return 0;
   }
   if (!pDesc->fPtr) return -ENODATA;
-  if (pDesc->fSize<=sizeof(AliRawDataHeader)) return 0;
+  AliHLTCDHWrapper header(pDesc->fPtr);
+  if (pDesc->fSize<=header.GetHeaderSize()) return 0;
 
   AliHLTUInt8_t slice = AliHLTTPCDefinitions::GetMinSliceNr( pDesc->fSpecification );
   AliHLTUInt8_t part  = AliHLTTPCDefinitions::GetMinPatchNr( pDesc->fSpecification );
@@ -114,13 +120,13 @@ int AliHLTTPCHWCFSpacePointContainer::AddInputBlock(const AliHLTComponentBlockDa
   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);
+  // skip the first 8 or 10 CDH words
+  buffer += header.GetHeaderSize()/sizeof(AliHLTUInt32_t);
+  UInt_t bufferSize32 = ((Int_t)pDesc->fSize - header.GetHeaderSize() )/sizeof(AliHLTUInt32_t);
 
   AliHLTTPCHWCFData* pDecoder=NULL;
-  AliHLTSpacePointGrid* pGrid=NULL;
-  if (fMode==1) {
+  AliHLTSpacePointPropertyGrid* pGrid=NULL;
+  if (fMode&kModeSingle) {
     pDecoder=fSingleBlock.GetDecoder();
     pGrid=fSingleBlock.GetGrid();
   } else {
@@ -134,22 +140,23 @@ int AliHLTTPCHWCFSpacePointContainer::AddInputBlock(const AliHLTComponentBlockDa
     pDecoder=new AliHLTTPCHWCFData;
     if (!pDecoder) return -ENOMEM;
   }
-  if (!pGrid) {
-    pGrid=new AliHLTSpacePointGrid(33, 1.0, 140, 8, 1024, 10);
-    if (!pGrid) {
-      delete 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;
   }
 
-  if (fMode!=1) {
+  if (fMode&kModeSingle && !pGrid) {
+    pGrid=AllocateIndexGrid();
+    if (!pGrid) {
+      delete pDecoder;
+      return -ENOMEM;
+    }
+  }
+
+  if (fMode&kModeCreateMap) { // register immediately
   UInt_t nofClusters=pDecoder->GetNumberOfClusters();
 
   for (UInt_t i=0; i<nofClusters; i++) {
@@ -168,13 +175,13 @@ int AliHLTTPCHWCFSpacePointContainer::AddInputBlock(const AliHLTComponentBlockDa
   }
   }
 
-  if ((iResult=PopulateAccessGrid(pGrid, pDecoder, slice, part))<0) {
+  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==1) {
+  if (fMode&kModeSingle) {
     fSingleBlock.SetDecoder(pDecoder);
     fSingleBlock.SetGrid(pGrid);
     fSingleBlock.SetId(decoderIndex);
@@ -184,7 +191,20 @@ int AliHLTTPCHWCFSpacePointContainer::AddInputBlock(const AliHLTComponentBlockDa
   return count;
 }
 
-int AliHLTTPCHWCFSpacePointContainer::PopulateAccessGrid(AliHLTSpacePointGrid* pGrid, AliHLTUInt32_t mask) const
+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;
@@ -202,7 +222,7 @@ int AliHLTTPCHWCFSpacePointContainer::PopulateAccessGrid(AliHLTSpacePointGrid* p
   return PopulateAccessGrid(pGrid, block->second.GetDecoder(), slice, partition);
 }
 
-int AliHLTTPCHWCFSpacePointContainer::PopulateAccessGrid(AliHLTSpacePointGrid* pGrid, AliHLTTPCHWCFData* pDecoder,
+int AliHLTTPCHWCFSpacePointContainer::PopulateAccessGrid(AliHLTSpacePointPropertyGrid* pGrid, AliHLTTPCHWCFData* pDecoder,
                                                         int slice, int partition) const
 {
   // populate an access grid
@@ -221,7 +241,7 @@ int AliHLTTPCHWCFSpacePointContainer::PopulateAccessGrid(AliHLTSpacePointGrid* p
   cl=pDecoder->begin();
   for (; cl!=pDecoder->end(); ++cl, count++) {
     AliHLTUInt32_t id=AliHLTTPCSpacePointData::GetID(slice, partition, count);
-    iResult=pGrid->AddSpacePoint(id, cl.GetPadRow(), cl.GetPad(), cl.GetTime());
+    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);
   }
@@ -229,7 +249,7 @@ int AliHLTTPCHWCFSpacePointContainer::PopulateAccessGrid(AliHLTSpacePointGrid* p
   return 0;
 }
 
-const AliHLTSpacePointContainer::AliHLTSpacePointGrid* AliHLTTPCHWCFSpacePointContainer::GetAccessGrid(AliHLTUInt32_t mask) const
+const AliHLTSpacePointContainer::AliHLTSpacePointPropertyGrid* AliHLTTPCHWCFSpacePointContainer::GetSpacePointPropertyGrid(AliHLTUInt32_t mask) const
 {
   // get the access grid for a data block
   AliHLTUInt8_t slice = AliHLTTPCDefinitions::GetMinSliceNr(mask);
@@ -243,6 +263,26 @@ const AliHLTSpacePointContainer::AliHLTSpacePointGrid* AliHLTTPCHWCFSpacePointCo
   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
@@ -308,7 +348,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
@@ -370,6 +410,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
@@ -407,12 +457,14 @@ void AliHLTTPCHWCFSpacePointContainer::Clear(Option_t * 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 << " 0x" << hex << setw(8) << setfill('0') << cl->first << dec << cl->second << endl;
+    str << " 0x" << hex << setw(8) << setfill('0') << cl->first << dec << cl->second << endl;
   }
+  out << str.str();
 }
 
 AliHLTSpacePointContainer* AliHLTTPCHWCFSpacePointContainer::SelectByMask(AliHLTUInt32_t mask, bool /*bAlloc*/) const
@@ -546,134 +598,9 @@ int AliHLTTPCHWCFSpacePointContainer::Write(AliHLTUInt8_t* outputPtr,
                                            const char* option) const
 {
   /// write blocks to HLT component output
-  if (fMode==0) return WriteUnsorted(outputPtr, size, offset, outputBlocks, pDeflater, option);
   return WriteSorted(outputPtr, size, offset, outputBlocks, pDeflater, option);
 }
 
-int AliHLTTPCHWCFSpacePointContainer::WriteUnsorted(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;
-  AliHLTUInt32_t capacity=size;
-  size=0;
-
-  for (int slice=0; slice<AliHLTTPCTransform::GetNSlice() && iResult>=0; slice++) {
-    for (int part=0; part<AliHLTTPCTransform::GetNPatches() && iResult>=0; 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 || collection->size()==0) continue;
-      if (size+sizeof(AliHLTTPCRawClusterData)+collection->size()*sizeof(AliHLTTPCRawCluster)>capacity) {
-       ALIHLTERRORGUARD(1,"too little space to write cluster output block");
-       iResult=-ENOSPC;
-       break;
-      }
-      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();
-      }
-
-      unsigned lastPadRow=0;
-      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!=fClusters.end())?cl++:cl) {
-         if (cl!=fClusters.end() && 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;
-         }
-
-         // 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));
-         } else {
-           AliHLTUInt64_t padrow64=cl->second.Decoder()->GetPadRow(index);
-           // enable if padrows are ordered
-           if (padrow64>=lastPadRow) {
-           //   padrow64-=lastPadRow;
-           //   lastPadRow+=padrow64;
-           } else {
-           //   AliFatal("padrows not ordered");
-           }
-
-           AliHLTUInt64_t pad64
-             =(AliHLTUInt64_t)round(pad*AliHLTTPCDefinitions::fgkClusterParameterDefinitions[AliHLTTPCDefinitions::kPad].fScale);
-           AliHLTUInt64_t time64
-             =(AliHLTUInt64_t)round(time*AliHLTTPCDefinitions::fgkClusterParameterDefinitions[AliHLTTPCDefinitions::kTime].fScale);
-           AliHLTUInt64_t sigmaY264
-             =(AliHLTUInt64_t)round(sigmaY2*AliHLTTPCDefinitions::fgkClusterParameterDefinitions[AliHLTTPCDefinitions::kSigmaY2].fScale);
-           AliHLTUInt64_t sigmaZ264
-             =(AliHLTUInt64_t)round(sigmaZ2*AliHLTTPCDefinitions::fgkClusterParameterDefinitions[AliHLTTPCDefinitions::kSigmaZ2].fScale);
-           pDeflater->OutputParameterBits(AliHLTTPCDefinitions::kPadRow , padrow64);
-           pDeflater->OutputParameterBits(AliHLTTPCDefinitions::kPad    , pad64);  
-           pDeflater->OutputParameterBits(AliHLTTPCDefinitions::kTime   , time64);
-           pDeflater->OutputParameterBits(AliHLTTPCDefinitions::kSigmaY2, sigmaY264);
-           pDeflater->OutputParameterBits(AliHLTTPCDefinitions::kSigmaZ2, sigmaZ264);
-           pDeflater->OutputParameterBits(AliHLTTPCDefinitions::kCharge , cl->second.Decoder()->GetCharge(index));
-           pDeflater->OutputParameterBits(AliHLTTPCDefinitions::kQMax   , cl->second.Decoder()->GetQMax(index));
-         }
-         blockout->fCount++;
-       }
-      }
-      AliHLTComponent_BlockData bd;
-      AliHLTComponent::FillBlockData(bd);
-      bd.fOffset        = size+offset;
-      if (!pDeflater) {
-       bd.fSize        = sizeof(AliHLTTPCRawClusterData)+blockout->fCount*sizeof(AliHLTTPCRawCluster);
-      } else {
-       pDeflater->Pad8Bits();
-       bd.fSize        = sizeof(AliHLTTPCRawClusterData)+pDeflater->GetBitDataOutputSizeBytes();
-       pDeflater->CloseBitDataOutput();
-      }
-      bd.fSpecification = AliHLTTPCDefinitions::EncodeDataSpecification(slice, slice, part, part);
-      bd.fDataType      = AliHLTTPCDefinitions::fgkRawClustersDataType;
-      outputBlocks.push_back(bd);
-      
-      size += bd.fSize;
-    }
-  }
-
-  if (iResult<0) return iResult;
-  return size;
-}
-
 int AliHLTTPCHWCFSpacePointContainer::WriteSorted(AliHLTUInt8_t* outputPtr,
                                                  AliHLTUInt32_t size,
                                                  AliHLTUInt32_t offset,
@@ -685,15 +612,23 @@ int AliHLTTPCHWCFSpacePointContainer::WriteSorted(AliHLTUInt8_t* outputPtr,
   /// write blocks to HLT component output
   int iResult=0;
 
-  if (fMode==1) {
+  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() && iResult>=0; block++) {
+        block!=fBlocks.end(); block++) {
       AliHLTTPCHWCFData* pDecoder=block->second.GetDecoder();
-      AliHLTSpacePointGrid* pGrid=block->second.GetGrid();
+      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;
@@ -703,16 +638,23 @@ int AliHLTTPCHWCFSpacePointContainer::WriteSorted(AliHLTUInt8_t* outputPtr,
                                                  AliHLTUInt32_t size,
                                                  AliHLTUInt32_t offset,
                                                  AliHLTTPCHWCFData* pDecoder,
-                                                 AliHLTSpacePointGrid* pGrid,
+                                                 AliHLTSpacePointPropertyGrid* pGrid,
                                                  AliHLTUInt32_t mask,
                                                  AliHLTComponentBlockDataList&
                                                  outputBlocks,
                                                  AliHLTDataDeflater* pDeflater,
-                                                 const char* /*option*/) const
+                                                 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;
@@ -720,6 +662,8 @@ int AliHLTTPCHWCFSpacePointContainer::WriteSorted(AliHLTUInt8_t* outputPtr,
   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;
@@ -728,49 +672,57 @@ int AliHLTTPCHWCFSpacePointContainer::WriteSorted(AliHLTUInt8_t* outputPtr,
     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;
-  AliHLTSpacePointGrid::iterator clusterID=pGrid->begin();
+  AliHLTUInt64_t lastPad64=0;
+  AliHLTUInt64_t lastTime64=0;
+  AliHLTSpacePointPropertyGrid::iterator clusterID=pGrid->begin();
   if (clusterID!=pGrid->end()) {
     for (; clusterID!=pGrid->end(); clusterID++) {
-      if ((unsigned)slice!=AliHLTTPCSpacePointData::GetSlice(clusterID.Data()) ||
-         (unsigned)part!=AliHLTTPCSpacePointData::GetPatch(clusterID.Data())) {
-       HLTError("cluster index 0x%08x out of slice %d partition %d", clusterID.Data(), slice, part);
+      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);
       }
-      int index=AliHLTTPCSpacePointData::GetNumber(clusterID.Data());
-      int padrow=pDecoder->GetPadRow(index);
+      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;
       }
 
-      // 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 =pDecoder->GetPad(index);
-      float time =pDecoder->GetTime(index);
-      float sigmaY2=pDecoder->GetSigmaY2(index);
-      float sigmaZ2=pDecoder->GetSigmaZ2(index);
-      sigmaY2-=pad*pad;
-      sigmaZ2-=time*time;
-
+      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(pDecoder->GetCharge(index));
+       c.SetCharge(input.GetCharge());
        c.SetPad(pad);  
        c.SetTime(time);
        c.SetSigmaY2(sigmaY2);
        c.SetSigmaZ2(sigmaZ2);
-       c.SetQMax(pDecoder->GetQMax(index));
+       c.SetQMax(input.GetQMax());
       } else {
-       AliHLTUInt64_t padrow64=pDecoder->GetPadRow(index);
+       AliHLTUInt64_t padrow64=input.GetPadRow();
        if (padrow64==lastPadRow) {
          padrow64-=lastPadRow;
        } else if (padrow64>lastPadRow) {
@@ -780,21 +732,61 @@ int AliHLTTPCHWCFSpacePointContainer::WriteSorted(AliHLTUInt8_t* outputPtr,
          AliFatal("padrows not ordered");
        }
 
-       AliHLTUInt64_t pad64
-         =(AliHLTUInt64_t)round(pad*AliHLTTPCDefinitions::fgkClusterParameterDefinitions[AliHLTTPCDefinitions::kPad].fScale);
-       AliHLTUInt64_t time64
-         =(AliHLTUInt64_t)round(time*AliHLTTPCDefinitions::fgkClusterParameterDefinitions[AliHLTTPCDefinitions::kTime].fScale);
-       AliHLTUInt64_t sigmaY264
-         =(AliHLTUInt64_t)round(sigmaY2*AliHLTTPCDefinitions::fgkClusterParameterDefinitions[AliHLTTPCDefinitions::kSigmaY2].fScale);
-       AliHLTUInt64_t sigmaZ264
-         =(AliHLTUInt64_t)round(sigmaZ2*AliHLTTPCDefinitions::fgkClusterParameterDefinitions[AliHLTTPCDefinitions::kSigmaZ2].fScale);
+       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 {
+           dpad64=pad64-lastPad64;
+           signdPad=0;
+         }
+         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);  
+       pDeflater->OutputParameterBits(AliHLTTPCDefinitions::kPad    , pad64);
+       if (fMode&kModeDifferentialPadTime) pDeflater->OutputBit(padType);
+       if (fMode&kModeDifferentialPadTime && padType==0) pDeflater->OutputBit(signdPad);
        pDeflater->OutputParameterBits(AliHLTTPCDefinitions::kTime   , time64);
-       pDeflater->OutputParameterBits(AliHLTTPCDefinitions::kSigmaY2, sigmaY264);
+       if (fMode&kModeDifferentialPadTime) pDeflater->OutputBit(signdTime);
+       if (padType==0) pDeflater->OutputParameterBits(AliHLTTPCDefinitions::kSigmaY2, sigmaY264);
        pDeflater->OutputParameterBits(AliHLTTPCDefinitions::kSigmaZ2, sigmaZ264);
-       pDeflater->OutputParameterBits(AliHLTTPCDefinitions::kCharge , pDecoder->GetCharge(index));
-       pDeflater->OutputParameterBits(AliHLTTPCDefinitions::kQMax   , pDecoder->GetQMax(index));
+       pDeflater->OutputParameterBits(AliHLTTPCDefinitions::kCharge , input.GetCharge());
+       pDeflater->OutputParameterBits(AliHLTTPCDefinitions::kQMax   , input.GetQMax());
       }
       blockout->fCount++;
     }
@@ -804,17 +796,34 @@ int AliHLTTPCHWCFSpacePointContainer::WriteSorted(AliHLTUInt8_t* outputPtr,
   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);
-  bd.fDataType      = AliHLTTPCDefinitions::fgkRawClustersDataType;
   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);
+      outputBlocks.push_back(bd);    
+      size += bd.fSize;
+    } else {
+      iResult=-ENOSPC;
+    }
+    fWrittenClusterIds->clear();
+  }
+
   if (iResult<0) return iResult;
   return size;
 }
@@ -869,9 +878,10 @@ void AliHLTTPCHWCFSpacePointContainer::AliHLTTPCHWCFSpacePointProperties::Print(
     out << "no data";
     return;
   }
+  std::stringstream str;
   const AliHLTTPCHWCFData* decoder=Decoder();
-  out.setf(ios::fixed,ios::floatfield);
-  out << " " << setfill(' ') << setw(3) << decoder->GetPadRow(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) 
@@ -879,6 +889,7 @@ void AliHLTTPCHWCFSpacePointContainer::AliHLTTPCHWCFSpacePointProperties::Print(
       << " " << setw(5) << decoder->GetCharge(fIndex) 
       << " " << setw(5) << decoder->GetQMax(fIndex)
       << " " << fTrackId << " " << fMCId << " " << fUsed;
+  out << str.str();
 }
 
 ostream& operator<<(ostream &out, const AliHLTTPCHWCFSpacePointContainer::AliHLTTPCHWCFSpacePointProperties& p)