subroutine astro_j2000(line,error)
  use gkernel_interfaces
  use gbl_message
  use ast_astro
  !---------------------------------------------------------------------
  ! @ private
  !	ASTRO Command :
  !	CONVERT out_catalog_name /J2000 obs_equinox ! change ref frame to J2000
  !	/PRECESS new_equinox		! precess to equinox
  !     /FLUX fmin                ! select sources larger than fmin Jy
  !     /NAME ncname iname        ! reserve ncname chars for names;
  !                               ! Put `IAU' standard name in iname^th position
  !     /INPUT POS filename pos
  !     /INPUT FLUX filename
  !---------------------------------------------------------------------
  character(len=*):: line           !
  logical :: error                  !
  ! Local
  integer(kind=4), parameter :: iopt_alt=1 !
  integer(kind=4), parameter :: iopt_j2000=2 !
  integer(kind=4), parameter :: iopt_prec=3 !
  integer(kind=4), parameter :: iopt_gal=4!
  integer(kind=4), parameter :: iopt_flux=5 !
  integer(kind=4), parameter :: iopt_name=6 !
  integer(kind=4), parameter :: iopt_input=7 !
  !
  character(len=2) :: coord, fcoord    ! coordinate system ('EQ','GA','HO'...)
  character(len=2) :: vtyp             ! velocity system ('LS', 'EA', 'HE')
  real(kind=4) :: equinox, new_equinox, fequinox   ! Equinox
  real(kind=8) :: velo,redsh                       ! Velocity (km/s)
  real(kind=8) :: lambda, beta, flambda, fbeta  ! coords (rad)
  character(len=40) :: name,file
  character(len=80) :: par
  logical :: to_j2000, precess, to_galactic, do_flux, do_alt
  logical :: do_name, input, found
  integer(kind=4) :: nlu, npar, lpar, nc, lun, olun, i, icat, ier
  integer(kind=4) :: iname, nkey, ncname
  character(len=2) :: ftype
  real(kind=4) :: flux, spindex, mag(9), obs_equinox, fmin, fflux, fspindex
  real(kind=4) :: poserr, posmin
  character(len=256) :: c_line, comment, ctext
  character(len=30) :: fcomment, ftext
  real(kind=8) :: s(2), x_0(3), x_1(3), matrix(9)
  integer(kind=4) :: mvfile
  parameter(mvfile=3)
  character(len=12) :: vfile(mvfile), key, arg, aname
  character(len=7) :: rname
  ! Data
  data vfile/'ALIAS','FLUX', 'POSITION'/
  data rname /'CONVERT'/
  ! Code -------------------------------------------------------------------
  !
  if (sic_nopt().le.0) then
    call astro_message(seve%i,rname,"Command requires at least one option")
    call astro_message(seve%i,rname,"Nothing done")
    return
  endif
  !
  do_alt = sic_present(iopt_alt,0)
  do_name = sic_present(iopt_name,0)
  do_flux = sic_present(iopt_flux,0)
  to_j2000 = sic_present(iopt_j2000,0)
  precess = sic_present(iopt_prec,0)
  to_galactic = sic_present(iopt_gal,0)
  input = sic_present(iopt_input,0)
  !
  ! Some options are exclusive
  if ((to_j2000.and.precess).or.(to_j2000.and.to_galactic).or.(to_galactic.and.precess)) then
    call astro_message(seve%e,rname,"/J2000, /PRECESS, /GALACTIC options cannot be combined")
    error=.true.
    return
  endif
  !
  ! Select right catalog
  if (do_alt) then
    icat = 2
  else
    icat = 1
  endif
  if (lenc(catalog_name(icat)).eq.0) then
    call astro_message(seve%f,rname,'No catalog')
    error = .true.
    return
  endif
  !
  ! Find output file name
  if (sic_present(0,1)) then
    ! Output File given in arg
    call sic_ch (line,0,1,name,nc,.true.,error)
    if (error) return
    call sic_parsef(name,file,' ','.sou')
  else
    ! Output file automatic
    name = catalog_name(icat)
    call sic_parsef(name,file,' ','.sou')
    nc = lenc(name)
    if (to_j2000) then
      name = name(1:nc)//'-J2000'
    elseif (precess) then
      name = name(1:nc)//'-prec'
    elseif (to_galactic) then
      name = name(1:nc)//'-gal'
    endif
    if (do_flux) then
      nc = lenc(name)
      name = name(1:nc)//'-flux'
    endif
    if (do_name) then
      nc = lenc(name)
      name = name(1:nc)//'-name'
    endif
    if (input) then
      nc = lenc(name)
      name = name(1:nc)//'-new'
    endif
    call sic_parsef(name,file,' ','.sou')
  endif
  !
  ! Input file for edition
  iname = 0
  if (input) then
    ! Read argument
    call sic_ke(line,iopt_input,1,arg,nc,.true.,error)
    if (error) return
    call sic_ambigs(rname,arg,key,nkey,vfile,mvfile,error)
    if (error) return
    ! Read file name
    call sic_ch(line,iopt_input,2,name,nc,.true.,error)
    if (error) return
    call sic_parsef(name,file,' ','.dat')
    if (key.eq.'POSITION') then
      posmin = 0.0001
      call sic_r4(line,iopt_input,3,posmin,.false.,error)
      if (error) return
    elseif (key.eq.'ALIAS') then
      iname = -1
    endif
    call get_input(key,file,error)
    if (error) return
  endif
  !
  ! /NAME ncname iname
  ncname = 48
  if (do_name) then
    call sic_i4(line,iopt_name,1,ncname,.true.,error)
    if (error) return
    call sic_i4(line,iopt_name,2,iname,.false.,error)
    if (error) return
  endif
  !
  ! Case of FLUX option
  fmin = -1.
  if (do_flux) then
    call sic_r4(line,iopt_flux,1,fmin,.true.,error)
    if (error) return
  endif
  !
  !
  ! Observation equinox:
  obs_equinox = 1950.
  if (to_j2000) then
    call sic_r4 (line,iopt_j2000,1,obs_equinox,.false.,error)
    if (error) return
  endif
  ! New equinox:
  new_equinox = 2000.
  if (precess) then
    call sic_r4 (line,iopt_prec,1,new_equinox,.false.,error)
    if (error) return
  endif
  !
  ! Open input catalog
  ier = sic_getlun (lun)
  ier = sic_open(lun,catalog_name(icat),'OLD',.true.)
  if (ier.ne.0) then
    call astro_message(seve%e,rname,'Error opening '// catalog_name(icat))
    call putios('E-CONVERT,  ',ier)
    error = .true.
    call sic_frelun(lun)
    return
  endif
  !
  ! Open output catalog
  ier = sic_getlun(olun)
  ier = sic_open(olun,file,'NEW',.false.)
  if (ier.ne.0) then
    call astro_message(seve%e,rname,'Error opening file:')
    call astro_message(seve%e,rname,file)
    call putios('E-CONVERT,  ',ier)
    error = .true.
    goto 210
  endif
  vtyp = 'LS'
  !
  do while (.true.)
    ! Start to read the catalog
    100      read(lun,1000,end=210,iostat=ier) c_line
    if (ier.ne.0) then
      call astro_message(seve%e,rname,'Error reading catalog')
      error = .true.
      goto 210
    endif
    nlu = lenc(c_line)
    if (nlu.eq.0) then
      ! Empty line in input
      write(olun,1000) '!'
      goto 100
    elseif (c_line(1:1).eq.'!') then    
      ! commented line in input
      write(olun,1000) c_line(1:nlu)
      goto 100
    endif
    ! Look for comment
    i = index(c_line(1:nlu),'!')
    if (i.ne.0) then
      comment = c_line(i+1:nlu)
      nc = lenc(comment)
      call sic_blanc(comment,nc)
    else
      comment = ' '
    endif
    ! Process the meaningful part of the line
    call sic_blanc(c_line,nlu)
    npar = 1
    lpar = 50
    call sic_next(c_line(1:nlu),par,lpar,npar)
    if (lpar.eq.0) goto 100
    par = par(1:lpar)
    lpar = min(lpar,48)
    ctext = par(1:lpar)
    ! Decode the line (coordinate, velocity, fluxes,...)
    call decode_line (c_line, npar, coord, equinox, lambda, beta, vtyp, velo, redsh, &
    ftype, flux, spindex, mag, error)
    ! Do the requested conversion
    if (to_j2000) then
      if (coord.eq.'EQ' .and. equinox.eq.1950. ) then
        call b1950_to_j2000(obs_equinox,lambda,beta)
        equinox = 2000.0
      else
        call astro_message(seve%r,rname,par(1:lpar)//' not converted to J2000')
      endif
    endif
    if (precess) then
      if (coord.eq.'EQ') then
        call do_precess(equinox,new_equinox,lambda,beta)
      elseif (coord.eq.'GA') then
        s(1) = lambda
        s(2) = beta
        call rect (s, x_0)
        call chgcoo ('GA','EQ',1950.0,new_equinox,matrix)
        call matvec (x_0, matrix, x_1)
        call spher (x_1, s)
        lambda = s(1)
        beta = s(2)
        coord = 'EQ'
      else
        call astro_message(seve%r,rname,par(1:lpar)//' not precessed')
      endif
    endif
    if (to_galactic) then
      if (coord.eq.'EQ') then
        s(1) = lambda
        s(2) = beta
        call rect (s, x_0)
        call chgcoo ('EQ','GA',equinox,1950.0,matrix)
        call matvec (x_0, matrix, x_1)
        call spher (x_1, s)
        lambda = s(1)
        beta = s(2)
        coord = 'GA'
      else
        call astro_message(seve%r,rname,par(1:lpar)//' not converted')
      endif
    endif
    ! /INPUT option: add info to the line
    if (input) then
      call find_input(ctext, key, ftext, fcoord, fequinox, flambda, fbeta,  &
      fflux, fspindex, fcomment, found)
      aname = ' '
      if (found) then
        if (key.eq.'FLUX') then
          if (fflux.gt.0) then
            flux = fflux
            if (fspindex.ne.0) spindex=fspindex
            comment = comment(1:lenc(comment))//' +' //fcomment
            print 1012, ftext, flux
            1012                 format('*** ',a12,' Flux ',f8.3,'Jy')
          endif
        elseif (key.eq.'POSITION') then
          if (coord.eq.fcoord .and. equinox.eq.fequinox) then
            poserr = sqrt((lambda-flambda)**2+(beta-fbeta)**2)   &
                     *180*3600/3.1415929d0
            if (poserr.gt.posmin) then
              print 1011, ftext, poserr
              1011 format('*** ',a12,' Position Error ',f8.3,'"')
              lambda = flambda
              beta = fbeta
            endif
            comment = comment(1:lenc(comment))//' +' //fcomment
          endif
        elseif (key.eq.'ALIAS') then
          aname  = fcomment
        endif
      endif
    endif
    if (flux.ge.fmin) then
      ! Build the output line
      call encode_line (olun, par, lpar, coord, equinox, lambda, beta, vtyp,  &
      velo, ftype, flux, spindex, comment, iname, ncname, aname, error)
    endif
  enddo
  !
  ! End
  210   close (unit=lun)
  call sic_frelun (lun)
  close (unit=olun)
  call sic_frelun (olun)
  return
  !
  1000  format(a)
end subroutine astro_j2000
!
subroutine encode_line (olun, par, lpar, coord, equinox, lambda, beta, vtypx,  &
  velo, ftype, flux, spindex, comment, iname, ncname, aname, error)
  use gkernel_interfaces
  use ast_constant
  !---------------------------------------------------------------------
  ! @ private
  !
  !---------------------------------------------------------------------
  integer(kind=4) :: olun           !
  character(len=*):: par            !
  integer(kind=4) :: lpar           !
  character(len=2) :: coord         !
  real(kind=4) :: equinox           !
  real(kind=8) :: lambda            !
  real(kind=8) :: beta              !
  character(len=2) :: vtypx         !
  real(kind=4) :: velo              !
  character(len=2) :: ftype         !
  real(kind=4) :: flux              !
  real(kind=4) :: spindex           !
  character(len=*):: comment        !
  integer(kind=4) :: iname          !
  integer(kind=4) :: ncname         !
  character(len=12) :: aname        !
  logical :: error                  !
  ! Local
  character(len=256) :: line
  character(len=80) :: cpar, ctest
  integer(kind=4) :: nc, j, k1, k2, lca
  character(len=16) :: lcoo, bcoo
  real(kind=4) :: ss
  !------------------------------------------------------------------------
  ! Code:
  ! iname = -1: insert comment as first name (in first position)
  ! iname gt 0 : insert a standard name in position iname
  ! note: this conforms to IAU standards, I guess (RL)
  ! (leave out EC or GA for the time being)
  lca = lenc(aname)
  if (iname.gt.0) then
    if (coord.eq.'EQ') then
      if (equinox.eq.2000.) then
        line(1:1) = 'J'
      elseif (equinox.eq.1950.0) then
        line(1:1) = 'B'
      endif
      call rad2sexa(lambda,24,lcoo,4,left=.true.)
      line(2:5) = lcoo(1:2)//lcoo(4:5)
      read(lcoo(7:11),'(f5.2)') ss
      write(line(6:6),'(i1.1)') int(ss/6.0)
      call rad2sexa(beta,360,bcoo,3,left=.true.)
      if (bcoo(1:1).ne.'-') then
        bcoo = '+'//bcoo(1:15)
      endif
      line(7:11) = bcoo(1:3)//bcoo(5:6)
      nc = 12
      ! strip out standard name if already there:
      k1 = index(par(1:lpar),line(1:5))
      if (k1.ne.0 .and.(k1.eq.1.or.par(k1-1:k1-1).eq.'|')) then
        k2 = index(par(k1:lpar),'|')
        if (k2.ne.0 .and. k1.gt.1) then
          par = par(1:k1-1)//par(k2+1:lpar)
          lpar = k1-1 + lpar-k2
        elseif (k2.ne.0 .and. k1.eq.1) then
          par = par(k2+1:lpar)
          lpar = lpar-k2
        else
          if (k1.gt.1) par = par(1:k1-1)
          lpar = k1-1
        endif
      endif
      !
      ! put standard name in inameth position
      j = 1
      k1 = 1
      do while (j.lt.iname .and. k1.lt.lpar)
        k1 = index(par(k1:lpar),'|')
        if (k1.gt.0) then
          k1 = k1+1
          j = j+1
        else
          k1 = lpar+1
        endif
      enddo
      if (j.lt.iname) then
        par = par(1:lpar)//'|'//line(1:11)
      elseif (j.eq.1 .and. lpar.gt.0) then
        par = line(1:11)//'|'//par(1:lpar)
      elseif (lpar.gt.0) then
        par = par(1:k1-1)//line(1:11)//'|'//par(k1:lpar)
      else
        par = line(1:11)
        lpar = -1
      endif
      lpar = lpar+12
    endif
    ! Alias operation:
  elseif (iname.eq.-1) then
    ! (no alias provided : shortcut.
    if (lca.le.0) then
      if (coord.eq.'EQ') then
        if (equinox.eq.2000.) then
          aname(1:1) = 'J'
        elseif (equinox.eq.1950.0) then
          aname(1:1) = 'B'
        endif
        call rad2sexa(lambda,24,lcoo,4,left=.true.)
        aname(2:5) = lcoo(1:2)//lcoo(4:5)
        call rad2sexa(beta,360,bcoo,3,left=.true.)
        if (bcoo(1:1).ne.'-') then
          bcoo = '+'//bcoo(1:15)
        endif
        aname(6:8) = bcoo(1:3)
        read(bcoo(5:6),'(f2.0)') ss
        write(aname(9:9),'(i1.1)') int(ss/6.0)
        lca = 9
      endif
    endif
    cpar(1:1)  = '|'
    cpar(2:lpar+1) = par(1:lpar)
    ctest(1:1)  = '|'
    ctest(2:lca+1) = par(1:lca)
    ! K1 = INDEX('|'//PAR(1:LPAR),'|'//ANAME(1:LCA))
    k1 = index(cpar(1:lpar+1),ctest(1:lca+1))
    if (k1.ne.0 .and.(k1.eq.1.or.par(k1-1:k1-1).eq.'|')) then
      k2 = index(par(k1:lpar),'|')
      if (k2.ne.0 .and. k1.gt.1) then
        par = par(1:k1-1)//par(k2+k1:lpar)
        lpar = lpar-k2
      elseif (k2.ne.0 .and. k1.eq.1) then
        par = par(k2+1:lpar)
        lpar = lpar-k2
      else
        if (k1.gt.2) par = par(1:k1-2)
        lpar = k1-2
      endif
    endif
    if (lpar.gt.11) then
      par= aname(1:lca)//'|'//par(13:lpar)
      lpar = lca+lpar-11
    else
      par= aname(1:lca)
      lpar = lca
    endif
  endif
  !
  ! shorten to ncname, but do not truncate an alias name:
  if (lpar.gt.ncname) then
    lpar = 0
    do while (lpar.lt.ncname)
      k1 = index(par(lpar+2:ncname+1),'|')
      if (k1.gt.0) then
        lpar = lpar + k1
      else
        if (lpar.gt.0) par(lpar+1:ncname) = ' '
        lpar = ncname
      endif
    enddo
  endif
  line = par(1:lpar)//' '
  nc = ncname+2
  !
  ! finished with names, now coords.
  line(nc:) = coord//' '
  nc = nc+3
  if (coord.eq.'EQ') then
    if (equinox.eq.2000.0) then
      line(nc+1:) = '2000 '
      nc = nc+5
    else
      write(line(nc+1:),'(F8.3,1X)') equinox
      nc = nc + 9
    endif
  endif
  if (coord.eq.'EQ') then
    call rad2sexa(lambda,24,line(nc+1:),4,left=.true.)
    line(nc+16:) = ' '
    nc = nc+16
  else
    write(line(nc+1:nc+12),'(f11.6,1x)') mod(lambda*180d0/pi+360d0,360d0)
    nc=nc+12
  endif
  if (coord.eq.'EQ') then
    if (beta.gt.0) then
      line(nc+1:) = '+'
      nc = nc+1
      call rad2sexa(beta,360,line(nc+1:),3,left=.true.)
      nc = nc+15
    else
      call rad2sexa(beta,360,line(nc+1:),3,left=.true.)
      nc = nc+16
    endif
  else
    write(line(nc+1:nc+12),'(f11.6,1x)') beta*180d0/pi
    nc=nc+12
  endif
  line(nc+1:) = ' '//vtypx//' '
  nc = nc + 4
  if (vtypx.ne.'NU') then
    write(line(nc+1:),'(F8.3,1X)') velo
    nc = nc + 9
  endif
  line(nc+1:) = ' '//ftype//' '
  nc = nc+4
  write(line(nc+1:),'(F8.3,1X)') flux
  nc = nc + 9
  write(line(nc+1:),'(F8.3,1X)') spindex
  nc = nc + 9
  write(olun,'(A,a,a)',err=99) line(1:nc),' ! ', comment(1:lenc(comment))
  return
  !
  99    error = .true.
end subroutine encode_line
!
subroutine get_input(key,file,error)
  use gbl_message
  use gkernel_interfaces
  !---------------------------------------------------------------------
  ! @ private
  !
  !---------------------------------------------------------------------
  character(len=*):: key            !
  character(len=*):: file           !
  logical :: error                  !
  ! Local
  character(len=*):: fkey, ctext, fcomment, fcoord, ftext
  logical :: found
  !
  integer(kind=4) :: ier, lun, nlu, i, npar, lpar, ndata, mdata, k, idata
  integer(kind=4) :: ltext, l, nc, l1
  parameter (mdata=3500)
  character(len=2) :: coodata(mdata)
  character(len=12) :: comdata(mdata),cdata(mdata)
  real(kind=4) :: fdata(mdata), sdata(mdata),equdata(mdata)
  real(kind=4) :: equinox, velo, flux, spindex, mag(9), fequinox, fflux, fspindex
  real(kind=8) :: flambda, fbeta
  real(kind=8) :: lambda, beta, lamdata(mdata), betdata(mdata)
  character(len=32) :: comment
  character(len=256) :: c_line,par
  character(len=2) :: coord,vtyp,ftype
  character(len=7) :: rname
  ! Data
  data rname /'CONVERT'/
  !
  save
  !--------------------------------------------------------------------
  !
  ! Open data file
  ier = sic_getlun (lun)
  ier = sic_open (lun,file,'OLD',.true.)
  if (ier.ne.0) then
    call astro_message(seve%e,rname,'Error opening file:')
    call astro_message(seve%e,rname,file)
    call putios('E-CONVERT,  ',ier)
    error = .true.
    call sic_frelun(lun)
    return
  endif
  !     read data
  ndata = 0
  do while (.true.)
    50       read(lun,1000,end=70,iostat=ier) c_line
    1000     format(a)
    if (ier.ne.0) then
      call astro_message(seve%e,rname,'Error reading file:')
      call astro_message(seve%e,rname,file)
      error = .true.
      goto 70
    endif
    nlu = lenc(c_line)
    if (nlu.eq.0) then
      goto 50
    elseif (c_line(1:1).eq.'!') then
      goto 50
    endif
    i = index(c_line(1:nlu),'!')
    if (i.ne.0) then
      comment = c_line(i+1:nlu)
      nc = lenc(comment)
      call sic_blanc(comment,nc)
    else
      comment = ' '
    endif
    call sic_blanc(c_line,nlu)
    npar = 1
    lpar = 40
    call sic_next(c_line(1:nlu),par,lpar,npar)
    if (lpar.eq.0) goto 50
    l = index(par(1:lpar), '|')
    if (ndata.ge.mdata) then
      call astro_message(seve%e,rname,'File is too big:')
      call astro_message(seve%e,rname,file)
      goto 70
    endif
    if (key.eq.'ALIAS') then
      if (l.gt.0 .and. l.lt.lpar) then
        ndata=ndata+1
        cdata(ndata) = par(1:lpar)
        l1 = index(par(l+1:lpar), '|')
        if (l1.eq.0) l1=lpar-l+1
        comdata(ndata) = par(l+1:l+l1-1)
      endif
    else
      if (l.gt.0 .and. l.le.lpar) lpar = l-1
      par = par(1:lpar)
      call decode_line (c_line, npar, coord, equinox, lambda, beta, vtyp, velo,  &
      ftype, flux, spindex, mag, error)
      if (key.eq.'FLUX') then
        if (flux.gt.0) then
          ndata=ndata+1
          cdata(ndata) = par(1:lpar)
          fdata(ndata) = flux
          sdata(ndata) = spindex
          comdata(ndata) = comment(1:lenc(comment))
        endif
      elseif (key.eq.'POSITION') then
        ndata=ndata+1
        cdata(ndata) = par(1:lpar)
        lamdata(ndata)= lambda
        betdata(ndata)= beta
        equdata(ndata)= equinox
        coodata(ndata)= coord
        comdata(ndata) = comment(1:lenc(comment))
      endif
    endif
  enddo
  70    close(unit=lun)
  call sic_frelun(lun)
  idata = 0
  return
  !
  entry find_input(ctext, fkey, ftext, fcoord, fequinox, flambda, fbeta, fflux,  &
  fspindex, fcomment, found)
  ltext = lenc(ctext)
  do k=1, ndata
    idata = mod(idata, ndata)+1
    l = lenc(cdata(idata))
    if (index(ctext(1:ltext),cdata(idata)(1:l)) .ne. 0) then
      if (fkey.eq.'FLUX') then
        fflux = fdata(idata)
        fspindex = sdata(idata)
        fcomment = comdata(idata)
      elseif (fkey.eq.'POSITION') then
        flambda = lamdata(idata)
        fbeta = betdata(idata)
        fequinox = equdata(idata)
        fcoord = coodata(idata)
        fcomment = comdata(idata)
      elseif (fkey.eq.'ALIAS') then
        fcomment = comdata(idata)
      endif
      ftext = cdata(idata)(1:l)
      found = .true.
      return
    endif
  enddo
  found = .false.
  return
end subroutine get_input
