MODULE DataFormats USE IOunits USE TPCdata USE Threshold USE Space USE LCIO4TPC PRIVATE ! Write DenseData ! WriteDenseHeader(chComment,chDate) ! event with or without additional information ! WriteDenseData() ! WriteDenseData(info) ! WriteEndOfRun() PUBLIC :: WriteDenseHeader,WriteDenseData,WriteEndOfRun ! Read DenseData ! OPENDense(IERR) ! ReadDenseHeader(IERR,chComment,chDate) ! ReadDenseEvent(IERR) PUBLIC :: OPENDense,ReadDenseHeader,ReadDenseEvent ! Read JTPC Monte Carlo ! ReadMCHeader(chComment,chDate) ! ReadMCEvent(IERR) PUBLIC :: ReadMCHeader,ReadMCEvent ! Read MIDAS data ! OPENMIDAS(IERR) is also used for JTPC ! ReadMIDASHeader(chComment,chDate) ! ReadMIDASEvent(IERR) PUBLIC :: OPENMIDAS,ReadMIDASHeader,ReadMIDASEvent ! Read LCIO data ! OPENLCIO(IERR) ! ReadLCIOHeader(ChComment,ChDate) ! ReadLCIOEvent(IERR) PUBLIC :: OPENLCIO,ReadLCIOHeader,ReadLCIOEvent PRIVATE :: WriteDenseDataHeader,WriteDenseDataGroups PRIVATE :: WriteDenseDataPlain,WriteDenseDataInfo PRIVATE :: scanHead,chExtract INTERFACE WriteDenseData MODULE PROCEDURE WriteDenseDataPlain,WriteDenseDataInfo END INTERFACE INTEGER,PRIVATE :: NewEvent=0 INTEGER,PRIVATE :: firstGroup,FADCbyte CHARACTER(LEN=80),PUBLIC,SAVE,ALLOCATABLE,DIMENSION(:) :: CHrunIN CHARACTER(LEN=80),PRIVATE,SAVE :: currentFile CONTAINS ! %%%%%%%%%%%%%%%%%%%% OUTPUT of dense data %%%%%%%%%%%%%%%%%%%%%%% SUBROUTINE WriteDenseHeader(chComment,chDate) ! write run header CHARACTER(LEN=*),INTENT(IN) :: chComment,chDate INTEGER :: IOS WRITE(UNIT=IODense,IOSTAT=IOS)RunNumber,Time,nGroups WRITE(UNIT=IODense,IOSTAT=IOS)chComment WRITE(UNIT=IODense,IOSTAT=IOS)chDate END SUBROUTINE WriteDenseHeader SUBROUTINE WriteDenseDataPlain() INTEGER :: IOS CALL WriteDenseDataHeader() WRITE(UNIT=IODense,IOSTAT=IOS) 0 CALL WriteDenseDataGroups() END SUBROUTINE WriteDenseDataPlain SUBROUTINE WriteDenseDataInfo(info) REAL,DIMENSION(:),INTENT(IN) :: info INTEGER :: IOS CALL WriteDenseDataHeader() WRITE(UNIT=IODense,IOSTAT=IOS) SIZE(info) WRITE(UNIT=IODense,IOSTAT=IOS) info CALL WriteDenseDataGroups() END SUBROUTINE WriteDenseDataInfo SUBROUTINE WriteDenseDataHeader() ! write event header INTEGER :: IOS WRITE(UNIT=IODense,IOSTAT=IOS) EventNumber,-100.0,-100.0 END SUBROUTINE WriteDenseDataHeader SUBROUTINE WriteDenseDataGroups() ! write group information INTEGER :: iGroup,IOS REAL :: Amplitude,T0 DO iGroup=1,nGroups CALL GetSignalGroup(iGroup,Amplitude,T0) IF( Amplitude>0.0 ) & WRITE(UNIT=IODense,IOSTAT=IOS) iGroup,Amplitude,T0 ENDDO END SUBROUTINE WriteDenseDataGroups SUBROUTINE WriteEndOfRun() INTEGER :: IOS WRITE(UNIT=IODense,IOSTAT=IOS) -1000,-100.0,-100.0 END SUBROUTINE WriteEndOfRun ! %%%%%%%%%%%%% INPUT dense data %%%%%%%%%%%%%%%%%%%%% SUBROUTINE OPENDense(IERR) INTEGER,INTENT(OUT) :: IERR INTEGER,SAVE :: iFile=0 INTEGER :: IOS=0 IF( iFile /= 0 ) CLOSE(UNIT=IOrunIN,IOSTAT=IOS) IF( IOS /= 0 )THEN WRITE(UNIT=IOErr,FMT=*) "ERROR, OPENDense> cant close input file" IERR = -3 RETURN ENDIF iFile = iFile+1 IF( iFile > size(CHrunIN) )THEN IERR = -1 RETURN ENDIF OPEN(UNIT=IOrunIN,FILE=CHrunIN(iFile),STATUS="OLD",ACTION="READ",& ACCESS="SEQUENTIAL",FORM="UNFORMATTED",POSITION="REWIND",IOSTAT=IOS) IF( IOS /= 0 )THEN WRITE(UNIT=IOErr,FMT=*) "ERROR, ReadHeader> cant open input file:" WRITE(UNIT=IOErr,FMT=*) CHrunIN(iFile) IERR = -2 RETURN ENDIF IERR = 0 END SUBROUTINE OPENDense SUBROUTINE ReadDenseHeader(IERR,chComment,chDate) INTEGER,INTENT(OUT) :: IERR CHARACTER(LEN=*),INTENT(OUT) :: chComment,chDate REAL :: Amplitude,T0 INTEGER :: nGr,IOS IERR = -99 READ(UNIT=IOrunIN,IOSTAT=IOS)RunNumber,Time,nGr IF( IOS/=0 )THEN IERR = -1 RETURN ENDIF IF( nGr /= nGroups )THEN WRITE(UNIT=IOErr,FMT=*) "ERROR, ReadDenseHeader> number of MIDAS channel does not match groups" STOP ENDIF READ(UNIT=IOrunIN,IOSTAT=IOS)chComment IF( IOS/=0 )THEN PRINT*,"ERROR ReadDenseHeader, comment" STOP ENDIF READ(UNIT=IOrunIN,IOSTAT=IOS)chDate IF( IOS/=0 )THEN PRINT*,"ERROR ReadDenseHeader, date" STOP ENDIF READ(UNIT=IOrunIN,IOSTAT=IOS)NewEvent,Amplitude,T0 IF( Amplitude>0 .OR. IOS/=0 )THEN PRINT*,"ERROR ReadDenseHeader, event" STOP ENDIF nTbin = 0 IERR = 0 END SUBROUTINE ReadDenseHeader SUBROUTINE ReadDenseEvent(IERR) INTEGER,INTENT(OUT) :: IERR INTEGER :: iGroup,iP,iPad,IOS,i,iTag REAL :: Amplitude,T0,xinfo IERR = -99 EventNumber = NewEvent DO iPad=1,nPads CALL FillSignal(iPad,0.0,1.0) ENDDO IF( .NOT.LoldDD )THEN READ(UNIT=IOrunIN,IOSTAT=IOS) iTag DO i=1,iTag READ(UNIT=IOrunIN,IOSTAT=IOS) xinfo ENDDO ENDIF DO READ(UNIT=IOrunIN,IOSTAT=IOS) iGroup,Amplitude,T0 IF( IOS/=0 )THEN IERR = -1 RETURN ENDIF IF( iGroup<0 )THEN IERR = 1 RETURN ENDIF IF( Amplitude<0.0 )THEN NewEvent = iGroup IERR = 0 RETURN ENDIF DO iP=1,nPadsinGroup(iGroup) iPad = iPadofGroup(iP,iGroup) CALL FillSignal(iPad,Amplitude,T0) ENDDO ENDDO END SUBROUTINE ReadDenseEvent ! %%%%%%%%%%%%%% .mc Monte Carlo %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% SUBROUTINE ReadMCHeader(chComment,chDate) CHARACTER(LEN=*),INTENT(OUT) :: chComment,chDate INTEGER :: i,nGr,IOS,MCVersion,sizeRunHeader INTEGER :: FADCbits,FADCgain,FADCtime INTEGER,PARAMETER :: lenTitle=32,nRunHeader=10 INTEGER,DIMENSION(nRunHeader) :: RunHeader CHARACTER(LEN=1),DIMENSION(lenTitle) :: chTitle ! read the title CALL readch(IOrunIN,chTitle,lenTitle,IOS) DO i=1,lenTitle chComment(i:i) = chTitle(i) ENDDO ! version CALL readint(IOrunIN,MCVersion,4,IOS) WRITE(UNIT=chComment(lenTitle+1:len(chComment)),FMT=*) & " Version: ",MCVersion chDate = " " ! header size CALL readint(IOrunIN,sizeRunHeader,4,IOS) IF( sizeRunHeader /= 4*nRunHeader )THEN WRITE(UNIT=IOErr,FMT=*) "ERROR, ReadMCHeader> Headersize doesnt match" STOP ENDIF DO i=1,nRunHeader ! run header CALL readint(IOrunIN,RunHeader(i),4,IOS) ENDDO RunNumber = RunHeader(1) nGr = RunHeader(5) firstGroup = RunHeader(6) FADCbits = RunHeader(7) nTbin = RunHeader(8) FADCgain = RunHeader(9) FADCtime = RunHeader(10) IF( nGr /= nGroups )THEN WRITE(UNIT=IOErr,FMT=*) "ERROR, ReadMCHeader> number of MIDAS channel does not match groups" STOP ENDIF FADCbyte = (FADCbits-1)/8 + 1 IF( FADCbyte>4 )THEN WRITE(UNIT=IOErr,FMT=*) "ERROR, ReadMCHeader> FADCbyte too large" STOP ENDIF END SUBROUTINE ReadMCHeader SUBROUTINE ReadMCEvent(IERR) INTEGER,INTENT(OUT) :: IERR INTEGER :: i,IOS,iG,iGroup,IVAL,iTb,sizeEventHeader INTEGER,PARAMETER :: nEventHeader=5 INTEGER,DIMENSION(nEventHeader) :: EventHeader IERR = -99 ! header size CALL readint(IOrunIN,sizeEventHeader,4,IOS) IF( IOS /= 0 )THEN IERR = -1 RETURN ENDIF IF( sizeEventHeader /= 4*nEventHeader )THEN WRITE(UNIT=IOErr,FMT=*) "ERROR, ReadMCEvent> Headersize doesnt match" STOP ENDIF DO i=1,nEventHeader ! run header CALL readint(IOrunIN,EventHeader(i),4,IOS) IF( IOS /= 0 )THEN IERR = -2 RETURN ENDIF ENDDO EventNumber = EventHeader(1) MCx0 = REAL(EventHeader(2))*1.0E-3 MCz0 = REAL(EventHeader(3))*1.0E-3 MCphi = REAL(EventHeader(4))*1.0E-6 MCtheta = REAL(EventHeader(5))*1.0E-6 DO i=1,nGroups CALL readint(IOrunIN,iG,4,IOS) IF( IOS /= 0 )THEN IERR = -3 RETURN ENDIF iGroup = iG - firstGroup + 1 IF( iGroup<1 .OR. iGroup>nGroups )THEN print*,i,iG,iGroup WRITE(UNIT=IOErr,FMT=*) "ERROR, ReadMCEvent> iGroup out of range" STOP ENDIF DO iTb=1,nTbin IVAL = 0 CALL readint(IOrunIN,IVAL,FADCbyte,IOS) IF( IOS /= 0 )THEN IERR = -4 RETURN ENDIF IADC(iTb,iGroup) = IVAL ENDDO ENDDO IERR = 0 END SUBROUTINE ReadMCEvent ! %%%%%%%%%%%%%%%%%%% MIDAS data %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% SUBROUTINE OPENMIDAS(IERR) INTEGER,INTENT(OUT) :: IERR INTEGER,SAVE :: iFile=0 INTEGER :: IOS=0 IF( iFile /= 0 ) CALL closefile(IOrunIN,IOS) IF( IOS /= 0 )THEN WRITE(UNIT=IOErr,FMT=*) "ERROR, ReadHeader> cant close input file" IERR = -3 RETURN ENDIF iFile = iFile+1 IF( iFile > size(CHrunIN) )THEN IERR = -1 RETURN ENDIF CALL openfile(IOrunIN,CHrunIN(iFile),IOS) IF( IOS /= 0 )THEN WRITE(UNIT=IOErr,FMT=*) "ERROR, ReadHeader> cant open input file:" WRITE(UNIT=IOErr,FMT=*) CHrunIN(iFile) IERR = -2 RETURN ENDIF IERR = 0 END SUBROUTINE OPENMIDAS SUBROUTINE ReadMIDASHeader(chComment,chDate) CHARACTER(LEN=*),INTENT(OUT) :: chComment,chDate INTEGER :: iHSize,nTb,nChan,nGr,IOS INTEGER,PARAMETER :: one_byte=1,two_byte=2,four_byte=3 CHARACTER(LEN=1),ALLOCATABLE,DIMENSION(:) :: cdata INTEGER(KIND=two_byte) :: IHWord nTb = -1 nChan = -1 ! read the first half word CALL readhword(IOrunIN,IHWord,IOS) IF( IHWord /= -32768 )THEN WRITE(UNIT=IOErr,FMT=*) "ERROR, ReadMIDASHeader> Header ID .NE. x8000" STOP ENDIF ! read the remaining 2 bytes CALL readhword(IOrunIN,IHWord,IOS) ! run number CALL readword(IOrunIN,RunNumber,IOS) ! time of the run since 1/1/1970 CALL readword(IOrunIN,Time,IOS) ! size of the event header CALL readword(IOrunIN,IHsize,IOS) ! get the memory for the event header ALLOCATE ( cdata(IHSize),STAT=IOS ) ! read the header CALL readch(IOrunIN,cdata,IHSize,IOS) ! scan header for number of time bins and the comment CALL scanHead(cdata,nTb,nChan,chComment,chDate,IOS) nTbin = nTb*2 nGr = nChan*4 IF( nGr /= nGroups )THEN WRITE(UNIT=IOErr,FMT=*) "ERROR, ReadMIDASHeader> number of MIDAS channel does not match groups" STOP ENDIF END SUBROUTINE ReadMIDASHeader SUBROUTINE scanHead(cdata,nTb,nChan,chComment,chDate,IOS) CHARACTER(LEN=1),DIMENSION(:),INTENT(IN) :: cdata INTEGER,INTENT(OUT) :: nTb,nChan,IOS CHARACTER(LEN=*),INTENT(OUT) :: chComment,chDate CHARACTER(LEN=80) :: chline CHARACTER(LEN=size(cdata)) :: string INTEGER :: I,length,delay IOS = 0 DO I=1,size(cdata) string(I:I) = cdata(I) ENDDO CALL chExtract("number of cards = INT :",string,chline,length) IF( length < 0 )THEN WRITE(UNIT=IOErr,FMT=*) "ERROR, scanHead> number of channels not found" STOP ENDIF READ(unit=chline(1:length),fmt=*) nChan CALL chExtract("number of bin pairs = INT :",string,chline,length) IF( length < 0 )THEN WRITE(UNIT=IOErr,FMT=*) "ERROR, scanHead> number of bin pairs not found" STOP ENDIF READ(unit=chline(1:length),fmt=*) nTb CALL chExtract("post trigger delay (ns) = INT :",string,chline,length) IF( length < 0 )THEN WRITE(UNIT=IOErr,FMT=*) "ERROR, scanHead> post trigger delay not found" ENDIF READ(unit=chline(1:length),fmt=*) delay CALL chExtract("Comment = STRING : [80]",string,chline,length) IF( length < 0 )THEN WRITE(UNIT=IOErr,FMT=*) "WARNING, scanHead> comment not found" ENDIF chComment = chline(1:length) IF( len(chComment) >=length+17 ) & WRITE(UNIT=chComment(length+2:length+17),FMT=*) "delay:",delay IF( len(chComment) >=length+30 ) & WRITE(UNIT=chComment(length+19:length+30) ,FMT=*) "nTb:",nTb CALL chExtract("Start time = STRING : [32]",string,chline,length) IF( length < 0 )THEN WRITE(UNIT=IOErr,FMT=*) "WARNING, scanHead> comment not found" ENDIF chDate = chline(1:length) END SUBROUTINE scanHead SUBROUTINE chExtract(chkey,string,chline,length) CHARACTER(LEN=*),INTENT(IN) :: chkey CHARACTER(LEN=*),INTENT(IN) :: string CHARACTER(LEN=*),INTENT(OUT) :: chline INTEGER,INTENT(OUT) :: length INTEGER :: ipos,iStart,iEnd ! get the index of the keywords ipos = index(string,chkey) ! string found? IF( ipos == 0 ) THEN length = -1 RETURN ENDIF ! search for the line break (ASCII code=10) iStart = ipos+len(chkey) DO iEnd=iStart,iStart+80 IF( ichar(string(iEnd:iEnd)) == 10 )EXIT ENDDO chline = string(iStart:iEnd-1) length = iEnd-iStart END SUBROUTINE chExtract SUBROUTINE ReadMIDASEvent(IERR) INTEGER,INTENT(OUT) :: IERR INTEGER,PARAMETER :: one_byte=1,two_byte=2,four_byte=3 INTEGER(KIND=one_byte) :: idata INTEGER(KIND=two_byte) :: IHWord INTEGER :: eSize,gSize,bSize,dummy,iGroup,iTb,IVAL,IOS IERR = -99 ! check the size of integers ! IF( BIT_SIZE(idata) /= 1 )THEN ! PRINT*,"ERROR, ReadMIDASEvent> check size of idata" ! STOP ! ENDIF ! IF( BIT_SIZE(IHWord) /= 2 )THEN ! PRINT*,"ERROR, ReadMIDASEvent> check size of IHWord" ! STOP ! ENDIF ! IF( BIT_SIZE(eSize) /= 4 )THEN ! PRINT*,"ERROR, ReadMIDASEvent> check size of eSize" ! STOP ! ENDIF ! read the first half word CALL readhword(IOrunIN,IHWord,IOS) IF( IOS /= 0 )THEN IERR = -12 RETURN ENDIF IF( IHWord == -32767 )THEN IERR = -11 RETURN ENDIF IF( IHWord /= 1 )THEN WRITE(UNIT=IOErr,FMT=*) "ERROR, ReadMIDASEvent> Header ID .NE. 1: ",IHWord IERR = -10 RETURN ENDIF ! read the remaining 2 bytes CALL readhword(IOrunIN,IHWord,IOS) IF( IOS /= 0 )THEN IERR = -9 RETURN ENDIF ! event number CALL readword(IOrunIN,EventNumber,IOS) IF( IOS /= 0 )THEN IERR = -8 RETURN ENDIF ! event time CALL readword(IOrunIN,dummy,IOS) IF( IOS /= 0 )THEN IERR = -7 RETURN ENDIF ! event size CALL readword(IOrunIN,eSize,IOS) IF( IOS /= 0 )THEN IERR = -6 RETURN ENDIF ! global bank size CALL readword(IOrunIN,gSize,IOS) IF( IOS /= 0 )THEN IERR = -5 RETURN ENDIF ! header CALL readword(IOrunIN,dummy,IOS) IF( IOS /= 0 )THEN IERR = -4 RETURN ENDIF ! get data for all groups DO iGroup = 1,nGroups ! channel name CALL readword(IOrunIN,dummy,IOS) IF( IOS /= 0 )THEN IERR = -3 RETURN ENDIF ! channel header CALL readword(IOrunIN,dummy,IOS) IF( IOS /= 0 )THEN IERR = -2 RETURN ENDIF ! bank size CALL readword(IOrunIN,bSize,IOS) IF( bSize /= nTbin )THEN WRITE(UNIT=IOErr,FMT=*) bSize,nTbin WRITE(UNIT=IOErr,FMT=*) "ERROR, ReadMIDASEvent> bankSize does not match time bins" STOP ENDIF DO iTb=1,nTbin CALL readbyte(IOrunIN,idata,IOS) IF( IOS /= 0 ) EXIT ! convert to F IVAL = idata IADC(iTb,iGroup) = IAND(IVAL+256,255) ENDDO IF( IOS /= 0 )THEN IERR = -1 RETURN ENDIF ENDDO IERR = 0 END SUBROUTINE ReadMIDASEvent ! %%%%%%%%%%%%%%%%%%% LCIO data %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% SUBROUTINE OPENLCIO(IERR) INTEGER,INTENT(OUT) :: IERR INTEGER,SAVE :: iFile=0 INTEGER :: IOS=0 iFile = iFile+1 IF( iFile > size(CHrunIN) )THEN IERR = -1 RETURN ENDIF currentFile = CHrunIN(iFile) CALL OpenReadLCIO(CHrunIN(iFile),IOS) IF( IOS /= 0 )THEN WRITE(UNIT=IOErr,FMT=*) "ERROR, OPENLCIO> cant open input file:" WRITE(UNIT=IOErr,FMT=*) CHrunIN(iFile) IERR = -2 RETURN ENDIF IERR = 0 END SUBROUTINE OPENLCIO SUBROUTINE ReadLCIOHeader(ChComment,ChDate) CHARACTER(LEN=*),INTENT(OUT) :: chComment,chDate INTEGER :: nTb,IOS ! read nTbin from the first events CALL ReadLCIOnTbin(nTb) IF( nTb > 0 )THEN nTbin = nTb ELSEIF( nTb == -1 )THEN ! ReadLCIOnTbin was called before, keep everything as is ELSE PRINT*, "WARNING, ReadLCIOHeader> number_of_Time_bins not found" PRINT*, "Bit LCIO_TPCBIT_RAW is set but first 10 events have no raw data" PRINT*, "Enter number_of_Time_bins now, or 0:" READ*,nTb IF( nTb > 0 )THEN nTbin = nTb ELSE nTbin = 0 ENDIF ENDIF print*,"nTbin",nTbin ! reopen the file and start again CALL OpenReadLCIO(currentFile,IOS) IF( IOS /= 0 )THEN WRITE(UNIT=IOErr,FMT=*) "ERROR, ReadLCIOHeader> cant reopen input file:" WRITE(UNIT=IOErr,FMT=*) currentFile STOP ENDIF CALL ReadLCIOComment(chComment,chDate,IOS) IF( IOS /= 0 )THEN ! no runheader - reopen file CALL OpenReadLCIO(currentFile,IOS) IF( IOS /= 0 )THEN WRITE(UNIT=IOErr,FMT=*) "ERROR, ReadLCIOHeader> cant reopen input file:" WRITE(UNIT=IOErr,FMT=*) currentFile STOP ENDIF ENDIF END SUBROUTINE ReadLCIOHeader SUBROUTINE ReadLCIOEvent(IERR) INTEGER,INTENT(OUT) :: IERR CALL ReadLCIONextEvent(IERR) END SUBROUTINE ReadLCIOEvent END MODULE DataFormats