!
module gio_params
  use gildas_def
  !
  !--------------------------------------------------------------------
  ! GIO parameters for image I/O support
  !--------------------------------------------------------------------
  !
  integer(kind=4), parameter :: gdf_maxdims=7  ! Maximum number of dimensions.
  !
  ! These ones are returned as img%status by the GIO lbrary
  integer, parameter :: code_read_data     =-1
  integer, parameter :: code_read_header   =-2
  integer, parameter :: code_update_header =-3
  integer, parameter :: code_write_header  =-4
  integer, parameter :: code_write_data    =-5
  integer, parameter :: code_read_image    =-6
  integer, parameter :: code_free_image    =-7
  integer, parameter :: code_create_image  =-8
  ! Missng or extra Columns in "Tables"
  integer(kind=4), parameter :: code_gio_miscol=-9    ! Missing UV column
  integer(kind=4), parameter :: code_gio_extcol=-10   ! Extra UV column
  !
  !
  ! Do not change the order and value of these integers
  integer(kind=4), parameter :: code_gio_empty=0
  ! The EMPTY state is attributed to any non-associated image slot,
  ! as well as any non-associated memory slot.
  !
  integer(kind=4), parameter :: code_gio_reado=1
  ! The READO state is attributed to any Read-Only image slot whose memory is
  ! handled by the Image library, through SIC_GETVM.
  !
  integer(kind=4), parameter :: code_gio_full=2
  ! The FULL state is attributed to an image slot which still has
  ! usefull information, but is not associated to data memory.
  ! It is typically used to update an image header, for example.
  !
  integer(kind=4), parameter :: code_gio_write=3
  ! The WRITE state is attributed to any Read-Write image slot whose memory is
  ! handled by the Image library, through SIC_GETVM. It indicates that the
  ! output file must be updated when closed
  !
  integer(kind=4), parameter :: code_gio_dumpi=4
  ! The DUMPI state is temporarily attributed to a Read-Write image slot
  ! to force update of the output file. It avoids Closing and Re-opening
  ! the file, and thus saves some I/O. In practice, only used by
  ! CLASS SUB_GRID routine so far.
  !
  integer(kind=4), parameter :: code_gio_dumpe=5
  ! The DUMPE state is attributed to Read-Write image slot whose memory is
  ! not handled by the Image library, but associated to the slot through
  ! call to GDF_PUMS. It indicates the output file should be written, but the
  ! memory area preserved.
  !
  integer(kind=4), parameter :: code_gio_reade=6
  ! The READE state is attributed to Read-Only image slot whose memory is
  ! not handled by the Image library, but associated to the slot through
  ! call to GDF_DAMS. It indicates the memory area should be preserved.
  !
  !
  ! Kind of GDF: The following codes imply a minimum number of available
  ! information. There may be more
  !
  ! Normal data, i.e. IMAGE...
  integer(kind=4), parameter :: code_gdf_image = 0
  ! Old UV Data with wrong weight
  integer(kind=4), parameter :: code_gdf_uvold = 1
  ! UV Data in "visibility" order
  integer(kind=4), parameter :: code_gdf_uvt =  10
  ! The transposed way (channel order)...
  integer(kind=4), parameter :: code_gdf_tuv = -code_gdf_uvt
  ! A simple Table, with no information
  integer(kind=4), parameter :: code_gdf_table = 20
  ! Virtual Observatory (VO) Tables are ordered in the transposed way...
  integer(kind=4), parameter :: code_gdf_vo = -code_gdf_table
  ! A specific CLASS table (by symmetry with code_gdf_uvt)
  integer(kind=4), parameter :: code_gdf_xyt = 40
  ! A specific CLASS table (by symmetry with code_gdf_uvt)
  integer(kind=4), parameter :: code_gdf_txy = -code_gdf_xyt
  ! A spread sheet for the SIC Tabler...
  integer(kind=4), parameter :: code_gdf_sheet = 50
  !
  ! Polarimetry parameters
  integer(kind=4), parameter :: code_polar_h = 1
  integer(kind=4), parameter :: code_polar_v = 2
  integer(kind=4), parameter :: code_polar_x = 3
  integer(kind=4), parameter :: code_polar_y = 4
  integer(kind=4), parameter :: code_polar_r = 5
  integer(kind=4), parameter :: code_polar_l = 6
  integer(kind=4), parameter :: code_polar_d = 7
  integer(kind=4), parameter :: code_polar_s = 8
  character(len=1), parameter :: gio_polar_names(1:8) =  &
    (/ 'H','V','X','Y','R','L','D','S' /)
  !
  integer(kind=4), parameter :: code_stokes_none = 0
  integer(kind=4), parameter :: code_stokes_all  = 10  ! Not in data format
  integer(kind=4), parameter :: code_stokes_any  = 20  ! Not in data format
  integer(kind=4), parameter :: code_stokes_i  = 1
  integer(kind=4), parameter :: code_stokes_q  = 2
  integer(kind=4), parameter :: code_stokes_u  = 3
  integer(kind=4), parameter :: code_stokes_v  = 4
  integer(kind=4), parameter :: code_stokes_rr = -1
  integer(kind=4), parameter :: code_stokes_ll = -2
  integer(kind=4), parameter :: code_stokes_rl = -3
  integer(kind=4), parameter :: code_stokes_lr = -4
  integer(kind=4), parameter :: code_stokes_xx = -5
  integer(kind=4), parameter :: code_stokes_yy = -6
  integer(kind=4), parameter :: code_stokes_xy = -7
  integer(kind=4), parameter :: code_stokes_yx = -8
  integer(kind=4), parameter :: code_stokes_dd = -9
  integer(kind=4), parameter :: code_stokes_ss = -10
  integer(kind=4), parameter :: code_stokes_ds = -11
  integer(kind=4), parameter :: code_stokes_sd = -12
  integer(kind=4), parameter :: code_stokes_hh = -13
  integer(kind=4), parameter :: code_stokes_vv = -14
  integer(kind=4), parameter :: code_stokes_hv = -15
  integer(kind=4), parameter :: code_stokes_vh = -16
  character(len=4), parameter :: gio_stokes_names(-16:4) =  &
    (/ 'VH  ','HV  ','VV  ','HH  ',  &  ! -16 -13
       'SD  ','DS  ','SS  ','DD  ',  &  ! -12  -9
       'YX  ','XY  ','YY  ','XX  ',  &  !  -8  -5
       'LR  ','RL  ','LL  ','RR  ',  &  !  -4  -1
       'NONE',                       &  !   0
       'I   ','Q   ','U   ','V   ' /)   !   1   4
  !
  ! Channel / Stokes ordering Must be out of range of the Stokes values
  integer(kind=4), parameter :: code_stok_chan = 100  ! Stokes/Channel order
  integer(kind=4), parameter :: code_chan_stok = -100 ! Channel/Stokes order
  !
  ! Visibility atom description
  integer(kind=4), parameter :: code_atom_real = 1
  integer(kind=4), parameter :: code_atom_imag = 2
  integer(kind=4), parameter :: code_atom_weig = 3
  !
  ! Sorting order
  integer(kind=4), parameter :: code_sort_none     = 1
  integer(kind=4), parameter :: code_sort_timebase = 2
  integer(kind=4), parameter :: code_sort_minus_v  = 3
  !
  ! Column kind of the uv tables
  integer(kind=4), parameter :: code_type_r4 = 1 ! Real number
  integer(kind=4), parameter :: code_type_r8 = 2 ! Double precision number
  !
  integer(kind=4), parameter :: code_follow   = -1 ! Column is a follower of the previous one
  integer(kind=4), parameter :: code_uvt_u    =  1 ! u
  integer(kind=4), parameter :: code_uvt_v    =  2 ! v
  integer(kind=4), parameter :: code_uvt_w    =  3 ! w
  integer(kind=4), parameter :: code_uvt_date =  4 ! Date
  integer(kind=4), parameter :: code_uvt_time =  5 ! Time
  integer(kind=4), parameter :: code_uvt_anti =  6 ! Antenna i
  integer(kind=4), parameter :: code_uvt_antj =  7 ! Antenna j
  integer(kind=4), parameter :: code_uvt_scan =  8 ! Scan number
  integer(kind=4), parameter :: code_uvt_topo =  9 ! Topocentric to System Doppler effect
  integer(kind=4), parameter :: code_uvt_loff = 10 ! Phase center Offset
  integer(kind=4), parameter :: code_uvt_moff = 11 ! Phase center Offset
  integer(kind=4), parameter :: code_uvt_xoff = 12 ! Pointing Offset
  integer(kind=4), parameter :: code_uvt_yoff = 13 ! Pointing Offset
  integer(kind=4), parameter :: code_uvt_stok = 14 ! Polarisation state
  integer(kind=4), parameter :: code_uvt_el   = 15 ! Elevation
  integer(kind=4), parameter :: code_uvt_ha   = 16 ! Hour angle
  integer(kind=4), parameter :: code_uvt_para = 17 ! Parallactic angle
  integer(kind=4), parameter :: code_uvt_int  = 18 ! Integration time
  integer(kind=4), parameter :: code_uvt_weig = 19 ! Weight column for SD
  integer(kind=4), parameter :: code_uvt_xofi = 20 ! Pointing error Ant I
  integer(kind=4), parameter :: code_uvt_yofi = 21 ! Pointing error Ant I
  integer(kind=4), parameter :: code_uvt_xofj = 22 ! Pointing error Ant J
  integer(kind=4), parameter :: code_uvt_yofj = 23 ! Pointing error Ant J
  integer(kind=4), parameter :: code_uvt_ra   = 24 ! RA of reference
  integer(kind=4), parameter :: code_uvt_dec  = 25 ! DEC of reference
  integer(kind=4), parameter :: code_uvt_if   = 26 ! VLA IF identification
  integer(kind=4), parameter :: code_uvt_tele = 27 ! Telescope pair ID
  integer(kind=4), parameter :: code_uvt_id   = 28 ! Any counter (e.g. source ID from UVFITS)
  integer(kind=4), parameter :: code_uvt_freq = 29 ! Frequency offset from Reference frequency
  integer(kind=4), parameter :: code_uvt_last = 29 ! Last uvt code
  ! currently up to code_uvt_last = 29 can fit in a single block
  !
  character(len=12), parameter :: gio_column_names(code_uvt_last) = (/  &
    'U           ','V           ','W           ','DATE        ',  &  !  1- 4
    'TIME        ','IANT        ','JANT        ','SCAN        ',  &  !  5- 8
    'DOPPLER     ','L_PHASE_OFF ','M_PHASE_OFF ','X_POINT_OFF ',  &  !  9-12
    'Y_POINT_OFF ','STOKES      ','ELEVATION   ','HOUR_ANGLE  ',  &  ! 13-16
    'PARA_ANGLE  ','ON_TIME     ','WEIGHT      ','X_POINT_IANT',  &  ! 17-20
    'Y_POINT_IANT','X_POINT_JANT','Y_POINT_JANT','RA          ',  &  ! 21-24
    'DEC         ','CASA_IF     ','TELESCOPE   ','SOURCE_ID   ',  &  ! 25-28
    'FREQUENCY   '  /)  ! 29
  !
  integer(kind=4), parameter :: gio_block1 = 16  ! Blocking factor for "big" blocks
  integer(kind=4), parameter :: gio_block2 = 16  ! Super Blocking factor for "huge" blocks
