!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!***JP: The cubeset_plot_tool module should probably be moved into a
!***JP: specific core/plot library that deals with the interface with
!***JP: outside plotting libraries.
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
module cubeset_plot_tool
  use cubetools_parameters
  use cubeset_messaging
  !
  public :: pane_k
  public :: code_x,code_y
  public :: plot
  private 
  !
  integer(kind=4), parameter :: pane_k = 4
  !-------------------------------------------------------------------
  integer(kind=code_k), parameter :: code_x = 1
  integer(kind=code_k), parameter :: code_y = 2
  !-------------------------------------------------------------------
  !
  type plot_prog_t
   contains
     procedure, public :: togreg               => cubeset_plot_prog_togreg !***JP: Temporarily put it public
     procedure, public :: get_pagesize         => cubeset_plot_prog_get_pagesize
     procedure, public :: put_image_into_rg    => cubeset_plot_prog_put_image_into_rg
     procedure, public :: put_spectrum_into_xy => cubeset_plot_prog_put_spectrum_into_xy
     procedure, public :: box                  => cubeset_plot_prog_box
     procedure, public :: viewport             => cubeset_plot_prog_set_viewport
  end type plot_prog_t
  type(plot_prog_t) :: plot
  !
contains
  !
  subroutine cubeset_plot_prog_togreg(prog,commline,error)
    use gkernel_interfaces
    !-------------------------------------------------------------------
    ! Spawn a GREG command and return the error status
    !-------------------------------------------------------------------
    class(plot_prog_t), intent(in)    :: prog
    character(len=*),   intent(in)    :: commline
    logical,            intent(inout) :: error
    !
    character(len=*), parameter :: rname='PLOT>PROG>TOGREG'
    !
    call cubeset_message(setseve%trace,rname,'Welcome')
    !
    call gr_exec(commline)
    error = gr_error()
    if (error) then
       call cubeset_message(seve%e,rname,'Error when spawning the GREG command:')
       call cubeset_message(seve%e,rname,commline)
       return
    endif
  end subroutine cubeset_plot_prog_togreg
  !
  subroutine cubeset_plot_prog_get_pagesize(prog,size)
    use gkernel_interfaces
    !-------------------------------------------------------------------
    ! Get page geometry from GREG
    !-------------------------------------------------------------------
    class(plot_prog_t), intent(in)  :: prog
    real(kind=pane_k),  intent(out) :: size(2)
    !
    character(len=*), parameter :: rname='PLOT>PROG>GET>PAGESIZE'
    ! 
    call gr_get_physical(size(code_x),size(code_y))
  end subroutine cubeset_plot_prog_get_pagesize
  !
  subroutine cubeset_plot_prog_put_image_into_rg(prog,head,data,error)
    use gkernel_interfaces
    use cubetools_unit
    use cubetools_axis_types
    use cubetools_header_types
    use cubetools_header_methods
    !-------------------------------------------------------------------
    ! 
    !-------------------------------------------------------------------
    class(plot_prog_t),  intent(in)    :: prog
    type(cube_header_t), intent(in)    :: head
    real(kind=sign_k),   intent(in)    :: data(:,:)
    logical,             intent(inout) :: error
    !
    logical :: iswcs 
    integer(kind=4) :: nx,ny ! Here nx and ny are int*4 because of the interfaces with gkernel
    real(kind=coor_k) :: conv(6),proj(3)
    type(axis_t) :: axis
    character(len=*), parameter :: rname='PLOT>PROG>PUT>IMAGE>INTO>RG'
    !
    call cubeset_message(setseve%trace,rname,'Welcome')
    !
    ! Give data to RG
    call cubetools_header_get_axis_head_l(head,axis,error)
    if (error) return
    iswcs = axis%kind.eq.code_unit_fov
    nx = axis%n
    conv(1:3) = axis%conv
    call cubetools_header_get_axis_head_m(head,axis,error)
    if (error) return    
    iswcs = iswcs.and.(axis%kind.eq.code_unit_fov)
    ny = axis%n
    conv(4:6) = axis%conv
    call gr4_tgive(nx,ny,conv,data)
    !
    ! Define blanking, since now we use NaNs bval=0 and eval=-1
    call gr8_blanking(0.d0,-1.d0)
    !
    if (iswcs) then
       ! Pass coordinate System
       call gr8_system(head%spa%fra%code,error,head%spa%fra%equinox)
       ! Pass projection
       proj(1) = head%spa%pro%l0
       proj(2) = head%spa%pro%m0
       proj(3) = head%spa%pro%pa
       call greg_projec(head%spa%pro%code,proj)
    else
       continue
    endif
  end subroutine cubeset_plot_prog_put_image_into_rg
  !
  subroutine cubeset_plot_prog_put_spectrum_into_xy(prog,head,data,error)
    use cubetools_header_types
    use cubetools_header_methods
    use cubetools_axis_types
    use cubetools_userspace
    use cubetools_uservar
    !-------------------------------------------------------------------
    ! 
    !-------------------------------------------------------------------
    class(plot_prog_t),  intent(in)    :: prog
    type(cube_header_t), intent(in)    :: head
    real(kind=sign_k),   intent(in)    :: data(:)
    logical,             intent(inout) :: error
    !
    type(axis_t) :: caxis
    type(uservar_t) :: xbuff,ybuff
    logical, parameter :: global = .true.
    logical, parameter :: overwrite = .true.
    character(len=*), parameter :: rname='PLOT>PROG>PUT>SPECTRUM>INTO>XY'
    !
    call cubeset_message(setseve%trace,rname,'Welcome')
    !
    call cubetools_header_get_axis_head_c(head,caxis,error)
    if (error) return
    call xbuff%create('x',global,overwrite_prog,error)
    if (error) return
    call ybuff%create('y',global,overwrite_prog,error)
    if (error) return
    !
    call xbuff%set(caxis%coord,error)
    if (error) return
    call ybuff%set(data,error)
    if (error) return    
  end subroutine cubeset_plot_prog_put_spectrum_into_xy
  !
  !---------------------------------------------------------------------
  !
  subroutine cubeset_plot_prog_box(prog,error)
    !-------------------------------------------------------------------
    !-------------------------------------------------------------------
    class(plot_prog_t), intent(in)    :: prog
    logical,            intent(inout) :: error
    !
    character(len=*), parameter :: rname='PLOT>PROG>BOX'
    !
    call cubeset_message(setseve%trace,rname,'Welcome')
    !
    call plot%togreg('box n n n',error)
    if (error) return
  end subroutine cubeset_plot_prog_box
  !
  subroutine cubeset_plot_prog_set_viewport(prog,min,max,error)
    !-------------------------------------------------------------------
    !-------------------------------------------------------------------
    class(plot_prog_t), intent(in)    :: prog
    real(kind=pane_k),  intent(in)    :: min(2)
    real(kind=pane_k),  intent(in)    :: max(2)
    logical,            intent(inout) :: error
    !
    character(len=clin_l) :: commline
    character(len=mess_l) :: mess
    character(len=*), parameter :: rname='PLOT>PROG>SET>VIEWPORT'
    !
    call cubeset_message(setseve%trace,rname,'Welcome')
    !
    if (any(min.lt.0.0).or.any(max.gt.1.0)) then
       write(mess,'(a,4f5.1)') 'Desired viewport is set beyond bounds: ',&
            min(code_x),max(code_x),min(code_y),max(code_y)
       call cubeset_message(seve%e,rname,mess)
       call cubeset_message(seve%e,rname,'Limits are: 0.0 1.0 0.0 1.0')
       error = .true.
       return
    endif
    write(commline,'(A,4(1X,1PG14.7))')&
         'SET VIEWPORT',&
         min(code_x),max(code_x),&
         min(code_y),max(code_y)
    call plot%togreg(commline,error)
    if (error) return
  end subroutine cubeset_plot_prog_set_viewport
