module mira 
!
  type primary_header
     integer naxis
     logical simple
     integer bitpix
     logical extend
     character telescop*13
     character origin*32
     character creator*32
     character mbftsver*11
  end type primary_header
!
  type scan_header
     character telescop*13
     real*8    sitelong
     real*8    sitelat
     real*4    siteelev
     character projid*12
     character obsid*12
     integer   scannum
     character date_obs*23
     real*8    mjd
     real*8    lst
     integer   nobs
     integer   nobstotal
     real*8    ut1utc
     real*8    taiutc
     real*8    etutc
     real*8    gpstai
     character ctype1*8
     character ctype2*8
     character radecsys*32
     real*4    equinox
     real*8    crval1
     real*8    crval2
     real*8    lonpole
     real*8    latpole
     character object*20
     real*8    longobj
     real*8    latobj
     real*8    longoff
     real*8    latoff
     character calcode*4
     logical   movefram
     real*8    peridate
     real*8    peridist
     real*8    longasc
     real*8    omega
     real*8    inclinat
     real*8    eccentr
     real*8    orbepoch
     real*8    orbeqnox
     real*8    distance
     character scantype*20
     character scanmode*20
     character scangeom*20
     character scandir*4
     integer   scanline
     integer   scanrpts
     real*8    scanlen
     real*8    scanxvel
     real*8    scantime
     real*8    scanxspc
     real*8    scanyspc
     real*8    scanskew
     real*8    scanpar1
     real*8    scanpar2
     character crocycle*20
     logical   zigzag
     integer   trandist
     integer   tranfreq
     integer   tranfocu
     logical   wobused
     real*8    wobthrow
     character wobdir*4
     real*4    wobcycle
     character wobmode*20
     integer   nfebe
     real*4    ia
     real*4    ca
     real*4    npae
     real*4    an
     real*4    aw
     real*4    ie
     real*4    ecec
     real*4    zflx 
  end type scan_header
!
  type scan_data
     real*8, dimension(:), pointer              :: longoff => null()
     real*8, dimension(:), pointer              :: latoff => null()
     character(len=32), dimension(:), pointer   :: febe => null()
  end type scan_data
!
  type febepar_header
     character   :: veloconv*8
     character   :: febe*32
     integer     :: scannum
     character   :: date_obs*23
     character   :: dewcabin*10
     character   :: dewrtmod*5
     real*4      :: dewang
     integer     :: febeband
     integer     :: febefeed 
     integer     :: nusefeed
     character   :: swtchmod*20
     character   :: widenar*6
     integer     :: nphases 
     real*4      :: frqoff1
     real*4      :: frqoff2
     real*4      :: frqthrow
     real*4      :: iarx
     real*4      :: carx
     real*4      :: ierx
     real*4      :: ifcenter
     real*4      :: ececrx
     real*4      :: zflxrx
  end type febepar_header
!
  type febepar_data
     integer, dimension(:),  pointer  :: usefeed => null()
     character, dimension(:), pointer :: feedtype => null()
     real*8, dimension(:), pointer    :: feedoffx => null()
     real*8, dimension(:), pointer    :: feedoffy => null()
     integer                          :: reffeed
     character, dimension(:), pointer :: polty => null()
     real*4, dimension(:), pointer    :: pola => null()
     real*4, dimension(:,:), pointer  :: apereff => null()
     real*4, dimension(:,:), pointer  :: beameff => null()
     real*4, dimension(:,:), pointer  :: etafss => null()
     real*4, dimension(:,:), pointer  :: hpbw => null()
     real*4, dimension(:,:), pointer  :: antgain  => null()
     real*4, dimension(:), pointer    :: bolcalfc => null()
     real*4, dimension(:,:), pointer  :: flatfiel => null()
     real*4, dimension(:,:), pointer  :: gainimag => null()
     real*4, dimension(:), pointer    :: gainele1  => null()
     real*4, dimension(:), pointer    :: gainele2 => null()
  end type febepar_data
