Project 6

Modify your bird_data type from Project 5 to make it a class. Make all the methods private.

You may use the same file_utils.f90 and sorters.f90 as before.

You may find that you need to declare your allocatable bird_list array to be of type class.

Sample solution

module bird_dat
implicit none

type bird_data
   character(len=50)                  :: species
   integer, dimension(:), allocatable :: obs

   contains
       procedure:: init=>constructor
       procedure:: stats
       procedure:: minmax
end type bird_data

private constructor, stats, minmax

contains
   
subroutine constructor(bird,species,dat)
      class(bird_data),        intent(inout)          :: bird
      character(len=50),       intent(in)             :: species
      integer, dimension(:),   intent(in)             :: dat

      bird%species=species
      allocate(bird%obs(size(dat)))
      bird%obs=dat
end subroutine

subroutine stats(bird,mean,std)
      class(bird_data),        intent(inout)          :: bird
      real,                    intent(out)            :: mean,std
      real                                            :: mu2
      
      mean=sum(bird%obs)/float(size(bird%obs))
      mu2=(sum(bird%obs)/float(size(bird%obs)))**2
      std=sqrt(sum(bird%obs**2-(mu2))/float(size(bird%obs)))
end subroutine

subroutine minmax(bird,years,min_val,max_val,min_year,max_year)
      class(bird_data),      intent(inout) :: bird
      integer, dimension(:), intent(in)    :: years
      real,                  intent(out)   :: min_val,max_val
      integer,               intent(out)   :: min_year, max_year
      
      min_val=minval(bird%obs)
      max_val=maxval(bird%obs)
      min_year=years(minloc(bird%obs,1))
      max_year=years(maxloc(bird%obs,1))

end subroutine

end module

program bird_obs
use bird_dat
use sorters
implicit none
!******************************************************************
!Mean observations, standard deviation, max and min of a set of 
!bird observations 
!Author:    Katherine Holcomb
!Changelog: Initial version 2015-03-4		
!******************************************************************

  class(bird_data),dimension (:), allocatable :: bird_list
  real,            dimension(:),  allocatable :: means,stds,oldmeans
  character(len=50)                           :: filename
  character(len=50)                           :: species,my_species,lc_species
  integer                                     :: n, nargs, nbirds
  logical                                     :: found_it
  real                                        :: std,mean,min_val,max_val
  integer                                     :: min_year, max_year
  integer, dimension(:),allocatable           :: years, pvec

  interface
     subroutine read_data(bird_list,filename,years)
        use bird_dat
        use file_utils
        implicit none
        class(bird_data), dimension(:),allocatable, intent(out) :: bird_list
        character(len=*),                           intent(in)  :: filename
        integer,         dimension(:),allocatable,  intent(out) :: years
     end subroutine
  end interface

  nargs=command_argument_count() 
  if ( nargs .ne. 2 ) then
     stop "Usage: <file> species"
  else
     call get_command_argument(1,filename)
     call get_command_argument(2,my_species)
  endif

  call read_data(bird_list,filename,years)
  nbirds=size(bird_list)

  found_it=.false.
  allocate(means(nbirds),stds(nbirds))
  do n=1,nbirds
     call bird_list(n)%stats(means(n),stds(n))
     if (my_species==bird_list(n)%species) then
        mean=means(n)
        std=stds(n)
        call bird_list(n)%minmax(years,min_val,max_val,min_year,max_year)
        found_it=.true.
     endif
  enddo

  if (found_it) then
     write(*,*) "Statistics for "//my_species
     write(*,'(a,f8.2)',advance='no') "The minimum value of observations is:",min_val
     write(*,'(a,i5)') " in year",min_year
     write(*,'(a,f8.2)',advance='no') "The maximum value of observations is:",max_val
     write(*,'(a,i5)') " in year",max_year
     write(*,'(a,f0.2)') "The mean value of the observations is:",mean
     write(*,'(a,f0.2)') "The standard deviation of the observations is:",std
  else
     write(*,*) "Requested species not found in the data file."
  endif

  allocate(pvec(nbirds))
  allocate(oldmeans(size(means)))
  oldmeans=means
  call pshellsort(means,pvec,nbirds)

  write(*,*)
  write(*,*) 'The 10 most common birds are'

  do n=nbirds,nbirds-9,-1
      write(*,'(a,f8.2)') bird_list(pvec(n))%species(1:len_trim(species)),oldmeans(pvec(n))
  enddo

End program 

subroutine read_data(bird_list,filename,years)
  use bird_dat
  use file_utils
  implicit none
  class(bird_data),dimension(:), allocatable, intent(out) :: bird_list
  character(len=*),                           intent(in)  :: filename
  integer,         dimension(:), allocatable, intent(out) :: years
  integer,         dimension(:), allocatable :: obs
  integer,         parameter                 :: nobs=47
  character(len=6),dimension(nobs)           :: cyears
  integer                                    :: inunit
  integer                                    :: nheaders,nbirds
  character(len=50)                          :: species
  character(len=1024)                        :: line
  character(len=:),dimension(:),allocatable  :: line_vals
  integer                                    :: num_vals
  integer                                    :: n

  inunit=open_file(filename,'r')

  if (inunit .ne. 0) then
      open(unit=inunit,file=filename)
  else
      stop "Unable to open specified data file."
  endif

  nheaders=3
  nbirds=count_records(inunit,nheaders)

  allocate(bird_list(nbirds))
  allocate(years(nobs))
  read(inunit,*) species,cyears(:)
  do n=1,nobs
     read(cyears(n),'(i4)') years(n)
  enddo

  allocate(obs(nobs))
     
  do n=1,nbirds
     read(inunit,*) species, obs
     call bird_list(n)%init(species,obs)
  end do

end subroutine read_data

Previous
Next