!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
subroutine wifisyn_complex_command(line,error)
  use gbl_message
  use gkernel_interfaces
  use wifisyn_interfaces, except_this=>wifisyn_complex_command
  use wifisyn_sic_buffer
  use wifisyn_cube_buffer
  !----------------------------------------------------------------------
  ! @ private
  ! Support routine for command
  !    COMPLEX VISICUBE|WIFICUBE TO|FROM AMPLITUDE|PHASE|REAL|IMAGINARY
  !      1 /LOGSCALE
  !      2 /NORMALIZE
  !----------------------------------------------------------------------
  character(len=*), intent(inout) :: line
  logical,          intent(inout) :: error
  !
  logical :: logscale
  integer :: narg,ioper,icube,idire
  character(len=*), parameter :: rname='COMPLEX/COMMAND'
  !
  call wifisyn_message(seve%t,rname,'Welcome')
  !
  ! Sanity check
  narg = sic_narg(0)
  if (narg.ne.3) then
     call wifisyn_message(seve%e,rname,'Three arguments needed')
     error = .true.
     return
  endif
  ! Parse
  call wifisyn_parse_cube_kind(line,icube,error)
  if (error) return
  call wifisyn_parse_dire_kind(line,idire,error)
  if (error) return
  call wifisyn_parse_oper_kind(line,ioper,error)
  if (error) return
  if (ioper.eq.code_ampl) then
     ! Currently logscale enabled only for AMPLITUDE...
     logscale = sic_present(1,0)
  endif
  ! Dispatch work
  if (idire.eq.code_complex2real) then
     if (icube.eq.code_cube_visi) then
        call wifisyn_visi_complex2real(logscale,ioper,progmap%win%cur(1),progmap,visi,error)
        if (error) return
     else if (icube.eq.code_cube_wifi) then
        call wifisyn_wifi_complex2real(logscale,ioper,1,progmap,wifi,error)
        if (error) return
     else
        call wifisyn_message(seve%e,rname,'Unknown cube kind')
        error = .true.
        return
     endif
  else if (idire.eq.code_real2complex) then
     if (icube.eq.code_cube_visi) then
        call wifisyn_visi_real2complex(ioper,progmap%win%cur(1),visi,error)
        if (error) return
     else if (icube.eq.code_cube_wifi) then
        call wifisyn_wifi_real2complex(ioper,1,wifi,error)
        if (error) return
     else
        call wifisyn_message(seve%e,rname,'Unknown cube kind')
        error = .true.
        return
     endif
  else
     call wifisyn_message(seve%e,rname,'Unknown cube kind')
     error = .true.
     return
  endif
  !
end subroutine wifisyn_complex_command
!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
subroutine wifisyn_wifi_complex2real(logscale,ioper,ichan,map,wifi,error)
  use gbl_message
  use phys_const
  use wifisyn_interfaces, except_this=>wifisyn_wifi_complex2real
  use wifisyn_gridding_types
  use wifisyn_cube_types
  !----------------------------------------------------------------------
  ! @ private
  !----------------------------------------------------------------------
  logical,      intent(in)    :: logscale
  integer,      intent(in)    :: ioper
  integer,      intent(in)    :: ichan
  type(map_t),  intent(in)    :: map
  type(wifi_t), intent(inout) :: wifi
  logical,      intent(inout) :: error
  !
  real(kind=4) :: wreal,wimag
  integer :: ix,iy,iu,iv
  character(len=*), parameter :: rname='WIFI/COMPLEX2REAL'
  !
  call wifisyn_message(seve%t,rname,'Welcome')
  !
  call wifisyn_wifi_header(map,wifi,error)
  if (error) return
  call wifisyn_cube_reallocate_r4d('wifi%amp',wifi%amp,error)
  if (error) return
  do iv=1,wifi%cub%nv
     do iu=1,wifi%cub%nu
        do iy=1,wifi%cub%ny
           do ix=1,wifi%cub%nx
              if (ioper.eq.code_ampl) then
                 wifi%amp%r4d(ix,iy,iu,iv) = abs(wifi%cub%val(ichan,ix,iy,iu,iv))
              else if (ioper.eq.code_phas) then
                 wreal = real(wifi%cub%val(ichan,ix,iy,iu,iv))
                 wimag = aimag(wifi%cub%val(ichan,ix,iy,iu,iv))
                 wifi%amp%r4d(ix,iy,iu,iv) = atan2(wimag,wreal)*deg_per_rad
              else if (ioper.eq.code_real) then
                 wifi%amp%r4d(ix,iy,iu,iv) = real(wifi%cub%val(ichan,ix,iy,iu,iv))
              else if (ioper.eq.code_imag) then
                 wifi%amp%r4d(ix,iy,iu,iv) = aimag(wifi%cub%val(ichan,ix,iy,iu,iv))
              else
                 call wifisyn_message(seve%e,rname,'Unknown operation')
                 error = .true.
                 return
              endif
           enddo ! ix
        enddo ! iy
     enddo ! iu
  enddo ! iv
  call wifisyn_cube_minmax_r4d(logscale,wifi%amp,error)
  if (error) return
  call wifisyn_cube_sicdef(code_readwrite,'xyuv',wifi%amp,error)
  if (error) return
  !
