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 subroutine smooth(t,x,xsmooth,n,dts,iopt,iw) 00021 save 00022 c 00023 c Smooth the input data, using one of a variety of methods. 00024 c 00025 c Options: 00026 c 00027 c iopt = 0: median 00028 c 1: arithmetic mean 00029 c 2: harmonic mean 00030 c 3: geometric mean 00031 c 11: clipped arithmetic mean 00032 c 12: clipped harmonic mean 00033 c 13: clipped geometric mean 00034 c 00035 c iwindow = 0: flat window 00036 c 1: triangular window 00037 c 00038 parameter (NMAX = 10000, FCLIP = 0.1) 00039 c 00040 dimension t(1),x(1),xsmooth(1),work(NMAX),tt(NMAX) 00041 c 00042 external comp 00043 c 00044 c Smooth the input data over a window of width dts. 00045 c Brute-force approach recalculates the sum at each data point! 00046 c 00047 c Window function: 00048 c 00049 window(xx) = max(0., 1. - iwindow*abs(xx/dt2)) 00050 c 00051 if (dts.le.0.) return 00052 iwindow = iw 00053 if (iwindow.ne.0) iwindow = 1 00054 dt2 = .5*dts 00055 c 00056 if (iopt.gt.0.and.iopt.le.10.and.iwindow.eq.0) then 00057 c 00058 c Flat window, straight average only: 00059 c 00060 sum = 0. 00061 ns = 0 00062 j0 = 1 00063 j1 = 0 00064 c 00065 do 190 i=1,n 00066 c 00067 120 continue 00068 c 00069 c if (j1.lt.n 00070 c & .and.t(j1+1).le.t(i)+min(dt2,t(i)-t(1))) then 00071 c 00072 if (j1.lt.n.and.t(j1+1).le.t(i)+dt2) then 00073 j1 = j1 + 1 00074 sum = sum + f(x(j1),iopt) 00075 ns = ns + 1 00076 go to 120 00077 end if 00078 c 00079 130 continue 00080 c if (t(j0).lt.t(i)-min(dt2,t(n)-t(i))) then 00081 if (t(j0).lt.t(i)-dt2) then 00082 sum = sum - f(x(j0),iopt) 00083 ns = ns - 1 00084 j0 = j0 + 1 00085 go to 130 00086 end if 00087 c 00088 xsmooth(i) = finv(sum/max(ns,1),iopt) 00089 c 00090 190 continue 00091 else 00092 c 00093 c All other options: 00094 c 00095 j0 = 1 00096 j1 = 0 00097 c 00098 c Locate the range containing the desired interval. 00099 c 00100 do 290 i=1,n 00101 c 00102 220 if (j1.lt.n 00103 & .and.t(j1+1).le.t(i)+min(dt2,t(i)-t(1))) then 00104 j1 = j1 + 1 00105 go to 220 00106 end if 00107 c 00108 230 if (t(j0).lt.t(i)-min(dt2,t(n)-t(i))) then 00109 j0 = j0 + 1 00110 go to 230 00111 end if 00112 c 00113 c Range is j0 to j1. 00114 c 00115 do 240 j=j0,j1 00116 work(j-j0+1) = x(j) 00117 tt(j-j0+1) = t(j) 00118 240 continue 00119 nw = j1-j0+1 00120 c 00121 if (iopt.eq.0.or.iopt.gt.10) then 00122 c 00123 c Sort the data. 00124 c 00125 if (nw.gt.1) call sort2(nw,work,tt) 00126 c 00127 if (iopt.eq.0) then 00128 c 00129 c Interpolate to the median. 00130 c 00131 xj = .5*(nw+1) 00132 jj = xj 00133 xsmooth(i) = work(jj) 00134 & + (xj-jj)*(work(jj+1) - work(jj)) 00135 else 00136 c 00137 c Clip the data. 00138 c 00139 xj1 = FCLIP*(nw+1) 00140 jj1 = max(1,nint(xj1)) 00141 xj2 = (1.-FCLIP)*(nw+1) 00142 jj2 = min(nw,nint(xj2)) 00143 c 00144 c New range is jj1 to jj2. 00145 c 00146 do 250 j=jj1,jj2 00147 work(j-jj1+1) = work(j) 00148 tt(j-jj1+1) = tt(j) 00149 250 continue 00150 nw = jj2-jj1+1 00151 end if 00152 end if 00153 c 00154 if (iopt.gt.0) then 00155 c 00156 c Perform averaging on the work data. 00157 c 00158 sum = 0. 00159 wsum = 0. 00160 c 00161 do 260 j=1,nw 00162 weight = window(tt(j)-t(i)) 00163 wsum = wsum + weight 00164 sum = sum + weight*f(work(j),iopt) 00165 260 continue 00166 c 00167 if (wsum.gt.0.) then 00168 xsmooth(i) = finv(sum/wsum,iopt) 00169 else 00170 xsmooth(i) = x(i) 00171 end if 00172 else 00173 end if 00174 c 00175 290 continue 00176 end if 00177 c 00178 end 00179 00180 00181 00182 function f(x,iopt) 00183 save 00184 c 00185 if (iopt.eq.1.or.iopt.eq.11) then 00186 f = x 00187 else if (iopt.eq.2.or.iopt.eq.12) then 00188 if (x.ne.0.) then 00189 f = 1./x 00190 else 00191 f = 0. 00192 end if 00193 else if (iopt.eq.3.or.iopt.eq.13) then 00194 if (x.gt.1.e-20) then 00195 f = log(x) 00196 else 00197 f = -46.05 00198 end if 00199 end if 00200 c 00201 end 00202 00203 00204 00205 function finv(x,iopt) 00206 save 00207 c 00208 c Compute the inverse function to f above. 00209 c 00210 if (iopt.eq.1.or.iopt.eq.11) then 00211 finv = x 00212 else if (iopt.eq.2.or.iopt.eq.12) then 00213 if (x.ne.0.) then 00214 finv = 1./x 00215 else 00216 finv = 0. 00217 end if 00218 else if (iopt.eq.3.or.iopt.eq.13) then 00219 if (x.gt.-46.05) then 00220 finv = exp(x) 00221 else 00222 finv = 1.e-20 00223 end if 00224 end if 00225 c 00226 end 00227 00228 00229 00230 integer*2 function comp(x,y) 00231 save 00232 c 00233 c Comparison function for use with qsort. 00234 c 00235 if (x.gt.y) then 00236 comp = 1 00237 else if (x.lt.y) then 00238 comp = -1 00239 else 00240 comp = 0 00241 end if 00242 c 00243 end