SUBROUTINE OVERRIDE(LINE,ERROR)

  USE mira

  IMPLICIT NONE

  INTEGER           :: firstIFB, ier, ifb, j, lastIFB, nbd, nc, &
                       npix, nrecords
  REAL*4            :: beamEfficiency, forwardEfficiency, gainImage
  REAL*8            :: tmpHotLoad, tmpColdLoad, tamb, pamb
  CHARACTER(LEN=1)  :: ch
  CHARACTER(LEN=10) :: string 
  CHARACTER(LEN=20) :: tmpString,tmpSwitchmode
  CHARACTER(LEN=*)  :: line
  LOGICAL           :: error
  LOGICAL           :: noSky
  LOGICAL           :: SIC_PRESENT
  LOGICAL           :: updateColdLoad, updateHotLoad, updateBeamEff,         &
 &                     updateForwEff, updateGainImage, updateTamb,           &
 &                     updatePamb

  updateColdLoad  = .false.
  updateHotLoad   = .false.
  updateBeamEff   = .false.
  updateForwEff   = .false.
  updateGainImage = .false.
  updateTamb      = .false.
  updatePamb      = .false.


  if (SIC_PRESENT(2,0)) then
     if (allocated(newpar)) then
        do j = 1, size(newpar)
           call freeNewpar(newpar(j),error)
        enddo
     endif
     deallocate(newpar,stat=ier)
     overrideFlag(1:7) = .false. 
     call GAGOUT('I-OVERRIDE: calibrations parameters changed.')
     call GAGOUT('            Please read in a calibration scan.')
     return
  endif

  if (.not.SIC_PRESENT(0,1)) then
     call GAGOUT('W-OVERRIDE: no keyword specified. Valid keywords are: '//  &
 &               'tempload, efficiency')
     return
  endif
  call SIC_CH(line,0,1,string,nc,.true.,error)
  call SIC_UPPER(string)

  if (SIC_PRESENT(1,1)) then

     call SIC_CH(line,1,1,ch,nc,.true.,error)
     call SIC_UPPER(ch)
     if (ch.eq.'A') then
        firstIFB = 1
        if (associated(scan)) then 
          lastIFB = scan%header%nfebe
        else
          call GAGOUT('W-OVERRIDE: pointer not associated. Please read a scan.')
          return
        endif
     else 
        call SIC_I4(line,1,1,ifb,.false.,error)
        firstIFB = ifb 
        lastIFB = ifb
     endif

  else

     firstIFB = 1
     lastIFB = 1
     call GAGOUT('W-OVERRIDE: no frontend/backend number specified. Set to 1.')

  endif

  if (index(string,'TEMP').ne.0) then

     if (SIC_PRESENT(0,2)) then
        call SIC_CH(line,0,2,ch,nc,.true.,error)
        if (ch.ne.'*') then
           updateColdLoad = .true.
           call SIC_R8(line,0,2,tmpColdLoad,.false.,error)
        endif
     endif

     if (SIC_PRESENT(0,3)) then
        call SIC_CH(line,0,3,ch,nc,.true.,error)
        if (ch.ne.'*') then
           updateHotLoad = .true.
           call SIC_R8(line,0,3,tmpHotLoad,.false.,error)
        endif
     endif

  else if (index(string,'EFF').ne.0) then

     if (SIC_PRESENT(0,2)) then
        call SIC_CH(line,0,2,ch,nc,.true.,error)
        if (ch.ne.'*') then
           updateForwEff = .true.
           call SIC_R4(line,0,2,forwardEfficiency,.false.,error)
        endif
     endif

     if (SIC_PRESENT(0,3)) then
        call SIC_CH(line,0,3,ch,nc,.true.,error)
        if (ch.ne.'*') then
           updateBeamEff = .true.
           call SIC_R4(line,0,3,beamefficiency,.false.,error)
        endif
     endif

  else if (index(string,'GAIN').ne.0) then

     if (SIC_PRESENT(0,2)) then
        call SIC_R4(line,0,2,gainImage,.false.,error)
        updateGainImage = .true.
     endif

  else if (index(string,'TAMB').ne.0) then

     if (SIC_PRESENT(0,2)) then
        call SIC_CH(line,0,2,ch,nc,.true.,error)
        if (ch.ne.'*') then
           updateTamb = .true.
           call SIC_R8(line,0,2,tamb,.false.,error)
        endif
     endif

     if (SIC_PRESENT(0,3)) then
        call SIC_CH(line,0,3,ch,nc,.true.,error)
        if (ch.ne.'*') then
           updatePamb = .true.
           call SIC_R8(line,0,3,pamb,.false.,error)
        endif
     endif

  else 

     call GAGOUT('W-OVERRIDE: no such keyword. Valid keywords are: '//  &
 &               'tempload, efficiency, gain')
     return

  endif

  if (count(overrideFlag).eq.0) then
     if (allocated(newPar)) deallocate(newPar,stat=ier)
     allocate(newPar(scan%header%nfebe),stat=ier)
  endif

  if (updateColdLoad) then
     if (.not.associated(mon)) then
        call GAGOUT('W-OVERRIDE: pointer not associated. Please read a scan.')
        return
     endif
     do ifb = firstIFB, lastIFB
        mon(ifb)%data%thotcold(1,2) = tmpColdLoad
     enddo
     overrideFlag(1) = .true.
  endif

  if (updateHotLoad) then
     if (.not.associated(mon)) then
        call GAGOUT('W-OVERRIDE: pointer not associated. Please read a scan.')
        return
     endif
     do ifb = firstIFB, lastIFB
        mon(ifb)%data%thotcold(1,1) = tmpHotLoad
     enddo
     overrideFlag(2) = .true.
  endif

  if (updateHotLoad.or.updateColdLoad) then
     do ifb = 1, scan%header%nfebe
        if (allocated(newpar(ifb)%thotcold))                              &
 &         deallocate(newpar(ifb)%thotcold,stat=ier)
        allocate(newpar(ifb)%thotcold(1,2),stat=ier)
        newpar(ifb)%thotcold = mon(ifb)%data%thotcold
     enddo
  endif

  if (updateTamb) then
     if (.not.associated(mon)) then
        call GAGOUT('W-OVERRIDE: pointer not associated. Please read a scan.')
        return
     endif
     do ifb = firstIFB, lastIFB
        mon(ifb)%data%tamb_p_humid(1,1) = tamb 
     enddo
     overrideFlag(6) = .true.
  endif

  if (updatePamb) then
     if (.not.associated(mon)) then
        call GAGOUT('W-OVERRIDE: pointer not associated. Please read a scan.')
        return
     endif
     do ifb = firstIFB, lastIFB
        mon(ifb)%data%tamb_p_humid(1,2) = pamb 
     enddo
     overrideFlag(7) = .true.
  endif

  if (updateTamb.or.updatePamb) then
     do ifb = 1, scan%header%nfebe
        if (allocated(newpar(ifb)%tamb_p_humid))                              &
 &         deallocate(newpar(ifb)%tamb_p_humid,stat=ier)
        allocate(newpar(ifb)%tamb_p_humid(1,3),stat=ier)
        newpar(ifb)%tamb_p_humid = mon(ifb)%data%tamb_p_humid
     enddo
  endif


  if (updateForwEff) then
     do ifb = firstIFB, lastIFB
        if (.not.associated(febe)) then
          call GAGOUT('W-OVERRIDE: pointer not associated. Please read a scan.')
          return
        endif
        npix = febe(ifb)%header%febefeed
        nbd = febe(ifb)%header%febeband
        febe(ifb)%data%etafss(1:npix,1:nbd) = forwardEfficiency
     enddo
     do ifb = 1, scan%header%nfebe
        npix = febe(ifb)%header%febefeed
        nbd = febe(ifb)%header%febeband
        if (allocated(newpar(ifb)%etafss))                                   &
 &         deallocate(newpar(ifb)%etafss,stat=ier)
        allocate(newpar(ifb)%etafss(npix,nbd),stat=ier)
        newpar(ifb)%etafss = febe(ifb)%data%etafss 
     enddo
     overrideFlag(3) = .true.
  endif

  if (updateBeamEff) then
     if (.not.associated(scan)) then
        call GAGOUT('W-OVERRIDE: pointer not associated. Please read a scan.')
        return
     endif
     do ifb = firstIFB, lastIFB
        if (.not.associated(febe)) then
          call GAGOUT('W-OVERRIDE: pointer not associated. Please read a scan.')
          return
        endif
        npix = febe(ifb)%header%febefeed
        nbd = febe(ifb)%header%febeband
        febe(ifb)%data%beameff(1:npix,1:nbd) = beamEfficiency
     enddo
     do ifb = 1, scan%header%nfebe
        npix = febe(ifb)%header%febefeed
        nbd = febe(ifb)%header%febeband
        if (allocated(newpar(ifb)%beameff))                           &
 &          deallocate(newpar(ifb)%beameff,stat=ier)
        allocate(newpar(ifb)%beameff(npix,nbd),stat=ier)
        newpar(ifb)%beameff = febe(ifb)%data%beameff
     enddo
     overrideFlag(4) = .true.
  endif

  if (updateGainImage) then
     if (.not.associated(scan)) then
        call GAGOUT('W-OVERRIDE: pointer not associated. Please read a scan.')
        return
     endif
     do ifb = firstIFB, lastIFB
        if (.not.associated(febe)) then
          call GAGOUT('W-OVERRIDE: pointer not associated. Please read a scan.')
          return
        endif
        npix = febe(ifb)%header%febefeed
        nbd = febe(ifb)%header%febeband
        febe(ifb)%data%gainimag(1:npix,1:nbd) = gainImage 
     enddo
     do ifb = 1, scan%header%nfebe
        if (allocated(newpar(ifb)%gainimag))                                  &
 &          deallocate(newpar(ifb)%gainimag,stat=ier)
        allocate(newpar(ifb)%gainimag(npix,nbd),stat=ier)
        newpar(ifb)%gainimag = febe(ifb)%data%gainimag
     enddo
     overrideFlag(5) = .true.
  endif

  if (.not.updateColdLoad.and..not.updateHotLoad.and..not.updateForwEff.and.  &
 &    .not.updateBeamEff.and..not.updateGainImage.and..not.updateTamb.and.    &
 &    .not.updatePamb) then
     call gagout('I-OVERRIDE: please specify at least one value, or * to '    &
 &               //'leave it unchanged.')
     return
  endif

  if (updateColdLoad.or.updateHotLoad) then
      write(*,*) ' ' 
      write(*,10) 'idFe', 'THotLoad', 'TColdLoad', 'idBe'
      write(*,20) '---- [Kelvin] ----'
      write(*,30) '--------------------------------' 
      do ifb = firstIFB, lastIFB
         j = index(febe(ifb)%header%febe,' ')
         write(*,40) febe(ifb)%header%febe(1:5),mon(ifb)%data%thotcold(1,1),   &
 &                   mon(ifb)%data%thotcold(1,2), febe(ifb)%header%febe(j+1:j+8)
      enddo
      write(*,*) ' ' 
  endif

  if (updateForwEff.or.updateBeamEff) then
      write(*,*) ' ' 
      write(*,50) 'idFe', 'forwardEff', 'beamEff', 'idBe'
      write(*,70) '--------------------------------------' 
      do ifb = firstIFB, lastIFB
         j = index(febe(ifb)%header%febe,' ')
         write(*,80) febe(ifb)%header%febe(1:5),febe(ifb)%data%etafss(1,1),   &
 &                   febe(ifb)%data%beameff(1,1),febe(ifb)%header%febe(j+1:j+8)
      enddo
      write(*,*) ' ' 
  endif

  if (updateGainImage) then
      write(*,*) ' ' 
      write(*,120) 'idFe', 'gainImage', 'idBe'
      write(*,140) '-----------------------------' 
      do ifb = firstIFB, lastIFB
         j = index(febe(ifb)%header%febe,' ')
         write(*,150) febe(ifb)%header%febe(1:5),febe(ifb)%data%gainimag(1,1), &
 &                    febe(ifb)%header%febe(j+1:j+8)
      enddo
      write(*,*) ' ' 
  endif

  noSky = count(array(1)%data(1)%iswitch.eq.'SKY').eq.0
  tmpString = scan%header%scantype
  call sic_upper(tmpString)

  if (index(tmpString,'CAL').ne.0.and..not.noSky) then
     write(*,*)  ' '
     write(*,90) 'idFe', 'THotLoad', 'TColdLoad', 'idBe',               &
 &                  'Pix', 'recTemp', 'sysTemp', 'calTemp',             &
 &                  'tauZenith', 'pwv'
     write(*,100) '---- [Kelvin] ----','------ [Kelvin] -------',       &
 &                  '[Neper]','[mm]'
     write(*,110) '----------------------------------------------'      &
 &                //'---------------------------'
     
     do ifb = 1, scan%header%nfebe
        call do_trx(ifb,error)
        nrecords = maxval(data(ifb)%data%integnum)
        call do_tcal(ifb,1,nrecords,.false.,0.,.false.,0.,error)
     enddo
     write(*,*)  ' '
  else if (index(tmpString,'CAL').eq.0) then
     call gagout('I-OVERRIDE: please recalibrate with new parameter(s).')
  endif

10  FORMAT(T6,A4,T11,A8,T20,A9,T30,A4)
20  FORMAT(T11,A18)
30  FORMAT(T6,A32)
40  FORMAT(T6,A5,T11,F8.3,T20,F9.3,T30,A8)
50  FORMAT(T6,A4,T13,A10,T24,A7,T34,A4)
60  FORMAT(T13,A18)
70  FORMAT(T6,A36)
80  FORMAT(T6,A5,T18,F5.3,T26,F5.3,T34,A8)
90  FORMAT(T6,A4,T11,A8,T20,A9,T30,A4,T36,A3,T41,A7,T49,A7,T57,A7,T65,A9,T75,A3)
100 FORMAT(T11,A18,T41,A23,T66,A7,T75,A4)
110 FORMAT(T6,A73)
120 FORMAT(T6,A4,T16,A9,T27,A4)
130 FORMAT(T17,A7)
140 FORMAT(T6,A27)
150  FORMAT(T6,A5,T18,F5.3,T26,A8)


  RETURN

END SUBROUTINE OVERRIDE

subroutine freeNewpar(var,error)

  use mira
  implicit none

  type(override_data) :: var
  logical       :: error

  integer       :: ier

  if (allocated(var%thotcold))     deallocate(var%thotcold,stat=ier)
  if (allocated(var%etafss))       deallocate(var%etafss,stat=ier)
  if (allocated(var%beameff))      deallocate(var%beameff,stat=ier)
  if (allocated(var%gainimag))     deallocate(var%gainimag,stat=ier)
  if (allocated(var%tamb_p_humid)) deallocate(var%tamb_p_humid,stat=ier)

end subroutine freeNewpar


subroutine do_trx(ifb,error)

  USE mira

  IMPLICIT NONE

  INTEGER                            :: ifb
  LOGICAL                            :: error
  CHARACTER(len=20)                  :: switchMode

  INTEGER                            :: ichan, ipix, ibd, ier, i1, i2,&
                                        nbd, nchan, nfb, npix
  REAL                               :: pcoldsignal, photsignal
  LOGICAL, DIMENSION(:), ALLOCATABLE :: calMask

  nbd = febe(ifb)%header%febeband
  nfb = scan%header%nfebe
  npix = febe(ifb)%header%febefeed
  switchMode = febe(ifb)%header%swtchmod
  call sic_upper(switchMode)
  !
  pixelLoop: do ipix = 1, npix
     !
     baseBandLoop: do ibd = 1, nbd
        !
        nchan = array(ifb)%header(ibd)%usedchan
        i1 = array(ifb)%header(ibd)%dropchan+1
        i2 = array(ifb)%header(ibd)%dropchan   &
             +array(ifb)%header(ibd)%usedchan
        allocate(calmask(i2-i1+1),stat=ier)
        if (calbychannel) then
           calmask=gains(ifb)%phot(ibd,ipix,i1:i2).ne.blankingraw   &
                   .and.   &
                   gains(ifb)%pcold(ibd,ipix,i1:i2).ne.blankingraw
           do ichan =  i1, i2
              if (calmask(ichan)) then
                 photsignal = gains(ifb)%phot(ibd,ipix,ichan)
                 pcoldsignal= gains(ifb)%pcold(ibd,ipix,ichan)
                 gains(ifb)%trx(ibd,ipix,ichan)   &
                 = (photsignal*mon(ifb)%data%thotcold(1,2)   &
                    -pcoldsignal*mon(ifb)%data%thotcold(1,1))   &
                   /(pcoldsignal-photsignal)
              else
                 gains(ifb)%trx(ibd,ipix,ichan) = -1.
              endif
           enddo
        else
           calmask = gains(ifb)%phot(ibd,ipix,i1:i2).ne.blankingraw
           photsignal = sum(gains(ifb)%phot(ibd,ipix,i1:i2),calmask)  &
                       /count(calmask)
           calmask = gains(ifb)%pcold(ibd,ipix,i1:i2).ne.blankingraw
           pcoldsignal =sum(gains(ifb)%pcold(ibd,ipix,i1:i2),calmask) &
                       /count(calmask)
           gains(ifb)%trx(ibd,ipix,1)   &
           = (photsignal*mon(ifb)%data%thotcold(1,2)   &
              -pcoldsignal*mon(ifb)%data%thotcold(1,1))   &
             /(pcoldsignal-photsignal)
        endif
        if (index(switchMode,'FREQ').ne.0) then
           calmask = gains(ifb+nfb)%phot(ibd,ipix,i1:i2).ne.blankingraw
           photsignal = sum(   &
                          gains(ifb+nfb)%phot(ibd,ipix,i1:i2),calmask &
                        )/count(calmask)
           calmask =gains(ifb+nfb)%pcold(ibd,ipix,i1:i2).ne.blankingraw
           pcoldsignal =sum(   &
                          gains(ifb+nfb)%pcold(ibd,ipix,i1:i2),calmask&
                        )/count(calmask)
           gains(ifb+nfb)%trx(ibd,ipix,1)   &
           = (photsignal*mon(ifb)%data%thotcold(1,2)   &
              -pcoldsignal*mon(ifb)%data%thotcold(1,1))   &
             /(pcoldsignal-photsignal)
        endif
        deallocate(calMask,stat=ier)
     enddo baseBandLoop
   enddo pixelLoop
   !
end subroutine do_trx
