MODULE TPCio
   USE IOunits
   USE Threshold
   USE Space
   USE TPCdata
   USE DataFormats
   USE TPCpaw,   only : PAWini,PAWend
   USE MyMinuit, only : MINini,MINend
   PRIVATE
   
! IOinitialize(ChVersion,Event_first,Event_last,nEvents,eventList)
! IOend()
   PUBLIC :: IOinitialize,IOend
   
! OPENData(IERR)
! ReadHeader(chComment,chDate)
! ReadEvent(IERR)
! readCalibData()
   PUBLIC :: OPENData,ReadHeader,ReadEvent,readCalibData


   PRIVATE :: ReadInput,ReadLayout
   PRIVATE :: GetValue,GetAll,GetAllR,checkLayout
   
   INTEGER,SAVE,PRIVATE :: DataFormat=0
   
   CONTAINS
   
   SUBROUTINE IOinitialize(ChVersion,Event_first,Event_last,nEvents,eventList)
      CHARACTER(LEN=*),INTENT(IN) :: CHVersion
      INTEGER,INTENT(OUT) :: Event_first,Event_last,nEvents
      INTEGER,DIMENSION(:),INTENT(OUT) :: eventList
      INTEGER :: IOS,lengthCh,nFile,iFile,IERR
      CHARACTER(LEN=200) :: CHline
      CHARACTER(LEN=40) ::  & !!! no capital letters for PAW!!!
      CHPAW    ="tpcanalysis.rzntp",&
      CHMIN    ="TPCminuit.input",&
      CHMOUT   ="/dev/null",&
!      CHMOUT   ="TPCminuit.output",&
      CHMSAV   ="TPCminuit.save", &
      CHLAYOUT ="TPClayout.txt", &
      CHINPUT  ="TPCinput.txt" ,&
      CHFILES  ="TPCfiles.txt" , &
      CHDENSE  ="thisrun.dd"
      
      PRINT*,"******************************************************"
      PRINT*,"***  This is   F TPC ANALYZER                      ***"
      PRINT*,"***  Version ",CHVersion
      PRINT*,"***  -------------------------------------------   ***"

! get the runIN files from TPCfiles.txt file
      OPEN(UNIT=IOFiles,FILE=CHFILES,STATUS="OLD",ACTION="READ",&
         ACCESS="SEQUENTIAL",FORM="FORMATTED",POSITION="REWIND",IOSTAT=IOS)
      IF( IOS/=0 )THEN
         WRITE(UNIT=IOErr,FMT=*) "ERROR opening file ",CHFILES
         STOP
      ENDIF
     
      Event_first = 0
      Event_last  = 0
      nEvents = 0
      eventList = 0

      read_input : DO
         READ(UNIT=IOFiles,FMT="(A)",IOSTAT=IOS) CHline
         IF( IOS /= 0 ) THEN
            WRITE(UNIT=IOErr,FMT=*) "WARNING, IOinitialize> input data not read properly"
            EXIT read_input
         ENDIF
         SELECT CASE( CHline(1:1) )
            CASE( "*" ) 
               CYCLE read_input
            CASE( ">" ) 
               EXIT read_input
            CASE( "F" ) 
               READ(UNIT=CHline(2:200),FMT=*) nFile
            CASE( "R" ) 
               READ(UNIT=CHline(2:200),FMT=*) Event_first,Event_last
            CASE( "S" )
               CALL GetAll(CHline(2:200),eventList,nEvents)
         END SELECT
      ENDDO read_input
      
      ALLOCATE ( CHrunIN(nFile),STAT=IERR )
      IF( IERR /= 0 )THEN
         WRITE(UNIT=IOErr,FMT=*) "ERROR, IOinitialize> Cant allocate CHrunIN"
         STOP
      ENDIF
      DO iFile = 1,nFile
         READ(UNIT=IOFiles,FMT="(A)",IOSTAT=IOS) CHline
         IF( IOS /= 0 ) &
            WRITE(UNIT=IOErr,FMT=*) "WARNING, IOinitialize> IOFILES not read properly"
         lengthCh = len_trim(CHline)
         IF( lengthCh > len(CHrunIN(1)) )THEN
            WRITE(UNIT=IOErr,FMT=*)"ERROR, IOinitialize> Length of CHrunIN too small, change in DataFormats.f95"
            STOP
         ENDIF
         CHrunIN(iFile) = CHline(1:lengthCh)
      ENDDO
      
