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