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

Last change on this file since 19853 was 19342, checked in by tbretz, 6 years ago
Added a comment
File size: 8.2 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
38
39using namespace std;
40
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 uint32_t magic = 0;
58 fileIn->read((char*)&magic, 4);
59
60 uint32_t blocklength = 0;
61
62 // This seems to be a new corsika binary identifier
63 if (magic==kBlockLengthRaw || magic==kBlockLengthThin)
64 {
65 blocklength = magic;
66 fileIn->read((char*)&magic, 4);
67 }
68
69 // Jump back that the "RUNH" is can be read again
70 fileIn->seekg(-4, ios::cur);
71
72 if (magic==kRUNH)
73 {
74 gLog << inf2 << "Corsika RAW" << (blocklength==kBlockLengthThin?"(+THIN)":"") << " format detected." << endl;
75 return new MCorsikaFormatRaw(fileIn, blocklength);
76 }
77
78 if (magic==kSyncMarker)
79 {
80 gLog << inf2 << "Corsika EventIO format detected." << endl;
81 return new MCorsikaFormatEventIO(fileIn);
82 }
83
84 gLog << err << "File " << fileName << Form(" (%08x) ", magic);
85 gLog << "is neither a CORSIKA raw nor EventIO file" << endl;
86
87 delete fileIn;
88
89 return NULL;
90}
91
92Bool_t MCorsikaFormat::Read(void *ptr, Int_t i) const
93{
94 fIn->read((char*)ptr, i);
95 return !fIn->fail();
96
97}
98// --------------------------------------------------------------------------
99//
100Bool_t MCorsikaFormat::Eof() const
101{
102 return fIn->eof();
103}
104
105// --------------------------------------------------------------------------
106//
107MCorsikaFormat::~MCorsikaFormat()
108{
109 delete fIn;
110}
111
112
113// --------------------------------------------------------------------------
114//
115// After a call to this function, the file pointer is located after the
116// header of the block. As the event block has no header it is located
117// at the beginning of this block, which is as the beginning of the data
118Bool_t MCorsikaFormatRaw::NextBlock(Int_t readState,
119 Int_t & blockType,
120 Int_t & blockVersion,
121 Int_t & blockIdentifier,
122 Int_t & blockLength) const
123{
124 if (fBlockLength)
125 {
126 // In the new corsika format each block
127 // starts and end with the block length
128 const size_t position = fIn->tellg()%(fBlockLength+8);
129
130 // Whenever we are prior to the end of such a block,
131 // we read and check the end and start tag of this
132 // and the following block
133 if (position==fBlockLength+4)
134 {
135 uint32_t h[2];
136 fIn->read((char*)h, 8);
137 if (fIn->eof())
138 return kFALSE;
139
140 if (h[0]!=fBlockLength || h[1]!=fBlockLength)
141 {
142 gLog << err << "ERROR - Block length missing at the end or beginning of a block." << endl;
143 return kERROR;
144 }
145 }
146 }
147
148 uint32_t blockHeader = 0;
149 fIn->read((char*)&blockHeader, 4);
150 if (fIn->eof())
151 return kFALSE;
152
153 blockVersion = 0;
154 blockIdentifier = 0;
155 blockLength = fBlockLength/21 - 4; // in bytes
156
157 switch(blockHeader)
158 {
159 case kRUNH:
160 blockType = 1200;
161 break;
162
163 case kRUNE:
164 blockType = 1210;
165 break;
166
167 case kEVTH:
168 if (readState != 10)
169 blockType = 1202; // event header (where readstate := 2)
170 else
171 {
172 blockType = 1105; // raw data
173 fIn->seekg(-4, ios::cur);
174 blockLength += 4;
175 }
176 break;
177
178 case kEVTE:
179 blockType = 1209;
180 break;
181
182 default: // the events, they don't have a specific header
183 blockType = 1105; // raw data
184 fIn->seekg(-4, ios::cur);
185 blockLength += 4;
186 }
187 return kTRUE;
188}
189// --------------------------------------------------------------------------
190//
191Bool_t MCorsikaFormatRaw::SeekEvtEnd()
192{
193 const uint32_t step = fBlockLength/21;
194 const uint32_t offset = (fBlockLength?4:0);
195
196 // Search subblockwise backward (Block: 5733*4 = 21*273*4)
197 for (uint32_t i=1; i<22; i++)
198 {
199 const int32_t L = i*step + offset;
200 fIn->seekg(-L, ios::end);
201
202 uint32_t magic = 0;
203 fIn->read((char*)&magic, 4);
204
205 if (magic==kRUNE)
206 {
207// fIn->seekg(-4, ios::cur);
208 return kTRUE;
209 }
210 }
211
212 return kFALSE;
213}
214///////////////////////////////////////////////////////////////////////////////
215///////////////////////////////////////////////////////////////////////////////
216
217Bool_t MCorsikaFormatEventIO::NextBlock(Int_t readState,
218 Int_t & blockType,
219 Int_t & blockVersion,
220 Int_t & blockIdentifier,
221 Int_t & blockLength) const
222{
223// we read - synchronisation markerif not subBlock
224// - type / version field
225// - identification field
226// - length
227// - unknown field
228// - id (first 4 bytes of data field)
229
230 if (readState == 4)
231// if (subBlock)
232 {
233 // this is a sub-block
234 int blockHeader[3];
235 fIn->read((char*)blockHeader, 3 * sizeof(int));
236
237 if (fIn->eof())
238 return kFALSE;
239
240
241 blockType = blockHeader[0] & 0xFFFF;
242 blockVersion = (blockHeader[0] & 0xFFF00000) >> 20;
243 blockIdentifier = blockHeader[1];
244 blockLength = blockHeader[2] & 0x3FFFFFFF;
245 }
246 else
247 {
248 int blockHeader[4];
249 fIn->read((char*)blockHeader, 4 * sizeof(int));
250
251 if (fIn->eof())
252 return kFALSE;
253
254
255 blockType = blockHeader[1] & 0xFFFF;
256 blockVersion = (blockHeader[1] & 0xFFF00000) >> 20;
257 blockIdentifier = blockHeader[2];
258 blockLength = blockHeader[3] & 0x3FFFFFFF;
259
260 if (blockType == 1200 || blockType == 1210 ||
261 blockType == 1202 || blockType == 1209 )
262 {
263 // read the "old" corsika header plus additional 4 unknown byte
264 char tmp[8];
265 fIn->read(tmp, 8);
266 blockLength -= 8;
267 }
268
269 }
270 return kTRUE;
271}
272
273// --------------------------------------------------------------------------
274//
275Bool_t MCorsikaFormatEventIO::SeekEvtEnd()
276{
277
278 // the RUNE block it at the very end of the file.
279 fIn->seekg(-32, ios::end);
280
281 unsigned int blockHeader[4];
282 fIn->read((char*)blockHeader, 4 * sizeof(int));
283
284 if ( blockHeader[0] == kSyncMarker &&
285 (blockHeader[1] & 0xffff) == 1210 &&
286 (blockHeader[3] & 0x3fffffff) == 16)
287 {
288 // this seams to be a RUNE (1210) block
289 fIn->seekg( 8, ios::cur);
290 return kTRUE;
291 }
292
293 return kFALSE;
294}
295
Note: See TracBrowser for help on using the repository browser.