! which data format?
      lengthCh = len_trim(CHrunIN(1))
      IF( CHrunIN(1)(lengthCH-3:lengthCH) == ".mid" )THEN
         DataFormat = 1
      ELSEIF( CHrunIN(1)(lengthCH-2:lengthCH) == ".dd" )THEN
         DataFormat = 2
      ELSEIF( CHrunIN(1)(lengthCH-2:lengthCH) == ".mc" )THEN
         DataFormat = 3
      ELSEIF( CHrunIN(1)(lengthCH-5:lengthCH) == ".slcio" )THEN
         DataFormat = 4
      ELSE
         PRINT*,"Unknown data format. Supported formats:"
         PRINT*,".mid   :  MIDAS"
         PRINT*,".dd    :  DenseData"
         PRINT*,".mc    :  Monte Carlo"
         PRINT*,".slcio :  LCIO"
         STOP
      ENDIF
      
      PRINT*,"***  The following",nFile," run files will be processed:"
      DO iFile = 1,nFile
         PRINT*,CHrunIN(iFile)
      ENDDO
      IF( nFile == 1 )THEN
         IF( nEvents /= 0 )THEN
            PRINT*,"***  The following list of events will be processed:"
            PRINT*,eventList(1:nEvents)
         ELSEIF( Event_first/=0 .OR. Event_last/=0 )THEN
            PRINT*,"***  Events in the range",Event_first,"to",Event_last,"will be processed:"
         ENDIF   
      ELSE
         Event_first = 0
         Event_last  = 0
         nEvents = 0
      ENDIF      

      CALL PAWini(CHPAW)
      CALL MINini(IOMIN,CHMIN,IOMOUT,CHMOUT,IOMSAV,CHMSAV)

      OPEN(UNIT=IOLayout,FILE=CHLAYOUT,STATUS="OLD",ACTION="READ",&
         ACCESS="SEQUENTIAL",FORM="FORMATTED",POSITION="REWIND",IOSTAT=IOS)
      IF( IOS/=0 )THEN
         WRITE(UNIT=IOErr,FMT=*) "ERROR opening file ",CHLAYOUT
         STOP
      ENDIF
      OPEN(UNIT=IOInput,FILE=CHINPUT,STATUS="OLD",ACTION="READ",&
         ACCESS="SEQUENTIAL",FORM="FORMATTED",POSITION="REWIND",IOSTAT=IOS)
      IF( IOS/=0 )THEN
         WRITE(UNIT=IOErr,FMT=*) "WARNING cant open file ",CHINPUT
         WRITE(UNIT=IOErr,FMT=*) "Will use default settings"
      ENDIF    

! read layout and allocate arrays
      CALL ReadLayout()
! read steering flags and thresholds
      CALL ReadInput()

      IF( LDData )THEN
      OPEN(UNIT=IODense,FILE=CHDENSE,STATUS="REPLACE",ACTION="WRITE",&
         ACCESS="SEQUENTIAL",FORM="UNFORMATTED",POSITION="REWIND",IOSTAT=IOS)
      IF( IOS/=0 )THEN
         WRITE(UNIT=IOErr,FMT=*) "ERROR opening file ",CHDENSE
         STOP
      ENDIF
      ENDIF
   END SUBROUTINE IOinitialize
   
   SUBROUTINE IOend()
      
      CLOSE(UNIT=IOLayout)
      CLOSE(UNIT=IOInput)
      CLOSE(UNIT=IOFiles)
      IF( LDData ) CLOSE(UNIT=IODense)
      
      CALL PAWend()
      CALL MINend()
   END SUBROUTINE IOend
   
   SUBROUTINE ReadInput()
      INTEGER :: IOS,IERR
      CHARACTER(LEN=80) :: ChTag,ChLine
      
