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