	SUBROUTINE SETCRD
!
!  invokes set-up routines for coordinate calculations for current
!  image and current display window; supplies defaults needed for
!  coordinates only (no display) if a display window has not been set
!
	COMMON /IMAGE/	IMFILE,FCTDWN,FCTACR,NPHOT,CENTRMLC,PIXOFF
	COMMON /IWINDOW/IXMIN,IXMAX,IYMIN,IYMAX
	COMMON /MAFREC/	HEADER,SCAN
!
	BYTE		HEADER(404),SCAN(1592)
	CHARACTER*128	IMFILE
	INTEGER*2	NPHOT,IXMIN,IXMAX,IYMIN,IYMAX,CENTRMLC,PIXOFF,
     &			I,LCENTR(3)
	INTEGER*4	MAXPIXINLINE
	REAL*4		FCTDWN,FCTACR
!
	EQUIVALENCE (HEADER(57),MAXPIXINLINE)
	DATA	LCENTR/80,73,90/
!
	IF (CENTRMLC.EQ.0) CENTRMLC = LCENTR(NPHOT)
!
!---set up window for standard image, coordinates only, if not
!		already set otherwise
	IF (IXMIN.EQ.0.AND.IXMAX.EQ.0) THEN
	    FCTDWN = 1.
	    FCTACR = 1.
	    IXMIN = 1
	    IXMAX = 128
	    IYMIN = 1
	    IYMAX = 150
	ENDIF
!
!---get position parameters, window coordinates, and other related data
	CALL ERRSET(67,.TRUE.,.FALSE.,.TRUE.,.FALSE.,32000)
	OPEN(UNIT=2,NAME=IMFILE,TYPE='OLD',FORM='UNFORMATTED',READONLY)
	READ(2) HEADER
	READ(2,ERR=13) (SCAN(I),I=1,MAXPIXINLINE+24)
 13	CALL SETIMCOORD
	CALL SETWNCOORD
	CALL MOTION
	CLOSE(UNIT=2)
!
	RETURN
!
	END
!
!
!
	SUBROUTINE SETIMCOORD
!
!  sets up for coordinate calculations for the current image file
!  with the view coordinate origin at the center of the Earth;
!  header record and first scanline record are assumed to be in the
!  MAFREC common block
!
	COMMON /IMAGE/	IMFILE,FCTDWN,FCTACR,NPHOT,CENTRMLC,PIXOFF
	COMMON /IWINDOW/IXMIN,IXMAX,IYMIN,IYMAX
	COMMON /IMCOORD/IMXMIN,IMXMAX,IMYMAX,STEP,PIXWD,PIXHT,
     &			NSPIN,TSPIN,UTNC1,SOLMSEC1,SP,ALTF,MDIREC
	COMMON /MAFREC/	HEADER,SCAN
!
	BYTE		HEADER(404),SCAN(1592),SUBCOMNO
	CHARACTER*128	IMFILE
	CHARACTER*4	NAME
	INTEGER*2	NPHOT,IXMIN,IXMAX,IYMIN,IYMAX,CENTRMLC,PIXOFF,
     &			MDIREC,LINECOUNT,I,CMLC,REFSECT,NP,
     &			SCOFFSET,DCU,NADCOR(3),LCENTR(3),NUMBER
	INTEGER*4	NSPIN,TSPIN,NPTIME,UTNC1,UTCENTER,OMSEC,FWVOLT,
     &			FIRSTMLC,LASTMLC,MMC,ORBIT,SCPOS(3),SPINVCTR(3),
     &			OAMSEC,LMSEC,SOLMSEC1,YEAR,DAY
	REAL*4		FCTDWN,FCTACR,IMXMIN,IMXMAX,IMYMAX,STEP,TOPYANG,
     &			PIXWD,PIXHT,ANGLE,XOFFSET,ANGLES(3),P(4),
     &			LNCOR(2,121),SP,ALTF
	REAL*8		DRPOS,DSTART,DSTOP
	LOGICAL*1	ADV
!
	EQUIVALENCE (HEADER(13),YEAR),	(HEADER(17),DAY),
     &		(HEADER(29),FWVOLT),	(HEADER(41),FIRSTMLC),
     &		(HEADER(45),LASTMLC),	(HEADER(97),MMC),
     &		(HEADER(117),ORBIT),	(HEADER(121),SCPOS(1)),
     &		(HEADER(133),SPINVCTR(1)),(HEADER(189),OAMSEC),
     &		(HEADER(395),SCOFFSET)
	EQUIVALENCE (SCAN(5),LMSEC),(SCAN(12),SUBCOMNO),
     &		    (SCAN(13),DCU), (SCAN(17),NADCOR(1))
	DATA	LCENTR/80,73,90/
	DATA	ANGLES/60.,70.,50./
