//  $Id: BrGeantInput.cxx,v 1.14 1998/08/14 21:25:14 videbaek Exp $
//
//  $Log: BrGeantInput.cxx,v $
//  Revision 1.14  1998/08/14 21:25:14  videbaek
//  changed include files for unix
//
//  Revision 1.13  1998/07/31 19:32:42  videbaek
//  Check and set error on read problems
//
//  Revision 1.12  1998/07/20 17:42:58  videbaek
//  Added Pid hit to hit structure. Needed for effecient handling
//  of detector response.
//
//  Revision 1.11  1998/07/17 02:20:08  hagel
//  Modifications for byte swapping in BrGeantInput
//
//  Revision 1.10  1998/06/23 20:22:28  hagel
//  Zero elements of many (not all) objects to avoid problems with overlaying in memory
//
//  Revision 1.9  1998/06/21 20:11:05  hagel
//  cleanup
//
//  Revision 1.8  1998/05/14 21:18:50  videbaek
//  update makefile - do not reload .so libraries
//
//  Revision 1.7  1998/04/30 22:30:00  hagel
//  Fix errors in WIN32 stuff again
//
//  Revision 1.6  1998/04/30 17:12:35  videbaek
//  Added functionality to BrGeantInput
//
//  Revision 1.3  1998/04/08 18:09:24  videbaek
//  changed GeantInput class to use open,read
//
//  Revision 1.2  1998/04/06 21:12:11  videbaek
//  Clean up and additions for Win95
//
//  Revision 1.1  1998/04/03 21:15:04  videbaek
//  part of first base release
//
//
// April 21 : fStatus was not set properly following i/o actions.
//            This was the reason the TestBase.C failed for a non existing file
//            Note that the code has also been changed for Linux,
//            ensure updates are merged.
//
// April 24/25 Add handling of the protected variables (from BrIOModule) fError and FEof
//             to ensure uniform handling of errors, and end-of-data across different
//              BrIOModules.
//
// July 8      Increase size of GeantHits to include Pid of hit
//
#include <iostream.h>
#include <fcntl.h>
#include <math.h>
#ifndef WIN32
#   include <unistd.h>
#else
#   include <sys/stat.h>
#   include <sys/types.h>
#   include <sys/stat.h>
#   include <sys/types.h>
#endif

#include "BrGeantInput.h"
#include "BrDataTable.h"
#include "BrGeantHit.h"
#include "BrGeantTrack.h"
#include "BrEvent.h"



ClassImp(BrGeantInput)

const int END_OF_STREAM_EVENT = -1;
const int EVENT_STREAM_HEADER = 1;
const int EVENT_STREAM_HIT = 2;
const int EVENT_STREAM_TRACK =  3;



////////////////////////////////////////////////////////////////
//                                                            //
// BrGeantInput provides an interface to GBRAHMS output       //
// 
// The class is derived from the general input/output class
// and falls natural into the hierachi of module classes,
// which the BrGeantData does not.
// In terms of functionality it is very similar
//
////////////////////////////////////////////////////////////////