end module gio_params
!
module gio_headers
  use gbl_format
  use gio_params
  use gbl_constant
  !
  integer(kind=4), parameter :: code_version_gdf_v10 = 10 !  1.0 in fact...
  integer(kind=4), parameter :: code_version_gdf_v20 = 20 !  2.0 in fact...
  integer(kind=4), parameter :: code_version_gdf_current = code_version_gdf_v20
  !
  ! An historic bug made this value equal to 20 in data files...
  integer(kind=4), parameter :: code_version_uvt_v20 = 20 !
  integer(kind=4), parameter :: code_version_uvt_freq = code_version_uvt_v20
  integer(kind=4), parameter :: code_version_uvt_v21 = 21 ! > previous value
  integer(kind=4), parameter :: code_version_uvt_dopp = code_version_uvt_v21
  integer(kind=4), parameter :: code_version_uvt_v22 = 22 ! > previous value
  integer(kind=4), parameter :: code_version_uvt_syst = code_version_uvt_v22
  integer(kind=4), parameter :: code_version_uvt_default = code_version_uvt_syst
  !
  integer(kind=4), parameter :: gdf_startdim = 17  ! Must be odd and > 12.
  !  17 is the maximum allowed to hold 8 dimensions in the first block
  !  Increasing this number and/or the number of dimensions beyond these
  !  values would require re-coding in the gio library..
  !
  ! First header block
  integer(kind=4) , parameter :: def_dim_words   = 2*gdf_maxdims+2  ! Dimension section length
  integer(kind=4) , parameter :: def_blan_words = 2    ! Blanking section length
  integer(kind=4) , parameter :: def_extr_words = 6    ! Extrema section length
  integer(kind=4) , parameter :: def_coor_words  = 6*gdf_maxdims     ! at s_coor  Section length
  integer(kind=4) , parameter :: def_desc_words  = 3*(gdf_maxdims+1) ! at s_desc, Description section length
  !
  ! Second header block
  ! Padding must NOT be included in the section length, as the actual section length is
  ! written to the data, so only available information should be written
  !
  integer(kind=4) , parameter :: def_posi_words = 15   ! Position section length 15 used 1 padding
  integer(kind=4) , parameter :: def_proj_words = 9    ! Projection section length 9 used 1 padding
  integer(kind=4) , parameter :: def_spec_words = 14   ! Spectroscopy section length 14 used
  integer(kind=4) , parameter :: def_reso_words = 3    ! Resolution section length 3 used 1 padding
  integer(kind=4) , parameter :: def_nois_words = 2    ! Noise section length
  integer(kind=4) , parameter :: def_astr_words = 3    ! Proper motion section length 3 used 1 padding
  integer(kind=4) , parameter :: def_uvda_words = 18+2*code_uvt_last ! UV data section
  ! currently up to 25 code_uvt_... can fit in a single block
  integer(kind=4) , parameter :: def_tele_words = 8    ! Telescope section length
  !
  ! Just as a convenience for tests...
  integer(kind=4) , parameter :: second_words = def_posi_words+2 + def_proj_words+2 + &
    &   def_reso_words+2 + def_nois_words+2 + def_astr_words+2
  !
  ! /XIPAR/
  type :: location
    sequence
    integer(kind=address_length) :: addr = 0  ! Address of image
    integer(kind=size_length) :: size = 0     ! Size of image
    integer :: islo         = 0               ! Image Slot number
    integer :: mslo         = 0               ! Memory Slot number
    logical :: read         = .true.          ! ReadOnly status
    logical :: getvm        = .false.         ! Memory / File indicator
    integer(kind=size_length) :: al64 = 0     ! Padding required for alignment
  end type location
  !
  ! /XCPAR/
  type :: strings
    sequence
    character(len=12) :: type    = 'GILDAS_IMAGE'  !     Image Type (see ITYP)
    character(len=12) :: unit    = ' '             !     Data Units (see IUNI)
    character(len=12) :: code(gdf_maxdims) = ' '         ! 59  Axis codes (see ICOD)
    character(len=12) :: syst    = ' '             ! 71  Coordinate system (see ISYS)
    character(len=12) :: name    = ' '             ! 75  Source name (see ISOU)
    character(len=12) :: line    = ' '             !     Line name (see ILIN)
    !For Even GDF_MAXDIMS only ! character(len=4)  :: pad_char
  end type strings
  !
  type :: telesco
    sequence
     ! Then for each telescope
     real(kind=8) :: lon=0     ! Longitude (radians)
     real(kind=8) :: lat=0     ! Latitude  (radians)
     real(kind=4) :: alt=0     ! Altitude (m)
     real(kind=4) :: diam=0    ! Diameter
     character(len=12) :: ctele=' '  ! Telescope name
     integer(kind=4) :: pad    ! Padding for alignment
     !
  end type telesco
  !
  ! Version 1.0  OLD File Format
  !
  type :: gildas_header_v1
     sequence
     integer(kind=4) :: ijtyp(3) = 0       !  1  Image Type
     integer(kind=4) :: form    = fmt_r4   !  4  Data format (FMT_xx)
     integer(kind=4) :: ndb     = 0        !  5  Number of data blocks
     integer(kind=4) :: type_gdf = code_null  ! 6
     integer(kind=4) :: fill(4) = 0        !  7  Reserved space
     ! GENERAL SECTION
     integer(kind=4) :: gene    = 29       ! 11  General section length
     integer(kind=4) :: ndim    = 0        ! 12  Number of dimensions
     integer(kind=4) :: dim(4)  = 0        ! 13  Dimensions
     real(kind=8) :: ref1 = 1.d0           ! 17  Reference pixel
     real(kind=8) :: val1 = 1.d0           ! 19  Value at reference pixel
     real(kind=8) :: inc1 = 1.d0           ! 21  Increment per pixel
     real(kind=8) :: ref2 = 1.d0           ! 23  idem for axis 2
     real(kind=8) :: val2 = 1.d0           ! 25
     real(kind=8) :: inc2 = 1.d0           ! 27
     real(kind=8) :: ref3 = 1.d0           ! 29  idem for axis 3
     real(kind=8) :: val3 = 1.d0           ! 31
     real(kind=8) :: inc3 = 1.d0           ! 33
     real(kind=8) :: ref4 = 1.d0           ! 35  idem for axis 4
     real(kind=8) :: val4 = 1.d0           ! 37
     real(kind=8) :: inc4 = 1.d0           ! 39
     ! BLANKING
     integer(kind=4) :: blan = 2           ! 41  Blanking section length
     real(kind=4) :: bval = +1.23456e+34   ! 42  Blanking value
     real(kind=4) :: eval = -1.0           ! 43  Tolerance
     ! EXTREMA
     integer(kind=4) :: extr = 0           ! 44  Extrema section length
     real(kind=4) :: rmin    = 0.0         ! 45  Minimum
     real(kind=4) :: rmax    = 0.0         ! 46  Maximum
     integer(kind=4) :: min1 = 0           ! 47  Pixel of min on axis 1
     integer(kind=4) :: max1 = 0           ! 48  Pixel of max ......
     integer(kind=4) :: min2 = 0           ! 49  idem for axis 2
     integer(kind=4) :: max2 = 0           ! 50
     integer(kind=4) :: min3 = 0           ! 51           axis 3
     integer(kind=4) :: max3 = 0           ! 52
     integer(kind=4) :: min4 = 0           ! 53           axis 4
     integer(kind=4) :: max4 = 0           ! 54
     ! DESCRIPTION
     integer(kind=4) :: desc      = 18     ! 55  Description section length
     integer(kind=4) :: ijuni(3)   = 0     ! 56  Data Unit
     integer(kind=4) :: ijcod(3,4) = 0     ! 59  Axis names
     integer(kind=4) :: ijsys(3)   = 0     ! 71  Coordinate System
     integer(kind=4) :: dum1      = 0      ! Void for padding
     ! POSITION
     integer(kind=4) :: posi    = 12       ! 74  Position section length
     integer(kind=4) :: ijsou(3) = 0       ! 75  Source name
     real(kind=8) :: ra         = 0.d0     ! 78  Right Ascension
     real(kind=8) :: dec        = 0.d0     ! 80  Declination
     real(kind=8) :: lii        = 0.d0     ! 82  Galactic longitude
     real(kind=8) :: bii        = 0.d0     ! 84           latitude
     real(kind=4) :: epoc       = 0.0      ! 86  Epoch of coordinates
     integer(kind=4) :: dum2    = 0        ! Void for padding
     ! PROJECTION
     integer(kind=4) :: proj = 9           ! 87  Projection section length
     integer(kind=4) :: ptyp = p_none      ! 88  Projection type (see p_... codes)
     real(kind=8) :: a0      = 0.d0        ! 89  X of projection center
     real(kind=8) :: d0      = 0.d0        ! 91  Y of projection center
     real(kind=8) :: pang    = 0.d0        ! 93  Projection angle
     integer(kind=4) :: xaxi = 0           ! 95  X axis
     integer(kind=4) :: yaxi = 0           ! 96  Y axis
     ! SPECTROSCOPY
     integer(kind=4) :: spec    = 12       ! 97  Spectroscopy section length
     integer(kind=4) :: ijlin(3) = 0       ! 98  Line name
     real(kind=8) :: fres       = 0.d0     !101  Frequency resolution
     real(kind=8) :: fima       = 0.d0     !103  Image frequency
     real(kind=8) :: freq       = 0.d0     !105  Rest Frequency
     real(kind=4) :: vres       = 0.0      !107  Velocity resolution
     real(kind=4) :: voff       = 0.0      !108  Velocity offset
     integer(kind=4) :: faxi    = 0        !109  Frequency axis
     ! RESOLUTION
     integer(kind=4) :: reso = 0           !110  Resolution section length
     real(kind=4) :: majo    = 0.0         !111  Major axis
     real(kind=4) :: mino    = 0.0         !112  Minor axis
     real(kind=4) :: posa    = 0.0         !113  Position angle
     ! NOISE
     integer(kind=4) :: sigm = 0           ! 114 Noise section length
     real(kind=4) :: noise   = 0.0         ! 115 Theoretical noise
     real(kind=4) :: rms     = 0.0         ! 116 Actual noise
     ! ASTROMETRY
     integer(kind=4) :: prop  = 0          ! 117 Proper motion section length
     real(kind=4) :: mura     = 0.0        ! 118 along RA, in mas/yr
     real(kind=4) :: mudec    = 0.0        ! 119 along Dec, in mas/yr
     real(kind=4) :: parallax = 0.0        ! 120 in mas
     ! real(kind=4) :: pepoch   = 2000.0     ! 121 in yrs ?
     !
     ! These are not in data, but useful for further reference
     ! For UV Data
     integer(kind=4) :: nchan = 0
     integer(kind=4) :: nvisi = 0
     integer(kind=4) :: nstokes = 1
     integer(kind=4) :: natom = 3
     real(kind=4)    :: basemin = 0.
     real(kind=4)    :: basemax = 0.
  end type gildas_header_v1
  !
  ! NEW File Format
  !
  ! Notes:
  !  1) Total array size will always be stored in INTEGER(8), even on 32-bit machines,
  !     as the mini and maxi indicators.
  !  2) Dimensions are Integer*8 in the data format
  !     Internally, Dimensions, blc, trc, will be typed INTEGER(index_length)
  ! with index_length=4 on 32-bit machines and 8 on 64 bit machines.
  !  3) Actual extrema location per dimension are derived from MINI and MAXI and
  ! the current dimensions. They can be available in the internal description,
  !     without being written on file.
  !
  type :: gildas_header_v2
     !
     ! Spread on two blocks
     !
     ! Block 1: Basic Header and Dimension information
     sequence
     !
     ! Trailer:
     integer(kind=4) :: ijtyp(3) = 0       !  1  Image Type
     integer(kind=4) :: form    = fmt_r4   !  4  Data format (FMT_xx)
     integer(kind=8) :: ndb     = 0        !  5  Number of blocks
     integer(kind=4) :: nhb     = 2        !  7  Number of header blocks
     integer(kind=4) :: ntb     = 0        !  8  Number of trailing blocks
     integer(kind=4) :: version_gdf = code_version_gdf_current !  9  Data format Version number
     integer(kind=4) :: type_gdf =  code_gdf_image  !  10 code_gdf_image or code_null
     integer(kind=4) :: dim_start = gdf_startdim    !  11  Start offset for DIMENSION, should be odd, >12
     integer(kind=4) :: pad_trail
     ! The maximum value would be 17 to hold up to 8 dimensions.
     !
     ! DIMENSION Section. Caution about alignment...
     integer(kind=4) :: dim_words   = 2*gdf_maxdims+2  ! at s_dim=17  Dimension section length
     integer(kind=4) :: blan_start !! = dim_start + dim_lenth + 2   ! 18  Pointer to next section
     integer(kind=4) :: mdim    = 4        !or > ! 19  Maximum number of dimensions in this data format
     integer(kind=4) :: ndim    = 0        ! 20  Number of dimensions
     integer(kind=index_length) :: dim(gdf_maxdims) = 0     ! 21  Dimensions
     !
     ! BLANKING
     integer(kind=4) :: blan_words = 2     ! Blanking section length
     integer(kind=4) :: extr_start         ! Pointer to next section
     real(kind=4) :: bval = +1.23456e+38   ! Blanking value
     real(kind=4) :: eval = -1.0           ! Tolerance
     !
     ! EXTREMA
     integer(kind=4) :: extr_words = 6    ! Extrema section length
     integer(kind=4) :: coor_start !! = extr_start + extr_words +2     !
     real(kind=4) :: rmin    = 0.0         ! Minimum
     real(kind=4) :: rmax    = 0.0         ! Maximum
     integer(kind=index_length) :: minloc(gdf_maxdims) = 0 ! Pixel of minimum
     integer(kind=index_length) :: maxloc(gdf_maxdims) = 0 ! Pixel of maximum