!
!---orbit data is needed
	IF (ORBIT.EQ.0) THEN
	    WRITE(6,'(A)') ' This image file has no orbit data.'
	    STOP
	ENDIF
!
!---check for advanced mode
	IF (IAND(MMC,3).EQ.2) THEN
	    ADV = .TRUE.
	ELSE
	    ADV = .FALSE.
	ENDIF
!
!---get the angle to mirror step for normal mode
	STEP = ANGLES(NPHOT)
!---add 60 degrees if in advanced mode
	IF (ADV) STEP = STEP + 60.
!
!---mirror stepping direction
	MDIREC = ISIGN(1,LASTMLC-FIRSTMLC)
	IF (NPHOT.LT.3) MDIREC = -MDIREC
!
!---get spin period
	CALL SPINS(NSPIN,TSPIN)
!
!---compute angular dimensions of a pixel
	PIXWD = .25
	PIXHT = 360. / (TSPIN/3.90625)
!
!---adjust top Y coordinate angle to reference sector boundary
	TOPYANG = 0.
	CALL SECTORS(REFSECT)
	NP = NPHOT
	IF (REFSECT.GT.1) THEN
	    DO I=3,REFSECT,-1
		NP = NP - 1
		IF (NP.EQ.0) NP = 3
		TOPYANG = TOPYANG + ANGLES(NP) + 60.
	    ENDDO
	ENDIF
	IF (.NOT.ADV) TOPYANG = TOPYANG + 60.
!
!---set top Y coordinate
	IMYMAX = -SCOFFSET + 1. + TOPYANG/PIXHT
!
!---set X coordinates
	IF (NPHOT.LT.3) THEN
	    IMXMIN = FLOAT( LCENTR(NPHOT) - MAX0(FIRSTMLC,LASTMLC) )
	    IMXMAX = FLOAT( LCENTR(NPHOT) - MIN0(FIRSTMLC,LASTMLC) )
	ELSE
	    IMXMIN = FLOAT( MIN0(FIRSTMLC,LASTMLC) - LCENTR(3) )
	    IMXMAX = FLOAT( MAX0(FIRSTMLC,LASTMLC) - LCENTR(3) )
	ENDIF
	IMXMIN = IMXMIN - .5
	IMXMAX = IMXMAX - .5
!
!---adjust X-dimensions by spin vector and s/c position angle
	DRPOS = DSQRT(DBLE(SCPOS(1))*DBLE(SCPOS(1)) +
     &	   DBLE(SCPOS(2))*DBLE(SCPOS(2)) + DBLE(SCPOS(3))*DBLE(SCPOS(3)))
	ANGLE = ACOSD( SNGL( (SCPOS(1)/DRPOS)*(SPINVCTR(1)/1.D6) + 
     &       (SCPOS(2)/DRPOS)*(SPINVCTR(2)/1.D6) +
     &	     (SCPOS(3)/DRPOS)*(SPINVCTR(3)/1.D6) ) )
!
!---calculate some necessary UTs
	UTNC1 = NPTIME(LMSEC,SUBCOMNO,DCU) - 
     &	    (NADCOR(1)+NADCOR(2)+NADCOR(3))*.48828125
	CALL EQTIME(YEAR,DAY,UTNC1,SOLMSEC1)
	IF (IAND(MMC,3).NE.2) UTNC1 = UTNC1 + TSPIN*.1666667
	OMSEC = OAMSEC
	IF (UTNC1.GT.85000000.AND.OMSEC.LT.1400000) OMSEC = OMSEC + 86400000
	IF (OMSEC.GT.85000000.AND.UTNC1.LT.1400000) OMSEC = OMSEC - 86400000
!
!---fill in filter data
	CALL FILTERS(NPHOT,FWVOLT,NAME,NUMBER,SP,ALTF)
!
!---iterate adjustment for a better fit
 75	XOFFSET = (ANGLE-90.)/PIXWD
	CMLC = (FIRSTMLC+LASTMLC)/2
	UTCENTER = UTNC1 + ABS(CMLC-FIRSTMLC)*NSPIN
	DSTART = (OAMSEC-UTCENTER)/1.D3
	DSTOP = -DSTART
	CALL DEORBIT(DSTART,DSTOP,0.D0,P)
	ANGLE = ACOSD( P(1)/DBLE(P(4))*(SPINVCTR(1)/1.D6)
     &			 + P(2)/DBLE(P(4))*(SPINVCTR(2)/1.D6)
     &			 + P(3)/DBLE(P(4))*(SPINVCTR(3)/1.D6) )
	IF (ABS((ANGLE-90.)/PIXWD-XOFFSET).GT..1) GO TO 75
