Gin4Imprint.f90
!------------------------------------------------------------------------------
!                        Program GIN4IMPRINT
!
! Auxiliary program for WOMBAT to set up inverse of gametic relationship matrix
! Files written out allow imprinting effects to be fitted with a GIN covariance
! structure:
!   1. The .gin file -> default name: imprint.gin
!   2. The corresponding .codes file -> default name: imprint.codes
!      Gametes are coded as: animal ID * 10 + 1 (paternal) and 
!                            animal ID * 10 + 2 (maternal)
!                            => need to add corresponding column to data file!
! Input required:
!   Pedigree file (after pruning) with animal, sire and dam ID recoded in
!   running order and animals' inbreeding coefficients;
!   this can easily be generated by WOMBAT by running a set-up step for a
!   corresponding model without the imprinting effect(s) fitted
!
! Code for gametic relationship matrix written by Bruce Tier
!-------------------------------------------------------------km----02/2011-----
 
! =======================
  program Gin4Imprinting
! =======================
 
  implicit none
 
  integer, parameter :: ibig = 2147483647
! Output files for WOMBAT, edit names as desired
  character(len=13)  :: ginfile   = 'imprint.gin  ', &
&                       codesfile = 'imprint.codes'
! Pruned pedigree file with inbreeding coefficients written out by WOMBAT
  character(len=18)  :: ppedfile  = 'PrunedPedFile1.dat'
  integer            :: nanis, ii, ian, idad, imum, jan, jdad, jmum
  real(8)            :: xx
 
  write(*,*)'***********   Program "Gin4Imprinting"  **************'
 
! read pedigree file & count no. of animals
  open(31, file = ppedfile, status = 'old', form ='formatted', action ='read')
  do
     read(31, *, iostat=ii ) ian, idad, imum, jan, jdad, jmum, xx
     if( ii < 0 ) then
         exit ! end of file
     else if( ii > 0 ) then
         write(*,*) 'Some sort of error: reading file "',ppedfile,'"'
         write(*,*) 'Last running no. read correctly was', ian
         stop 'Check file!'
     end if
  end do
  write(*,*)'Highest animal ID found      =', ian, jan
 
! set up inverse of gametic relationship matrix
  nanis = ian;  rewind(31)
  call fbt
 
  write(*,*)'"Gametic inverse" complete'
  write(*,*)'Files written out: "',trim(ginfile),'"  and  "',trim(codesfile),'"'
  write(*,*)'******************************************************'
  stop
 
  contains
 
! ==============
  subroutine fbt
! ==============
 
  real(8), dimension(:), allocatable   :: eff, diag, pxp, pxg
  integer, dimension(:,:), allocatable :: ged, ped
  real(8)                              :: rlogl, ras, das, rad, ff, slogl
  integer                              :: npxp, i, ia, is, id, ka1, ka2, &
&                                         ks1, ks2, kd1, kd2, ngams
 
! memory requirement = nanis*14 words
  ngams = nanis*2
  allocate( pxg(0:ngams), ped(2,0:nanis), ged(0:2,0:ngams),  &
            eff(0:nanis), diag(0:ngams), pxp(0:ngams), stat=ii )
  ped = 0; ged = 0; eff = 0.d0; diag = 0.d0; pxp = 0.d0; pxg = 0.d0
 
! read in pedigree  & inbreeding and store elements
  eff(0)= - 1.d0; rlogl = 0.d0
 
! read in pedigree and store elements
  do i = 1, nanis
     read(31,*) ia, is, id, jan, jmum, jdad, ff
     xx = jan * 10 + 2
     if( xx > dble(ibig) ) then
         write(*,*)'Original ID too big for coding gametes as "ID*10+i"'
         write(*,*) jan
         stop
     end if
     ped(1,i) = is
     ped(2,i) = id
     eff(i) = ff
!    codes for gametes -> original ID*10+i; i=1: paternal, i=2: maternal
     ka2 = ia * 2; ka1 = ka2 - 1
     ged(0,ka1) = 10 * jan + 1  
     ged(0,ka2) = 10 * jan + 2
!    gametes contributions 
     ras = 2.d0 / (1.d0 - eff(is) )
     rad = 2.d0 / (1.d0 - eff(id) )
     rlogl = rlogl + log(ras) + log(rad)
     diag(ka1) = ras
     diag(ka2) = rad
     if( is > 0 ) then         ! sire gametes
        ks2 = is * 2
        ks1 = ks2 - 1
        ged(1,ka1) = ks1
        ged(2,ka1) = ks2
        ras = -0.5d0*ras
        pxg(ka1) = ras
        ras = -0.5d0*ras
        pxp(ks2) = pxp(ks2) + ras
        diag(ks1) = diag(ks1) + ras
        diag(ks2) = diag(ks2) + ras
    end if
    if( id > 0 ) then          ! dam gametes
       kd2 = id * 2
       kd1 = kd2 - 1
       ged(1,ka2) = kd1
       ged(2,ka2) = kd2
       rad = -0.5d0*rad
       pxg(ka2) = rad
       rad = -0.5d0*rad
       pxp(kd2) = pxp(kd2)+rad
       diag(kd1) = diag(kd1)+rad
       diag(kd2) = diag(kd2)+rad
    end if
    if( mod(ia,50000) == 0 ) write(*,'(2hAt,3(i12,2i8))') ia, ped(:,ia), ka1, &
&                                               ged(1:,ka1), ka2, ged(1:,ka2)
  end do
  close(31)
 
! write out files for WOMBAT
  open(408, file = codesfile, status = 'unknown', form = 'formatted', &
&                                                 action = 'write' )
  open(409, file = ginfile,  status = 'unknown', form = 'formatted',   &
&                                                 action = 'write' )
 
  write(409,*) -rlogl, -rlogl/log(10.0)   ! log determinant
  npxp = 0
  do i = 1, ngams
     write(408,'(i8,i15)') i, ged(0,i)
     if( pxg(i) /= 0.d0 ) then
         write(409,'(2i8,f16.8)') ged(1,i), i, pxg(i)
         write(409,'(2i8,f16.8)') ged(2,i), i, pxg(i)
         npxp = npxp + 2
     end if
     if( mod(i,2) == 0 .and. pxp(i) /= 0.d0) then
         write(409,'(2i8,f16.8)') i-1, i, pxp(i)
         npxp = npxp + 1
     end if
     write(409,'(2i8,f16.8)') i, i, diag(i)
  end do
  close(408); close(409) 
  write(*,*)'No. of gametes               =', ngams
  write(*,*)'No. of elements in inverse G =', ngams + npxp
 
  return
  end subroutine fbt
 
  end program Gin4Imprinting