! for safety allocate 0 size arrays per default
      ALLOCATE( AERRpar(0) )
      ALLOCATE( PRFdel(0) )
      ALLOCATE( trackWidthPar(0) )
      ALLOCATE( riseTimePar(0) )
      ALLOCATE( fallTimePar(0) )
      ALLOCATE( riseTimeGr(0) )
      ALLOCATE( fallTimeGr(0) )
      
! by default no bias correction -> array size=0
      ALLOCATE( iRowBias(nRows) )
      iRowBias = 0
      ALLOCATE( biasX(0) )
      ALLOCATE( biasData(0,0) )

! by default calculate pedestals event-by-event
      LPedestalEvent = .TRUE.
      ALLOCATE( Pedestal(nGroups),STAT=IERR )
      IF( IERR /= 0 )THEN
         WRITE(UNIT=IOErr,FMT=*) "ERROR, ReadInput> cant allocate Pedestal"
         STOP
      ENDIF
      ALLOCATE ( gainCor(nGroups),STAT=IERR )
      IF( IERR /= 0 )THEN
         WRITE(UNIT=IOErr,FMT=*) "ERROR, ReadInput> cant allocate gainCor"
         STOP
      ENDIF
      gainCor = 1.0  
          
      DO
         READ(UNIT=IOinput,FMT="(A)",IOSTAT=IOS)ChTag
         IF( IOS /= 0 )EXIT
         
         SELECT CASE( ChTag(1:1) )
            CASE( "*"," " ) 
            CASE( ">" )
               READ(UNIT=IOinput,FMT="(A)",IOSTAT=IOS)ChLine
               IF( IOS /= 0)THEN
                  WRITE(UNIT=IOErr,FMT=*) "ERROR, ReadInput> Values are missing for ",ChTag
                  EXIT
               ENDIF
               CALL GetValue(ChTag,ChLine)
            CASE default
               WRITE(UNIT=IOErr,FMT=*) "ERROR, ReadInput> strange Tag: ",ChTag
         END SELECT
      ENDDO  
       
      PRINT*,"*** ---------------------------------------------- ***"
     
      IF( Lcalib )THEN
      PRINT*,"***   This is a calibration run                    ***"
      ELSEIF( LDData )THEN
      PRINT*,"***   Writing DenseData                            ***"
      ELSE
      PRINT*,"***   This is an analysis run                      ***"
      ENDIF
         
      PRINT*,"******************************************************"
      PRINT*,"***  Start analysis ............                   ***"
   END SUBROUTINE ReadInput
   SUBROUTINE GetValue(ChTag,ChLine)
      USE Threshold
      CHARACTER(LEN=80),INTENT(IN) :: ChTag,ChLine
      INTEGER :: nVal,IOS
      INTEGER,PARAMETER :: maxVal=20