!
	XOFFSET = (ANGLE-90.)/PIXWD
	IMXMIN = IMXMIN + XOFFSET
	IMXMAX = IMXMAX + XOFFSET
!
	RETURN
	END
!
!
!
	SUBROUTINE SPINS(NSPIN,TSPIN)
!
!  calculates a spin period with respect to nadir and a
!  360 degree spin period in milliseconds for the image header record
!  in the MAFREC common block
!
!			name	type	description
!
!  output arguments:	NSPIN	INT*4	spin period in milliseconds
!					  with respect to nadir
!			TSPIN	INT*4	360 degree spin period in msec.
!
!
	COMMON /MAFREC/ HEADER,SCAN
!
	BYTE		HEADER(404),SCAN(1592)
	INTEGER*4	NSPIN,TSPIN,SCPOS2(3),SCPOS(3),VEL(3),
     &			SPINRATE,SPINPERIOD

	REAL*4		TWOPI,ANGLE
	REAL*8		DRPOS,DRPOS2
!
	EQUIVALENCE (HEADER(121),SCPOS(1)),(HEADER(161),VEL(1)),
     &			(HEADER(185),SPINRATE),(HEADER(193),SPINPERIOD)
	DATA	TWOPI/6.283185/
!
!---spin period with respect to nadir
	IF (SPINPERIOD.NE.0) THEN
	    NSPIN = SPINPERIOD
	ELSE
	    IF (SPINRATE.NE.0) THEN
		NSPIN = NINT(TWOPI*1.D9/SPINRATE)
	    ELSE
		NSPIN = 6070
	    ENDIF
	ENDIF
!
!---360 degree spin period
	SCPOS2(1) = SCPOS(1) + NINT(VEL(1)/1.E6*NSPIN)
	SCPOS2(2) = SCPOS(2) + NINT(VEL(2)/1.E6*NSPIN)
	SCPOS2(3) = SCPOS(3) + NINT(VEL(3)/1.E6*NSPIN)
	DRPOS = DSQRT(DBLE(SCPOS(1))*DBLE(SCPOS(1)) +
     &	   DBLE(SCPOS(2))*DBLE(SCPOS(2))+DBLE(SCPOS(3))*DBLE(SCPOS(3)))
	DRPOS2 = DSQRT( DBLE(SCPOS2(1))*DBLE(SCPOS2(1)) +
     &			 DBLE(SCPOS2(2))*DBLE(SCPOS2(2)) +
     &			  DBLE(SCPOS2(3))*DBLE(SCPOS2(3)) )
	ANGLE = ACOS( (SCPOS(1)/DRPOS)*(SCPOS2(1)/DRPOS2) +
     &			(SCPOS(2)/DRPOS)*(SCPOS2(2)/DRPOS2) + 
     &			 (SCPOS(3)/DRPOS)*(SCPOS2(3)/DRPOS2) )
	TSPIN = NINT(NSPIN * TWOPI/(TWOPI-ANGLE))
!
	RETURN
	END
!
!
!
	SUBROUTINE SECTORS(REFSECT)
!
!  determine the sector boundary reference for setting coordinates
!
!			name	type	description
!
!   output argument:	REFSECT	INT*2	first sector selected for this
!					  photometer
!
!
	COMMON /IMAGE/	IMFILE,FCTDWN,FCTACR,NPHOT,CENTRMLC,PIXOFF
	COMMON /MAFREC/	HEADER,SCAN
!
	BYTE		HEADER(404),SCAN(1592)
	INTEGER*4	MMC
	INTEGER*2	REFSECT,NSECTS,K,PHOTSEL(3),SECT(2),TOTAL,
     &			NPHOT,CENTRMLC,PIXOFF
	CHARACTER*128	IMFILE
	REAL*4		FCTDWN,FCTACR
!
	EQUIVALENCE (HEADER(97),MMC)
!
!---extract nadir pulse sector codes
	PHOTSEL(1) = IAND(MMC,24)/8
	PHOTSEL(2) = IAND(MMC,192)/64
	PHOTSEL(3) = IAND(MMC,1536)/512
!
!---decode sector selection
	NSECTS = 0					
	DO K=1,3
	    IF (MOD(PHOTSEL(K)+K-1,3).EQ.NPHOT-1) THEN
		NSECTS = NSECTS + 1
		IF (NSECTS.LT.3) SECT(NSECTS) = MOD(3-PHOTSEL(K),3) + 1
	    ENDIF
	ENDDO
!
!---determine first sector for coordinate reference
	IF (NSECTS.EQ.1) THEN
	    REFSECT = SECT(1)
	    RETURN
	ELSE
	    TOTAL = SECT(1) + SECT(2)
	    REFSECT = MOD(6-TOTAL,3) + 1
	ENDIF