!
  type arraydata_header
     character febe*32
     integer   baseband
     integer   scannum
     integer   obsnum
     character date_obs*23
     integer   channels
     integer   usedchan
     integer   dropchan
     real*8    freqres
     real*8    bandwid
     character molecule*20
     character transiti*20
     real*8    restfreq
     character sideband*3
     real*8    sbsep
     character ctyp4_1*8
     integer   crpx4_1
     integer   crvl4_1
     integer   cd3a_11
     character wcsnm4f*8
     character ctyp4f_2*8
     real*4    crpx4f_2
     real*8    crvl4f_2
     real*8    cd4f_21
     character cuni4f_2*8
     character spec4f_2*8
     character sobs4f_2*8
     character wcsnm4r*8
     character ctyp4r_2*8
     real*4    crpx4r_2
     real*8    crvl4r_2
     real*8    cd4r_21
     character cuni4r_2*8
     character spec4r_2*8
     character sobs4r_2*8
     real*4    vsou4r_2
     real*4    vsys4r_2
     real*8    restfreqO
  end type arraydata_header
!
  type arraydata_data
     real*8, dimension(:), pointer           :: mjd => null()
     real*8, dimension(:), pointer           :: integtim => null()
                                                         ! in MBFITS v.1.54 
                                                         ! removed from this
                                                         ! section (now in 
                                                         ! DATAPAR)
     character(len=4), dimension(:,:),pointer :: iswitch => null()
                                                         ! is in DATAPAR in 
                                                         ! MBFITS, for MIRA
                                                         ! more practical here
     real*8, dimension(:,:,:,:), pointer     :: data => null()
  end type arraydata_data
!
  type monitor_header
     integer                             :: scannum
     integer                             :: obsnum
     real*8, dimension(3)                :: iaobs_caobs_ieobs
     real*8, dimension(3)                :: focobs_x_y_z
     real*8, dimension(3)                :: phiobs_x_y_z
     character(len=23)                   :: date_obs
  end type monitor_header
!
  type monitor_data
     integer, dimension(:), pointer         :: subScan => null()
     integer, dimension(:), pointer         :: subScanFast => null()
     integer, dimension(:), pointer         :: subScanSubref => null()
     real*8, dimension(:), pointer          :: mjd => null()
     real*8, dimension(:), pointer          :: lst => null()
     character(len=30), dimension(:), pointer :: monpoint => null()
     real*8, dimension(:), pointer          :: monvalue => null()
     character(len=8), dimension(:), pointer:: monunits => null()
     real*8, dimension(:,:), pointer        :: antennadata => null()
     real*8, dimension(:,:), pointer        :: encoder_az_el => null()
     real*8, dimension(:,:), pointer        :: tracking_az_el => null()
     real*8, dimension(:), pointer          :: antenna_az_el => null()
     real*8, dimension(:), pointer          :: parangle => null()
     real*8, dimension(:), pointer          :: baslat => null()
     real*8, dimension(:), pointer          :: baslong  => null()
     real*8, dimension(:), pointer          :: longoff => null()
     real*8, dimension(:), pointer          :: latoff => null()
     real*8, dimension(:,:), pointer        :: tamb_p_humid => null()
     real*8, dimension(:,:), pointer        :: wind_dir_vavg_vmax => null()
     real*8, dimension(:,:), pointer        :: thotcold => null()
     real*8, dimension(:), pointer          :: refractio => null()
     real*8, dimension(:,:), pointer        :: focus_x_y_z => null()
     real*8, dimension(:,:), pointer        :: dfocus_x_y_z => null()
     real*8, dimension(:,:), pointer        :: phi_x_y_z => null()
     real*8, dimension(:,:), pointer        :: dphi_x_y_z => null()
  end type monitor_data
!
  type antenna_data
     real*8, dimension(:,:), allocatable    :: encoder_az_el
     real*8, dimension(:,:), allocatable    :: tracking_az_el
     real*8, dimension(:,:), allocatable    :: slowtrace
  end type antenna_data
