source: trunk/Mars/mcorsika/MCorsikaFormat.cc@ 10005

Last change on this file since 10005 was 9949, checked in by tbretz, 14 years ago
Fixed a problem reading the RUNE section in the raw corsika files and accelerated plain readcorsika.
File size: 15.1 KB
Line 
1/* ======================================================================== *\
2!
3! *
4! * This file is part of MARS, the MAGIC Analysis and Reconstruction
5! * Software. It is distributed to you in the hope that it can be a useful
6! * and timesaving tool in analysing Data of imaging Cerenkov telescopes.
7! * It is distributed WITHOUT ANY WARRANTY.
8! *
9! * Permission to use, copy, modify and distribute this software and its
10! * documentation for any purpose is hereby granted without fee,
11! * provided that the above copyright notice appear in all copies and
12! * that both that copyright notice and this permission notice appear
13! * in supporting documentation. It is provided "as is" without express
14! * or implied warranty.
15! *
16!
17!
18! Author(s): Reiner Rohlfs 2010
19! Author(s): Thomas Bretz 2010 <mailto:thomas.bretz@epfl.ch>
20!
21! Copyright: Software Development, 2000-2010
22!
23!
24\* ======================================================================== */
25
26//////////////////////////////////////////////////////////////////////////////
27//
28// MCorsikaFormat
29//
30//////////////////////////////////////////////////////////////////////////////
31#include "MCorsikaFormat.h"
32
33#include <errno.h>
34#include <fstream>
35
36#include "MLogManip.h"
37
38using namespace std;
39
40const unsigned int MCorsikaFormat::kSyncMarker = 0xd41f8a37;
41
42// --------------------------------------------------------------------------
43//
44MCorsikaFormat *MCorsikaFormat::CorsikaFormatFactory(const char * fileName)
45{
46 ifstream * fileIn = new ifstream(fileName);
47
48 const Bool_t noexist = !(*fileIn);
49 if (noexist)
50 {
51 gLog << err << "Cannot open file " << fileName << ": ";
52 gLog << (errno!=0?strerror(errno):"Insufficient memory for decompression") << endl;
53 delete fileIn;
54 return NULL;
55 }
56
57 char buffer[5]="\0\0\0\0";
58 fileIn->read(buffer, 4);
59 fileIn->seekg(-4, ios::cur);
60
61 if (strcmp(buffer, "RUNH") == 0)
62 return new MCorsikaFormatRaw(fileIn);
63
64 if (*reinterpret_cast<unsigned int*>(buffer) == kSyncMarker)
65 return new MCorsikaFormatEventIO(fileIn);
66
67 gLog << err << "File " << fileName <<
68 " is neither a CORSIKA raw nor EventIO file" << endl;
69 delete fileIn;
70
71 return NULL;
72}
73
74void MCorsikaFormat::Read(void *ptr, Int_t i) const
75{
76 fIn->read((char*)ptr, i);
77}
78
79// --------------------------------------------------------------------------
80//
81Bool_t MCorsikaFormat::Eof() const
82{
83 return fIn->eof();
84}
85
86// --------------------------------------------------------------------------
87//
88streampos MCorsikaFormat::GetCurrPos() const
89{
90 return fIn->tellg();
91}
92
93// --------------------------------------------------------------------------
94//
95Bool_t MCorsikaFormat::ReadData(Int_t numValues, Float_t * buffer,
96 Int_t minSeekValues)
97{
98 fPrevPos = fIn->tellg();
99
100 fIn->read((char*)buffer, numValues * sizeof(Float_t));
101
102 if (numValues < minSeekValues)
103 // skip the remaining data of this block
104 fIn->seekg( (minSeekValues - numValues) * 4, ios::cur);
105
106 return !fIn->fail();
107
108}
109
110// --------------------------------------------------------------------------
111//
112void MCorsikaFormat::UnreadLastData() const
113{
114 fIn->seekg(fPrevPos, ios::beg);
115}
116
117// --------------------------------------------------------------------------
118//
119void MCorsikaFormat::StorePos()
120{
121 fPos = fIn->tellg();
122}
123
124// --------------------------------------------------------------------------
125//
126void MCorsikaFormat::ResetPos() const
127{
128 fIn->seekg(fPos, ios::beg);
129}
130
131void MCorsikaFormat::Rewind() const
132{
133 fIn->seekg(0, ios::beg);
134}
135
136// --------------------------------------------------------------------------
137//
138MCorsikaFormat::~MCorsikaFormat()
139{
140 delete fIn;
141}
142
143// --------------------------------------------------------------------------
144//
145// Reads the next 4 bytes which should be the id. (for example "RUNH", RUNE".
146// "EVTH")
147// Returns kTRUE if the functions finds the id
148// kFALSE if the functions does not find the "id" as the next 4
149// bytes in the file.
150// After this call the file position pointer points just after the 4 bytes
151// of the id.
152//
153Int_t MCorsikaFormatRaw::SeekNextBlock(const char * id, unsigned short type) const
154{
155 char blockHeader[5]="\0\0\0\0";
156 fIn->read(blockHeader, 4);
157
158 if (strcmp(blockHeader, id)==0)
159 return kTRUE;
160
161 // at the end of a file we are looking for the next Event header,
162 // but find the end of a run. This is expected, therefor no error
163 // message.
164 if (strcmp(blockHeader, "RUNE")==0)
165 return kFALSE;
166
167 gLog << err << "ERROR - Wrong identifier: " << id << " expected.";
168 gLog << " But read " << blockHeader << " from file." << endl;
169
170 return kERROR;
171}
172
173// --------------------------------------------------------------------------
174//
175void MCorsikaFormatRaw::UnreadLastHeader() const
176{
177 fIn->seekg(-4, ios::cur);
178}
179
180// --------------------------------------------------------------------------
181//
182Bool_t MCorsikaFormatRaw::SeekEvtEnd()
183{
184 // Search subblockwise backward (Block: 5733*4 = 21*273*4)
185 for (int i=1; i<22; i++)
186 {
187 fIn->seekg(-i*273*4, ios::end);
188
189 char runh[5]="\0\0\0\0";
190 fIn->read(runh, 4);
191
192 if (!strcmp(runh, "RUNE"))
193 {
194 fIn->seekg(-4, ios::cur);
195 return kTRUE;
196 }
197 }
198
199 return kTRUE;
200}
201
202// --------------------------------------------------------------------------
203//
204// Returns one event (7 Float values) after the other until the EventEnd
205// block is found.
206// If a read error occurred, the readError is set to kTRUE and the function
207// returns kFALSE;
208//
209Int_t MCorsikaFormatRaw::GetNextEvent(Float_t **buffer, Int_t)
210{
211 static Float_t data[273];
212 static Float_t * next = data + 273;
213
214 if (next == data + 273)
215 {
216 // read next block of events
217 if (!ReadData(273, data))
218 return kERROR;
219
220 if (!memcmp(data, "EVTE", 4))
221 {
222 // we found the end of list of events
223 UnreadLastData();
224 return kFALSE;
225 }
226
227 next = data;
228 }
229
230 *buffer = next;
231 next += 7;
232
233 return kTRUE;
234}
235
236///////////////////////////////////////////////////////////////////////////////
237///////////////////////////////////////////////////////////////////////////////
238
239// --------------------------------------------------------------------------
240//
241// Jumps from one top level object to the next until if finds the object with
242// correct type and correct id. The id is identifier of the raw corsika block,
243// for example "RUNH", RUNE", "EVTH"
244//
245// Returns kTRUE if the functions finds the type / id
246// kFALSE if the functions does not find the type / id.
247//
248// After this call the file position pointer points just after the 4 bytes
249// of the id.
250//
251Int_t MCorsikaFormatEventIO::SeekNextBlock(const char * id, unsigned short type) const
252{
253 cout << "Seek " << type << endl;
254 while (1)
255 {
256 // we read - synchronisation marker
257 // - type / version field
258 // - identification field
259 // - length
260 // - unknown field
261 // - id (first 4 bytes of data field)
262 int blockHeader[4];
263 fIn->read((char*)blockHeader, 4 * sizeof(int));
264
265 if (fIn->eof())
266 {
267 gLog << err << "MCorsikaFormatEventIO::SeekNextBlock: ERROR - Unexpected end-of-file seeking " << id << " (" << type << ")." << endl;
268 return kERROR;
269 }
270
271 const unsigned short objType = blockHeader[1] & 0xFFFF;
272 cout << "objType=" << objType << endl;
273 if (type == objType)
274 {
275 if (!id)
276 break;
277
278 char c[9];
279 fIn->read(c, 8);
280
281 if (memcmp(c+4, id, 4)==0)
282 break;
283
284 c[8] = 0;
285 gLog << err << "MCorsikaFormatEventIO::SeekNextBlock: ERROR - '" << c+4 << "' doesn't match expected one '" << id << "' in object " << type << endl;
286 return kFALSE;
287 }
288
289 // we are looking for a event header, but found a runEnd.
290 // This will happen at the end of a run. We stop here looking for
291 // the next event header
292 if (type == 1202 && objType == 1210)
293 return kFALSE;
294
295 // a unknown block, we jump to the next one
296 const int length = blockHeader[3] & 0x3fffffff;
297 fIn->seekg(length, ios::cur);
298 }
299
300
301 return kTRUE;
302}
303
304// --------------------------------------------------------------------------
305//
306void MCorsikaFormatEventIO::UnreadLastHeader() const
307{
308 fIn->seekg( -6 * (Int_t)(sizeof(int)), ios::cur);
309}
310
311// --------------------------------------------------------------------------
312//
313Bool_t MCorsikaFormatEventIO::SeekEvtEnd()
314{
315 if (fRunePos != streampos(0))
316 {
317 fIn->seekg(fRunePos, ios::beg);
318 return kTRUE;
319 }
320
321 // it is the first time we are looking for the RUNE block
322
323 // is the RUNE block at the very end of the file?
324 const streampos currentPos = fIn->tellg();
325
326 fIn->seekg(-32, ios::end);
327
328 unsigned int blockHeader[4];
329 fIn->read((char*)blockHeader, 4 * sizeof(int));
330
331 if ( blockHeader[0] == kSyncMarker &&
332 (blockHeader[1] & 0xffff) == 1210 &&
333 (blockHeader[3] & 0x3fffffff) == 16)
334 {
335 // this seams to be a RUNE (1210) block
336 fIn->seekg( -4 * (Int_t)(sizeof(int)), ios::cur);
337 fRunePos = fIn->tellg();
338 return kTRUE;
339 }
340
341 // we do not find a RUNE block at the end of the file
342 // we have to search in the file
343 fIn->seekg(currentPos, ios::beg);
344 if (SeekNextBlock("RUNE", 1210)!=kTRUE)
345 return kFALSE;
346
347 UnreadLastHeader();
348 fRunePos = fIn->tellg();
349
350 return kTRUE;
351}
352
353// --------------------------------------------------------------------------
354//
355// Returns one event (7 Float values) after the other until the EventEnd
356// block is found.
357// If a read error occurred, the readError is set to kTRUE and the function
358// returns kFALSE;
359//
360Int_t MCorsikaFormatEventIO::GetNextEvent(Float_t **buffer, Int_t telescope)
361{
362 static Float_t *data = NULL;
363
364 static int lengthPhotonData = 0;
365 static int lengthEvent = 0;
366
367 if (lengthPhotonData>0)
368 {
369 cout << "Return Bunch l2=" << lengthPhotonData << endl;
370
371 lengthPhotonData -= 8 * sizeof(Float_t);
372 *buffer += 8; // Return the pointer to the start of the current photon data
373 return kTRUE;
374 }
375
376 if (data)
377 {
378 delete [] data;
379 data = NULL;
380 cout << "Return end-of-tel LE=" << lengthEvent << endl;
381 return kFALSE;
382 }
383
384 if (lengthEvent==0)
385 {
386 cout << "Searching 1204... " << flush;
387 // The length of the block is stored and we use it to determine
388 // when the next top level block is expected
389 const Int_t rc = NextEventObject(lengthEvent);
390 if (rc==kERROR)
391 return kERROR;
392 if (!rc)
393 {
394 cout << "skip EVTE." << endl;
395 return kFALSE;
396 }
397
398 cout << "found new array." << endl;
399 }
400
401 cout << "Searching 1205..." << flush;
402
403 // Look for the next event photon bunch (object type 1205)
404 const Int_t tel = NextPhotonObject(lengthPhotonData);
405 if (tel<0)
406 return kERROR;
407
408 lengthEvent -= lengthPhotonData+12; // Length of data + Length of header
409
410 lengthPhotonData -= 12; // Length of data before the photon bunches
411 fIn->seekg(12, ios::cur); // Skip this data
412
413 cout << " found (tel=" << tel << ",LEN=" << lengthEvent << ",len=" << lengthPhotonData << ")... " << flush;
414
415 if (lengthPhotonData==0)
416 {
417 cout << "empty!" << endl;
418 return kFALSE;
419 }
420
421 const UInt_t cnt = lengthPhotonData / sizeof(Float_t);
422 // Read next object (photon bunch)
423 data = new Float_t[cnt];
424 if (!ReadData(cnt, data, 0))
425 {
426 delete [] data;
427 data = NULL;
428 return kERROR;
429 }
430
431 cout << "return!" << endl;
432
433 lengthPhotonData -= 8 * sizeof(Float_t);
434 *buffer = data; // Return the pointer to the start of the current photon data
435
436 return kTRUE;
437}
438
439// --------------------------------------------------------------------------
440//
441// Looks for the next Block with type 1204 and return kTRUE.
442// The function also stops moving forward in the file, if it finds a
443// EventEnd block (1209). In this case kFALSE is returned
444//
445Int_t MCorsikaFormatEventIO::NextEventObject(Int_t &length) const
446{
447 while (1)
448 {
449 // we read - synchronisation marker
450 // - type / version field
451 // - identification field
452 // - length
453 UInt_t blockHeader[4];
454 fIn->read((char*)blockHeader, 4 * sizeof(Int_t));
455
456 if (fIn->eof())
457 {
458 gLog << err << "MCorsikaFormatEventIO::NextEventObject: ERROR - Unexpected end-of-file." << endl;
459 return kERROR;
460 }
461
462 // For speed reasons we skip the check of the synchronization marker
463
464 // Decode the object type
465 const unsigned short objType = blockHeader[1] & 0xFFFF;
466
467 cout << "objType=" << objType << endl;
468
469 // Decode length of block
470 length = blockHeader[3] & 0x3fffffff;
471
472 // Check if we found the next array (reuse / impact parameter)
473 // blockHeader[2] == array number (reuse)
474 if (objType==1204)
475 return kTRUE;
476
477 // we found an eventEnd block, reset file pointer
478 if (objType==1209)
479 break;
480
481 // a unknown block, we jump to the next one
482 fIn->seekg(length, ios::cur);
483 }
484
485 fIn->seekg( -4 * (Int_t)(sizeof(Int_t)), ios::cur);
486 length = 0;
487
488 return kFALSE;
489}
490
491// --------------------------------------------------------------------------
492//
493Int_t MCorsikaFormatEventIO::NextPhotonObject(Int_t &length) const
494{
495 UInt_t blockHeader[3];
496
497 // we read - synchronisation marker
498 // - type / version field
499 // - identification field
500 // - length
501 fIn->read((char*)blockHeader, 3 * sizeof(UInt_t));
502
503 if (fIn->eof())
504 {
505 gLog << err << "MCorsikaFormatEventIO::NextPhotonObject: ERROR - Unexpected end-of-file.." << endl;
506 return -1;
507 }
508
509 const unsigned short objType = blockHeader[0] & 0xFFFF;
510 if (objType != 1205)
511 {
512 gLog << err << "MCorsikaFormatEventIO::NextPhotonObject: ERROR - Unexpected EventIO object type " << objType << " (expected 1205)." << endl;
513 return -1;
514 }
515
516 const unsigned short version = (blockHeader[0] >> 20) & 0x0FFF;
517 if (version != 0)
518 {
519 gLog << err << "MCorsikaFormatEventIO::NextPhotonObject: ERROR - Unexpected EventIO object version " << version << " (expected 0 for object type 1205)." << endl;
520 return -1;
521 }
522
523 length = blockHeader[2] & 0x3fffffff;
524
525 // blockHeader[1] == 1000 x array number (reuse) + telescope number
526 return blockHeader[1] % 1000;
527}
Note: See TracBrowser for help on using the repository browser.