!
	RETURN
!
	END
!
!
!
	SUBROUTINE SETWNCOORD
!
!  sets coordinates for the display window based on the current
!  image file with origin at the center of the Earth;
!  header record must be in MAFREC common block and a previous
!  call to SETIMCOORD is necessary
!
!
	COMMON /MAFREC/	HEADER,SCAN
	COMMON /IMAGE/	IMFILE,FCTDWN,FCTACR,NPHOT,CENTRMLC,PIXOFF
	COMMON /IWINDOW/IXMIN,IXMAX,IYMIN,IYMAX
	COMMON /IMCOORD/IMXMIN,IMXMAX,IMYMAX,STEP,PIXWD,PIXHT,
     &			NSPIN,TSPIN,UTNC1,SOLMSEC1,SP,ALTF,MDIREC
	COMMON /WINDOW/	WNXMIN,WNXMAX,WNYMIN,WNYMAX
!
	CHARACTER*128	IMFILE
	INTEGER*2	NPHOT,IXMIN,IXMAX,IYMIN,IYMAX,CENTRMLC,PIXOFF,
     &			MDIREC,ICENTR,LEFTMLC,LCENTR(3)
	REAL*4		FCTDWN,FCTACR,IMXMIN,IMXMAX,IMYMAX,STEP,SP,ALTF,
     &			PIXWD,PIXHT,WNXMIN,WNXMAX,WNYMIN,WNYMAX,CENTERX
	BYTE		HEADER(404),SCAN(1592)
	INTEGER*4	FIRSTMLC,LASTMLC,NSPIN,TSPIN,UTNC1,SOLMSEC1
!
	EQUIVALENCE (HEADER(41),FIRSTMLC),(HEADER(45),LASTMLC)
	DATA	LCENTR/80,73,90/
!
!---determine center X coordinate
	ICENTR = (IXMIN+IXMAX)/2
	IF (CENTRMLC.EQ.0) CENTRMLC = LCENTR(NPHOT)
	IF (NPHOT.EQ.3) THEN
	    LEFTMLC = MIN0(FIRSTMLC,LASTMLC)
	    CENTERX = IMXMIN + (CENTRMLC-LEFTMLC)
	ELSE
	    LEFTMLC = MAX0(FIRSTMLC,LASTMLC)
	    CENTERX = IMXMIN + (LEFTMLC-CENTRMLC)
	ENDIF
!
!---left and right window edges
	WNXMIN = CENTERX - (ICENTR-IXMIN)/FCTACR
	WNXMAX = CENTERX + (IXMAX-ICENTR)/FCTACR
!
!---top and bottom window edges
	WNYMAX = IMYMAX - PIXOFF
	WNYMIN = WNYMAX - (IYMAX-IYMIN)/FCTDWN
!
	RETURN
	END
!
!
!
	SUBROUTINE MOTION
!
!  gets the DE-1 spacecraft position for the approximate nadir
!  crossing of each scan line and sets up related information needed
!  to correct for s/c motion in coordinate mapping
!
	COMMON /IWINDOW/IXMIN,IXMAX,IYMIN,IYMAX
	COMMON /IMCOORD/IMXMIN,IMXMAX,IMYMAX,STEP,PIXWD,PIXHT,
     &			NSPIN,TSPIN,UTNC1,SOLMSEC1,SP,ALTF,MDIREC
	COMMON /WINDOW/	WNXMIN,WNXMAX,WNYMIN,WNYMAX
	COMMON /MOTION/	POSITION,SPINANG,XP1,SPINX,SPINY,SPINZ,
     &			SUNX,SUNZ
	COMMON /MAFREC/HEADER,SCAN
!
	BYTE		HEADER(404),SCAN(1592)
	INTEGER*2	IXMIN,IXMAX,IYMIN,IYMAX,MDIREC,INDEX1,K,I,TOTAL
	INTEGER*4	UTNC1,NSPIN,TSPIN,OMSEC,SPINVCTR(3),
     &			SUN(3),OAMSEC,SOLMSEC1
	REAL*4		IMXMIN,IMXMAX,IMYMAX,STEP,PIXWD,PIXHT,SP,ALTF,
     &			WNXMIN,WNXMAX,WNYMIN,WNYMAX,POSITION(1026,3),
     &			SPINANG(1026),XP1,SPINX,SPINY,SPINZ,SUNX,SUNZ,XYR,
     &			P(4,1026),PCOS,PSIN,SUN1,SUN2,SUN3,SPIN1,SPIN2,XLAST
	REAL*8		DSTART,DSTOP
!
	EQUIVALENCE (HEADER(133),SPINVCTR(1)),
     &			(HEADER(173),SUN(1)),(HEADER(189),OAMSEC)