!
  type calibration
     character*32                        :: febe
     integer, dimension(:), pointer      :: channels => null()
     real*8                              :: lcalof, bcalof ! offsets for 
                                                           ! sky subscan of 
                                                           ! a calibration,
     real*8, dimension(:), pointer       :: crvl4f_2 => null()
     real*8, dimension(:), pointer       :: cd4f_21 => null()
     real*8, dimension(:,:,:), pointer   :: gainarray => null()
     real*8, dimension(:,:,:), pointer   :: gainimage => null()
     real*8, dimension(:,:,:), pointer   :: phasearray => null()
     real*8, dimension(:,:,:), pointer   :: tcal => null()
     real*8, dimension(:,:,:), pointer   :: tauzen => null()
     real*8, dimension(:,:,:), pointer   :: tauzenImage => null()
     real*8, dimension(:,:,:), pointer   :: tauzenDry => null()
     real*8, dimension(:,:,:), pointer   :: tauzenImageDry => null()
     real*8, dimension(:,:,:), pointer   :: tauzenWet => null()
     real*8, dimension(:,:,:), pointer   :: tauzenImageWet => null()
     real*8, dimension(:,:,:), pointer   :: tatms => null()
     real*8, dimension(:,:,:), pointer   :: tatmi => null()
     real*8, dimension(:,:,:), pointer   :: temis => null()
     real*8, dimension(:,:,:), pointer   :: temii => null()
     real*8, dimension(:,:,:), pointer   :: tsys => null()
     real*8, dimension(:,:,:), pointer   :: trx => null()
     real*8, dimension(:,:,:), pointer   :: h2omm => null()
     real*8, dimension(:,:,:), pointer   :: psky       => null()
     real*8, dimension(:,:,:), pointer   :: phot       => null()
     real*8, dimension(:,:,:), pointer   :: pcold      => null()
     real*8, dimension(:,:,:), pointer   :: pgrid      => null()
  end type calibration 
!
  type datapar_header
     integer   scannum
     integer   obsnum
     integer   channels
     real*4    crpx4f_2         ! reference pixel for frequency scale
     real*4    crpx4r_2         ! reference pixel for velocity scale
     real*8    crvl4f_2         ! frequency [Hz] at reference pixel
     real*8    crvl4r_2         ! rest velocity [km/s] at reference pixel
     real*8    cd4f_21          ! frequency channel spacing [Hz]
     real*8    cd4r_21          ! velocity channel spacing [Hz]
     character date_obs*23
     character febe*32
     real*8    lst
     character obstype
     logical   dpblock
     character obstatus*10
  end type datapar_header
!
  type datapar_data
     integer, dimension(:), pointer      :: integnum => null()
     integer, dimension(:), pointer      :: subscan => null()
     integer, dimension(:), pointer      :: nints => null()
     real*8, dimension(:), pointer       :: mjd => null()
     real*8, dimension(:), pointer       :: lst => null()
     real*8, dimension(:), pointer       :: midtime => null()
     real*8, dimension(:), pointer       :: integtim => null()
     real*8, dimension(:), pointer       :: longoff => null()
     real*8, dimension(:), pointer       :: latoff => null()
     real*8, dimension(:), pointer       :: azimuth => null()
     real*8, dimension(:), pointer       :: elevatio => null()
     real*8, dimension(:), pointer       :: cbaslong => null()
     real*8, dimension(:), pointer       :: cbaslat => null()
     real*8, dimension(:), pointer       :: baslong => null()
     real*8, dimension(:), pointer       :: baslat => null()
     real*8, dimension(:), pointer       :: parangle => null()
     real*8, dimension(:), pointer       :: pc_11 => null()
     real*8, dimension(:), pointer       :: pc_12 => null()
     real*8, dimension(:), pointer       :: pc_21 => null()
     real*8, dimension(:), pointer       :: pc_22 => null()
     real*8, dimension(:), pointer       :: mcrval1 => null()
     real*8, dimension(:), pointer       :: mcrval2 => null()
     real*8, dimension(:), pointer       :: mlonpole => null()
     real*8, dimension(:), pointer       :: mlatpole => null()
     real*4, dimension(:), pointer       :: cr4K1 => null()
     real*4, dimension(:), pointer       :: cr4K2 => null()
!     real*8, dimension(:,:), pointer     :: dfocus => null()
     real*8, dimension(:,:), pointer     :: focus_x_y_z => null()
     real*8, dimension(:,:), pointer     :: dfocus_x_y_z => null()
     real*8, dimension(:,:), pointer     :: dphi_x_y_z => null()
     real*8, dimension(:,:), pointer     :: phi_x_y_z => null()
     real*4, dimension(:,:,:), pointer   :: otfdata => null()
     real*4, dimension(:,:), pointer     :: rdata => null()
  end type datapar_data
!
  type heraDerot
     real*8, dimension(:), pointer      :: mjd => null()
     real*4, dimension(:), pointer      :: actFrame => null()
  end type heraDerot