end module cubeset_plot_tool
!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
module cubeset_plot_page_tool
  use cubetools_parameters
  use cubeset_messaging
  use cubeset_plot_tool
  !
  public :: plot_page_geometry_user_t
  private
  !
  integer(kind=code_k), parameter :: code_page_landscape = 1
  integer(kind=code_k), parameter :: code_page_portrait  = 2
  !
  type plot_page_geometry_user_t
     integer(kind=code_k), public :: geo = code_page_landscape ! By default page is in landscape
     real(kind=pane_k),    public :: size(2) = 0.0             !
     real(kind=pane_k),    public :: aspect = 0.0              ! 
   contains
     procedure, public :: get_geometry => cubeset_plot_page_user_get_geometry
  end type plot_page_geometry_user_t
  !
contains
  !
  subroutine cubeset_plot_page_user_get_geometry(user,error)
    !-------------------------------------------------------------------
    ! Get page geometry
    !-------------------------------------------------------------------
    class(plot_page_geometry_user_t), intent(inout) :: user
    logical,                          intent(inout) :: error
    !
    character(len=mess_l) :: mess
    real(kind=pane_k), parameter :: ga4landscape = 1.42857146  ! GILDAS A4 landscape
    real(kind=pane_k), parameter :: ga4portrait  = 0.699999988 ! GILDAS A4 portrait
    character(len=*),  parameter :: rname='PLOT>PAGE>USER>GET>GEOMETRY'
    !
    call plot%get_pagesize(user%size)
    !
    user%aspect = user%size(code_x)/user%size(code_y)
    if (user%aspect.le.0) then
       call cubeset_message(seve%e,rname,' Page Aspect is zero or negative')
       error = .true.
       return
    else if (user%aspect.ge.1) then
       ! This case includes the square case
       user%geo = code_page_landscape
    else if (user%aspect.lt.1) then
       user%geo = code_page_portrait
    else ! user%aspect .eq. NAN +-inf
       write(mess,'(a,f8.3,a,f8.3)') 'Nonsense page size: ',user%size(code_x),'x',user%size(code_y)
       call cubeset_message(seve%e,rname,mess)
       error = .true.
       return
    endif
    !
    if (user%aspect.ne.ga4landscape.and.user%aspect.ne.ga4portrait) then
       write(mess,'(a,f8.3,a,f8.3,a)') 'Page size: ',user%size(code_x),'x',user%size(code_y),&
            ' is not 21x30 or 30x21, plots may set out of bounds'
       call cubeset_message(seve%w,rname,mess)
    endif
  end subroutine cubeset_plot_page_user_get_geometry  
end module cubeset_plot_page_tool
!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
