!
!----------------------------------------------------------------------
!
! <DOCUMENTATION name="modulePakoSource">
!   <VERSION>
!     Id: modulePakoSource.f90,v 1.2.4 2015-07-16 Hans Ungerechts
!     Id: modulePakoSource.f90,v 1.2.4 2015-06-18 Hans Ungerechts
!     Id: modulePakoSource.f90,v 1.2.3 2014-09-01 Hans Ungerechts
!     Id: modulePakoSource.f90,v 1.2.3 2014-02-13 Hans Ungerechts
!                                1.2.1 2012-08-23 Hans Ungerechts
!     based on:
!     Id: modulePakoSource.f90,v 1.1.3 2010-11-16 Hans Ungerechts
!     originally based on SOURCE in PdB OBS
!   </VERSION>
!   <PROGRAM>
!                Pako
!   </PROGRAM>
!   <FAMILY>
!                Source
!   </FAMILY>
!   <SIBLINGS>
!                Source
!   </SIBLINGS>        
!
!   Pako module for command: SOURCE
!
! </DOCUMENTATION> <!-- name="modulePakoSource" -->
!
!----------------------------------------------------------------------
!
!
Module modulePakoSource
  !
  Use modulePakoMessages
  Use modulePakoTypes
  Use modulePakoGlobalParameters
  Use modulePakoLimits
  Use modulePakoXML
  Use modulePakoDisplayText
  Use modulePakoUtilities
  Use modulePakoGlobalVariables
!!  Use modulePakoSubscanList
  Use modulePakoReceiver
  !
  Use gbl_message
  Use gkernel_interfaces
  !
  Implicit None
  Save
  Private
  Public :: source,  displaySource, saveSource, storeSource, getSource
  Public :: writeXMLsource, writeXMLoffsets, writeXMLtopology
  Public :: writeXMLfocusCorrections, writeXMLpointingCorrections
  Public :: offsets, displayOffsets, saveOffsets, queryOffsets
  !     
  ! *** Variables for Commands ***
  Include 'inc/variables/variablesSource.inc'
