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