!
!---find index of first scan line in position array
	IF (MDIREC.EQ.1) THEN
	    INDEX1 = IMXMIN - WNXMIN + 1
	ELSE
	    INDEX1 = IMXMAX - WNXMIN + 1
	ENDIF
!
!---set time parameters for DEORBIT call
	XP1 = IMXMIN - NINT(IMXMIN-WNXMIN) - 1.
	XLAST = IMXMIN + NINT(WNXMAX-IMXMIN) + 1.
	TOTAL = XLAST - XP1 + 1
	OMSEC = OAMSEC
	IF (UTNC1.GT.85000000.AND.OMSEC.LT.1400000) OMSEC = OMSEC + 86400000
	IF (OMSEC.GT.85000000.AND.UTNC1.LT.1400000) OMSEC = OMSEC - 86400000
	IF (MDIREC.EQ.1) THEN
	    DSTART = (OMSEC - (UTNC1-(IMXMIN-XP1)*NSPIN))/1.D3
	    DSTOP = ((UTNC1+(XLAST-IMXMIN)*NSPIN) - OMSEC)/1.D3
	ELSE
	    DSTART = (OMSEC - (UTNC1-(XLAST-IMXMAX)*NSPIN))/1.D3
	    DSTOP = ((UTNC1+(IMXMAX-XP1)*NSPIN) - OMSEC)/1.D3
	ENDIF
	DSTOP = DSTOP + .0005*NSPIN
!
	CALL DEORBIT(DSTART,DSTOP,DBLE(NSPIN)/1.D3,P)
!
!---rotate all vectors to GSEq
	SUN1 = DBLE(SUN(1))/1.D6
	SUN2 = DBLE(SUN(2))/1.D6
	SUN3 = DBLE(SUN(3))/1.D6
	XYR = SQRT( SUN1*SUN1 + SUN2*SUN2 )
	PCOS = SUN1/XYR
	PSIN = SUN2/XYR
	SPIN1 = DBLE(SPINVCTR(1))/1.D6
	SPIN2 = DBLE(SPINVCTR(2))/1.D6
	SPINX = PCOS*SPIN1 + PSIN*SPIN2
	SPINY = PCOS*SPIN2 - PSIN*SPIN1
	SPINZ = DBLE(SPINVCTR(3))/1.D6
	SUNX = SQRT(1.-SUN3*SUN3)
	SUNZ = SUN3
	DO K=1,TOTAL
	    I = K
	    IF (MDIREC.EQ.-1) I = TOTAL + 1 - K
	    POSITION(I,1) = PCOS*P(1,K) + PSIN*P(2,K)
	    POSITION(I,2) = PCOS*P(2,K) - PSIN*P(1,K)
	    POSITION(I,3) = P(3,K)
	    SPINANG(I) = ACOSD( -POSITION(I,1)/P(4,K)*SPINX -
     &		POSITION(I,2)/P(4,K)*SPINY - POSITION(I,3)/P(4,K)*SPINZ )
	ENDDO
!
	RETURN
	END
!
!
!
	SUBROUTINE DEORBIT(DSTART,DSTOP,DINC,P)
!
!  generates DE-1 ephemeris at intervals of DINC seconds for the
!  time period specified as seconds before (DSTART) to seconds after
!  (DSTOP) the time of the orbit/attitude data given in the image
!  header record
!
!			name	type	description
!
!   input arguments:	DSTART	REAL*8	start time in seconds before
!					  time of orbit/attitude data
!			DSTOP	REAL*8	stop time in seconds after
!					  time of orbit/attitude data
!			DINC	REAL*8	increment in seconds between
!					  ephemeris entries
!  output arguments:	P(1,*)	REAL*4	X component GEI in kilometers
!			P(2,*)		Y component GEI in kilometers
!			P(3,*)		Z component GEI in kilometers
!			P(4,*)		radial distance in kilometers
!
!
	COMMON /MAFREC/	HEADER,SCAN
!
	REAL*8		DT,PI,TWOPI,GM,DER,DEX,DEY,DEZ,V2,A,VR,VA,
     &			AREAL,SLR,ECC,TA,EA,DMA,DMA1,EA1,C1,TA1,DTA,
     &			DD,DER1,DEX1,DEY1,DEZ1,PERIOD,X1,Y1,Z1,X2,Y2,
     &			Z2,X3,Y3,Z3,X4,Y4,Z4,X5,Y5,Z5,DSTART,DSTOP,DINC,
     &			VX,VY,VZ,ONX,ONY,ONZ
	REAL*4		P(4,1026)
	INTEGER*2	K
	BYTE		HEADER(404),SCAN(1592)
	INTEGER*4	SCPOS(3),NORMAL(3),VEL(3)
