! Here are useful F programs for Astr137 v1.3 ! To use this module, compile it once (g95 -c a137.f95 ) and ! thereafter copy a137.o & a137.mod into the folder (if different) ! where you will be writing your programs. Insert USE a137 ! after the program statement in your application. Build as ! usual. ! ! Contents (not including private functions): ! IMage Draw an image in color or greyscale in GrWin ! IMhist Draw binned or cumulative histograms ! moment Data moments (mean, variance, etc) ! qsort sort real array into ascending sequence ! gaussdev Random numbers from Gaussian distribution ! poissondev Random number from Poisson distribution ! (Use Fortran 95 intrinsic function ! call random_number(array) for array of random #s ! uniform between 0 & 1 ) ! realft 1d Fourier Transform ! rlft2 2d Fourier Transform ! convlv convolution of two 1d functions ! spctrm power spectrum of 1d data stream ! wfits write FITS file (uses cfitsio) module A137 ! useful programs for Astr 137 integer, parameter, private :: dp = selected_real_kind(precision(0.0)+1) real(kind=dp), public, parameter :: PI = 3.14159265358979323846264338_dp integer, public, parameter :: erase_pen = 0, black_pen = 1, red_pen = 2, green_pen = 3, & blue_pen = 4, cyan_pen = 5, magenta_pen = 6, yellow_pen = 7 interface assert_eq module procedure assert_eq2, assert_eq3 end interface interface assert module procedure assert_1, assert_m end interface interface swap module procedure swap_r, swap_cmplx end interface interface arth module procedure arth_r, arth_i end interface public :: DSgraph, IMage, spectrm, convlv, four1, realft, four2, qsort, gaussdev, & poissondev, rlft2, moment, wfits private :: swap, assert_eq, assert_eq2, assert_eq3, & swapm, array_copy, gammln, fourrow, & swap_r, swap_cmplx, assert, arth, arth_r, arth_i, & assert_1, assert_m, zroots_unity, window contains recursive function zroots_unity(n,nn) result(zroots_unit) integer, intent(in) :: n,nn complex, dimension(nn) :: zroots_unit integer :: k real :: theta !============================================================= zroots_unit(1) = 1.0 theta = 2*PI/n k = 1 do if ( k >= nn ) exit zroots_unit(k+1) = cmplx(cos(k*theta),sin(k*theta)) zroots_unit(k+2:min(2*k,nn)) = zroots_unit(k+1)* & zroots_unit(2:min(k,nn-k)) k = 2*k end do end function zroots_unity subroutine array_copy(src,dest,n_copied,n_not_copied) real, dimension(:), intent(in) :: src real, dimension(:), intent(out) :: dest integer, intent(out) :: n_copied, n_not_copied !============================================================= n_copied = min(size(src),size(dest)) n_not_copied = size(src)-n_copied dest(1:n_copied) = src(1:n_copied) end subroutine array_copy function assert_eq2(n1,n2,string) result(assert) character(len=*), intent(in) :: string integer, intent(in) :: n1,n2 integer :: assert if ( n1 == n2 ) then assert = n1 else print*,"nerror: an assert_eq fialed with this tag:",string end if end function assert_eq2 function assert_eq3(n1,n2,n3,string) result(assert) character(len=*), intent(in) :: string integer, intent(in) :: n1,n2,n3 integer :: assert if ( n1 == n2 .and. n2 == n3 ) then assert = n1 else print*,"nerror: an assert_eq failed with this tag:",string end if end function assert_eq3 subroutine assert_m(n1,string) character(len=*), intent(in) :: string logical, intent(in), dimension(:) :: n1 if ( .not. all(n1) ) then print*,"nerror: an assertion failed with this tag:",string stop end if end subroutine assert_m subroutine assert_1(n1,string) character(len=*), intent(in) :: string logical, intent(in) :: n1 if ( .not. n1 ) then print*,"nerror: an assertion failed with this tag:",string stop end if end subroutine assert_1 function arth_r(first,increment,n) result(arthval) real(kind=dp), intent(in) :: first,increment integer, intent(in) :: n real(kind=dp), dimension(n) :: arthval integer :: k,k2 real(kind=dp) :: temp integer, parameter :: NPAR_ARTH=16, NPAR2_ARTH=8 !=============================================================== if ( n > 0 ) arthval(1) = first if ( n <= NPAR_ARTH ) then do k=2,n arthval(k) = arthval(k-1)+increment end do else do k=2,NPAR2_ARTH arthval(k) = arthval(k-1)+increment end do temp = increment*NPAR2_ARTH k = NPAR2_ARTH do if ( k >= n ) exit k2 = k+k arthval(k+1:min(k2,n)) = temp+arthval(1:min(k,n-k)) temp = temp+temp k = k2 end do end if end function arth_r function arth_i(first,increment,n) result(arthval) integer, intent(in) :: first,increment,n integer, dimension(n) :: arthval integer :: k,k2,temp integer, parameter :: NPAR_ARTH=16, NPAR2_ARTH=8 if ( n > 0 ) arthval(1) = first if ( n <= NPAR_ARTH ) then do k=2,n arthval(k) = arthval(k-1)+increment end do else do k=2,NPAR2_ARTH arthval(k) = arthval(k-1)+increment end do temp = increment*NPAR2_ARTH k = NPAR2_ARTH do if ( k >= n ) exit k2 = k+k arthval(k+1:min(k2,n)) = temp+arthval(1:min(k,n-k)) temp = temp+temp k = k2 end do end if end function arth_i subroutine realft(data,isign,zdata) real, dimension(:), intent(inout) :: data integer, intent(in) :: isign complex, dimension(:), intent(out), optional, target :: zdata integer :: n,ndum,nh,nq complex, dimension(size(data)/4) :: w complex, dimension(size(data)/4-1) :: h1,h2 complex, dimension(:), pointer :: cdata complex :: z real :: c1=0.5,c2 !============================================================== n = size(data) call assert(iand(n,n-1)==0,"n must be a power of 2 in realft") nh = n/2 nq = n/4 if ( present(zdata) ) then ndum = assert_eq(n/2,size(zdata),"realft") cdata=>zdata if ( isign == 1 ) cdata = cmplx(data(1:n-1:2),data(2:n:2)) else allocate(cdata(n/2)) cdata = cmplx(data(1:n-1:2),data(2:n:2)) end if if ( isign == 1 ) then c2 = -0.5 call four1(cdata,+1) else c2 = 0.5 end if w = zroots_unity(sign(n,isign),n/4) w = cmplx(-aimag(w),real(w)) h1 = c1*(cdata(2:nq)+conjg(cdata(nh:nq+2:-1))) h2 = c2*(cdata(2:nq)-conjg(cdata(nh:nq+2:-1))) cdata(2:nq) = h1+w(2:nq)*h2 cdata(nh:nq+2:-1) = conjg(h1-w(2:nq)*h2) z = cdata(1) if ( isign == 1 ) then cdata(1) = cmplx(real(z)+aimag(z),real(z)-aimag(z)) else cdata(1) = cmplx(c1*(real(z)+aimag(z)),c1*(real(z)-aimag(z))) call four1(cdata,-1) end if if ( present(zdata) ) then if ( isign /= 1 ) then data(1:n-1:2) = real(cdata) data(2:n:2) = aimag(cdata) end if else data(1:n-1:2) = real(cdata) data(2:n:2) = aimag(cdata) deallocate(cdata) end if end subroutine realft subroutine moment(data,ave,adev,sdev,var,skew,curt) real, intent(out) :: ave,adev,sdev,var,skew,curt real, dimension(:), intent(in) :: data integer :: n real :: ep real, dimension(size(data)) :: p,s !============================================================= n = size(data) ave = sum(data)/n s = data - ave ep = sum(s) adev = sum(abs(s))/n p = s**2 var = sum(p) p = p*s skew = sum(p) curt = sum(p*s) var = ( var-ep**2/n )/(n-1) sdev = sqrt(var) if ( var /= 0.0 ) then skew = skew/(n*sdev**3) curt = curt/(n*var**2)-3.0 else print*,"moment: no skew or kurtosis when 0 variance" stop end if end subroutine moment subroutine four1(data,isign) complex, dimension(:), intent(inout) :: data integer, intent(in) :: isign complex, dimension(:,:), allocatable :: dat,temp complex(kind=dp), dimension(:), allocatable :: w,wp real(kind=dp), dimension(:), allocatable :: theta integer :: n,m1,m2,j !============================================================ n = size(data) call assert(iand(n,n-1)==0,"n must be power of 2 in four1") m1 = 2**ceiling(0.5*log(real(n))/0.693147) m2 = n/m1 allocate(dat(m1,m2),theta(m1),w(m1),wp(m1),temp(m2,m1)) dat = reshape(data,shape(dat)) call fourrow(dat,isign) theta = arth(0,isign,m1)*2*PI/n wp = cmplx(-2.0_dp*sin(0.5_dp*theta)**2,sin(theta),kind=dp) w = cmplx(1.0_dp,0.0_dp,kind=dp) do j=2,m2 w = w*wp+w dat(:,j) = dat(:,j)*w end do temp = transpose(dat) call fourrow(temp,isign) data = reshape(temp,shape(data)) deallocate(dat,w,wp,theta,temp) end subroutine four1 subroutine rlft2(data,spec,speq,isign) real, dimension(:,:), intent(inout) :: data complex, dimension(:,:), intent(out) :: spec complex, dimension(:), intent(out) :: speq integer, intent(in) :: isign integer :: i1,j1,nn1,nn2 real(kind=dp) :: theta complex :: c1=(0.5,0.0),c2,h1,h2,w complex, dimension(size(data,2)-1) :: h1a,h2a complex(kind=dp) :: ww,wp !============================================================ nn1 = assert_eq(size(data,1),2*size(spec,1),"rlft2: nn1") nn2 = assert_eq(size(data,2),size(spec,2),size(speq),"rlft2: nn2") call assert(iand((/nn1,nn2/),(/nn1,nn2/)-1)==0, & "dimensions must be powers of 2 in rlft2") c2 = cmplx(0.0,-0.5*isign) theta = 2*PI/(isign*nn1) wp = cmplx(-2.0_dp*sin(0.5_dp*theta)**2,sin(theta)) if ( isign == 1 ) then spec(:,:) = cmplx(data(1:nn1:2,:),data(2:nn1:2,:)) call four2(spec,isign) speq = spec(1,:) end if h1 = c1*(spec(1,1)+conjg(speq(1))) h1a = c1*(spec(1,2:nn2)+conjg(speq(nn2:2:-1))) h2 = c2*(spec(1,1)-conjg(speq(1))) h2a = c2*(spec(1,2:nn2)-conjg(speq(nn2:2:-1))) spec(1,1) = h1+h2 spec(1,2:nn2) = h1a+h2a speq(1) = conjg(h1-h2) speq(nn2:2:-1) = conjg(h1a-h2a) ww = cmplx(1.0_dp,0.0_dp,kind=dp) do i1=2,nn1/4+1 j1 = nn1/2-i1+2 ww = ww*wp+ww w = ww h1 = c1*(spec(i1,1)+conjg(spec(j1,1))) h1a = c1*(spec(i1,2:nn2)+conjg(spec(j1,nn2:2:-1))) h2 = c2*(spec(i1,1)-conjg(spec(j1,1))) h2a = c2*(spec(i1,2:nn2)-conjg(spec(j1,nn2:2:-1))) spec(i1,1) = h1+w*h2 spec(i1,2:nn2) = h1a+w*h2a spec(j1,1) = conjg(h1-w*h2) spec(j1,nn2:2:-1) = conjg(h1a-w*h2a) end do if ( isign == -1 ) then call four2(spec,isign) data(1:nn1:2,:) = real(spec)/(nn1*nn2) data(2:nn1:2,:) = aimag(spec)/(nn1*nn2) end if end subroutine rlft2 subroutine four2(data,isign) complex, dimension(:,:), intent(inout) :: data integer, intent(in) :: isign complex, dimension(size(data,2),size(data,1)) :: temp !========================================================== call fourrow(data,isign) temp = transpose(data) call fourrow(temp,isign) data = transpose(temp) end subroutine four2 subroutine convlv(data,respns,isign,conv) real, dimension(:), intent(inout) :: data real, dimension(:), intent(in) :: respns integer, intent(in) :: isign real, dimension(:), intent(out) :: conv integer :: no2,n,m complex, dimension(size(data)/2) :: tmpd,tmpr !=========================================================== n = size(data) m = size(respns) call assert(iand(n,n-1)==0,"n must be a power of 2 in convlv") call assert(modulo(m,2)== 1,"m must be odd in convlv") conv(1:m) = respns(:) conv(n-(m-3)/2:n) = conv((m+3)/2:m) conv((m+3)/2:n-(m-1)/2) = 0.0 no2 = n/2 call realft(data,1,tmpd) call realft(conv,1,tmpr) if ( isign == 1 ) then tmpr(1) = cmplx(real(tmpd(1))*real(tmpr(1))/no2, & aimag(tmpd(1))*aimag(tmpr(1))/no2) tmpr(2:) = tmpd(2:)*tmpr(2:)/no2 else if ( isign == -1 ) then if ( any(abs(tmpr(2:)) == 0.0 ) .or. real(tmpr(1)) == 0.0 & .or. aimag(tmpr(1)) == 0.0 ) print*,"deconvoling at response 0 in convlv" tmpr(1) = cmplx(real(tmpd(1))/real(tmpr(1))/no2, & aimag(tmpr(1))/aimag(tmpr(1))/no2) tmpr(2:) = tmpd(2:)/tmpr(2:)/no2 else print*,"no meaning for isign in convlv" end if call realft(conv,-1,tmpr) end subroutine convlv subroutine spectrm(p,k,ovrlap,unit,n_window) real, dimension(:), intent(inout) :: p integer, intent(in) :: k logical, intent(in) :: ovrlap integer, optional, intent(in) :: n_window,unit integer :: j,joff,joffn,kk,m,m4,m43,m44,mm,iunit,nn_window real :: den,facm,facp,sumw real, dimension(2*size(p)) :: w real, dimension(4*size(p)) :: w1 real, dimension(size(p)) :: w2 complex, dimension(2*size(p)) :: cw1 !======================================================================================== m = size(p) if ( present(n_window) ) then nn_window = n_window else nn_window = 1 end if if ( present(unit) ) then iunit = unit else iunit = 9 end if mm = m+m m4 = mm+mm m44 = m4+4 m43 = m4+3 den = 0.0 facm = m facp = 1.0/m w1(1:mm) = window(arth(1,1,mm),facm,facp,nn_window) sumw = dot_product(w1(1:mm),w1(1:mm)) p = 0.0 if ( ovrlap ) read(unit=iunit,fmt=*) (w2(j),j=1,m) do kk=1,k do joff=-1,0,1 if ( ovrlap ) then w1(joff+2:joff+mm:2) = w2(1:m) read(unit=iunit,fmt=*) (w2(j),j=1,m) joffn = joff+mm w1(joff+2:joffn+mm:2) = w2(1:m) else read(unit=iunit,fmt=*) (w1(j),j=joff+2,m4,2) end if end do w = window(arth(1,1,mm),facm,facp,nn_window) w1(2:m4:2) = w1(2:m4:2)*w w1(1:m4:2) = w1(1:m4:2)*w cw1(1:mm) = cmplx(w1(1:m4:2),w1(2:m4:2)) call four1(cw1(1:mm),1) w1(1:m4:2) = real(cw1(1:mm)) w1(2:m4:2) = aimag(cw1(1:mm)) p(1) = p(1)+w(1)**2+w1(2)**2 p(2:m) = p(2:m)+w1(4:2*m:2)**2+w1(3:2*m-1:2)**2 + & w1(m44-4:m44-2*m:-2)**2+w1(m43-4:m43-2*m:-2)**2 den = den+sumw end do p = p/(m4*den) end subroutine spectrm function window(j,facm,facp,nn_window) result(wind) integer, dimension(:), intent(in) :: j integer, intent(in) :: nn_window real, intent(in) :: facm,facp real, dimension(size(j)) :: wind select case(nn_window) case(1) wind(j) = 1.0-abs((j-1)-facm)*facp case(2) wind(j) = 1.0 case(3) wind(j) = 1.0-(((j-1)-facm)*facp)**2 case default print*,"unimplemented window function in spctrm" end select end function window subroutine fourrow(data,isign) complex, dimension(:,:), intent(inout) :: data integer, intent(in) :: isign integer :: n,i,istep,j,m,mmax,n2 real(kind=dp) :: theta complex, dimension(size(data,1)) :: temp complex(kind=dp) :: w,wp complex :: ws !=========================================================== n = size(data,2) n2 = n/2 j = n2 do i=1,n-2 if ( j > i ) call swap(data(:,j+1),data(:,i+1)) m = n2 do if ( m < 2 .or. j < m ) exit j = j-m m = m/2 end do j = j+m end do mmax = 1 do if ( n <= mmax ) exit istep = 2*mmax theta = PI/(isign*mmax) wp = cmplx(-2.0_dp*sin(0.5_dp*theta)**2,sin(theta),kind=dp) w = cmplx(1.0_dp,0.0_dp,kind=dp) do m=1,mmax ws = w do i=m,n,istep j = i+mmax temp = ws*data(:,j) data(:,j) = data(:,i)-temp data(:,i) = data(:,i)+temp end do w = w*wp+w end do mmax = istep end do end subroutine fourrow subroutine gaussdev(harvest) ! return array of random numbers distributed in Gaussian ! of mean 0 and sigma 1 real, dimension(:), intent(out) :: harvest real, allocatable, dimension(:), save :: g real, dimension(size(harvest)) :: rsq,v1,v2 integer :: n,ng,nn,m integer, save :: last_allocated = 0 logical, save :: gaus_stored = .false. logical, dimension(size(harvest)) :: mask !============================================================== n = size(harvest) if ( n /= last_allocated ) then if ( last_allocated /= 0 ) deallocate(g) allocate(g(n)) last_allocated = n gaus_stored = .false. end if if ( gaus_stored ) then harvest = g gaus_stored = .false. else ng = 1 do if ( ng > n ) exit call random_number(v1(ng:n)) call random_number(v2(ng:n)) v1(ng:n) = 2.0*v1(ng:n)-1.0 v2(ng:n) = 2.0*v2(ng:n)-1.0 rsq(ng:n) = v1(ng:n)**2 + v2(ng:n)**2 mask(ng:n) = ( rsq(ng:n) > 0.0 .and. rsq(ng:n) < 1.0 ) call array_copy(pack(v1(ng:n),mask(ng:n)),v1(ng:),nn,m) v2(ng:ng+nn-1) = pack(v2(ng:n),mask(ng:n)) rsq(ng:ng+nn-1) = pack(rsq(ng:n),mask(ng:n)) ng = ng+nn end do rsq = sqrt(-2.0*log(rsq)/rsq) harvest = v1*rsq g = v2*rsq gaus_stored = .true. end if end subroutine gaussdev function gammln(xx) result(gamln) real, intent(in) :: xx real :: gamln real(kind=dp) :: tmp,x real(kind=dp), parameter :: stp = 2.5066282746310005_dp real(kind=dp), dimension(6), parameter :: coef = (/ 76.18009172947146_dp, & -86.50532032941677_dp, 24.01409824083091_dp, -1.231739572450155_dp, & 0.1208650973866179e-2_dp, -0.5395239384953e-5_dp /) !======================================================== x = xx tmp = x+5.5_dp tmp = (x+0.5_dp)*log(tmp)-tmp gamln = tmp+log(stp*(1.000000000190015_dp + & sum(coef(:)/arth(x+1.0_dp,1.0_dp,size(coef))))/x) end function gammln subroutine poissondev(xm,poidev) ! return one Poisson deviate. Note: F cannot do this in function ! because it assumes that functions are PURE, i.e. cannot SAVE anything real, intent(in) :: xm real, intent(out) :: poidev real :: em,harvest,t,y real, save :: alxm, g, sq, oldm=-1.0 !======================================================= if ( xm < 12.0 ) then if ( xm /= oldm ) then oldm = xm g = exp(-xm) end if em = -1 t = 1.0 do em = em+1.0 call random_number(harvest) t = t*harvest if ( t <= g ) exit end do else if ( xm /= oldm ) then oldm = xm sq = sqrt(2.0*xm) alxm = log(xm) g = xm*alxm-gammln(xm+1.0) end if do do call random_number(harvest) y = tan(PI*harvest) em = sq*y+xm if ( em >= 0.0 ) exit end do em = int(em) t = 0.9*(1.0+y**2)*exp(em*alxm-gammln(em+1.0)-g) call random_number(harvest) if ( harvest <= t ) exit end do end if poidev = em end subroutine poissondev subroutine swap_r(a,b) real, intent(inout) :: a,b real :: dum dum = a a = b b = dum end subroutine swap_r subroutine swap_cmplx(a,b) complex, dimension(:), intent(inout) :: a,b complex, dimension(size(a,1)) :: dum dum = a a = b b = dum end subroutine swap_cmplx subroutine swapm(a,b,mask) real, intent(inout) :: a,b logical, intent(in) :: mask real :: swp if ( mask ) then swp = a a = b b = swp end if end subroutine swapm subroutine qsort(arr) ! sort real array into ascending order, overwriting the input real, dimension(:), intent(inout) :: arr integer, parameter :: NN=15, NSTACK=50 real :: a integer :: n,k,i,j,jstack,l,r integer, dimension(NSTACK) :: istack n = size(arr) jstack = 0 l = 1 r = n do if ( r-l < NN ) then do j=l+1,r a = arr(j) do i=j-1,l,-1 if ( arr(i) <= a ) exit arr(i+1) = arr(i) end do arr(i+1) = a end do if ( jstack == 0 ) RETURN r = istack(jstack) l = istack(jstack-1) jstack = jstack-2 else k = (l+r)/2 call swap(arr(k),arr(l+1)) call swapm(arr(l),arr(r),arr(l)>arr(r)) call swapm(arr(l+1),arr(r),arr(l+1)>arr(r)) call swapm(arr(l),arr(l+1),arr(l)>arr(l+1)) i = l+1 j = r a = arr(l+1) do do i = i+1 if ( arr(i) >= a ) exit end do do j = j-1 if ( arr(j) <= a ) exit end do if ( j < i ) exit call swap(arr(i),arr(j)) end do arr(l+1) = arr(j) arr(j) = a jstack = jstack+2 if ( jstack > NSTACK ) then print*,"sort: NSTACK too small" stop end if if ( r-i+1 >= j-l ) then istack(jstack) = r istack(jstack-1) = i r = j-1 else istack(jstack) = j-1 istack(jstack-1) = l l = i end if end if end do end subroutine qsort subroutine IMage(type,im,cap) real, dimension(:,:), intent(in) :: im character(len=*), dimension(3), intent(in), optional :: cap character(len=*), intent(in) :: type !================================================================================= if ( present(cap) ) then if ( len_trim(cap(1)) /= 0 ) call name(cap(1),"x") if ( len_trim(cap(2)) /= 0 ) call name(cap(2),"y") if ( len_trim(cap(3)) /= 0 ) call titlin(cap(3),2) end if call setvlt(type) call qplclr(im,size(im,1),size(im,2)) end subroutine IMage subroutine DSgraph(device) character(len=*), intent(in) :: device !================================================================================= call setpag("USAL") if ( device == "xwin" .or. device(1:3) /= "eps" ) then call metafl(device) else if ( index(device,"P") == 0 ) then call metafl(device(1:3)) else call setpag("USAP") call metafl(device(1:3)) end if call scrmod("reverse") call disini() call axslen(1500,1500) end subroutine DSgraph ! subroutine IMshow(type,f,i1in,i2in,i3in,i4in,fmin,fmax,t) ! ! Display image on graphics device ! ! type is colortable: 1= greyscale, 2= rainbow, 3 = heat, etc ! ! (if -ve then add to existing page) ! ! f: array dimensioned containing values to plot ! ! 4 boundaries: optional ! ! i1: bottom left x, i2: bottom left y, i3: top right x, i4: top right y ! ! fmin: minimum intensity to plot, values below are ignored (optional) ! ! fmax: maximum intensity, values above are ignored (optional) ! ! t: rotation/shear coefficients (optional ! integer, intent(in) :: type ! real, dimension(:,:), intent(in) :: f ! real, dimension(6), intent(in), optional :: t ! real, intent(in), optional :: i1in,i2in,i3in,i4in,fmin,fmax ! real :: i1,i2,i3,i4,fmn,fmx ! real, parameter :: contra = 1.0, bright = 0.0 ! real, dimension(2) :: gl, gr, gg, gb ! real, dimension(9) :: rl, rr, rg, rb ! real, dimension(5) :: hl, hr, hg, hb ! real, dimension(10) :: wl, wr, wg, wb ! real, dimension(20) :: al, ar, ag, ab ! real, dimension(6) :: tr,ts = (/0, 1, 0, 0, 0, 1/) ! real :: d, vpx1, vpx2, vpy1, vpy2 ! integer :: lut,mxi,mxj ! !======================================================== ! mxi = size(f,1) ! mxj = size(f,2) ! if ( present(t) ) then ! tr = t ! else ! tr = ts ! end if ! if ( present(i1in) ) then ! i1 = i1in ! else ! i1 = 1.0 ! end if ! if ( present(i2in) ) then ! i2 = i2in ! else ! i2 = size(f,1) ! end if ! if ( present(i3in) ) then ! i3 = i3in ! else ! i3 = 1.0 ! end if ! if ( present(i4in) ) then ! i4 = i4in ! else ! i4 = size(f,2) ! end if ! if ( present(fmin) ) then ! fmn = fmin ! else ! fmn = minval(f) ! end if ! if ( present(fmax) ) then ! fmx = fmax ! else ! fmx = maxval(f) ! end if ! if ( type > 0 ) then ! call pgpage() ! call pgsvp(0.0, 1.0, 0.0, 1.0) ! lut = type ! else ! lut = -type ! end if ! call pgqvp(1, vpx1, vpx2, vpy1, vpy2) ! d = min(vpx2-vpx1, vpy2-vpy1)/40.0 ! vpx1 = vpx1 + 5.0*d ! vpx2 = vpx2 - 2.0*d ! vpy1 = vpy1 + 8.0*d -1.2 ! vpy2 = vpy2 - 2.0*d ! call pgvsiz(vpx1, vpx2, vpy1, vpy2) ! gl = (/0.0, 1.0/) ! gr = gl ! gg = gl ! gb = gl ! rl = (/-0.5, 0.0, 0.17, 0.33, 0.50, 0.67, 0.83, 1.0, 1.7/) ! rr = (/ 0.0, 0.0, 0.0, 0.0, 0.6, 1.0, 1.0, 1.0, 1.0/) ! rg = (/ 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.6, 0.0, 1.0/) ! rb = (/ 0.0, 0.3, 0.8, 1.0, 0.3, 0.0, 0.0, 0.0, 1.0/) ! hl = (/0.0, 0.2, 0.4, 0.6, 1.0/) ! hr = (/0.0, 0.5, 1.0, 1.0, 1.0/) ! hg = (/0.0, 0.0, 0.5, 1.0, 1.0/) ! hb = (/0.0, 0.0, 0.0, 0.3, 1.0/) ! wl = (/0.0, 0.5, 0.5, 0.7, 0.7, 0.85, 0.85, 0.95, 0.95, 1.0/) ! wr = (/0.0, 1.0, 0.0, 0.0, 0.3, 0.8, 0.3, 1.0, 1.0, 1.0/) ! wg = (/0.0, 0.5, 0.4, 1.0, 0.0, 0.0, 0.2, 0.7, 1.0, 1.0/) ! wb = (/0.0, 0.0, 0.0, 0.0, 0.4, 1.0, 0.0, 0.0, 0.95, 1.0/) ! al = (/0.0, 0.1, 0.1, 0.2, 0.2, 0.3, 0.3, 0.4, 0.4, 0.5, & ! 0.5, 0.6, 0.6, 0.7, 0.7, 0.8, 0.8, 0.9, 0.9, 1.0/) ! ar = (/0.0, 0.0, 0.3, 0.3, 0.5, 0.5, 0.0, 0.0, 0.0, 0.0, & ! 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0/) ! ag = (/0.0, 0.0, 0.3, 0.3, 0.0, 0.0, 0.0, 0.0, 0.8, 0.8, & ! 0.6, 0.6, 1.0, 1.0, 1.0, 1.0, 0.8, 0.8, 0.0, 0.0/) ! ab = (/0.0, 0.0, 0.3, 0.3, 0.7, 0.7, 0.7, 0.7, 0.9, 0.9, & ! 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0/) ! select case (lut) ! case (1) ! -- gray scale ! call pgctab(gl, gr, gg, gb, 2, contra, bright) ! case (2) ! -- rainbow ! call pgctab(rl, rr, rg, rb, 9, contra, bright) ! case (3) ! -- heat ! call pgctab(hl, hr, hg, hb, 5, contra, bright) ! case (4) ! -- iraf ! call pgctab(wl, wr, wg, wb, 10, contra, bright) ! case (5) ! -- aips ! call pgctab(al, ar, ag, ab, 20, contra, bright) ! end select ! call pgwnad(i1,i2,i3,i4) ! call pgimag(f,mxi,mxj,1,mxi,1,mxj,fmn,fmx,tr) ! if ( type < 0 ) then ! call pgwedg("ti", 2.5, 5.0, fmn, fmx, "pixel value") ! call pgbox("bctsi",0.0,0,"bctsi",0.0,0) ! else ! call pgwedg("ri", 2.5, 5.0, fmn, fmx, "pixel value") ! call pgbox("bcntsi",0.0,0,"bcntsiv",0.0,0) ! end if ! ! end subroutine IMshow ! subroutine IMhist(f,dmin,dmax,bins) ! optional last 3 args ! ! Draw binned or cumulative histogram on graphics device ! ! f: 2d array, each row to histogram. If array is 1d (or 3d), then use ! ! call Imhist(reshape(f, /( nx*ny*nz,1 )/), ...) ! ! successive distributions in f are drawn in different colors ! ! dmin,dmax: only data between these limits are histogramed. If not ! ! provided then use entire data range ! ! bins: if this 2d real array is provided then its length gives # bins to ! ! fill, plot, & return. Max of 400 bins. If not provided then plot a ! ! cumulative histogram (i.e. no binning) ! real, dimension(:,:), intent(in) :: f ! real, optional, intent(in) :: dmin,dmax ! real :: dmn,dmx ! real, dimension(:,:), optional, intent(inout) :: bins ! real, dimension(:), allocatable :: f1,y ! integer :: n,i,j,lo,hi,nb,nl,l ! ! call pgsci(l) = 2,... : rR, G, B, cyan, magenta, yellow ! real :: s ! !========================================================= ! if ( present(dmin) ) then ! dmn = dmin ! else ! dmn = minval(f) ! end if ! if ( present(dmax) ) then ! dmx = dmax ! else ! dmx = maxval(f) ! end if ! n = size(f,1) ! nl = size(f,2) ! if ( present(bins) ) then ! regular binned histogram ! nb = size(bins,1) ! allocate(y(1:nb)) ! do l=1,nl ! bins(:,l) = 0.0 ! do i=1,n ! j = nb*(f(i,l)-dmn)/(dmx-dmn) ! if ( j >= 1 .and. j <= min(nb,400) ) bins(j,l) = bins(j,l)+1 ! end do ! if ( l == 1 ) then ! call pgsci(1) ! call pgenv(dmn,dmx,0.0,maxval(bins(1:nb,l),l),0,0) ! call pgslw(3) ! s = (dmx-dmn)/nb ! y(1:nb) = (/ (dmn+s*(i-1),i=1,nb) /) ! else ! call pgsci(l) ! end if ! call pgbin(nb,y(1:l),bins(:,l),.false.) ! end do ! deallocate(y) ! call pgslw(1) ! else ! cumulative histogram ! do l=1,nl ! allocate(f1(1:n)) ! f1 = f(1:n,l) ! call qsort(f1) ! if ( l == 1 ) then ! do lo=1,n ! if ( f1(lo) >= dmn ) exit ! end do ! do hi=n,i,-1 ! if ( f1(hi) <= dmx ) exit ! end do ! call pgsci(1) ! call pgenv(dmn,dmx,0.0,1.01,0,0) ! else ! call pgsci(l) ! end if ! call pgbin(hi-lo+1,f1(lo:hi),(/ (real(i)/n,i=lo,hi) /),.false.) ! deallocate(f1) ! end do ! end if ! call pgsci(1) ! end subroutine IMhist subroutine wfits(filename,a) character(len=*), intent(in) :: filename real, dimension(:,:), intent(in) :: a logical :: simple,existingfile integer :: status,unit,blocksize,bitpix,fpixel,nx,ny,naxis,readwrite = 1 integer, dimension(3) :: axes !============================================================================= status = 0 call ftgiou(unit,status) call ftinit(unit,filename,blocksize,status) existingfile = ( status == 105 ) if ( existingfile ) then status = 0 call ftfiou(unit,status) call ftgiou(unit,status) call ftopen(unit,filename,readwrite,blocksize,status) end if nx = size(a,1) ny = size(a,2) simple = .true. bitpix = -32 axes(3) = 0 if ( ny > 0 ) then naxis = 2 axes(2) = ny else naxis = 1 axes(2) = 0 end if axes(1) = nx if ( .not.existingfile ) call ftphpr(unit,simple,bitpix,naxis,axes,0,1,.false.,status) fpixel = 1 call ftppre(unit,1,fpixel,nx*max(1,ny),a,status) call ftclos(unit,status) call ftfiou(unit,status) end subroutine wfits end module a137