! in file:     integer(kind=8) :: mini = 0           ! Rank 1 pixel of minimum
! in file:     integer(kind=8) :: maxi = 0           ! Rank 1 pixel of maximum
     !
     ! COORDINATE Section
     integer(kind=4) :: coor_words  = 6*gdf_maxdims   ! at s_coor  Section length
     integer(kind=4) :: desc_start  !! = coord_start + coord_words +2     !
     real(kind=8)    :: convert(3,gdf_maxdims)   !  Ref, Val, Inc for each dimension
     !
     ! DESCRIPTION Section
     integer(kind=4) :: desc_words  = 3*(gdf_maxdims+1) ! at s_desc, Description section length
     integer(kind=4) :: null_start  !! = desc_start + desc_words +2     !
     integer(kind=4) :: ijuni(3)   = 0        ! Data Unit
     integer(kind=4) :: ijcod(3,gdf_maxdims) = 0    ! Axis names
     integer(kind=4) :: pad_desc              ! For Odd gdf_maxdims only
     !
     !
     ! The first block length is thus
     !  s_dim-1 + (2*mdim+4) + (4) + (8) +  (6*mdim+2) + (3*mdim+5)
     ! = s_dim-1 + mdim*(2+6+3) + (4+4+2+5+8)
     ! = s_dim-1 + 11*mdim + 23
     ! With mdim = 7, s_dim=11, this is 110 spaces
     ! With mdim = 8, s_dim=11, this is 121 spaces
     ! MDIM > 8 would NOT fit in one block...
     !
     ! Block 2: Ancillary information
     !
     ! The same logic of Length + Pointer is used there too, although the
     ! length are fixed. Note rounding to even number for the pointer offsets
     ! in order to preserve alignement...
     !
     integer(kind=4) :: posi_start  = 1
     !
     ! POSITION
     integer(kind=4) :: posi_words = 15    ! Position section length: 15 used + 1 padding
     integer(kind=4) :: proj_start         !! = s_posi + 16     ! Pointer to next section
     integer(kind=4) :: ijsou(3) = 0       ! 75  Source name
     integer(kind=4) :: ijsys(3) = 0       ! 71  Coordinate System (moved from Description section)
     real(kind=8) :: ra         = 0.d0     ! 78  Right Ascension
     real(kind=8) :: dec        = 0.d0     ! 80  Declination
     real(kind=8) :: lii        = 0.d0     ! 82  Galactic longitude
     real(kind=8) :: bii        = 0.d0     ! 84           latitude
     real(kind=4) :: epoc       = 0.0      ! 86  Epoch of coordinates
     real(kind=4) :: pad_posi
     !
     ! PROJECTION
     integer(kind=4) :: proj_words = 9     ! Projection length: 9 used + 1 padding
     integer(kind=4) :: spec_start !! = proj_start + 12
     real(kind=8) :: a0      = 0.d0        ! 89  X of projection center
     real(kind=8) :: d0      = 0.d0        ! 91  Y of projection center
     real(kind=8) :: pang    = 0.d0        ! 93  Projection angle
     integer(kind=4) :: ptyp = p_none      ! 88  Projection type (see p_... codes)
     integer(kind=4) :: xaxi = 0           ! 95  X axis
     integer(kind=4) :: yaxi = 0           ! 96  Y axis
     integer(kind=4) :: pad_proj
     !
     ! SPECTROSCOPY
     integer(kind=4) :: spec_words  = 14   ! Spectroscopy length: 14 used
     integer(kind=4) :: reso_start  !! = spec_words + 16
     real(kind=8) :: fres       = 0.d0     !101  Frequency resolution
     real(kind=8) :: fima       = 0.d0     !103  Image frequency
     real(kind=8) :: freq       = 0.d0     !105  Rest Frequency
     real(kind=4) :: vres       = 0.0      !107  Velocity resolution
     real(kind=4) :: voff       = 0.0      !108  Velocity offset
     real(kind=4) :: dopp       = -1.0     !     Doppler factor
     integer(kind=4) :: faxi    = 0        !109  Frequency axis
     integer(kind=4) :: ijlin(3) = 0       ! 98  Line name
     integer(kind=4) :: vtyp    = vel_unk  ! Velocity type (see vel_... codes)
     !
     ! RESOLUTION
     integer(kind=4) :: reso_words = 3     ! Resolution length: 3 used + 1 padding
     integer(kind=4) :: nois_start !! = reso_words + 6
     real(kind=4) :: majo    = 0.0         !111  Major axis
     real(kind=4) :: mino    = 0.0         !112  Minor axis
     real(kind=4) :: posa    = 0.0         !113  Position angle
     real(kind=4) :: pad_reso
     !
     ! NOISE
     integer(kind=4) :: nois_words = 2     ! Noise section length: 2 used
     integer(kind=4) :: astr_start !! = s_nois + 4
     real(kind=4) :: noise   = 0.0         ! 115 Theoretical noise
     real(kind=4) :: rms     = 0.0         ! 116 Actual noise
     !
     ! ASTROMETRY
     integer(kind=4) :: astr_words = 3    ! Proper motion section length: 3 used + 1 padding
     integer(kind=4) :: uvda_start !! = s_astr + 4
     real(kind=4) :: mura     = 0.0        ! 118 along RA, in mas/yr
     real(kind=4) :: mudec    = 0.0        ! 119 along Dec, in mas/yr
     real(kind=4) :: parallax = 0.0        ! 120 in mas
     real(kind=4) :: pad_astr
     ! real(kind=4) :: pepoch   = 2000.0     ! 121 in yrs ?
     !
     ! TELESCOPE information section, normally after the UV Data section
     integer(kind=4) :: tele_words  = 2    ! Length of section: 8 used
     integer(kind=4) :: void_start  !! = s_tele + l_tele + 2
     ! Added for UV version V2.2
     integer(kind=4) :: nteles = 0        ! Number of telescopes
     integer(kind=4) :: magic  = 1000     ! Magic offset to code telescope pairs
     !
     !
     ! UV_DATA information
     integer(kind=4) :: uvda_words  = 18+2*code_uvt_last ! Length of section: 14 used
     integer(kind=4) :: tele_start  !! = s_uvda + l_uvda + 2
     integer(kind=4) :: version_uv = code_version_uvt_default  ! 1 version number. Will allow us to change the data format
     integer(kind=4) :: nchan = 0         ! 2 Number of channels
     integer(kind=8) :: nvisi = 0         ! 3-4 Independent of the transposition status
     integer(kind=4) :: nstokes = 0       ! 5 Number of polarizations
     integer(kind=4) :: natom = 0         ! 6. 3 for real, imaginary, weight. 1 for real.
     real(kind=4)    :: basemin = 0.      ! 7 Minimum Baseline
     real(kind=4)    :: basemax = 0.      ! 8 Maximum Baseline
     integer(kind=4) :: fcol              ! 9 Column of first channel
     integer(kind=4) :: lcol              ! 10 Column of last  channel
     ! The number of information per channel can be obtained by
     !       (lcol-fcol+1)/(nchan*natom)
     ! so this could allow to derive the number of Stokes parameters
     ! Leading data at start of each visibility contains specific information
     integer(kind=4) :: nlead = 7           ! 11 Number of leading informations (at lest 7)
     ! Trailing data at end of each visibility may hold additional information
     integer(kind=4) :: ntrail = 0          ! 12 Number of trailing informations
     !
     ! Leading / Trailing information codes have been specified before
     integer(kind=4) :: column_pointer(code_uvt_last) = code_null ! Back pointer to the columns...
     integer(kind=4) :: column_size(code_uvt_last) = 0  ! Number of columns for each
     ! In the data, we instead have the codes for each column
     ! integer(kind=4) :: column_codes(nlead+ntrail)         ! Start column for each ...
     ! integer(kind=4) :: column_types(nlead+ntrail) /0,1,2/ ! Number of columns for each: 1 real*4, 2 real*8
     ! Leading / Trailing information codes
     !
     integer(kind=4) :: order = 0          ! 13  Stoke/Channel ordering
     integer(kind=4) :: nfreq = 0          ! 14  ! 0 or = nchan*nstokes
     integer(kind=4) :: atoms(4)           ! 15-18 Atom description
     !
     ! Then for each telescope
     !   real(kind=8) :: lon     ! Longitude (radians)
     !   real(kind=8) :: lat     ! Latitude  (radians)
     !   real(kind=4) :: alt     ! Altitude (m)
     !   real(kind=4) :: diam    ! Diameter
     !   integer(4)   :: ijtele(3)  ! Telescope name
     !   integer(4)   :: pad     ! Padding for alignment
     !
     type(telesco), allocatable :: teles(:)  !
     !
     real(kind=8), pointer :: freqs(:) => null()     ! (nchan*nstokes) = 0d0
     integer(kind=4), pointer :: stokes(:) => null() ! (nchan*nstokes) or (nstokes) = code_stoke
     !
     ! Only in code
     real(kind=8), pointer :: ref(:) => null()
     real(kind=8), pointer :: val(:) => null()
     real(kind=8), pointer :: inc(:) => null()
  end type gildas_header_v2
  !
  type :: gildas_v1
     sequence
     !
     character(len=256)   :: file = ' '  ! File name
     type (strings)       :: char        !
     type (location)      :: loca        !
     type (gildas_header_v1) :: gil      !
     integer(kind=index_length) :: blc(4) = 0  ! Bottom left corner
     integer(kind=index_length) :: trc(4) = 0  ! Top right corner
     integer(kind=4) :: version = 0      ! = %header 1 = Defined / 0 = Undefined
     integer(kind=4) :: status = 0       ! Last error code
  end type gildas_v1
  !
  type :: gildas_v2
     sequence
     type (gildas_header_v2) :: gil      !
     type (location)      :: loca        !
     type (strings)       :: char        !
     integer(kind=index_length) :: blc(gdf_maxdims) = 0   ! Bottom left corner
     integer(kind=index_length) :: trc(gdf_maxdims) = 0   ! Top right corner
     integer(kind=4) :: version = 0      ! 0 = Undefined / # 0 = Version number
     integer(kind=4) :: status = 0       ! Last error code
     character(len=filename_length) :: file = ' '  ! File name
  end type gildas_v2
  !