!
	EQUIVALENCE (HEADER(121),SCPOS(1)),(HEADER(145),NORMAL(1)),
     &			(HEADER(161),VEL(1))
	DATA PI,TWOPI/3.14159265D0,6.28318531D0/
!   
	GM = 398600.D9
	ONX = DBLE(NORMAL(1))
	ONY = DBLE(NORMAL(2))
	ONZ = DBLE(NORMAL(3))
	DEX = DBLE(SCPOS(1))
	DEY = DBLE(SCPOS(2))
	DEZ = DBLE(SCPOS(3))
	DER = DSQRT( DEX*DEX + DEY*DEY + DEZ*DEZ )
	DEX = DEX/DER
	DEY = DEY/DER
	DEZ = DEZ/DER
	VX = DBLE(VEL(1))
	VY = DBLE(VEL(2))
	VZ = DBLE(VEL(3))
	V2 = ( VX*VX + VY*VY + VZ*VZ )/1.D6
	A = GM*DER/(2.D0*GM-DER*V2)
	VR = ( DEX*VX + DEY*VY + DEZ*VZ )/1.D3
	VA = DSQRT( V2 - VR*VR )
	AREAL = DER*VA/2.D0
	SLR = 4.D0*AREAL*AREAL/GM
	ECC = DSQRT( 1.D0 - SLR/A )
	TA = DBLE( ASIN( SLR*VR/(2.0*AREAL*ECC) ) )
	IF (DER.GT.SLR) TA = PI - TA
	IF (TA.LT.0.0) TA = TWOPI + TA
	EA = DBLE( ACOS( (1.0-DER/A)/ECC ) )
	IF (TA.GT.PI) EA = TWOPI - EA
	DMA = EA - ECC*DSIN(EA)
	PERIOD = TWOPI * DSQRT(A*A*A/GM)
!
	K = 0
	DT = -DSTART
!
 20	K = K + 1
	DMA1 = TWOPI*DT/PERIOD + DMA
	IF (DMA1.GT.TWOPI) DMA1 = DMA1 - TWOPI
	EA1 = DMA1 + ECC*DSIN(DMA1)
	C1 = DSIN(EA1) * ECC
 30	EA1 = C1 + DMA1
	C1 = ECC * DSIN(EA1)
	IF (DABS((EA1-C1-DMA1)/EA1).GT.1.D-8) GO TO 30
	TA1 = 2.D0*DATAN(DSIN(EA1/2.D0)/DCOS(EA1/2.D0)*
     &	  DSQRT((1.D0+ECC)/(1.D0-ECC)))
	IF (TA1.LT.0.D0) TA1 = TA1 + TWOPI
	DTA = TA1 - TA
!
	DD = DSQRT( 1.D0 - ONZ*ONZ/1.D12 )
	X1 = (DEX*ONX+DEY*ONY)/(DD*1.D6)
	Y1 = (-DEX*ONY+DEY*ONX)/(DD*1.D6)
	Z1 = DEZ
	X2 = DD*X1 + ONZ*Z1/1.D6
	Y2 = Y1
	Z2 = -ONZ*X1/1.D6 + DD*Z1
	X3 = X2
	Y3 = DCOS(DTA)*Y2 - DSIN(DTA)*Z2
	Z3 = DSIN(DTA)*Y2 + DCOS(DTA)*Z2
	X4 = DD*X3 - ONZ*Z3/1.D6
	Y4 = Y3
	Z4 = ONZ*X3/1.D6 + DD*Z3
	X5 = (X4*ONX - Y4*ONY)/(DD*1.D6)
	Y5 = (X4*ONY + Y4*ONX)/(DD*1.D6)
	Z5 = Z4
	DER1 = A*(1.D0 - ECC*DCOS(EA1))
	DEX1 = X5*DER1
	DEY1 = Y5*DER1
	DEZ1 = Z5*DER1
!
	P(1,K) = DEX1/1000.
	P(2,K) = DEY1/1000.
	P(3,K) = DEZ1/1000.
	P(4,K) = DER1/1000.
!
	IF (DINC.GT.0.) THEN
	    DT = DT + DINC
	    IF (DT.LE.DSTOP) GO TO 20
	ENDIF
!
 99	RETURN
	END
!
!
!
	INTEGER*2 FUNCTION ICOUNT(TM)
!
!  returns the true uncompressed count for the input telemetry count
!
!			name	type	description
!
!     input argument:	TM	INT*2	compressed count
!
!	      result:	ICOUNT	INT*2	uncompressed count
!
!
!
	INTEGER*2 TM,IX,IY
