!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
module azimuth_average_head
  !
  interface
     subroutine azimuthal_averaging(image,averaged,summed,nxy,first,last,error)
       use image_def
       type (gildas), intent(in)  :: image
       type (gildas), intent(inout) :: averaged, summed
       logical,               intent(out) :: error
       integer,               intent(in)  :: first,last
       integer, dimension(2), intent(in)  :: nxy
     end subroutine azimuthal_averaging
  end interface
  !
end module azimuth_average_head
!
program azimuth_average
  use image_def
  use azimuth_average_head, only : azimuthal_averaging
  use gkernel_interfaces
  type (gildas) :: image_head,averaged_head,summed_head
  character(len=*), parameter :: rname = 'AZIMUTH_AVERAGE'
  logical :: error
  integer               :: nradius,nplane,iplane,first,last
  integer, dimension(2) :: nxy
  real, dimension(:,:),   allocatable, save, target :: averaged_data,summed_data
  real, dimension(:,:,:), allocatable, save, target :: image_data
  !
  ! Initialize gildas header
  call gildas_null(image_head)
  call gildas_null(summed_head)
  call gildas_null(averaged_head)
  !
  ! Get input parameters and verifies them
  call gildas_open
  call gildas_char('IMAGE$',image_head%file)
  call gildas_char('SUMMED$',summed_head%file)
  call gildas_char('AVERAGED$',averaged_head%file)
  call gildas_inte('NPLANE$',iplane,1)
  call gildas_close
  !
  ! Read IMAGE header, allocates memory space and reads data
  call gdf_read_header(image_head,error)
  if (gildas_error(image_head,rname,error)) call sysexi(fatale)
  nxy = image_head%gil%dim(1:2)
  !
  allocate(image_data(image_head%gil%dim(1),&
       image_head%gil%dim(2),&
       image_head%gil%dim(3)),&
       stat = image_head%status)
  if (gildas_error(image_head,rname,error)) call sysexi(fatale)
  image_head%r3d => image_data
  !
  call gdf_read_data(image_head,image_data,error)
  if (gildas_error(image_head,rname,error)) call sysexi(fatale)
  !
  ! Sanity checks
  if (iplane.eq.0) then
     first = 1
     last = image_head%gil%dim(3)
  else if (iplane.gt.image_head%gil%dim(3)) then
     call gagout('F-'//rname//',  iplane is greater than the 3rd image dimension')
     call sysexi(fatale)
  else if (iplane.lt.0) then
     call gagout('F-'//rname//',  iplane is negative or zero valued')
     call sysexi(fatale)
  else
     first = iplane
     last = iplane
  endif
  if ((image_head%gil%inc(1).eq.0.0).or.(image_head%gil%inc(2).eq.0.0)) then
     call gagout('F-'//rname//',  pixel size is zero valued')
     call sysexi(fatale)
  endif
  !
  ! Allocate memory space for the output results
  nradius = minval(nxy)
  nplane  = image_head%gil%dim(3)
  allocate(averaged_data(nradius,nplane),stat=averaged_head%status)
  if (gildas_error(averaged_head,rname,error)) call sysexi(fatale)
  averaged_head%r2d => averaged_data
  !
  allocate(summed_data(nradius,nplane),stat=summed_head%status)
  if (gildas_error(summed_head,rname,error)) call sysexi(fatale)
  summed_head%r2d => summed_data
  !
  ! Compute azimuthal average and sum
  call azimuthal_averaging(image_head,averaged_head,summed_head,nxy,first,last,error)
  if (error) call sysexi(fatale)
  !
  ! Write results on disk
  call gdf_write_image(averaged_head,averaged_data,error)
  if (gildas_error(averaged_head,rname,error)) call sysexi(fatale)
  !
  call gdf_write_image(summed_head,summed_data,error)
  if (gildas_error(summed_head,rname,error)) call sysexi(fatale)
  !
  ! Free memory space and return
  deallocate(image_data,stat=image_head%status)
  if (gildas_error(image_head,rname,error)) call sysexi(fatale)
  !
  deallocate(summed_data,stat=summed_head%status)
  if (gildas_error(summed_head,rname,error)) call sysexi(fatale)
  !
  deallocate(summed_data,stat=summed_head%status)
  if (gildas_error(averaged_head,rname,error)) call sysexi(fatale)
  !
end program azimuth_average
!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
subroutine azimuthal_averaging(image,averaged,summed,nxy,first,last,error)
  use image_def
  use gkernel_interfaces
  type (gildas), intent(in)  :: image
  type (gildas), intent(inout) :: averaged,summed
  logical,               intent(out) :: error
  integer,               intent(in)  :: first,last
  integer, dimension(2), intent(in)  :: nxy
  !
  ! Local variables
  integer, dimension(min(nxy(1),nxy(2))) :: indices
  integer :: i,iplane,jplane,jradius,nrad
  real    :: r_pix,x_pix,y_pix
  real, dimension(nxy(1)) :: x
  real, dimension(nxy(2)) :: y
  real, dimension(nxy(1),nxy(2)) :: xy
  !
  error = .false.
  !
  x_pix = abs(image%gil%inc(1))
  y_pix = abs(image%gil%inc(2))
  !
  r_pix = sqrt(x_pix*y_pix)
  nrad  = min(nxy(1)*x_pix,nxy(2)*y_pix)/r_pix
  !
  x = (/ (real(i), i = 1, nxy(1)) /)
  y = (/ (real(i), i = 1, nxy(2)) /)
  !
  x = image%gil%val(1)+(x-image%gil%ref(1))*image%gil%inc(1)
  y = image%gil%val(2)+(y-image%gil%ref(2))*image%gil%inc(2)
  !
  summed%r2d = 0.0
  averaged%r2d = 0.0
  !
  do jradius = 1, nxy(2)
     xy(:,jradius) = sqrt(x**2+y(jradius)**2)
     indices = int(xy(:,jradius)/r_pix)+1
     do iplane=first,last
        jplane=iplane-first+1
        where(indices.le.nrad)
           summed%r2d(indices,jplane) = summed%r2d(indices,jplane) + image%r3d(:,jradius,iplane)
           averaged%r2d(indices,jplane) = averaged%r2d(indices,jplane) + 1.0
        endwhere
     enddo
  enddo
  !
  where(averaged%r2d /= 0.0)
     averaged%r2d = summed%r2d/averaged%r2d
  endwhere
  !
  ! Update headers
  summed%char = image%char
  summed%gil = image%gil
  summed%gil%dim(1) = nrad
  summed%gil%ref(1) = 1
  summed%gil%val(1) = 0.0
  summed%gil%inc(1) = r_pix
  summed%gil%xaxi = 1
  summed%gil%yaxi = 0
  if (last-first.eq.0) then
     summed%char%code(1) = 'AZM. SUM'
     summed%gil%ndim = 1
     summed%gil%dim(2) = 0
     summed%gil%ref(2) = 0
     summed%gil%val(2) = 0
     summed%gil%inc(2) = 0
     summed%gil%faxi = 0
  else
     summed%char%code(2) = image%char%code(3)
     summed%gil%ndim   = 2
     summed%gil%dim(2) = last-first+1
     summed%gil%ref(2) = image%gil%ref(3)
     summed%gil%val(2) = image%gil%val(3)
     summed%gil%inc(2) = image%gil%inc(3)
     summed%gil%faxi = 2
  endif
  summed%char%code(3:4) = 'UNKNOWN'
  summed%gil%dim(3:4) = 0
  summed%gil%convert(:,3:) =  0
  !
  averaged%gil  = summed%gil
  averaged%char = summed%char
  averaged%char%code(1) = 'AZM. AVE.'
  !
end subroutine azimuthal_averaging
!
!!!!!!!!!!!!!!!!!!!!! azimuth_average.f90 ends here !!!!!!!!!!!!!!!!!!!!!!!