end subroutine wifisyn_wifi_complex2real
!
subroutine wifisyn_visi_complex2real(logscale,ioper,win,map,visi,error)
  use gbl_message
  use phys_const
  use wifisyn_interfaces, except_this=>wifisyn_visi_complex2real
  use wifisyn_gridding_types
  use wifisyn_cube_types
  !----------------------------------------------------------------------
  ! @ private
  !----------------------------------------------------------------------
  logical,        intent(in)    :: logscale
  integer,        intent(in)    :: ioper
  type(window_t), intent(in)    :: win
  type(map_t),    intent(in)    :: map
  type(visi_t),   intent(inout) :: visi
  logical,        intent(inout) :: error
  !
  integer :: ic,iu,iv
  real(kind=4) :: wreal,wimag
  character(len=*), parameter :: rname='VISI/COMPLEX2REAL'
  !
  call wifisyn_message(seve%t,rname,'Welcome')
  !
  call wifisyn_visi_header(map,visi,error)
  if (error) return
  call wifisyn_cube_reallocate_r3d(win%nchan,'visi%amp',visi%amp,error)
  if (error) return
  do ic=1,visi%cub%nc
     do iv=1,visi%cub%ny
        do iu=1,visi%cub%nx
           if (ioper.eq.code_ampl) then
              visi%amp%r3d(iu,iv,ic) = abs(visi%cub%val(iu,iv,ic))
           else if (ioper.eq.code_phas) then
              wreal = real(visi%cub%val(iu,iv,ic))
              wimag = aimag(visi%cub%val(iu,iv,ic))
              visi%amp%r3d(iu,iv,ic) = atan2(wimag,wreal)*deg_per_rad
           else if (ioper.eq.code_real) then
              visi%amp%r3d(iu,iv,ic) = real(visi%cub%val(iu,iv,ic))
           else if (ioper.eq.code_imag) then
              visi%amp%r3d(iu,iv,ic) = aimag(visi%cub%val(iu,iv,ic))
           else
              call wifisyn_message(seve%e,rname,'Unknown operation')
              error = .true.
              return
           endif
        enddo ! iu
     enddo ! iv
  enddo ! ic
  call wifisyn_cube_minmax_r3d(logscale,win,visi%amp,error)
  if (error) return
  call wifisyn_cube_sicdef(code_readwrite,'uv',visi%amp,error)
  if (error) return
  !