!
	IF (TM.LT.33) THEN
	    ICOUNT = TM
	ELSE
	    IF (TM.GT.127) THEN
		ICOUNT = 0
	    ELSE
		IX = MOD(TM,16)
		IY = TM/16
		ICOUNT = (IX+16) * 2**(IY-1)
	    ENDIF
	ENDIF
	RETURN
!
	END
!
!
!
	INTEGER*4 FUNCTION NPTIME(MSEC,SUBCOM,DCU)
!
!  returns the time of the nadir pulse that started the scanline
!
!			name	type	description
!
!    input arguments:	MSEC	INT*4	milliseconds from scanline record
!			SUBCOM	BYTE	subcom number from scanline record
!			DCU	INT*2	DCU count from scanline record
!
!    	      result:	NPTIME	INT*4	scanline's nadir pulse time in
!					  milliseconds
!
!
	REAL*4		T3BYTE
	INTEGER*4	MSEC
	INTEGER*2	DCU
	BYTE		SUBCOM
!
	DATA T3BYTE/1.46484375/
!
	NPTIME = MSEC - T3BYTE + 500 + MOD(ZEXT(SUBCOM)/8,2)*500
     &	   - DCU/8.192
!
	RETURN
	END
!
!
!
	SUBROUTINE FILTERS(NPHOT,NCOUNT,NAME,NUMBER,SP,ALT)
!
!  given the photometer ID and the telemetry filter wheel voltage count,
!  returns the filter name, number, sensitivity factor, and default
!  altitude, when known
!
!			name	type	description
!
!   input arguments:	NPHOT	INT*2	photometer ID (1, 2, or 3)
!			NCOUNT	INT*4	filter wheel voltage count
!
!  output arguments:	NAME	CHAR*4	filter name
!			NUMBER	INT*2	filter number
!			SP	REAL*4	sensitivity factor
!			ATL	REAL*4	assumed altitude in kilometers
!			
!
	REAL*4		SPS(12,3),ALTS(12,3),SP,ALT
	INTEGER*2	NPHOT,NUMBER,N
	INTEGER*4	NCOUNT
	CHARACTER*4	NAME,NAMES(12,3)
!
	DATA NAMES/'360Z','317Z','630W','557W','391W','394B','626B',
     &	    '630W','557N','391N','630N','557N','629C','630N','557N',
     &	    '391N','630N','317Z','482M','554B','557W','390W','630W',
     &	    '557W','136W','123W','120W','140N','136W','125N','123W',
     &	    '117N','140N','125N','117N','117A'/
	DATA SPS/2.3E-4,5.7E-4,  0.88,  2.40,  3.31,  1.96,  1.08,
     &	    0.78,  1.30,  2.33,  0.66,  1.60,3.2E-4,  1.31,  2.40,
     &	    4.49,  1.19,4.5E-4,  7.40,  3.85,  4.85,  5.84,  2.00,
     &	    4.64,  1.65,  3.08,  3.10,  1.27,  2.05,  1.71,  3.08,
     &	    0.84,  1.26,  1.80,  0.91,  10.5/
	DATA ALTS/   0.,    0.,    0., 120.0, 100.0, 100.0, 300.0,
     &     300.0,    0.,    0.,    0.,    0.,    0.,    0.,    0.,
     &	      0.,    0.,    0.,    0., 120.0, 120.0, 100.0, 300.0,
     &	      0., 100.0, 200.0, 200.0,    0.,    0.,    0.,    0.,
     &	      0.,    0.,    0.,    0., 200.0/
!
	N = NCOUNT
	GO TO(1,2,3),NPHOT
  1	IF (N.LT.95) N = N + 217
	NUMBER = (N-77)/18
	GO TO 15
  2	IF (N.LT.56) N = N + 240
	NUMBER = (N-36)/20
	GO TO 15
  3	IF (N.LT.85) N = N + 227
	NUMBER = (N-66)/19
!
 15	NAME = NAMES(NUMBER,NPHOT)
	SP   = SPS(NUMBER,NPHOT)
	ALT  = ALTS(NUMBER,NPHOT)
!
	RETURN
	END
!
!
!
	SUBROUTINE IMAGEIN(IMFILE)
!
!  opens the input image file; for each scan line unpacks pixels
!  and saves corrections as real pixel units in SCANS block;
!  puts header record and first scan line record into MAFREC block
!
!			name	type	description
!
!  input argument:	IMFILE	CHAR	fully qualified image file name,
!					  up to 128 characters in length
!
!
	COMMON /SCANS/	SCANPIX,LNCOR,MLCS,NPIXL
	COMMON /MAFREC/	HEADER,SCAN
