C @(#)modcol.for 13.1.1.2 (ESO-DMD) 02/12/99 19:14:48 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 C+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ C C.IDENTIFICATION C program MODCOL version 1.00 881028 C K. Banse ESO - Garching C M.Peron 910417 modif in the call of TCLSER C S. Wolf 980113 not selected table-rows has not C to be processed (swolf@eso.org)! C.KEYWORDS C bulk data frame, bad pixels C C.PURPOSE C C to replace a column or row of undefined or bad pixels values by quadratic C interpolation of adjacent columns or rows.The bad columns or rows are C defined via the cursor or coordinates or taken from a table. C C.ALGORITHM C C The adjacent pixels are used to compute the coefficients of a least-squares C approximating second order polynomial C C.INPUT/OUTPUT C the following keywords are used: C P1/C/1/60 input frame, table C or C CURSOR C or C input frame C IN_A/C/1/60 input frame, if P1 does not indicate table use C OUT_A/C/1/60 result frame C ACTION/C/1/2 C or R, for column or row C V or C for variable or constant offset C of column/row in question C P4/C/1/80 column or row world coords. if P1 holds just C input frame C C.VERSIONS C C 1.00 from program MODICOL version 2.20 as of 850212 C use FORTRAN 77 + new ST interfaces C C------------------------------------------------------------------- C PROGRAM MODCOL C IMPLICIT NONE C INTEGER N,NCOUNT,IAV,ISTAT INTEGER*8 PNTRA,PNTRB,PNTRX,PNTRY INTEGER IMNOA,IMNOB,STAT INTEGER INDXFL,SIZE,NAXIS,SLEN,SLEN1,TBLFLG INTEGER NCOL,NROW INTEGER IBUF(2),KINDEX,OFF,KROW,KROW1,KROW2 INTEGER TIDI,TABCLN(1) INTEGER UNI(1),NULO,MADRID(1) INTEGER NPIXA(2) C CHARACTER CUNITA*48,IDENTA*72,ACTION*2,COLROW*80 CHARACTER FRAMEA*80,FRAMEB*80,TABLE*80 CHARACTER OUTPUT*80,COLNAM*20 CHARACTER MESS(2)*50,ERRMS1*40,ERRMS2*40 CHARACTER SUBPAR(40)*30 C REAL TEMP,CUTS(4),FMIN,FMAX,RMIN,RMAX,RR C DOUBLE PRECISION STARTA(2),STEPA(2),DD C LOGICAL TABNUL(1),SELFLG C COMMON /VMR/ MADRID C INCLUDE 'MID_INCLUDE:ST_DEF.INC' C DATA FRAMEA /' '/, FRAMEB /' '/ DATA IDENTA /' '/, CUNITA /' '/ DATA OUTPUT /' '/, TABLE /' '/ DATA MESS /'column/row too close to image boundary... ', + 'column/row too large...'/ DATA ERRMS1 /'col/row no.s missing...'/ DATA ERRMS2 /'invalid syntax for col/row no.s ...'/ C INCLUDE 'MID_INCLUDE:ST_DAT.INC' C C get into MIDAS environment CALL STSPRO('MODCOL') C C get input option (frame or frame,table) + read keys CALL STKRDC('IN_A',1,1,80,IAV,OUTPUT,UNI,NULO,STAT) CALL STKRDC('ACTION',1,1,2,IAV,ACTION,UNI,NULO,STAT) CALL UPCAS(ACTION,ACTION) IF (ACTION(1:1).EQ.'C') THEN INDXFL = 1 !index = 1 for columns... ELSE INDXFL = 2 !index = 2 for rows ENDIF C N = INDEX(OUTPUT,',') IF (N.GT.0) THEN TBLFLG = 2 FRAMEA(1:) = OUTPUT(1:N-1) CALL CLNFRA(FRAMEA,FRAMEA,0) !because it's not isolated TABLE(1:) = OUTPUT(N+1:) N = INDEX(TABLE,',') IF (N.GT.0) THEN IAV = N IF (TABLE(N+1:N+1).EQ.':') IAV = N + 1 COLNAM(1:) = TABLE(IAV+1:)//' ' TABLE(N:) = ' ' ELSE IF (ACTION(1:1).EQ.'C') THEN !default column labels COLNAM(1:) = 'X ' ELSE COLNAM(1:) = 'Y ' ENDIF ENDIF CALL TBTOPN(TABLE,F_I_MODE,TIDI,STAT) CALL TBIGET(TIDI,NCOL,NROW,N,N,N,STAT) CALL TBLSER(TIDI,COLNAM,TABCLN(1),STAT) !find columns... IF (TABCLN(1).LE.0) THEN N = INDEX(COLNAM,' ') OUTPUT(1:) = 'column '//COLNAM(1:N)// + ' not found in input table...' CALL STETER (9,OUTPUT) ENDIF ELSE TBLFLG = 1 FRAMEA(1:) = OUTPUT(1:) CALL STKRDC('P4',1,1,80,IAV,COLROW,UNI,NULO,STAT) !get coords. ENDIF CALL STKRDC('OUT_A',1,1,80,IAV,FRAMEB,UNI,NULO,STAT) C C map input + result frame CALL GENEQF(FRAMEA,FRAMEB,STAT) IF (STAT.EQ.1) THEN !same name CALL STIGET(FRAMEA,D_R4_FORMAT,F_IO_MODE,F_IMA_TYPE, + 2,NAXIS,NPIXA,STARTA,STEPA,IDENTA, + CUNITA,PNTRA,IMNOA,STAT) IF (NAXIS.LT.2) THEN CALL STETER(1,'input frame must be a 2-dim frame...') ELSE IF (NAXIS.GT.2) THEN CALL STTPUT + ('only first plane of 3-dim input frame processed',STAT) NAXIS = 2 ENDIF PNTRB = PNTRA IMNOB = IMNOA SIZE = NPIXA(1)*NPIXA(2) ELSE CALL STIGET(FRAMEA,D_R4_FORMAT,F_I_MODE,F_IMA_TYPE, + 2,NAXIS,NPIXA,STARTA,STEPA,IDENTA, + CUNITA,PNTRA,IMNOA,STAT) IF (NAXIS.LT.2) THEN CALL STETER(1,'input frame must be a 2-dim frame...') ELSE IF (NAXIS.GT.2) THEN CALL STTPUT + ('only first plane of 3-dim input frame processed',STAT) NAXIS = 2 ENDIF CALL STIPUT(FRAMEB,D_R4_FORMAT,F_O_MODE,F_IMA_TYPE, + NAXIS,NPIXA,STARTA,STEPA,IDENTA, + CUNITA,PNTRB,IMNOB,STAT) SIZE = NPIXA(1)*NPIXA(2) CALL COPYF(MADRID(PNTRA),MADRID(PNTRB),SIZE) !copy data... ENDIF CALL FRAMOU(FRAMEA) C IF (ACTION(1:1).EQ.'C') THEN !allocate workspace SIZE = NPIXA(2) ELSE SIZE = NPIXA(1) ENDIF CALL STFXMP(SIZE,D_R4_FORMAT,PNTRX,STAT) CALL STFXMP(SIZE,D_R4_FORMAT,PNTRY,STAT) C C save min,max + cuts of image CALL STDRDR(IMNOA,'LHCUTS',1,4,IAV,CUTS,UNI,NULO,STAT) RMIN = CUTS(3) RMAX = CUTS(4) C C fork according to input mode IF (TBLFLG.EQ.2) THEN KROW2 = 0 ISTAT = 2 !thus we start with KROW = 0 GOTO 3000 !and ISTAT != 1 ENDIF C C extract columns/rows from COLROW ISTAT = 1 KINDEX = 0 NCOUNT = 0 OFF = 1 DO 600, N=1,40 CALL EXTRSS(COLROW,',',OFF,SUBPAR(N),SLEN) IF (SLEN.LE.0) THEN IF (NCOUNT.LE.0) CALL STETER(2,ERRMS1) GOTO 1000 !we reached the end... ELSE NCOUNT = N ENDIF 600 CONTINUE C C finally loop through columns or rows C 1000 KINDEX = KINDEX + ISTAT IF (KINDEX.GT.NCOUNT) GOTO 4000 C N = KINDEX IF (SUBPAR(N)(1:1).EQ.'@') THEN !input = @pixel CALL GENCNV(SUBPAR(N)(2:),1,1,IBUF,RR,DD,SLEN) IF (SLEN.LE.0) CALL STETER(3,ERRMS2) ELSE !input = world coord CALL GENCNV(SUBPAR(N),2,1,IAV,TEMP,DD,SLEN) IF (SLEN.LE.0) CALL STETER(3,ERRMS2) IBUF(1) = NINT((TEMP - STARTA(INDXFL))/STEPA(INDXFL)) + 1 ENDIF IF (KINDEX.EQ.NCOUNT) THEN IBUF(2) = 0 ELSE N = N + 1 IF (SUBPAR(N)(1:1).EQ.'@') THEN !input = @pixel CALL GENCNV(SUBPAR(N)(2:),1,1,IBUF(2),TEMP,DD,SLEN) IF (SLEN.LE.0) CALL STETER(3,ERRMS2) ELSE !input = world coord CALL GENCNV(SUBPAR(N),2,1,IAV,TEMP,DD,SLEN) IF (SLEN.LE.0) CALL STETER(3,ERRMS2) IBUF(2) = NINT((TEMP - STARTA(INDXFL))/STEPA(INDXFL)) + 1 ENDIF ENDIF C 1010 FMIN = RMIN FMAX = RMAX CALL DOIT(ACTION,MADRID(PNTRB),MADRID(PNTRX),MADRID(PNTRY), + STARTA,STEPA,NPIXA, + IBUF,FMIN,FMAX,ISTAT) IF (ISTAT.LT.0) THEN CALL STTPUT(MESS(-ISTAT),STAT) ISTAT = 1 !on return, ISTAT = 1 or 2 ELSE !depending on no. of columns/rows used SLEN = INDEX(SUBPAR(KINDEX),' ') !cut off trailing blanks IF (SLEN.LE.0) SLEN = LEN(SUBPAR(KINDEX)) C IF (ISTAT.EQ.1) THEN OUTPUT(1:) = 'column/row at x/y = ' + //SUBPAR(KINDEX)(1:SLEN)// + 'cleaned... ' ELSE SLEN1 = INDEX(SUBPAR(KINDEX+1),' ') !cut off trailing blanks IF (SLEN1.LE.0) SLEN1 = LEN(SUBPAR(KINDEX+1)) OUTPUT(1:) = 'columns/rows at x/y = '// + SUBPAR(KINDEX)(1:SLEN)//', '// + SUBPAR(KINDEX+1)(1:SLEN1)//'cleaned...' ENDIF CALL STTPUT(OUTPUT,STAT) RMIN = MIN(RMIN,FMIN) RMAX = MAX(RMAX,FMAX) ENDIF GOTO (1000,3000),TBLFLG !look for more... C C here we get our input data from a table 3000 KROW = KROW2 + ISTAT - 1 !KROW -> KROW2 or -> KROW2+1 IF (KROW.LE.NROW) THEN KROW1 = KROW IF (ISTAT.EQ.1) THEN !only one row used last time... IBUF(1) = IBUF(2) SUBPAR(1)(1:) = SUBPAR(2)(1:) GOTO 3100 !so reuse last value ENDIF C 3030 CALL TBSGET(TIDI,KROW1,SELFLG,STAT) !only use selected rows IF (.NOT.SELFLG) THEN KROW1 = KROW1 + 1 !get next row IF (KROW1.LE.NROW) THEN GOTO 3030 ELSE GOTO 3300 !end of table reached ENDIF ENDIF C CALL TBRRDR(TIDI,KROW1,1,TABCLN,TEMP,TABNUL,STAT) IBUF(1) = NINT((TEMP - STARTA(INDXFL))/STEPA(INDXFL)) + 1 WRITE(SUBPAR(1),10000) TEMP DO 3060, N=1,30 IF (SUBPAR(1)(N:N).NE.' ') THEN IF (N.GT.1) SUBPAR(1)(1:) = SUBPAR(1)(N:)//' ' GOTO 3100 ENDIF 3060 CONTINUE C 3100 KROW2 = KROW1 + 1 !point to next possible row IF (KROW1.EQ.NROW) THEN IBUF(2) = 0 ELSE 3130 CALL TBSGET(TIDI,KROW2,SELFLG,STAT) !only use selected rows IF (.NOT.SELFLG) THEN KROW2 = KROW2 + 1 !get next row IF (KROW2.LE.NROW) THEN GOTO 3130 ELSE IBUF(2) = 0 GOTO 3200 ENDIF ENDIF C CALL TBRRDR(TIDI,KROW2,1,TABCLN,TEMP,TABNUL,STAT) IBUF(2) = NINT((TEMP - STARTA(INDXFL))/STEPA(INDXFL)) + 1 WRITE(SUBPAR(2),10000) TEMP DO 3160, N=1,30 IF (SUBPAR(2)(N:N).NE.' ') THEN IF (N.GT.1) SUBPAR(2)(1:) = SUBPAR(2)(N:)//' ' GOTO 3200 ENDIF 3160 CONTINUE ENDIF C 3200 KINDEX = 1 !force index to 1 GOTO 1010 !now continue as above ENDIF C C close table 3300 CALL TBTCLO(TIDI,STAT) C C get new dynamic range + write descriptor LHCUTS 4000 CUTS(3) = MIN(RMIN,CUTS(3)) CUTS(4) = MAX(RMAX,CUTS(4)) C C copy descriptors + append HISTORY CALL DSCUPT(IMNOA,IMNOB,' ',STAT) CALL STDWRR(IMNOB,'LHCUTS',CUTS,1,4,UNI,STAT) !use old cuts... C C That's it folks... CALL STSEPI C C format statements 10000 FORMAT(F20.10) END SUBROUTINE DOIT(ACTION,A,TEMPA,TEMPB, + START,STEP,NPIX,COORD,FMIN,FMAX,ISTAT) C IMPLICIT NONE C INTEGER COORD(2),ISTAT INTEGER JOF,JOF1,N,M,NFLAG,KFLAG INTEGER NEXT,NP,JNDX,NOLINS INTEGER NPIX(2),INDX(4),IOF(4) C CHARACTER ACTION*2 C REAL A(*),TEMPA(*),TEMPB(*),FMIN,FMAX REAL V,VV,W,WW,XX,XXX REAL RMIN,RMAX C DOUBLE PRECISION START(2),STEP(2) DOUBLE PRECISION S(4),Z(4),X(4),F(4) DOUBLE PRECISION RR1,RR2,RR3,P1,P2,P3,Q DOUBLE PRECISION SUM1,SUM2 DOUBLE PRECISION A0,A1,A2 C IF (ACTION(1:1).EQ.'C') THEN NFLAG = 1 !columns... ELSE NFLAG = 2 !rows... ENDIF KFLAG = 3 - NFLAG INDX(1) = COORD(1) - 2 !take 2 pixels less NEXT = COORD(2) - 2 C INDX(2) = INDX(1) + 1 JNDX = INDX(2) + 1 !keep index of bad line... IF (NEXT .EQ. INDX(1)+1) THEN NOLINS = 2 !double lines... ELSE NOLINS = 1 ENDIF INDX(3) = INDX(2) + NOLINS + 1 !single line... INDX(4) = INDX(3) + 1 C C check input pars IF ((INDX(1).LT.1).OR.(INDX(4).GT.NPIX(NFLAG))) THEN ISTAT = -1 RETURN ELSE ISTAT = NOLINS ENDIF C C get "x" values + related sums for later calculations DO 200, N=1,4 !get x values... X(N) = START(NFLAG) + (INDX(N)-1)*STEP(NFLAG) Z(N) = 1.D0 200 CONTINUE XX = START(NFLAG) + (JNDX-1)*STEP(NFLAG) !x of bad row/column... XXX = XX + STEP(NFLAG) C DO 1000, M=1,4 DO 400, N=1,4 !get x**2,x**3,x**4 ... Z(N) = Z(N)*X(N) 400 CONTINUE S(M) = 0.D0 !compute sums DO 600, N=1,4 S(M) = S(M) + Z(N) 600 CONTINUE 1000 CONTINUE C C branch according to columns + rows IF (ACTION(1:1).EQ.'C') GOTO 5000 C C handle rows... DO 1200, N=1,4 !get y values... IOF(N) = (INDX(N)-1)*NPIX(1) 1200 CONTINUE JOF = (JNDX-1)*NPIX(1) JOF1 = JOF + NPIX(1) C C go through the row DO 3300, NP=1,NPIX(1) DO 1400, M=1,4 !get function values F(M) = A(IOF(M)+NP) Z(M) = 0.D0 1400 CONTINUE C DO 1600, M=1,4 !compute sums on right side Z(1) = Z(1) + F(M) Z(2) = Z(2) + F(M)*X(M) Z(3) = Z(3) + F(M)*X(M)*X(M) 1600 CONTINUE C C reduce + solve the linear system 4.*A0 + S1*A1 + S2*A2 = Z1 C S1*A0 + S2*A1 + S3*A2 = Z2 C S2*A0 + S3*A1 + S4*A2 = Z3 Q = S(1) * 0.25D0 RR1 = S(2) - S(1)*Q RR2 = S(3) - S(2)*Q RR3 = Z(2) - Z(1)*Q Q = S(2) * 0.25D0 P1 = S(3) - S(1)*Q P2 = S(4) - S(2)*Q P3 = Z(3) - Z(1)*Q C we now have: RR1*A1 + RR2*A2 = RR3 C P1*A1 + P2*A2 = P3 Q = P1/RR1 IF (ABS(P2-RR2*Q).LE.10.D-30) THEN IF (ABS(P1 - RR1*Q).LE.10.D-30) THEN !linearly dependant system A0 = 0.D0 A1 = 1.D0 A2 = 0.D0 GOTO 3000 ENDIF Q = P2/RR2 A1 = (P3 - RR3*Q) / (P1 - RR1*Q) A2 = (RR3 - A1*RR1)/RR2 ELSE A2 = (P3 - RR3*Q) / (P2 - RR2*Q) A1 = (RR3 - A2*RR2)/RR1 ENDIF C A0 = (Z(1) - S(2)*A2 - S(1)*A1) * .25D0 C C finally calculate interpolated value...! 3000 TEMPA(NP) = A0 + A1*XX + A2*XX*XX IF (NOLINS.EQ.2) + TEMPB(NP) = A0 + A1*XXX + A2*XXX*XXX 3300 CONTINUE C C check, if we work on single line or not C IF (NOLINS.EQ.2) GOTO 4000 C C for constant offset, get average difference to orignal bad row IF (ACTION(2:2).EQ.'C') THEN SUM1 = 0.D0 DO 3500, NP=1,NPIX(1) SUM1 = SUM1 + DBLE(A(JOF+NP) - TEMPA(NP)) !sum differences 3500 CONTINUE V = SNGL(SUM1/NPIX(1)) !get average offset C C and correct pixels in bad row with that offset DO 3600, NP=1,NPIX(1) W = A(JOF+NP) A(JOF+NP) = W - V IF (W.LT.FMIN) THEN FMIN = W ELSE IF (W.GT.FMAX) FMAX = W ENDIF 3600 CONTINUE C ELSE C C store approximated pixels in bad row DO 3800, NP=1,NPIX(1) W = TEMPA(NP) A(JOF+NP) = W IF (W.LT.FMIN) THEN FMIN = W ELSE IF (W.GT.FMAX) FMAX = W ENDIF 3800 CONTINUE ENDIF RETURN C C here to handle two adjacent "bad" rows C 4000 IF (ACTION(2:2).EQ.'C') THEN SUM1 = 0.D0 !get average difference to adjacent lines SUM2 = 0.D0 DO 4200, NP=1,NPIX(1) SUM1 = SUM1 + DBLE(A(JOF+NP) - TEMPA(NP)) !sum differences SUM2 = SUM2 + DBLE(A(JOF1+NP) - TEMPB(NP)) !sum differences 4200 CONTINUE V = SNGL(SUM1/NPIX(1)) !get average offset VV = SNGL(SUM2/NPIX(1)) C C and correct pixels in bad rows with these offsets DO 4400, NP=1,NPIX(1) W = A(JOF+NP) A(JOF+NP) = W - V WW = A(JOF1+NP) A(JOF1+NP) = WW - VV RMIN = MIN(W,WW) RMAX = MAX(W,WW) IF (RMIN.LT.FMIN) FMIN = RMIN IF (RMAX.GT.FMAX) FMAX = RMAX 4400 CONTINUE C ELSE C C store approximated pixels in bad rows DO 4600, NP=1,NPIX(1) W = TEMPA(NP) WW = TEMPB(NP) A(JOF+NP) = W A(JOF1+NP) = WW RMIN = MIN(W,WW) RMAX = MAX(W,WW) IF (RMIN.LT.FMIN) FMIN = RMIN IF (RMAX.GT.FMAX) FMAX = RMAX 4600 CONTINUE ENDIF RETURN C C handle columns... C C go through the column 5000 JOF = 0 DO 6600, NP=1,NPIX(2) DO 5200, M=1,4 !get function values F(M) = A(JOF+INDX(M)) Z(M) = 0.D0 5200 CONTINUE C DO 5400, M=1,4 !compute sums on right side Z(1) = Z(1) + F(M) Z(2) = Z(2) + F(M)*X(M) Z(3) = Z(3) + F(M)*X(M)*X(M) 5400 CONTINUE C C reduce + solve the linear system 4.*A0 + S1*A1 + S2*A2 = Z1 C S1*A0 + S2*A1 + S3*A2 = Z2 C S2*A0 + S3*A1 + S4*A2 = Z3 Q = S(1)*.25D0 RR1 = S(2) - S(1)*Q RR2 = S(3) - S(2)*Q RR3 = Z(2) - Z(1)*Q Q = S(2)*.25D0 P1 = S(3) - S(1)*Q P2 = S(4) - S(2)*Q P3 = Z(3) - Z(1)*Q C we now have: RR1*A1 + RR2*A2 = RR3 C P1*A1 + P2*A2 = P3 Q = P1/RR1 IF (ABS(P2-RR2*Q).LE.10.D-30) THEN IF (ABS(P1 - RR1*Q).LE.10.D-30) THEN !linearly dependant system A0 = 0.D0 A1 = 1.D0 A2 = 0.D0 GOTO 6000 ENDIF Q = P2/RR2 A1 = (P3 - RR3*Q) / (P1 - RR1*Q) A2 = (RR3 - A1*RR1)/RR2 ELSE A2 = (P3 - RR3*Q) / (P2 - RR2*Q) A1 = (RR3 - A2*RR2)/RR1 ENDIF C A0 = (Z(1) - S(2)*A2 - S(1)*A1)*.25D0 C C finally calculate interpolated value...! 6000 TEMPA(NP) = A0 + A1*XX + A2*XX*XX IF (NOLINS.EQ.2) + TEMPB(NP) = A0 + A1*XXX + A2*XXX*XXX JOF = JOF + NPIX(1) !update offset to next row... 6600 CONTINUE C C check, if we work on single line or not C IF (NOLINS.EQ.2) GOTO 8000 C C for constant offset, get average difference to original bad column IF (ACTION(2:2).EQ.'C') THEN SUM1 = 0.D0 JOF = JNDX DO 6800, NP=1,NPIX(2) SUM1 = SUM1 + DBLE(A(JOF) - TEMPA(NP)) !sum differences JOF = JOF + NPIX(1) 6800 CONTINUE W = SNGL(SUM1/NPIX(2)) !get average offset C C and correct pixels in bad column with that offset JOF = JNDX DO 7000, NP=1,NPIX(2) V = A(JOF) - W A(JOF) = V IF (V.LT.FMIN) THEN FMIN = V ELSE IF (V.GT.FMAX) FMAX = V ENDIF JOF = JOF + NPIX(1) 7000 CONTINUE C ELSE C C fill approximated pixels into frame JOF = JNDX DO 7400, NP=1,NPIX(2) V = TEMPA(NP) A(JOF) = V IF (V.LT.FMIN) THEN FMIN = V ELSE IF (V.GT.FMAX) FMAX = V ENDIF JOF = JOF + NPIX(1) 7400 CONTINUE ENDIF RETURN C C here to handle two adjacent "bad" columns 8000 IF (ACTION(2:2).EQ.'C') THEN SUM1 = 0.D0 !get average difference to adjacent lines SUM2 = 0.D0 JOF = JNDX C DO 8200, NP=1,NPIX(2) SUM1 = SUM1 + DBLE(A(JOF) - TEMPA(NP)) !sum differences SUM2 = SUM2 + DBLE(A(JOF+1) - TEMPB(NP)) JOF = JOF + NPIX(1) 8200 CONTINUE V = SNGL(SUM1/NPIX(2)) !get average offset VV = SNGL(SUM2/NPIX(2)) C C and correct pixels in bad columns with these offsets JOF = JNDX DO 8400, NP=1,NPIX(2) W = A(JOF) WW = A(JOF+1) A(JOF) = W - V A(JOF+1) = WW - VV RMIN = MIN(W,WW) RMAX = MAX(W,WW) IF (RMIN.LT.FMIN) FMIN = RMIN IF (RMAX.GT.FMAX) FMAX = RMAX JOF = JOF + NPIX(1) 8400 CONTINUE C ELSE C C fill approximated pixels into frame JOF = JNDX DO 8600, NP=1,NPIX(2) W = TEMPA(NP) WW = TEMPB(NP) A(JOF) = W A(JOF+1) = WW W = A(JOF) RMIN = MIN(W,WW) RMAX = MAX(W,WW) IF (RMIN.LT.FMIN) FMIN = RMIN IF (RMAX.GT.FMAX) FMAX = RMAX JOF = JOF + NPIX(1) 8600 CONTINUE ENDIF RETURN C END