end module gio_headers
!
module image_def
  use gildas_def
  use gbl_format
  use gio_headers
  !
  !
  type :: gildas
    sequence
    character(len=256)   :: file = ' '  ! File name
    type (strings)       :: char        !
    type (location)      :: loca        !
    type (gildas_header_v2) :: gil      !
    integer(kind=index_length) :: blc(gdf_maxdims) = 0       ! Bottom left corner
    integer(kind=index_length) :: trc(gdf_maxdims) = 0       ! Top right corner
    integer(kind=4) :: header = 0       ! Defined / Undefined
    integer(kind=4) :: status = 0       ! Last error code
    real,         pointer :: r1d(:)       => null()  ! Pointer to 1D data
    real(kind=8), pointer :: d1d(:)       => null()
    integer,      pointer :: i1d(:)       => null()
    real,         pointer :: r2d(:,:)     => null()  ! Pointer to 2D data
    real(kind=8), pointer :: d2d(:,:)     => null()
    integer,      pointer :: i2d(:,:)     => null()
    real,         pointer :: r3d(:,:,:)   => null()  ! Pointer to 3D data
    real(kind=8), pointer :: d3d(:,:,:)   => null()
    integer,      pointer :: i3d(:,:,:)   => null()
    real,         pointer :: r4d(:,:,:,:) => null()  ! Pointer to 4D data
    real(kind=8), pointer :: d4d(:,:,:,:) => null()
    integer,      pointer :: i4d(:,:,:,:) => null()
  end type gildas
  !