!      INTEGER,DIMENSION(maxVal) :: value
      REAL,DIMENSION(maxVal) :: valueR
      
      IOS = 0
      SELECT CASE( ChTag(3:20) )
         CASE( "Lcalib             " )
            READ(UNIT=ChLine,FMT=*,IOSTAT=IOS) Lcalib
         CASE( "Lcalhist           " )
            READ(UNIT=ChLine,FMT=*,IOSTAT=IOS) Lcalhist
         CASE( "Lplot              " )
            READ(UNIT=ChLine,FMT=*,IOSTAT=IOS) Lplot
         CASE( "LDData             " )
            READ(UNIT=ChLine,FMT=*,IOSTAT=IOS) LDData
         CASE( "LoldDD             " )
            READ(UNIT=ChLine,FMT=*,IOSTAT=IOS) LoldDD
         CASE( "LPRF               " )
            READ(UNIT=ChLine,FMT=*,IOSTAT=IOS) LPRF
         CASE( "FitType            " )
            READ(UNIT=ChLine,FMT=*,IOSTAT=IOS) FitType
         CASE( "minSignal          " )
            READ(UNIT=ChLine,FMT=*,IOSTAT=IOS) minSignal
         CASE( "smallSignal        " )
            READ(UNIT=ChLine,FMT=*,IOSTAT=IOS) smallSignal
         CASE( "minSignalVeto      " )
            READ(UNIT=ChLine,FMT=*,IOSTAT=IOS) minSignalVeto
         CASE( "minSignalRow       " )
            READ(UNIT=ChLine,FMT=*,IOSTAT=IOS) minSignalRow
         CASE( "minSignalCalib     " )
            READ(UNIT=ChLine,FMT=*,IOSTAT=IOS) minSignalCalib
         CASE( "minDistPad         " )
            READ(UNIT=ChLine,FMT=*,IOSTAT=IOS) minDistPad
         CASE( "minHitTrack        " )
            READ(UNIT=ChLine,FMT=*,IOSTAT=IOS) minHitTrack
         CASE( "driftVelocity      " )
            READ(UNIT=ChLine,FMT=*,IOSTAT=IOS) tBin0,tBin2ns,vDrift
         CASE( "AERRpar            " )
            CALL GetAllR(ChLine,valueR,nVal)
            DEALLOCATE ( AERRpar )
            ALLOCATE ( AERRpar(nVal) )
            AERRpar = valueR(1:nVal)
         CASE( "PRF                " )
            READ(UNIT=ChLine,FMT=*,IOSTAT=IOS) PRFa,PRFb
         CASE( "PRFdel             " )
            CALL GetAllR(ChLine,valueR,nVal)
            DEALLOCATE ( PRFdel )
            ALLOCATE ( PRFdel(nVal) )
            PRFdel = valueR(1:nVal)
         CASE( "trackWidth         " )
            CALL GetAllR(ChLine,valueR,nVal)
            DEALLOCATE ( trackWidthPar )
            ALLOCATE ( trackWidthPar(nVal) )
            trackWidthPar = valueR(1:nVal)
         CASE( "riseTime           " )
            CALL GetAllR(ChLine,valueR,nVal)
            DEALLOCATE ( riseTimePar )
            ALLOCATE ( riseTimePar(nVal) )
            riseTimePar = valueR(1:nVal)
         CASE( "fallTime           " )
            CALL GetAllR(ChLine,valueR,nVal)
            DEALLOCATE ( fallTimePar )
            ALLOCATE ( fallTimePar(nVal) )
            fallTimePar = valueR(1:nVal)
         CASE( "ADC2Electron       " )
            READ(UNIT=ChLine,FMT=*,IOSTAT=IOS) ADC2Electron
         CASE( "pNoise             " )
            READ(UNIT=ChLine,FMT=*,IOSTAT=IOS) pNoise
         CASE( "Tshift             " )
            READ(UNIT=ChLine,FMT=*,IOSTAT=IOS) Tshift
         CASE default
            WRITE(UNIT=IOErr,FMT=*) "ERROR, GetValue> unknown input tag ",ChTag(3:20)
      END SELECT
      IF( IOS/=0 ) &
         WRITE(UNIT=IOErr,FMT=*) "WARNING> GetValue", ChTag(1:20) 
   END SUBROUTINE GetValue
   SUBROUTINE GetAll(ChLine,value,nVal)
      CHARACTER(LEN=*),INTENT(IN) :: ChLine
      INTEGER,DIMENSION(:),INTENT(OUT) :: value
      INTEGER,INTENT(OUT) :: nVal
      INTEGER :: IOS,iVal,Blank,noBlank
      
      iVal  = 0
      Blank = 0
      
      Search : DO
         noB_loop : DO noBlank = Blank+1,len(ChLine)
            IF( ChLine(noBlank:noBlank) /= " " ) EXIT noB_loop
         ENDDO noB_loop
         IF( noBlank >= len(ChLine) ) EXIT Search
         B_loop : DO Blank = noBlank+1,len(ChLine)
            IF( ChLine(Blank:Blank) == " " ) EXIT B_loop
         ENDDO B_loop
      
         iVal = iVal + 1
         IF( iVal > SIZE(value) ) THEN
            WRITE(UNIT=IOErr,FMT=*) "ERROR, GetAll> too many input values"
            EXIT Search
         ENDIF
         READ(UNIT=ChLine(noBlank:Blank),FMT=*,IOSTAT=IOS) value(iVal)
         IF( IOS /= 0 )THEN
            iVal = iVal - 1
            EXIT Search
         ENDIF
      ENDDO Search
      
      nVal = iVal
   END SUBROUTINE GetAll
   SUBROUTINE GetAllR(ChLine,value,nVal)
      CHARACTER(LEN=*),INTENT(IN) :: ChLine
      REAL,DIMENSION(:),INTENT(OUT) :: value
      INTEGER,INTENT(OUT) :: nVal
      INTEGER :: IOS,iVal,Blank,noBlank
      
      iVal  = 0
      Blank = 0
      
      Search : DO
         noB_loop : DO noBlank = Blank+1,len(ChLine)
            IF( ChLine(noBlank:noBlank) /= " " ) EXIT noB_loop
         ENDDO noB_loop
         IF( noBlank >= len(ChLine) ) EXIT Search
         B_loop : DO Blank = noBlank+1,len(ChLine)
            IF( ChLine(Blank:Blank) == " " ) EXIT B_loop
         ENDDO B_loop
      
         iVal = iVal + 1
         IF( iVal > SIZE(value) ) THEN
            WRITE(UNIT=IOErr,FMT=*) "ERROR, GetAllR> too many input values"
            EXIT Search
         ENDIF
         READ(UNIT=ChLine(noBlank:Blank),FMT=*,IOSTAT=IOS) value(iVal)
         IF( IOS /= 0 )THEN
            iVal = iVal - 1
            EXIT Search
         ENDIF
      ENDDO Search
      
      nVal = iVal
   END SUBROUTINE GetAllR
   
   SUBROUTINE ReadLayout()      
      INTEGER :: I,iPad,iGroup,iRow,IERR,mapNumber,nX,nY,iX,iY
      LOGICAL,ALLOCATABLE,DIMENSION(:,:) :: GisinR
      CHARACTER(LEN=1),ALLOCATABLE,DIMENSION(:,:) :: bits
      
      READ(UNIT=IOLayout,FMT=*) nPads
      READ(UNIT=IOLayout,FMT=*) nGroups
      READ(UNIT=IOLayout,FMT=*) nRows
      READ(UNIT=IOLayout,FMT=*) maxPinGroup
      READ(UNIT=IOLayout,FMT=*) maxPinRow
      READ(UNIT=IOLayout,FMT=*) maxGinRow
      READ(UNIT=IOLayout,FMT=*)
      READ(UNIT=IOLayout,FMT=*)
      READ(UNIT=IOLayout,FMT=*)
      READ(UNIT=IOLayout,FMT=*)
      
      ALLOCATE ( GisinR(nGroups,nRows),STAT=IERR )
     
       IF( IERR /= 0 )THEN
         WRITE(UNIT=IOErr,FMT=*) "ERROR, ReadLayout> cant allocate GisinR"
         STOP
      ENDIF
      CALL AllocArrays()
      nPadsinGroup = 0.0  
      nPadsinRow   = 0.0  
      nGroupsinRow = 0.0
      GisinR = .FALSE.
      
      DO iPad=1,nPads
         CALL ReadChannel(iPad)
         iGroup = PadGroup(iPad)
         iRow   = PadRow(iPad)
         
