]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/TPCLib/AliHLTTPCTrackGeometry.cxx
correcting calculation of padrow crossings for tracks; writing of associated clusters...
[u/mrichter/AliRoot.git] / HLT / TPCLib / AliHLTTPCTrackGeometry.cxx
1 // $Id$
2
3 //**************************************************************************
4 //* This file is property of and copyright by the ALICE HLT Project        * 
5 //* ALICE Experiment at CERN, All rights reserved.                         *
6 //*                                                                        *
7 //* Primary Authors: Matthias Richter <Matthias.Richter@ift.uib.no>        *
8 //*                  for The ALICE HLT Project.                            *
9 //*                                                                        *
10 //* Permission to use, copy, modify and distribute this software and its   *
11 //* documentation strictly for non-commercial purposes is hereby granted   *
12 //* without fee, provided that the above copyright notice appears in all   *
13 //* copies and that both the copyright notice and this permission notice   *
14 //* appear in the supporting documentation. The authors make no claims     *
15 //* about the suitability of this software for any purpose. It is          *
16 //* provided "as is" without express or implied warranty.                  *
17 //**************************************************************************
18
19 /// @file   AliHLTTPCTrackGeometry.cxx
20 /// @author Matthias Richter
21 /// @date   2011-05-20
22 /// @brief  Desciption of a track by a sequence of track points
23 ///
24
25 #include "AliHLTTPCTrackGeometry.h"
26 #include "AliHLTTPCTransform.h"
27 #include "AliHLTTPCSpacePointData.h"
28 #include "AliHLTTPCClusterDataFormat.h"
29 #include "AliHLTTPCSpacePointContainer.h"
30 #include "AliHLTTPCHWCFSpacePointContainer.h"
31 #include "AliHLTTPCDefinitions.h"
32 #include "AliHLTComponent.h"
33 #include "AliHLTGlobalBarrelTrack.h"
34 #include "AliHLTDataDeflater.h"
35 #include "TMath.h"
36 #include "TH2F.h"
37 #include <memory>
38
39 /** ROOT macro for the implementation of ROOT specific class methods */
40 ClassImp(AliHLTTPCTrackGeometry)
41
42 AliHLTTPCTrackGeometry::AliHLTTPCTrackGeometry()
43   : AliHLTTrackGeometry()
44   , fRawTrackPoints()
45 {
46   /// standard constructor
47 }
48
49 AliHLTTPCTrackGeometry::AliHLTTPCTrackGeometry(const AliHLTTPCTrackGeometry& src)
50   : AliHLTTrackGeometry(src)
51   , fRawTrackPoints(src.fRawTrackPoints)
52 {
53   /// copy constructor
54 }
55
56 AliHLTTPCTrackGeometry& AliHLTTPCTrackGeometry::operator=(const AliHLTTPCTrackGeometry& src)
57 {
58   /// assignment operator
59   AliHLTTrackGeometry::operator=(src);
60   fRawTrackPoints.assign(src.fRawTrackPoints.begin(), src.fRawTrackPoints.end());
61   return *this;
62 }
63
64 AliHLTTPCTrackGeometry::~AliHLTTPCTrackGeometry()
65 {
66   /// destructor
67 }
68
69 float AliHLTTPCTrackGeometry::GetPlaneAlpha(AliHLTUInt32_t planeId) const
70 {
71   /// alpha of the plane
72   UInt_t slice=AliHLTTPCSpacePointData::GetSlice(planeId);
73   float alpha=( slice + 0.5 ) * TMath::Pi() / 9.0;
74   if (alpha>TMath::TwoPi()) alpha-=TMath::TwoPi();
75   return alpha;
76 }
77
78 float AliHLTTPCTrackGeometry::GetPlaneR(AliHLTUInt32_t planeId) const
79 {
80   /// radial distance from global {0,0,0}
81   UInt_t partition=AliHLTTPCSpacePointData::GetPatch(planeId);
82   UInt_t number=AliHLTTPCSpacePointData::GetNumber(planeId);
83   Int_t row=AliHLTTPCTransform::GetFirstRow(partition)+number;
84   return AliHLTTPCTransform::Row2X(row);
85 }
86
87 float AliHLTTPCTrackGeometry::GetPlaneTheta(AliHLTUInt32_t /*planeId*/) const
88 {
89   /// theta of the plane
90   return 0.0;
91 }
92
93 bool AliHLTTPCTrackGeometry::CheckBounds(AliHLTUInt32_t planeId, float u, float /*v*/) const
94 {
95   /// check bounds in u and v coordinate
96   float r=GetPlaneR(planeId);
97   if (r<AliHLTTPCTransform::GetFirstRow(0)) return false;
98
99   // TODO: check if the pad width needs to be considered here
100   return TMath::Abs(TMath::ASin(u/r))<=TMath::Pi()/18;
101 }
102
103 int AliHLTTPCTrackGeometry::CalculateTrackPoints(const AliHLTExternalTrackParam& track)
104 {
105   /// calculate the track points, expects the global magnetic field to be initialized
106   AliHLTGlobalBarrelTrack bt(track);
107   return CalculateTrackPoints(bt);
108 }
109
110 int AliHLTTPCTrackGeometry::CalculateTrackPoints(AliHLTGlobalBarrelTrack& track)
111 {
112   /// calculate the track points, expects the global magnetic field to be initialized
113   int iResult=0;
114   int firstpadrow=0;
115   for (;
116        firstpadrow<AliHLTTPCTransform::GetNRows() && 
117          AliHLTTPCTransform::Row2X(firstpadrow)+AliHLTTPCTransform::GetPadLength(firstpadrow)<track.GetX();
118        firstpadrow++);
119   if (firstpadrow>=AliHLTTPCTransform::GetNRows()) return 0;
120   iResult=CalculateTrackPoints(track, firstpadrow, 1);
121   if (iResult>=0 && firstpadrow>0)
122     iResult=CalculateTrackPoints(track, firstpadrow-1, -1);
123   return iResult;
124 }
125
126 int AliHLTTPCTrackGeometry::CalculateTrackPoints(AliHLTGlobalBarrelTrack& track, int firstpadrow, int step)
127 {
128   /// calculate the track points, expects the global magnetic field to be initialized
129   float offsetAlpha=0.0;
130   for (int padrow=firstpadrow; padrow>=0 && padrow<AliHLTTPCTransform::GetNRows(); padrow+=step) {
131     float x=AliHLTTPCTransform::Row2X(padrow);
132     float y=0.0;
133     float z=0.0;
134
135     int maxshift=9;
136     int shift=0;
137     int result=0;
138     do {
139       // start calculation of crossing points with padrow planes in the slice of the first point
140       // plane alpha corresponds to alpha of the track, switch to neighboring slice if the result
141       // is out of bounds
142       if ((result=track.CalculateCrossingPoint(x, track.GetAlpha()-offsetAlpha, y, z))<1) break;
143       float pointAlpha=TMath::ATan(y/x);
144       if (TMath::Abs(pointAlpha)>TMath::Pi()/18) {
145         offsetAlpha+=(pointAlpha>0?-1:1)*TMath::Pi()/9;
146         result=0;
147       }
148     } while (result==0 && shift++<maxshift);
149     if (result<1) continue;
150     float planealpha=track.GetAlpha()-offsetAlpha;
151     if (planealpha<0) planealpha+=TMath::TwoPi();
152     int slice=int(9*planealpha/TMath::Pi());
153     if (z<0) slice+=18;
154     int partition=AliHLTTPCTransform::GetPatch(padrow);
155     int row=padrow-AliHLTTPCTransform::GetFirstRow(partition);
156     UInt_t id=AliHLTTPCSpacePointData::GetID(slice, partition, row);
157     if (TMath::Abs(planealpha-GetPlaneAlpha(id))>0.0001) {
158       HLTError("alpha missmatch for plane %08x (slice %d): alpha from id %f (%.0f), expected %f (%.0f)", id, slice, GetPlaneAlpha(id), 180*GetPlaneAlpha(id)/TMath::Pi(), planealpha, 180*planealpha/TMath::Pi());
159     }
160     if (AddTrackPoint(AliHLTTrackPoint(id, y, z), AliHLTTPCSpacePointData::GetID(slice, partition, 0))>=0) {
161       Float_t rpt[3]={0.,y,z}; // row pad time
162       AliHLTTPCTransform::LocHLT2Raw(rpt, slice, padrow);
163       fRawTrackPoints.push_back(AliHLTTrackPoint(id, rpt[1], rpt[2]));
164     }
165   }
166   return 0;
167 }
168
169 int AliHLTTPCTrackGeometry::FindMatchingTrackPoint(AliHLTUInt32_t spacepointId, float spacepoint[3], AliHLTUInt32_t& planeId)
170 {
171   /// find the track point which can be associated to a spacepoint with coordinates and id
172   UInt_t slice=AliHLTTPCSpacePointData::GetSlice(spacepointId);
173   UInt_t partition=AliHLTTPCSpacePointData::GetPatch(spacepointId);
174   int row=AliHLTTPCTransform::GetPadRow(spacepoint[0]);
175   bool bSpecialRow=row==30 || row==90 || row==139;
176   if (row<AliHLTTPCTransform::GetFirstRow(partition) || row>AliHLTTPCTransform::GetLastRow(partition)) {
177     HLTError("row number %d calculated from x value %f is outside slice %d partition %d", row, spacepoint[0], slice, partition);
178     return -EINVAL;
179   }
180
181   // find the crossing point of the track with the padrow plane where
182   // the spacepoint is
183   // 1) calculate plane id from slice, partition and row (within partition)
184   row-=AliHLTTPCTransform::GetFirstRow(partition);
185   UInt_t id=AliHLTTPCSpacePointData::GetID(slice, partition, row);
186   const AliHLTTrackPoint* point=GetTrackPoint(id);
187   // track might be outside the partition and cross the central membrane
188   // search in the other half of the TPC
189   if (!point && slice<18) {
190     // search in the neighboring partition on the C side
191     id=AliHLTTPCSpacePointData::GetID(slice+18, partition, row);
192     point=GetTrackPoint(id);
193   } else if (!point && slice>=18) {
194     // search in the neighboring partition on the A side
195     id=AliHLTTPCSpacePointData::GetID(slice-18, partition, row);
196     point=GetTrackPoint(id);
197   }
198   
199   // search in the neighboring partition, this takes account for rows
200   // 30, 90, and 139 which are partly in one and the other partition
201   if (!point && bSpecialRow) {
202     row+=AliHLTTPCTransform::GetFirstRow(partition);
203     row-=AliHLTTPCTransform::GetFirstRow(partition-1);
204     id=AliHLTTPCSpacePointData::GetID(slice, partition-1, row);
205     point=GetTrackPoint(id);
206     if (!point && slice<18) {
207       // search in the neighboring partition on the C side
208       id=AliHLTTPCSpacePointData::GetID(slice+18, partition-1, row);
209       point=GetTrackPoint(id);
210     } else if (!point && slice>=18) {
211       // search in the neighboring partition on the A side
212       id=AliHLTTPCSpacePointData::GetID(slice-18, partition-1, row);
213       point=GetTrackPoint(id);
214     }
215   }
216
217   if (point) {
218     planeId=id;
219     if (point->HaveAssociatedSpacePoint()) {
220       if (GetVerbosity()>2) HLTInfo("descarding spacepoint 0x%08x z=%f y=%f z=%f: track point 0x%08x already occupied", spacepoint[0], spacepoint[1], spacepoint[2], planeId);
221       return 0; // already occupied
222     }
223     float maxdy=2.;
224     float maxdz=2.;
225     if (TMath::Abs(point->GetU()-spacepoint[1])>maxdy) {
226       if (GetVerbosity()>0) HLTInfo("descarding spacepoint 0x%08x y=%f z=%f: track point 0x%08x y %f outside tolerance %f", spacepoint[1], spacepoint[2], planeId, point->GetU(), maxdy);
227       return -ENOENT;
228     }
229     if (TMath::Abs(point->GetV()-spacepoint[2])>maxdz) {
230       if (GetVerbosity()>0) HLTInfo("descarding spacepoint 0x%08x y=%f z=%f: track point 0x%08x z %f outside tolerance %f", spacepoint[1], spacepoint[2], planeId, point->GetV(), maxdz);
231       return -ENOENT;
232     }
233     return 1;
234   }
235   return -ENOENT;
236 }
237
238
239 int AliHLTTPCTrackGeometry::RegisterTrackPoints(AliHLTTrackGrid* pGrid) const
240 {
241   /// register track points in the index grid, at this step the number
242   /// of tracks in each cell is counted
243   if (!pGrid) return -EINVAL;
244   int iResult=0;
245   for (vector<AliHLTTrackPoint>::const_iterator tp=TrackPoints().begin();
246        tp!=TrackPoints().end() && iResult>=0; tp++) {
247     AliHLTUInt32_t id=tp->GetId();
248     iResult=pGrid->CountSpacePoint(AliHLTTPCSpacePointData::GetSlice(id),
249                                    AliHLTTPCSpacePointData::GetPatch(id),
250                                    AliHLTTPCSpacePointData::GetNumber(id));
251   }
252   return iResult;
253 }
254
255 int AliHLTTPCTrackGeometry::FillTrackPoints(AliHLTTrackGrid* pGrid) const
256 {
257   /// fill track points to index grid
258   if (!pGrid) return -EINVAL;
259   int iResult=0;
260   for (vector<AliHLTTrackPoint>::const_iterator tp=TrackPoints().begin();
261        tp!=TrackPoints().end() && iResult>=0; tp++) {
262     AliHLTUInt32_t id=tp->GetId();
263     iResult=pGrid->AddSpacePoint(GetTrackId(),
264                                  AliHLTTPCSpacePointData::GetSlice(id),
265                                  AliHLTTPCSpacePointData::GetPatch(id),
266                                  AliHLTTPCSpacePointData::GetNumber(id));
267   }
268   return iResult;
269 }
270
271 AliHLTSpacePointContainer* AliHLTTPCTrackGeometry::ConvertToSpacePoints(bool bAssociated) const
272 {
273   /// create a collection of all points
274   std::auto_ptr<AliHLTTPCSpacePointContainer> spacepoints(new AliHLTTPCSpacePointContainer);
275   if (!spacepoints.get()) return NULL;
276
277   const vector<AliHLTTrackPoint>& trackPoints=TrackPoints();
278   unsigned i=0;
279   while (i<trackPoints.size()) {
280     // allocate buffer for all points, even though the buffer might not be filled
281     // completely because of a partition change
282     int nofPoints=trackPoints.size()-i;
283     int blocksize=sizeof(AliHLTTPCClusterData)+nofPoints*sizeof(AliHLTTPCSpacePointData);
284     AliHLTUInt8_t* pBuffer=spacepoints->Alloc(blocksize);
285     if (!pBuffer) return NULL;
286     AliHLTTPCClusterData* pClusterData=reinterpret_cast<AliHLTTPCClusterData*>(pBuffer);
287     pClusterData->fSpacePointCnt=0;
288     AliHLTTPCSpacePointData* pClusters=pClusterData->fSpacePoints;
289     int currentSlice=-1;
290     int currentPartition=-1;
291     for (; i<trackPoints.size(); i++) {
292       if (bAssociated && !trackPoints[i].HaveAssociatedSpacePoint()) continue;
293       AliHLTUInt32_t planeId=trackPoints[i].GetId();
294       int slice=AliHLTTPCSpacePointData::GetSlice(planeId);
295       int partition=AliHLTTPCSpacePointData::GetPatch(planeId);
296       int number=AliHLTTPCSpacePointData::GetNumber(planeId);
297       if ((currentSlice>=0 && currentSlice!=slice) || (currentPartition>=0 && currentPartition!=partition)) {
298         // change of partition or slice, need to go to next block
299         // 2011-07-26 currently all spacepoints go into one block, if separated
300         // blocks per partition are needed one has to leave the inner loop here
301         // and set the data block specification below
302         // Caution: not tested, only the last block seems to make it through
303         //break;
304       }
305       currentSlice=slice;
306       currentPartition=partition;
307       pClusters[pClusterData->fSpacePointCnt].fX=GetPlaneR(planeId);
308       pClusters[pClusterData->fSpacePointCnt].fY=trackPoints[i].GetU();
309       pClusters[pClusterData->fSpacePointCnt].fZ=trackPoints[i].GetV();
310       pClusters[pClusterData->fSpacePointCnt].fID=planeId;
311       pClusters[pClusterData->fSpacePointCnt].fPadRow=AliHLTTPCTransform::GetFirstRow(partition)+number;
312       pClusters[pClusterData->fSpacePointCnt].fSigmaY2=0.;
313       pClusters[pClusterData->fSpacePointCnt].fSigmaZ2=0.;
314       pClusters[pClusterData->fSpacePointCnt].fCharge=0;
315       pClusters[pClusterData->fSpacePointCnt].fQMax=0;
316       pClusters[pClusterData->fSpacePointCnt].fUsed=0;
317       pClusters[pClusterData->fSpacePointCnt].fTrackN=0;
318       pClusterData->fSpacePointCnt++;
319     }
320     AliHLTComponentBlockData bd;
321     AliHLTComponent::FillBlockData(bd);
322     bd.fPtr=pBuffer;
323     bd.fSize=sizeof(AliHLTTPCClusterData)+pClusterData->fSpacePointCnt*sizeof(AliHLTTPCSpacePointData);
324     AliHLTComponent::SetDataType(bd.fDataType, "CLUSTERS", "TPC ");
325     bd.fSpecification=kAliHLTVoidDataSpec;//AliHLTTPCDefinitions::EncodeDataSpecification(currentSlice, currentSlice, currentPartition, currentPartition);
326     spacepoints->AddInputBlock(&bd);
327   }
328
329   return spacepoints.release();
330 }
331
332 const AliHLTTrackGeometry::AliHLTTrackPoint* AliHLTTPCTrackGeometry::GetRawTrackPoint(AliHLTUInt32_t id) const
333 {
334   /// get raw track point of id
335   const AliHLTTrackGeometry::AliHLTTrackPoint* p=find(&fRawTrackPoints[0], &fRawTrackPoints[fRawTrackPoints.size()], id);
336   if (p==&fRawTrackPoints[fRawTrackPoints.size()]) return 0;
337   return p;
338 }
339
340 AliHLTTrackGeometry::AliHLTTrackPoint* AliHLTTPCTrackGeometry::GetRawTrackPoint(AliHLTUInt32_t id)
341 {
342   /// get raw track point of id
343   AliHLTTrackGeometry::AliHLTTrackPoint* p=find(&fRawTrackPoints[0], &fRawTrackPoints[fRawTrackPoints.size()], id);
344   if (p==&fRawTrackPoints[fRawTrackPoints.size()]) return 0;
345   return p;
346 }
347
348 int AliHLTTPCTrackGeometry::FillRawResidual(int coordinate, TH2* histo, AliHLTSpacePointContainer* points) const
349 {
350   // fill residual histogram
351   if (!histo || !points) return -EINVAL;
352   const vector<AliHLTTrackPoint>& trackPoints=TrackPoints();
353   for (vector<AliHLTTrackPoint>::const_iterator trackpoint=trackPoints.begin();
354        trackpoint!=trackPoints.end(); trackpoint++) {
355     if (!trackpoint->HaveAssociatedSpacePoint()) continue;
356     for (vector<AliHLTTrackSpacepoint>::const_iterator sp=(trackpoint->GetSpacepoints()).begin();
357          sp!=(trackpoint->GetSpacepoints()).end(); sp++) {
358     AliHLTUInt32_t spacepointId=sp->fId;
359     vector<AliHLTTrackPoint>::const_iterator rawpoint=find(fRawTrackPoints.begin(), fRawTrackPoints.end(), trackpoint->GetId());
360     if (rawpoint==fRawTrackPoints.end()) {
361       HLTError("can not find track raw coordinates of track point 0x%08x", trackpoint->GetId());
362       continue;
363     }
364     if (!points->Check(spacepointId)) {
365       //HLTError("can not find associated space point 0x%08x of track point 0x%08x", spacepointId, trackpoint->GetId());
366       continue;
367     }
368     float value=0.;
369     if (coordinate==0) {
370       value=rawpoint->GetU()-points->GetY(spacepointId);
371       histo->Fill(GetPlaneR(trackpoint->GetId()), value);
372     } else {
373       value=rawpoint->GetV()-points->GetZ(spacepointId);
374       //histo->Fill(GetPlaneR(trackpoint->GetId()), value);
375       histo->Fill(rawpoint->GetV(), value);
376     }
377     }
378   }
379   return 0;
380 }
381
382 int AliHLTTPCTrackGeometry::Write(const AliHLTGlobalBarrelTrack& track,
383                                   AliHLTSpacePointContainer* pSpacePoints,
384                                   AliHLTDataDeflater* pDeflater,
385                                   AliHLTUInt8_t* outputPtr,
386                                   AliHLTUInt32_t size,
387                                   const char* option) const
388 {
389   // write track block to buffer
390   if (size<=sizeof(AliHLTTPCTrackBlock)) return -ENOSPC;
391   AliHLTTPCTrackBlock* pTrackBlock=reinterpret_cast<AliHLTTPCTrackBlock*>(outputPtr);
392   pTrackBlock->fSize=sizeof(AliHLTTPCTrackBlock); // size of cluster block added later
393   pTrackBlock->fSlice=AliHLTUInt8_t(9*track.GetAlpha()/TMath::Pi());
394   pTrackBlock->fReserved=0;
395   pTrackBlock->fX      = track.GetX();
396   pTrackBlock->fY      = track.GetY();
397   pTrackBlock->fZ      = track.GetZ();
398   pTrackBlock->fSinPsi = track.GetSnp();
399   pTrackBlock->fTgl    = track.GetTgl();
400   pTrackBlock->fq1Pt   = track.GetSigned1Pt();
401
402   pDeflater->Clear();
403   pDeflater->InitBitDataOutput(reinterpret_cast<AliHLTUInt8_t*>(outputPtr+sizeof(AliHLTTPCTrackBlock)), size-sizeof(AliHLTTPCTrackBlock));
404   int result=WriteAssociatedClusters(pSpacePoints, pDeflater, option);
405   if (result<0) return result;
406   pTrackBlock->fSize+=result;
407   return pTrackBlock->fSize;
408 }
409
410 int AliHLTTPCTrackGeometry::WriteAssociatedClusters(AliHLTSpacePointContainer* pSpacePoints,
411                                                     AliHLTDataDeflater* pDeflater,
412                                                     const char* /*option*/) const
413 {
414   // write associated clusters to buffer via deflater
415   if (!pDeflater || !pSpacePoints) return -EINVAL;
416   AliHLTTPCHWCFSpacePointContainer* pTPCRawSpacePoints=dynamic_cast<AliHLTTPCHWCFSpacePointContainer*>(pSpacePoints);
417   if (!pTPCRawSpacePoints) return -EINVAL;
418   bool bReverse=true;
419   bool bWriteSuccess=true;
420   int writtenClusters=0;
421   // filling of track points starts from first point on track outwards, and
422   // then from that point inwards. That's why the lower padrows might be in
423   // reverse order at the end of the track point array. If the last element
424   // is bigger than the first element, only trackpoints in ascending order
425   // are in the array
426   vector<AliHLTTrackPoint>::const_iterator clrow=fRawTrackPoints.end();
427   if (clrow!=fRawTrackPoints.begin()) {
428     clrow--;
429     AliHLTUInt32_t partition=AliHLTTPCSpacePointData::GetPatch(clrow->GetId());
430     AliHLTUInt32_t partitionrow=AliHLTTPCSpacePointData::GetNumber(clrow->GetId());
431     partitionrow+=AliHLTTPCTransform::GetFirstRow(partition);
432     AliHLTUInt32_t firstpartition=AliHLTTPCSpacePointData::GetPatch(fRawTrackPoints.begin()->GetId());
433     AliHLTUInt32_t firstpartitionrow=AliHLTTPCSpacePointData::GetNumber(fRawTrackPoints.begin()->GetId());
434     firstpartitionrow+=AliHLTTPCTransform::GetFirstRow(firstpartition);
435     if (partitionrow>=firstpartitionrow) {
436       bReverse=false;
437       clrow=fRawTrackPoints.begin();
438     }
439   }
440   unsigned long dataPosition=pDeflater->GetCurrentByteOutputPosition();
441   for (unsigned row=0; row<159 && bWriteSuccess; row++) {
442     if (clrow!=fRawTrackPoints.end()) {
443       AliHLTUInt32_t thisPartition=AliHLTTPCSpacePointData::GetPatch(clrow->GetId());
444       AliHLTUInt32_t thisTrackRow=AliHLTTPCSpacePointData::GetNumber(clrow->GetId());
445       thisTrackRow+=AliHLTTPCTransform::GetFirstRow(thisPartition);
446       if (thisTrackRow==row) {
447         // write clusters
448         const vector<AliHLTTrackSpacepoint>&  clusters=clrow->GetSpacepoints();
449         AliHLTUInt32_t haveClusters=clusters.size()>0;
450         // 1 bit for clusters on that padrow
451         bWriteSuccess=bWriteSuccess && pDeflater->OutputBit(haveClusters);
452         if (haveClusters) {
453           bWriteSuccess=bWriteSuccess && pDeflater->OutputParameterBits(AliHLTTPCDefinitions::kClusterCount, clusters.size());
454           for (vector<AliHLTTrackSpacepoint>::const_iterator clid=clusters.begin();
455                clid!=clusters.end() && bWriteSuccess; clid++) {
456             if (!pSpacePoints->Check(clid->fId)) {
457               HLTError("can not find spacepoint 0x%08x", clid->fId);
458               continue;
459             }
460
461             float deltapad =clid->fdU;
462             float deltatime =clid->fdV;
463             float sigmaY2=pSpacePoints->GetYWidth(clid->fId);
464             float sigmaZ2=pSpacePoints->GetZWidth(clid->fId);
465             AliHLTUInt64_t charge=(AliHLTUInt64_t)pSpacePoints->GetCharge(clid->fId);
466             AliHLTUInt64_t qmax=(AliHLTUInt64_t)pTPCRawSpacePoints->GetQMax(clid->fId);
467
468             AliHLTUInt64_t deltapad64=0;
469             AliHLTUInt32_t signDeltaPad=0;
470             if (!isnan(deltapad)) {
471               if (deltapad<0.) {deltapad*=-1; signDeltaPad=1;}
472               deltapad*=AliHLTTPCDefinitions::fgkClusterParameterDefinitions[AliHLTTPCDefinitions::kResidualPad].fScale;
473               deltapad64=(AliHLTUInt64_t)round(deltapad);
474             }
475             AliHLTUInt64_t deltatime64=0;
476             AliHLTUInt32_t signDeltaTime=0;
477             if (!isnan(deltatime)) {
478               if (deltatime<0.) {deltatime*=-1; signDeltaTime=1;}
479               deltatime*=AliHLTTPCDefinitions::fgkClusterParameterDefinitions[AliHLTTPCDefinitions::kResidualTime].fScale;
480               deltatime64=(AliHLTUInt64_t)round(deltatime);
481             }
482             AliHLTUInt64_t sigmaY264=0;
483             if (!isnan(sigmaY2)) sigmaY264=(AliHLTUInt64_t)round(sigmaY2*AliHLTTPCDefinitions::fgkClusterParameterDefinitions[AliHLTTPCDefinitions::kSigmaY2].fScale);
484             AliHLTUInt64_t sigmaZ264=0;
485             if (!isnan(sigmaZ2)) sigmaZ264=(AliHLTUInt64_t)round(sigmaZ2*AliHLTTPCDefinitions::fgkClusterParameterDefinitions[AliHLTTPCDefinitions::kSigmaZ2].fScale);
486             bWriteSuccess=bWriteSuccess && pDeflater->OutputBit(signDeltaPad);
487             bWriteSuccess=bWriteSuccess && pDeflater->OutputParameterBits(AliHLTTPCDefinitions::kResidualPad    , deltapad64);  
488             bWriteSuccess=bWriteSuccess && pDeflater->OutputBit(signDeltaTime);
489             bWriteSuccess=bWriteSuccess && pDeflater->OutputParameterBits(AliHLTTPCDefinitions::kResidualTime   , deltatime64);
490             bWriteSuccess=bWriteSuccess && pDeflater->OutputParameterBits(AliHLTTPCDefinitions::kSigmaY2        , sigmaY264);
491             bWriteSuccess=bWriteSuccess && pDeflater->OutputParameterBits(AliHLTTPCDefinitions::kSigmaZ2        , sigmaZ264);
492             bWriteSuccess=bWriteSuccess && pDeflater->OutputParameterBits(AliHLTTPCDefinitions::kCharge         , charge);
493             bWriteSuccess=bWriteSuccess && pDeflater->OutputParameterBits(AliHLTTPCDefinitions::kQMax           , qmax);
494             if (bWriteSuccess) writtenClusters++;
495           }
496         }
497
498         // set to next trackpoint
499         if (bReverse) {
500           if (clrow!=fRawTrackPoints.begin()) {
501             AliHLTUInt32_t nextPartition=AliHLTTPCSpacePointData::GetPatch((clrow-1)->GetId());
502             AliHLTUInt32_t nextTrackRow=AliHLTTPCSpacePointData::GetNumber((clrow-1)->GetId());
503             nextTrackRow+=AliHLTTPCTransform::GetFirstRow(nextPartition);
504             if (thisTrackRow+1==nextTrackRow) {
505               clrow--;
506             } else {
507               // switch direction start from beginning
508               clrow=fRawTrackPoints.begin();
509               bReverse=false;
510             }
511           } else {
512             // all trackpoints processed
513             clrow=fRawTrackPoints.end();
514           }
515         } else {
516           clrow++;
517         }
518         continue;
519       } else {
520         // sequence not ordered, search
521         // this has been fixed and the search is no longer necessary
522         // for (clrow=fRawTrackPoints.begin(); clrow!=fRawTrackPoints.end(); clrow++) {
523         //   if ((AliHLTTPCSpacePointData::GetNumber(clrow->GetId())+AliHLTTPCTransform::GetFirstRow(AliHLTTPCSpacePointData::GetPatch(clrow->GetId())))==row) break;
524         // }
525         // if (clrow==fRawTrackPoints.end()) {
526         //   clrow=fRawTrackPoints.begin();
527         //   HLTWarning("no trackpoint on row %d, current point %d", row, thisTrackRow);
528         // }
529       }
530     }
531     // no cluster on that padrow
532     AliHLTUInt32_t haveClusters=0;
533     bWriteSuccess=bWriteSuccess && pDeflater->OutputBit(haveClusters);
534   }
535
536   if (!bWriteSuccess) return -ENOSPC;
537
538   int allClusters=0;
539   for (clrow=fRawTrackPoints.begin(); clrow!=fRawTrackPoints.end(); clrow++) {
540     allClusters+=clrow->GetSpacepoints().size();
541   }
542   if (allClusters!=writtenClusters) {
543     HLTError("track %d mismatch in written clusters: %d but expected %d", GetTrackId(), writtenClusters, allClusters);
544   }
545
546   pDeflater->Pad8Bits();
547   return pDeflater->GetCurrentByteOutputPosition()-dataPosition;
548 }
549
550 // int AliHLTTPCTrackGeometry::Read(AliHLTUInt8_t* buffer,
551 //                               AliHLTUInt32_t size,
552 //                               const char* /*option*/) const
553 // {
554 //   // read track block from buffer
555 //   if (!buffer) return -EINVAL;
556 //   if (size<sizeof(AliHLTTPCTrackBlock)) {
557 //     HLTError("buffer does not contain valid data of track model clusters");
558 //     return -ENODATA;
559 //   }
560 //   AliHLTTPCTrackBlock* pTrackBlock=reinterpret_cast<AliHLTTPCTrackBlock*>(buffer);
561 //   if (pTrackBlock->fSize>size) {
562 //     HLTError("inconsistent track data block of size %d exceeds available buffer of size %d", pTrackBlock->fSize, size);
563 //     return -ENODATA;
564 //   }
565 //   pTrackBlock->fSlice=AliHLTUInt8_t(9*track.GetAlpha()/TMath::Pi());
566 //   pTrackBlock->fReserved=0;
567 //   pTrackBlock->fX      = track.GetX();
568 //   pTrackBlock->fY      = track.GetY();
569 //   pTrackBlock->fZ      = track.GetZ();
570 //   pTrackBlock->fSinPsi = track.GetSnp();
571 //   pTrackBlock->fTgl    = track.GetTgl();
572 //   pTrackBlock->fq1Pt   = track.GetSigned1Pt();
573
574 // }