!
	INTEGER*2	LCENTR(3),MLCS(121),NPIXL(121),DMLC,LMLC,
     &			LINECOUNT,ISINK,K,L,SCOFFSET,LBYTES,DCU,
     &			MLCA,MLCZ,NADCOR(3),ORDERNC,NC1,IMSYNCVERS
	INTEGER*4	MAXPIXINLINE,FIRSTMLC,LASTMLC
	BYTE		SCANPIX(1568,121),HEADER(404),SCAN(1592),
     &			MLC,PIXEL(1568)
	REAL*4		LNCOR(2,121)
	CHARACTER*128	IMFILE
!
	DATA	LCENTR/80,73,90/
!
	EQUIVALENCE	(HEADER(41),FIRSTMLC),(HEADER(45),LASTMLC),
     &			(HEADER(57),MAXPIXINLINE),(HEADER(389),IMSYNCVERS),
     &			(HEADER(395),SCOFFSET)
	EQUIVALENCE	(SCAN(3),LBYTES),(SCAN(9),MLC),(SCAN(13),DCU),
     &                  (SCAN(17),NADCOR(1)),(SCAN(23),ORDERNC),
     &			(SCAN(25),PIXEL(1))
!
!---set to continue on short scan line records
	CALL ERRSET(67,.TRUE.,.FALSE.,.TRUE.,.FALSE.,122)
!
!---open file and read header record
	OPEN(UNIT=2,FILE=IMFILE,FORM='UNFORMATTED',TYPE='OLD',
     &			READONLY)
	READ(2) HEADER
!
!---read each scan line record, get MLC, nadir corrections, and pixels
	MLCA = 0
	LMLC = 0
	LINECOUNT = 0
 21	READ(2,END=40,ERR=25) (SCAN(K),K=1,MAXPIXINLINE+24)
 25	IF (ZEXT(MLC).LT.1) GO TO 21
	IF (MLCA.EQ.0) MLCA = ZEXT(MLC)
	MLCZ = ZEXT(MLC)
	IF (LINECOUNT.EQ.0) THEN
	    LINECOUNT = 1
	ELSE
	    DMLC = ABS(ZEXT(MLC)-LMLC)
	    IF (DMLC.GT.1) THEN
		DO K=LINECOUNT+1,LINECOUNT+DMLC-1
		    NPIXL(K) = 0
		    MLCS(K) = -1
		    DO L=1,1568
			SCANPIX(L,K) = -1
		    ENDDO
		ENDDO
	    ENDIF
	    LINECOUNT = LINECOUNT + DMLC
	ENDIF
	LMLC = ZEXT(MLC)
	MLCS(LINECOUNT) = LMLC
	NC1 = IAND(NADCOR(1),255)
	IF (NC1.GT.127) NC1 = NC1 - 256
	LNCOR(1,LINECOUNT) = (NC1+NADCOR(2)+NADCOR(3))/8.
     &				+ ISINK(IMSYNCVERS,DCU)
	IF (SCOFFSET.EQ.-75) THEN
	    LNCOR(2,LINECOUNT) = ORDERNC/100.
	ELSE
	    LNCOR(2,LINECOUNT) = 0.
	ENDIF
	NPIXL(LINECOUNT) = MIN(LBYTES-22,1568)
	DO K=1,NPIXL(LINECOUNT)
	    SCANPIX(K,LINECOUNT) = PIXEL(K)
	ENDDO
	GO TO 21
!
 40	IF (LINECOUNT.LT.121) THEN
	    DO K=LINECOUNT+1,121
		MLCS(K) = -1
		NPIXL(K) = 0
	    ENDDO
	ENDIF
!
!---put first scan record back in SCAN and close file
	REWIND 2
	READ(2) HEADER
	IF (FIRSTMLC.EQ.0) FIRSTMLC = MLCA
	IF (LASTMLC.EQ.0) LASTMLC = MLCZ
 42	READ(2,ERR=45) (SCAN(K),K=1,MAXPIXINLINE+24)
	IF (ZEXT(MLC).LT.1) GO TO 42
 45	CLOSE(UNIT=2)
!
	RETURN
!
	END
!
!
!
	INTEGER*2 FUNCTION ISINK(IMSYNC,DCU)
!
!  checks for the sinkhole problem, an artifact of an early software bug;
!  if the scan line is shifted down one pixel, sets function value to -1;
!  otherwise it is 0
!
!			name	type	description
!
!    input arguments:	IMSYNC	INT*2	IMSYNC version number from MAF
!					  header record
!			DCU	INT*2	DCU count from scan line record
!
!	      result:	ISINK	INT*2	-1 if scanline was moved down,
!					  0 if not
!
	INTEGER*2 DCU,IMSYNC
!
	ISINK = 0
	IF (IMSYNC.LT.195.AND.MOD(DCU,32).EQ.0) ISINK = -1
	RETURN
!
	END