! fill nPadsinGroup and iPadofGroup    
         nPadsinGroup(iGroup) = nPadsinGroup(iGroup) +1
         IF( nPadsinGroup(iGroup) > maxPinGroup )THEN
            WRITE(UNIT=IOErr,FMT=*) "ERROR: too many pads in group,",iGroup
            STOP
         ENDIF
         iPadofGroup(nPadsinGroup(iGroup),iGroup) = iPad

! fill nPadsinRow and iPadofRow
         nPadsinRow(iRow) = nPadsinRow(iRow) + 1
         IF( nPadsinRow(iRow) > maxPinRow )THEN
            WRITE(UNIT=IOErr,FMT=*) "ERROR: too many pads in row",iRow
            STOP
         ENDIF
         iPadofRow(nPadsinRow(iRow),iRow) = iPad

! fill nGroupsinRow and iGroupofRow
         IF( .NOT.GisinR(iGroup,iRow) )THEN
            nGroupsinRow(iRow) = nGroupsinRow(iRow) + 1
            IF( nGroupsinRow(iRow) > maxGinRow )THEN
               WRITE(UNIT=IOErr,FMT=*) "ERROR: too many groups in row",iRow
               STOP
            ENDIF
            iGroupofRow(nGroupsinRow(iRow),iRow) = iGroup
            GisinR(iGroup,iRow) = .TRUE.
         ENDIF
      ENDDO

