C  @(#)avwndw.for	19.1 (ESO-DMD) 02/25/03 14:01:40 
C===========================================================================
C Copyright (C) 1995 European Southern Observatory (ESO)
C
C This program is free software; you can redistribute it and/or 
C modify it under the terms of the GNU General Public License as 
C published by the Free Software Foundation; either version 2 of 
C the License, or (at your option) any later version.
C
C This program is distributed in the hope that it will be useful,
C but WITHOUT ANY WARRANTY; without even the implied warranty of
C MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
C GNU General Public License for more details.
C
C You should have received a copy of the GNU General Public 
C License along with this program; if not, write to the Free 
C Software Foundation, Inc., 675 Massachusetts Ave, Cambridge, 
C MA 02139, USA.
C
C Correspondence concerning ESO-MIDAS should be addressed as follows:
C	Internet e-mail: midas@eso.org
C	Postal address: European Southern Observatory
C			Data Management Division 
C			Karl-Schwarzschild-Strasse 2
C			D 85748 Garching bei Muenchen 
C			GERMANY
C===========================================================================
C
      PROGRAM AVWNDW
C
C++++++++++++++++++++++++++++++++++++++++++++++++++
C
C.IDENTIFICATION
C  program AVWNDW			version 1.00	890123
C  K. Banse                  		ESO - Garching
C  1.20	      890529	1.30	900130
C
C.KEYWORDS
C  bulk data frames, average
C
C.PURPOSE
C  average a no. of image frames, take only values which don't differ too much
C  from the median value (at each pixel), the result will either be a frame with
C  size equal to common area of all frames involved or size equal to union of
C  all frame areas
C
C.ALGORITHM
C  extract input frames either from given parameter string or from catalogue,
C  add up all frames + divide in the end
C  max. 20 frames may be averaged at one time !
C
C.INPUT/OUTPUT
C  the following keys are used:
C
C  ACTION/C/1/3			= WIN, MED, MIN or MAX
C  OUT_A/C/1/60			result frame
C  P3/C/1/80			list of frames to be averaged
C  INPUTR/R/1/2			BGERR,SNOISE - Poisson + Gaussian errors
C				for WINDOW option
C
C  the following descriptors are used with WINDOW option:
C  LHCUTS/R/5/2			low, high cuts for calculations
C  FLAT_BKG/R/1/1		background value
C  O_TIME/D/7/1			exposure time
C	
C.VERSIONS
C 
C 010802		last modif
C	
C--------------------------------------------------
C
      IMPLICIT NONE
C
      INTEGER     BEGIN,FRMCNT,IAV,ISEQ
      INTEGER     L,LL,LP,M,IOFF
      INTEGER     N,NAXIS,NAXISC,NCHECK,NIN,NP,NPERC,NTL
      INTEGER*8   PNTRC,PNTRT
      INTEGER     SIZEC,STAT
      INTEGER     IMNOC,IMN(20)
      INTEGER     NPIX(3),NPIXC(3)
      INTEGER     OFX(20),OFY(20),POFF(20),NPNTS(20)
      INTEGER     IORD(20),NORD(20),REJ(20),TNP(4)
      INTEGER     EC,EL,ED
      INTEGER     UNI(1),NULO,MADRID(1)
      INTEGER     LEN,INDEX            !system functions
C
      CHARACTER   FRAME(20)*60,FRAMEC*60,CATFIL*60
      CHARACTER   CUNIT*64,IDENT*72,OUTPUT*80
      CHARACTER   NOCUTS*60,LINE*80,ACTION*3
      CHARACTER   ERROR1*60,ERROR2*50,ERROR3*40,ERROR4*40,ERROR6*40
      CHARACTER   ERROR7*40,ERROR9*60
C
      DOUBLE PRECISION STEP(2,20),STEPC(2)
      DOUBLE PRECISION START(2,20),STARTC(2),OSTART(2),OEND(2)
C
      REAL        EPS(3),CUTS(4)
      REAL        VAL(20),BGV(20),RMS(20),RFC(20)
      REAL        AJCUL(20),AJCUH(20),AJCU(2),SNOISE,BGERR
      REAL        INPUTR(2),EXPTI(20)
C
      DOUBLE PRECISION      EXPTIM
C
      INCLUDE 'MID_INCLUDE:ST_DEF.INC'
C
      COMMON   /VMR/     MADRID
      COMMON   /MYREAL/  VAL,BGV,RMS,RFC,AJCUL,AJCUH,SNOISE,BGERR,EXPTI
      COMMON   /MYINT/   IORD,NORD,REJ,TNP
C
      DATA    IDENT    /'average frame '/
      DATA    ERROR1   /'operands do not match in stepsize... '/
      DATA    ERROR2   /'operands do not overlap...'/
      DATA    ERROR3   /'stepsizes of different sign...'/
      DATA    ERROR4   /'catalogue empty...'/
      DATA    ERROR6   /'no. of input frames < 2 ...'/
      DATA    ERROR7   /'more than 20 entries in catalogue...'/
      DATA    ERROR9   /'no. of axes do not match... '/
      DATA    NOCUTS   /'LHCUTS(5,6) not there - use LHCUTS(3,4)... '/
      DATA    STARTC   /2*0.D0/,    STEPC  /2*1.D0/
C
      INCLUDE 'MID_INCLUDE:ST_DAT.INC'
C
C  set up MIDAS environment + enable automatic error abort
      CALL STSPRO('AVWNDW')
C 
C  init COMMON variables
      DO 50 N=1,20
         REJ(N) = 0
50    CONTINUE
      DO 60 N=1,4
         TNP(N) = 0
60    CONTINUE
C
C  get necessary keys
      CALL STKRDC('ACTION',1,1,3,IAV,ACTION,UNI,NULO,STAT)    !get option
      CALL STKRDC('OUT_A',1,1,60,IAV,FRAMEC,UNI,NULO,STAT)    !get result frame
      CALL STKRDC('P3',1,1,80,IAV,LINE,UNI,NULO,STAT)         !list of frames
      CALL UPCAS(ACTION,ACTION)
      IF (ACTION(1:1).EQ.'W') THEN                        !only for real window option
         CALL STKRDR('INPUTR',1,2,IAV,INPUTR,UNI,NULO,STAT)
         BGERR = INPUTR(1) * INPUTR(1)                   !take square of errors
         SNOISE = INPUTR(2) * INPUTR(2)
      ENDIF
C
C  test, if we have list of frames or catalogue
      LL = INDEX(LINE,'.cat')
      IF (LL.LE.0) THEN
         LL = INDEX(LINE,'.CAT')
         IF (LL.LE.0) GOTO 500                     !No. Treat list input
      ENDIF
C
C  here we handle input from a catalog
C  get name of first image file in catalog
C
      ISEQ = 0
      CATFIL(1:) = LINE(1:)
      CALL STCGET(CATFIL,0,FRAME(1),OUTPUT,ISEQ,STAT)
      IF (FRAME(1)(1:1).EQ.' ')                 !there must be at least 1 image
     +   CALL STETER(4,ERROR4)
C
C  now loop through catalogue
      DO 200 N=2,20                                !max. 20 frames
         CALL STCGET(CATFIL,0,FRAME(N),OUTPUT,ISEQ,STAT)
         IF (FRAME(N)(1:1).EQ.' ') THEN            !indicates the end ...
            FRMCNT = N - 1
            GOTO 1000
         ENDIF
200   CONTINUE
C
      CALL STCGET(CATFIL,0,LINE,OUTPUT,ISEQ,STAT)
      IF (LINE(1:1).NE.' ')
     +   CALL STTPUT
     +   ('Max. 20 frames are used, following frames ignored...',STAT)
      FRMCNT = 20
      GOTO 1000
C
C  here we handle input from single inout line
C  pull out operands      (max. 20)
C
500   BEGIN = 1
      DO 800 N=1,21                             !max. of 20 frames...!
         CALL EXTRSS(LINE,',',BEGIN,FRAME(N),LL)
         IF (LL.LE.0) THEN
            FRMCNT = N - 1
            GOTO 1000
         ELSE
            CALL CLNFRA(FRAME(N),FRAME(N),0)
         ENDIF
800   CONTINUE
C
C  check no. of input frames
1000  IF (FRMCNT.LT.2) CALL STETER(6,ERROR6)
C
      DO 1200 N=1,FRMCNT
         DO 1100 M=1,2                        !init values...
            START(M,N) = 0.D0
            STEP(M,N) = 1.D0
            NPIX(M) = 1
1100     CONTINUE
1200  CONTINUE
C
C  get initial area from 1. frame
      DO 1400 M=1,2                  !init values...
         OSTART(M) = 0.D0
         OEND(M) = 0.D0
         NPIX(M) = 1
1400  CONTINUE
C
      CALL STFOPN(FRAME(1),D_R4_FORMAT,0,F_IMA_TYPE,IMN(1),STAT)
      CALL STDRDI(IMN(1),'NAXIS',1,1,IAV,NAXISC,UNI,NULO,STAT)
      IF (NAXISC.GT.2) THEN                !we only work on max 2-dim. frames
         NAXISC = 2
         OUTPUT(1:) = 'currently only 1 or 2-dim frames supported... '
         CALL STTPUT(OUTPUT,STAT)
      ENDIF
C
      CALL STDRDI(IMN(1),'NPIX',1,2,IAV,NPIX,UNI,NULO,STAT)
      NPNTS(1) = NPIX(1)
      CALL STDRDD(IMN(1),'START',1,2,IAV,START(1,1),UNI,NULO,STAT)
      OSTART(1) = START(1,1)
      OSTART(2) = START(2,1)
      CALL STDRDD(IMN(1),'STEP',1,2,IAV,STEP(1,1),UNI,NULO,STAT)
      STEPC(1) = STEP(1,1)
      STEPC(2) = STEP(2,1)
      CALL STDRDC(IMN(1),'CUNIT',1,1,64,IAV,CUNIT,UNI,NULO,STAT)
C
C  for "real" window option get exposure-time, low + high cuts and background
      IF (ACTION(1:1).EQ.'W') THEN
         CALL STECNT('GET',EC,EL,ED)            !disable error abort
         CALL STECNT('PUT',1,0,0)
C
         CALL STDRDD(IMN(1),'O_TIME',7,1,IAV,EXPTIM,UNI,NULO,STAT)
         IF (STAT.NE.0) THEN
            EXPTI(1) = 1.0                      !default to 1 second
         ELSE
            EXPTI(1) = EXPTIM
         ENDIF
C
C  get LHCUTS(5,6) - if not there use LHCUTS(3,4)
         CALL STDRDR(IMN(1),'LHCUTS',5,2,IAV,AJCU,UNI,NULO,STAT)
         IF (STAT.NE.0) THEN
            CALL STTPUT(NOCUTS,STAT)
            CALL STDRDR(IMN(1),'LHCUTS',3,2,IAV,AJCU,UNI,NULO,STAT)
         ENDIF
         IF (AJCU(2).LE.AJCU(1))
     +      CALL STETER(43,'invalid LHCUTS: LHCUTS(6).LE.LHCUTS(5)...')
         AJCUL(1) = AJCU(1)
         AJCUH(1) = AJCU(2)
C
         CALL STDRDR(IMN(1),'FLAT_BKG',1,1,IAV,BGV(1),UNI,NULO,STAT)
         IF (STAT.NE.0) BGV(1) = 0.             !default to background = 0.
         CALL STECNT('PUT',EC,EL,ED)
      ENDIF
C
      DO 2000 M=1,2
         EPS(M) = 0.0001 * ABS(STEPC(M))        !0.01% of stepsize as epsilon
         OEND(M) = OSTART(M) + (NPIX(M)-1)*STEPC(M)
2000  CONTINUE
C
C  now loop through the other input frames
      DO 3000 N=2,FRMCNT
         CALL STFOPN(FRAME(N),D_R4_FORMAT,0,F_IMA_TYPE,IMN(N),STAT)
C
         CALL STDRDI(IMN(N),'NAXIS',1,1,IAV,NAXIS,UNI,NULO,STAT)
         IF (NAXISC.NE.NAXIS) CALL STETER(1,ERROR9)
C
         CALL STDRDI(IMN(N),'NPIX',1,2,IAV,NPIX,UNI,NULO,STAT)
         NPNTS(N) = NPIX(1)
         CALL STDRDD(IMN(N),'START',1,2,IAV,START(1,N),UNI,NULO,STAT)
         CALL STDRDD(IMN(N),'STEP',1,2,IAV,STEP(1,N),UNI,NULO,STAT)
C
         IF (ACTION(1:1).EQ.'W') THEN
            CALL STECNT('GET',EC,EL,ED)            !disable error abort
            CALL STECNT('PUT',1,0,0)
C
            CALL STDRDD(IMN(N),'O_TIME',7,1,IAV,EXPTIM,UNI,NULO,STAT)
            IF (STAT.NE.0) THEN
               EXPTI(N) = 1.0                      !default to 1 second
            ELSE
               EXPTI(N) = EXPTIM
            ENDIF
C
            CALL STDRDR(IMN(N),'LHCUTS',5,2,IAV,AJCU,UNI,NULO,STAT)
            IF (STAT.NE.0)
     +         CALL STDRDR(IMN(N),'LHCUTS',3,2,IAV,AJCU,UNI,NULO,STAT)
            AJCUL(N) = AJCU(1)
            AJCUH(N) = AJCU(2)
C
            CALL STDRDR(IMN(N),'FLAT_BKG',1,1,IAV,BGV(N),UNI,NULO,STAT)
            IF (STAT.NE.0) BGV(N) = 0.            !default to background = 0.
            CALL STECNT('PUT',EC,EL,ED)
         ENDIF
C
C  create new result frame with dimension as intersection of input frames
C  stepsizes should have same sign and not differ too much...
         DO 2400 M=1,NAXISC
            IF (STEPC(M)*STEP(M,N).LE.0.) CALL STETER(1,ERROR3)
            IF (ABS(STEP(M,N)-STEPC(M)).GT.EPS(M))
     +         CALL STTPUT(ERROR1,STAT)                 !just warning message
2400     CONTINUE
C
C  get intersection of image areas
         DO 2600 M=1,NAXISC
            IF (STEPC(M).GT.0.) THEN
               OSTART(M) = MAX(OSTART(M),START(M,N))
               OEND(M) = MIN(OEND(M),START(M,N) + (NPIX(M)-1)*STEP(M,N))
            ELSE
               OSTART(M) = MIN(OSTART(M),START(M,N))
               OEND(M) = MAX(OEND(M),START(M,N) + (NPIX(M)-1)*STEP(M,N))
            ENDIF
2600     CONTINUE
C
C  compute individual offsets
         DO 2800 NIN=1,N
            OFX(NIN) = NINT((OSTART(1)-START(1,NIN))/STEP(1,NIN)) + 1
            OFY(NIN) = NINT((OSTART(2)-START(2,NIN))/STEP(2,NIN)) + 1
2800     CONTINUE
C
3000  CONTINUE
C
C  test, if something is left...
C
      DO 3300 M=1,NAXISC
         IF (STEPC(M)*(OEND(M)-OSTART(M)).LT.0.) CALL STETER(2,ERROR2)
3300  CONTINUE
C
C  set up standard stuff for result frame
      SIZEC = 1
      NPIXC(2) = 1
      DO 3600 M=1,NAXISC
         STARTC(M) = OSTART(M)
         NPIXC(M) = NINT((OEND(M)-OSTART(M))/STEPC(M)) + 1
         SIZEC = SIZEC * NPIXC(M)
3600  CONTINUE
      LP = NPIXC(2)
      NP = NPIXC(1)
C
C  map result frame
      CALL STIPUT(FRAMEC,D_R4_FORMAT,F_O_MODE,F_IMA_TYPE,
     +            NAXISC,NPIXC,STARTC,STEPC,
     +            IDENT,CUNIT,PNTRC,IMNOC,STAT)
C
C  initialize some working variables
      DO 3900 N=1,FRMCNT
         IF (ACTION(1:1).EQ.'W') RFC(N) = 1./EXPTI(N)
         POFF(N) = (OFY(N)-1)*NPNTS(N) + OFX(N)      !determine 1.pixel no.
3900  CONTINUE
C
C  and allocate working space
      NTL = NP * FRMCNT
      IF (NTL.LT.512) NTL = 512
      CALL STFXMP(NTL,D_R4_FORMAT,PNTRT,STAT)
C
C  set up counters for calculation of progress
      NTL = INT(FLOAT(LP)*.2)                  !20% of total no. of lines
      IF (NTL.LE.2) THEN
         NCHECK = LP + 1                       !not worth it...
      ELSE
         NPERC = 20
         NCHECK = NTL
      ENDIF
C
C  now, loop through lines
      DO 5000 L=1,LP
C
C  and loop through frames
         IOFF = 1
         DO 4200 N=1,FRMCNT
            CALL COPULA(IOFF,IMN(N),POFF(N),MADRID(PNTRT),NP)
            POFF(N) = POFF(N) + NPNTS(N)                  !move to next line
            IOFF = IOFF + NP
4200     CONTINUE
C
C  and do it ...
         IF (ACTION(1:1).EQ.'W') THEN
            CALL AVWIN1(MADRID(PNTRT),FRMCNT,NP)
         ELSE
            CALL AVWIN2(ACTION,MADRID(PNTRT),FRMCNT,NP)
         ENDIF
         CALL COPUL(MADRID(PNTRT),MADRID(PNTRC),L,NP)    !save resulting line
C
C  display progress
         IF (L.GE.NCHECK) CALL PROGRS(20,NTL,NPERC,NCHECK)
5000  CONTINUE
C
C  display more info
      IF (ACTION(1:1).EQ.'W') THEN
         DO 5500 N=1,FRMCNT
            WRITE(OUTPUT,10000) AJCUL(N),AJCUH(N)
            L = INDEX(FRAME(N),' ') - 1
            IF (L.LE.0) L = LEN(FRAME(N))
            LINE(1:) = FRAME(N)(1:L)//OUTPUT(1:)
            CALL STTPUT(LINE,STAT)
            WRITE(OUTPUT,10001) EXPTI(N),BGV(N),REJ(N)
            CALL STTPUT(OUTPUT,STAT)
5500     CONTINUE
         WRITE(OUTPUT,10002) TNP(1),TNP(2),TNP(3),TNP(4)
         CALL STTPUT(OUTPUT,STAT)
      ENDIF
C
C  copy descriptors + calculate new dynamic range of result frame
      CALL DSCUPT(IMN(1),IMNOC,' ',STAT)
      CALL MYMX(MADRID(PNTRC),SIZEC,CUTS(3))
      CUTS(1) = CUTS(3)
      CUTS(2) = CUTS(4)
      CALL STDWRR(IMNOC,'LHCUTS',CUTS,1,4,UNI,STAT)
C
      CALL STSEPI
C
C  Formats
10000 FORMAT(' low and high cuts',G12.5,' ,',G12.5)
10001 FORMAT('         EXPTIM',G12.5,', BGV',G12.5,', rej_pix',I8)
10002 FORMAT('pixels with N=0:',I8,', N=1:',I8,', N=2:',I8,', N>2:',I8)
      END

      SUBROUTINE COPULA(IOFF,IMNO,OFFSET,A,NP)
C
      IMPLICIT NONE
C
      INTEGER     IOFF,IMNO,OFFSET,NP
      INTEGER     IAV,STAT
C
      REAL        A(1)
C
      CALL STFGET(IMNO,OFFSET,NP,IAV,A(IOFF),STAT)
      RETURN
      END

      SUBROUTINE COPUL(A,B,NLINE,NP)
C
      IMPLICIT NONE
C
      INTEGER     IOFF,N,NLINE,NP
C
      REAL        A(1),B(1)
C
      IOFF = (NLINE-1) * NP
      DO 800 N=1,NP
         B(N+IOFF) = A(N)
800   CONTINUE
C
      RETURN
      END

      SUBROUTINE AVWIN1(T,TOTAL,NP)
C
      IMPLICIT NONE
C
      REAL        T(1)
      REAL        V,VM,ER,ERR,WG,AM,ALP,F
      REAL        VAL(20),BGV(20),RMS(20),RFC(20)
      REAL        AJCUL(20),AJCUH(20),SNOISE,BGERR
      REAL        EXPTI(20)
      REAL        SQRT                        !system function
C
      LOGICAL     NOK(20)
C
      INTEGER     TOTAL,NP
      INTEGER     IORD(20),NORD(20),REJ(20),TNP(4)
      INTEGER     I,IDX,II,IM1,IO
      INTEGER     N1,N2,NH,NN,NX
      INTEGER     TNP1,TNP2,TNP3,TNP4
C
      COMMON  /MYREAL/  VAL,BGV,RMS,RFC,AJCUL,AJCUH,SNOISE,BGERR,EXPTI
      COMMON  /MYINT/   IORD,NORD,REJ,TNP
C
      EQUIVALENCE    (NORD(1),N1),(NORD(2),N2)
      EQUIVALENCE    (TNP(1),TNP1),(TNP(2),TNP2),
     +               (TNP(3),TNP3),(TNP(4),TNP4)
C
      ALP = 0.
C
C  loop through pixels in each line
      DO 5000 NX=1,NP
         NN = 0                          !init no. of valid pixels
         IDX = NX                        !init offset in working area
C
         DO 400 I=1,TOTAL
            V = T(IDX)
            NOK(I) = V.LT.AJCUL(I) .OR. V.GT.AJCUH(I)      !set NOK, if outside
C
            IF (.NOT.NOK(I)) THEN
               V = V - BGV(I)
               VAL(I) = RFC(I) * V       !fill value stack
             NN = NN + 1                 !increment no. of valid pixels
             IF (V.LT.0.) THEN
                F = 0.
             ELSE
                F = SNOISE * V
             ENDIF
             RMS(I) = RFC(I) * SQRT(BGERR + F)      !estimate deviation
            ENDIF
C
            IDX = IDX + NP                          !increase offset
400      CONTINUE
C
C  order pixel values + find median
         IF (NN.GE.3) THEN
            GOTO 2000                       !more than 2 pixels o.k.
         ELSE
            GOTO (1400,1410,1450),NN+1      !branch acc. to no. of good pixels
         ENDIF
C
C  no good pixels, take 1. frame
1400     NOK(1) = .FALSE.
         TNP1 = TNP1 + 1
         GOTO 3900
C
C  only one good pixel, take it
1410     TNP2 = TNP2 + 1
         GOTO 3900
C
C  two good pixels, test them
1450     II = 1
         DO 1600 I=1,TOTAL
            IF (.NOT.NOK(I)) THEN
               NORD(II) = I
               II = II + 1
            ENDIF
1600     CONTINUE
C
         IF (ABS(VAL(N1)-VAL(N2)).LE.RMS(N1)+RMS(N2)) THEN
            TNP3 = TNP3 + 1
         ELSE
            TNP2 = TNP2 + 1
            IF (ABS(VAL(N1)-ALP).LE.ABS(VAL(N2)-ALP)) THEN
               NOK(N2) = .TRUE.
            ELSE
               NOK(N1) = .TRUE.
            ENDIF
         ENDIF
         GOTO 3900
C
C  more than 2 pixels, compare them
2000     DO 2500 I=1,TOTAL
            IF (.NOT.NOK(I)) THEN
               V = VAL(I)
               IO = 0
               IF (I.EQ.1) GOTO 2400
               IM1 = I - 1
               DO 2200 II=1,IM1
                  IF (.NOT.NOK(II)) THEN
                     IF (V.GT.VAL(II)) THEN
                        IO = IO + 1
                     ELSE
                        IORD(II) = IORD(II) + 1
                     ENDIF
                  ENDIF
2200           CONTINUE
2400           IORD(I) = IO
            ENDIF
2500     CONTINUE
C
C  update NORD
         DO 2600 I=1,TOTAL
            IF (.NOT.NOK(I)) THEN
               II = IORD(I) + 1
               NORD(II) = I
            ENDIF
2600     CONTINUE
C
C  and get median
         NH = (NN+1) / 2
         IM1 = NH - 1
         I = NORD(NH)
         VM = VAL(I)
         ER = RMS(I)
         NH = NN
C
C  now remove all pixels with high residuals (not close to median...)
         DO 3000 I=1,IM1
            II = NORD(I)                                !start at bottom...
            ERR = RMS(II) + ER
            IF (ABS(VAL(II)-VM).GT.ERR) THEN    !discard, if value differs much
               NN = NN - 1
               NOK(II) = .TRUE.
            ENDIF
            II = NORD(NH)                               !and move to top...
            NH = NH - 1
            ERR = RMS(II) + ER
            IF (ABS(VAL(II)-VM).GT.ERR) THEN
               NN = NN - 1
               NOK(II) = .TRUE.
            ENDIF
3000     CONTINUE
C
         NN = MIN(4,NN+1)
         TNP(NN) = TNP(NN) + 1
C
C  calculate final flux
3900     WG = 0.
         AM = 0.
         DO 4000 I=1,TOTAL
            IF (.NOT.NOK(I)) THEN
               WG = WG + EXPTI(I)
               AM = AM + EXPTI(I)*VAL(I)
            ELSE
               REJ(I) = REJ(I) + 1
            ENDIF
4000     CONTINUE
         ALP = AM / WG
         T(NX) = ALP
C
5000  CONTINUE                               !end of loop through pixels
      RETURN
      END

      SUBROUTINE AVWIN2(ACTION,T,TOTAL,NP)
C
      IMPLICIT NONE
C
      REAL        T(1)
      REAL        VAL(20),V,O(11),RVAL
      REAL        VVAL(122)                         !just to pad the COMMON ...
C
      INTEGER     TOTAL,NP
      INTEGER     I,IDX,NN
      INTEGER     NH,NX,NH1
C
      CHARACTER   ACTION*3
C
      COMMON   /MYREAL/  VAL,VVAL
C
C ***
C
C  handle maximum search
C
C ***
C
      IF (ACTION(1:2).EQ.'MA') THEN
C
C  loop through pixels in each line
         DO 800 NX=1,NP
C
            IDX = NX                           !init offset in working area
            DO 200 I=1,TOTAL
               VAL(I) = T(IDX)
               IDX = IDX + NP                  !increase offset
200         CONTINUE
C
            V = VAL(1)
            DO 400 I=2,TOTAL
               IF (V.LT.VAL(I)) V = VAL(I)
400         CONTINUE
            T(NX) = V
800      CONTINUE
C
C ***
C
C  handle minimum search
C
C ***
C
      ELSE IF (ACTION(1:2).EQ.'MI') THEN
C
C  loop through pixels in each line
         DO 1800 NX=1,NP
C
            IDX = NX                           !init offset in working area
            DO 1200 I=1,TOTAL
               VAL(I) = T(IDX)
               IDX = IDX + NP                  !increase offset
1200        CONTINUE
C
            V = VAL(1)
            DO 1400 I=2,TOTAL
               IF (V.GT.VAL(I)) V = VAL(I)
1400        CONTINUE
            T(NX) = V
1800     CONTINUE
C
C ***
C
C  handle median search
C
C ***
C
      ELSE
C
C  loop through pixels in each line
         NH = (TOTAL+1) / 2
         NH1 = NH + 1
         DO 5000 NX=1,NP
C
            IDX = NX                           !init offset in working area
            DO 2200 I=1,TOTAL
               VAL(I) = T(IDX)
               IDX = IDX + NP                  !increase offset
2200        CONTINUE
C
C  order pixel values
            O(1) = VAL(1)
C
C  build up lower half of ordered array (including median index)
            DO 3600 I=2,NH
               NN = I
               RVAL = VAL(NN)
C
3100           IF ((NN.LE.1) .OR. (O(NN-1).LE.RVAL) ) GOTO 3200
               O(NN) = O(NN-1)
               NN = NN - 1
               GOTO 3100
C
3200           O(NN) = RVAL
3600        CONTINUE
C
C  now only merge upper half of array VAL into ordered array O if necessary
            DO 4000 I=NH1,TOTAL
               RVAL = VAL(I)
               NN = NH
               IF (RVAL.GE.O(NN)) GOTO 4000
C
3700           IF ( (NN.LE.1) .OR. (O(NN-1).LE.RVAL) ) GOTO 3800
               O(NN) = O(NN-1)
               NN = NN - 1
               GOTO 3700
C
3800           O(NN) = RVAL
4000        CONTINUE
C
            T(NX) = O(NH)
5000  CONTINUE
      ENDIF
C
      RETURN
      END