end module image_def
!
function uv_column_name(code)
  use gio_params
  !---------------------------------------------------------------------
  ! @ public
  ! As it is not portable to share a character array between libraries,
  ! this function returns the UV column name given its code.
  !---------------------------------------------------------------------
  character(len=12) :: uv_column_name
  integer(kind=4), intent(in) :: code
  !
  if (code.le.0 .or. code.gt.code_uvt_last) then
    uv_column_name = 'Unknown'
  else
    ! UV column names must match UV column codes
    uv_column_name = gio_column_names(code)
  endif
  !
end function uv_column_name
!
subroutine uv_column_names(list)
  use gio_params
  !---------------------------------------------------------------------
  ! @ public
  ! As it is not portable to share a character array between libraries,
  ! this function returns the UV column name list.
  !---------------------------------------------------------------------
  character(len=*), intent(inout) :: list(:)
  ! Local
  integer(kind=4) :: icol
  !
  do icol=1,min(size(list),code_uvt_last)  ! List may be truncated, that's a desired feature
    list(icol) = gio_column_names(icol)
  enddo
end subroutine uv_column_names
!
function gdf_polar_name(code)
  use gio_params
  !---------------------------------------------------------------------
  ! @ public
  ! Return the polarization name given its code
  !---------------------------------------------------------------------
  character(len=1) :: gdf_polar_name
  integer(kind=4), intent(in) :: code
  !
  if (code.ge.lbound(gio_polar_names,1) .and.  &
      code.le.ubound(gio_polar_names,1)) then
    gdf_polar_name = gio_polar_names(code)
  else
    gdf_polar_name = '?'
  endif
  !