! read in the bitmaps for grid_type
      CALL AllocBitMap(NumMaps)
      
      ALLOCATE( bits(0,0) )
      DO I=1,NumMaps
         READ(UNIT=IOLayout,FMT=*)mapNumber,nX,nY
         IF( I/=mapNumber )THEN
            WRITE(UNIT=IOErr,FMT=*) "ERROR: Please give bitmaps in sequence"
            STOP
         ENDIF
         DEALLOCATE(bits)
         ALLOCATE( bits(nX,nY) )
      
         DO iY=1,nY
         DO iX=1,nX
            READ(UNIT=IOLayout,FMT="(A1)",ADVANCE="no") bits(iX,iY)
         ENDDO
         READ(UNIT=IOLayout,FMT=*)
         ENDDO
         
         CALL FillBitMap(mapNumber,bits)
      ENDDO
     
      CALL checkLayout()
   END SUBROUTINE ReadLayout 
      
   SUBROUTINE checkLayout()
! check that pads don't overlap
   END SUBROUTINE checkLayout 

! Wrapper: INPUT of data files ---------------------------------
   SUBROUTINE OPENData(IERR)
      INTEGER,INTENT(OUT) :: IERR
      
      SELECT CASE (DataFormat)
      CASE (1)
! MIDAS data
         CALL OPENMIDAS(IERR)
      CASE (2)
! DenseData            
         CALL OPENDense(IERR)
      CASE (3)
! Monte Carlo           
         CALL OPENMIDAS(IERR)
      CASE (4)
! LCIO           
         CALL OPENLCIO(IERR)
      CASE DEFAULT
         PRINT*,"ERROR OPENData> unkown data format"
   END SELECT
   
   END SUBROUTINE OPENdata
   SUBROUTINE ReadHeader(chComment,chDate)
      CHARACTER(LEN=*),INTENT(OUT) :: chComment,chDate
      INTEGER :: IERR

      SELECT CASE (DataFormat)
      CASE (1)
! MIDAS data
         CALL ReadMIDASHeader(ChComment,ChDate)
      CASE (2)
! DenseData            
         CALL ReadDenseHeader(IERR,ChComment,ChDate)
      CASE (3)
! Monte Carlo            
         CALL ReadMCHeader(ChComment,ChDate)
      CASE (4)