//#define debug
//#define BR_DEBUG

  BrGeantInput::BrGeantInput()
{
  //
  //  Constructor. Set fFilePointer and fEventCounter to NULL
  //  In root environment use the named constructor normally.
#ifdef _BRDEBUG
  cout << "Ctor : BrGeantInput " << endl;
#endif

#if USE_FSTREAM
    fFilePointer  = NULL;
#else
    fFileDescriptor  = -1;
#endif
    fEventCounter = 0;
    rHeader = kFALSE;
    fByteSwap = kFALSE;
}

 BrGeantInput::BrGeantInput(Char_t *Name) :
  BrIOModule(Name, Name)
{
  //
  // Constructor. Set fFilePointer and fEventCounter to NULL
  // name becomes Name and Title for the Module.
  // No data file is opened this has to be done in
  // the Open() method.
  //
#if USE_FSTREAM
    fFilePointer  = NULL;
#else
    fFileDescriptor  = -1;
#endif
    fEventCounter = 0;
    rHeader = kFALSE;
}

 BrGeantInput::~BrGeantInput(){
//
//  Destructor for BrGeantInput. Close the file if open.
//
#if USE_FSTREAM
if(fFilePointer) {
  fFilePointer->close();
  delete fFilePointer;
}
#else
    if(fFileDescriptor != -1)
    close(fFileDescriptor);
#endif
}

  Bool_t BrGeantInput::Open(Char_t *fname)
{
  // Open the C stream file with fname. Returns kFALSE
  // if the file can't be opened.
  // Otherwise the fFileName data member is set to the 
  // corresponding filepointer. The file header is read
  // and the volume information is stored in the intrinsic arrays
  //
  fStatus = 0;
    if(!fname)
    {
        printf("Can't open file : %sn", fname);
        return kFALSE;
    }
    sprintf(fFileName,"%s",fname);
#if USE_FSTREAM
    if(!fFilePointer)
      fFilePointer = new ifstream();
    if(!fFilePointer) {
       printf("Can't create fFilePointer object %s\n",fFileName);
       return kFALSE;
       }
    fFilePointer->open(fFileName,ios::binary|ios::in);
    if(fFilePointer->fail()) {
      printf("Can't open File %s\n",fFileName);
      delete fFilePointer;
      fFilePointer = NULL;
      fError = kTRUE;
      return kFALSE;
    }
    else {
      fStatus = 1;
      fError = kFALSE;
      fEof   = kFALSE;
      return ReadStreamHeader();
      fBytesTransferred =0;
    }
#else
#ifndef WIN32
    fFileDescriptor = open(fFileName, O_RDONLY);
#else
    fFileDescriptor = open(fFileName, O_RDONLY|O_BINARY);
#endif
    if(fFileDescriptor == -1 ) {
      printf("Can't open File %s\n",fFileName);
      fError = kTRUE;
      return kFALSE;
    }
    else {
      fStatus = 1;
      fBytesTransferred =0;
      return ReadStreamHeader();
    }

#endif
}

  Bool_t BrGeantInput::Close()
{
// Close the file Opened by the object. Return 
// kFALSE if no file was open.

#if USE_FSTREAM
    if(fFilePointer)
    {
        fFilePointer->close();
       	delete fFilePointer;
        fFilePointer = NULL;
        return kTRUE;
    }
    else
    {
        return kFALSE;
    }
#else
    if(fFileDescriptor != -1){
    close(fFileDescriptor);
      fFileDescriptor = -1;
    }
    return kTRUE;
#endif
}

 Bool_t BrGeantInput::ReadStreamHeader()
{
  //
  // read the volume information from the header.
  // At this time it is only used to define the Names
  // of the hit structures. The information is not used by other parts
  // of the reconstruction even though one could imagine that
  // the code could 'inquire' on volume information for a specific
  // detector.
  // This is not implemented. A better way will alos be to have a general
  // method for passing geometries around.
  //
  Int_t i, ivol;
  Int_t nb = 4; Int_t nread;
  
  Char_t*  VolumeName;
  
  
  Char_t * numvol = (Char_t *) (&fNumberOfVolumes);

#if USE_FSTREAM
  fFilePointer->read(numvol,nb);
#else
  nread = read(fFileDescriptor, numvol, nb);
  if(nb != nread){
    if(nb == 0) fEof = kTRUE;
    if(nb == -1) fError = kTRUE;
    return kFALSE;
  }
#endif
 fBytesTransferred +=nb;
 /*  if(fNumberOfVolumes > MAXGIVOLU){
    cout << "Try to convert file first " << endl;
    return kFALSE;
  };*/
  if(fNumberOfVolumes > MAXGIVOLU){
    fByteSwap = kTRUE;
    SwapLong(&fNumberOfVolumes,4);
  };

  for(ivol=0; ivol<fNumberOfVolumes; ivol++) {
    Char_t *bufp = (Char_t*) (&fVolume[ivol]);
    nb = sizeof(GeantVol);
#if USE_FSTREAM
    fFilePointer->read(bufp, nb);
#else
  nread = read(fFileDescriptor, bufp, nb);
  if(nb != nread){
    if(nb == 0) fEof = kTRUE;
    if(nb == -1) fError = kTRUE;
    return kFALSE;
  }
#endif
 if(fByteSwap) {
      SwapLong((int*)&fVolume[ivol].shape,8);
      SwapLong((int*)&fVolume[ivol].pos[0],96);
      }
 fBytesTransferred +=nb;
    VolumeName = fVolume[ivol].Name;
    VolumeName[sizeof(fVolume[ivol].Name)] = 0;
    //   VolumeName[sizeof(fVolume[ivol].Name)] = 0;
    //need to do this because fortran(geant?) pads with blank (32)
    for(i=0;i<sizeof(fVolume[ivol].Name);i++) {
      if(fVolume[ivol].Name[i] == 32) fVolume[ivol].Name[i] = 0;
    }

  }
SetrHeader( kTRUE );
return kTRUE;
}

 void BrGeantInput::SkipEvent(Int_t numevt)
{
BrEvent *dummyevent;
for(Int_t i=0;i<numevt;i++) {
   dummyevent = new BrEvent("Dummy",0,0);
   Event(dummyevent);
   delete dummyevent;
   }
}

 void BrGeantInput::Event(BrEvent* event)
{
  // Reads one event from the C-stream  data file.The BrEvent 
  // object has hitlist and tracklist added to the Event.
  // 
  // This object is filled with data read from the file. 
  //  It is the responsibility of the calling program to have created the
  //  event.
  // 
  // Releasing the memory for this event is the responsibility
  // of the function/macro calling Event();

  Int_t      rectyp=0, nb, ivol, nread;
  Char_t*    bufp;
  Int_t      EventHeader[2];
  Char_t     name[64];
  GeantStreamHits fHits;
  GeantStreamTracks fTracks;
  BrDataTable *HitBuffer[30];
//
//
// Create new data container for Geant Tracks and
// Geant Hits (for each of the possible volumes
//
  BrDataTable *TrackBuffer = new BrDataTable("GeantTracks");
  for(ivol=0;ivol<fNumberOfVolumes;ivol++) {
    if(fVolume[ivol].Active == 1 ){
      sprintf(name,"GeantHits %sx0",fVolume[ivol].Name);
      HitBuffer[ivol] = new BrDataTable(name);
      event->AddObject(HitBuffer[ivol]);
    }
  }

  event->AddObject(TrackBuffer);
  event->GetEventHeader()->SetRunNumber(0);
  event->GetEventHeader()->SetEventNumber(fEventCounter);
  //
  fStatus = 1;
  fEof   = kFALSE;
  fError = kFALSE;
  
  while(rectyp != END_OF_STREAM_EVENT) {
    nb = 4;
    bufp = (char*) &rectyp;
#if USE_FSTREAM
    fFilePointer->read(bufp, nb);

    if(fFilePointer->eof()) {
      cout<<"End of STREAM file found: closing file"<<endl;
      fFilePointer->close();
      fFilePointer = NULL;
      fEof = kTRUE;
      fStatus = 0;
      return;
    }
    if(fFilePointer->bad()) {
      cout << "Unexpected Bad file\n";
      fStatus = 0;
      fError = kTRUE;
#ifdef debug
    cout << nread << " " << fStatus << endl;
  if(fEof)
    cout << "*      EOF   :  TRUE \n";
  else
    cout << "*      EOF   : FALSE \n";
  if(fError)
    cout << "*      ERROR :  TRUE \n";
  else
    cout << "*      ERROR : FALSE \n";

#endif
      return;
    }
#else
  nread = read(fFileDescriptor, bufp, nb);
  if(nb != nread){    
    if(nread ==  0)   fEof = kTRUE;
    if(nread <  0 ) fError = kTRUE;
    fStatus = 0;
#ifdef debug
    cout << nread << " " << fStatus << endl;
  if(fEof)
    cout << "*      EOF   :  TRUE \n";
  else
    cout << "*      EOF   : FALSE \n";
  if(fError)
    cout << "*      ERROR :  TRUE \n";
  else
    cout << "*      ERROR : FALSE \n";

#endif
    return;
  }
#endif
  if(fByteSwap) SwapLong(&rectyp,nb);
  fBytesTransferred +=nb;
    switch (rectyp) {
    case END_OF_STREAM_EVENT:
      break;

    case  EVENT_STREAM_HEADER:
      nb = sizeof(EventHeader);
      bufp = (char*) EventHeader;
#if USE_FSTREAM
      fFilePointer->read(bufp,nb);
#else
  nread = read(fFileDescriptor, bufp, nb);
  if(nb != nread){
    if(nread == 0)  fEof  = kTRUE;
    if(nread < 0)  fError = kTRUE;
    fStatus = 0;
#ifdef debug
    cout << nread << " " << fStatus << endl;
  if(fEof)
    cout << "*      EOF   :  TRUE \n";
  else
    cout << "*      EOF   : FALSE \n";
  if(fError)
    cout << "*      ERROR :  TRUE \n";
  else
    cout << "*      ERROR : FALSE \n";

#endif
    return;
  }
#endif
 if(fByteSwap) SwapLong((int*)EventHeader,nb);
 fBytesTransferred +=nb;
      event->GetEventHeader()->SetEventNumber(EventHeader[0]);
      break;

    case  EVENT_STREAM_TRACK:
      nb = sizeof(GeantStreamTracks);
      bufp = (char*) &fTracks;
#if USE_FSTREAM
      fFilePointer->read(bufp,nb);

      if(fFilePointer->bad()) {
	cerr<<"Bad status"<<endl;
	fStatus = 0;
	return;
      }
      if(fFilePointer->eof()) {
	cerr<<"EOF status"<<endl;
	fStatus = 0;
	return;
      }
      if(fFilePointer->fail()) {
	cerr<<"Fail status"<<endl;
	fStatus = 0;
	return;
      }
#else
  nread = read(fFileDescriptor, bufp, nb);
  if(nb != nread){
    if(nread ==  0) fEof   = kTRUE;
    if(nread < 0  ) fError = kTRUE;
    fStatus = 0;
#ifdef debug
    cout << nread << " " << fStatus << endl;
    cout << fStatus << endl;
  if(fEof)
    cout << "*      EOF   :  TRUE \n";
  else
    cout << "*      EOF   : FALSE \n";
  if(fError)
    cout << "*      ERROR :  TRUE \n";
  else
    cout << "*      ERROR : FALSE \n";

#endif
    return;
  }
#endif
 if(fByteSwap) SwapLong((int*)bufp,44);
 fBytesTransferred +=nb;
      TrackBuffer->Add(new BrGeantTrack(fTracks));
      break;

    case  EVENT_STREAM_HIT:
      nb = sizeof(GeantStreamHits);
      bufp = (char*) & fHits;
#if USE_FSTREAM
      fFilePointer->read(bufp,nb);

      if(fFilePointer->bad()) {
	cerr<<"Bad status"<<endl;
	fStatus = 0;
	return;
      }
      if(fFilePointer->eof()) {
	cerr<<"EOF status"<<endl;
	fStatus = 0;
	return;
      }
      if(fFilePointer->fail()) {
	cerr<<"Fail status"<<endl;
	fStatus = 0;
#ifdef debug
    cout << fStatus << endl;
  if(fEof)
    cout << "*      EOF   :  TRUE \n";
  else
    cout << "*      EOF   : FALSE \n";
  if(fError)
    cout << "*      ERROR :  TRUE \n";
  else
    cout << "*      ERROR : FALSE \n";

#endif
	return;
      }

#else
  nread = read(fFileDescriptor, bufp, nb);
  if(nb != nread){
    if(nread == 0)  fEof   = kTRUE;
    if(nread < 0  ) fError = kTRUE;
    fStatus = 0;
#ifdef debug
  cout << nread << " " << fStatus << endl;
  if(fEof)
    cout << "*      EOF   :  TRUE \n";
  else
    cout << "*      EOF   : FALSE \n";
  if(fError)
    cout << "*      ERROR :  TRUE \n";
  else
    cout << "*      ERROR : FALSE \n";

#endif
    return;
  }
#endif
 if(fByteSwap) SwapLong((int*)bufp,nb);
 fBytesTransferred +=nb;
      ivol = fHits.DetectorId - 1; //-1 needed because indices start at 0
      if( fHits.dedx > 0 ) {
	HitBuffer[ivol]->Add(new BrGeantHit(fHits));
      }
      break;

    default:
      //          This should not happen!!
      //          Indicates logic error.
      fStatus = 0;
      fError = kTRUE;
      cout <<"*** Problem in data:" << endl;
      cout << "rectype in stream file is " << rectyp<< endl;
#ifdef debug
    cout << fStatus << endl;
  if(fEof)
    cout << "*      EOF   :  TRUE \n";
  else
    cout << "*      EOF   : FALSE \n";
  if(fError)
    cout << "*      ERROR :  TRUE \n";
  else
    cout << "*      ERROR : FALSE \n";

#endif
      return;

    }
  }
  sprintf(name,"event_%d_%d",event->GetRunNumber(),event->GetEventNumber());
  event->SetName(name);
  sprintf(name,"BrEvent %d %d",event->GetRunNumber(),event->GetEventNumber());
  event->SetTitle(name);
  fEventCounter++;

#ifdef debug
    cout << fStatus << endl;
  if(fEof)
    cout << "*      EOF   :  TRUE \n";
  else
    cout << "*      EOF   : FALSE \n";
  if(fError)
    cout << "*      ERROR :  TRUE \n";
  else
    cout << "*      ERROR : FALSE \n";

#endif
  return;
}

 void BrGeantInput::SwapLong(int *buffer,int nb)
{
int i,j;
union {
   int il;
   char ib[4];
   } temp;

union {
   int il;
   char ib[4];
   } temp1;

j = 0;
for(i=0;i<nb;i+=4) {
   temp.il = buffer[j];
   temp1.ib[0] = temp.ib[3];
   temp1.ib[1] = temp.ib[2];
   temp1.ib[2] = temp.ib[1];
   temp1.ib[3] = temp.ib[0];
   buffer[j] = temp1.il;
   j++;
   }
}





ROOT page - Class index - Top of the page

This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.