end subroutine wifisyn_visi_complex2real
!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
subroutine wifisyn_wifi_header(map,wifi,error)
  use gbl_message
  use wifisyn_interfaces, except_this=>wifisyn_wifi_header
  use wifisyn_gridding_types
  use wifisyn_cube_types
  !----------------------------------------------------------------------
  ! @ private
  !----------------------------------------------------------------------
  type(map_t),  intent(in)    :: map
  type(wifi_t), intent(inout) :: wifi
  logical,      intent(inout) :: error
  !
  character(len=*), parameter :: rname='WIFI/HEADER'
  !
  call wifisyn_message(seve%t,rname,'Welcome')
  !
  call wifisyn_common_header(map,wifi%amp,error)
  if (error) return
  wifi%amp%gil%xaxi = 0
  wifi%amp%gil%yaxi = 0
  if (wifi%xykind) then
     ! 1st axis
     wifi%amp%char%code(1) = 'RA'
     wifi%amp%gil%dim(1) = map%axes(1)%x%sky%n
     wifi%amp%gil%ref(1) = map%axes(1)%x%sky%ref
     wifi%amp%gil%val(1) = map%axes(1)%x%sky%val
     wifi%amp%gil%inc(1) = map%axes(1)%x%sky%inc
     ! 2nd axis
     wifi%amp%char%code(2) = 'DEC'
     wifi%amp%gil%dim(2) = map%axes(2)%x%sky%n
     wifi%amp%gil%ref(2) = map%axes(2)%x%sky%ref
     wifi%amp%gil%val(2) = map%axes(2)%x%sky%val
     wifi%amp%gil%inc(2) = map%axes(2)%x%sky%inc
  else
     ! 1st axis
     wifi%amp%char%code(1) = 'Us'
     wifi%amp%gil%dim(1) = map%axes(1)%x%uvp%n
     wifi%amp%gil%ref(1) = map%axes(1)%x%uvp%ref
     wifi%amp%gil%val(1) = map%axes(1)%x%uvp%val
     wifi%amp%gil%inc(1) = map%axes(1)%x%uvp%inc
     ! 2nd axis
     wifi%amp%char%code(2) = 'Vs'
     wifi%amp%gil%dim(2) = map%axes(2)%x%uvp%n
     wifi%amp%gil%ref(2) = map%axes(2)%x%uvp%ref
     wifi%amp%gil%val(2) = map%axes(2)%x%uvp%val
     wifi%amp%gil%inc(2) = map%axes(2)%x%uvp%inc
  endif
  if (wifi%uvkind) then
     ! 3rd axis
     wifi%amp%char%code(3) = 'Up'
     wifi%amp%gil%dim(3) = map%axes(1)%u%uvp%n
     wifi%amp%gil%ref(3) = map%axes(1)%u%uvp%ref
     wifi%amp%gil%val(3) = map%axes(1)%u%uvp%val
     wifi%amp%gil%inc(3) = map%axes(1)%u%uvp%inc
     ! 4th axis
     wifi%amp%char%code(4) = 'Vp'
     wifi%amp%gil%dim(4) = map%axes(2)%u%uvp%n
     wifi%amp%gil%ref(4) = map%axes(2)%u%uvp%ref
     wifi%amp%gil%val(4) = map%axes(2)%u%uvp%val
     wifi%amp%gil%inc(4) = map%axes(2)%u%uvp%inc
  else
     ! 3rd axis
     wifi%amp%char%code(3) = 'RA'
     wifi%amp%gil%dim(3) = map%axes(1)%u%sky%n
     wifi%amp%gil%ref(3) = map%axes(1)%u%sky%ref
     wifi%amp%gil%val(3) = map%axes(1)%u%sky%val
     wifi%amp%gil%inc(3) = map%axes(1)%u%sky%inc
     ! 4th axis
     wifi%amp%char%code(4) = 'DEC'
     wifi%amp%gil%dim(4) = map%axes(2)%u%sky%n
     wifi%amp%gil%ref(4) = map%axes(2)%u%sky%ref
     wifi%amp%gil%val(4) = map%axes(2)%u%sky%val
     wifi%amp%gil%inc(4) = map%axes(2)%u%sky%inc
  endif
  !
