]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/RCU/AliHLTAltroGenerator.cxx
code documantation and minor cleanup
[u/mrichter/AliRoot.git] / HLT / RCU / AliHLTAltroGenerator.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   AliHLTAltroGenerator.cxx
20     @author Matthias Richter
21     @date   
22     @brief  Simulation class of 10/40bit Altro Data.
23 */
24
25 #include <cassert>
26 #include <cerrno>
27 #include "AliHLTAltroGenerator.h"
28 #include "TArrayS.h"
29 #include "TArrayC.h"
30 #include "TRandom.h"
31 #include "TDatime.h"
32 #include "AliRawDataHeader.h"
33 #include "AliHLTAltroEncoder.h"
34
35 /** ROOT macro for the implementation of ROOT specific class methods */
36 ClassImp(AliHLTAltroGenerator)
37
38 AliHLTAltroGenerator::AliHLTAltroGenerator(int maxChannels,
39                                            int maxBunches,
40                                            int maxBunchLength,
41                                            int maxTimebin,
42                                            int maxSignal)
43   :
44   fpData(NULL),
45   fpSimData(NULL),
46   fChannelPositions(),
47   fNof10BitWords(0),
48   fpCDH(NULL),
49   fCDHSize(0),
50   fpTrailer(NULL),
51   fTrailerSize(0),
52   fMaxChannels(maxChannels),
53   fMaxBunches(maxBunches),
54   fMaxBunchLength(maxBunchLength),
55   fMaxTimebin(maxTimebin),
56   fMaxSignal(maxSignal),
57   fpRand(NULL),
58   fDirection(kBackwards),
59   fCurrentPosition(-1),
60   fCurrentBunch(-1),
61   fCurrentTimeOffset(-1)
62 {
63   // see header file for class documentation
64   // or
65   // refer to README to build package
66   // or
67   // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
68 }
69
70 AliHLTAltroGenerator::~AliHLTAltroGenerator()
71 {
72   // see header file for class documentation
73   if (fpTrailer) delete[] fpTrailer;
74   if (fpCDH) delete[] fpCDH;
75   if (fpSimData) delete fpSimData;
76   if (fpData) delete fpData;
77 }
78
79 int AliHLTAltroGenerator::Generate()
80 {
81   // see header file for class documentation
82   int iResult=0;
83
84   if (!fpSimData) fpSimData=new TArrayS;
85   if (!fpSimData) {
86     return -ENOMEM;
87   }
88
89   Reset();
90
91   int nofChannels=GetRandom(1, fMaxChannels);
92   if (nofChannels==0) nofChannels=1;
93
94   HLTDebug("number of channels: %d", nofChannels);
95   int channelAddress=-1;
96   int lastChannel=-1;
97   int dataPos=0;
98   int repetitions=0;
99   for (int channel=0; channel<nofChannels; channel++) {
100     channelAddress=GetRandom(0, fMaxChannels);
101     //HLTDebug("channel %d: address %d, %d bunch(es)", channel, channelAddress, nofBunches);
102     if (channelAddress==lastChannel) {
103       channel--;
104       if (repetitions++>5) break;
105       continue;
106     }
107     int nofBunches=GetRandom(1, fMaxBunches);
108     if (nofBunches==0) {
109       channel--;
110       if (repetitions++>5) break;
111       continue;
112     }
113     repetitions=0;
114     int totalBunches=0;
115     int bunchEndTime=fMaxTimebin;
116
117     HLTDebug("simulate channel %d: address %d", channel, channelAddress);
118
119     // save beginning of this channel for better navigation
120     AliChannelPosition position={channelAddress, dataPos, 0};
121
122     // add channel address and bunch count at the beginning
123     if (fpSimData->GetSize()<dataPos+2) fpSimData->Set(dataPos+2);
124     (*fpSimData)[dataPos++]=channelAddress;
125     dataPos++; // placeholder for number of bunches
126
127     int bunch=0;
128     for (bunch=0; bunch<nofBunches && bunchEndTime>0; bunch++) {
129       bunchEndTime=GetRandom(0, bunchEndTime-1);
130       int bunchLength=GetRandom(0, bunchEndTime<fMaxBunchLength?bunchEndTime:fMaxBunchLength);
131       if (bunchLength==0) continue;
132       totalBunches++;
133
134       HLTDebug("       bunch %d, length %d, end time %d ", bunch, bunchLength, bunchEndTime);
135
136       if (fpSimData->GetSize()<dataPos+bunchLength+4) fpSimData->Set(dataPos+bunchLength+4);
137       // write bunch length and time at both ends
138       (*fpSimData)[dataPos++]=bunchLength;
139       int time=bunchEndTime-bunchLength+1;
140       (*fpSimData)[dataPos++]=time;
141       for (; time<=bunchEndTime; time++) {      
142         int signal=GetRandom(0, fMaxSignal);
143         (*fpSimData)[dataPos++]=signal;
144       }
145       (*fpSimData)[dataPos++]=bunchEndTime;
146       (*fpSimData)[dataPos++]=bunchLength;
147       fNof10BitWords+=bunchLength+2;
148     }
149     if (totalBunches>0) {
150       (*fpSimData)[position.fPosition+1]=totalBunches;
151       if (fpSimData->GetSize()<dataPos+2) fpSimData->Set(dataPos+2);
152       (*fpSimData)[dataPos++]=totalBunches;
153       position.fEnd=dataPos;
154       (*fpSimData)[dataPos++]=channelAddress;
155       lastChannel=channelAddress;
156       fNof10BitWords=(fNof10BitWords+7)/4; fNof10BitWords*=4; // align to 4 and add 4
157       fChannelPositions.push_back(position);
158       assert((*fpSimData)[position.fPosition]==(*fpSimData)[position.fEnd]);
159       HLTDebug("       channel %d added: address %d, %d bunch(es)", channel, channelAddress, totalBunches);
160     } else {
161       dataPos-=2;
162       HLTDebug("       channel %d skipped: address %d, %d bunch(es)", channel, channelAddress, totalBunches);
163     }
164   }
165
166   assert(fNof10BitWords%4==0);
167   if (iResult<0) {
168     fpSimData->Set(0);
169     return iResult;
170   }
171   fpSimData->Set(dataPos);
172   return GetDataSize();
173 }
174
175 int AliHLTAltroGenerator::GetNof40BitAltroWords() const
176 {
177   // see header file for class documentation
178   assert(fNof10BitWords%4==0);
179   return fNof10BitWords/4;
180 }
181
182 int AliHLTAltroGenerator::GetDataSize()
183 {
184   // see header file for class documentation
185   int iResult=0;
186   iResult=(fNof10BitWords*5)/4;
187   if (fpTrailer) {
188     *(reinterpret_cast<AliHLTUInt32_t*>(fpTrailer))=GetNof40BitAltroWords();
189     iResult+=fTrailerSize;
190   }
191   if (fpCDH) iResult+=fCDHSize;
192   return iResult;
193 }
194
195 int AliHLTAltroGenerator::GetData(AliHLTUInt8_t* &pBuffer)
196 {
197   // see header file for class documentation
198   int iResult=GetDataSize();
199   if (iResult>0) {
200     if (!fpData) fpData=new TArrayC(iResult);
201     if (fpData) {
202       if (fpData->GetSize()<iResult) fpData->Set(iResult);
203       if ((iResult=GetData(reinterpret_cast<AliHLTUInt8_t*>(fpData->GetArray()), fpData->GetSize()))>=0) {
204         pBuffer=reinterpret_cast<AliHLTUInt8_t*>(fpData->GetArray());
205       }
206     } else {
207       iResult=-ENOMEM;
208     }
209   }
210   return iResult;
211 }
212
213 int AliHLTAltroGenerator::GetData(AliHLTUInt8_t* pBuffer, int size)
214 {
215   // see header file for class documentation
216   int iResult=0;
217   int dataPos=0;
218
219   if (size<GetDataSize()) return -ENOSPC;
220
221   // copy Common Data Header
222   if (fpCDH) {
223     fpCDH->fSize=GetDataSize();
224     memcpy(pBuffer+dataPos, fpCDH, fCDHSize);
225     dataPos+=fCDHSize;
226   }
227
228   // encode simulated data
229   if ((iResult=EncodeData(pBuffer+dataPos, size-dataPos))>=0) {
230     dataPos+=iResult;
231   }
232
233   // copy trailer
234   if (fpTrailer) {
235     memcpy(pBuffer+dataPos, fpTrailer, fTrailerSize);
236     AliHLTUInt32_t* pLast=reinterpret_cast<AliHLTUInt32_t*>(fpTrailer+fTrailerSize-sizeof(AliHLTUInt32_t));
237     *pLast=GetNof40BitAltroWords();
238     dataPos+=fTrailerSize;
239   }
240
241   if (iResult<0) return iResult;
242   assert(fpCDH==NULL || (int)fpCDH->fSize==dataPos);
243   return dataPos;
244 }
245
246 int AliHLTAltroGenerator::SetCDH(AliRawDataHeader* pCDH, int size)
247 {
248   // see header file for class documentation
249   int iResult=0;
250   if (pCDH && size>0) {
251     if (fpCDH) delete[] fpCDH;
252     fpCDH=new AliRawDataHeader;
253     if (fpCDH) {
254       memcpy(fpCDH, pCDH, size);
255       fCDHSize=size;
256     } else {
257       iResult=-ENOMEM;
258     }
259   } else {
260     iResult=-EINVAL;
261   }
262   return iResult;
263 }
264
265 int AliHLTAltroGenerator::SetRCUTrailer(AliHLTUInt8_t* pTrailer, int size)
266 {
267   // see header file for class documentation
268   int iResult=0;
269   if (pTrailer && size>=(int)sizeof(AliHLTUInt32_t)) {
270     AliHLTUInt32_t* pLast=reinterpret_cast<AliHLTUInt32_t*>(pTrailer+size-sizeof(AliHLTUInt32_t));
271     if (size!=sizeof(AliHLTUInt32_t)) {
272       // if more than one trailer words, the last one is the trailer length (# 32bit words)
273       if (*pLast!=size/sizeof(AliHLTUInt32_t)) {
274         HLTError("invalid trailer: trailer length (last 32bit word) does not match trailer size (bytes)");
275         return -EBADF;
276       }
277     }
278     if (fpTrailer) delete[] fpTrailer;
279     fpTrailer=new AliHLTUInt8_t[size];
280     if (fpTrailer) {
281       memcpy(fpTrailer, pTrailer, size);
282       fTrailerSize=size;
283     } else {
284       iResult=-ENOMEM;
285     }
286   } else {
287     iResult=-EINVAL;
288   }
289   return iResult;
290 }
291
292 int AliHLTAltroGenerator::GetChannels(vector<AliHLTUInt16_t> list)
293 {
294   // see header file for class documentation
295   int iResult=0;
296   list.clear();
297   for (vector<AliChannelPosition>::iterator element=fChannelPositions.begin();
298        element!=fChannelPositions.end();
299        element++) {
300     list.push_back(element->fChannel);
301   }
302   iResult=list.size();
303   return iResult;
304 }
305
306 int AliHLTAltroGenerator::SetSorting(AliHLTUInt16_t */*array*/, int /*arraySize*/)
307 {
308   // see header file for class documentation
309   int iResult=0;
310   HLTError("function not yet implemented");
311   return iResult;
312 }
313
314 int AliHLTAltroGenerator::EncodeData(AliHLTUInt8_t* pBuffer, int size)
315 {
316   // see header file for class documentation
317   int iResult=0;
318   if (!pBuffer) return -EINVAL;
319
320   AliHLTAltroEncoder encoder;
321   encoder.SetBuffer(pBuffer, size);
322
323   Short_t channelAddress=-1;
324   for (vector<AliChannelPosition>::iterator element=fChannelPositions.begin();
325        element!=fChannelPositions.end() && iResult>=0;
326        element++) {
327     if (!fpSimData ||
328         fpSimData->GetSize()<=element->fPosition ||
329         fNof10BitWords==0) {
330       iResult=-ENODATA;
331       break;
332     }
333     channelAddress=element->fChannel;
334     assert(fpSimData->At(element->fPosition)==channelAddress);
335     if (fpSimData->At(element->fPosition)!=channelAddress) {
336       iResult=-ENODATA;
337       break;
338     }
339     int dataPos=element->fPosition+1;
340     int nofBunches=fpSimData->At(dataPos++);
341     int bunch=0;
342     for (; bunch<nofBunches; bunch++) {
343       int bunchLength=fpSimData->At(dataPos++);
344       int startTime=fpSimData->At(dataPos++);
345       int time=startTime;
346       for (; time<startTime+bunchLength; time++) {
347         iResult=encoder.AddSignal(fpSimData->At(dataPos++), time);
348       }
349       assert(time-1==fpSimData->At(dataPos));
350       dataPos++; // DO NOT PUT INTO ASSERT
351       assert(bunchLength==fpSimData->At(dataPos));
352       dataPos++; // DO NOT PUT INTO ASSERT
353     }
354
355     if (iResult>=0 && channelAddress>=0) {
356       assert(nofBunches==fpSimData->At(dataPos));
357       dataPos++; // DO NOT PUT INTO ASSERT
358       assert(channelAddress==fpSimData->At(dataPos));
359       dataPos++; // DO NOT PUT INTO ASSERT
360     }
361     encoder.SetChannel(channelAddress);
362   }
363
364   if (iResult>=0) {
365     iResult=(encoder.GetTotal40bitWords()*5)/4;
366   }
367
368   return iResult;
369 }
370
371 int AliHLTAltroGenerator::GetRandom(int min, int max)
372 {
373   // see header file for class documentation
374   if (max-min<2) return min;
375   bool setTheSeed=fpRand!=NULL;
376   if (fpRand==NULL) {
377     fpRand=new TRandom;
378   }
379   if (fpRand==NULL) return min;
380   if (!setTheSeed) {
381     TDatime dt;
382     fpRand->SetSeed(dt.Get());
383   }
384   return fpRand->Integer(max-min);
385 }
386
387 int AliHLTAltroGenerator::Reset()
388 {
389   // see header file for class documentation
390   fChannelPositions.clear();
391   fNof10BitWords=0;
392   Rewind();
393   return 0;
394 }
395
396 int AliHLTAltroGenerator::Rewind()
397 {
398   // see header file for class documentation
399   fCurrentPosition=-1;
400   fCurrentBunch=-1;
401   fCurrentTimeOffset=-1;
402   return 0;
403 }
404
405 bool AliHLTAltroGenerator::Next()
406 {
407   // see header file for class documentation
408   bool haveData=false;
409   if (!fpSimData) return false;
410   do {
411     if (haveData=(fCurrentTimeOffset>=0 &&
412                   fCurrentBunch>0 &&
413                   ++fCurrentTimeOffset<GetBunchSize())) {
414       break;
415     }
416
417     if (haveData=(NextBunch() && GetBunchSize()>0)) {
418       fCurrentTimeOffset=0;
419       break;
420     }
421   } while (NextChannel());
422   return haveData;
423 }
424
425 AliHLTUInt16_t AliHLTAltroGenerator::GetSignal()
426 {
427   // see header file for class documentation
428   if (!fpSimData || fCurrentTimeOffset<0) return 0;
429   assert(fCurrentPosition>=0 && fCurrentPosition<(int)fChannelPositions.size());
430   assert(fCurrentBunch>=0);
431   if (fDirection==kForwards) {
432     return fpSimData->At(fCurrentBunch+2+fCurrentTimeOffset);
433   } else if (fDirection==kBackwards){
434     return fpSimData->At(fCurrentBunch-(2+fCurrentTimeOffset));
435   }
436   return 0;
437 }
438
439 bool AliHLTAltroGenerator::NextChannel()
440 {
441   // see header file for class documentation
442   bool haveData=false;
443   if (fpSimData && fChannelPositions.size()==0) return false;
444   fpSimData->GetArray();
445   if (fCurrentPosition==-1) {
446     if (fDirection==kForwards) fCurrentPosition=0;
447     else fCurrentPosition=fChannelPositions.size()-1;
448     haveData=true;
449   } else {
450     if (fDirection==kForwards && (haveData=(fCurrentPosition+1<(int)fChannelPositions.size()))) {
451       fCurrentPosition++;
452     } else if (fDirection==kBackwards && (haveData=(fCurrentPosition>0))) {
453       fCurrentPosition--;
454     }
455   }
456   
457   fCurrentBunch=-1;
458   fCurrentTimeOffset=-1;
459   return haveData;
460 }
461
462 AliHLTUInt16_t AliHLTAltroGenerator::GetHwAddress()
463 {
464   // see header file for class documentation
465   if (fCurrentPosition>=0 && fCurrentPosition<(int)fChannelPositions.size())
466     return fChannelPositions[fCurrentPosition].fChannel;
467   return ~((AliHLTUInt16_t)0);
468 }
469
470 int AliHLTAltroGenerator::GetBunchCount()
471 {
472   // see header file for class documentation
473   if (fpSimData && fCurrentPosition>=0 && fCurrentPosition<(int)fChannelPositions.size()) {
474     if (fDirection==kForwards)
475       return fpSimData->At(fChannelPositions[fCurrentPosition].fPosition+1);
476     else if (fDirection==kBackwards)
477       return fpSimData->At(fChannelPositions[fCurrentPosition].fEnd-1);
478   }
479   return ~((AliHLTUInt16_t)0);
480 }
481
482 bool AliHLTAltroGenerator::NextBunch()
483 {
484   // see header file for class documentation
485   bool haveData=false;
486   if (fpSimData && fCurrentPosition>=0 && fCurrentPosition<(int)fChannelPositions.size()) {
487     if (fDirection==kBackwards) {
488       if (fCurrentBunch<0) {
489         // bunch count in channel end - 1
490         if (haveData=(fpSimData->At(fChannelPositions[fCurrentPosition].fEnd-1))>0) {
491           // first bunch length at channel end - 2
492           fCurrentBunch=fChannelPositions[fCurrentPosition].fEnd-2;
493         }
494       } else if (fCurrentBunch>fChannelPositions[fCurrentPosition].fPosition+1) {
495         fCurrentBunch-=fpSimData->At(fCurrentBunch)+4;
496         haveData=fCurrentBunch>fChannelPositions[fCurrentPosition].fPosition+1;
497       }
498       // cross check
499       if (haveData) {
500         assert(fpSimData->At(fCurrentBunch)==fpSimData->At(fCurrentBunch-fpSimData->At(fCurrentBunch)-3));
501         haveData=fpSimData->At(fCurrentBunch)==fpSimData->At(fCurrentBunch-fpSimData->At(fCurrentBunch)-3);
502       }
503     } else if (fDirection==kForwards) {
504       if (fCurrentBunch<0) {
505         // bunch count in channel start + 1
506         if (haveData=(fpSimData->At(fChannelPositions[fCurrentPosition].fPosition+1))>0) {
507           // first bunch length at channel start + 2
508           fCurrentBunch=fChannelPositions[fCurrentPosition].fPosition+2;
509         }
510       } else if (fCurrentBunch<fChannelPositions[fCurrentPosition].fEnd-1) {
511         fCurrentBunch+=fpSimData->At(fCurrentBunch)+4;
512         haveData=fCurrentBunch<fChannelPositions[fCurrentPosition].fEnd-1;
513       }
514       // cross check
515       if (haveData) {
516         assert(fpSimData->At(fCurrentBunch)==fpSimData->At(fCurrentBunch+fpSimData->At(fCurrentBunch)+3));
517         haveData=fpSimData->At(fCurrentBunch)==fpSimData->At(fCurrentBunch+fpSimData->At(fCurrentBunch)+3);
518       }
519     }
520   }
521   fCurrentTimeOffset=-1;
522   return haveData;
523 }
524
525 AliHLTUInt16_t AliHLTAltroGenerator::GetBunchSize()
526 {
527   // see header file for class documentation
528   if (fCurrentBunch<0) return 0;
529   if (fCurrentBunch<fChannelPositions[fCurrentPosition].fPosition+2) return 0;
530   if (fCurrentBunch>fChannelPositions[fCurrentPosition].fEnd-2) return 0;
531   return fpSimData->At(fCurrentBunch);
532 }
533
534 AliHLTUInt16_t AliHLTAltroGenerator::GetStartTime()
535 {
536   // see header file for class documentation
537   if (!fpSimData || GetBunchSize()==0) return 0;
538   AliHLTUInt16_t startTime=0;
539   if (fDirection==kForwards) {
540     startTime=fpSimData->At(fCurrentBunch+1);
541   } else if (fDirection==kBackwards) {
542     startTime=fpSimData->At(fCurrentBunch-fpSimData->At(fCurrentBunch)-2);
543   }
544   if (fCurrentTimeOffset>=0) {
545     if (fDirection==kForwards) {
546       startTime+=fCurrentTimeOffset;
547     } else if (fDirection==kBackwards) {
548       startTime=GetEndTime();
549     }
550   }
551   return startTime;
552 }
553
554 AliHLTUInt16_t AliHLTAltroGenerator::GetEndTime()
555 {
556   // see header file for class documentation
557   if (!fpSimData || GetBunchSize()==0) return 0;
558   AliHLTUInt16_t endTime=0;
559   if (fDirection==kForwards) {
560     endTime=fpSimData->At(fCurrentBunch+fpSimData->At(fCurrentBunch)+2);
561   } else if (fDirection==kBackwards) {
562     endTime=fpSimData->At(fCurrentBunch-1);
563   }
564   if (fCurrentTimeOffset>=0) {
565     assert(fCurrentTimeOffset<fpSimData->At(fCurrentBunch));
566     if (fDirection==kForwards) {
567       endTime=GetStartTime();
568     } else if (fDirection==kBackwards) {
569       endTime-=fCurrentTimeOffset;
570     }
571   }
572   return endTime;
573 }
574
575 const Short_t* AliHLTAltroGenerator::GetSignals()
576 {
577   // see header file for class documentation
578   if (!fpSimData || GetBunchSize()==0) return NULL;
579   if (fDirection==kForwards) {
580     return fpSimData->GetArray()+fCurrentBunch+2;
581   } else if (fDirection==kBackwards) {
582     return fpSimData->GetArray()+(fCurrentBunch-fpSimData->At(fCurrentBunch)-1);
583   }
584   return NULL;
585 }
586
587 void AliHLTAltroGenerator::Print()
588 {
589   // see header file for class documentation
590   cout << *this << endl;
591 }
592
593 ostream &operator<<(ostream &stream, AliHLTAltroGenerator &generator)
594 {
595   // see header file for class documentation
596   int iResult=0;
597   Short_t channelAddress=-1;
598   for (vector<AliHLTAltroGenerator::AliChannelPosition>::iterator element=generator.fChannelPositions.begin();
599        element!=generator.fChannelPositions.end() && iResult>=0;
600        element++) {
601     if (!generator.fpSimData ||
602         generator.fpSimData->GetSize()<=element->fPosition ||
603         generator.fNof10BitWords==0) {
604       stream << "AliHLTAltroGenerator: no data available" << endl;;
605       break;
606     }
607     channelAddress=element->fChannel;
608     assert(generator.fpSimData->At(element->fPosition)==channelAddress);
609     if (generator.fpSimData->At(element->fPosition)!=channelAddress) {
610       stream << "AliHLTAltroGenerator: internal data mismatch" << endl;;
611       iResult=-ENODATA;
612       break;
613     }
614     int dataPos=element->fPosition+1;
615     int nofBunches=generator.fpSimData->At(dataPos++);
616     stream << "***************************************************************" << endl;
617     stream << "channel address: " << channelAddress << "    " << nofBunches << " bunch(es)" << endl;
618     int bunch=0;
619     for (; bunch<nofBunches; bunch++) {
620       int bunchLength=generator.fpSimData->At(dataPos++);
621       int startTime=generator.fpSimData->At(dataPos++);
622       int time=startTime;
623       stream << "   length " << bunchLength << " start time " << startTime << ":     ";
624       for (; time<startTime+bunchLength; time++) {
625         stream << " " << generator.fpSimData->At(dataPos++);
626       }
627       assert(time-1==generator.fpSimData->At(dataPos));
628       dataPos++; // DO NOT PUT INTO ASSERT
629       assert(bunchLength==generator.fpSimData->At(dataPos));
630       dataPos++; // DO NOT PUT INTO ASSERT
631       stream << "      -> end time " << time-1 << endl;
632     }
633
634     if (iResult>=0 && channelAddress>=0) {
635       assert(nofBunches==generator.fpSimData->At(dataPos));
636       dataPos++; // DO NOT PUT INTO ASSERT
637       assert(channelAddress==generator.fpSimData->At(dataPos));
638       dataPos++; // DO NOT PUT INTO ASSERT
639     }
640   }
641
642   return stream;
643 }