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