! LCIO           
         CALL ReadLCIOHeader(ChComment,ChDate)
      CASE DEFAULT
         PRINT*,"ERROR ReadHeader> unkown data format"
      END SELECT

      DEALLOCATE ( nTbGroup )
      ALLOCATE ( nTbGroup(nGroups),STAT=IERR )
      IF( IERR /= 0 )THEN
         WRITE(UNIT=IOErr,FMT=*) "ERROR, ReadHeader> cant allocate nTbGroup, IERR = ",IERR
         STOP
      ENDIF
      nTbGroup = nTbin
      DEALLOCATE ( IADC )
      ALLOCATE ( IADC(nTbin,nGroups),STAT=IERR )
      IF( IERR /= 0 )THEN
         WRITE(UNIT=IOErr,FMT=*) "ERROR, ReadHeader> cant allocate IADC, IERR = ",IERR
         STOP
      ENDIF
      DEALLOCATE ( ADC )
      ALLOCATE ( ADC(nTbin,nGroups),STAT=IERR )
      IF( IERR /= 0 )THEN
         WRITE(UNIT=IOErr,FMT=*) "ERROR, ReadHeader> cant allocate ADC, IERR = ",IERR
         STOP
      ENDIF


   END SUBROUTINE ReadHeader
   SUBROUTINE ReadEvent(IERR)
      INTEGER,INTENT(OUT) :: IERR      
      CHARACTER(LEN=80) :: chComment,chDate
      
      SELECT CASE (DataFormat)
      CASE (1)
! MIDAS data
         CALL ReadMIDASEvent(IERR)
      CASE (2)
! DenseData            
         CALL ReadDenseEvent(IERR)
         IF( IERR>0 ) THEN
!           new run
            CALL ReadDenseHeader(IERR,ChComment,ChDate)
            IF( IERR ==0 )THEN
               PRINT*,"Run:",RunNumber," - ",trim(ChDate), &
                                       " / ",trim(ChComment)
               CALL ReadDenseEvent(IERR)
            ENDIF
         ENDIF
      CASE (3)
! Monte Carlo
         CALL ReadMCEvent(IERR)
      CASE (4)