!!!   
!!!   
Contains
!!!
!!!
  Subroutine source(programName,line,command, ERROR)
    !
    !	searches the source catalog for source 'name'
    !	parses the line found for coords and velocities
    !	converts coordinates to internal format
    !
    ! *** Arguments: ***
    Include 'inc/variables/headerForCommandHandler.inc'
    !
    ! *** standard working variables   ***
    Include 'inc/variables/standardWorkingVariables.inc'
    !
    Character(len=lenCO)   :: cInputUpper2
    Character(len=lenVar)  :: cFileCount, cFileGrep
    Character(len=lenLine) :: shellCommand
    Logical                :: errorSourceNotInCatalog
    Logical                :: longitudeInCommandLine, latitudeInCommandLine
    Integer                :: iEr, System
    !
    Integer                :: iUnitR
    !
    Character(len=lenCh)   :: howTo
    !
    Logical                :: longitudeFromVariable, latitudeFromVariable
    Character(len=lenCh)   :: longitudeValue,        latitudeValue
    !
    Logical                :: isConnectedBolo
    Logical                :: isConnectedHERA1, isConnectedHERA2
    Logical                :: isConnectedHERA  
    !
    iUnitR  =  ioUnit%Read
    !
    Call initializeSystemNameChoices   !!! TBD: delete / obsolete
    !
    !     TBD: the following shall be replaced by a SR reading from XML:
    Include 'inc/ranges/rangesSource.inc'
    !
    errorSourceNotInCatalog = .False.
    !
    !
    Call pako_message(seve%t,programName,                                        &
         &    " module source, 1.2.4 2015-06-18 ---> SR: Source ")               ! trace execution
    !
    !D      Write (6,*) " modulePako Source ---> SR: Source "
    !D      Write (6,*) "                      "
    !D      Write (6,*) "        programName:    ->", programName,"<-"
    !D!
    !D      Write (6,*) "        command:      ", command
    !D      Write (6,*) "        modeSelected: ", modeSelected
    !D      Write (6,*) "        error:        ", error
    !D      Write (6,*) "        isInitialized:   ", isInitialized
    !D      Write (6,*) "                      "
    !
    ! *** initialize:   ***
    If (.Not.isInitialized) Then
       Include 'inc/variables/setDefaults.inc'
       varsOffsets(iIn,:)    = varsOffsets(iDefault,:)
       varsOffsets(iTemp,:)  = varsOffsets(iDefault,:)
       varsOffsets(iValue,:) = varsOffsets(iDefault,:)
       isInitialized = .True.
       GV%sourceSet  = .True.
       messageText = " default source "//vars(iValue)%sourceName//" selected"
       l = Len_trim (messageText)
       Call  pakoMessage(priorityW,severityW,command,messageText(1:l))
    Endif
    !
    option = 'DEFAULTS'
    Call indexCommmandOption                                                     &
         &        (command,option,commandFull,optionFull,                        &
         &        commandIndex,optionIndex,iCommand,iOption,                     &
         &        errorNotFound,errorNotUnique)                                  !
    setDefaults = SIC_PRESENT(iOption,0)
    !
    ! *** set In-values = previous Values   ***
    If (.Not.ERROR) Then
       vars(iIn) = vars(iValue)
    End If
    !
    ! *** check N of Parameters: 0, n --> at  most n allowed  ***
    ! *** read Parameters, Options (to detect errors)         ***
    ! *** and check for validity and ranges                   ***
    Call checkNofParameters(command,                                             &
         &     0, 12,                                                            &
         &     nArguments,                                                       &
         &     errorNumber)                                                      !
    ERROR = ERROR .Or. errorNumber
    !
    If (.Not. ERROR) Then
       Call pakoMessageSwitch (setOn = .True.)
       If (.Not. setDefaults) Then
          Include 'inc/options/optionCatalog.inc'
          Include 'inc/parameters/parametersSource.inc'      
          !D           l = len_trim(vars(iIn)%sourceCatalog)
          !D           Write (6,*) " vars(iIn)%sourceCatalog(1:l) -->",                       &
          !D                &        vars(iIn)%sourceCatalog(1:l), "<--"                      !
       End If
       !
       Include 'inc/options/readOptionsSource.inc'
    End If
    !
    ! *** set defaults   ***
    If (.Not. ERROR) Then
       option = 'DEFAULTS'
       Call indexCommmandOption                                                  &
            &        (command,option,commandFull,optionFull,                     &
            &        commandIndex,optionIndex,iCommand,iOption,                  &
            &        errorNotFound,errorNotUnique)                               !
       setDefaults = SIC_PRESENT(iOption,0)
       If (setDefaults) Then
          Include 'inc/variables/setDefaults.inc'
          GV%sourceSet  = .True.
          messageText = " default source "//vars(iValue)%sourceName//" selected"
          l = Len_trim (messageText)
          Call  pakoMessage(priorityW,severityW,command,messageText(1:l))
          !TBD reset offsets with SOURCE command? NO!
       Endif
    Endif
    !
    ! *** read Parameters, Options (again, after defaults!)   ***
    ! *** and check for validity and ranges                   ***
    If (.Not. ERROR) Then
       Call pakoMessageSwitch (setOff = .True.)
       If (.Not. setDefaults) Then
          Include 'inc/options/optionCatalog.inc'
          Include 'inc/parameters/parametersSource.inc'      
       End If
       !
       Include 'inc/options/readOptionsSource.inc'
    End If
    Call pakoMessageSwitch (setOn = .True.)
    !
    ! *** check consistency and                           ***
    ! *** store into temporary (intermediate) variables   ***
    If (.Not.ERROR) Then
       !
       Include 'inc/parameters/checkConsistentSource.inc'
       !
       If (.Not. errorInconsistent) Then
          vars(iTemp) = vars(iIn)
       End If
       !
    End If
    !
    ERROR = ERROR .Or. errorInconsistent
    !
    ! *** store from Temp into persistent variables   ***
    If (.Not.ERROR) Then
       vars(iValue)          = vars(iTemp)
       GV%sourceProjectID    = vars(iValue)%projectID
       GV%sourceSet          = .True.
    End If
    !D     l = len_trim(vars(iValue)%sourceCatalog)
    !D     Write (6,*) " vars(iValue)%sourceCatalog(1:l) -->",                          &
    !D          &        vars(iValue)%sourceCatalog(1:l), "<--"                         !
    !
    ! *** display values  ***
    !     (Note: this is done independantly of the Error status)
    Call displaySource
    !D    Write (6,*) "      GV%sourceProjectID: ",  GV%sourceProjectID
    !
    ! ***  ***
    If (.Not.error) Then
       If (vars(iValue)%isPlanet) Then
          messageText = "Planet selected:"//' '//vars(iValue)%sourceName
       Else If (vars(iValue)%isSatellite) Then
          messageText = "Satellite selected:"//' '//vars(iValue)%sourceName
       Else If (vars(iValue)%isBody) Then
          messageText = "Solar System Body selected:"//                          &
               &        ' '//vars(iValue)%sourceName                             !
       Else
          !
          If (vars(iValue)%systemName.Eq.sys%equatorial.Or.                      &
               &    vars(iValue)%systemName.Eq.sys%ecliptic) Then                !
             !
             Write (valueText,'(f6.1)') vars(iValue)%epoch
             larg = Len_trim(valueText)
             Write (messageText,*) "selected: ", vars(iValue)%sourceName,        &
                  &            " ",vars(iValue)%systemName(1:2),                 &
                  &            " ",vars(iValue)%equinoxSystemName(1:1)//         &
                  &                valueText(1:larg),                            &
                  &            " ",vars(iValue)%longitude%text,                  &
                  &            " ",vars(iValue)%latitude%text,                   &
                  &            " "                                               !
          Else
             Write (messageText,*) "selected: ", vars(iValue)%sourceName,        &
                  &            " ",vars(iValue)%systemName(1:2),                 &
                  &            " ",vars(iValue)%longitude%text,                  &
                  &            " ",vars(iValue)%latitude%text,                   &
                  &            " "                                               !
          End If
          !
       End If
       !
       l = Len_trim (messageText)
       If (        GV%matchSource .Eq. setMatchSource%Start                      &
            & .Or. GV%matchSource .Eq. setMatchSource%Match ) Then               !
          Call  pakoMessage(        7,severityI,command,messageText(1:l))
       Else
          Call  pakoMessage(priorityI,severityI,command,messageText(1:l))
       End If
       !
       Do ii = nDimOffsetChoices, 1, -1
          If (varsOffsets(iValue,ii)%isSet) Then
             !
             messageText = "   please review OFFSETS (not cleared by SOURCE!)"
             l = Len_trim (messageText)
             Call  pakoMessage(priorityW,severityW,command,messageText(1:l))
             messageText = "   consider: OFFSETS or OFFSET /CLEAR "
             l = Len_trim (messageText)
             Call  pakoMessage(priorityI,severityI,command,messageText(1:l))
             !
          End If
       End Do
       sourceCommand = line(1:lenc(line))
    End If
    !
    If (catalogOpen) Close(UNIT=10)
    !
    Return
  End Subroutine source
!!!
!!!
  Subroutine displaySource
    !
    Include 'inc/variables/standardWorkingVariables.inc'
    !
    Character(len=24)  :: command
    !
    Include 'inc/display/commandDisplaySource.inc'
    !
  End Subroutine displaySource
!!!
!!!
  Subroutine  storeSource(OM,iOm)
    !
    Character(len=lenCh), Intent(IN)   ::  OM 
    Integer,              Intent(IN)   ::  iOm
    !
    !D    Write (6,*) "      --> storeSource: "
    !D    Write (6,*) "          OM, iOm:   ", OM, iOm
    !
    OMsource(iOm) = vars(iValue) 
    ! 
    !D    Write (6,*) "          OMsource(iOm) = ",  OMsource(iOm)
    !
  End Subroutine storeSource