end function gdf_polar_name
!
subroutine gdf_polar_code(name,code,error)
  use gio_params
  !---------------------------------------------------------------------
  ! @ public
  ! This function returns the polarization code given its name (must be
  ! upcased)
  !---------------------------------------------------------------------
  character(len=*), intent(in)    :: name
  integer(kind=4),  intent(out)   :: code
  logical,          intent(inout) :: error
  ! Local
  integer(kind=4) :: icode
  !
  do icode=lbound(gio_polar_names,1),ubound(gio_polar_names,1)
    if (name.eq.gio_polar_names(icode)) then
      code = icode
      return
    endif
  enddo
  !
  code = -1000
  error = .true.
  !
end subroutine gdf_polar_code
!
function gdf_stokes_name(code)
  use gio_params
  !---------------------------------------------------------------------
  ! @ public
  ! Return the Stokes name given its code
  !---------------------------------------------------------------------
  character(len=4) :: gdf_stokes_name
  integer(kind=4),  intent(in)    :: code
  !
  if (code.ge.lbound(gio_stokes_names,1) .and.  &
      code.le.ubound(gio_stokes_names,1)) then
    gdf_stokes_name = gio_stokes_names(code)
  else if (code.eq.code_stokes_all) then
    gdf_stokes_name = 'ALL'
  else if (code.eq.code_stokes_any) then
    gdf_stokes_name = 'ANY'
  else  
    gdf_stokes_name = 'UNKNOWN'
  endif
  !
end function gdf_stokes_name
!
subroutine gdf_stokes_code(name,code,error)
  use gio_params
  !---------------------------------------------------------------------
  ! @ public
  ! This function returns the Stokes code given its name (must be
  ! upcased)
  !---------------------------------------------------------------------
  character(len=*), intent(in)    :: name
  integer(kind=4),  intent(out)   :: code
  logical,          intent(inout) :: error
  ! Local
  integer(kind=4) :: icode
  !
  select case (name)
  case ('ALL')
    code = code_stokes_all
  case ('ANY')
    code = code_stokes_any
  case default
    do icode=lbound(gio_stokes_names,1),ubound(gio_stokes_names,1)
      if (name.eq.gio_stokes_names(icode)) then
        code = icode
        return
      endif
    enddo
    code = -1000
    error = .true.
  end select
  !
end subroutine gdf_stokes_code
