| 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 |
|
|---|
| 39 | using namespace std;
|
|---|
| 40 |
|
|---|
| 41 |
|
|---|
| 42 | const unsigned int MCorsikaFormat::kMagicNumber = 0x5994;
|
|---|
| 43 | const unsigned int MCorsikaFormat::kSyncMarker = 0xd41f8a37;
|
|---|
| 44 |
|
|---|
| 45 | // --------------------------------------------------------------------------
|
|---|
| 46 | //
|
|---|
| 47 | MCorsikaFormat *MCorsikaFormat::CorsikaFormatFactory(const char * fileName)
|
|---|
| 48 | {
|
|---|
| 49 | ifstream * fileIn = new ifstream(fileName);
|
|---|
| 50 |
|
|---|
| 51 | const Bool_t noexist = !(*fileIn);
|
|---|
| 52 | if (noexist)
|
|---|
| 53 | {
|
|---|
| 54 | gLog << err << "Cannot open file " << fileName << ": ";
|
|---|
| 55 | gLog << (errno!=0?strerror(errno):"Insufficient memory for decompression") << endl;
|
|---|
| 56 | delete fileIn;
|
|---|
| 57 | return NULL;
|
|---|
| 58 | }
|
|---|
| 59 |
|
|---|
| 60 | char *buffer = new char[5];
|
|---|
| 61 | memset(buffer, 0, 5);
|
|---|
| 62 | fileIn->read(buffer, 4);
|
|---|
| 63 |
|
|---|
| 64 | // This seems to be a new corsika binary identifier
|
|---|
| 65 | const bool hasMagicNumber = *reinterpret_cast<unsigned int*>(buffer) == kMagicNumber;
|
|---|
| 66 | if (hasMagicNumber)
|
|---|
| 67 | fileIn->read(buffer, 4);
|
|---|
| 68 |
|
|---|
| 69 | fileIn->seekg(-4, ios::cur);
|
|---|
| 70 |
|
|---|
| 71 | if (strcmp(buffer, "RUNH") == 0)
|
|---|
| 72 | {
|
|---|
| 73 | delete [] buffer;
|
|---|
| 74 | gLog << inf2 << "Corsika RAW format detected." << endl;
|
|---|
| 75 | return new MCorsikaFormatRaw(fileIn, hasMagicNumber);
|
|---|
| 76 | }
|
|---|
| 77 |
|
|---|
| 78 | if (*reinterpret_cast<unsigned int*>(buffer) == kSyncMarker)
|
|---|
| 79 | {
|
|---|
| 80 | delete [] buffer;
|
|---|
| 81 | gLog << inf2 << "Corsika EventIO format detected." << endl;
|
|---|
| 82 | return new MCorsikaFormatEventIO(fileIn);
|
|---|
| 83 | }
|
|---|
| 84 |
|
|---|
| 85 | gLog << err << "File " << fileName <<
|
|---|
| 86 | " is neither a CORSIKA raw nor EventIO file" << endl;
|
|---|
| 87 | delete fileIn;
|
|---|
| 88 | delete [] buffer;
|
|---|
| 89 |
|
|---|
| 90 | return NULL;
|
|---|
| 91 | }
|
|---|
| 92 |
|
|---|
| 93 | Bool_t MCorsikaFormat::Read(void *ptr, Int_t i) const
|
|---|
| 94 | {
|
|---|
| 95 | fIn->read((char*)ptr, i);
|
|---|
| 96 | return !fIn->fail();
|
|---|
| 97 |
|
|---|
| 98 | }
|
|---|
| 99 | // --------------------------------------------------------------------------
|
|---|
| 100 | //
|
|---|
| 101 | Bool_t MCorsikaFormat::Eof() const
|
|---|
| 102 | {
|
|---|
| 103 | return fIn->eof();
|
|---|
| 104 | }
|
|---|
| 105 |
|
|---|
| 106 | // --------------------------------------------------------------------------
|
|---|
| 107 | //
|
|---|
| 108 | MCorsikaFormat::~MCorsikaFormat()
|
|---|
| 109 | {
|
|---|
| 110 | delete fIn;
|
|---|
| 111 | }
|
|---|
| 112 |
|
|---|
| 113 |
|
|---|
| 114 | // --------------------------------------------------------------------------
|
|---|
| 115 | //
|
|---|
| 116 | // After a call to this function, the file pointer is located after the
|
|---|
| 117 | // header of the block. As the event block has no header it is located
|
|---|
| 118 | // at the beginning of this block, which is as the beginning of the data
|
|---|
| 119 | Bool_t MCorsikaFormatRaw::NextBlock(Int_t readState,
|
|---|
| 120 | Int_t & blockType,
|
|---|
| 121 | Int_t & blockVersion,
|
|---|
| 122 | Int_t & blockIdentifier,
|
|---|
| 123 | Int_t & blockLength) const
|
|---|
| 124 | {
|
|---|
| 125 |
|
|---|
| 126 | int blockHeader;
|
|---|
| 127 | fIn->read((char*)&blockHeader, 4);
|
|---|
| 128 | if (fIn->eof())
|
|---|
| 129 | return kFALSE;
|
|---|
| 130 |
|
|---|
| 131 | blockVersion = 0;
|
|---|
| 132 | blockIdentifier = 0;
|
|---|
| 133 | blockLength = 272 * 4;
|
|---|
| 134 |
|
|---|
| 135 | switch(blockHeader)
|
|---|
| 136 | {
|
|---|
| 137 | case 1213093202 : // RUNH
|
|---|
| 138 | blockType = 1200;
|
|---|
| 139 | break;
|
|---|
| 140 | case 22932: // Magic Number (seems(!) to also signal run end, RUNE comes AFTER)
|
|---|
| 141 | case 1162761554 : // RUNE
|
|---|
| 142 | blockType = 1210;
|
|---|
| 143 | break;
|
|---|
| 144 | case 1213486661 : // EVTH
|
|---|
| 145 | if (readState != 10)
|
|---|
| 146 | blockType = 1202;
|
|---|
| 147 | else
|
|---|
| 148 | {
|
|---|
| 149 | blockType = 1105;
|
|---|
| 150 | fIn->seekg(-4, ios::cur);
|
|---|
| 151 | blockLength += 4;
|
|---|
| 152 | }
|
|---|
| 153 | break;
|
|---|
| 154 | case 1163155013 : // EVTE
|
|---|
| 155 | blockType = 1209;
|
|---|
| 156 | break;
|
|---|
| 157 | default: // the events, they don't have a specific header
|
|---|
| 158 | blockType = 1105;
|
|---|
| 159 | fIn->seekg(-4, ios::cur);
|
|---|
| 160 | blockLength += 4;
|
|---|
| 161 | }
|
|---|
| 162 | return kTRUE;
|
|---|
| 163 | }
|
|---|
| 164 | // --------------------------------------------------------------------------
|
|---|
| 165 | //
|
|---|
| 166 | Bool_t MCorsikaFormatRaw::SeekEvtEnd()
|
|---|
| 167 | {
|
|---|
| 168 | // Search subblockwise backward (Block: 5733*4 = 21*273*4)
|
|---|
| 169 | for (int i=1; i<22; i++)
|
|---|
| 170 | {
|
|---|
| 171 | fIn->seekg(-i*273*4-(fHasMagicNumber?4:0), ios::end);
|
|---|
| 172 |
|
|---|
| 173 | char runh[5]="\0\0\0\0";
|
|---|
| 174 | fIn->read(runh, 4);
|
|---|
| 175 |
|
|---|
| 176 | if (!strcmp(runh, "RUNE"))
|
|---|
| 177 | {
|
|---|
| 178 | // fIn->seekg(-4, ios::cur);
|
|---|
| 179 | return kTRUE;
|
|---|
| 180 | }
|
|---|
| 181 | }
|
|---|
| 182 |
|
|---|
| 183 | return kFALSE;
|
|---|
| 184 | }
|
|---|
| 185 | ///////////////////////////////////////////////////////////////////////////////
|
|---|
| 186 | ///////////////////////////////////////////////////////////////////////////////
|
|---|
| 187 |
|
|---|
| 188 | Bool_t MCorsikaFormatEventIO::NextBlock(Int_t readState,
|
|---|
| 189 | Int_t & blockType,
|
|---|
| 190 | Int_t & blockVersion,
|
|---|
| 191 | Int_t & blockIdentifier,
|
|---|
| 192 | Int_t & blockLength) const
|
|---|
| 193 | {
|
|---|
| 194 | // we read - synchronisation markerif not subBlock
|
|---|
| 195 | // - type / version field
|
|---|
| 196 | // - identification field
|
|---|
| 197 | // - length
|
|---|
| 198 | // - unknown field
|
|---|
| 199 | // - id (first 4 bytes of data field)
|
|---|
| 200 |
|
|---|
| 201 | if (readState == 4)
|
|---|
| 202 | // if (subBlock)
|
|---|
| 203 | {
|
|---|
| 204 | // this is a sub-block
|
|---|
| 205 | int blockHeader[3];
|
|---|
| 206 | fIn->read((char*)blockHeader, 3 * sizeof(int));
|
|---|
| 207 |
|
|---|
| 208 | if (fIn->eof())
|
|---|
| 209 | return kFALSE;
|
|---|
| 210 |
|
|---|
| 211 |
|
|---|
| 212 | blockType = blockHeader[0] & 0xFFFF;
|
|---|
| 213 | blockVersion = (blockHeader[0] & 0xFFF00000) >> 20;
|
|---|
| 214 | blockIdentifier = blockHeader[1];
|
|---|
| 215 | blockLength = blockHeader[2] & 0x3FFFFFFF;
|
|---|
| 216 | }
|
|---|
| 217 | else
|
|---|
| 218 | {
|
|---|
| 219 | int blockHeader[4];
|
|---|
| 220 | fIn->read((char*)blockHeader, 4 * sizeof(int));
|
|---|
| 221 |
|
|---|
| 222 | if (fIn->eof())
|
|---|
| 223 | return kFALSE;
|
|---|
| 224 |
|
|---|
| 225 |
|
|---|
| 226 | blockType = blockHeader[1] & 0xFFFF;
|
|---|
| 227 | blockVersion = (blockHeader[1] & 0xFFF00000) >> 20;
|
|---|
| 228 | blockIdentifier = blockHeader[2];
|
|---|
| 229 | blockLength = blockHeader[3] & 0x3FFFFFFF;
|
|---|
| 230 |
|
|---|
| 231 | if (blockType == 1200 || blockType == 1210 ||
|
|---|
| 232 | blockType == 1202 || blockType == 1209 )
|
|---|
| 233 | {
|
|---|
| 234 | // read the "old" corsika header plus additional 4 unknown byte
|
|---|
| 235 | char tmp[8];
|
|---|
| 236 | fIn->read(tmp, 8);
|
|---|
| 237 | blockLength -= 8;
|
|---|
| 238 | }
|
|---|
| 239 |
|
|---|
| 240 | }
|
|---|
| 241 | return kTRUE;
|
|---|
| 242 | }
|
|---|
| 243 |
|
|---|
| 244 | // --------------------------------------------------------------------------
|
|---|
| 245 | //
|
|---|
| 246 | Bool_t MCorsikaFormatEventIO::SeekEvtEnd()
|
|---|
| 247 | {
|
|---|
| 248 |
|
|---|
| 249 | // the RUNE block it at the very end of the file.
|
|---|
| 250 | fIn->seekg(-32, ios::end);
|
|---|
| 251 |
|
|---|
| 252 | unsigned int blockHeader[4];
|
|---|
| 253 | fIn->read((char*)blockHeader, 4 * sizeof(int));
|
|---|
| 254 |
|
|---|
| 255 | if ( blockHeader[0] == kSyncMarker &&
|
|---|
| 256 | (blockHeader[1] & 0xffff) == 1210 &&
|
|---|
| 257 | (blockHeader[3] & 0x3fffffff) == 16)
|
|---|
| 258 | {
|
|---|
| 259 | // this seams to be a RUNE (1210) block
|
|---|
| 260 | fIn->seekg( 8, ios::cur);
|
|---|
| 261 | return kTRUE;
|
|---|
| 262 | }
|
|---|
| 263 |
|
|---|
| 264 | return kFALSE;
|
|---|
| 265 | }
|
|---|
| 266 |
|
|---|