]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/TPCLib/AliHLTTPCAgent.cxx
flat friends update
[u/mrichter/AliRoot.git] / HLT / TPCLib / AliHLTTPCAgent.cxx
1 // $Id$
2
3 //**************************************************************************
4 //* This file is property of and copyright by the                          * 
5 //* ALICE Experiment at CERN, All rights reserved.                         *
6 //*                                                                        *
7 //* Primary Authors: Matthias Richter <Matthias.Richter@ift.uib.no>        *
8 //*                                                                        *
9 //* Permission to use, copy, modify and distribute this software and its   *
10 //* documentation strictly for non-commercial purposes is hereby granted   *
11 //* without fee, provided that the above copyright notice appears in all   *
12 //* copies and that both the copyright notice and this permission notice   *
13 //* appear in the supporting documentation. The authors make no claims     *
14 //* about the suitability of this software for any purpose. It is          *
15 //* provided "as is" without express or implied warranty.                  *
16 //**************************************************************************
17
18 //  @file   AliHLTTPCAgent.cxx
19 //  @author Matthias Richter
20 //  @date   
21 //  @brief  Agent of the libAliHLTTPC library
22 //  @note   
23
24 #include "AliHLTTPCAgent.h"
25 #include "AliHLTTPCDefinitions.h"
26 #include "AliHLTOUT.h"
27 #include "AliHLTOUTHandlerChain.h"
28 #include "AliHLTMisc.h"
29 #include "AliRunLoader.h"
30 #include "AliCDBManager.h"
31 #include "AliCDBEntry.h"
32 #include "AliTPCParam.h"
33 #include "AliTPCRecoParam.h"
34 #include "AliDAQ.h"
35 #include "TObject.h"
36
37 /** global instance for agent registration */
38 AliHLTTPCAgent gAliHLTTPCAgent;
39
40 // component headers
41 #include "AliHLTTPCCAInputDataCompressorComponent.h"
42 #include "AliHLTTPCCATrackerComponent.h"
43 #include "AliHLTTPCCATrackerOutputConverter.h"
44 #include "AliHLTTPCTrackMCMarkerComponent.h"
45 #include "AliHLTTPCCAGlobalMergerComponent.h"
46 #include "AliHLTTPCdEdxComponent.h"
47 #include "AliHLTTPCdEdxMonitoringComponent.h"
48 #include "AliHLTTPCClusterFinderComponent.h"
49 #include "AliHLTTPCDigitPublisherComponent.h"
50 #include "AliHLTTPCDigitDumpComponent.h"
51 #include "AliHLTTPCClusterDumpComponent.h"
52 #include "AliHLTTPCClusterHistoComponent.h"
53 #include "AliHLTTPCHistogramHandlerComponent.h"
54 #include "AliHLTTPCTrackHistoComponent.h"
55 #include "AliHLTTPCTrackDumpComponent.h"
56 #include "AliHLTTPCHWCFDataReverterComponent.h"
57 #include "AliHLTTPCHWClusterTransformComponent.h"
58 #include "AliHLTTPCCFComparisonComponent.h"
59 #include "AliHLTTPCDataCheckerComponent.h"
60 #include "AliHLTTPCHWCFEmulatorComponent.h"
61 #include "AliHLTTPCHWCFConsistencyControlComponent.h"
62 #include "AliHLTTPCDataCompressionComponent.h"
63 #include "AliHLTTPCDataCompressionMonitorComponent.h"
64 #include "AliHLTTPCDataCompressionFilterComponent.h"
65 #include "AliHLTTPCDataPublisherComponent.h"
66 #include "AliHLTTPCHWClusterDecoderComponent.h"
67 #include "AliHLTTPCClusterTransformationComponent.h"
68
69 /** ROOT macro for the implementation of ROOT specific class methods */
70 ClassImp(AliHLTTPCAgent)
71
72 AliHLTTPCAgent::AliHLTTPCAgent()
73   : AliHLTModuleAgent("TPC")
74   , fRawDataHandler(NULL)
75   , fTracksegsDataHandler(NULL)
76   , fClustersDataHandler(NULL)
77   , fCompressionMonitorHandler(NULL)
78 {
79   // see header file for class documentation
80   // or
81   // refer to README to build package
82   // or
83   // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
84 }
85
86 AliHLTTPCAgent::~AliHLTTPCAgent()
87 {
88   // see header file for class documentation
89 }
90
91 UInt_t AliHLTTPCAgent::GetDetectorMask() const
92 {
93   return AliDAQ::kTPC;
94 }
95
96 int AliHLTTPCAgent::CreateConfigurations(AliHLTConfigurationHandler* handler,
97                                          AliRawReader* rawReader,
98                                          AliRunLoader* runloader) const
99 {
100   // see header file for class documentation
101   if (handler) {
102     // AliSimulation: use the AliRawReaderPublisher if the raw reader is available
103     // AliReconstruction: indicated by runloader==NULL, run always on raw data
104     bool bPublishRaw=rawReader!=NULL || runloader==NULL;
105
106     // This the tracking configuration for the full TPC
107     // - 216 clusterfinders (1 per partition)
108     // - 36 slice trackers
109     // - one global merger
110     // - the esd converter
111     // The ESD is shipped embedded into a TTree
112     int iMinSlice=0; 
113     int iMaxSlice=35;
114     int iMinPart=0;
115     int iMaxPart=5;
116     TString arg;
117     TString mergerInput;
118     TString sinkRawData;
119     TString sinkHWClusterInput;
120     TString dEdXInput;
121     TString hwclustOutput;
122     TString compressorInput;
123     TString trackerInput;
124
125
126     arg.Form("-publish-raw filtered");
127     handler->CreateConfiguration("TPC-DP", "TPCDataPublisher", NULL , arg.Data());
128
129     for (int slice=iMinSlice; slice<=iMaxSlice; slice++) {
130       for (int part=iMinPart; part<=iMaxPart; part++) {
131         TString publisher;
132
133         // digit publisher components
134         publisher.Form("TPC-DP_%02d_%d", slice, part);
135         if (bPublishRaw) {
136           // AliSimulation: use the AliRawReaderPublisher if the raw reader is available
137           // AliReconstruction: indicated by runloader==NULL, run always on raw data
138           int ddlno=768;
139           if (part>1) ddlno+=72+4*slice+(part-2);
140           else ddlno+=2*slice+part;
141           arg.Form("-datatype 'DDL_RAW ' 'TPC '  -dataspec 0x%02x%02x%02x%02x", slice, slice, part, part);
142           handler->CreateConfiguration(publisher.Data(), "BlockFilter", "TPC-DP" , arg.Data());
143           if (sinkRawData.Length()>0) sinkRawData+=" ";
144           sinkRawData+=publisher;
145         } else {
146           arg.Form("-slice %d -partition %d", slice, part);
147           handler->CreateConfiguration(publisher.Data(), "TPCDigitPublisher", NULL , arg.Data());
148         }
149
150         // Hardware CF emulator
151         TString hwcfemu;
152         hwcfemu.Form("TPC-HWCFEmu_%02d_%d", slice, part);
153         arg="";
154         if (!bPublishRaw) arg+=" -do-mc 1";
155         handler->CreateConfiguration(hwcfemu.Data(), "TPCHWClusterFinderEmulator", publisher.Data(), arg.Data());
156         if (hwclustOutput.Length()>0) hwclustOutput+=" ";
157         hwclustOutput+=hwcfemu;
158         
159         TString hwcf;
160         hwcf.Form("TPC-HWCF_%02d_%d", slice, part);
161         handler->CreateConfiguration(hwcf.Data(), "TPCHWClusterTransform",hwcfemu.Data(), "-publish-raw");
162
163         //if (trackerInput.Length()>0) trackerInput+=" ";
164         //trackerInput+=hwcf;
165         //if (dEdXInput.Length()>0) dEdXInput+=" ";
166         //dEdXInput+=hwcf;
167         //if (sinkHWClusterInput.Length()>0) sinkHWClusterInput+=" ";
168         //sinkHWClusterInput+=hwcf;       
169       }
170     }
171  
172     TString hwcfDecoder = "TPC-HWCFDecoder";
173     handler->CreateConfiguration(hwcfDecoder.Data(), "TPCHWClusterDecoder",hwclustOutput.Data(), "");
174
175     TString clusterTransformation = "TPC-ClusterTransformation";
176     handler->CreateConfiguration(clusterTransformation.Data(), "TPCClusterTransformation",hwcfDecoder.Data(), "");
177
178     if (trackerInput.Length()>0) trackerInput+=" ";
179     trackerInput+=clusterTransformation;
180     if (dEdXInput.Length()>0) dEdXInput+=" ";
181     dEdXInput+=clusterTransformation;
182     if (sinkHWClusterInput.Length()>0) sinkHWClusterInput+=" ";
183     sinkHWClusterInput+=clusterTransformation;
184
185     // tracker finder component
186     // 2012-01-05 changing the configuration according to online setup
187     // the tracking strategy has been changed in the online system in Sep 2011
188     // the tracker now processes all clusters, and several of this 'global' trackers
189     // run in parallel. The GlobalMerger is still in the chain as it produces the final
190     // fit.
191     TString tracker;
192     tracker.Form("TPC-TR");
193     handler->CreateConfiguration(tracker.Data(), "TPCCATracker", trackerInput.Data(), "-GlobalTracking");
194
195     if (mergerInput.Length()>0) mergerInput+=" ";
196     mergerInput+=tracker;
197
198     // GlobalMerger component
199     handler->CreateConfiguration("TPC-globalmerger","TPCCAGlobalMerger",mergerInput.Data(),"");
200
201     // dEdx component
202     if (dEdXInput.Length()>0) dEdXInput+=" ";
203     dEdXInput+="TPC-globalmerger";
204
205     handler->CreateConfiguration("TPC-dEdx","TPCdEdx",dEdXInput.Data(),"");
206
207     // compression component
208     if (compressorInput.Length()>0) compressorInput+=" ";
209     //compressorInput+=hwclustOutput;
210     compressorInput+=hwcfDecoder;
211
212     // special configuration to run the emulation automatically if the compressed clusters
213     // of a particular partition is missing. This configuration is announced for reconstruction
214     // of raw data if the HLT mode of the TPC reconstruction is enabled. Compression component
215     // always needs to run in mode 1. Even if the recorded data is mode 3 (optimized partition
216     // clusters), 2 (track model compression), or 4. The emulation can not be in mode 2 or 4,
217     // since the track model block can not be identified with a partition. Have to duplicate the
218     // configuration of the compression component
219     handler->CreateConfiguration("TPC-compression-emulation", "TPCDataCompressor", compressorInput.Data(), "-mode 1");
220
221     if (compressorInput.Length()>0) compressorInput+=" ";
222     compressorInput+="TPC-globalmerger";
223     handler->CreateConfiguration("TPC-compression", "TPCDataCompressor", compressorInput.Data(), "");
224     handler->CreateConfiguration("TPC-compression-huffman-trainer", "TPCDataCompressor", compressorInput.Data(),"-deflater-mode 3");
225     handler->CreateConfiguration("TPC-compression-monitoring-component", "TPCDataCompressorMonitor", "TPC-compression TPC-hwcfdata","-pushback-period=30");
226     handler->CreateConfiguration("TPC-compression-monitoring", "ROOTFileWriter", "TPC-compression-monitoring-component","-concatenate-events -overwrite -datafile HLT.TPCDataCompression-statistics.root");
227
228     // the esd converter configuration
229     TString converterInput="TPC-globalmerger";
230     if (!bPublishRaw) {
231       // propagate cluster info to the esd converter in order to fill the MC information
232       handler->CreateConfiguration("TPC-clustermc-info", "BlockFilter"   , sinkHWClusterInput.Data(), "-datatype 'CLMCINFO' 'TPC '");  
233       handler->CreateConfiguration("TPC-mcTrackMarker","TPCTrackMCMarker","TPC-globalmerger TPC-clustermc-info","" );
234       converterInput+=" ";
235       converterInput+="TPC-mcTrackMarker";
236     }
237     handler->CreateConfiguration("TPC-esd-converter", "TPCEsdConverter"   , converterInput.Data(), "");
238
239     // cluster dump collection
240     handler->CreateConfiguration("TPC-clusters", "BlockFilter"   , sinkHWClusterInput.Data(), "-datatype 'CLUSTERS' 'TPC ' -datatype 'CLMCINFO' 'TPC '");
241     handler->CreateConfiguration("TPC-raw-clusters", "BlockFilter"   , sinkHWClusterInput.Data(), "-datatype 'CLUSTRAW' 'TPC ' -datatype 'CLMCINFO' 'TPC '");
242     handler->CreateConfiguration("TPC-hwclusters", "BlockFilter"   , sinkHWClusterInput.Data(), "-datatype 'CLUSTERS' 'TPC ' -datatype 'CLMCINFO' 'TPC '");
243     handler->CreateConfiguration("TPC-raw-hwclusters", "BlockFilter"   , sinkHWClusterInput.Data(), "-datatype 'CLUSTRAW' 'TPC ' -datatype 'CLMCINFO' 'TPC '");
244
245     // raw data
246     handler->CreateConfiguration("TPC-raw-data", "BlockFilter"   , sinkRawData.Data(), "");
247
248     handler->CreateConfiguration("TPC-hwcfdata", "BlockFilter"   , hwclustOutput.Data(), "-datatype 'HWCLUST1' 'TPC '");
249
250     /////////////////////////////////////////////////////////////////////////////////////
251     //
252     // dumps on the ALTRO digit level
253     //
254     // selected channel dump
255     arg.Form("-datafile selected-channel.dump -specfmt=_0x%%08x -subdir -blcknofmt= -idfmt=");
256     handler->CreateConfiguration("TPC-selected-altro-digits", "TPCDigitDump", "RCU-channelselect", arg.Data());
257
258     // raw channel dump
259     arg.Form("-datafile channel.dump -specfmt=_0x%%08x -subdir -blcknofmt= -idfmt=");
260     handler->CreateConfiguration("TPC-raw-altro-digits", "TPCDigitDump", "TPC-raw-data", arg.Data());
261
262     /////////////////////////////////////////////////////////////////////////////////////
263     //
264     // a kChain HLTOUT configuration for processing of {'TRAKSEGS':'TPC '} data blocks
265     // collects the data blocks, merges the tracks and produces an ESD object
266
267     // publisher component
268     handler->CreateConfiguration("TPC-hltout-tracksegs-publisher", "AliHLTOUTPublisher"   , NULL, "");
269
270     // GlobalMerger component
271     handler->CreateConfiguration("TPC-hltout-tracksegs-merger", "TPCGlobalMerger", "TPC-hltout-tracksegs-publisher", "");
272
273     // the esd converter configuration
274     handler->CreateConfiguration("TPC-hltout-tracksegs-esd-converter", "TPCEsdConverter", "TPC-hltout-tracksegs-merger", "");
275
276     /////////////////////////////////////////////////////////////////////////////////////
277     //
278     // a kChain HLTOUT configuration for processing of {'TRACKS  ':'TPC '} data blocks
279     // produces an ESD object from the track structure
280
281     // publisher component
282     handler->CreateConfiguration("TPC-hltout-tracks-publisher", "AliHLTOUTPublisher"   , NULL, "");
283
284     // the esd converter configuration
285     handler->CreateConfiguration("TPC-hltout-tracks-esd-converter", "TPCEsdConverter", "TPC-hltout-tracks-publisher", "");
286
287     /////////////////////////////////////////////////////////////////////////////////////
288     //
289     // a kChain HLTOUT configuration for processing of {'CLUSTERS':'TPC '} data blocks
290     // stores the blocks in file HLT.TPC.Clusters.root in HOMER format
291
292     // publisher component
293     handler->CreateConfiguration("TPC-hltout-cluster-publisher", "AliHLTOUTPublisher"   , NULL, "");
294
295     // the HLTOUT component collects the blocks and stores the file
296     handler->CreateConfiguration("TPC-hltout-cluster-dump", "HLTOUT", "TPC-hltout-cluster-publisher", "-digitfile HLT.TPC.Clusters.root -rawout=off -links 2");
297
298     /////////////////////////////////////////////////////////////////////////////////////
299     //
300     // monitoring of compressed TPC data {CLUSTRAW:TPC }, {REMCLSCM,TPC }, {CLSTRKCM,TPC }
301     // 
302
303     // publisher component
304     handler->CreateConfiguration("TPC-hltout-compressionmonitor-publisher", "AliHLTOUTPublisher"   , NULL,
305                                  "-datatype HWCLUST1 'TPC ' "
306                                  "-datatype CLUSTRAW 'TPC ' "
307                                  "-datatype REMCLSCM 'TPC ' "
308                                  "-datatype CLSTRKCM 'TPC ' "
309                                  "-datatype REMCLIDS 'TPC ' "
310                                  "-datatype CLIDSTRK 'TPC ' "
311                                  );
312
313     // the HLTOUT component collects the blocks and stores the file
314     handler->CreateConfiguration("TPC-hltout-compressionmonitor", "TPCDataCompressorMonitor", "TPC-hltout-compressionmonitor-publisher", "-histogram-file HLT.TPC-compression-statistics.root -publishing-mode off");
315   }
316
317   return 0;
318 }
319
320 const char* AliHLTTPCAgent::GetReconstructionChains(AliRawReader* /*rawReader*/,
321                                                     AliRunLoader* runloader) const
322 {
323   // see header file for class documentation
324   if (runloader) {
325     // reconstruction chains for AliRoot simulation
326     return "TPC-compression";
327   } else {
328     return "TPC-compression-emulation";
329   }
330   return NULL;
331 }
332
333 const char* AliHLTTPCAgent::GetRequiredComponentLibraries() const
334 {
335   // see header file for class documentation
336
337   // actually, the TPC library has dependencies to Util and RCU
338   // so the two has to be loaded anyhow before we get here
339   //return "libAliHLTUtil.so libAliHLTRCU.so";
340   return "libAliHLTUtil.so";
341 }
342
343 int AliHLTTPCAgent::RegisterComponents(AliHLTComponentHandler* pHandler) const
344 {
345   // see header file for class documentation
346   if (!pHandler) return -EINVAL;
347
348   pHandler->AddComponent(new AliHLTTPCCAInputDataCompressorComponent);
349   pHandler->AddComponent(new AliHLTTPCCATrackerComponent);
350   pHandler->AddComponent(new AliHLTTPCCATrackerOutputConverter);
351   pHandler->AddComponent(new AliHLTTPCCAGlobalMergerComponent);
352   pHandler->AddComponent(new AliHLTTPCTrackMCMarkerComponent);
353   pHandler->AddComponent(new AliHLTTPCdEdxComponent);
354   pHandler->AddComponent(new AliHLTTPCdEdxMonitoringComponent);
355   pHandler->AddComponent(new AliHLTTPCClusterFinderComponent(AliHLTTPCClusterFinderComponent::kClusterFinderPacked));
356   pHandler->AddComponent(new AliHLTTPCClusterFinderComponent(AliHLTTPCClusterFinderComponent::kClusterFinderUnpacked));
357   pHandler->AddComponent(new AliHLTTPCClusterFinderComponent(AliHLTTPCClusterFinderComponent::kClusterFinderDecoder));
358   pHandler->AddComponent(new AliHLTTPCClusterFinderComponent(AliHLTTPCClusterFinderComponent::kClusterFinder32Bit));
359   pHandler->AddComponent(new AliHLTTPCDigitPublisherComponent);
360   pHandler->AddComponent(new AliHLTTPCDigitDumpComponent);
361   pHandler->AddComponent(new AliHLTTPCClusterDumpComponent);
362   pHandler->AddComponent(new AliHLTTPCClusterHistoComponent);
363   pHandler->AddComponent(new AliHLTTPCHistogramHandlerComponent);
364   pHandler->AddComponent(new AliHLTTPCTrackHistoComponent);
365   pHandler->AddComponent(new AliHLTTPCTrackDumpComponent);
366   pHandler->AddComponent(new AliHLTTPCHWCFDataReverterComponent);
367   pHandler->AddComponent(new AliHLTTPCHWClusterTransformComponent);
368   pHandler->AddComponent(new AliHLTTPCCFComparisonComponent);
369   pHandler->AddComponent(new AliHLTTPCDataCheckerComponent);
370   pHandler->AddComponent(new AliHLTTPCHWCFEmulatorComponent);
371 //  pHandler->AddComponent(new AliHLTTPCHWCFConsistencyControlComponent);  //FIXME: Causes crash: https://savannah.cern.ch/bugs/?83677
372   pHandler->AddComponent(new AliHLTTPCDataCompressionComponent);
373   pHandler->AddComponent(new AliHLTTPCDataCompressionMonitorComponent);
374   pHandler->AddComponent(new AliHLTTPCDataCompressionFilterComponent);
375   pHandler->AddComponent(new AliHLTTPCDataPublisherComponent);
376   pHandler->AddComponent(new AliHLTTPCHWClusterDecoderComponent);
377   pHandler->AddComponent(new AliHLTTPCClusterTransformationComponent);
378   return 0;
379 }
380
381 int AliHLTTPCAgent::GetHandlerDescription(AliHLTComponentDataType dt,
382                                           AliHLTUInt32_t spec,
383                                           AliHLTOUTHandlerDesc& desc) const
384 {
385   // see header file for class documentation
386
387   // raw data blocks to be fed into offline reconstruction
388   if (dt==(kAliHLTDataTypeDDLRaw|kAliHLTDataOriginTPC)) {
389     int slice=AliHLTTPCDefinitions::GetMinSliceNr(spec);
390     int part=AliHLTTPCDefinitions::GetMinPatchNr(spec);
391     if (slice==AliHLTTPCDefinitions::GetMaxSliceNr(spec) &&
392         part==AliHLTTPCDefinitions::GetMaxPatchNr(spec)) {
393       desc=AliHLTOUTHandlerDesc(kRawReader, dt, GetModuleId());
394       return 1;
395     } else {
396       HLTWarning("handler can not process merged data from multiple ddls:"
397                  " min slice %d, max slice %d, min part %d, max part %d",
398                  slice, AliHLTTPCDefinitions::GetMaxSliceNr(spec),
399                  part, AliHLTTPCDefinitions::GetMaxPatchNr(spec));
400       return 0;
401     }
402   }
403
404   // dump for {'CLUSTERS':'TPC '} blocks stored in a 'digit' file
405   if (dt==AliHLTTPCDefinitions::fgkClustersDataType) {
406       desc=AliHLTOUTHandlerDesc(kChain, dt, GetModuleId());
407       return 1;
408   }
409
410   // define handlers for all blocks related to compression, flag if the
411   // cluster id blocks are existing, this will be used to decide
412   // whether to create the handler or not
413   // {'CLUSTRAW':'TPC '}
414   // {'HWCLUST1':'TPC '}
415   // {'REMCLSCM':'TPC '}
416   // {'CLSTRKCM':'TPC '}
417   // {'REMCLIDS':'TPC '}
418   // {'CLIDSTRK':'TPC '}
419   if (dt==AliHLTTPCDefinitions::RawClustersDataType() ||
420       dt==AliHLTTPCDefinitions::HWClustersDataType() ||
421       dt==AliHLTTPCDefinitions::RemainingClustersCompressedDataType() ||
422       dt==AliHLTTPCDefinitions::ClusterTracksCompressedDataType()) {
423       desc=AliHLTOUTHandlerDesc(kProprietary, dt, GetModuleId());
424       return 1;
425   }
426   if (dt==AliHLTTPCDefinitions::RemainingClusterIdsDataType() ||
427       dt==AliHLTTPCDefinitions::ClusterIdTracksDataType()) {
428       desc=AliHLTOUTHandlerDesc(kProprietary, dt, GetModuleId());
429       const_cast<AliHLTTPCAgent*>(this)->SetBit(kHaveCompressedClusterIdDataBlock);
430       return 1;
431   }
432
433   // {'CLMCINFO':'TPC '} 
434   if (dt==AliHLTTPCDefinitions::fgkAliHLTDataTypeClusterMCInfo) {
435       desc=AliHLTOUTHandlerDesc(kProprietary, dt, GetModuleId());
436       return 1;
437   }
438
439   // afterburner for {'TRAKSEGS':'TPC '} blocks to be converted to ESD format
440   if (dt==AliHLTTPCDefinitions::fgkTrackSegmentsDataType) {
441       desc=AliHLTOUTHandlerDesc(kChain, dt, GetModuleId());
442       return 1;
443   }
444
445   // afterburner for {'TRACKS  ':'TPC '} block to be converted to ESD format
446   // there is only one data block
447   if (dt==AliHLTTPCDefinitions::fgkTracksDataType) {
448       desc=AliHLTOUTHandlerDesc(kChain, dt, GetModuleId());
449       return 1;
450   }
451   return 0;
452 }
453
454 AliHLTOUTHandler* AliHLTTPCAgent::GetOutputHandler(AliHLTComponentDataType dt,
455                                                    AliHLTUInt32_t /*spec*/)
456 {
457   // see header file for class documentation
458
459   // raw data blocks to be fed into offline reconstruction
460   if (dt==(kAliHLTDataTypeDDLRaw|kAliHLTDataOriginTPC)) {
461     if (!fRawDataHandler) {
462       fRawDataHandler=new AliHLTTPCAgent::AliHLTTPCRawDataHandler;
463     }
464     return fRawDataHandler;
465   }
466
467   // dump for {'CLUSTERS':'TPC '}, stored in a file HLT.TPC.Clusters.root in HOMER format
468   if (dt==AliHLTTPCDefinitions::fgkClustersDataType) {
469     if (fClustersDataHandler==NULL)
470       fClustersDataHandler=new AliHLTOUTHandlerChain("chains=TPC-hltout-cluster-dump libHLTsim.so libAliHLTUtil.so");
471     return fClustersDataHandler;
472   }
473
474   // afterburner for {'TRAKSEGS':'TPC '} blocks to be converted to ESD format
475   // in a kChain HLTOUT handler
476   if (dt==AliHLTTPCDefinitions::fgkTrackSegmentsDataType) {
477     if (fTracksegsDataHandler==NULL)
478       fTracksegsDataHandler=new AliHLTOUTHandlerChain("chains=TPC-hltout-tracksegs-esd-converter");
479     return fTracksegsDataHandler;
480   }
481
482   // afterburner for {'TRACKS  ':'TPC '} block to be converted to ESD format
483   // there is only one data block
484   if (dt==AliHLTTPCDefinitions::fgkTracksDataType) {
485     return new AliHLTOUTHandlerChain("chains=TPC-hltout-tracks-esd-converter");
486   }
487
488   // monitoring of compressed data if cluster verification blocks exist
489   // {'REMCLIDS':'TPC '}
490   // {'CLIDSTRK':'TPC '}
491   // FIXME: needs to be commissioned
492   // if (dt==AliHLTTPCDefinitions::RawClustersDataType() ||
493   //     dt==AliHLTTPCDefinitions::HWClustersDataType() ||
494   //     dt==AliHLTTPCDefinitions::RemainingClustersCompressedDataType() ||
495   //     dt==AliHLTTPCDefinitions::ClusterTracksCompressedDataType() ||
496   //     dt==AliHLTTPCDefinitions::RemainingClusterIdsDataType() ||
497   //     dt==AliHLTTPCDefinitions::ClusterIdTracksDataType()) {
498   //   const char* arg="chains=TPC-hltout-compressionmonitor";
499   //   if (!TestBit(kHaveCompressedClusterIdDataBlock))
500   //     arg="chains=TPC-hltout-compressionmonitorpublisher";
501   //   if (!fCompressionMonitorHandler)
502   //     fCompressionMonitorHandler=new AliHLTOUTHandlerChain(arg);
503   //   return fCompressionMonitorHandler;
504   // }
505
506   return NULL;
507 }
508
509 int AliHLTTPCAgent::DeleteOutputHandler(AliHLTOUTHandler* pInstance)
510 {
511   // see header file for class documentation
512   if (pInstance==NULL) return -EINVAL;
513
514   if (pInstance==fRawDataHandler) {
515     delete fRawDataHandler;
516     fRawDataHandler=NULL;
517   }
518
519   if (pInstance==fTracksegsDataHandler) {
520     delete fTracksegsDataHandler;
521     fTracksegsDataHandler=NULL;
522   }
523
524   if (pInstance==fClustersDataHandler) {
525     delete fClustersDataHandler;
526     fClustersDataHandler=NULL;
527   }
528
529   if (pInstance==fCompressionMonitorHandler) {
530     delete fCompressionMonitorHandler;
531     fCompressionMonitorHandler=NULL;
532   }
533
534   return 0;
535 }
536
537 AliHLTTPCAgent::AliHLTTPCRawDataHandler::AliHLTTPCRawDataHandler()
538 {
539   // see header file for class documentation
540 }
541
542 AliHLTTPCAgent::AliHLTTPCRawDataHandler::~AliHLTTPCRawDataHandler()
543 {
544   // see header file for class documentation
545 }
546
547 int AliHLTTPCAgent::AliHLTTPCRawDataHandler::ProcessData(AliHLTOUT* pData)
548 {
549   // see header file for class documentation
550   if (!pData) return -EINVAL;
551   AliHLTComponentDataType dt=kAliHLTVoidDataType;
552   AliHLTUInt32_t spec=kAliHLTVoidDataSpec;
553   int iResult=pData->GetDataBlockDescription(dt, spec);
554   if (iResult>=0) {
555     int slice=AliHLTTPCDefinitions::GetMinSliceNr(spec);
556     int part=AliHLTTPCDefinitions::GetMinPatchNr(spec);
557     if (slice==AliHLTTPCDefinitions::GetMaxSliceNr(spec) &&
558         part==AliHLTTPCDefinitions::GetMaxPatchNr(spec)) {
559       iResult=768;
560       if (part>1) iResult+=72+4*slice+(part-2);
561       else iResult+=2*slice+part;
562     } else {
563       HLTError("handler can not process merged data from multiple ddls:"
564                " min slice %d, max slice %d, min part %d, max part %d",
565                slice, AliHLTTPCDefinitions::GetMaxSliceNr(spec),
566                part, AliHLTTPCDefinitions::GetMaxPatchNr(spec));
567       iResult=-EBADMSG;
568     }
569   }
570   return iResult;
571 }