!!!
!!!
  Subroutine  getSource(OM,iOm)
    !
    Character(len=lenCh), Intent(IN)   ::  OM 
    Integer,              Intent(IN)   ::  iOm
    !
    ! *** standard working variables   ***
    Include 'inc/variables/standardWorkingVariables.inc'
    !
    vars(iValue) = OMsource(iOm)  
    ! 
    Write (messageText,*) " got last source ",OMsource(iOm)%sourceName
    l = Len_trim (OM)
    Call  pakoMessage(priorityW,severityW,OM(1:l)//" /lastSource",messageText)
    !
    Call displaySource
    !
  End Subroutine getSource
!!!
!!!
  Subroutine offsets(programName,line,command, ERROR)
    !
    ! *** Arguments: ***
    Include 'inc/variables/headerForCommandHandler.inc'
    !
    ! *** standard working variables   ***
    Include 'inc/variables/standardWorkingVariables.inc'
    !
    Integer                ::  nPDB, nEH, nTH
    Logical                ::  inconsistentReceiverOffsets
    !
    Call initializeSystemNameChoices   !!  TBD: delete /obsolete
    !
    !     TBD: the following shall be replaced by a SR reading from XML:
    Include 'inc/ranges/rangesSource.inc'
    !
    Call pako_message(seve%t,programName,                                        &
         &    " module source,  --> SR: Offsets ")                               ! trace execution
    !
    !D    Write (6,*) " modulePako Source ---> SR: Offsets "
    !D    Write (6,*) "                      "
    !D    Write (6,*) "      iiSystemOffset:    ", iiSystemOffset
    !D    Write (6,*) "      ccSystemOffset:    ", ccSystemOffset
    !
    ! *** initialize:   ***
    If (.Not.isInitialized) Then
       varsOffsets(iIn,:)    = varsOffsets(iDefault,:)
       varsOffsets(iTemp,:)  = varsOffsets(iDefault,:)
       varsOffsets(iValue,:) = varsOffsets(iDefault,:)
       isInitialized = .True.
    Endif
    !
    ! *** set In-values = previous Values   ***
    If (.Not.ERROR) Then
       varsOffsets(iIn,:) = varsOffsets(iValue,:)
    End If
    !
    ! *** check N of Parameters: 0, n --> at  most n allowed  ***
    ! *** read Parameters, Options (to detect errors)         ***
    ! *** and check for validity and ranges                   ***
    Call checkNofParameters(command,                                             &
         &     0, 2,                                                             &
         &     nArguments,                                                       &
         &     errorNumber)                                                      !
    ERROR = ERROR .Or. errorNumber
    !
    If (.Not. ERROR) Then
       !TBD check case depending on /SYSTEM
       Include 'inc/options/optionSystemOffsets.inc'
       Include 'inc/options/optionClearOffsets.inc'
       Include 'inc/parameters/parametersOffsets.inc'      
       !! Include 'inc/options/readOptionsOffsets.inc'
    End If
    !
    ! *** set defaults   ***
    If (.Not. ERROR) Then
       option = 'DEFAULTS'
       Call indexCommmandOption                                                  &
            &        (command,option,commandFull,optionFull,                     &
            &        commandIndex,optionIndex,iCommand,iOption,                  &
            &        errorNotFound,errorNotUnique)                               !
       setDefaults = SIC_PRESENT(iOption,0)
       If (setDefaults) Then
          varsOffsets(iIn,:)    = varsOffsets(iDefault,:)
          varsOffsets(iTemp,:)  = varsOffsets(iDefault,:)
          varsOffsets(iValue,:) = varsOffsets(iDefault,:)
       Endif
    Endif
    !
    ! *** read Parameters, Options (again, after defaults!)   ***
    ! *** and check for validity and ranges                   ***
    If (.Not. ERROR) Then
       !TBD check case depending on /SYSTEM
       Include 'inc/options/optionSystemOffsets.inc'
       Include 'inc/options/optionClearOffsets.inc'
       Include 'inc/parameters/parametersOffsets.inc'      
       !! Include 'inc/options/readOptionsOffsets.inc'
    End If
    !
    ! *** check consistency and                           ***
    ! *** store into temporary (intermediate) variables   ***
    !D    Write (6,*) "        GV%observingMode ", GV%observingMode
    If (.Not.ERROR) Then
       !
       Include 'inc/options/checkConsistentOffsets.inc'
       !
       l = Len_trim(command)
       !
       doWarnOffsets = .False.
       doWarnOM      = .False.
       If (GV%observingMode .Eq. OM%onOff) Then
          Do ii = 1, nDimOffsetChoices, 1
             If (varsOffsets(iIn,ii)%isSet) Then
                !
                If (varsOffsets(iIn,ii)%systemName .Eq. GV%omSystemName) Then
                   doWarnOffsets = .True.
                   !D                   Write (6,*) "      GV%omSystemName:   ", GV%omSystemName
                   Write (messageText,*)                                         &
                        &    " NOTE: the offsets set with OFFSETS /system "      &
                        &    //varsOffsets(iIn,ii)%SystemName//                  &
                        &    " will be ignored!"                                 !
                   Call PakoMessage(priorityW,severityW,                         &
                        &    command(1:l)//" /SYSTEM",                           &
                        &    messageText)                                        !
                   Write (messageText,*)                                         &
                        &    " -- i.e., they are not added to those of the "     &
                        &    //"observing mode "                                 &
                        &    //GV%observingMode                                  !
                   Call PakoMessage(priorityW,severityW,                         &
                        &    command(1:l)//" /SYSTEM",                           &
                        &    messageText)                                        !
                End If
                !
             End If
          End Do
          !
          ! **  observing mode must be specified after OFFSETS:
          !
          If (GV%observingMode .Eq. OM%OnOff) Then
             doWarnOM                      = .True.
             GV%notReadyOffsetsAfterOnOff  = .True.
             GV%notReadyOnOff              = .True.
             messageText = "Please re-execute ONOFF"//                           &
                  &        " after OFFSETS"                                      !
             Call PakoMessage(priorityW,severityW,command,messageText)
             messageText = "Recommended Usage: ONOFF"
             Call PakoMessage(priorityI,severityI,command,messageText)
          End If
       End If
       !
       If (.Not. errorInconsistent) Then
          varsOffsets(iTemp,:) = varsOffsets(iIn,:)
       End If
       !
    End If
    !
    ERROR = ERROR .Or. errorInconsistent
    !
    ! *** store from Temp into persistent variables   ***
    If (.Not.ERROR) Then
       varsOffsets(iValue,:) = varsOffsets(iTemp,:)
    !!   GV%sourceOffsets      = varsOffsets(iTemp,:)
    End If
    !
    !! ! OBSOLETE:
    !! ! *** check consistency with receiver offsets
    !
    !! Call checkBolometerArray (inconsistentReceiverOffsets,  errorCode)
    !D     Write (6,*) "  inconsistentReceiverOffsets: ", inconsistentReceiverOffsets
    !D     Write (6,*) "  errorCode: ", errorCode(1:len_trim(errorCode))
    !
    If (inconsistentReceiverOffsets) Then
       GV%notReadyReceiverOffsets = .True.
       messageText = "OFFSETS /SYSTEM Nasmyth and "//                            &
            &    "RX Array offsets are inconsistent"                             !
       Call PakoMessage(priorityW,severityW,command,messageText)
       Call PakoMessage(priorityI,severityI,command,errorCode)
    Else
       GV%notReadyReceiverOffsets = .False.
    End If
    !
    ! *** display values  ***
    !     (Note: this is done independently of the Error status)
    Call displayOffsets
    !
    Do ii = 1, nDimOffsetChoices, 1
       If (varsOffsets(iValue,ii)%isSet) Then
          !
          If ( ii.Eq.iNas) Then
             !
             Write (messageText,*)                                               &
                  &              varsOffsets(iValue,ii)%point%x/GV%anglefactorR, &
                  &              varsOffsets(iValue,ii)%point%y/GV%anglefactorR, &
                  & " /SYSTEM ", varsOffsets(iValue,ii)%systemName               !
             Write (messageText,*)                                               &
                  & " /SYSTEM ", varsOffsets(iValue,ii)%systemName,              &
                  & " are explicitly set: they OVERRULE any automatic values"    ! 
             Call  pakoMessage(666,severityW,command,messageText)
             !
          Else
             Write (messageText,*)                                               &
                  &              varsOffsets(iValue,ii)%point%x/GV%anglefactorR, &
                  &              varsOffsets(iValue,ii)%point%y/GV%anglefactorR, &
                  & " /SYSTEM ", varsOffsets(iValue,ii)%systemName               !
          End If
          Call  pakoMessage(priorityI,severityI,command,messageText)
          !
       End If
    End Do
    !
    !D    Do ii = 1, nDimOffsetChoices, 1
    !D       If (GV%sourceOffsets(ii)%isSet) Then
    !D          !
    !D          If (GV%sourceOffsets(ii)%systemName .Eq.                                     &
    !D               &  offsetSystemChoices(iNASMYTH)) Then
    !D             Write (messageText,*)                                                     &
    !D                  &                GV%sourceOffsets(ii)%point%x/GV%anglefactorR,       &
    !D                  &                GV%sourceOffsets(ii)%point%y/GV%anglefactorR,       &
    !D                  & " /SYSTEM ",    GV%sourceOffsets(ii)%systemName
    !D             !TBD                    & "/CHANNEL ",   GV%sourceOffsets(ii)%channel,    &
    !D             !TBD                    & "/ELEVATION ", GV%sourceOffsets(ii)%elevation
    !D          Else
    !D             Write (messageText,*)                                                     &
    !D                  &             GV%sourceOffsets(ii)%point%x/GV%anglefactorR,          &
    !D                  &             GV%sourceOffsets(ii)%point%y/GV%anglefactorR,          &
    !D                  & " /SYSTEM ", GV%sourceOffsets(ii)%systemName
    !D          End If
    !D          Call  pakoMessage(priorityI,severityI,command,messageText)
    !D          !
    !D       End If
    !D    End Do
    !
    Return
  End Subroutine offsets
!!!
!!!
  Subroutine queryOffsets(iQuery,nameQuery,isSet,pointResult)
    !
    Integer              ,  Intent(IN)    :: iQuery
    Character(len=lenCh) ,  Intent(IN)    :: nameQuery
    Logical              ,  Intent(OUT)   :: isSet
    Type(xyPointType)    ,  Intent(OUT)   :: pointResult
    !
    ! TBD: elaborate!
    !
    !D        Write (6,*) "   --> queryOffsets: "
    !D        Write (6,*) "            iQuery = ", iQuery
    !
    isSet = .False.
    pointResult = xyPointType(GPnoneR,GPnoneR)
    If (iQuery.Ge.1 .And. iQuery.Le.nDimOffsetChoices) Then
       If (varsOffsets(iValue,iQuery)%isSet) Then
          isSet = .True.
          pointResult =  varsOffsets(iValue,iQuery)%point
       End If
    End If
    !
    !D        Write (6,*) "           isSet =       ", isSet
    !D        Write (6,*) "           pointResult = ", pointResult
    !
    Return
  End Subroutine queryOffsets
!!!
!!!
  Subroutine displayOffsets
    !
    Include 'inc/variables/standardWorkingVariables.inc'
    !
    Character(len=24)  :: command
    !
    Integer  :: nCount
    !
    Include 'inc/display/commandDisplayOffsets.inc'
    !
  End Subroutine displayOffsets
!!!
!!!
  Subroutine saveSource(programName,LINE,commandToSave,                          &
       &        iUnit, error)                                                    !
    !
    ! *** Variables   ***
    Include 'inc/variables/headerForSaveMethods.inc'
    !
    Integer :: l1, l2
    !
    B = '\'  ! '
    S = ' '
    CMD =  programName//B//"SOURCE"
    lCMD = lenc(CMD)
    !
    ERROR = .False.
    !
    contC = contNN
    !
    Write (iUnit,*) "! "
    Write (iUnit,*) "! ", CMD(1:lCMD)
    !
    ! TBD debug for all possible cases ///
    !
    If (vars(iValue)%isBody) Then
       contC = contNC
       Include 'inc/parameters/saveBodyName.inc'
       contC = contCC
       Include 'inc/parameters/savePerihelionEpoch.inc'
       Include 'inc/parameters/saveAscendingNode.inc'
       Include 'inc/parameters/saveArgumentOfPerihelion.inc'
       Include 'inc/parameters/saveInclination.inc'
       Include 'inc/parameters/savePerihelionDistance.inc'
       contC = contCN
       Include 'inc/parameters/saveEccentricity.inc'
    Else If (vars(iValue)%isPlanet .Or. vars(iValue)%isSatellite) Then
       contC = contNC
       Include 'inc/parameters/saveSourceName.inc'
       contC = contCN
!!$       Include 'inc/options/saveVelocity.inc'
!!$       Include 'inc/options/saveFlux.inc'
    Else
       contC = contNC
       Include 'inc/parameters/saveSourceName.inc'
       contC = contCC
       Include 'inc/parameters/saveSystem.inc'
       Include 'inc/parameters/saveLongitudeLatitude.inc'
       If (vars(iValue)%projectID .Eq. GPnone) Then
          contC = contCN
          Include 'inc/parameters/saveVelocity.inc'
!!$       Include 'inc/parameters/saveFlux.inc'
       Else
          Include 'inc/parameters/saveVelocity.inc'
          Include 'inc/parameters/saveFlux.inc'
          contC = contCN
          Include 'inc/parameters/saveSourceProjectID.inc'
       End If
    End If
    !
    Write (iUnit,*) "!"
    !
    Return
  End Subroutine saveSource
!!!
!!!
  Subroutine saveOffsets(programName,LINE,commandToSave,                         &
       &        iUnit, error)                                                    !
    !
    ! *** Variables   ***
    Include 'inc/variables/headerForSaveMethods.inc'
    !
    Integer  :: ii
    !
    B = '\'  ! '
    S = ' '
    CMD =  programName//B//"OFFSETS"
    lCMD = lenc(CMD)
    !
    ERROR = .False.
    !
    Write (iUnit,*) "! "
    Write (iUnit,*) "! ", CMD(1:lCMD)
    !
    contC = contNN
    Include 'inc/commands/saveOffsets.inc'
    contC = contCN
    Include 'inc/options/saveClear.inc'
    !
    Do ii = 1, nDimOffsetChoices, 1
       If (varsOffsets(iValue,ii)%isSet) Then
          !
          !TBD: special case Nasmyth:
!!$            If (varsOffsets(iValue,ii)%systemName .EQ.                  &
!!$                 &  offsetSystemChoices(iNASMYTH)) Then
!!$            Else      
          !
          contC = contNN
          !
          Include 'inc/commands/saveOffsets.inc'
          !
          contC = contCC
          !
          Include 'inc/parameters/saveXoffsetYoffset.inc'
          !
          contC = contCN
          !
          Include 'inc/options/saveOffsetsSystem.inc'
          !
!!$            End If
       End If
    End Do
    !
    Write (iUnit,*) "!"
    !
    Return
  End Subroutine saveOffsets
!!!
!!!
  Subroutine SUFFIX(PAR,LPAR,R1,R2)
    !------------------------------------------------------------------------
    !------------------------------------------------------------------------
    ! Dummy variables:
    Character*(*) PAR
    Real R1,R2
    Integer LPAR
    ! Local variables:
    Integer I
    Character*80 CHAIN
    !------------------------------------------------------------------------
    ! Code:
    !
    R1 = 0
    R2 = 0
    I = Index(PAR(1:LPAR),',')
    If (I.Eq.0) Return
    CHAIN = PAR(I+1:LPAR)
    PAR = PAR(1:I-1)
    LPAR = I-1
    I = Index(CHAIN,',')
    If (I.Eq.0) Then
       Read (CHAIN,*,ERR=99) R1
    Else
       Read (CHAIN,*,ERR=99) R1,R2
    Endif
99  Return
  End Subroutine SUFFIX
!!!
!!!
!!$      SUBROUTINE CHECK_POSITION
!!$!------------------------------------------------------------------------
!!$! Check elevation and distance from sun
!!$!------------------------------------------------------------------------
!!$! Global variables:
!!$      INCLUDE 'const.f'
!!$      INCLUDE 'obs_parameter.inc'
!!$      INCLUDE 'obs_obs.inc'
!!$      INCLUDE 'obs_structure.inc'
!!$      INCLUDE 'obs_common.inc'
!!$      REAL*4 D_SUN, S_RISE, S_SET, D_AZIM
!!$      LOGICAL D_SHADOW, ERROR
!!$      COMMON/SUN/D_SUN, D_AZIM, D_SHADOW
!!$! Local variables:
!!$      REAL*8 D_ELEV, TEST, TRISE, TSET
!!$      REAL*4 SUNLIM
!!$      CHARACTER*80 MSG
!!$!------------------------------------------------------------------------
!!$! Code:
!!$      TEST = D_ELEV(0.)
!!$      TRISE = S_RISE(0.)
!!$      TSET = S_SET(0.)
!!$      IF (TEST.LT.0) THEN
!!$         IF (TRISE.LT.25) THEN
!!$            WRITE(MSG,'(a,f6.2,a)') NEXT.SOU.NAME
!!$     $      //' is set and will rise at ',TRISE,' h LST'
!!$            CALL  pakoMessage(8,3,'SOURCE',MSG)
!!$         ELSE
!!$            CALL  pakoMessage(8,3,'SOURCE',NEXT.SOU.NAME
!!$     $      //' cannot be observed (low declnation).')
!!$         ENDIF
!!$      ELSEIF (TEST.LT.20.) THEN
!!$         WRITE(MSG,300) NEXT.SOU.NAME//' is at low elevation: ',
!!$     $   TEST,' degrees.'
!!$         CALL  pakoMessage(4,2,'SOURCE',MSG)
!!$      ELSE
!!$         WRITE(MSG,300) 'Elevation of '
!!$     $   //NEXT.SOU.NAME//' is ',TEST,' degrees.'
!!$         CALL  pakoMessage(2,1,'SOURCE',MSG)
!!$      ENDIF
!!$      IF (TEST.GT.0) THEN
!!$         IF (D_SHADOW) THEN
!!$            CALL  pakoMessage(4,2,'SOURCE','Antenna shadowing will occur')
!!$         ENDIF
!!$      ENDIF
!!$      IF (TSET.GE.0 .AND. TSET.LE.24.) THEN
!!$         WRITE(MSG,'(a,f6.2,a)') 'Setting time : ',TSET,'h LST'
!!$         CALL MESSAGE (2,1,'SOURCE',MSG)
!!$      ENDIF
!!$      WRITE(MSG,300) NEXT.SOU.NAME//' is at ',D_SUN,' degrees from Sun.'
!!$      CALL SIC_GET_REAL('SUN_LIMIT',SUNLIM,ERROR)
!!$      IF (D_SUN.LT.30) THEN
!!$         CALL  pakoMessage(8,3,'SOURCE',MSG)
!!$      ELSEIF (.NOT.ERROR .AND. D_SUN.LT.SUNLIM) THEN
!!$         CALL  pakoMessage(6,2,'SOURCE',MSG)
!!$      ELSEIF (D_SUN.LT.50) THEN
!!$         CALL  pakoMessage(4,1,'SOURCE',MSG)
!!$      ENDIF
!!$      RETURN
!!$300   FORMAT(A,F6.2,A)
!!$      END SUBROUTINE CHECK_POSITION
!!!
!!!
  Subroutine DECDEG(CHAIN,LCHAIN,Value,NDIV,ERROR)
    !----------------------------------------------------------------------
    ! ASTRO	Internal routine
    !	Decode a sexagesimal character string into angle value in
    !	DEGREES. Formats can be
    !	61.5000000	or	161
    !	61:30.0000	or	161:40
    !	61:45:50.9	or	161:40:50
    ! Arguments :
    !	CHAIN	C*(*)	Character string		Input
    !	LCHAIN	I	length of			Input
    !	VALUE	R*8	Value of angle(radians)		Output
    !	NDIV	I	360/24				Input
    !	ERROR	L	Error flag
    ! No subroutines
    ! No common
    !----------------------------------------------------------------------
    Character*(*) CHAIN
    Real*8 Value,CONV,DEGREE,MINUTE,SECOND
    Integer NDIV,NDOT,NLEN,NMIN,NSEC, LENC, LCHAIN
    Logical MINUS, ERROR
    !
    NLEN = LENC(CHAIN(1:LCHAIN))
    !
    ! Zeroth find minus sign if any
    NDOT = Index(CHAIN(1:NLEN),'-')
    MINUS = NDOT.Ne.0
    !
    ! First find if any dot in Chain
    NDOT = Index(CHAIN(1:NLEN),'.')
    If (NDOT.Eq.0) Then
       NDOT=NLEN+1
    Endif
    !
    ! Set CONV factor
    CONV = 360.D0/NDIV
    !
    ! Find if any minute Field
    NMIN = Index(CHAIN(1:NLEN),':')
    If (NMIN.Eq.0) Then
       ! No Minutes Field
       Read(CHAIN(1:NLEN),100,ERR=99) DEGREE
       Value = CONV*DEGREE
       Return
    Endif
    !
    ! Find if any Second field
    NSEC = Index(CHAIN(NMIN+1:NLEN),':')
    If (NSEC.Eq.0) Then
       ! No Seconds Field
       If (NDOT.Ne.NMIN+3) Then
          ! Minutes Field not two characters
          Goto 99
       Endif
       Read(CHAIN(NMIN+1:NLEN),100,ERR=99) MINUTE
       If (MINUTE.Ge.60.D0) Then
          Write(6,101) 'E-ANGLE, more than 60 minutes...'
          ERROR = .True.
          Return
       Endif
       Read(CHAIN(1:NMIN-1),100,ERR=99) DEGREE
       If (.Not.MINUS) Then
          Value = CONV*(DEGREE+MINUTE/60.D0)
       Else
          Value = CONV*(DEGREE-MINUTE/60.D0)
       Endif
    Elseif (NSEC.Ne.3) Then
       ! Minutes Field not two characters
       Goto 99
    Else
       ! Seconds Field is present
       If (NDOT.Ne.NMIN+6) Then
          ! Seconds Field not two characters
          Goto 99
       Endif
       Read(CHAIN(NMIN+4:NLEN),100,ERR=99) SECOND
       If (SECOND.Ge.60.D0) Then
          Write(6,101) 'E-ANGLE,  more than 60 seconds...'
          ERROR = .True.
          Return
       Endif
       Read(CHAIN(NMIN+1:NMIN+2),100,ERR=99) MINUTE
       If (MINUTE.Ge.60.D0) Then
          Write(6,101) 'E-ANGLE,  more than 60 minutes...'
          ERROR = .True.
          Return
       Endif
       Read(CHAIN(1:NMIN-1),100,ERR=99) DEGREE
       If (.Not.MINUS) Then
          Value = CONV*(DEGREE+MINUTE/60.D0+SECOND/3600.D0)
       Else
          Value = CONV*(DEGREE-MINUTE/60.D0-SECOND/3600.D0)
       Endif
    Endif
    Return
    !
99  Write(6,101) 'E-ANGLE,  Invalid angle format'
    ERROR = .True.
    Return
100 Format(F20.0)
101 Format(1X,A)
  End Subroutine DECDEG
!!!
!!!
  Subroutine CVDEG (ARG,NARG,ANG,DVAL,ERROR)
    !------------------------------------------------------------------------
    ! POM	internal routine
    !	converts a chain into RADIANS according to angle unit
    !	arg	c*1	chain to be decoded	Input
    !	narg	I	length of arg		Input
    !	ang	C*1	angle unit : H = hours, M = arc minutes,
    !			D = arc degrees, S = arc seconds	Input
    !	dval	R*8	result			Output
    !	error	L*1	error code		Output
    !
    ! Dummy -----------------------------------------------------------------
    Character*(*) ARG, ANG
    Integer NARG, NDIV1
    Logical ERROR
    Real*8 DVAL, PI
    Parameter (PI=3.141592653589793D0)
    ! Code ------------------------------------------------------------------
    If (ANG.Eq.'S') Then
       Read(ARG(1:NARG),'(f20.0)',ERR=900) DVAL
       DVAL = DVAL / 3600.
    Else
       If (ANG.Eq.'M') Then
          NDIV1 = 21600
       Elseif (ANG.Eq.'H') Then
          NDIV1 = 24
       Else
          NDIV1 = 360
       Endif
       Call DECDEG(ARG,NARG,DVAL,NDIV1,ERROR)
       If(ERROR) Return
       DVAL = DVAL * PI /180D0
    Endif
    Return
900 Write(6,100) 'E-CVDEG,  error decoding ',ARG(1:NARG)
    ERROR = .True.
    Return
100 Format(1X,A,A)
  End Subroutine CVDEG
!!!
!!!
  Subroutine FIND_VTYPE (PAR,VTYPE)
    Character*(*) PAR
    Integer VTYPE
    ! Velocity type
    ! (note that for CLASS: 3 means observatory, 4 earth-moon baryc.)
    Integer V_LSR, V_HELIO, V_EARTH, V_NULL, V_UNKNOWN
    Parameter (V_LSR = 1)
    Parameter (V_HELIO = 2)
    Parameter (V_EARTH = 3)
    Parameter (V_NULL = 4)
    Parameter (V_UNKNOWN = 0)
    !
!!$      Write (6,*) "   ---> SR: FIND_VTYPE "
!!$      Write (6,*) "            par :", par
    !
    If (PAR(1:1).Eq.'l') Then
       VTYPE = V_LSR                   !LSR
    Elseif (PAR(1:1).Eq.'h') Then
       VTYPE = V_HELIO                 !Helio
    Elseif (PAR(1:1).Eq.'e') Then
       VTYPE = V_EARTH                 !Earth
    Elseif (PAR(1:1).Eq.'n') Then
       VTYPE = V_NULL                  !Null
    Else
       VTYPE = V_UNKNOWN
    Endif
    !
    !D      Write (6,*) "            vtype :", vtype
    !
  End Subroutine FIND_VTYPE
!!!
!!!
  Subroutine checkSOURCE(NAME,LNAME,PAR,LPAR,FOUND)
    Character*(*) NAME,PAR
    Integer LNAME,LPAR
    Logical FOUND
    !
    Integer J,K,J1,J2,NAME_OUT,JK
    Character*80 NOM
    Data NAME_OUT/0/
    !
    ! Syntax  is   NAME1[|NAME2[|NAME3]]
    !
!!$      Write (6,*) "   ---> SR: checkSource "
!!$      Write (6,*) "            par :", par
    !
    If (.Not.FOUND) Then
       JK = 1
       Do While (.Not.FOUND .And. JK.Lt.LPAR)
          J = Index(PAR(JK:LPAR),NAME(1:LNAME))
          FOUND = J.Ne.0
          If (.Not.FOUND) Return
          K = JK-1+J-1
          If (K.Gt.0 .And. PAR(K:K).Ne.'|') FOUND = .False.
          K = JK-1+J+LNAME
          If (K.Le.LPAR .And. PAR(K:K).Ne.'|') FOUND = .False.
          JK = K
       Enddo
       If (.Not.FOUND) Return
       ! Use only one name if NAME_OUT is set
       If (NAME_OUT.Eq.0) Then
          PAR = NAME(1:LNAME)
          LPAR = LNAME
          ! Use all names
       Elseif (NAME_OUT.Eq.-1) Then
          Return
       Endif
    Elseif (NAME_OUT.Eq.-1) Then
       Return
    Else
       ! Extract name of order NAME_OUT
       J = 0
       J1 = 1
       Do While (.True.)
          J2 = Index(PAR(J1:LPAR),'|')
          If (J2.Eq.0) Then
             NOM = PAR(J1:LPAR)
             LPAR = LPAR-J1+1
             PAR = NOM
             Return
          Endif
          J2 = J2+J1-2
          If (J.Eq.NAME_OUT) Then
             NOM = PAR(J1:J2)
             LPAR = J2-J1+1
             PAR = NOM
             Return
          Endif
          J1 = J2+2
          J = J+1
       Enddo
    Endif
  End Subroutine checkSource
!!!
!!!
  Subroutine writeXMLsource(programName,LINE,commandToSave,                      &
       &        iUnit, ERROR)                                                    !
    !
    ! *** Variables   ***
    Include 'inc/variables/headerForSaveMethods.inc'
    !
    Logical :: errorXML
    !
    Character (len=lenVar) :: valueC
    Character (len=lenVar) :: valueComment
    !
    !D      write (6,*)  "      modulePakoSource --> SR: writeXMLsource "
    !
    ! TBD: solve problem with "special characters" in source name: <>& 
    !      --> write source information as XML table like receivers & backends
    !
    Include 'inc/startXML/source.inc'
    !
    Return
  End Subroutine writeXMLsource
!!!
!!!
  Subroutine writeXMLradialVelocity(programName,LINE,commandToSave,              &
       &        iUnit, ERROR)                                                    !
    !
    ! *** Variables   ***
    Include 'inc/variables/headerForSaveMethods.inc'
    !
    Logical :: errorXML
    !
    Character (len=24) :: valueC
    Character (len=48) :: valueComment
    !
    ERROR = .False.
    !
    !D    Write (6,*)  "      modulePakoSource --> SR: writeXMLradialVelocity "
    !
    Include 'inc/startXML/radialVelocity.inc'
    !
    Return
  End Subroutine writeXMLradialVelocity
!!!
!!!
  Subroutine writeXMLoffsets(programName,LINE,commandToSave,                     &
       &        iUnit, ERROR)                                                    !
    !
    ! *** Variables   ***
    Include 'inc/variables/headerForSaveMethods.inc'
    !
    Logical :: errorXML
    !
    Integer :: ii
    Integer :: nCount
    !
    Character (len=24) :: valueC
    Character (len=48) :: valueComment
    !
    ERROR = .False.
    !
    !D      Write (6,*)  "      modulePakoSource --> SR: writeXMLoffsets "
    !
    Include 'inc/startXML/startXMLoffsets.inc'
    !
    Return
  End Subroutine writeXMLoffsets
!!!
!!!
  Subroutine writeXMLtopology(programName,LINE,commandToSave,                    &
       &     iUnit, ERROR)                                                       !
    !
    ! *** inc/variables   ***
    Include 'inc/variables/headerForSaveMethods.inc'
    !
    Logical :: errorXML
    !
    Character (len=24) :: valueC
    !
    ERROR = .False.
    !
    !D        Write (6,*)  "      modulePakoSource --> SR: writeXMLtopology "
    !D        !
    !D        Write (6,*)  "       GV%topology = ",  GV%topology
    !
    If (.Not. GV%topology.Eq."none") Then
       !
       Call pakoXMLwriteStartElement("RESOURCE","topology",                      &
            &                         error=errorXML)                            !
       !
       valueC = GV%topology
       Call pakoXMLcase(valueC,error=errorXML)
       Call pakoXMLwriteElement("PARAM","azimuthWrap",valueC,                    &
            &                         dataType="char",                           &
            &                         error=errorXML)                            !
       !
       Call pakoXMLwriteEndElement  ("RESOURCE","topology",                      &
            &                         error=errorXML)                            !
       !
    End If
    !
    Return
  End Subroutine writeXMLtopology
!!!
!!!
  Subroutine writeXMLpointingCorrections(programName,LINE,commandToSave,         &
       &     iUnit, ERROR)                                                       !
    !
    ! *** Variables   ***
    Include 'inc/variables/headerForSaveMethods.inc'
    !
    Logical :: errorXML
    !
    Character (len=24) :: valueC
    Character (len=48) :: valueComment
    !
    ERROR = .False.
    !
    !D  Write (6,*)  " modulePakoSource --> SR: writeXMLpointingCorrections "
    !
    Call pakoXMLwriteStartElement("RESOURCE","pointingCorrections",              &
         &                         error=errorXML)                               !
    !
    Write (valueC,*)       Real(0.0*arcsec)
    Write (valueComment,*) Real(0.0), au%arcsec
    Call pakoXMLwriteElement("PARAM","pointingCorrectionP1",valueC,              &
         &                         "rad", "double",                              &
         &                         comment=valueComment,                         &
         &                         error=errorXML)                               !
    !
    Write (valueC,*)       Real(GVpCorr%azimuthCorrection*arcsec)
    Write (valueComment,*) Real(GVpCorr%azimuthCorrection), au%arcsec
    Call pakoXMLwriteElement("PARAM","pointingCorrectionP2",valueC,              &
         &                         "rad", "double",                              &
         &                         comment=valueComment,                         &
         &                         error=errorXML)                               !
    !
    Write (valueC,*)       Real(0.0*arcsec)
    Write (valueComment,*) Real(0.0), au%arcsec
    Call pakoXMLwriteElement("PARAM","pointingCorrectionP3",valueC,              &
         &                         "rad", "double",                              &
         &                         comment=valueComment,                         &
         &                         error=errorXML)                               !
    !
    Write (valueC,*)       Real(0.0*arcsec)
    Write (valueComment,*) Real(0.0), au%arcsec
    Call pakoXMLwriteElement("PARAM","pointingCorrectionP4",valueC,              &
         &                         "rad", "double",                              &
         &                         comment=valueComment,                         &
         &                         error=errorXML)                               !
    !
    Write (valueC,*)       Real(0.0*arcsec)
    Write (valueComment,*) Real(0.0), au%arcsec
    Call pakoXMLwriteElement("PARAM","pointingCorrectionP5",valueC,              &
         &                         "rad", "double",                              &
         &                         comment=valueComment,                         &
         &                         error=errorXML)                               !
    !
    Write (valueC,*)       Real(GVpCorr%elevationCorrection*arcsec)
    Write (valueComment,*) Real(GVpCorr%elevationCorrection), au%arcsec
    Call pakoXMLwriteElement("PARAM","pointingCorrectionP7",valueC,              &
         &                         "rad", "double",                              &
         &                         comment=valueComment,                         &
         &                         error=errorXML)                               !
    !
    Write (valueC,*)       Real(0.0*arcsec)
    Write (valueComment,*) Real(0.0), au%arcsec
    Call pakoXMLwriteElement("PARAM","pointingCorrectionP8",valueC,              &
         &                         "rad", "double",                              &
         &                         comment=valueComment,                         &
         &                         error=errorXML)                               !
    !
    Write (valueC,*)       Real(0.0*arcsec)
    Write (valueComment,*) Real(0.0), au%arcsec
    Call pakoXMLwriteElement("PARAM","pointingCorrectionP9",valueC,              &
         &                         "rad", "double",                              &
         &                         comment=valueComment,                         &
         &                         error=errorXML)                               !
    !
    Write (valueC,*)       Real(0.0*arcsec)
    Write (valueComment,*) Real(0.0), au%arcsec
    Call pakoXMLwriteElement("PARAM","pointingCorrectionRxHorizontal",valueC,    &
         &                         "rad", "double",                              &
         &                         comment=valueComment,                         &
         &                         error=errorXML)                               !
    !
    Write (valueC,*)       Real(0.0*arcsec)
    Write (valueComment,*) Real(0.0), au%arcsec
    Call pakoXMLwriteElement("PARAM","pointingCorrectionRxVertical",valueC,      &
         &                         "rad", "double",                              &
         &                         comment=valueComment,                         &
         &                         error=errorXML)                               !
    !
    Call pakoXMLwriteEndElement  ("RESOURCE","pointingCorrections",              &
         &                         error=errorXML)                               !
    !
    Return
  End Subroutine writeXMLpointingCorrections
!!!
!!!
  Subroutine writeXMLfocusCorrections(programName,LINE,commandToSave,            &
       &        iUnit, ERROR)                                                    !
    !
    ! *** Variables   ***
    Include 'inc/variables/headerForSaveMethods.inc'
    !
    Logical :: errorXML
    !
    Character (len=24) :: valueC
    Character (len=48) :: valueComment
    !
    !D        Write (6,*)  "      modulePakoSource --> SR: writeXMLfocusCorrections "
    !
    ERROR = .False.
    !
    Call pakoXMLwriteStartElement("RESOURCE","focusCorrections",                 &
         &                         error=errorXML)                               !
    !
    Write (valueC,*)       Real(GVfCorrX%focusCorrection)
    Write (valueComment,*) Real(GVfCorrX%focusCorrection), "mm"
!!$    Write (valueC,*)       Real(0.0)
!!$    Write (valueComment,*) Real(0.0), "mm"
    Call pakoXMLwriteElement("PARAM","focusCorrectionX",valueC,                  &
         &                         "mm", "double",                               &
         &                         comment=valueComment,                         &
         &                         error=errorXML)                               !
    !
    Write (valueC,*)       Real(GVfCorrY%focusCorrection)
    Write (valueComment,*) Real(GVfCorrY%focusCorrection), "mm"
!!$    Write (valueC,*)       Real(0.0)
!!$    Write (valueComment,*) Real(0.0), "mm"
    Call pakoXMLwriteElement("PARAM","focusCorrectionY",valueC,                  &
         &                         "mm", "double",                               &
         &                         comment=valueComment,                         &
         &                         error=errorXML)                               !
    !
    Write (valueC,*)       Real(GVfCorr%focusCorrection)
    Write (valueComment,*) Real(GVfCorr%focusCorrection), "mm"
    Call pakoXMLwriteElement("PARAM","focusCorrectionZ",valueC,                  &
         &                         "mm", "double",                               &
         &                         comment=valueComment,                         &
         &                         error=errorXML)                               !
    !
    Call pakoXMLwriteEndElement  ("RESOURCE","focusCorrections",                 &
         &                         error=errorXML)                               !
    !
    Return
  End Subroutine writeXMLfocusCorrections
!!!
!!!
End Module modulePakoSource
!!!
!!!