!
  type heraTemp
     real*8, dimension(:), pointer      :: mjd => null()
     real*4, dimension(:), pointer      :: cr4K1 => null()
     real*4, dimension(:), pointer      :: cr4K2 => null()
  end type heraTemp
!
  type imbFitsAntenna
     character(len=8)  :: sbCalRec
     character(len=20) :: systemOff
     character(len=40) :: subScanType
     real*8            :: dateObs
     real*8            :: dateEnd
     real*8            :: dopplerCorr
     real*8            :: obsVelRf
     real*8            :: subScanStart
     real*8            :: subScanEnd
     real*8            :: subScanXOff
     real*8            :: subScanYOff
     real*8            :: segmentXStart
     real*8            :: segmentXEnd
     real*8            :: segmentYStart
     real*8            :: segmentYEnd
     real*8            :: trackingError
  end type imbFitsAntenna
!
  type imbFitsSubreflector
     character(len=1)  :: focusTransl
     character(len=40) :: subScanType
     real*8            :: subScanStart
     real*8            :: subScanEnd
     real*8            :: segmentXStart
     real*8            :: segmentXEnd
     real*8            :: segmentYStart
     real*8            :: segmentYEnd
  end type imbFitsSubreflector
!
  type imbFitsBackend
     real*8 :: subScanStart
     real*8 :: subScanEnd
  end type imbFitsBackend
!
  type selection
     character(len=8), dimension(:), allocatable  :: backend
     character(len=23), dimension(2)              :: date_obs
     character(len=8), dimension(:), allocatable  :: frontend
     character(len=20), dimension(:), allocatable :: object
     character(len=8), dimension(:), allocatable  :: procedure
     character(len=8), dimension(:), allocatable  :: switchmode
     character(len=4), dimension(2)               :: scan
     character(len=13), dimension(:), allocatable :: telescope
     character(len=20), dimension(:), allocatable :: transition 
     character(len=6), dimension(:), allocatable  :: project
  end type selection
!
  type flag 
     logical, dimension(5) :: calibration_done 
     logical               :: base_done
     logical               :: despike_done
     logical               :: focus_done
     logical               :: pointing_done
  end type flag 
!
  type stack 
     integer                                  :: indx
     integer                                  :: ncfe
     integer                                  :: scan
     character(len=20)                        :: object
     character(len=13)                        :: telescope
     character(len=8)                         :: procedure
     character(len=20)                        :: switchmode
     character(len=8), dimension(:), pointer  :: backend => null()
     character(len=8), dimension(:), pointer  :: frontend => null()
     character(len=20), dimension(:), pointer :: transition => null()
     character(len=23)                        :: dateObs
     character(len=6)                         :: project
  end type stack 
!
  type primary
     type(primary_header)    header
  end type primary
!
  type scanpar
     type (scan_header)      header
     type (scan_data)        data 
  end type scanpar
!
  type febepar 
     type (febepar_header)   header
     type (febepar_data)     data 
  end type febepar
!
  type arraydata
     type (arraydata_header), dimension(:), pointer :: header => null()
     type (arraydata_data), dimension(:), pointer   :: data  => null()
  end type arraydata
!
  type monitor
     type (monitor_header)                       :: header
     type (monitor_data)                         :: data 
  end type monitor
!
  type datapar
     type (datapar_header) :: header
     type (datapar_data)   :: data 
  end type datapar
!
!
  type imbFits
     type (imbFitsAntenna), dimension(:), pointer      :: antenna => null()
     type (imbFitsSubreflector), dimension(:), pointer :: subRef => null()
     type (imbFitsBackend), dimension(:), pointer      :: backend => null()
  end type imbFits
!
!
  type override_data
     real*4, dimension(:,:), allocatable               :: beameff
     real*4, dimension(:,:), allocatable               :: etafss
     real*4, dimension(:,:), allocatable               :: gainimag
     real*8, dimension(:,:), allocatable               :: thotcold
     real*8, dimension(:,:), allocatable               :: tamb_p_humid 
  end type override_data
!
!
  type switch
     character(len=4), dimension(:,:), allocatable     :: switch
  end type switch
