!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
module cubeio_header_hcdf
  use cubetools_parameters
  use cubetools_header_interface
  use cubedag_node_type
  use cubecdf_header
  use cubeio_header_interface
  use cubeio_messaging
  !
  public :: cubeio_header_get_and_derive_fromhcdf
  public :: cubeio_header_put_tohcdf
  public :: cubeio_header_truncate_and_put_tohcdf
  private
  !
contains
  !
  subroutine cubeio_header_get_and_derive_fromhcdf(hcdf,dno,error)
    !-------------------------------------------------------------------
    ! From type(cdf_header_t) to type(cube_header_interface_t)
    !-------------------------------------------------------------------
    type(cdf_header_t),           intent(in)    :: hcdf
    class(cubedag_node_object_t), intent(inout) :: dno
    logical,                      intent(inout) :: error
    !
    character(len=*), parameter :: rname='HEADER>GET>AND>DERIVE'
    !
    call cubeio_message(ioseve%trace,rname,'Welcome')
    !
    call cubeio_hcdf_export(hcdf,dno%node%head,error)
    if (error) return
    call dno%node%interf2head(error)
    if (error) return
  end subroutine cubeio_header_get_and_derive_fromhcdf
  !
  subroutine cubeio_header_put_tohcdf(dno,order,hcdf,error)
    !-------------------------------------------------------------------
    ! From type(cube_header_interface_t) to type(cdf_header_t) with
    ! desired order.
    !-------------------------------------------------------------------
    class(cubedag_node_object_t), intent(inout) :: dno
    integer(kind=code_k),         intent(in)    :: order  ! code_order_*
    type(cdf_header_t),           intent(inout) :: hcdf
    logical,                      intent(inout) :: error
    !
    character(len=*), parameter :: rname='HEADER>PUT'
    !
    call cubeio_message(ioseve%trace,rname,'Welcome')
    !
    call dno%node%head2interf(error)
    if (error) return
    call cubeio_header_interface_transpose(dno%node%head,order,error)  ! Inplace
    if (error) return
    call dno%node%head%compact_dim(error)
    if (error) return
    call cubeio_hcdf_import(dno%node%head,hcdf,error)
    if (error) return
  end subroutine cubeio_header_put_tohcdf
  !
  subroutine cubeio_header_truncate_and_put_tohcdf(dno,order,dim3,hcdf,error)
    !-------------------------------------------------------------------
    ! From type(cube_header_interface_t) to type(cdf_header_t) with
    ! desired order.
    !-------------------------------------------------------------------
    class(cubedag_node_object_t), intent(inout) :: dno
    integer(kind=code_k),         intent(in)    :: order  ! code_order_*
    integer(kind=data_k),         intent(in)    :: dim3
    type(cdf_header_t),           intent(inout) :: hcdf
    logical,                      intent(inout) :: error
    !
    character(len=*), parameter :: rname='HEADER>TRUNCATE>AND>PUT'
    !
    call cubeio_message(ioseve%trace,rname,'Welcome')
    !
    call dno%node%head2interf(error)
    if (error) return
    call cubeio_header_interface_transpose(dno%node%head,order,error)  ! Inplace
    if (error) return
    call cubeio_header_interface_truncate(dno%node%head,dim3,error)  ! Inplace
    if (error) return
    call dno%node%head%compact_dim(error)
    if (error) return
    call cubeio_hcdf_import(dno%node%head,hcdf,error)
    if (error) return
  end subroutine cubeio_header_truncate_and_put_tohcdf
  !
  !---------------------------------------------------------------------
  !
  subroutine cubeio_hcdf_export(hcdf,out,error)
    use cubetools_messaging
    !-------------------------------------------------------------------
    ! From type(cdf_header_t) to type(cube_header_interface_t)
    !-------------------------------------------------------------------
    type(cdf_header_t),            intent(in)    :: hcdf
    type(cube_header_interface_t), intent(inout) :: out
    logical,                       intent(inout) :: error
    !
    character(len=*), parameter :: rname='HCDF>EXPORT'
    !
    call cubeio_message(seve%e,rname,'Not implemented')
    error = .true.
    return
  end subroutine cubeio_hcdf_export
  !
  subroutine cubeio_hcdf_import(in,hcdf,error)
    use cubetools_messaging
    !-------------------------------------------------------------------
    ! From type(cube_header_interface_t) to type(gildas)
    !-------------------------------------------------------------------
    type(cube_header_interface_t), intent(in)    :: in
    type(cdf_header_t),            intent(inout) :: hcdf
    logical,                       intent(inout) :: error
    !
    integer(kind=ndim_k) :: ndim
    character(len=*), parameter :: rname='HGDF>IMPORT'
    !
    call cubeio_message(ioseve%trace,rname,'Welcome')
    !
    ! By design CUBE does not insert fake dimensions before exporting to
    ! CDF format (shoud they be needed). Or should we?...
    call in%sanity_dim(error)
    if (error)  return
    !
    ! Data format
    hcdf%type = in%array_type
    ! Dimension section
    if (in%axset_ndim.le.maxdim) then
       ndim = in%axset_ndim
    else
       call hcdf%message(seve%d,rname,'Larger number of dimensions than room to store it! => Truncating')
       ndim = maxdim
    endif
    hcdf%ndim = ndim
    hcdf%dim = 0
    hcdf%dim(1:ndim) = in%axset_dim(1:ndim)
  end subroutine cubeio_hcdf_import
  !
