!
!----------------------------------------------------------------------
!
! <DOCUMENTATION name="modulePakoFocus">
!   <VERSION>
!                Id: modulePakoFocus.f90,v 1.2.3 2014-12-15 Hans Ungerechts
!                Id: modulePakoFocus.f90,v 1.2.3 2014-12-04 Hans Ungerechts
!                Id: modulePakoFocus.f90,v 1.2.3 2014-10-27 Hans Ungerechts
!                Id: modulePakoFocus.f90,v 1.2.3 2014-09-24 Hans Ungerechts
!                Id: modulePakoFocus.f90,v 1.2.3 2014-02-03 Hans Ungerechts
!                                          1.2.1 2012-08-16 Hans Ungerechts 
!                based on
!                Id: modulePakoFocus.f90,v 1.1.0 2009-03-25 Hans Ungerechts
!   </VERSION>
!   <PROGRAM>
!                Pako
!   </PROGRAM>
!   <FAMILY>
!                Observing Modes
!   </FAMILY>
!   <SIBLINGS>
!                Calibrate
!                Focus
!                OnOff
!                OtfMap
!                Pointing
!                Tip
!                Track
!                VLBI
!   </SIBLINGS>        
!
!   Pako module for command: FOCUS
!
! </DOCUMENTATION> <!-- name="modulePakoFocus" -->
!
!----------------------------------------------------------------------
!
Module modulePakoFocus
  !
  Use modulePakoTypes
  Use modulePakoMessages
  Use modulePakoGlobalParameters
  Use modulePakoLimits
  Use modulePakoXML
  Use modulePakoUtilities
  Use modulePakoPlots
  Use modulePakoDisplayText
  Use modulePakoGlobalVariables
  Use modulePakoSubscanList
  Use modulePakoReceiver
  Use modulePakoBackend
  Use modulePakoSource
  Use modulePakoSwBeam
  Use modulePakoSwFrequency
  Use modulePakoSwWobbler
  Use modulePakoSwTotalPower
  Use modulePakoDIYlist
  !
  Use gbl_message
  !
  Implicit None
  Save
  Private
  Public :: Focus, displayFocus, saveFocus, startFocus
  !     
  ! *** Variables for Focus ***
  Include 'inc/variables/variablesFocus.inc'
  !
  Real    :: swWobblerAmplitude       = 0.0
  Real    :: swWobblerShiftAzimuth    = 0.0       !   Shift in Azimuth when Wobbler Switching
  Real    :: swWobblerShiftElevation  = 0.0       !   Shift in Elevation when Wobbler Switching
  !
