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