end module cubeio_header_hcdf
!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
module cubeio_cdf
  use cubetools_parameters
  use cubetools_header_types
  use cubecdf_header
  use cubeio_messaging
  use cubeio_header_hcdf
  use cubeio_range

  public :: cubeio_create_hcdf,cubeio_create_and_truncate_hcdf
  public :: cubeio_cdf_read_data
  public :: cubeio_cdf_write_data
  private

  interface cubeio_cdf_read_data
    module procedure cubeio_cdf_read_data_r4
    module procedure cubeio_cdf_read_data_c4
  end interface cubeio_cdf_read_data

  interface cubeio_cdf_write_data
    module procedure cubeio_cdf_write_data_r4
    module procedure cubeio_cdf_write_data_c4
  end interface cubeio_cdf_write_data

contains
  !
  subroutine cubeio_create_hcdf(dno,oorder,hcdf,error)
    use cubedag_node_type
    !---------------------------------------------------------------------
    ! Create or recreate the hcdf by converting the header with requested
    ! order.
    !---------------------------------------------------------------------
    class(cubedag_node_object_t), intent(inout) :: dno
    integer(kind=code_k),         intent(in)    :: oorder
    type(cdf_header_t),           intent(inout) :: hcdf
    logical,                      intent(inout) :: error
    ! Local
    character(len=*), parameter :: rname='CREATE>HCDF'
    !
    call cubeio_header_put_tohcdf(dno,oorder,hcdf,error)
    if (error)  return
  end subroutine cubeio_create_hcdf
  !
  subroutine cubeio_create_and_truncate_hcdf(dno,oorder,dim3,hcdf,error)
    use cubedag_node_type
    !---------------------------------------------------------------------
    ! Same as cubeio_create_hcdf, but truncate the 3rd dimension to
    ! requested size.
    !---------------------------------------------------------------------
    class(cubedag_node_object_t), intent(inout) :: dno
    integer(kind=code_k),         intent(in)    :: oorder
    integer(kind=data_k),         intent(in)    :: dim3
    type(cdf_header_t),           intent(inout) :: hcdf
    logical,                      intent(inout) :: error
    ! Local
    character(len=*), parameter :: rname='CREATE>AND>TRUNCATE>HCDF'
    !
    call cubeio_header_truncate_and_put_tohcdf(dno,oorder,dim3,hcdf,error)
    if (error)  return
  end subroutine cubeio_create_and_truncate_hcdf

  subroutine cubeio_cdf_read_data_r4(hcdf,data,range,error)
    !-------------------------------------------------------------------
    !-------------------------------------------------------------------
    type(cdf_header_t),   intent(in)    :: hcdf
    real(kind=4),         intent(out)   :: data(:,:,:)
    type(cubeio_range_t), intent(in)    :: range
    logical,              intent(inout) :: error
    !
    character(len=*), parameter :: rname='CDF>READ>DATA>R4'
    !
    call cubeio_message(seve%e,rname,'Reading REAL*4 data from CDF is not implemented')
    error = .true.
    return
  end subroutine cubeio_cdf_read_data_r4

  subroutine cubeio_cdf_read_data_c4(hcdf,data,range,error)
    !-------------------------------------------------------------------
    !-------------------------------------------------------------------
    type(cdf_header_t),   intent(in)    :: hcdf
    complex(kind=4),      intent(out)   :: data(:,:,:)
    type(cubeio_range_t), intent(in)    :: range
    logical,              intent(inout) :: error
    !
    character(len=*), parameter :: rname='CDF>READ>DATA>C4'
    !
    call cubeio_message(seve%e,rname,'Reading COMPLEX*4 data from CDF is not implemented')
    error = .true.
    return
  end subroutine cubeio_cdf_read_data_c4

  subroutine cubeio_cdf_write_data_r4(hcdf,data,range,error)
    use cubecdf_image_write
    !-------------------------------------------------------------------
    !-------------------------------------------------------------------
    type(cdf_header_t),   intent(in)    :: hcdf
    real(kind=4),         intent(in)    :: data(:,:,:)
    type(cubeio_range_t), intent(in)    :: range
    logical,              intent(inout) :: error
    !
    call cubecdf_image_datawrite(hcdf,data,range%blc,range%trc,error)
    if (error)  return
  end subroutine cubeio_cdf_write_data_r4

  subroutine cubeio_cdf_write_data_c4(hcdf,data,range,error)
    !-------------------------------------------------------------------
    !-------------------------------------------------------------------
    type(cdf_header_t),   intent(in)    :: hcdf
    complex(kind=4),      intent(in)    :: data(:,:,:)
    type(cubeio_range_t), intent(in)    :: range
    logical,              intent(inout) :: error
    !
    character(len=*), parameter :: rname='CDF>WRITE>DATA>C4'
    !
    call cubeio_message(seve%e,rname,'Exporting COMPLEX*4 data to CDF is not implemented')
    error = .true.
    return
  end subroutine cubeio_cdf_write_data_c4

end module cubeio_cdf
!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