!!!   
!!!   
Contains
!!!
!!!
  Subroutine FOCUS(programName,line,command, ERROR)
    !
    ! *** Arguments ***
    Include 'inc/variables/headerForCommandHandler.inc'
    !
    ! *** standard working variables ***
    Include 'inc/variables/standardWorkingVariables.inc'
    !
    Logical :: isConnected   = .False.
    !
    Character (len=lenCh) ::  bolometerName
    !
    ! *** special working variables:   ***
    !
    !     TBD: the following shall be replaced by a SR reading from XML:
    Include 'inc/ranges/rangesFocus.inc'
    !
    ERROR = .False.
    !
    Call pako_message(seve%t,programName,                                        &
         &  " module Focus, v 1.2.3 2014-09-24 ---> SR: Focus ")                 ! trace execution
    !
    ! *** initialize:   ***
    If (.Not.isInitialized) Then
       Include 'inc/variables/setDefaults.inc'
       isInitialized = .True.
    Endif
    !
    ! *** 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  ***
    Call checkNofParameters(command,                                             &
         &     0, 1,                                                             &
         &     nArguments,                                                       &
         &     errorNumber)                                                      !
    ERROR = ERROR .Or. errorNumber
    !
    ! *** read Parameters, Options (to detect errors)            
    !     and check for validity and ranges                      
    If (.Not. ERROR) Then
       Call pakoMessageSwitch (setOn = .True.)
       Include 'inc/parameters/parametersLengthFocus.inc'
       Include 'inc/options/readOptionsFocus.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'
       Endif
    Endif
    !
    ! *** Read Parameters, Options (again, after defaults!)   ***
    ! *** and check for validity and ranges                   ***
    If (.Not. ERROR) Then
       Call pakoMessageSwitch (setOff = .True.)
       Include 'inc/parameters/parametersLengthFocus.inc'
       Include 'inc/options/readOptionsFocus.inc'
    End If
    Call pakoMessageSwitch (setOn = .True.)
    !
    ! *** check consistency and                           ***
    ! *** store into temporary (intermediate) variables   ***
    If (.Not.ERROR) Then
       !
       errorInconsistent = .False.
       !
       If (vars(iIn)%tSubscan .Lt. 5*GV%tRecord) Then
          If (vars(iIn)%tSubscan .Lt. 3*GV%tRecord) Then
             errorInconsistent = .True.
             Write (messageText,*)    "must be at least 3 times "                &
                  &                // "tRecord = tPhase*nPhases*nCycles = "      &
                  &                 ,  GV%tRecord                                &
                  &                 , "of switching mode "//GV%switchingMode     !
             Call pakoMessage(priorityE,severityE,                               &
                  &           command(1:l)//"/"//"tSubscan",messageText)         !
          Else
             Write (messageText,*)    "should be at least 5 times "              &
                  &                // "tRecord = tPhase*nPhases*nCycles = "      &
                  &                 ,  GV%tRecord                                &
                  &                 , "of switching mode "//GV%switchingMode     !
             Call pakoMessage(priorityW,severityW,                               &
                  &           command(1:l)//"/"//"tSubscan",messageText)         !
          End If
       End If
       !
       If (GV%switchingMode.Eq.swMode%Freq) Then
          errorInconsistent = .True.
          GV%notReadyFocus  = .True.
          Write (messageText,*)  "will not work with switching mode ",           &
               &                  swModePako%Freq                                !
          Call PakoMessage(priorityE,severityE,command,messageText)
       End If
       !
       If (.Not. errorInconsistent) Then
          vars(iTemp) = vars(iIn)
       End If
       !
    End If
    !
    ERROR = ERROR .Or. errorInconsistent
    !
    ! *** store from temporary into final variables ***
    If (.Not.ERROR) Then
       vars(iValue)  = vars(iTemp)
    End If
    !
    ! *** display values ***
    If (.Not.ERROR) Then
       Call displayFocus
    End If
    !
    ! *** set "selected" observing mode, analyze & plot ***
    If (.Not.error) Then
       GV%observingMode     = OM%Focus
       GV%observingModePako = OMpako%Focus
       GV%omSystemName      = GPnone
       GV%notReadySecondaryRafterOM = .False.
       !D       Write (6,*) '      GV%notReadySecondaryRafterOM: ',                    &
       !D            &             GV%notReadySecondaryRafterOM
       GV%notReadySWafterOM = .False.
       GV%notReadyFocus     = .False.
       focusCommand         = line(1:lenc(line))
       Call analyzeFocus (errorA)
       Call plotFocus (errorP)
       !
       ! TBD:
!!$       Call listDIYlist (error)
    End If
    !
    Return
  End Subroutine FOCUS
!!!
!!!
  Subroutine displayFocus
    !
    Include 'inc/variables/standardWorkingVariables.inc'
    !
    Character(len=24)  :: command
    !
    Include 'inc/display/commandDisplayFocus.inc'
    !
  End Subroutine displayFocus
!!!
!!!
  Subroutine analyzeFocus (errorA)
    !
    ! <DOCUMENTATION name="analyzeFocus">
    !
    ! The sequence of focus subscans is determined by 
    ! lengthFocus /nSubscans /otfFocus
    !
    !  lengthFocus     ! total length [mm] of the focus scan 
    !  /nSubscans      ! number of focus subscans
    !  /otfFocus       ! not yet implemented
    !
    !  focus subscan 1 is at offset  0.0
    !  focus subscan 2 is at offset  lengthFocus/2
    !  in case /nSubscans 3:
    !  focus subscan 3 is at offset -lengthFocus/2
    !  in case /nSubscans >3:
    !  focus subscan 3 is at offset  lengthFocus/2
    !  focus subscan 4 is at offset -lengthFocus/2
    !  focus subscan 5 is at offset -lengthFocus/2
    !  focus subscan 6 is at offset  0.0
    !  (etc.)
    !
    ! </DOCUMENTATION> <!-- name="analyzeFocus" -->
    !
    Include 'inc/variables/standardWorkingVariables.inc'
    !
    Integer              :: nScan 
    Character (len=12)   :: aUnit, sUnit
    Integer              :: iSS           = 0     ! counts subcans/segment
    !
    Call pako_message(seve%t,"PAKO",                                             &
         &  " module Focus, v 1.2.3 2014-09-24  --> SR: analyzeFocus ")          !                      
    !
    errorA = .False.
    !
    ! TBD:  proper scan numbers
    nScan     = 1111
    aUnit     = GV%angleUnitC
    sUnit     = GV%speedUnitC
    !
    swWobblerAmplitude       =  0.0
    swWobblerShiftAzimuth    =  0.0
    swWobblerShiftElevation  =  0.0
    iSS  = 0
    !
    If (GV%switchingMode .Eq. swMode%wobb) Then   
       swWobblerAmplitude = 0.5*Abs(GV%wOffset(2)-GV%wOffset(1))
       swWobblerShiftAzimuth   =                                                 &
            &          -swWobblerAmplitude*Cos(GV%secondaryRotation/180.0*Pi)    !
       swWobblerShiftElevation =                                                 &
            &           swWobblerAmplitude*Sin(GV%secondaryRotation/180.0*Pi)    !
       If (Abs(swWobblerShiftAzimuth)  .Lt.0.1e-11) swWobblerShiftAzimuth   = 0.0
       If (Abs(swWobblerShiftElevation).Lt.0.1e-11) swWobblerShiftElevation = 0.0
       Write (messageText,*)                                                     &
            &      "SWWOBBLER implies: subscans will be shifted by: "            !
       Call pakoMessage(priorityI,severityI,'FOCUS',messageText)
       Write (messageText,*)                                                     &
            &      swWobblerShiftAzimuth, " [arc sec] in azimuth"                !
       Call pakoMessage(priorityI,severityI,'FOCUS',messageText)
       Write (messageText,*)                                                     &
            &      swWobblerShiftElevation, " [arc sec] in elevation"            !
       Call pakoMessage(priorityI,severityI,'FOCUS',messageText)
    End If
    !
    ! TBD: calibration subscans
    !
    ! ***
    !
    If (vars(iValue)%doTune) Then
       iSS = iSS+1                                                               !  !!  tune subscan
       segList(iSS)            =  segDefault  
       segList(iSS)%newSubscan =  .True.
       segList(iSS)%scanNumber =  nScan
       segList(iSS)%ssNumber   =  iSS
       segList(iSS)%segNumber  =  1
       segList(iSS)%ssType     =  ss%tune
       segList(iSS)%segType    =  seg%track
       segList(iSS)%angleUnit  =  aUnit
       segList(iSS)%speedUnit  =  sUnit
       segList(iSS)%flagOn     =  .True.
       segList(iSS)%flagRef    =  .False.
       !
       segList(iSS)%flagDropin =  .False.
       segList(iSS)%flagTune   =  vars(iIn)%doTune
       !
       segList(iSS)%pStart     =  vars(iValue)%offsetTune
       segList(iSS)%pEnd       =  segList(iSS)%pStart
       ! TBD: system from source command
       segList(iSS)%systemName =  offsetSystemChoices(iHORIZONTRUE)
       segList(iSS)%altOption  =  'tSegment'
       segList(iSS)%speedStart =  0.0
       segList(iSS)%speedEnd   =  0.0
       segList(iSS)%tSegment   =  vars(iValue)%tTune
       ! TBD:        segList(iSS)%tRecord    =  
       Write (messageText,*)  "  subscan #:   ", iSS, " ",                       &
            &           segList(iSS)%ssType,                                     &
            &           segList(iSS)%pStart, segList(iSS)%tSegment               !
       Call pakoMessage(priorityI,severityI,"Focus  Analyze",messageText)
       !
    End If
    !
    ! ***
    If (vars(iValue)%nSubscans .Ge. 1) Then
       !
       iSS = iSS+1                                                               !  !!  1st Focus subscan
       segList(iSS)            =  segDefault                    ! 
       segList(iSS)%newSubscan =  .True.
       segList(iSS)%scanNumber =  nScan
       segList(iSS)%ssNumber   =  iSS
       segList(iSS)%segNumber  =  1
       segList(iSS)%ssType     =  ss%onFocus
       segList(iSS)%segType    =  seg%track
       segList(iSS)%angleUnit  =  aUnit
       segList(iSS)%speedUnit  =  sUnit
       segList(iSS)%flagOn     =  .True.
       segList(iSS)%flagRef    =  .False.
       segList(iSS)%pStart     =  xyPointType(0.0,0.0)
       segList(iSS)%pEnd       =  segList(iSS)%pStart
       ! TBD: system from source command
       segList(iSS)%systemName =  offsetSystemChoices(iHORIZONTRUE)
       segList(iSS)%altOption  =  'tSegment'
       segList(iSS)%speedStart =  0.0
       segList(iSS)%speedEnd   =  0.0
       segList(iSS)%tSegment   =  vars(iValue)%tSubscan
       ! TBD:        segList(iSS)%tRecord    =  
       segList(iSS)%focusOffset = 0.0
       segList(iSS)%directionFocus = vars(iValue)%directionFocus
       !
       If (GV%switchingMode .Eq. swMode%wobb) Then   
          segList(iSS)%pStart%x  = segList(iSS)%pStart%x +swWobblerShiftAzimuth
          segList(iSS)%pEnd%x    = segList(iSS)%pEnd%x   +swWobblerShiftAzimuth
          segList(iSS)%pStart%y  = segList(iSS)%pStart%y +swWobblerShiftElevation 
          segList(iSS)%pEnd%y    = segList(iSS)%pEnd%y   +swWobblerShiftElevation
       End If
       !
       Write (messageText,*)  "  subscan #:   ", iSS, " ",                       &
            &           segList(iSS)%ssType,                                     &
            &           segList(iSS)%directionFocus, segList(iSS)%focusOffset    !
       Call pakoMessage(priorityI,severityI,"Focus  Analyze",messageText)
       !
    End If
    !
    If (vars(iValue)%nSubscans .Ge. 2) Then
       !
       iSS = iSS+1
       segList(iSS)            =  segList(iSS-1)
       segList(iSS)%focusOffset = vars(iValue)%lengthFocus/2.0
       !
       Write (messageText,*)  "  subscan #:   ", iSS, " ",                       &
            &           segList(iSS)%ssType,                                     &
            &           segList(iSS)%directionFocus, segList(iSS)%focusOffset    !
       Call pakoMessage(priorityI,severityI,"Focus  Analyze",messageText)
       !
    End If
    !
    If (vars(iValue)%nSubscans .Eq. 3) Then
       !
       iSS = iSS+1
       segList(iSS)            =  segList(iSS-1)
       segList(iSS)%focusOffset = -vars(iValue)%lengthFocus/2.0
       !
       Write (messageText,*)  "  subscan #:   ", iSS, " ",                       &
            &           segList(iSS)%ssType,                                     &
            &           segList(iSS)%directionFocus, segList(iSS)%focusOffset    !
       Call pakoMessage(priorityI,severityI,"Focus  Analyze",messageText)
       !
    End If
    !
    If (vars(iValue)%nSubscans .Gt. 3) Then
       !
       Do ii = 3, vars(iValue)%nSubscans, 1
          !
          iSS = iSS+1
          segList(iSS)             =  segList(iSS-1)
          !
          Select Case (Mod(ii,6))
             !
          Case (0)
             segList(iSS)%focusOffset = 0.0
          Case (1)
             segList(iSS)%focusOffset = 0.0
          Case (2)
             segList(iSS)%focusOffset = vars(iValue)%lengthFocus/2.0
          Case (3)
             segList(iSS)%focusOffset = vars(iValue)%lengthFocus/2.0
          Case (4)
             segList(iSS)%focusOffset = -vars(iValue)%lengthFocus/2.0
          Case (5)
             segList(iSS)%focusOffset = -vars(iValue)%lengthFocus/2.0
          Case Default
             !
          End Select
          !
          Write (messageText,*)  "  subscan #:   ", iSS,  " ",                   &
               &           segList(iSS)%ssType,                                  &
               &           segList(iSS)%directionFocus, segList(iSS)%focusOffset !
          Call pakoMessage(priorityI,severityI,"Focus  Analyze",messageText)
          !
       End Do
       !
    End If
    !
    ! ***
    nSegments = iSS
    !
    Write (messageText,*)  "   number of Subscans/Segments: ", nSegments
    Call pakoMessage(priorityI,severityI,"Focus "//" Analyze",messageText)
    !
    Return 
    !
  End Subroutine analyzeFocus
!!!
!!!
  Subroutine plotFocus (errorP)
    !
    !**   Variables  for Plots   ***
    Include 'inc/variables/headerForPlotMethods.inc'
    !
    !**   standard working variables   ***
    Include 'inc/variables/standardWorkingVariables.inc'
    !
    errorP = .False.
    !
    Call pako_message(seve%t,"FOCUS",                                            &
         &  " module Focus, v 1.2.3 2014-12-15 --> SR: plotFocus ")              ! trace execution
    !
    Call configurePlots
    !
    Call plotTrackP( xyPointType(0.0,0.0),                                       &
         &           errorP,                                                     &
         &           Type=ss%on)                                                 !
    !
    If (vars(iValue)%doTune) Then
       Call plotTrackP( vars(iValue)%offsetTune,                                 &
            &           errorP,                                                  &
            &           Type=ss%tune)                                            !
    End If
    !
    ! TBD:
!!$    Call plotDIYlist(errorP)
!!$    !
    !
    If (errorP)                                                                  &
         &        Call pakoMessage(priorityE,severityE,                          &
         &        'Focus',' could not plot ')                                    !
    !
    Return
  End Subroutine plotFocus
!!!
!!!
  Subroutine saveFocus(programName,LINE,commandToSave,                           &
       &         iUnit, ERROR)                                                   !
    !
    ! *** Variables   ***
    Include 'inc/variables/headerForSaveMethods.inc'
    !
    contC = contNN
    !
    Include 'inc/commands/saveCommand.inc'
    !
!!OLD      doContinue = .True.
    !
    contC = contCC
    !
    Include 'inc/parameters/saveLengthFocus.inc'
    !
    !TBD:      Include 'inc/options/saveCalibrate.inc'
    Include 'inc/options/saveDirectionFocus.inc'
    Include 'inc/options/saveFeBe.inc'
    Include 'inc/options/saveNsubscans.inc'
    !
    If (.Not.vars(iValue)%doTuneSet) Then
       contC = contCN
    End If
    !
    Include 'inc/options/saveTsubscan.inc'
    !TBD:      Include 'inc/options/saveOtfFocus.inc'
    !
    If (vars(iValue)%doTuneSet) Then
       If ( vars(iValue)%doTune) Then
          Include 'inc/options/saveTuneOffsets.inc'
          doContinue = .False.
          contC = contCN
          Include 'inc/options/saveTuneTime.inc'
       Else 
          doContinue = .False.
          contC = contCN
          Include 'inc/options/saveTuneOffsets.inc'
       End If
    End If
    !
    contC = contCN
    !
    !TBD:      Include 'inc/options/saveUpdate.inc'

    Write (iUnit,*) "!"
    !
    Return
  End Subroutine saveFocus
!!!
!!!
  Subroutine startFocus(programName,LINE,commandToSave,iUnit, ERROR)
    !
    ! *** Variables ***
    Include 'inc/variables/headerForSaveMethods.inc'
    !
    Integer                 :: ii
    Character (len=lenCh)   :: valueC
    Character (len=lenLine) :: valueComment
    Character (len=lenLine) :: messageText
    Logical                 :: errorL, errorXML
    ! 
    Call pako_message(seve%t,"PAKO",                                             &
         &  " module Focus, v 1.2.1  --> SR: startFocus ")                       !                      
    !
    ERROR = .False.
    !
    !
    Call pakoXMLsetOutputUnit(iunit=iunit)
    Call pakoXMLsetIndent(iIndent=2)
!!OLD   Call pakoXMLsetLevel(1)
    !
    Include 'inc/startXML/generalHead.inc'
    !
    Call writeXMLset(programName,LINE,commandToSave,iUnit, ERROR)
    !
    !!! Call writeXMLversion !!! incorporated in generalHead above
    !
    Call pakoXMLwriteStartElement("RESOURCE","pakoScript",                       &
         &                         comment="save from pako",                     &
         &                         error=errorXML)                               !
    Call pakoXMLwriteStartElement("DESCRIPTION",                                 &
         &                         doCdata=.True.,                               &
         &                         error=errorXML)                               !
    !
    Include 'inc/startXML/savePakoScriptFirst.inc'
    !
    Call saveFocus        (programName,LINE,commandToSave, iUnit, errorL)
    !                                                                       
    Call pakoXMLwriteEndElement("DESCRIPTION",                                   &
         &      error=errorXML)                                                  !
    Call pakoXMLwriteEndElement("RESOURCE", "pakoScript",                        &
         &      error=errorXML)                                                  !
    !
    Call writeXMLantenna(programName,LINE,commandToSave,                         &
         &         iUnit, ERROR)                                                 !
    !
    Call writeXMLreceiver(programName,LINE,commandToSave,                        &
         &         iUnit, ERROR)                                                 !
    !
    Call writeXMLbackend(programName,LINE,commandToSave,                         &
         &         iUnit, ERROR)                                                 !
    !
    Include 'inc/startXML/switchingMode.inc'
    !
    Call writeXMLsource(programName,LINE,commandToSave,                          &
         &         iUnit, ERROR)                                                 !
    !
    Include 'inc/startXML/generalScanHead.inc'
    !
    ! **  Observing Mode to XML
    If (gv%doXMLobservingMode) Then
       messageText = "writing observing mode in XML format"
       Call PakoMessage(priorityI,severityI,                                     &
               &           commandToSave,messageText)                            !
       Call writeXMLfocus(programName,LINE,commandToSave,                        &
         &         iUnit, ERROR)                                                 !
    End If
    !
    ! **  subscan list to XML
    Include 'inc/startXML/focusSubscansXML.inc'
    !   
    Include 'inc/startXML/generalTail.inc'
    !
    Return
  End Subroutine startFocus
!!!
!!!
  Subroutine writeXMLfocus(programName,LINE,commandToSave,iUnit,ERROR)
    !
    ! *** Variables   ***
    Include 'inc/variables/headerForSaveMethods.inc'
    !
    Integer                 :: iMatch, nMatch, len1, len2
    Character (len=lenCh)   :: valueC, errorCode
    Character (len=lenLine) :: valueComment
    Logical                 :: errorM, errorXML
    Character (len=lenCh)   :: systemName
    !
    Call pako_message(seve%t,"PAKO",                                             &
         &  " module Focus, v 1.2.3 ---> SR: writeXMLfocus 2014-10-27")          !
    !
    ERROR = .False.
    !
    Call pakoXMLwriteStartElement("RESOURCE","observingMode",                    &
         &                         space ="before",                              &
         &                         error=errorXML)                               !
    !
    valueC = GV%observingMode
    Call pakoXMLwriteElement("PARAM","observingMode",valueC,                     &
         &                         dataType="char",                              &
         &                         error=errorXML)                               !
    !
    Include 'inc/startXML/parametersLengthFocusXML.inc'
    Include 'inc/startXML/optionNsubscansXML.inc'
    Include 'inc/startXML/optionTsubscanXML.inc'
    !
    systemName = offsPako%tru
    If (vars(iValue)%doTune) Then 
       Include 'inc/startXML/optionTuneXML.inc'
       Include 'inc/startXML/optionTtuneXML.inc'
    End If
    !D     Write (6,*) " systemName: --> ", systemName, "<-- "
    !D     Write (6,*) " offs%tru:   --> ", offs%tru,   "<-- "
    !
    Include 'inc/startXML/annotationsXML.inc'
    !
    Call pakoXMLwriteEndElement("RESOURCE","observingMode",                      &
         &                         error=errorXML)                               !
    !
    Return
  End Subroutine writeXMLfocus
!!!
!!!
End Module modulePakoFocus