!
!
  INTEGER, PUBLIC               :: IPC, NCALCHAN, NMXOFF, NSUBSCAN, OBSNUMBER
  CHARACTER*5, PUBLIC, PARAMETER:: miraVersion = 'v2.6'
  REAL*4, PUBLIC                :: blankingRaw, blankingRed, badLevel
  REAL*8, PUBLIC                :: CLIGHT, PI, RAD2ASEC, RAD2DEG, SEC2RAD, TWOPI
  REAL*8, PUBLIC                :: DAY2RAD, SEC2DAY
  CHARACTER*256, PUBLIC         :: ncsData, visData
  CHARACTER*4, PUBLIC           :: atmVersion
  CHARACTER*20, PUBLIC          :: atmType
  LOGICAL, PUBLIC               :: calByChannel, classOption, doPause,      & 
 &                                 writeXML, searchTrec, calCheck,          &
 &                                 ignoreTraceflag, flagBSwSpikes,          &
 &                                 timingCheck, traceExtrapolation
  LOGICAL, DIMENSION(7), PUBLIC :: overrideFlag
!
  REAL*8, DIMENSION(9), PARAMETER  :: xHera = &
 &                                      (/-24.,-24.,-24.,0.,0.,0.,24.,24.,24./)
  REAL*8, DIMENSION(9), PARAMETER  :: yHera = &
 &                                      (/-24.,0.,24.,-24.,0.,24.,-24.,0.,24./)
!
  TYPE(PRIMARY), POINTER, PUBLIC                     :: PRIM => NULL()
  TYPE(SCANPAR), POINTER, PUBLIC                     :: SCAN => NULL()
  TYPE(FEBEPAR), DIMENSION(:), POINTER, PUBLIC       :: FEBE => NULL()
  TYPE(ARRAYDATA), DIMENSION(:), POINTER, PUBLIC     :: ARRAY => NULL()
  TYPE(DATAPAR), DIMENSION(:), POINTER, PUBLIC       :: DATA => NULL()
  TYPE(MONITOR), DIMENSION(:), POINTER, PUBLIC       :: MON => NULL()
  TYPE(CALIBRATION), DIMENSION(:), POINTER, PUBLIC   :: GAINS => NULL()
  TYPE(CALIBRATION), DIMENSION(:),ALLOCATABLE,PUBLIC :: IGAINS
  TYPE(imbFits), DIMENSION(:), ALLOCATABLE, PUBLIC   :: RAW
  TYPE(override_data), DIMENSION(:), ALLOCATABLE, PUBLIC :: NEWPAR
  TYPE(ANTENNA_DATA), PUBLIC                         :: ANTDATA
  TYPE(SELECTION), PUBLIC                            :: CHOICE
  TYPE(FLAG), DIMENSION(:), ALLOCATABLE, PUBLIC      :: REDUCE
  TYPE(HERADEROT), POINTER, PUBLIC                   :: DEROT => NULL()
  TYPE(HERATEMP), POINTER, PUBLIC                    :: CRYO => NULL()
  TYPE(STACK), DIMENSION(:), POINTER, PUBLIC         :: LIST  => NULL()
!
  TYPE(PRIMARY), TARGET, PUBLIC, SAVE                                :: PR
  TYPE(SCANPAR), TARGET, PUBLIC, SAVE                                :: SC
  TYPE(FEBEPAR), DIMENSION(:), ALLOCATABLE, TARGET, PUBLIC, SAVE     :: FB
  TYPE(ARRAYDATA), DIMENSION(:), ALLOCATABLE, TARGET, PUBLIC, SAVE   :: AR
  TYPE(DATAPAR), DIMENSION(:), ALLOCATABLE, TARGET, PUBLIC, SAVE     :: DT
  TYPE(MONITOR), DIMENSION(:), ALLOCATABLE, TARGET, PUBLIC, SAVE     :: MNT
  TYPE(HERADEROT), TARGET, PUBLIC, SAVE                              :: DRT 
  TYPE(HERATEMP), TARGET, PUBLIC, SAVE                               :: CRX
  TYPE(CALIBRATION), DIMENSION(:), ALLOCATABLE, TARGET, PUBLIC, SAVE :: GN
  TYPE(STACK), DIMENSION(:), ALLOCATABLE, TARGET, PUBLIC, SAVE       :: myList
