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

Last change on this file since 9937 was 9893, checked in by rohlfs, 14 years ago
bug fix in comparing the fRunePos with position 0
File size: 12.4 KB
Line 
1#include <fstream>
2#include <errno.h>
3
4
5#include "MLogManip.h"
6
7#include "MCorsikaFormat.h"
8
9
10using namespace std;
11
12MCorsikaFormat * CorsikaFormatFactory(MLog * log, const char * fileName)
13{
14 ifstream * fileIn = new ifstream(fileName);
15
16 const Bool_t noexist = !(*fileIn);
17 if (noexist)
18 {
19 *log << err << "Cannot open file " << fileName << ": ";
20 *log << (errno!=0?strerror(errno):"Insufficient memory for decompression") << endl;
21 delete fileIn;
22 fileIn = NULL;
23 return NULL;
24 }
25
26
27 if (!fileIn->is_open())
28 {
29 *log << err << "Failed to open file " << fileName << endl;
30 delete fileIn;
31 fileIn = NULL;
32 return NULL;
33 }
34
35 char buffer[4];
36 fileIn->read(buffer, 4);
37 fileIn->seekg(-4, ios::cur);
38
39 int * syncmarker = reinterpret_cast<int*>(buffer);
40 if (memcmp(buffer, "RUNH", 4) == 0)
41 return new MCorsikaFormatRaw(log, fileIn);
42
43 else if (*syncmarker == -736130505)
44 return new MCorsikaFormatEventIO(log, fileIn);
45
46 *log << err << "File " << fileName <<
47 " is neither a corsica file, nor an eventio file" << endl;
48 delete fileIn;
49 fileIn = NULL;
50
51 return NULL;
52}
53
54///////////////////////////////////////////////////////////////////////////////
55///////////////////////////////////////////////////////////////////////////////
56
57Bool_t MCorsikaFormat::ReadData(Int_t numValues, Float_t * buffer,
58 Int_t minSeekValues)
59{
60 fPrevPos = fIn->tellg();
61
62 fIn->read((char*)buffer, numValues * sizeof(Float_t));
63
64 if (numValues < minSeekValues)
65 // skip the remaining data of this block
66 fIn->seekg( (minSeekValues - numValues) * 4, ios::cur);
67
68 return !fIn->fail();
69
70}
71
72void MCorsikaFormat::UnreadLastData()
73{
74 fIn->seekg(fPrevPos, ios::beg);
75}
76
77void MCorsikaFormat::StorePos()
78{
79 fPos = fIn->tellg();
80//*fLog << all << "storePos: " << fPos << endl;
81}
82
83void MCorsikaFormat::ResetPos()
84{
85 fIn->seekg(fPos, ios::beg);
86}
87
88
89///////////////////////////////////////////////////////////////////////////////
90///////////////////////////////////////////////////////////////////////////////
91
92
93MCorsikaFormat::~MCorsikaFormat()
94{
95 delete fIn;
96}
97
98
99// --------------------------------------------------------------------------
100//
101// Reads the next 4 bytes which should be the id. (for example "RUNH", RUNE".
102// "EVTH")
103// Returns kTRUE if the functions finds the id
104// kFALSE if the functions does not find the "id" as the next 4
105// bytes in the file.
106// After this call the file position pointer points just after the 4 bytes
107// of the id.
108//
109Bool_t MCorsikaFormatRaw::SeekNextBlock(const char * id, unsigned short type)
110{
111 char blockHeader[5];
112 fIn->read(blockHeader, 4);
113
114 if (memcmp(blockHeader, id, 4))
115 {
116 blockHeader[4] = 0;
117 if (strcmp(id, "EVTH") != 0 || strcmp(blockHeader, "RUNE") != 0 )
118 {
119 // at the end of a file we are looking for the next Event header,
120 // but find the end of a run. This is expected, therefor no error
121 // message.
122 *fLog << err << "ERROR - Wrong identifier: " << id << " expected."
123 << " But read " << blockHeader << " from file." << endl;
124 }
125 return kFALSE;
126 }
127
128 return kTRUE;
129}
130
131// --------------------------------------------------------------------------
132//
133void MCorsikaFormatRaw::UnreadLastHeader()
134{
135 fIn->seekg(-4, ios::cur);
136}
137
138Bool_t MCorsikaFormatRaw::SeekEvtEnd()
139{
140
141 // Search subblockwise backward (Block: 5733*4 = 21*273*4)
142 for (int i=1; i<22; i++)
143 {
144 fIn->seekg(-i*273*4, ios::end);
145
146 char runh[4];
147 fIn->read(runh, 4);
148
149 if (!memcmp(runh, "RUNE", 4))
150 {
151 fIn->seekg(-4, ios::cur);
152 return kTRUE;
153 }
154 }
155
156 return kTRUE;
157}
158
159
160// --------------------------------------------------------------------------
161//
162// Returns one event (7 Float values) after the other until the EventEnd
163// block is found.
164// If a read error occurred, the readError is set to kTRUE and the function
165// returns kFALSE;
166Bool_t MCorsikaFormatRaw::GetNextEvent(Float_t ** buffer, Bool_t & readError)
167{
168 static Float_t data[273];
169 static Float_t * next = data + 273;
170
171 if (next == data + 273)
172 {
173 // read next block of events
174 if (!ReadData(273, data))
175 {
176 readError = kTRUE;
177 return kFALSE;
178 }
179
180 if (!memcmp(data, "EVTE", 4))
181 {
182 // we found the end of list of events
183 UnreadLastData();
184 return kFALSE;
185 }
186
187 next = data;
188 }
189
190 *buffer = next;
191 next += 7;
192
193 return kTRUE;
194
195}
196
197
198///////////////////////////////////////////////////////////////////////////////
199///////////////////////////////////////////////////////////////////////////////
200
201// --------------------------------------------------------------------------
202//
203// Jumps from one top level object to the next until if finds the object with
204// correct type and correct id. The id is identifier of the raw corsika block,
205// for example "RUNH", RUNE", "EVTH"
206//
207// Returns kTRUE if the functions finds the type / id
208// kFALSE if the functions does not find the type / id.
209//
210// After this call the file position pointer points just after the 4 bytes
211// of the id.
212//
213Bool_t MCorsikaFormatEventIO::SeekNextBlock(const char * id, unsigned short type)
214{
215 int blockHeader[7];
216
217 while (1)
218 {
219 // we read - synchronisation marker
220 // - type / version field
221 // - identification field
222 // - length
223 // - unknown field
224 // - id (first 4 bytes of data field)
225 fIn->read((char*)blockHeader, 6 * sizeof(int));
226
227 if (fIn->eof())
228 {
229 *fLog << err << "ERROR - Missing identifier: " << id <<
230 " type: " << type << endl;
231 return kFALSE;
232 }
233
234 unsigned short fileType = blockHeader[1] & 0xFFFF;
235 if (type == fileType )
236 break;
237
238 if (type == 1202 && fileType == 1210)
239 // we are looking for a event header, but found a runEnd.
240 // This will happen at the end of a run. We stop here looking for
241 // the next event header
242 return kFALSE;
243
244 // a unknown block, we jump to the next one
245//*fLog << "unknown: " << id << " type: " << fileType << " sub-blocks: " << (blockHeader[3]>>29);
246//*fLog << " length: " << (blockHeader[3] & 0x3fffffff) << " pos: " << fIn->tellg() << endl;
247 int length = blockHeader[3] & 0x3fffffff;
248
249 fIn->seekg(length - 2 * (Int_t)(sizeof(int)), ios::cur);
250 }
251
252
253 return kTRUE;
254}
255
256// --------------------------------------------------------------------------
257//
258void MCorsikaFormatEventIO::UnreadLastHeader()
259{
260 fIn->seekg( -6 * (Int_t)(sizeof(int)), ios::cur);
261}
262
263// --------------------------------------------------------------------------
264//
265Bool_t MCorsikaFormatEventIO::SeekEvtEnd()
266{
267 if (fRunePos != streampos(0))
268 {
269 fIn->seekg(fRunePos, ios::beg);
270 return kTRUE;
271 }
272 else
273 {
274 // it is the first time we are looking for the RUNE block
275
276 // is the RUNE block at the very end of the file?
277 std::streampos currentPos = fIn->tellg();
278
279 fIn->seekg(-32, ios::end);
280 unsigned int blockHeader[4];
281 fIn->read((char*)blockHeader, 4 * sizeof(int));
282 if ( blockHeader[0] == 0xd41f8a37 &&
283 (blockHeader[1] & 0xffff) == 1210 &&
284 (blockHeader[3] & 0x3fffffff) == 16)
285 {
286 // this seams to be a RUNE (1210) block
287 fIn->seekg( -4 * (Int_t)(sizeof(int)), ios::cur);
288 fRunePos = fIn->tellg();
289 return kTRUE;
290 }
291
292 // we do not find a RUNE block at the end of the file
293 // we have to search in the file
294 fIn->seekg(currentPos, ios::beg);
295 if (SeekNextBlock("RUNE", 1210))
296 {
297 UnreadLastHeader();
298 fRunePos = fIn->tellg();
299 return kTRUE;
300 }
301 }
302 return kFALSE;
303}
304
305// --------------------------------------------------------------------------
306//
307// Returns one event (7 Float values) after the other until the EventEnd
308// block is found.
309// If a read error occurred, the readError is set to kTRUE and the function
310// returns kFALSE;
311Bool_t MCorsikaFormatEventIO::GetNextEvent(Float_t ** buffer,
312 Bool_t & readError)
313{
314
315 static Float_t * data = NULL;
316 static Float_t * next;
317 static Int_t topLevelLength = 0;
318 static Int_t eventLength = 0;
319
320
321 while (eventLength == 0)
322 {
323 delete [] data;
324 data = NULL;
325
326 if (topLevelLength == 0)
327 {
328 if (!NextTopLevelBlock(topLevelLength, readError))
329 return kFALSE;
330 }
331
332 if (!NextEventBlock(eventLength, readError))
333 return kFALSE;
334 topLevelLength -= eventLength + 3 * sizeof(int);
335
336 // read next block of events
337 data = new Float_t [eventLength / sizeof(Float_t)];
338 if (!ReadData(eventLength / sizeof(Float_t), data, 0))
339 {
340 delete [] data;
341 data = NULL;
342 readError = kTRUE;
343 return kFALSE;
344 }
345 next = data + 3;
346 eventLength -= 3 * sizeof(Float_t);
347 }
348
349 eventLength -= 8 * sizeof(Float_t);
350 *buffer = next;
351 next += 8;
352
353
354 return kTRUE;
355}
356// --------------------------------------------------------------------------
357//
358// Looks for the next Block with type 1204 and return kTRUE.
359// The function also stops moving forward in the file, if it finds a
360// EventEnd block (1209). In this case kFALSE is returned
361Bool_t MCorsikaFormatEventIO::NextTopLevelBlock(Int_t & length,
362 Bool_t & readError)
363{
364 Int_t blockHeader[4];
365
366 while (1)
367 {
368 // we read - synchronisation marker
369 // - type / version field
370 // - identification field
371 // - length
372 fIn->read((char*)blockHeader, 4 * sizeof(Int_t));
373
374 if (fIn->eof())
375 {
376 *fLog << err << "ERROR - Missing identifier: 1204 or 1209" << endl;
377 readError = kTRUE;
378 return kFALSE;
379 }
380
381 length = blockHeader[3] & 0x3fffffff;
382 unsigned short fileType = blockHeader[1] & 0xFFFF;
383 if (fileType == 1204)
384 return kTRUE;
385
386 if (fileType == 1209)
387 {
388 // we found an eventEnd block, reset file pointer
389 fIn->seekg( -4 * (Int_t)(sizeof(Int_t)), ios::cur);
390 length = 0;
391 return kFALSE;
392 }
393
394
395 // a unknown block, we jump to the next one
396 fIn->seekg(length, ios::cur);
397 }
398
399 return kTRUE;
400}
401
402Bool_t MCorsikaFormatEventIO::NextEventBlock(Int_t & length,
403 Bool_t & readError)
404{
405 Int_t blockHeader[3];
406
407 // we read - synchronisation marker
408 // - type / version field
409 // - identification field
410 // - length
411 fIn->read((char*)blockHeader, 3 * sizeof(Int_t));
412
413 if (fIn->eof())
414 {
415 *fLog << err << "ERROR - Missing identifier: 1205" << endl;
416 readError = kTRUE;
417 return kFALSE;
418 }
419
420 unsigned short fileType = blockHeader[0] & 0xFFFF;
421 if (fileType != 1205)
422 {
423 *fLog << err << "ERROR - Unexpected type: " << fileType << "expected 1205" << endl;
424 readError = kTRUE;
425 return kFALSE;
426 }
427
428 unsigned short version = (blockHeader[0] >> 20) & 0x0FFF;
429 if (version != 0)
430 {
431 *fLog << err << "ERROR - Unexpected version: " << version << "expected: 0" << endl;
432 readError = kTRUE;
433 return kFALSE;
434 }
435
436 length = blockHeader[2] & 0x3fffffff;
437
438 return kTRUE;
439
440}
441
442
Note: See TracBrowser for help on using the repository browser.