end subroutine wifisyn_wifi_header
!
subroutine wifisyn_visi_header(map,visi,error)
  use gbl_message
  use phys_const
  use wifisyn_interfaces, except_this=>wifisyn_visi_header
  use wifisyn_gridding_types
  use wifisyn_cube_types
  !----------------------------------------------------------------------
  ! @ private
  !----------------------------------------------------------------------
  type(map_t),  intent(in)    :: map
  type(visi_t), intent(inout) :: visi
  logical,      intent(inout) :: error
  !
  character(len=*), parameter :: rname='VISI/HEADER'
  !
  call wifisyn_message(seve%t,rname,'Welcome')
  !
  call wifisyn_common_header(map,visi%amp,error)
  if (error) return
  visi%amp%gil%ndim = 3
  if (visi%uvkind) then
     ! 1st axis
     visi%amp%char%code(1) = 'U'
     visi%amp%gil%dim(1) = map%axes(1)%a%uvp%n
     visi%amp%gil%ref(1) = map%axes(1)%a%uvp%ref
     visi%amp%gil%val(1) = map%axes(1)%a%uvp%val
     visi%amp%gil%inc(1) = map%axes(1)%a%uvp%inc
     visi%amp%gil%xaxi = 0
     ! 2nd axis
     visi%amp%char%code(2) = 'V'
     visi%amp%gil%dim(2) = map%axes(2)%a%uvp%n
     visi%amp%gil%ref(2) = map%axes(2)%a%uvp%ref
     visi%amp%gil%val(2) = map%axes(2)%a%uvp%val
     visi%amp%gil%inc(2) = map%axes(2)%a%uvp%inc
     visi%amp%gil%yaxi = 0
  else
     ! 1st axis
     visi%amp%char%code(1) = 'RA'
     visi%amp%gil%dim(1) = map%axes(1)%a%sky%n
     visi%amp%gil%ref(1) = map%axes(1)%a%sky%ref
     visi%amp%gil%val(1) = map%axes(1)%a%sky%val
     visi%amp%gil%inc(1) = map%axes(1)%a%sky%inc
     visi%amp%gil%xaxi = 1
     ! 2nd axis
     visi%amp%char%code(2) = 'DEC'
     visi%amp%gil%dim(2) = map%axes(2)%a%sky%n
     visi%amp%gil%ref(2) = map%axes(2)%a%sky%ref
     visi%amp%gil%val(2) = map%axes(2)%a%sky%val
     visi%amp%gil%inc(2) = map%axes(2)%a%sky%inc
     visi%amp%gil%yaxi = 2
  endif
  ! 3rd axis
  ! *** JP The following information should be stored in a freq/velo axis component of map
  visi%amp%char%code(3) = 'VELOCITY'
  visi%amp%gil%dim(3) = map%win%cur(map%win%n)%last-map%win%cur(1)%first+1
  visi%amp%gil%ref(3) = map%huv%gil%ref(2) - map%win%cur(1)%first +1
  visi%amp%gil%val(3) = map%huv%gil%voff
  visi%amp%gil%inc(3) = -(clight/1000d0)*map%huv%gil%fres/map%huv%gil%freq ! *** JP doppler not taken into account
!  visi%amp%gil%inc(3) = map%huv%gil%vres
  visi%amp%gil%faxi = 3
  !
end subroutine wifisyn_visi_header
!
subroutine wifisyn_common_header(map,cube,error)
  use gbl_message
  use image_def
  use gkernel_interfaces
  use wifisyn_interfaces, except_this=>wifisyn_common_header
  use wifisyn_gridding_types
  !----------------------------------------------------------------------
  ! @ private
  !----------------------------------------------------------------------
  type(map_t),  intent(in)    :: map
  type(gildas), intent(inout) :: cube
  logical,      intent(inout) :: error
  !
  character(len=*), parameter :: rname='COMMON/HEADER'
  !
  call wifisyn_message(seve%t,rname,'Welcome')
  !
  call gdf_copy_header(map%huv,cube,error)
  if (error)  return
  !
  ! Cube unit
  cube%char%unit = 'Jy/beam'
  ! Projection information (assume equatorial system)
  cube%gil%proj_words = 9
! *** JP Should use the map%shift information.
!  cube%gil%ra  = map%huv%gil%ra
!  cube%gil%dec = map%huv%gil%dec
!  cube%gil%lii = map%huv%gil%lii
!  cube%gil%bii = map%huv%gil%bii
  cube%gil%ptyp = p_azimuthal ! Azimuthal (Sin)
  cube%gil%pang = map%shift%pang
  cube%gil%a0 = map%shift%a0
  cube%gil%d0 = map%shift%d0
  cube%char%syst = 'EQUATORIAL'
  ! Noise section
  cube%gil%nois_words = 0
  ! Initialized extrema section
  cube%gil%extr_words = 10
  cube%gil%rmin = +1e38
  cube%gil%rmax = -1e38
  ! No beam yet
  cube%gil%reso_words = 0
  ! Others
  cube%char%type = 'GILDAS_IMAGE'
  cube%loca%size = cube%gil%dim(1)*cube%gil%dim(2)*cube%gil%dim(3)*cube%gil%dim(4)
  !
