]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/TPCLib/AliHLTTPCHWCFSpacePointContainer.cxx
changing type of index grid; using intermediate stringstream for printout to save...
[u/mrichter/AliRoot.git] / HLT / TPCLib / AliHLTTPCHWCFSpacePointContainer.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   AliHLTTPCHWCFSpacePointContainer.cxx
20 /// @author Matthias Richter
21 /// @date   2011-08-08
22 /// @brief  Helper class for handling of HLT TPC cluster data blocks from the
23 ///         HW ClusterFinder
24 /// @note   Class is a duplicate of AliHLTTPCHWCFSpacePointContainer and should
25 ///         be merged with it in a generic way
26
27 #include "AliHLTTPCHWCFSpacePointContainer.h"
28 #include "AliHLTErrorGuard.h"
29 #include "AliHLTTPCDefinitions.h"
30 #include "AliHLTTPCSpacePointData.h"
31 #include "AliHLTTPCRawCluster.h"
32 #include "AliHLTTPCTransform.h"
33 #include "AliHLTComponent.h"
34 #include "AliHLTTemplates.h"
35 #include "AliHLTDataDeflater.h"
36 #include "AliRawDataHeader.h"
37 #include "AliLog.h"
38 #include "TMath.h"
39 #include <memory>
40 #include <algorithm>
41 #include <cmath>
42 #include <iostream>
43 #include <sstream>
44 #include <iomanip>
45
46
47 /** ROOT macro for the implementation of ROOT specific class methods */
48 ClassImp(AliHLTTPCHWCFSpacePointContainer)
49
50 AliHLTTPCHWCFSpacePointContainer::AliHLTTPCHWCFSpacePointContainer(int mode)
51   : AliHLTSpacePointContainer()
52   , fClusters()
53   , fSelections()
54   , fBlocks()
55   , fSingleBlock()
56   , fMode(mode)
57 {
58   // see header file for class documentation
59   // or
60   // refer to README to build package
61   // or
62   // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
63   if (fMode==1) {
64     fSingleBlock.SetDecoder(new AliHLTTPCHWCFData);
65     fSingleBlock.SetGrid(AllocateIndexGrid());
66   }
67 }
68
69 AliHLTTPCHWCFSpacePointContainer::AliHLTTPCHWCFSpacePointContainer(const AliHLTTPCHWCFSpacePointContainer& c)
70   : AliHLTSpacePointContainer(c)
71   , fClusters(c.fClusters.begin(), c.fClusters.end())
72   , fSelections()
73   , fBlocks()
74   , fSingleBlock()
75   , fMode(c.fMode)
76 {
77   /// copy constructor
78 }
79
80 AliHLTTPCHWCFSpacePointContainer& AliHLTTPCHWCFSpacePointContainer::operator=(const AliHLTTPCHWCFSpacePointContainer& c)
81 {
82   /// assignment operator
83   if (&c==this) return *this;
84   AliHLTSpacePointContainer::operator=(c);
85   fClusters=c.fClusters;
86   fMode=c.fMode;
87
88   return *this;
89 }
90
91 AliHLTTPCHWCFSpacePointContainer::~AliHLTTPCHWCFSpacePointContainer()
92 {
93   // destructor
94   Clear();
95   if (fSingleBlock.GetDecoder()) delete fSingleBlock.GetDecoder();
96   if (fSingleBlock.GetGrid()) delete fSingleBlock.GetGrid();
97 }
98
99 int AliHLTTPCHWCFSpacePointContainer::AddInputBlock(const AliHLTComponentBlockData* pDesc)
100 {
101   // add input block to the collection
102   if (!pDesc) return -EINVAL;
103   int iResult=0;
104   int count=0;
105   if (pDesc->fDataType!=AliHLTTPCDefinitions::fgkHWClustersDataType) {
106     HLTWarning("ignoring data block of type %s", AliHLTComponent::DataType2Text(pDesc->fDataType).c_str());
107     return 0;
108   }
109   if (!pDesc->fPtr) return -ENODATA;
110   if (pDesc->fSize<=sizeof(AliRawDataHeader)) return 0;
111
112   AliHLTUInt8_t slice = AliHLTTPCDefinitions::GetMinSliceNr( pDesc->fSpecification );
113   AliHLTUInt8_t part  = AliHLTTPCDefinitions::GetMinPatchNr( pDesc->fSpecification );
114
115   AliHLTUInt32_t decoderIndex=AliHLTTPCSpacePointData::GetID(slice, part, 0);
116
117   AliHLTUInt32_t *buffer=reinterpret_cast<AliHLTUInt32_t*>(pDesc->fPtr);
118   // skip the first 8 32-bit CDH words
119   buffer += 8;
120   UInt_t bufferSize32 = ((Int_t)pDesc->fSize - sizeof(AliRawDataHeader) )/sizeof(AliHLTUInt32_t);
121
122   AliHLTTPCHWCFData* pDecoder=NULL;
123   AliHLTSpacePointPropertyGrid* pGrid=NULL;
124   if (fMode==1) {
125     pDecoder=fSingleBlock.GetDecoder();
126     pGrid=fSingleBlock.GetGrid();
127   } else {
128     if (fBlocks.find(decoderIndex)!=fBlocks.end()) {
129       HLTError("data block of slice %d partition %d already added, skipping data block", slice, part);
130       return -EEXIST;
131     }
132   }
133
134   if (!pDecoder) {
135     pDecoder=new AliHLTTPCHWCFData;
136     if (!pDecoder) return -ENOMEM;
137   }
138
139   if (pDecoder->Init(reinterpret_cast<AliHLTUInt8_t*>(buffer), bufferSize32*sizeof(AliHLTUInt32_t))<0 ||
140       (pDecoder->CheckVersion()<0 && (int)bufferSize32>pDecoder->GetRCUTrailerSize())) {
141     HLTError("data block of type %s corrupted: can not decode format",
142              AliHLTComponent::DataType2Text(pDesc->fDataType).c_str());
143     return -EBADMSG;
144   }
145
146   if (fMode==1 && !pGrid) {
147     pGrid=AllocateIndexGrid();
148     if (!pGrid) {
149       delete pDecoder;
150       return -ENOMEM;
151     }
152   }
153
154   if (fMode==0) { // register immediately
155   UInt_t nofClusters=pDecoder->GetNumberOfClusters();
156
157   for (UInt_t i=0; i<nofClusters; i++) {
158     AliHLTUInt32_t clusterID=~(AliHLTUInt32_t)0;
159     // cluster ID from slice, partition and index
160     clusterID=AliHLTTPCSpacePointData::GetID(slice, part, i);
161
162     if (fClusters.find(clusterID)==fClusters.end()) {
163       // new cluster
164       fClusters[clusterID]=AliHLTTPCHWCFSpacePointProperties(pDecoder, i);
165       count++;
166     } else {
167       HLTError("cluster with ID 0x%08x already existing, skipping cluster %d of data block 0x%08x",
168                clusterID, i, pDesc->fSpecification);
169     }
170   }
171   }
172
173   if (pGrid && (iResult=PopulateAccessGrid(pGrid, pDecoder, slice, part))<0) {
174     HLTError("failed to populate access grid for block %s 0x%09x: %d",
175              AliHLTComponent::DataType2Text(pDesc->fDataType).c_str(), pDesc->fSpecification, iResult);
176     return iResult;
177   }
178
179   if (fMode==1) {
180     fSingleBlock.SetDecoder(pDecoder);
181     fSingleBlock.SetGrid(pGrid);
182     fSingleBlock.SetId(decoderIndex);
183   } else {
184     fBlocks[decoderIndex]=AliHLTTPCHWCFSpacePointBlock(decoderIndex, pDecoder, pGrid);
185   }
186   return count;
187 }
188
189 AliHLTSpacePointContainer::AliHLTSpacePointPropertyGrid* AliHLTTPCHWCFSpacePointContainer::AllocateIndexGrid()
190 {
191   // allocate index grid, one single point to define the dimensions
192   
193   // max 33 padrows, step 1 padrow
194   // max 139 pads, step 8 pads
195   // max 1024 time bins, step 10 timebins
196   return new AliHLTSpacePointPropertyGrid(33, 1.0, 140, 8, 1024, 10);
197 }
198
199 int AliHLTTPCHWCFSpacePointContainer::PopulateAccessGrid(AliHLTSpacePointPropertyGrid* pGrid, AliHLTUInt32_t mask) const
200 {
201   // populate an access grid
202   if (!pGrid) return -EINVAL;
203
204   pGrid->Clear();
205   
206   AliHLTUInt8_t slice = AliHLTTPCDefinitions::GetMinSliceNr(mask);
207   AliHLTUInt8_t partition  = AliHLTTPCDefinitions::GetMinPatchNr(mask);
208   AliHLTUInt32_t decoderIndex=AliHLTTPCSpacePointData::GetID(slice, partition, 0);
209   std::map<AliHLTUInt32_t, AliHLTTPCHWCFSpacePointBlock>::const_iterator block=fBlocks.find(decoderIndex);
210   if (block==fBlocks.end()) {
211     HLTError("can not find data block of id 0x%08x", mask);
212     return -ENOENT;
213   }
214   return PopulateAccessGrid(pGrid, block->second.GetDecoder(), slice, partition);
215 }
216
217 int AliHLTTPCHWCFSpacePointContainer::PopulateAccessGrid(AliHLTSpacePointPropertyGrid* pGrid, AliHLTTPCHWCFData* pDecoder,
218                                                          int slice, int partition) const
219 {
220   // populate an access grid
221   if (!pDecoder) return -EINVAL;
222   int iResult=0;
223
224   if (pDecoder->GetNumberOfClusters()==0) return 0;
225   AliHLTTPCHWCFData::iterator cl=pDecoder->begin();
226   for (; cl!=pDecoder->end(); ++cl) {
227     iResult=pGrid->CountSpacePoint(cl.GetPadRow(), cl.GetPad(), cl.GetTime());
228     if (iResult<0)
229       HLTError("CountSpacePoint %f %f %f failed: %d", cl.GetPadRow(), cl.GetPad(), cl.GetTime(), iResult);
230   }
231   
232   int count=0;
233   cl=pDecoder->begin();
234   for (; cl!=pDecoder->end(); ++cl, count++) {
235     AliHLTUInt32_t id=AliHLTTPCSpacePointData::GetID(slice, partition, count);
236     iResult=pGrid->AddSpacePoint(AliHLTSpacePointProperties(id), cl.GetPadRow(), cl.GetPad(), cl.GetTime());
237     if (iResult<0)
238       HLTError("AddSpacePoint 0x%08x %f %f %f failed: %d", id, cl.GetPadRow(), cl.GetPad(), cl.GetTime(), iResult);
239   }
240
241   return 0;
242 }
243
244 const AliHLTSpacePointContainer::AliHLTSpacePointPropertyGrid* AliHLTTPCHWCFSpacePointContainer::GetSpacePointPropertyGrid(AliHLTUInt32_t mask) const
245 {
246   // get the access grid for a data block
247   AliHLTUInt8_t slice = AliHLTTPCDefinitions::GetMinSliceNr(mask);
248   AliHLTUInt8_t part  = AliHLTTPCDefinitions::GetMinPatchNr(mask);
249   AliHLTUInt32_t decoderIndex=AliHLTTPCSpacePointData::GetID(slice, part, 0);
250   std::map<AliHLTUInt32_t, AliHLTTPCHWCFSpacePointBlock>::const_iterator block=fBlocks.find(decoderIndex);
251   if (block==fBlocks.end()) {
252     HLTError("can not find data block of id 0x%08x", mask);
253     return NULL;
254   }
255   return block->second.GetGrid();
256 }
257
258 int AliHLTTPCHWCFSpacePointContainer::SetSpacePointPropertyGrid(AliHLTUInt32_t mask, AliHLTSpacePointContainer::AliHLTSpacePointPropertyGrid* pGrid)
259 {
260   // set the access grid for a data block
261   AliHLTUInt8_t slice = AliHLTTPCDefinitions::GetMinSliceNr(mask);
262   AliHLTUInt8_t part  = AliHLTTPCDefinitions::GetMinPatchNr(mask);
263   AliHLTUInt32_t decoderIndex=AliHLTTPCSpacePointData::GetID(slice, part, 0);
264   std::map<AliHLTUInt32_t, AliHLTTPCHWCFSpacePointBlock>::iterator block=fBlocks.find(decoderIndex);
265   if (block==fBlocks.end()) {
266     HLTError("can not find data block of id 0x%08x", mask);
267     return -ENOENT;
268   }
269   if (block->second.GetGrid()!=NULL && pGrid!=NULL && block->second.GetGrid()!=pGrid) {
270     // there is trouble ahead because this will delete the index grid instance
271     // but it might be an external pointer supposed to be deleted by someone else
272     ALIHLTERRORGUARD(1, "overriding previous instance of index grid, potential memory leak or invalid deallocation ahead");
273   }
274   block->second.SetGrid(pGrid);
275   return 0;
276 }
277
278 int AliHLTTPCHWCFSpacePointContainer::GetClusterIDs(vector<AliHLTUInt32_t>& tgt) const
279 {
280   // get array of cluster IDs
281   tgt.clear();
282   transform(fClusters.begin(), fClusters.end(), back_inserter(tgt), HLT::AliGetKey());
283   return tgt.size();
284 }
285
286 bool AliHLTTPCHWCFSpacePointContainer::Check(AliHLTUInt32_t clusterID) const
287 {
288   // check if the cluster is available
289   return fClusters.find(clusterID)!=fClusters.end();
290 }
291
292 const vector<AliHLTUInt32_t>* AliHLTTPCHWCFSpacePointContainer::GetClusterIDs(AliHLTUInt32_t mask)
293 {
294   // get array of cluster IDs filtered by mask
295   if (fSelections.find(mask)!=fSelections.end()) {
296     // return existing selection
297     return fSelections.find(mask)->second;
298   }
299   // create new collection
300   vector<AliHLTUInt32_t>* selected=new vector<AliHLTUInt32_t>;
301   if (!selected) return NULL;
302   UInt_t slice=AliHLTTPCSpacePointData::GetSlice(mask);
303   UInt_t partition=AliHLTTPCSpacePointData::GetPatch(mask);
304   //HLTInfo("creating collection 0x%08x", mask);
305
306   // the first cluster with number 0 has equal ID to mask unless
307   // the mask selects multiple partitions/slices
308   std::map<AliHLTUInt32_t, AliHLTTPCHWCFSpacePointProperties>::const_iterator cl=fClusters.find(mask);
309   bool bAll=false;
310   if (slice>=(unsigned)AliHLTTPCTransform::GetNSlice() ||
311       partition>=(unsigned)AliHLTTPCTransform::GetNumberOfPatches()) {
312     cl=fClusters.begin();
313     bAll=true;
314   }
315   for (; cl!=fClusters.end(); cl++) {
316     UInt_t s=AliHLTTPCSpacePointData::GetSlice(cl->first);
317     UInt_t p=AliHLTTPCSpacePointData::GetPatch(cl->first);
318     if ((slice>=(unsigned)AliHLTTPCTransform::GetNSlice() || s==slice) && 
319         (partition>=(unsigned)AliHLTTPCTransform::GetNumberOfPatches() || p==partition)) {
320       selected->push_back(cl->first);
321     } else if (!bAll) {
322       // no need to continue, we are out of the range
323       break;
324     }
325   }
326   //HLTInfo("collection 0x%08x with %d spacepoints", mask, selected->size());
327   fSelections[mask]=selected;
328   return selected;
329 }
330
331 float AliHLTTPCHWCFSpacePointContainer::GetX(AliHLTUInt32_t clusterID) const
332 {
333   // get X coordinate
334   std::map<AliHLTUInt32_t, AliHLTTPCHWCFSpacePointProperties>::const_iterator cl=fClusters.find(clusterID);
335   if (cl==fClusters.end() ||
336       cl->second.Decoder()==NULL) return 0.0;
337   // FIXME: understand deviation from the nominal x value
338   // there is a small deviation in the x coordinate - padrow number correlation
339   // in principle, the clusterfinder only uses the mapping to set the x parameter.
340   // now extracting the x value from the padrow no.
341   //return cl->second.Decoder()->fX;
342   int index=AliHLTTPCSpacePointData::GetNumber(cl->first);
343   return cl->second.Decoder()->GetPadRow(index);
344 }
345
346 float AliHLTTPCHWCFSpacePointContainer::GetXWidth(AliHLTUInt32_t clusterID) const
347 {
348   // get error for X coordinate
349   std::map<AliHLTUInt32_t, AliHLTTPCHWCFSpacePointProperties>::const_iterator cl=fClusters.find(clusterID);
350   if (cl==fClusters.end() ||
351       cl->second.Decoder()==NULL) return 0.0;
352   return 0.0; // fixed in padrow number
353 }
354
355 float AliHLTTPCHWCFSpacePointContainer::GetY(AliHLTUInt32_t clusterID) const
356 {
357   // get Y coordinate
358   std::map<AliHLTUInt32_t, AliHLTTPCHWCFSpacePointProperties>::const_iterator cl=fClusters.find(clusterID);
359   if (cl==fClusters.end() ||
360       cl->second.Decoder()==NULL) return 0.0;
361   int index=AliHLTTPCSpacePointData::GetNumber(cl->first);
362   return cl->second.Decoder()->GetPad(index);
363 }
364
365 float AliHLTTPCHWCFSpacePointContainer::GetYWidth(AliHLTUInt32_t clusterID) const
366 {
367   // get error for Y coordinate
368   std::map<AliHLTUInt32_t, AliHLTTPCHWCFSpacePointProperties>::const_iterator cl=fClusters.find(clusterID);
369   if (cl==fClusters.end() ||
370       cl->second.Decoder()==NULL) return 0.0;
371   int index=AliHLTTPCSpacePointData::GetNumber(cl->first);
372   return cl->second.Decoder()->GetSigmaY2(index);
373 }
374
375 float AliHLTTPCHWCFSpacePointContainer::GetZ(AliHLTUInt32_t clusterID) const
376 {
377   // get Z coordinate
378   std::map<AliHLTUInt32_t, AliHLTTPCHWCFSpacePointProperties>::const_iterator cl=fClusters.find(clusterID);
379   if (cl==fClusters.end() ||
380       cl->second.Decoder()==NULL) return 0.0;
381   int index=AliHLTTPCSpacePointData::GetNumber(cl->first);
382   return cl->second.Decoder()->GetTime(index);
383 }
384
385 float AliHLTTPCHWCFSpacePointContainer::GetZWidth(AliHLTUInt32_t clusterID) const
386 {
387   // get error for Z coordinate
388   std::map<AliHLTUInt32_t, AliHLTTPCHWCFSpacePointProperties>::const_iterator cl=fClusters.find(clusterID);
389   if (cl==fClusters.end() ||
390       cl->second.Decoder()==NULL) return 0.0;
391   int index=AliHLTTPCSpacePointData::GetNumber(cl->first);
392   return cl->second.Decoder()->GetSigmaZ2(index);
393 }
394
395 float AliHLTTPCHWCFSpacePointContainer::GetCharge(AliHLTUInt32_t clusterID) const
396 {
397   // get charge
398   std::map<AliHLTUInt32_t, AliHLTTPCHWCFSpacePointProperties>::const_iterator cl=fClusters.find(clusterID);
399   if (cl==fClusters.end() ||
400       cl->second.Decoder()==NULL) return 0.0;
401   int index=AliHLTTPCSpacePointData::GetNumber(cl->first);
402   return cl->second.Decoder()->GetCharge(index);
403 }
404
405 float AliHLTTPCHWCFSpacePointContainer::GetPhi(AliHLTUInt32_t clusterID) const
406 {
407   // get charge
408
409   // phi can be derived directly from the id, no need to search
410   // for existing cluster
411   int slice=AliHLTTPCSpacePointData::GetSlice(clusterID);
412   return ( slice + 0.5 ) * TMath::Pi() / 9.0;
413 }
414
415 void AliHLTTPCHWCFSpacePointContainer::Clear(Option_t * option)
416 {
417   // clear the object and reset pointer references
418   fClusters.clear();
419
420   for (std::map<AliHLTUInt32_t, vector<AliHLTUInt32_t>*>::iterator selection=fSelections.begin();
421        selection!=fSelections.end(); selection++) {
422     if (selection->second) delete selection->second;
423   }
424   fSelections.clear();
425
426   for (std::map<AliHLTUInt32_t, AliHLTTPCHWCFSpacePointBlock>::iterator block=fBlocks.begin();
427        block!=fBlocks.end(); block++) {
428     if (block->second.GetDecoder()) delete block->second.GetDecoder();
429     if (block->second.GetGrid()) delete block->second.GetGrid();
430   }
431   fBlocks.clear();
432
433   if (fSingleBlock.GetDecoder()) fSingleBlock.GetDecoder()->Reset();
434   if (fSingleBlock.GetGrid()) fSingleBlock.GetGrid()->Clear();
435
436   AliHLTSpacePointContainer::Clear(option);
437 }
438
439 void AliHLTTPCHWCFSpacePointContainer::Print(ostream& out, Option_t */*option*/) const
440 {
441   // print to stream
442   std::stringstream str;
443   str << "AliHLTTPCHWCFSpacePointContainer::Print" << endl;
444   str << "n clusters: " << fClusters.size() << endl;
445   for (std::map<AliHLTUInt32_t, AliHLTTPCHWCFSpacePointProperties>::const_iterator cl=fClusters.begin();
446        cl!=fClusters.end(); cl++) {
447     str << " 0x" << hex << setw(8) << setfill('0') << cl->first << dec << cl->second << endl;
448   }
449   out << str;
450 }
451
452 AliHLTSpacePointContainer* AliHLTTPCHWCFSpacePointContainer::SelectByMask(AliHLTUInt32_t mask, bool /*bAlloc*/) const
453 {
454   /// create a collection of clusters for a space point mask
455   std::auto_ptr<AliHLTTPCHWCFSpacePointContainer> c(new AliHLTTPCHWCFSpacePointContainer);
456   if (!c.get()) return NULL;
457
458   UInt_t slice=AliHLTTPCSpacePointData::GetSlice(mask);
459   UInt_t partition=AliHLTTPCSpacePointData::GetPatch(mask);
460   for (std::map<AliHLTUInt32_t, AliHLTTPCHWCFSpacePointProperties>::const_iterator cl=fClusters.begin();
461        cl!=fClusters.end(); cl++) {
462     UInt_t s=AliHLTTPCSpacePointData::GetSlice(cl->first);
463     UInt_t p=AliHLTTPCSpacePointData::GetPatch(cl->first);
464     if ((slice>=(unsigned)AliHLTTPCTransform::GetNSlice() || s==slice) && 
465         (partition>=(unsigned)AliHLTTPCTransform::GetNumberOfPatches() || p==partition)) {
466       c->fClusters[cl->first]=cl->second;
467     }
468   }
469   return c.release();
470 }
471
472 AliHLTSpacePointContainer* AliHLTTPCHWCFSpacePointContainer::SelectByTrack(int trackId, bool /*bAlloc*/) const
473 {
474   /// create a collection of clusters for a specific track
475   std::auto_ptr<AliHLTTPCHWCFSpacePointContainer> c(new AliHLTTPCHWCFSpacePointContainer);
476   if (!c.get()) return NULL;
477
478   HLT::copy_map_if(fClusters.begin(), fClusters.end(), c->fClusters, HLT::AliHLTUnaryPredicate<AliHLTTPCHWCFSpacePointContainer::AliHLTTPCHWCFSpacePointProperties, int>(&AliHLTTPCHWCFSpacePointContainer::AliHLTTPCHWCFSpacePointProperties::GetTrackId,trackId));
479   return c.release();
480 }
481
482 AliHLTSpacePointContainer* AliHLTTPCHWCFSpacePointContainer::SelectByMC(int mcId, bool /*bAlloc*/) const
483 {
484   /// create a collection of clusters for a specific MC track
485   std::auto_ptr<AliHLTTPCHWCFSpacePointContainer> c(new AliHLTTPCHWCFSpacePointContainer);
486   if (!c.get()) return NULL;
487
488   HLT::copy_map_if(fClusters.begin(), fClusters.end(), c->fClusters, HLT::AliHLTUnaryPredicate<AliHLTTPCHWCFSpacePointContainer::AliHLTTPCHWCFSpacePointProperties, int>(&AliHLTTPCHWCFSpacePointContainer::AliHLTTPCHWCFSpacePointProperties::GetMCId,mcId));
489   return c.release();
490 }
491
492 AliHLTSpacePointContainer* AliHLTTPCHWCFSpacePointContainer::UsedClusters(bool /*bAlloc*/) const
493 {
494   /// create a collection of all used clusters
495   std::auto_ptr<AliHLTTPCHWCFSpacePointContainer> c(new AliHLTTPCHWCFSpacePointContainer);
496   if (!c.get()) return NULL;
497
498   HLT::copy_map_if(fClusters.begin(), fClusters.end(), c->fClusters, HLT::AliHLTUnaryPredicate<AliHLTTPCHWCFSpacePointContainer::AliHLTTPCHWCFSpacePointProperties, bool>(&AliHLTTPCHWCFSpacePointContainer::AliHLTTPCHWCFSpacePointProperties::IsUsed,true));
499   return c.release();
500 }
501
502 AliHLTSpacePointContainer* AliHLTTPCHWCFSpacePointContainer::UnusedClusters(bool /*bAlloc*/) const
503 {
504   /// create a collection of all unused clusters
505   std::auto_ptr<AliHLTTPCHWCFSpacePointContainer> c(new AliHLTTPCHWCFSpacePointContainer);
506   if (!c.get()) return NULL;
507
508   HLT::copy_map_if(fClusters.begin(), fClusters.end(), c->fClusters, HLT::AliHLTUnaryPredicate<AliHLTTPCHWCFSpacePointContainer::AliHLTTPCHWCFSpacePointProperties, bool>(&AliHLTTPCHWCFSpacePointContainer::AliHLTTPCHWCFSpacePointProperties::IsUsed,false));
509   return c.release();
510 }
511
512 int AliHLTTPCHWCFSpacePointContainer::MarkUsed(const AliHLTUInt32_t* clusterIDs, int arraySize)
513 {
514   /// mark the clusters with specified IDs as used
515   if (!clusterIDs) return -EINVAL;
516   int iCount=0;
517   for (int i=0; i<arraySize; i++) {
518     if (fClusters.find(clusterIDs[i])==fClusters.end()) continue;
519     fClusters[clusterIDs[i]].MarkUsed();
520     iCount++;
521   }
522   return iCount;
523 }
524
525 int AliHLTTPCHWCFSpacePointContainer::SetTrackID(int trackID, const AliHLTUInt32_t* clusterIDs, int arraySize)
526 {
527   /// set track id for specified clusters
528   if (!clusterIDs) return -EINVAL;
529   int iCount=0;
530   for (int i=0; i<arraySize; i++) {
531     if (fClusters.find(clusterIDs[i])==fClusters.end()) continue;
532     fClusters[clusterIDs[i]].SetTrackId(trackID);
533     iCount++;
534   }
535   return iCount;
536 }
537
538 int AliHLTTPCHWCFSpacePointContainer::GetTrackID(AliHLTUInt32_t clusterID) const
539 {
540   /// get track id for specified cluster
541   map<AliHLTUInt32_t, AliHLTTPCHWCFSpacePointProperties>::const_iterator element=fClusters.find(clusterID);
542   if (element==fClusters.end()) return -1;
543   return element->second.GetTrackId();
544 }
545
546 int AliHLTTPCHWCFSpacePointContainer::SetMCID(int mcID, const AliHLTUInt32_t* clusterIDs, int arraySize)
547 {
548   /// set mc id for specified clusters
549   if (!clusterIDs) return -EINVAL;
550   int iCount=0;
551   for (int i=0; i<arraySize; i++) {
552     if (fClusters.find(clusterIDs[i])==fClusters.end()) continue;
553     fClusters[clusterIDs[i]].SetMCId(mcID);
554     iCount++;
555   }
556   return iCount;
557 }
558
559 int AliHLTTPCHWCFSpacePointContainer::Write(AliHLTUInt8_t* outputPtr,
560                                             AliHLTUInt32_t size,
561                                             AliHLTComponentBlockDataList&
562                                             outputBlocks,
563                                             AliHLTDataDeflater* pDeflater,
564                                             const char* option) const
565 {
566   /// write blocks to HLT component output
567   AliHLTUInt32_t offset=0;
568   if (outputBlocks.size()>0) {
569     offset=outputBlocks.back().fOffset+outputBlocks.back().fSize;
570   }
571   return Write(outputPtr, size, offset, outputBlocks, pDeflater, option);
572 }
573
574 int AliHLTTPCHWCFSpacePointContainer::Write(AliHLTUInt8_t* outputPtr,
575                                             AliHLTUInt32_t size,
576                                             AliHLTUInt32_t offset,
577                                             AliHLTComponentBlockDataList&
578                                             outputBlocks,
579                                             AliHLTDataDeflater* pDeflater,
580                                             const char* option) const
581 {
582   /// write blocks to HLT component output
583   if (fMode==0) return WriteUnsorted(outputPtr, size, offset, outputBlocks, pDeflater, option);
584   return WriteSorted(outputPtr, size, offset, outputBlocks, pDeflater, option);
585 }
586
587 int AliHLTTPCHWCFSpacePointContainer::WriteUnsorted(AliHLTUInt8_t* outputPtr,
588                                                     AliHLTUInt32_t size,
589                                                     AliHLTUInt32_t offset,
590                                                     AliHLTComponentBlockDataList&
591                                                     outputBlocks,
592                                                     AliHLTDataDeflater* pDeflater,
593                                                     const char* /*option*/) const
594 {
595   /// write blocks to HLT component output
596   if (!outputPtr) return -EINVAL;
597   int iResult=0;
598   AliHLTUInt32_t capacity=size;
599   size=0;
600
601   for (int slice=0; slice<AliHLTTPCTransform::GetNSlice() && iResult>=0; slice++) {
602     for (int part=0; part<AliHLTTPCTransform::GetNPatches() && iResult>=0; part++) {
603       AliHLTUInt32_t mask=AliHLTTPCSpacePointData::GetID(slice,part,0);
604       // FIXME: make GetClusterIDs a const function and handle the cast there
605       const vector<AliHLTUInt32_t>* collection=const_cast<AliHLTTPCHWCFSpacePointContainer*>(this)->GetClusterIDs(mask);
606       if (!collection || collection->size()==0) continue;
607       if (size+sizeof(AliHLTTPCRawClusterData)+collection->size()*sizeof(AliHLTTPCRawCluster)>capacity) {
608         ALIHLTERRORGUARD(1,"too little space to write cluster output block");
609         iResult=-ENOSPC;
610         break;
611       }
612       AliHLTTPCRawClusterData* blockout=reinterpret_cast<AliHLTTPCRawClusterData*>(outputPtr+size);
613       blockout->fVersion=0;
614       blockout->fCount=0;
615
616       if (pDeflater) {
617         pDeflater->Clear();
618         pDeflater->InitBitDataOutput(reinterpret_cast<AliHLTUInt8_t*>(blockout->fClusters), capacity-size-sizeof(AliHLTTPCRawClusterData));
619         blockout->fVersion=pDeflater->GetDeflaterVersion();
620       }
621
622       unsigned lastPadRow=0;
623       vector<AliHLTUInt32_t>::const_iterator clusterID=collection->begin();
624       if (clusterID!=collection->end()) {
625         std::map<AliHLTUInt32_t, AliHLTTPCHWCFSpacePointProperties>::const_iterator cl=fClusters.find(*clusterID);
626         for (; clusterID!=collection->end(); clusterID++, (cl!=fClusters.end())?cl++:cl) {
627           if (cl!=fClusters.end() && cl->first!=*clusterID) cl=fClusters.find(*clusterID);
628           if (cl==fClusters.end() || cl->second.Decoder()==NULL) continue;
629           int index=AliHLTTPCSpacePointData::GetNumber(cl->first);
630           int padrow=cl->second.Decoder()->GetPadRow(index);
631           if (padrow<0) {
632             // something wrong here, padrow is stored in the cluster header
633             // word which has bit pattern 0x3 in bits bit 30 and 31 which was
634             // not recognized
635             ALIHLTERRORGUARD(1, "can not read cluster header word");
636             break;
637           }
638
639           // FIXME: the HW ClusterFinder returns only the sum
640           // sum(q_i*pad_i*pad_i)/sum(q_i)
641           // where the mean needs to be subtracted, not yet in the decoder
642           // but should be implemented there
643           float pad =cl->second.Decoder()->GetPad(index);
644           float time =cl->second.Decoder()->GetTime(index);
645           float sigmaY2=cl->second.Decoder()->GetSigmaY2(index);
646           float sigmaZ2=cl->second.Decoder()->GetSigmaZ2(index);
647           sigmaY2-=pad*pad;
648           sigmaZ2-=time*time;
649
650           if (!pDeflater) {
651             AliHLTTPCRawCluster& c=blockout->fClusters[blockout->fCount];
652             padrow+=AliHLTTPCTransform::GetFirstRow(part);
653             c.SetPadRow(padrow);
654             c.SetCharge(cl->second.Decoder()->GetCharge(index));
655             c.SetPad(pad);  
656             c.SetTime(time);
657             c.SetSigmaY2(sigmaY2);
658             c.SetSigmaZ2(sigmaZ2);
659             c.SetQMax(cl->second.Decoder()->GetQMax(index));
660           } else {
661             AliHLTUInt64_t padrow64=cl->second.Decoder()->GetPadRow(index);
662             // enable if padrows are ordered
663             if (padrow64>=lastPadRow) {
664             //   padrow64-=lastPadRow;
665             //   lastPadRow+=padrow64;
666             } else {
667             //   AliFatal("padrows not ordered");
668             }
669
670             AliHLTUInt64_t pad64
671               =(AliHLTUInt64_t)round(pad*AliHLTTPCDefinitions::fgkClusterParameterDefinitions[AliHLTTPCDefinitions::kPad].fScale);
672             AliHLTUInt64_t time64
673               =(AliHLTUInt64_t)round(time*AliHLTTPCDefinitions::fgkClusterParameterDefinitions[AliHLTTPCDefinitions::kTime].fScale);
674             AliHLTUInt64_t sigmaY264
675               =(AliHLTUInt64_t)round(sigmaY2*AliHLTTPCDefinitions::fgkClusterParameterDefinitions[AliHLTTPCDefinitions::kSigmaY2].fScale);
676             AliHLTUInt64_t sigmaZ264
677               =(AliHLTUInt64_t)round(sigmaZ2*AliHLTTPCDefinitions::fgkClusterParameterDefinitions[AliHLTTPCDefinitions::kSigmaZ2].fScale);
678             pDeflater->OutputParameterBits(AliHLTTPCDefinitions::kPadRow , padrow64);
679             pDeflater->OutputParameterBits(AliHLTTPCDefinitions::kPad    , pad64);  
680             pDeflater->OutputParameterBits(AliHLTTPCDefinitions::kTime   , time64);
681             pDeflater->OutputParameterBits(AliHLTTPCDefinitions::kSigmaY2, sigmaY264);
682             pDeflater->OutputParameterBits(AliHLTTPCDefinitions::kSigmaZ2, sigmaZ264);
683             pDeflater->OutputParameterBits(AliHLTTPCDefinitions::kCharge , cl->second.Decoder()->GetCharge(index));
684             pDeflater->OutputParameterBits(AliHLTTPCDefinitions::kQMax   , cl->second.Decoder()->GetQMax(index));
685           }
686           blockout->fCount++;
687         }
688       }
689       AliHLTComponent_BlockData bd;
690       AliHLTComponent::FillBlockData(bd);
691       bd.fOffset        = size+offset;
692       if (!pDeflater) {
693         bd.fSize        = sizeof(AliHLTTPCRawClusterData)+blockout->fCount*sizeof(AliHLTTPCRawCluster);
694       } else {
695         pDeflater->Pad8Bits();
696         bd.fSize        = sizeof(AliHLTTPCRawClusterData)+pDeflater->GetBitDataOutputSizeBytes();
697         pDeflater->CloseBitDataOutput();
698       }
699       bd.fSpecification = AliHLTTPCDefinitions::EncodeDataSpecification(slice, slice, part, part);
700       bd.fDataType      = AliHLTTPCDefinitions::fgkRawClustersDataType;
701       outputBlocks.push_back(bd);
702       
703       size += bd.fSize;
704     }
705   }
706
707   if (iResult<0) return iResult;
708   return size;
709 }
710
711 int AliHLTTPCHWCFSpacePointContainer::WriteSorted(AliHLTUInt8_t* outputPtr,
712                                                   AliHLTUInt32_t size,
713                                                   AliHLTUInt32_t offset,
714                                                   AliHLTComponentBlockDataList&
715                                                   outputBlocks,
716                                                   AliHLTDataDeflater* pDeflater,
717                                                   const char* option) const
718 {
719   /// write blocks to HLT component output
720   int iResult=0;
721
722   if (fMode==1) {
723     iResult=WriteSorted(outputPtr, size, offset, fSingleBlock.GetDecoder(), fSingleBlock.GetGrid(), fSingleBlock.GetId(), outputBlocks, pDeflater, option);
724   } else {
725     iResult=-ENOENT;
726     for (std::map<AliHLTUInt32_t, AliHLTTPCHWCFSpacePointBlock>::const_iterator block=fBlocks.begin();
727          block!=fBlocks.end(); block++) {
728       AliHLTTPCHWCFData* pDecoder=block->second.GetDecoder();
729       AliHLTSpacePointPropertyGrid* pGrid=block->second.GetGrid();
730       AliHLTUInt32_t mask=block->first;
731       // FIXME: have to propagate the parameter which block is currently to be written
732       // for now the index grid is only set for that one
733       if (!pGrid) continue;
734       iResult=WriteSorted(outputPtr, size, offset, pDecoder, pGrid, mask, outputBlocks, pDeflater, option);
735       break; // only one is supposed to be written
736     }
737     if (iResult==-ENOENT) {
738       HLTError("could not find the index grid of the partition to be written");
739     }
740   }
741   return iResult;
742 }
743
744 int AliHLTTPCHWCFSpacePointContainer::WriteSorted(AliHLTUInt8_t* outputPtr,
745                                                   AliHLTUInt32_t size,
746                                                   AliHLTUInt32_t offset,
747                                                   AliHLTTPCHWCFData* pDecoder,
748                                                   AliHLTSpacePointPropertyGrid* pGrid,
749                                                   AliHLTUInt32_t mask,
750                                                   AliHLTComponentBlockDataList&
751                                                   outputBlocks,
752                                                   AliHLTDataDeflater* pDeflater,
753                                                   const char* /*option*/) const
754 {
755   /// write blocks to HLT component output
756   if (!outputPtr || !pDecoder || !pGrid) return -EINVAL;
757   if (pDecoder->GetNumberOfClusters()==0) return 0;
758   int iResult=0;
759   AliHLTUInt32_t capacity=size;
760   size=0;
761
762   int slice=AliHLTTPCSpacePointData::GetSlice(mask);
763   int part=AliHLTTPCSpacePointData::GetPatch(mask);
764
765   AliHLTTPCRawClusterData* blockout=reinterpret_cast<AliHLTTPCRawClusterData*>(outputPtr+size);
766   blockout->fVersion=0;
767   blockout->fCount=0;
768
769   if (pDeflater) {
770     pDeflater->Clear();
771     pDeflater->InitBitDataOutput(reinterpret_cast<AliHLTUInt8_t*>(blockout->fClusters), capacity-size-sizeof(AliHLTTPCRawClusterData));
772     blockout->fVersion=pDeflater->GetDeflaterVersion();
773   }
774
775   unsigned lastPadRow=0;
776   AliHLTSpacePointPropertyGrid::iterator clusterID=pGrid->begin();
777   if (clusterID!=pGrid->end()) {
778     for (; clusterID!=pGrid->end(); clusterID++) {
779       if ((unsigned)slice!=AliHLTTPCSpacePointData::GetSlice(clusterID.Data().fId) ||
780           (unsigned)part!=AliHLTTPCSpacePointData::GetPatch(clusterID.Data().fId)) {
781         HLTError("cluster index 0x%08x out of slice %d partition %d", clusterID.Data().fId, slice, part);
782       }
783       int index=AliHLTTPCSpacePointData::GetNumber(clusterID.Data().fId);
784       const AliHLTTPCHWCFData::iterator& input=pDecoder->find(index);
785       if (!(input!=pDecoder->end())) continue;
786       int padrow=input.GetPadRow();
787       if (padrow<0) {
788         // something wrong here, padrow is stored in the cluster header
789         // word which has bit pattern 0x3 in bits bit 30 and 31 which was
790         // not recognized
791         ALIHLTERRORGUARD(1, "can not read cluster header word");
792         iResult=-EBADF;
793         break;
794       }
795
796       // FIXME: the HW ClusterFinder returns only the sum
797       // sum(q_i*pad_i*pad_i)/sum(q_i)
798       // where the mean needs to be subtracted, not yet in the decoder
799       // but should be implemented there
800       float pad =input.GetPad();
801       float time =input.GetTime();
802       float sigmaY2=input.GetSigmaY2();
803       float sigmaZ2=input.GetSigmaZ2();
804       sigmaY2-=pad*pad;
805       sigmaZ2-=time*time;
806
807       if (!pDeflater) {
808         AliHLTTPCRawCluster& c=blockout->fClusters[blockout->fCount];
809         padrow+=AliHLTTPCTransform::GetFirstRow(part);
810         c.SetPadRow(padrow);
811         c.SetCharge(input.GetCharge());
812         c.SetPad(pad);  
813         c.SetTime(time);
814         c.SetSigmaY2(sigmaY2);
815         c.SetSigmaZ2(sigmaZ2);
816         c.SetQMax(input.GetQMax());
817       } else {
818         AliHLTUInt64_t padrow64=input.GetPadRow();
819         if (padrow64==lastPadRow) {
820           padrow64-=lastPadRow;
821         } else if (padrow64>lastPadRow) {
822           padrow64-=lastPadRow;
823           lastPadRow+=padrow64;
824         } else {
825           AliFatal("padrows not ordered");
826         }
827
828         AliHLTUInt64_t pad64=0;
829         if (!isnan(pad)) pad64=(AliHLTUInt64_t)round(pad*AliHLTTPCDefinitions::fgkClusterParameterDefinitions[AliHLTTPCDefinitions::kPad].fScale);
830         AliHLTUInt64_t time64=0;
831         if (!isnan(time)) time64=(AliHLTUInt64_t)round(time*AliHLTTPCDefinitions::fgkClusterParameterDefinitions[AliHLTTPCDefinitions::kTime].fScale);
832         AliHLTUInt64_t sigmaY264=0;
833         if (!isnan(sigmaY2)) sigmaY264=(AliHLTUInt64_t)round(sigmaY2*AliHLTTPCDefinitions::fgkClusterParameterDefinitions[AliHLTTPCDefinitions::kSigmaY2].fScale);
834         AliHLTUInt64_t sigmaZ264=0;
835         if (!isnan(sigmaZ2)) sigmaZ264=(AliHLTUInt64_t)round(sigmaZ2*AliHLTTPCDefinitions::fgkClusterParameterDefinitions[AliHLTTPCDefinitions::kSigmaZ2].fScale);
836         pDeflater->OutputParameterBits(AliHLTTPCDefinitions::kPadRow , padrow64);
837         pDeflater->OutputParameterBits(AliHLTTPCDefinitions::kPad    , pad64);  
838         pDeflater->OutputParameterBits(AliHLTTPCDefinitions::kTime   , time64);
839         pDeflater->OutputParameterBits(AliHLTTPCDefinitions::kSigmaY2, sigmaY264);
840         pDeflater->OutputParameterBits(AliHLTTPCDefinitions::kSigmaZ2, sigmaZ264);
841         pDeflater->OutputParameterBits(AliHLTTPCDefinitions::kCharge , input.GetCharge());
842         pDeflater->OutputParameterBits(AliHLTTPCDefinitions::kQMax   , input.GetQMax());
843       }
844       blockout->fCount++;
845     }
846   }
847   AliHLTComponent_BlockData bd;
848   AliHLTComponent::FillBlockData(bd);
849   bd.fOffset        = size+offset;
850   if (!pDeflater) {
851     bd.fSize        = sizeof(AliHLTTPCRawClusterData)+blockout->fCount*sizeof(AliHLTTPCRawCluster);
852   } else {
853     pDeflater->Pad8Bits();
854     bd.fSize        = sizeof(AliHLTTPCRawClusterData)+pDeflater->GetBitDataOutputSizeBytes();
855     pDeflater->CloseBitDataOutput();
856   }
857   bd.fSpecification = AliHLTTPCDefinitions::EncodeDataSpecification(slice, slice, part, part);
858   bd.fDataType      = AliHLTTPCDefinitions::fgkRawClustersDataType;
859   outputBlocks.push_back(bd);
860       
861   size += bd.fSize;
862
863   if (iResult<0) return iResult;
864   return size;
865 }
866
867 AliHLTTPCHWCFSpacePointContainer::AliHLTTPCHWCFSpacePointProperties::AliHLTTPCHWCFSpacePointProperties()
868   : fDecoder(NULL)
869   , fIndex(-1)
870   , fUsed(false)
871   , fTrackId(-1)
872   , fMCId(-1)
873 {
874   // constructor
875 }
876
877 AliHLTTPCHWCFSpacePointContainer::AliHLTTPCHWCFSpacePointProperties::AliHLTTPCHWCFSpacePointProperties(const AliHLTTPCHWCFData* pDecoder, int index)
878   : fDecoder(pDecoder)
879   , fIndex(index)
880   , fUsed(false)
881   , fTrackId(-1)
882   , fMCId(-1)
883 {
884   // constructor
885 }
886
887 AliHLTTPCHWCFSpacePointContainer::AliHLTTPCHWCFSpacePointProperties::AliHLTTPCHWCFSpacePointProperties(const AliHLTTPCHWCFSpacePointProperties& src)
888   : fDecoder(src.fDecoder)
889   , fIndex(src.fIndex)
890   , fUsed(src.fUsed)
891   , fTrackId(src.fTrackId)
892   , fMCId(src.fMCId)
893 {
894   // copy constructor
895 }
896
897 AliHLTTPCHWCFSpacePointContainer::AliHLTTPCHWCFSpacePointProperties& AliHLTTPCHWCFSpacePointContainer::AliHLTTPCHWCFSpacePointProperties::operator=(const AliHLTTPCHWCFSpacePointProperties& src)
898 {
899   // assignment operator
900   if (&src==this) return *this;
901   fDecoder=src.fDecoder;
902   fIndex=src.fIndex;
903   fUsed=src.fUsed;
904   fTrackId=src.fTrackId;
905   fMCId=src.fMCId;
906
907   return *this;
908 }
909
910 void AliHLTTPCHWCFSpacePointContainer::AliHLTTPCHWCFSpacePointProperties::Print(ostream& out, Option_t */*option*/) const
911 {
912   // print info
913   if (!Decoder()) {
914     out << "no data";
915     return;
916   }
917   std::stringstream str;
918   const AliHLTTPCHWCFData* decoder=Decoder();
919   out.setf(ios::fixed,ios::floatfield);
920   out << " " << setfill(' ') << setw(3) << decoder->GetPadRow(fIndex) 
921       << " " << setw(8) << setprecision(3) << decoder->GetPad(fIndex)
922       << " " << setw(8) << setprecision(3) << decoder->GetTime(fIndex)
923       << " " << setw(8) << setprecision(1) << decoder->GetSigmaY2(fIndex) 
924       << " " << setw(9) << setprecision(1) << decoder->GetSigmaZ2(fIndex)
925       << " " << setw(5) << decoder->GetCharge(fIndex) 
926       << " " << setw(5) << decoder->GetQMax(fIndex)
927       << " " << fTrackId << " " << fMCId << " " << fUsed;
928   out << str;
929 }
930
931 ostream& operator<<(ostream &out, const AliHLTTPCHWCFSpacePointContainer::AliHLTTPCHWCFSpacePointProperties& p)
932 {
933   p.Print(out);
934   return out;
935 }