update of AltroChannelSelector component by Jason: added monitoring histograms, make...
[u/mrichter/AliRoot.git] / HLT / RCU / AliHLTAltroChannelSelectorComponent.cxx
CommitLineData
3e6ec852 1// $Id$
2
13398559 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//**************************************************************************
3e6ec852 18
ff4a65b9 19/// @file AliHLTAltroChannelSelectorComponent.cxx
1ea9f419 20/// @author Matthias Richter edited by Jason Glyndwr Ulery
ff4a65b9 21/// @date
22/// @brief A filter/selective readout component for Altro data.
23///
3e6ec852 24
e1440dab 25#include <cassert>
ff4a65b9 26#include <memory>
3e6ec852 27#include "AliHLTAltroChannelSelectorComponent.h"
ff4a65b9 28#include "AliHLTErrorGuard.h"
29#include "AliHLTDAQ.h"
30#include "AliRawReaderMemory.h"
31#include "AliAltroRawStreamV3.h"
2a32beb8 32#include "TMath.h"
72ecb506 33#include "TH1.h"
34#include "TH2.h"
35#include "TFile.h"
3e6ec852 36
37/** ROOT macro for the implementation of ROOT specific class methods */
38ClassImp(AliHLTAltroChannelSelectorComponent)
39
40AliHLTAltroChannelSelectorComponent::AliHLTAltroChannelSelectorComponent()
41 :
e1440dab 42 AliHLTProcessor(),
2a32beb8 43 fSkipCorrupted(true),
44 fTalkative(false),
45 fStartTimeBin(0),
f5bd9c68 46 fEndTimeBin(1024),
2a32beb8 47 fSignalThreshold(0),
72ecb506 48 fRMSThreshold(0),
49 fMakeHistogram(false),
50 fhThreshold(NULL),
51 fhRMS(NULL)
3e6ec852 52{
53 // see header file for class documentation
54 // or
55 // refer to README to build package
56 // or
57 // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
58}
59
60AliHLTAltroChannelSelectorComponent::~AliHLTAltroChannelSelectorComponent()
61{
62 // see header file for class documentation
63}
64
65const char* AliHLTAltroChannelSelectorComponent::GetComponentID()
66{
67 // see header file for class documentation
68 return "AltroChannelSelector";
69}
70
71void AliHLTAltroChannelSelectorComponent::GetInputDataTypes(AliHLTComponentDataTypeList& list)
72{
73 // see header file for class documentation
74 list.clear();
75 list.push_back(kAliHLTDataTypeDDLRaw|kAliHLTDataOriginTPC);
64defa03 76 list.push_back(kAliHLTDataTypeHwAddr16);
3e6ec852 77}
78
79AliHLTComponentDataType AliHLTAltroChannelSelectorComponent::GetOutputDataType()
80{
81 // see header file for class documentation
82 return kAliHLTDataTypeDDLRaw|kAliHLTDataOriginTPC;
83}
84
85void AliHLTAltroChannelSelectorComponent::GetOutputDataSize(unsigned long& constBase, double& inputMultiplier)
86{
87 // see header file for class documentation
88 constBase=0;
89 inputMultiplier=1.0;
90}
91
92AliHLTComponent* AliHLTAltroChannelSelectorComponent::Spawn()
93{
94 // see header file for class documentation
95 return new AliHLTAltroChannelSelectorComponent;
96}
97
98int AliHLTAltroChannelSelectorComponent::DoInit(int argc, const char** argv)
99{
100 // see header file for class documentation
101 int iResult=0;
102 TString argument="";
e1440dab 103 bool bMissingParam=0;
2a32beb8 104 char* cpErr=NULL;
105 int i=0;
106 for (; i<argc && iResult>=0; i++) {
107 cpErr=NULL;
3e6ec852 108 argument=argv[i];
109 if (argument.IsNull()) continue;
110
2a32beb8 111 // -skip-corrupted, just for backward compatibility, not announced
4ca5858d 112 if (argument.CompareTo("-skip-corrupted")==0) {
113 fSkipCorrupted=true;
114
2a32beb8 115 // -keep-corrupted
116 } else if (argument.CompareTo("-keep-corrupted")==0) {
117 fSkipCorrupted=false;
118
4ca5858d 119 // -talkative
120 } else if (argument.CompareTo("-talkative")==0) {
121 fTalkative=true;
2a32beb8 122
123 // -start-timebin
124 } else if (argument.CompareTo("-start-timebin")==0) {
9d5f00ad 125 if ((bMissingParam=(++i>=argc))) break;
2a32beb8 126 fStartTimeBin = strtoul( argv[i], &cpErr ,0);
127 if ( *cpErr ) break;
128
129 // -end-timebin
130 } else if (argument.CompareTo("-end-timebin")==0) {
9d5f00ad 131 if ((bMissingParam=(++i>=argc))) break;
2a32beb8 132 fEndTimeBin = strtoul( argv[i], &cpErr ,0);
133 if ( *cpErr ) break;
134
135 // -signal-threshold
136 } else if (argument.CompareTo("-signal-threshold")==0) {
9d5f00ad 137 if ((bMissingParam=(++i>=argc))) break;
2a32beb8 138 fSignalThreshold = strtoul( argv[i], &cpErr ,0);
139 if ( *cpErr ) break;
140
141 // -rms-threshold
142 } else if (argument.CompareTo("-rms-threshold")==0) {
9d5f00ad 143 if ((bMissingParam=(++i>=argc))) break;
72ecb506 144 fRMSThreshold = strtod( argv[i], &cpErr);
2a32beb8 145 if ( *cpErr ) break;
146
72ecb506 147 }
148 //-make-histogram
149 else if(argument.CompareTo("-make-histogram")==0){
150 fMakeHistogram=true;
151 }
152 else {
4ca5858d 153 HLTError("unknown argument %s", argument.Data());
3e6ec852 154 iResult=-EINVAL;
155 }
156 }
157
2a32beb8 158 if (cpErr && *cpErr) {
159 HLTError("Cannot convert specifier '%s' for argument '%s'", argv[i], argument.Data());
160 iResult=-EINVAL;
161 } else if (bMissingParam) {
e1440dab 162 HLTError("missing parameter for argument %s", argument.Data());
163 iResult=-EINVAL;
164 }
165
72ecb506 166 if(fMakeHistogram){
167 fhThreshold=new TH1F("fhThreshold","signal-threshold",1000,0,20);
168 if (fhThreshold) {
169 fhThreshold->Sumw2();
170 fhThreshold->GetXaxis()->SetTitle("MaxSignal - <Signal>");
171 }
172 fhRMS=new TH1F("fhRMS","rms-threshold",1000,0,10);
173 if (fhRMS) {
174 fhRMS->Sumw2();
175 fhRMS->GetXaxis()->SetTitle("MaxSignal/ #sqrt{<Signal^{2}>}");
176 }
177 }
178
3e6ec852 179 return iResult;
180}
181
182int AliHLTAltroChannelSelectorComponent::DoDeinit()
183{
184 // see header file for class documentation
72ecb506 185 if(fMakeHistogram){
186 std::auto_ptr<TFile> outFile(new TFile("CSHistos.root","recreate"));
187 if (outFile.get() && !outFile->IsZombie()) {
188 if (fhThreshold) fhThreshold->Write();
189 if (fhRMS) fhRMS->Write();
190 outFile->Write();
191 outFile->Close();
192 }
193 }
194 if (fhThreshold) delete fhThreshold;
195 if (fhRMS) delete fhRMS;
196 fhRMS=NULL;
197 fhThreshold=NULL;
3e6ec852 198 return 0;
199}
200
201int AliHLTAltroChannelSelectorComponent::DoEvent(const AliHLTComponentEventData& evtData,
202 const AliHLTComponentBlockData* blocks,
203 AliHLTComponentTriggerData& /*trigData*/,
204 AliHLTUInt8_t* outputPtr,
205 AliHLTUInt32_t& size,
206 AliHLTComponentBlockDataList& outputBlocks )
207{
208 // see header file for class documentation
209 int iResult=0;
1ea9f419 210 AliHLTUInt32_t iCapacity=size;
211 size=0;
212
213 const int cdhSize=32;//8 32-bit words so 32 bytes
214 const int rcuSize=36;//9 32-bit words
3e6ec852 215
8d682af4 216 if (!IsDataEvent()) {
217 size=0;
218 return 0;
219 }
220
e1440dab 221 // process the DLL input
222 int blockno=0;
1d337632 223 const AliHLTComponentBlockData* pDesc=NULL;
ff4a65b9 224 std::auto_ptr<AliRawReaderMemory> pRawReader(new AliRawReaderMemory);
fa7ed16b 225 if (!pRawReader.get()) return -ENOMEM;
1d337632 226
4ca5858d 227 for (pDesc=GetFirstInputBlock(kAliHLTDataTypeDDLRaw); pDesc!=NULL; pDesc=GetNextInputBlock(), blockno++) {
228 iResult=0;
359ba057 229 if (pDesc->fSize<=32) {
230 continue;
231 }
e1440dab 232
233 // search for the active pad information
64defa03 234 AliHLTUInt16_t* pActiveHwAddressArray=NULL;
235 int iArraySize=0;
72ecb506 236 if (fSignalThreshold==0 && fabs(fRMSThreshold)<1E-4) {
e1440dab 237 for (int i=0; i<(int)evtData.fBlockCnt; i++ ) {
64defa03 238 // search for selection data of hw address type
4ca5858d 239 // which matches the data specification of the block
240 if (blocks[i].fDataType==kAliHLTDataTypeHwAddr16 && blocks[i].fSpecification==pDesc->fSpecification) {
241 pActiveHwAddressArray=reinterpret_cast<AliHLTUInt16_t*>(blocks[i].fPtr);
242 iArraySize=blocks[i].fSize/sizeof(AliHLTUInt16_t);
243 break;
e1440dab 244 }
245 }
4ca5858d 246 if (pActiveHwAddressArray==NULL) {
2a32beb8 247 HLTWarning("no block of type %s for specification 0x%08x available, data block skipped",
64defa03 248 DataType2Text(kAliHLTDataTypeHwAddr16).c_str(),
1d337632 249 pDesc->fSpecification);
2a32beb8 250 break;
251 }
4ca5858d 252 }
253
ff4a65b9 254 pRawReader->Reset();
255 int ddlid=AliHLTDAQ::DdlIDFromHLTBlockData(pDesc->fDataType.fOrigin, pDesc->fSpecification);
256 if (ddlid<0) {
257 HLTError("unable to extract DDL Id for data block %s 0x%08x", DataType2Text(pDesc->fDataType).c_str(), pDesc->fSpecification);
258 continue;
259 }
260
261 if (!pRawReader->AddBuffer((UChar_t*)pDesc->fPtr,pDesc->fSize, ddlid)) {
262 ALIHLTERRORGUARD(1, "can not set up AltroDecoder for data block %s 0x%08x,"
263 " skipping data block and suppressing further messages",
264 DataType2Text(pDesc->fDataType).c_str(), pDesc->fSpecification);
265 continue;
266 }
267
268 std::auto_ptr<AliAltroRawStreamV3> altroRawStream(new AliAltroRawStreamV3(pRawReader.get()));
269
270 if (!altroRawStream.get()) {
271 iResult=-ENOMEM;
272 break;
273 }
274
275 altroRawStream->Reset();
276 if (!altroRawStream->NextDDL()) {
277 ALIHLTERRORGUARD(1, "internal error, can not read data from AliRawReaderMemory");
278 continue;
4ca5858d 279 }
280
1ea9f419 281 unsigned int rcuTrailerLength=rcuSize;
282 if(rcuTrailerLength>pDesc->fSize-cdhSize) HLTWarning("corrupted data block: RCU trailer length exceeds buffer size");
283
4ca5858d 284 if (iResult<0) {
8d682af4 285 // TODO: here the trigger has to come into play. It is up to
286 // policy if a corrupted data block should be kept (original
287 // DDL) or discarded. In any case, the block is not going to
288 // be part of HLTOUT
289 HLTWarning("skipping corrupted data block for event %lu, data block %s 0x%08x", evtData.fEventID,
290 DataType2Text(pDesc->fDataType).c_str(), pDesc->fSpecification);
3dcae0cc 291 iResult=0;
e1440dab 292 continue;
293 }
294
1d337632 295 int iSelected=0;
296 int iTotal=0;
4ca5858d 297 int iCorrupted=0;
e1440dab 298 AliHLTUInt32_t iOutputSize=0;
1ea9f419 299
300 //First add the common data header (CDH)
301 memcpy(outputPtr+size,pDesc->fPtr,cdhSize);
302 iOutputSize+=cdhSize;
8d682af4 303
ff4a65b9 304 while (altroRawStream->NextChannel() && iResult>=0) {
1d337632 305 iTotal++;
ff4a65b9 306 int hwAddress=altroRawStream->GetHWAddress();
1ea9f419 307
2a32beb8 308 if (fSignalThreshold!=0) {
309 // treshold by adc counts
310 unsigned int sumSignals=0;
311 unsigned int maxSignal=0;
312 unsigned int nofSignals=0;
ff4a65b9 313 while(altroRawStream->NextBunch()){
314 const UShort_t *bunchData=altroRawStream->GetSignals();
315 unsigned int time=altroRawStream->GetStartTimeBin();
316 for(Int_t i=0;i<altroRawStream->GetBunchLength();i++){
2a32beb8 317 if(bunchData[i]>0){// disregarding 0 data.
318 if(time+i>=fStartTimeBin && time+i<=fEndTimeBin){
319 sumSignals+=bunchData[i];
320 if (maxSignal<bunchData[i]) maxSignal=bunchData[i];
321 nofSignals++;
322 }
323 }
324 }
325 }
326 if (nofSignals==0 || maxSignal<=(sumSignals/nofSignals)+fSignalThreshold) {
327 continue;
328 }
72ecb506 329 if (fhThreshold) fhThreshold->Fill(maxSignal-(sumSignals/nofSignals));
2a32beb8 330
72ecb506 331 } else if (fabs(fRMSThreshold)>1E-4) {
2a32beb8 332 // treshold by adc counts
333 unsigned int sumSignals=0;
334 unsigned int maxSignal=0;
335 unsigned int nofSignals=0;
ff4a65b9 336 while(altroRawStream->NextBunch()){
337 const UShort_t *bunchData=altroRawStream->GetSignals();
338 unsigned int time=altroRawStream->GetStartTimeBin();
339 for(Int_t i=0;i<altroRawStream->GetBunchLength();i++){
2a32beb8 340 if(bunchData[i]>0){// disregarding 0 data.
341 if(time+i>=fStartTimeBin && time+i<=fEndTimeBin){
342 sumSignals+=bunchData[i]*bunchData[i];
343 if (maxSignal<bunchData[i]) maxSignal=bunchData[i];
344 nofSignals++;
345 }
346 }
347 }
348 }
349 if (nofSignals==0 || maxSignal<=TMath::Sqrt(sumSignals/nofSignals)*fRMSThreshold) {
350 continue;
351 }
72ecb506 352 if (fhRMS) fhRMS->Fill(maxSignal/TMath::Sqrt(sumSignals/nofSignals));
2a32beb8 353 } else {
e1440dab 354 int active=0;
4ca5858d 355 for (active=0; active<iArraySize; active++) {
356 if (pActiveHwAddressArray[active]==(AliHLTUInt16_t)hwAddress) {
357 break;
e1440dab 358 }
359 }
64defa03 360 if (active>=iArraySize) {
4ca5858d 361 HLTDebug("ALTRO block %#x (%d) discarded (inactive)", hwAddress, hwAddress);
e1440dab 362 continue;
363 }
2a32beb8 364 }
e1440dab 365
4ca5858d 366 // no of 10 bit words is without the fill words to fill complete 40 bit words
367 // in addition, align to complete 40 bit words (the '+3')
1ea9f419 368 // also, the 4 bytes of the Altro trailer must be added to get the full size
ff4a65b9 369 int channelSize=((altroRawStream->GetChannelPayloadSize()+2)/3)*4;
8d682af4 370 if (channelSize==0) {
371 if (fTalkative) HLTWarning("skipping zero length channel (hw address %d)", hwAddress);
372 iCorrupted++;
373 continue;
374 }
ff4a65b9 375 channelSize+=4;
4ca5858d 376 HLTDebug("ALTRO block hwAddress 0x%08x (%d) selected (active), size %d", hwAddress, hwAddress, channelSize);
4ca5858d 377
1ea9f419 378 if (iCapacity>=(channelSize+iOutputSize)) {
379 const UChar_t *ChannelData=altroRawStream->GetChannelPayload();
380 iResult=channelSize;
381 memcpy(outputPtr+size+iOutputSize,ChannelData,channelSize);
382 if (channelSize == iResult){
ff4a65b9 383 if (channelSize%4 == 0) {
4ca5858d 384 iOutputSize+=channelSize;
e1440dab 385 } else {
1ea9f419 386 if (fTalkative) HLTWarning("corrupted ALTRO channel: incomplete 32 bit word (channel hw address %d)", hwAddress);
4ca5858d 387 iCorrupted++;
388 continue;
e1440dab 389 }
4ca5858d 390 } else {
8d682af4 391 if (fTalkative) HLTWarning("internal error: failed to copy full channel: %d out of %d bytes (hw address %d)", iResult, channelSize, hwAddress);
4ca5858d 392 iCorrupted++;
393 continue;
e1440dab 394 }
e1440dab 395 } else {
8d682af4 396 if (fTalkative) HLTError("failed to write ALTRO channel of length %d for block %d (hw address %d)", channelSize, blockno, hwAddress);
4ca5858d 397 // corrupted channel, but keep going
398 iCorrupted++;
399 iResult=0;
400 continue;
1ea9f419 401 }
4ca5858d 402 iSelected++;
e1440dab 403 }
1ea9f419 404
e1440dab 405 if (iResult>=0) {
1ea9f419 406 //Write the RCU Trailer
407 AliHLTUInt8_t* pSrc=reinterpret_cast<AliHLTUInt8_t*>(pDesc->fPtr);
408 pSrc+=pDesc->fSize-rcuTrailerLength;
409 memcpy(outputPtr+size+iOutputSize,pSrc,rcuTrailerLength);
410 iOutputSize+=rcuTrailerLength;
411
412 //Set new payload length of the new data bloock
413 AliHLTUInt32_t* pSize=reinterpret_cast<AliHLTUInt32_t*>(outputPtr+size+iOutputSize-rcuTrailerLength);
414 (*pSize)&=~0x3FFFFFF;
415 (*pSize)|=(iOutputSize-rcuTrailerLength-cdhSize+3)/4;//# of 32 bit words in payload
416
417 //Write DDL length
418 AliHLTUInt32_t* pCdhSize=reinterpret_cast<AliHLTUInt32_t*>(outputPtr+size);
419 *pCdhSize=iOutputSize;
420
421 // insert block descriptor
422 AliHLTComponentBlockData bd;
423 FillBlockData(bd);
424 bd.fOffset=size;
425 bd.fSize=iOutputSize;
426 bd.fDataType=pDesc->fDataType;
427 bd.fSpecification=pDesc->fSpecification;
428 outputBlocks.push_back(bd);
429 size+=iOutputSize;
e1440dab 430 }
359ba057 431 if (fTalkative) HLTImportant("data block %d (0x%08x): selected %d out of %d ALTRO channel(s), %d corrupted channels skipped", blockno, pDesc->fSpecification, iSelected, iTotal, iCorrupted);
3e6ec852 432 }
433
e1440dab 434 if (iResult<0) {
435 outputBlocks.clear();
3e6ec852 436 }
3e6ec852 437 return iResult;
438}