!
  TYPE(ARRAYDATA), DIMENSION(:), ALLOCATABLE, TARGET, PUBLIC, SAVE   :: arrayBuf
  TYPE(DATAPAR), DIMENSION(:), ALLOCATABLE, TARGET, PUBLIC, SAVE     :: dataBuf
  TYPE(MONITOR), DIMENSION(:), ALLOCATABLE, TARGET, PUBLIC, SAVE     :: monBuf
!
  TYPE(SWITCH), DIMENSION(:), ALLOCATABLE, TARGET, PUBLIC, SAVE      :: INTEGTYP
  INTEGER, DIMENSION(:,:), ALLOCATABLE, TARGET, PUBLIC, SAVE         :: IFLAG
!
end module mira
!
!
module linearRegression

      TYPE base
         REAL*4  :: Y
         REAL*8  :: X
      END TYPE BASE

      TYPE lg
         INTEGER :: N
         REAL*8  :: A, B, DET
      END Type lg

end module linearRegression

!
module fit
  use point_definitions
  type(fit_fun), dimension(2), public :: fun
end module fit
!
module chopper_def
  !----------------------------------------------------------------------
  ! TELCAL support module for chopper wheel calibration (MIRA version)
  !----------------------------------------------------------------------
  !
  type :: chop_mode ! 
     logical :: water ! Search for water?
     logical :: atm   ! Compute opacities?
     logical :: trec  ! Compute trec?
     logical :: tcal  ! Compute tcal?
     logical :: tsys  ! Compute tsys?
  end type chop_mode
  !
  type :: telescope !
     real (8) :: alti ! [  km] Telescope altitude
     real (8) :: lati ! [ rad] Telescope latitude    
     real (8) :: elev ! [ rad] Telescope elevation
     real (8) :: hwat ! [  km] Water scale height
     real (8) :: tout ! [   K] Outside temperature
     real (8) :: tcab ! [   K] Cabin   temperature 
     real (8) :: pres ! [mbar] Ambient pressure
  end type telescope
  !
  type :: dsb_value ! (e.g. frequency, temperature)
     real (8) :: s ! Signal value   
     real (8) :: i ! Image  value
  end type dsb_value
  !
  type :: mixer ! Comment: feff+fout+fcab = 1.0 
     real (8) :: sbgr  ! [   ] Sideband gain ratio
     real (8) :: beff  ! [   ] Beam efficiency    
     real (8) :: feff  ! [   ] Forward efficiency 
     real (8) :: fout  ! [   ] Coupling to ground 
     real (8) :: fcab  ! [   ] Coupling to cabin  
     real (8) :: temp  ! [  K] Noise temperature
  end type mixer
  !
  type :: chop_load ! Load description
     real (8) :: count ! [ ] Power expressed in counts
     real (8) :: temp  ! [K] Power expressed in Rayleigh-Jeans temperature
     real (8) :: ceff  ! [ ] Coupling. Comment: 1-coupling = sky coupling
  end type chop_load
  !
  type :: chop_meas ! Measurements to perform a "chopper" calibration
     real (8)         :: dark_count ! [ ] Dark power expressed in counts
     real (8)         ::  sky_count ! [ ] Sky  power expressed in counts
     type (chop_load) :: cold       ! [ ] Cold load description
     type (chop_load) :: hot        ! [ ] Hot  load description
  end type chop_meas
  !
  type :: opacity !
     real (8) :: wat ! [neper] Opacity due to water
     real (8) :: oth ! [neper] Opacity due to other components
     real (8) :: tot ! [neper] Total opacity
  end type opacity
  !
  type :: atm_prop ! Atmospheric properties
     real (8) :: airmass      ! [     ] Air mass number (about 1/sin(elev))
     real (8) :: h2omm        ! [   mm] Zenith water vapor content
     type (opacity)   :: taus ! [neper] Zenith opacities at signal frequency
     type (opacity)   :: taui ! [neper] Zenith opacities at image  frequency
     type (dsb_value) :: temp ! [    K] Sky mean     temperatures (signal and image)
     type (dsb_value) :: temi ! [    K] Sky emission temperatures (signal and image)
  end type atm_prop
  !
  type(dsb_value), public :: freq
  type(atm_prop),  public :: atm
  type(telescope), public :: telNumRec
  type(mixer),     public :: rec
  real(8),         public :: temi0, tau0
  !
end module chopper_def
!
!