end subroutine wifisyn_common_header
!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
subroutine wifisyn_wifi_real2complex(ioper,ichan,wifi,error)
  use gbl_message
  use phys_const
  use wifisyn_interfaces, except_this=>wifisyn_wifi_real2complex
  use wifisyn_gridding_types
  use wifisyn_cube_types
  !----------------------------------------------------------------------
  ! @ private
  !----------------------------------------------------------------------
  integer,      intent(in)    :: ioper
  integer,      intent(in)    :: ichan
  type(wifi_t), intent(inout) :: wifi
  logical,      intent(inout) :: error
  !
  real(kind=4) :: wreal,wimag,wampl,wphas
  integer :: ix,iy,iu,iv
  character(len=*), parameter :: rname='WIFI/REAL2COMPLEX'
  !
  call wifisyn_message(seve%t,rname,'Welcome')
  !
  do iv=1,wifi%cub%nv
     do iu=1,wifi%cub%nu
        do iy=1,wifi%cub%ny
           do ix=1,wifi%cub%nx
              if (ioper.eq.code_ampl) then
                 wampl = wifi%amp%r4d(ix,iy,iu,iv)
                 wreal = real(wifi%cub%val(ichan,ix,iy,iu,iv))
                 wimag = aimag(wifi%cub%val(ichan,ix,iy,iu,iv))
                 wphas = atan2(wimag,wreal)
                 wreal = wampl*cos(wphas)
                 wimag = wampl*sin(wphas)
              else if (ioper.eq.code_phas) then
                 wampl = abs(wifi%cub%val(ichan,ix,iy,iu,iv))
                 wphas = wifi%amp%r4d(ix,iy,iu,iv)*rad_per_deg
                 wreal = wampl*cos(wphas)
                 wimag = wampl*sin(wphas)
              else if (ioper.eq.code_real) then
                 wreal = wifi%amp%r4d(ix,iy,iu,iv)
                 wimag = aimag(wifi%cub%val(ichan,ix,iy,iu,iv))
              else if (ioper.eq.code_imag) then
                 wreal = real(wifi%cub%val(ichan,ix,iy,iu,iv))
                 wimag = wifi%amp%r4d(ix,iy,iu,iv)
              else
                 call wifisyn_message(seve%e,rname,'Unknown operation')
                 error = .true.
                 return
              endif
              wifi%cub%val(ichan,ix,iy,iu,iv) = cmplx(wreal,wimag)
           enddo ! ix
        enddo ! iy
     enddo ! iu
  enddo ! iv
  !
end subroutine wifisyn_wifi_real2complex
!
subroutine wifisyn_visi_real2complex(ioper,win,visi,error)
  use gbl_message
  use phys_const
  use wifisyn_interfaces, except_this=>wifisyn_visi_real2complex
  use wifisyn_gridding_types
  use wifisyn_cube_types
  !----------------------------------------------------------------------
  ! @ private
  !----------------------------------------------------------------------
  integer,        intent(in)    :: ioper
  type(window_t), intent(in)    :: win
  type(visi_t),   intent(inout) :: visi
  logical,        intent(inout) :: error
  !
  integer :: ic,iu,iv
  real(kind=4) :: wreal,wimag,wampl,wphas
  character(len=*), parameter :: rname='VISI/REAL2COMPLEX'
  !
  call wifisyn_message(seve%t,rname,'Welcome')
  !
  do ic=1,visi%cub%nc
     do iv=1,visi%cub%ny
        do iu=1,visi%cub%nx
           if (ioper.eq.code_ampl) then
              wampl = visi%amp%r3d(iu,iv,ic)
              wreal = real(visi%cub%val(iu,iv,ic))
              wimag = aimag(visi%cub%val(iu,iv,ic))
              wphas = atan2(wimag,wreal)
              wreal = wampl*cos(wphas)
              wimag = wampl*sin(wphas)
           else if (ioper.eq.code_phas) then
              wampl = abs(visi%cub%val(iu,iv,ic))
              wphas = visi%amp%r3d(iu,iv,ic)*rad_per_deg
              wreal = wampl*cos(wphas)
              wimag = wampl*sin(wphas)
           else if (ioper.eq.code_real) then
              wreal = visi%amp%r3d(iu,iv,ic)
              wimag = aimag(visi%cub%val(iu,iv,ic))
           else if (ioper.eq.code_imag) then
              wreal = real(visi%cub%val(iu,iv,ic))
              wimag = visi%amp%r3d(iu,iv,ic)
           else
              call wifisyn_message(seve%e,rname,'Unknown operation')
              error = .true.
              return
           endif
           visi%cub%val(iu,iv,ic) = cmplx(wreal,wimag)
        enddo ! iu
     enddo ! iv
  enddo ! ic
  !
end subroutine wifisyn_visi_real2complex
!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
