adding further optimized compression format with additional 15% compression ratio...
authorrichterm <richterm@f7af4fe6-9843-0410-8265-dc069ae4e863>
Thu, 13 Oct 2011 20:35:01 +0000 (20:35 +0000)
committerrichterm <richterm@f7af4fe6-9843-0410-8265-dc069ae4e863>
Thu, 13 Oct 2011 20:35:01 +0000 (20:35 +0000)
HLT/TPCLib/AliHLTTPCHWCFSpacePointContainer.cxx
HLT/TPCLib/AliHLTTPCHWCFSpacePointContainer.h
HLT/TPCLib/AliHLTTPCTrackGeometry.cxx
HLT/TPCLib/comp/AliHLTTPCDataCompressionComponent.cxx
HLT/TPCLib/comp/AliHLTTPCDataCompressionComponent.h
HLT/TPCLib/comp/AliHLTTPCDataCompressionDecoder.h

index 2d8bdb10b927b33b26d28127f2ad62f6058b1c82..125fbca75f21513751f2722e5022e3b5c7bb1275 100644 (file)
@@ -671,9 +671,12 @@ 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;
+  AliHLTUInt64_t lastPad64=0.;
+  AliHLTUInt64_t lastTime64=0.;
   AliHLTSpacePointPropertyGrid::iterator clusterID=pGrid->begin();
   if (clusterID!=pGrid->end()) {
     for (; clusterID!=pGrid->end(); clusterID++) {
@@ -707,7 +710,6 @@ int AliHLTTPCHWCFSpacePointContainer::WriteSorted(AliHLTUInt8_t* outputPtr,
       float time =input.GetTime();
       float sigmaY2=input.GetSigmaY2();
       float sigmaZ2=input.GetSigmaZ2();
-
       if (!pDeflater) {
        AliHLTTPCRawCluster& c=blockout->fClusters[blockout->fCount];
        padrow+=AliHLTTPCTransform::GetFirstRow(part);
@@ -729,18 +731,58 @@ int AliHLTTPCHWCFSpacePointContainer::WriteSorted(AliHLTUInt8_t* outputPtr,
          AliFatal("padrows not ordered");
        }
 
+       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 , input.GetCharge());
        pDeflater->OutputParameterBits(AliHLTTPCDefinitions::kQMax   , input.GetQMax());
index a98fb3c393ece33ac6c80a786aba15f9070dc0fb..6293cfbb189b033980770a88ccc74ddd443a352c 100644 (file)
@@ -40,7 +40,8 @@ class AliHLTTPCHWCFSpacePointContainer : public AliHLTSpacePointContainer
 
   enum {
     kModeSingle = 0x1,
-    kModeCreateMap = 0x2
+    kModeCreateMap = 0x2,
+    kModeDifferentialPadTime = 0x4
   };
 
   virtual bool Check(AliHLTUInt32_t clusterID) const;
index db166ef1cdbecc3c827be23e3e827bf6d4d6146f..ec5b11d67f3c2c267735a121b404fd1a96b02a4e 100644 (file)
@@ -536,19 +536,51 @@ int AliHLTTPCTrackGeometry::WriteAssociatedClusters(AliHLTSpacePointContainer* p
            //   << "  qmax "   << setfill(' ') << setw(4) << fixed << right << qmax
            //   << endl;
 
+           // time and pad coordinates are scaled and transformed to integer values for
+           // both cluster and track point before calculating the residual. this makes
+           // the compression lossless with respect to the format without track model
+           // compression
            AliHLTUInt64_t deltapad64=0;
            AliHLTUInt32_t signDeltaPad=0;
            if (!isnan(deltapad)) {
-             if (deltapad<0.) {deltapad*=-1; signDeltaPad=1;}
-             deltapad*=AliHLTTPCDefinitions::fgkClusterParameterDefinitions[AliHLTTPCDefinitions::kResidualPad].fScale;
-             deltapad64=(AliHLTUInt64_t)round(deltapad);
+             double clusterpad=pSpacePoints->GetY(clid->fId);
+             double trackpad=clrow->GetU();
+             if (clusterpad<0.) {
+               HLTError("cluster 0x%08x has negative pad position", clid->fId, clusterpad);
+             }
+             clusterpad*=AliHLTTPCDefinitions::fgkClusterParameterDefinitions[AliHLTTPCDefinitions::kResidualPad].fScale;
+             trackpad*=AliHLTTPCDefinitions::fgkClusterParameterDefinitions[AliHLTTPCDefinitions::kResidualPad].fScale;
+             AliHLTUInt64_t clusterpad64=(AliHLTUInt64_t)round(clusterpad);
+             AliHLTUInt64_t trackpad64=0;
+             if (trackpad>0.) trackpad64=(AliHLTUInt64_t)round(trackpad);
+             if (clusterpad64<trackpad64) {
+               deltapad64=trackpad64-clusterpad64;
+               signDeltaPad=1;
+             } else {
+               deltapad64=clusterpad64-trackpad64;
+               signDeltaPad=0;
+             }
            }
            AliHLTUInt64_t deltatime64=0;
            AliHLTUInt32_t signDeltaTime=0;
            if (!isnan(deltatime)) {
-             if (deltatime<0.) {deltatime*=-1; signDeltaTime=1;}
-             deltatime*=AliHLTTPCDefinitions::fgkClusterParameterDefinitions[AliHLTTPCDefinitions::kResidualTime].fScale;
-             deltatime64=(AliHLTUInt64_t)round(deltatime);
+             double clustertime=pSpacePoints->GetZ(clid->fId);
+             double tracktime=clrow->GetV();
+             if (clustertime<0.) {
+               HLTError("cluster 0x%08x has negative time position", clid->fId, clustertime);
+             }
+             clustertime*=AliHLTTPCDefinitions::fgkClusterParameterDefinitions[AliHLTTPCDefinitions::kResidualTime].fScale;
+             tracktime*=AliHLTTPCDefinitions::fgkClusterParameterDefinitions[AliHLTTPCDefinitions::kResidualTime].fScale;
+             AliHLTUInt64_t clustertime64=(AliHLTUInt64_t)round(clustertime);
+             AliHLTUInt64_t tracktime64=0;
+             if (tracktime>0.) tracktime64=(AliHLTUInt64_t)round(tracktime);
+             if (clustertime64<tracktime64) {
+               deltatime64=tracktime64-clustertime64;
+               signDeltaTime=1;
+             } else {
+               deltatime64=clustertime64-tracktime64;
+               signDeltaTime=0;
+             }
            }
            AliHLTUInt64_t sigmaY264=0;
            if (!isnan(sigmaY2)) sigmaY264=(AliHLTUInt64_t)round(sigmaY2*AliHLTTPCDefinitions::fgkClusterParameterDefinitions[AliHLTTPCDefinitions::kSigmaY2].fScale);
index 7a254083aef559d70567c5ef17cd29a9ca2c06d8..18d50f637ec52a335c6492598e542739f7a94caf 100644 (file)
@@ -132,6 +132,19 @@ AliHLTComponent* AliHLTTPCDataCompressionComponent::Spawn()
   return new AliHLTTPCDataCompressionComponent;
 }
 
+void AliHLTTPCDataCompressionComponent::GetOCDBObjectDescription(TMap* const targetMap)
+{
+  /// Get a list of OCDB object needed for the particular component
+  if (!targetMap) return;
+
+  targetMap->Add(new TObjString("HLT/ConfigTPC/TPCDataCompressor"),
+                new TObjString("component arguments"));
+  if (fDeflaterMode==2) {
+    targetMap->Add(new TObjString("HLT/ConfigTPC/TPCDataCompressorHuffmanTables"),
+                  new TObjString("huffman tables for deflater mode 2"));
+  }
+}
+
 int AliHLTTPCDataCompressionComponent::DoEvent( const AliHLTComponentEventData& /*evtData*/, 
                                                const AliHLTComponentBlockData* /*inputBlocks*/, 
                                                AliHLTComponentTriggerData& /*trigData*/,
@@ -169,6 +182,7 @@ int AliHLTTPCDataCompressionComponent::DoEvent( const AliHLTComponentEventData&
   AliHLTUInt32_t outputDataSize=0;
   int allClusters=0;
   int associatedClusters=0;
+  float bz=GetBz();
 
   /// input track array
   vector<AliHLTGlobalBarrelTrack> inputTrackArray;
@@ -205,7 +219,7 @@ int AliHLTTPCDataCompressionComponent::DoEvent( const AliHLTComponentEventData&
   vector<int> trackindexmap; // stores index for every track id
 
   // track data input
-  if (fMode==2) {
+  if (fMode==2 || fMode==4) {
     for (pDesc=GetFirstInputBlock(kAliHLTDataTypeTrack|kAliHLTDataOriginTPC);
         pDesc!=NULL; pDesc=GetNextInputBlock()) {
       if (GetBenchmarkInstance()) {
@@ -261,9 +275,33 @@ int AliHLTTPCDataCompressionComponent::DoEvent( const AliHLTComponentEventData&
     AliHLTTPCTrackGeometry* trackpoints=new AliHLTTPCTrackGeometry;
     if (!trackpoints) continue;
     HLTDebug("track %d id %d:", trackindex, trackID);
+
+    // in order to avoid rounding errors the track points are
+    // calculated in exactly the same way as in the decoding
+    // Thats why the track instance can not be used directly
+    // but a new instance is created from the values in the
+    // storage format.
+    // think about moving that to some common code used by
+    // both compression and decoding
+    AliHLTExternalTrackParam param;
+    memset(&param, 0, sizeof(param));    
+    float alpha=track->GetAlpha();
+    while (alpha<0.) alpha+=TMath::TwoPi();
+    while (alpha>TMath::TwoPi()) alpha-=TMath::TwoPi();
+    AliHLTUInt8_t tSlice=AliHLTUInt8_t(9*alpha/TMath::Pi());
+    param.fAlpha   =( tSlice + 0.5 ) * TMath::Pi() / 9.0;
+    if (param.fAlpha>TMath::TwoPi()) param.fAlpha-=TMath::TwoPi();
+    param.fX       = track->GetX();
+    param.fY       = track->GetY();
+    param.fZ       = track->GetZ();
+    param.fSinPsi  = track->GetSnp();
+    param.fTgl     = track->GetTgl();
+    param.fq1Pt    = track->GetSigned1Pt();
+    AliHLTGlobalBarrelTrack ctrack(param);
+    ctrack.CalculateHelixParams(bz);
     trackpoints->InitDriftTimeTransformation(fDriftTimeFactorA, fDriftTimeOffsetA, fDriftTimeFactorC, fDriftTimeOffsetC);
     trackpoints->SetTrackId(trackID);
-    trackpoints->CalculateTrackPoints(*track);
+    trackpoints->CalculateTrackPoints(ctrack);
     trackpoints->RegisterTrackPoints(fTrackGrid);
     track->SetTrackGeometry(trackpoints);
   }
@@ -399,7 +437,7 @@ int AliHLTTPCDataCompressionComponent::DoEvent( const AliHLTComponentEventData&
     }
 
     AliHLTUInt32_t parameterIndex=0;
-    trackModelBlock->fGlobalParameters[parameterIndex++]=GetBz();
+    trackModelBlock->fGlobalParameters[parameterIndex++]=bz;
     trackModelBlock->fGlobalParameters[parameterIndex++]=fDriftTimeFactorA;
     trackModelBlock->fGlobalParameters[parameterIndex++]=fDriftTimeOffsetA;
     trackModelBlock->fGlobalParameters[parameterIndex++]=fDriftTimeFactorC;
@@ -410,7 +448,7 @@ int AliHLTTPCDataCompressionComponent::DoEvent( const AliHLTComponentEventData&
       break;
     }
 
-    if (fMode==2) {
+    if (trackindexmap.size()>0) {// condition for track model compression
     iResult=WriteTrackClusters(inputTrackArray, fRawInputClusters, fpDataDeflater, outputPtr+size+tracksBufferOffset, capacity-size-tracksBufferOffset);
     if (iResult>=0) {
       AliHLTComponent_BlockData bd;
@@ -750,7 +788,15 @@ int AliHLTTPCDataCompressionComponent::DoInit( int argc, const char** argv )
     return -ENOMEM;
   }
 
-  unsigned spacePointContainerMode=(fMode==2)?AliHLTTPCHWCFSpacePointContainer::kModeCreateMap:0;
+  unsigned spacePointContainerMode=0;
+  if (fMode==2 || fMode==4) {
+    // initialize map data for cluster access in the track association loop
+    spacePointContainerMode|=AliHLTTPCHWCFSpacePointContainer::kModeCreateMap;
+  }
+  if (fMode==3 || fMode==4) {
+    // optimized storage format: differential pad and time storage
+    spacePointContainerMode|=AliHLTTPCHWCFSpacePointContainer::kModeDifferentialPadTime;
+  }
   std::auto_ptr<AliHLTTPCHWCFSpacePointContainer> rawInputClusters(new AliHLTTPCHWCFSpacePointContainer(spacePointContainerMode));
   std::auto_ptr<AliHLTTPCSpacePointContainer> inputClusters(new AliHLTTPCSpacePointContainer);
 
index 837ce0297d56ccc54d84005f4d74b66e6e78704c..1679eccb82ca3bb4fcc89825b023f8a3e7a0f232 100644 (file)
@@ -31,6 +31,12 @@ class TH1F;
  * of TPC data.
  *
  * <h2>General properties:</h2>
+ * The component subscribes to the output of the HW cluster finder (emulator)
+ * and performs various types of dat compressions. For each input block a
+ * block of compressed clusters is created. If track model compression is
+ * enabled, all clusters associated to a track are stored in a separate
+ * block together with the tracks. Those clusters are removed from the cluster
+ * blocks of the individual partitions.
  *
  * Component ID: \b TPCDataCompressor      <br>
  * Library: \b libAliHLTTPC.so     <br>
@@ -40,22 +46,54 @@ class TH1F;
  *  -  kAliHLTDataTypeTrack|kAliHLTDataOriginTPC
  * Output Data Types: none <br>
  *
+ * <h2>Data Formats</h2>
+ * Two formats for compressed clusters can be used.
+ * <h3>Format v1</h3>
+ * Format v1 stores the cluster parameters with the following precision:
+ * <pre>
+ *   padrow number & local padrow in partition    &   6 \\ 
+ *   pad position  & pitch 0.4/0.6 cm -> 1/60     &  14 \\ 
+ *   timebin       & 0.25cm/timebin   -> 1/25     &  15 \\ 
+ *   sigmaY2       &                              &   8 \\ 
+ *   sigmaZ2       &                              &   8 \\ 
+ *   total charge  & encoded 10bit number         &   8 \\ 
+ *   max charge    & encoded 16bit number         &  11 \\ 
+ * <pre>
+ * For the padrow, only the difference to the last padrow is stored. The
+ * clusters are ordered by padrow such that there are only positive differences.
+ *
+ * <h3>Format v2</h3>
+ * Format v2 uses the same parameters as v1 but treats single-pad clusters
+ * specially. Furthermore it stores the differences of pad and time with respect
+ * to the previous cluster. The difference is calculated on integers after the
+ * scale and lossy conversion of the float values to integer numbers. Format v2
+ * prepares all parameters for optimal huffman compression.
+ *
  * <h2>Mandatory arguments:</h2>
  * <!-- NOTE: ignore the \li. <i> and </i>: it's just doxygen formatting -->
  *
  * <h2>Optional arguments:</h2>
  * <!-- NOTE: ignore the \li. <i> and </i>: it's just doxygen formatting -->
  * \li -mode     <i> number  </i> <br>
- *      compression mode
- * \li -deflater-mode     <i> number  </i> <br>
- *      data deflater mode
- * \li -histogram-file     <i> file  </i> <br>
+ *      compression mode                                             <br>
+ *      1 compressed format version 1                                <br>
+ *      2 compressed format version 1 & track model compression      <br>
+ *      3 compressed format version 2                                <br>
+ *      4 compressed format version 2 & track model compression      <br>
+ * \li -deflater-mode     <i> number  </i>                           <br>
+ *      data deflater mode                                           <br>
+ *      0 no data deflation                                          <br>
+ *      1 simple deflation (AliHLTDataDeflaterSimple)                <br>
+ *      2 huffman deflation (AliHLTDataDeflaterHuffman)              <br>
+ * \li -histogram-file     <i> file  </i>                            <br>
  *      file to store internal histograms at the end
  *
  * <h2>Configuration:</h2>
  * <!-- NOTE: ignore the \li. <i> and </i>: it's just doxygen formatting -->
  *
  * <h2>Default CDB entries:</h2>
+ * - HLT/ConfigTPC/TPCDataCompressor
+ * - HLT/ConfigTPC/TPCDataCompressorHuffmanTables
  *
  * <h2>Performance:</h2>
  *
@@ -91,6 +129,9 @@ public:
   /// inherited from AliHLTComponent: spawn function.
   virtual AliHLTComponent* Spawn();
 
+  /// inherited from AliHLTComponent: list of OCDB objects
+  void GetOCDBObjectDescription(TMap* const targetMap);
+
   struct AliHLTTPCTrackModelBlock {
     AliHLTUInt8_t  fVersion;             //! version of the header
     AliHLTUInt8_t  fDeflaterMode;        //! deflater mode
index cdb7daa3dcb8a68b4c16cf46485b76f8b1e8bcbc..445ed015900ffe31902341ab605adc23383dfa12 100644 (file)
@@ -36,7 +36,7 @@ class AliHLTTPCDataCompressionDecoder : public AliHLTLogging {
   int ReadRemainingClustersCompressed(T& c, const AliHLTUInt8_t* pData, int dataSize, AliHLTUInt32_t specification);
 
   template<typename T>
-  int ReadRemainingClustersCompressed(T& c, AliHLTDataInflater* pInflater, int nofClusters, AliHLTUInt32_t specification);
+  int ReadRemainingClustersCompressed(T& c, AliHLTDataInflater* pInflater, int nofClusters, AliHLTUInt32_t specification, int formatVersion=0);
 
   template<typename T>
   int ReadTrackModelClustersCompressed(T& c, const AliHLTUInt8_t* pData, int dataSize, AliHLTUInt32_t specification);
@@ -66,7 +66,17 @@ int AliHLTTPCDataCompressionDecoder::ReadRemainingClustersCompressed(T& c, const
   const AliHLTTPCRawClusterData* clusterData = reinterpret_cast<const AliHLTTPCRawClusterData*>(pBuffer);
   Int_t nCount = (Int_t) clusterData->fCount;
 
-  AliHLTDataInflater* inflater=CreateInflater(clusterData->fVersion, 1);
+  int formatVersion=1;
+  int deflaterMode=2;
+  switch (clusterData->fVersion) {
+  case 1: deflaterMode=1; formatVersion=0; break;
+  case 2: deflaterMode=2; formatVersion=0; break;
+  case 3: deflaterMode=1; formatVersion=1; break;
+  case 4: deflaterMode=2; formatVersion=1; break;
+  default:
+    return -EBADF;
+  }
+  AliHLTDataInflater* inflater=CreateInflater(deflaterMode, 1);
   if (!inflater) return -ENODEV;
 
   if ((iResult=inflater->InitBitDataInput(reinterpret_cast<const AliHLTUInt8_t*>(clusterData->fClusters),
@@ -74,13 +84,13 @@ int AliHLTTPCDataCompressionDecoder::ReadRemainingClustersCompressed(T& c, const
     return iResult;
   }
 
-  iResult=ReadRemainingClustersCompressed(c, inflater, nCount, specification);
+  iResult=ReadRemainingClustersCompressed(c, inflater, nCount, specification, formatVersion);
 
   return iResult;
 }
 
 template<typename T>
-int AliHLTTPCDataCompressionDecoder::ReadRemainingClustersCompressed(T& c, AliHLTDataInflater* pInflater, int nofClusters, AliHLTUInt32_t specification)
+int AliHLTTPCDataCompressionDecoder::ReadRemainingClustersCompressed(T& c, AliHLTDataInflater* pInflater, int nofClusters, AliHLTUInt32_t specification, int formatVersion)
 {
   // read cluster data
 
@@ -94,13 +104,19 @@ int AliHLTTPCDataCompressionDecoder::ReadRemainingClustersCompressed(T& c, AliHL
   // add the first row in the partition to get global row number
   int rowOffset=AliHLTTPCTransform::GetFirstRow(partition);
 
-  int parameterId=0;
+  int parameterId=pInflater->NextParameter();
+  if (parameterId<0) return parameterId;
   int outClusterCnt=0;
   AliHLTUInt64_t value=0;
   AliHLTUInt32_t length=0;
   AliHLTUInt32_t lastPadRow=0;
+  AliHLTUInt64_t lastPad64=0;
+  AliHLTUInt64_t lastTime64=0;
+  AliHLTUInt8_t isSinglePad=0;
+  AliHLTUInt8_t sign=0;
   bool bNextCluster=true;
-  while (outClusterCnt<nofClusters && pInflater->NextValue(value, length)) {
+  bool bReadSuccess=true;
+  while (outClusterCnt<nofClusters && bReadSuccess && pInflater->NextValue(value, length)) {
     if (bNextCluster) {
       // switch to next cluster
       c.Next(slice, partition);
@@ -118,10 +134,39 @@ int AliHLTTPCDataCompressionDecoder::ReadRemainingClustersCompressed(T& c, AliHL
     switch (parameterId) {
     case AliHLTTPCDefinitions::kPadRow:
       {c.SetPadRow(value+lastPadRow+rowOffset); lastPadRow+=value;break;}
-    case AliHLTTPCDefinitions::kPad:
-      {float pad=value; pad/=parameter.fScale; c.SetPad(pad); break;}
-    case AliHLTTPCDefinitions::kTime:
-      {float time=value; time/=parameter.fScale; c.SetTime(time); break;}
+    case AliHLTTPCDefinitions::kPad: {
+      if (formatVersion==1) {
+       bReadSuccess=bReadSuccess && pInflater->InputBit(isSinglePad);
+       if (isSinglePad==0) {
+         bReadSuccess=bReadSuccess && pInflater->InputBit(sign);
+         if (sign) {
+           value=lastPad64-value;
+         } else {
+           value+=lastPad64;
+         }
+         lastPad64=value;
+       }
+      }
+      float pad=value;
+      if (isSinglePad==0) pad/=parameter.fScale;
+      else pad/=2; // for the sake of the 0.5 pad offset (see AliHLTTPCHWCFSpacePointContainer::WriteSorted for details)
+      c.SetPad(pad);
+      break;
+    }
+    case AliHLTTPCDefinitions::kTime: {
+      if (formatVersion==1) {
+       bReadSuccess=bReadSuccess && pInflater->InputBit(sign);
+       if (sign) {
+         value=lastTime64-value;
+       } else {
+         value+=lastTime64;
+       }
+       lastTime64=value;
+      }
+      float time=value; time/=parameter.fScale;
+      c.SetTime(time);
+      break;
+    }
     case AliHLTTPCDefinitions::kSigmaY2:
       {float sigmaY2=value; sigmaY2/=parameter.fScale; c.SetSigmaY2(sigmaY2); break;}
     case AliHLTTPCDefinitions::kSigmaZ2:
@@ -134,9 +179,14 @@ int AliHLTTPCDataCompressionDecoder::ReadRemainingClustersCompressed(T& c, AliHL
     if (parameterId>=AliHLTTPCDefinitions::kLast) {
       bNextCluster=true;
       outClusterCnt++;
-      parameterId=-1;
     }
-    parameterId++;
+    parameterId=pInflater->NextParameter();
+    if (parameterId==AliHLTTPCDefinitions::kSigmaY2 && isSinglePad==1) {
+      // skip sigmaY for single pad clusters in format version 1
+      parameterId=pInflater->NextParameter();
+      isSinglePad=0;
+      c.SetSigmaY2(0.);
+    }
   }
   pInflater->Pad8Bits();
   AliHLTUInt8_t bit=0;
@@ -292,6 +342,7 @@ int AliHLTTPCDataCompressionDecoder::ReadTrackClustersCompressed(T& c, AliHLTDat
       if (bNextCluster) {
        // switch to next cluster
        c.Next(slice, partition);
+       c.SetPadRow(row);
        bNextCluster=false;
       }
       const AliHLTTPCDefinitions::AliClusterParameter& parameter
@@ -311,9 +362,17 @@ int AliHLTTPCDataCompressionDecoder::ReadTrackClustersCompressed(T& c, AliHLTDat
        {
          AliHLTUInt8_t sign=0;
          bReadSuccess=bReadSuccess && pInflater->InputBit(sign);
-         float pad=value*(sign?-1.:1.); pad/=parameter.fScale;
-         deltapad=pad;
-         pad+=currentTrackPoint->GetU();
+         deltapad=((float)value)*(sign?-1.:1.)/parameter.fScale;
+         AliHLTUInt64_t trackpad64=0;
+         double trackpad=currentTrackPoint->GetU();
+         trackpad*=AliHLTTPCDefinitions::fgkClusterParameterDefinitions[AliHLTTPCDefinitions::kResidualPad].fScale;
+         if (currentTrackPoint->GetU()>0.) trackpad64=(AliHLTUInt64_t)round(trackpad);
+         if (sign) {
+           value=trackpad64-value;
+         } else {
+           value+=trackpad64;
+         }
+         float pad=((float)value)/parameter.fScale;
          c.SetPad(pad); 
          break;
        }
@@ -321,10 +380,18 @@ int AliHLTTPCDataCompressionDecoder::ReadTrackClustersCompressed(T& c, AliHLTDat
        {
          AliHLTUInt8_t sign=0;
          bReadSuccess=bReadSuccess && pInflater->InputBit(sign);
-         float time=value*(sign?-1.:1.); time/=parameter.fScale;
-         deltatime=time;
-         time+=currentTrackPoint->GetV();
-         c.SetTime(time);
+         deltatime=((float)value)*(sign?-1.:1.)/parameter.fScale;
+         AliHLTUInt64_t tracktime64=0;
+         double tracktime=currentTrackPoint->GetV();
+         tracktime*=AliHLTTPCDefinitions::fgkClusterParameterDefinitions[AliHLTTPCDefinitions::kResidualTime].fScale;
+         if (currentTrackPoint->GetV()>0.) tracktime64=(AliHLTUInt64_t)round(tracktime);
+         if (sign) {
+           value=tracktime64-value;
+         } else {
+           value+=tracktime64;
+         }
+         float time=((float)value)/parameter.fScale;
+         c.SetTime(time); 
          break;
        }
       case AliHLTTPCDefinitions::kSigmaY2:
@@ -342,7 +409,6 @@ int AliHLTTPCDataCompressionDecoder::ReadTrackClustersCompressed(T& c, AliHLTDat
       }
       if (lastParameter) {
        // switch to next cluster
-       c.SetPadRow(row);
        // cout << "  row "    << setfill(' ') << setw(3) << fixed << right                     << c.GetRow()
        //      << "  pad "    << setfill(' ') << setw(7) << fixed << right << setprecision (4) << c.GetPad()
        //      << "  dpad "   << setfill(' ') << setw(7) << fixed << right << setprecision (4) << deltapad