source: trunk/MagicSoft/Mars/mcorsika/MCorsikaFormat.cc@ 9620

Last change on this file since 9620 was 9616, checked in by rohlfs, 14 years ago
can read also EventIO files
File size: 11.6 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 (/*memcmp(blockHeader+5, id, 4) == 0 && */
236 type == fileType )
237 {
238//*fLog << all << "found " << id << " type: " << type << endl;
239 break;
240 }
241
242 if (type == 1202 && fileType == 1210)
243 // we are looking for a event header, but found a runEnd.
244 // This will happen at the end of a run. We stop here looking for
245 // the next event header
246 return kFALSE;
247
248 // a unknown block, we jump to the next one
249//*fLog << "unknown: " << id << " type: " << fileType << " sub-blocks: " << (blockHeader[3]>>29);
250//*fLog << " length: " << (blockHeader[3] & 0x3fffffff) << endl;
251 int length = blockHeader[3] & 0x3fffffff;
252 fIn->seekg(length - 2 * sizeof(int), ios::cur);
253 }
254
255
256 return kTRUE;
257}
258
259// --------------------------------------------------------------------------
260//
261void MCorsikaFormatEventIO::UnreadLastHeader()
262{
263 fIn->seekg( (int)(-6 * sizeof(int)), ios::cur);
264}
265
266// --------------------------------------------------------------------------
267//
268Bool_t MCorsikaFormatEventIO::SeekEvtEnd()
269{
270 if (SeekNextBlock("RUNE", 1210))
271 {
272 UnreadLastHeader();
273 return kTRUE;
274 }
275
276 return kFALSE;
277}
278
279// --------------------------------------------------------------------------
280//
281// Returns one event (7 Float values) after the other until the EventEnd
282// block is found.
283// If a read error occurred, the readError is set to kTRUE and the function
284// returns kFALSE;
285Bool_t MCorsikaFormatEventIO::GetNextEvent(Float_t ** buffer,
286 Bool_t & readError)
287{
288
289 static Float_t * data = NULL;
290 static Float_t * next;
291 static Int_t topLevelLength = 0;
292 static Int_t eventLength = 0;
293
294
295 while (eventLength == 0)
296 {
297 delete [] data;
298 data = NULL;
299
300 if (topLevelLength == 0)
301 {
302 if (!NextTopLevelBlock(topLevelLength, readError))
303 return kFALSE;
304 }
305
306 if (!NextEventBlock(eventLength, readError))
307 return kFALSE;
308 topLevelLength -= eventLength + 3 * sizeof(int);
309
310 // read next block of events
311 data = new Float_t [eventLength / sizeof(Float_t)];
312 if (!ReadData(eventLength / sizeof(Float_t), data, 0))
313 {
314 delete [] data;
315 data = NULL;
316 readError = kTRUE;
317 return kFALSE;
318 }
319 next = data + 3;
320 eventLength -= 3 * sizeof(Float_t);
321 }
322
323 eventLength -= 8 * sizeof(Float_t);
324 *buffer = next;
325 next += 8;
326
327
328 return kTRUE;
329}
330
331// --------------------------------------------------------------------------
332//
333// Looks for the next Block with type 1204 and return kTRUE.
334// The function also stops moving forward in the file, if it finds a
335// EventEnd block (1209). In this case kFALSE is returned
336Bool_t MCorsikaFormatEventIO::NextTopLevelBlock(Int_t & length,
337 Bool_t & readError)
338{
339 Int_t blockHeader[4];
340
341 while (1)
342 {
343 // we read - synchronisation marker
344 // - type / version field
345 // - identification field
346 // - length
347 fIn->read((char*)blockHeader, 4 * sizeof(Int_t));
348
349 if (fIn->eof())
350 {
351 *fLog << err << "ERROR - Missing identifier: 1204 or 1209" << endl;
352 readError = kTRUE;
353 return kFALSE;
354 }
355
356 length = blockHeader[3] & 0x3fffffff;
357 unsigned short fileType = blockHeader[1] & 0xFFFF;
358 if (fileType == 1204)
359{
360*fLog << all << "found new top level block 1204" << endl;
361 return kTRUE;
362}
363 if (fileType == 1209)
364 {
365 // we found an eventEnd block, reset file pointer
366 fIn->seekg( (Int_t)(-4 * sizeof(Int_t)), ios::cur);
367 length = 0;
368 return kFALSE;
369 }
370
371
372 // a unknown block, we jump to the next one
373*fLog << all << "found block " << fileType << endl;
374 fIn->seekg(length, ios::cur);
375 }
376
377 return kTRUE;
378}
379
380Bool_t MCorsikaFormatEventIO::NextEventBlock(Int_t & length,
381 Bool_t & readError)
382{
383 Int_t blockHeader[3];
384
385 // we read - synchronisation marker
386 // - type / version field
387 // - identification field
388 // - length
389 fIn->read((char*)blockHeader, 3 * sizeof(Int_t));
390
391 if (fIn->eof())
392 {
393 *fLog << err << "ERROR - Missing identifier: 1205" << endl;
394 readError = kTRUE;
395 return kFALSE;
396 }
397
398 unsigned short fileType = blockHeader[0] & 0xFFFF;
399 if (fileType != 1205)
400 {
401 *fLog << err << "ERROR - Unexpected type: " << fileType << "expected 1205" << endl;
402 readError = kTRUE;
403 return kFALSE;
404 }
405
406 unsigned short version = (blockHeader[0] >> 20) & 0x0FFF;
407 if (version != 0)
408 {
409 *fLog << err << "ERROR - Unexpected version: " << version << "expected: 0" << endl;
410 readError = kTRUE;
411 return kFALSE;
412 }
413
414 length = blockHeader[2] & 0x3fffffff;
415
416 return kTRUE;
417
418}
419
420
Note: See TracBrowser for help on using the repository browser.