00001
00002 c
00003 c Copyright (c) 1986,1987,1988,1989,1990,1991,1992,1993,
00004 c by Steve McMillan, Drexel University, Philadelphia, PA.
00005 c
00006 c All rights reserved.
00007 c
00008 c Redistribution and use in source and binary forms are permitted
00009 c provided that the above copyright notice and this paragraph are
00010 c duplicated in all such forms and that any documentation,
00011 c advertising materials, and other materials related to such
00012 c distribution and use acknowledge that the software was developed
00013 c by the author named above.
00014 c
00015 c THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
00016 c IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
00017 c WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00018 c
00019
00020 c------------------------------------------------------------------------
00021 c
00022 c Histogram-plotting routines: histogram
00023 c histo (used by histogram)
00024 c
00025 c------------------------------------------------------------------------
00026
00027 subroutine histogram(input,istart,nin,x,y,z,nx,ny,nz,
00028 & iherr,ihmode,ihsave,iprompt,*)
00029 save
00030 c
00031 c Draw a histogram from z or y(x).
00032 c
00033 character*(*) input
00034 dimension x(*),y(*),z(*)
00035 c
00036 common/scales/xl,xr,dinchx,ybot,ytop,dinchy,rlen,slen
00037 c
00038 common/draw params/roff,soff,aspect1,xlen,ylen,hs,hn,hp,
00039 & idevset,jbox,iorig
00040 c
00041 common/frame params 1/xmin,xmax,ymin,ymax,modex,modey
00042 character*80 xttl,yttl
00043 common/frame params 2/xttl,yttl
00044 c
00045 parameter (NHISTOMAX=200)
00046 dimension xh(0:NHISTOMAX),yh(0:NHISTOMAX),xp(19)
00047 logical normal
00048 c
00049 common/weights/wt(NHISTOMAX),nw
00050 c
00051 if (input(3:3).eq.'x') then
00052 c
00053 if (nx.le.1) go to 1001
00054 c
00055 c Already have the data in x, y, and the box is drawn.
00056 c
00057 dx2 = .5*(x(2) - x(1))
00058 yh(0) = 0.
00059 xh(0) = max(xl,min(xr,x(1)-1.5*dx2))
00060 do 10180 i=1,nx
00061 xh(i) = max(xl,min(xr,x(i)-dx2))
00062 yh(i) = y(i)
00063 10180 continue
00064 c
00065 if (.not.normal) then
00066 ier = 1
00067 else
00068 ier = nz
00069 end if
00070 c
00071 call histo(xh,yh,nx+1,ihmode,ier*iherr)
00072 return
00073 c
00074 end if
00075 c
00076 if (nz.le.1) go to 1001
00077 c
00078 c Must make the histogram from scratch.
00079 c
00080 call minmax(z,nz,z1,z2)
00081 xmin0 = z1
00082 xmax0 = z2
00083 c
00084 c Determine binning to use:
00085 c
00086 if (input(3:3).ne.'2') then
00087 if (input(3:3).eq.'n'.or.input(4:4).eq.'n') then
00088 normal = .true.
00089 else
00090 normal = .false.
00091 end if
00092 c
00093 ref = -1.e35
00094 io = 1
00095 call readrq(input(istart:nin),2,
00096 & del,ref,dum,dum,*100)
00097 io = 0
00098 c
00099 100 if (io.ne.0.or.ref.lt.-9.e34) then
00100 read(input(istart:nin),*,err=1001,end=1001)del
00101 ref = z1
00102 end if
00103 if (del.le.0.) go to 1001
00104 c
00105 xmin = z1
00106 xmax = z2
00107 c
00108 if (modex.lt.0) then
00109 if (z1.le.0..or.ref.le.0.) go to 1001
00110 z1 = log10(z1)
00111 z2 = log10(z2)
00112 ref = log10(ref)
00113 end if
00114 c
00115 iref = 0.9999*(ref-z1)/del
00116 nh = 0
00117 xh(0) = ref - (iref+1)*del
00118 iref = iref + 2
00119 c
00120 c Notes: xh(i) is the TOP of bin #i.
00121 c ref will be at the BOTTOM of bin #iref
00122 c
00123 180 nh = nh+1
00124 if (nh.gt.NHISTOMAX) then
00125 if (iprompt.eq.1) write(6,'(''Too many bins.'')')
00126 go to 1001
00127 end if
00128 xh(nh) = xh(nh-1) + del
00129 if (xh(nh).le.z2) go to 180
00130 else
00131 if (del.le.0..or.nh.le.0..or.nh.gt.nhmax) go to 1001
00132 end if
00133 c
00134 c Bin the data.
00135 c
00136 do 182 j=0,nh
00137 yh(j) = 0.
00138 182 continue
00139 zbar=0.
00140 var=0.
00141 do 184 i=1,nz
00142 zz = z(i)
00143 if (modex.lt.0) zz = log10(zz)
00144 zbar = zbar + z(i)
00145 var = var + z(i)**2
00146 j = iref + (zz-ref)/del
00147 j = max(1,min(nh,j))
00148 yh(j) = yh(j) + 1.
00149 184 continue
00150 c
00151 if (normal) then
00152 do 185 j = 0,nh
00153 yh(j) = yh(j)/nz
00154 185 continue
00155 end if
00156 c
00157 c Get statistics (percentiles from the binned data)...
00158 c
00159 zbar = zbar/nz
00160 var = var/nz - zbar**2
00161 c
00162 ix=0
00163 sum=0.
00164 do 190 ip=1,19
00165 sp = .05*ip*nz
00166 if (normal) sp = sp/nz
00167 188 ix = ix + 1
00168 if (ix.gt.nh) go to 191
00169 sum = sum + yh(ix)
00170 if (sum.lt.sp) go to 188
00171 xp(ip) = xh(ix) - del*(sum-sp)/yh(ix)
00172 sum = sum - yh(ix)
00173 ix = ix - 1
00174 190 continue
00175 c
00176 c ...and (clip and) draw the histogram.
00177 c
00178 191 call minmax(yh(1),nh,y1,y2)
00179 c
00180 if (modey.gt.0) then
00181 ymin = 0.
00182 else
00183 if (.not.normal) then
00184 ymin = 1.
00185 else
00186 ymin = 1./nz
00187 end if
00188 ymin1 = log10(ymin) - 10.
00189 do 192 j = 0,nh
00190 if (yh(j).lt.ymin) then
00191 yh(j) = ymin1
00192 else
00193 yh(j) = log10(max(ymin,yh(j)))
00194 end if
00195 192 continue
00196 end if
00197 c
00198 if (input(3:3).ne.'1'.and.input(3:3).ne.'2') then
00199 c
00200 ymax = min(10.+y2,1.1*y2)
00201 c
00202 delz = xp(19) - xp(1)
00203 c
00204 if (xp(1)-z1.gt.delz) then
00205 c
00206 c Bottom 5% too spread out:
00207 c
00208 xmin = xp(19) - sqrt(delz*(xp(19)-z1))
00209 ix = abs(xmin - ref)/del
00210 if (xmin.lt.ref) then
00211 xmin = ref - (ix+1)*del
00212 else
00213 xmin = ref + ix * del
00214 end if
00215 if (modex.lt.0) xmin = 10.**z1
00216 end if
00217 c
00218 if (z2-xp(19).gt.delz) then
00219 c
00220 c Top 5% too spread out:
00221 c
00222 xmax = xp(1) + sqrt(delz*(z2-xp(1)))
00223 ix = abs(xmax - ref)/del
00224 if (xmax.lt.ref) then
00225 xmax = ref - ix*del
00226 else
00227 xmax = ref + (ix+1) * del
00228 end if
00229 if (modex.lt.0) xmax = 10.**z2
00230 end if
00231 c
00232 c Expand the range slightly (linear case only):
00233 c
00234 if (modex.gt.0) then
00235 xav = .5*(xmin+xmax)
00236 xmin = xmin - .1*(xav-xmin)
00237 xmax = xmax + .1*(xav-xmin)
00238 end if
00239 c
00240 if (idevset.eq.0) call setup(' ','histogram')
00241 call devon
00242 call clear
00243 c
00244 if (.not.normal) then
00245 yttl = '@H'
00246 else
00247 yttl = ' fraction'
00248 end if
00249 c
00250 call eframe(xmin,xmax,xlen,modex,xttl,
00251 & ymin,ymax,ylen,modey,yttl)
00252 ibox=1
00253 c
00254 c More clipping...
00255 c
00256 do 193 j=0,nh
00257 if (xh(j).lt.xl) xh(j)=xl
00258 if (xh(j).gt.xr) xh(j)=xr
00259 193 continue
00260 end if
00261 c
00262 if (.not.normal) then
00263 ier = 1
00264 else
00265 ier = nz
00266 end if
00267 c
00268 call histo(xh,yh,nh+1,ihmode,ier*iherr)
00269 call devoff
00270 c
00271 if (ihsave.ne.0) then
00272 c
00273 c Save the histogram data (top center of each bar) in y(x).
00274 c
00275 do 200 j=2,nh
00276 x(j-1) = .5*(xh(j-1)+xh(j))
00277 y(j-1) = yh(j)
00278 if (ihsave.eq.2.and.nw.gt.0) z(j-1) = wt(j)
00279 200 continue
00280 nx = nh-1
00281 ny = nx
00282 end if
00283 if (ihsave.eq.2.and.nw.gt.0) nz = nx
00284 c
00285 if (iprompt.eq.1) then
00286 if (modex.lt.0) then
00287 do 194 ip=1,19
00288 xp(ip) = 10.**xp(ip)
00289 194 continue
00290 end if
00291 write(6,195)nz,xmin0,xmax0,zbar,
00292 & sqrt(var),(xp(ip),ip=2,18,2)
00293 195 format(i6,' points: ',
00294 & ' xmin = ',1pe10.3,', xmax = ',e10.3/
00295 & 15x,' mean = ',e10.3,', s.d. = ',e10.3/
00296 & ' %tiles:',5e12.3/8x,4e12.3)
00297 end if
00298 c
00299 return
00300 1001 return 1
00301 c
00302 end
00303
00304
00305 subroutine histo(x,y,n,ihmode,iherr)
00306 save
00307 c
00308 c Draw y(x) as a histogram or as data points with error bars.
00309 c
00310 dimension x(*),y(*)
00311 c
00312 common/frame params 1/xmin,xmax,ymin,ymax,modex,modey
00313 common/scales/xl,xr,dinchx,ybot,ytop,dinchy,rlen,slen
00314 common/draw params/roff,soff,aspect1,xlen,ylen,hs,hn,hp,
00315 & idevset,jbox,iorig
00316 c
00317 parameter (NHISTOMAX=200)
00318 common/weights/wt(NHISTOMAX),nw
00319 c
00320 nw = 0
00321 c
00322 if (iherr.le.0) then
00323 r = (x(1)-xl)*dinchx
00324 so = 0.
00325 do 100 i=2,n
00326 s = max(y(i)-ybot,0.)*dinchy
00327 if (ihmode.eq.0) then
00328 call plot(r,0.,3)
00329 else
00330 call plot(r,min(s,so),3)
00331 end if
00332 call plot(r,max(s,so),2)
00333 call plot(r,s,3)
00334 r = (x(i)-xl)*dinchx
00335 call plot(r,s,2)
00336 so = s
00337 if (r.ge.rlen) go to 101
00338 100 continue
00339 101 if (r.lt.rlen) call plot(r,0.,2)
00340 else
00341 dx = .5*(x(3)-x(2))
00342 if (hp.le.0.) then
00343 nn = 4
00344 hh = .025
00345 else
00346 nn = 10
00347 hh = .5*hp
00348 end if
00349 c
00350 do 250 i = 2,n
00351 if (x(i).ge.xr.or.y(i).lt.ybot) go to 250
00352 r = (x(i)-dx-xl)*dinchx
00353 s = (y(i)-ybot)*dinchy
00354 call ngon(r,s,hh,nn,0.)
00355 c
00356 c Find the actual number of points in the bin, zbin.
00357 c
00358 zbin = y(i)
00359 if (modey.lt.0) zbin = 10.**zbin
00360 zbin = zbin*iherr
00361 c
00362 c Determine the standard error.
00363 c
00364 nw = nw + 1
00365 wt(i-1) = sqrt(zbin)
00366 c
00367 c (Note that wt(1) corresponds to x(2)!)
00368 c
00369 zfac = 1./wt(i-1)
00370 if (zbin.le.1.) zfac = .999
00371 c
00372 if (modey.gt.0) then
00373 su = (y(i)*(1.+zfac) - ybot)*dinchy
00374 208 sl = (y(i)*(1.-zfac) - ybot)*dinchy
00375 else
00376 su = (y(i) + log10(1.+zfac) - ybot)*dinchy
00377 sl = (y(i) + log10(1.-zfac) - ybot)*dinchy
00378 end if
00379 c
00380 c Plot the error bars.
00381 c
00382 call plotin(r-hh,sl,3)
00383 call plotin(r+hh,sl,2)
00384 call plotin(r,sl,3)
00385 call plotin(r,su,2)
00386 call plotin(r-hh,su,3)
00387 call plotin(r+hh,su,2)
00388 c
00389 250 continue
00390 c
00391 end if
00392 c
00393 end