! LCIO
         CALL ReadLCIOEvent(IERR)
      CASE DEFAULT
         PRINT*,"ERROR ReadEvent> unkown data format"
   END SELECT

   END SUBROUTINE ReadEvent
   
   SUBROUTINE readCalibData()
      INTEGER :: I,J,IOS,IERR,nRows_bias,nPkt_bias,dummy
      INTEGER,DIMENSION(:),ALLOCATABLE :: bRows
      CHARACTER(LEN=80) :: CHComment ,&
      CHPEDEST ="TPCpedestal.txt" ,&
      CHRTIME  ="TPCrtime.txt" ,&
      CHFTIME  ="TPCftime.txt" ,&
      CHGAIN   ="TPCgain.txt" ,&
      CHBIAS   ="TPCbias.txt"
      
      OPEN(UNIT=IOcalib,FILE=CHPEDEST,STATUS="OLD",ACTION="READ",&
         ACCESS="SEQUENTIAL",FORM="FORMATTED",POSITION="REWIND",IOSTAT=IOS)
      IF( IOS == 0 )THEN
         READ(UNIT=IOcalib,FMT="(A80)",IOSTAT=IOS) CHComment
         PRINT*,CHComment
         READ(UNIT=IOcalib,FMT=*,IOSTAT=IOS) Pedestal
         IF( IOS /= 0 ) PRINT*,"ERROR CalibData> reading Pedestals"
         LPedestalEvent = .FALSE.
      ELSE
         PRINT*,"Calculate Pedestals event-by-event"
      ENDIF
      CLOSE(UNIT=IOcalib)
      
      OPEN(UNIT=IOCalib,FILE=CHRTIME,STATUS="OLD",ACTION="READ",&
         ACCESS="SEQUENTIAL",FORM="FORMATTED",POSITION="REWIND",IOSTAT=IOS)
      IF( IOS == 0 )THEN
         DEALLOCATE ( riseTimeGr )
         ALLOCATE ( riseTimeGr(nGroups),STAT=IERR )
         IF( IERR /= 0 )THEN
            WRITE(UNIT=IOErr,FMT=*) "ERROR, readCalibData> cant allocate riseTimeGr"
            STOP
         ENDIF
         READ(UNIT=IOcalib,FMT="(A80)",IOSTAT=IOS) CHComment
         PRINT*,CHComment
         READ(UNIT=IOcalib,FMT=*,IOSTAT=IOS) riseTimeGr
         IF( IOS /= 0 ) PRINT*,"ERROR CalibData> reading rise times"
      ELSE
         IF( size(riseTimePar)>0 )THEN
            PRINT*,"Use parametrisation of risetime"
         ENDIF
      ENDIF
      CLOSE(UNIT=IOcalib)
      
      OPEN(UNIT=IOCalib,FILE=CHFTIME,STATUS="OLD",ACTION="READ",&
         ACCESS="SEQUENTIAL",FORM="FORMATTED",POSITION="REWIND",IOSTAT=IOS)
      IF( IOS == 0 )THEN
         DEALLOCATE ( fallTimeGr )
         ALLOCATE ( fallTimeGr(nGroups),STAT=IERR )
         IF( IERR /= 0 )THEN
            WRITE(UNIT=IOErr,FMT=*) "ERROR, readCalibData> cant allocate fallTimeGr"
            STOP
         ENDIF
         READ(UNIT=IOcalib,FMT="(A80)",IOSTAT=IOS) CHComment
         PRINT*,CHComment
         READ(UNIT=IOcalib,FMT=*,IOSTAT=IOS) fallTimeGr
         IF( IOS /= 0 ) PRINT*,"ERROR CalibData> reading fall times"
      ELSE
         IF( size(fallTimePar)>0 )THEN
            PRINT*,"Use parametrisation of falltime"
         ENDIF
      ENDIF
      CLOSE(UNIT=IOcalib)
      
      OPEN(UNIT=IOCalib,FILE=CHGAIN,STATUS="OLD",ACTION="READ",&
         ACCESS="SEQUENTIAL",FORM="FORMATTED",POSITION="REWIND",IOSTAT=IOS)
      IF( IOS == 0 )THEN
         READ(UNIT=IOcalib,FMT="(A80)") CHComment
         PRINT*,CHComment
         READ(UNIT=IOcalib,FMT=*,IOSTAT=IOS) gainCor
         IF( IOS /= 0 ) PRINT*,"ERROR CalibData> reading gain correction"
      ELSE
         PRINT*,"No gain correction"
      ENDIF
      CLOSE(UNIT=IOcalib)      

      OPEN(UNIT=IOCalib,FILE=CHBIAS,STATUS="OLD",ACTION="READ",&
         ACCESS="SEQUENTIAL",FORM="FORMATTED",POSITION="REWIND",IOSTAT=IOS)
      IF( IOS == 0 )THEN
         READ(UNIT=IOcalib,FMT="(A80)") CHComment
         PRINT*,CHComment
         READ(UNIT=IOcalib,FMT=*,IOSTAT=IOS) nRows_bias,nPkt_bias
         IF( IOS == 0 )THEN
            DEALLOCATE ( biasX )
            ALLOCATE   ( biasX(nPkt_bias),STAT=IERR )
            DEALLOCATE ( biasData )
            ALLOCATE   ( biasData(nPkt_bias,nRows_bias),STAT=IERR )

! bias data for which rows?  ->  biasData(:,iRowBias(iRow))
            ALLOCATE   ( bRows(nRows_bias),STAT=IERR )
            READ(UNIT=IOcalib,FMT=*,IOSTAT=IOS) dummy,bRows
            DO I=1,nRows_bias
               iRowBias(bRows(I)) = I
            ENDDO
            DEALLOCATE( bRows )
            
            DO I=1,nPkt_bias
               READ(UNIT=IOcalib,FMT=*,IOSTAT=IOS) biasX(I),(biasData(I,J),J=1,nRows_bias)
            ENDDO
         ELSE
            PRINT*,"ERROR readCalibData> reading bias data"
         ENDIF
      ELSE
         PRINT*,"No bias correction"
      ENDIF
      CLOSE(UNIT=IOcalib)      
   END SUBROUTINE readCalibData
   
END MODULE TPCio
